diff --git a/coverage/tomlconfig.py b/coverage/tomlconfig.py index a06da65f7..82f84ce9c 100644 --- a/coverage/tomlconfig.py +++ b/coverage/tomlconfig.py @@ -6,16 +6,21 @@ import configparser import os import re +import sys from coverage.exceptions import ConfigError from coverage.misc import import_third_party, substitute_variables -# TOML support is an install-time extra option. (Import typing is here because -# import_third_party will unload any module that wasn't already imported. -# tomli imports typing, and if we unload it, later it's imported again, and on -# Python 3.6, this causes infinite recursion.) -import typing # pylint: disable=unused-import, wrong-import-order -tomli = import_third_party("tomli") +if sys.version_info >= (3, 11): + import tomllib +else: + # TOML support on Python 3.10 and below is an install-time extra option. + # (Import typing is here because import_third_party will unload any module + # that wasn't already imported. tomli imports typing, and if we unload it, + # later it's imported again, and on Python 3.6, this causes infinite + # recursion.) + import typing # pylint: disable=unused-import, wrong-import-order + tomllib = import_third_party("tomli") class TomlDecodeError(Exception): @@ -45,11 +50,11 @@ def read(self, filenames): toml_text = fp.read() except OSError: return [] - if tomli is not None: + if tomllib is not None: toml_text = substitute_variables(toml_text, os.environ) try: - self.data = tomli.loads(toml_text) - except tomli.TOMLDecodeError as err: + self.data = tomllib.loads(toml_text) + except tomllib.TOMLDecodeError as err: raise TomlDecodeError(str(err)) from err return [filename] else: diff --git a/setup.py b/setup.py index 00f6086d4..4b7b6bf94 100644 --- a/setup.py +++ b/setup.py @@ -108,7 +108,7 @@ def better_set_verbosity(v): extras_require={ # Enable pyproject.toml support. - 'toml': ['tomli'], + 'toml': ['tomli; python_version < "3.11"'], }, # We need to get HTML assets from our htmlfiles directory. diff --git a/tests/test_config.py b/tests/test_config.py index d85dfc7bb..6aa435112 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -4,6 +4,7 @@ """Test the config file handling for coverage.py""" import math +import sys from collections import OrderedDict from unittest import mock @@ -706,19 +707,21 @@ def test_note_is_obsolete(self): def test_no_toml_installed_no_toml(self): # Can't read a toml file that doesn't exist. - with without_module(coverage.tomlconfig, 'tomli'): + with without_module(coverage.tomlconfig, 'tomllib'): msg = "Couldn't read 'cov.toml' as a config file" with pytest.raises(ConfigError, match=msg): coverage.Coverage(config_file="cov.toml") + @pytest.mark.skipif(sys.version_info >= (3, 11), reason="Python 3.11 has toml in stdlib") def test_no_toml_installed_explicit_toml(self): # Can't specify a toml config file if toml isn't installed. self.make_file("cov.toml", "# A toml file!") - with without_module(coverage.tomlconfig, 'tomli'): + with without_module(coverage.tomlconfig, 'tomllib'): msg = "Can't read 'cov.toml' without TOML support" with pytest.raises(ConfigError, match=msg): coverage.Coverage(config_file="cov.toml") + @pytest.mark.skipif(sys.version_info >= (3, 11), reason="Python 3.11 has toml in stdlib") def test_no_toml_installed_pyproject_toml(self): # Can't have coverage config in pyproject.toml without toml installed. self.make_file("pyproject.toml", """\ @@ -726,7 +729,7 @@ def test_no_toml_installed_pyproject_toml(self): [tool.coverage.run] xyzzy = 17 """) - with without_module(coverage.tomlconfig, 'tomli'): + with without_module(coverage.tomlconfig, 'tomllib'): msg = "Can't read 'pyproject.toml' without TOML support" with pytest.raises(ConfigError, match=msg): coverage.Coverage() @@ -738,7 +741,7 @@ def test_no_toml_installed_pyproject_no_coverage(self): [tool.something] xyzzy = 17 """) - with without_module(coverage.tomlconfig, 'tomli'): + with without_module(coverage.tomlconfig, 'tomllib'): cov = coverage.Coverage() # We get default settings: assert not cov.config.timid diff --git a/tests/test_testing.py b/tests/test_testing.py index e1d3a345e..43c682cd3 100644 --- a/tests/test_testing.py +++ b/tests/test_testing.py @@ -357,10 +357,10 @@ def _same_python_executable(e1, e2): def test_without_module(): - toml1 = tomlconfig.tomli - with without_module(tomlconfig, 'tomli'): - toml2 = tomlconfig.tomli - toml3 = tomlconfig.tomli + toml1 = tomlconfig.tomllib + with without_module(tomlconfig, 'tomllib'): + toml2 = tomlconfig.tomllib + toml3 = tomlconfig.tomllib assert toml1 is toml3 is not None assert toml2 is None