diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2019-11-03 18:32:01 -0500 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2019-11-03 21:27:42 -0500 |
commit | df744f8cbcad7ea7dca893be5017920afa4ce32f (patch) | |
tree | 05faf86a600898561b10ae2fed36382101a6cd9d | |
parent | 9c04f2d6c4dd4e1bda5fae1e58c9aad846881024 (diff) | |
download | python-coveragepy-git-df744f8cbcad7ea7dca893be5017920afa4ce32f.tar.gz |
Give warnings about not being able to parse TOML files if toml isn't installed
-rw-r--r-- | coverage/config.py | 3 | ||||
-rw-r--r-- | coverage/tomlconfig.py | 47 | ||||
-rw-r--r-- | tests/test_config.py | 34 |
3 files changed, 62 insertions, 22 deletions
diff --git a/coverage/config.py b/coverage/config.py index ca3de3bd..62f281ad 100644 --- a/coverage/config.py +++ b/coverage/config.py @@ -260,9 +260,6 @@ class CoverageConfig(object): """ _, ext = os.path.splitext(filename) if ext == '.toml': - from coverage.optional import toml - if toml is None: - return False cp = TomlConfigParser(our_file) else: cp = HandyConfigParser(our_file) diff --git a/coverage/tomlconfig.py b/coverage/tomlconfig.py index 33647309..f5978820 100644 --- a/coverage/tomlconfig.py +++ b/coverage/tomlconfig.py @@ -25,34 +25,43 @@ class TomlConfigParser: # pylint: disable=missing-function-docstring def __init__(self, our_file): + self.our_file = our_file self.getters = [lambda obj: obj['tool']['coverage']] - if our_file: + if self.our_file: self.getters.append(lambda obj: obj) self._data = [] def read(self, filenames): + # RawConfigParser takes a filename or list of filenames, but we only + # ever call this with a single filename. + assert isinstance(filenames, path_types) + filename = filenames + if env.PYVERSION >= (3, 6): + filename = os.fspath(filename) + from coverage.optional import toml if toml is None: - raise RuntimeError('toml module is not installed.') - - if isinstance(filenames, path_types): - filenames = [filenames] - read_ok = [] - for filename in filenames: - try: - with io.open(filename, encoding='utf-8') as fp: - toml_data = fp.read() - toml_data = substitute_variables(toml_data, os.environ) + if self.our_file: + raise CoverageException("Can't read {!r} without TOML support".format(filename)) + + try: + with io.open(filename, encoding='utf-8') as fp: + toml_data = fp.read() + toml_data = substitute_variables(toml_data, os.environ) + if toml: + try: self._data.append(toml.loads(toml_data)) - except IOError: - continue - except toml.TomlDecodeError as err: - raise TomlDecodeError(*err.args) - if env.PYVERSION >= (3, 6): - filename = os.fspath(filename) - read_ok.append(filename) - return read_ok + except toml.TomlDecodeError as err: + raise TomlDecodeError(*err.args) + elif re.search(r"^\[tool\.coverage\.", toml_data, flags=re.MULTILINE): + # Looks like they meant to read TOML, but we can't. + raise CoverageException("Can't read {!r} without TOML support".format(filename)) + else: + return [] + except IOError: + return [] + return [filename] def has_option(self, section, option): for data in self._data: diff --git a/tests/test_config.py b/tests/test_config.py index 3bd2fd2b..74ff5f00 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -8,6 +8,7 @@ import mock import coverage from coverage.misc import CoverageException +import coverage.optional from tests.coveragetest import CoverageTest, UsingModulesMixin @@ -651,3 +652,36 @@ class ConfigFileTest(UsingModulesMixin, CoverageTest): self.assertFalse(cov.config.timid) self.assertFalse(cov.config.branch) self.assertEqual(cov.config.data_file, ".coverage") + + def test_no_toml_installed_explicit_toml(self): + # Can't specify a toml config file if toml isn't installed. + with coverage.optional.without('toml'): + msg = "Can't read 'cov.toml' without TOML support" + with self.assertRaisesRegex(CoverageException, msg): + coverage.Coverage(config_file="cov.toml") + + def test_no_toml_installed_pyproject_toml(self): + # Can't have coverage config in pyproject.toml without toml installed. + self.make_file("pyproject.toml", """\ + # A toml file! + [tool.coverage.run] + xyzzy = 17 + """) + with coverage.optional.without('toml'): + msg = "Can't read 'pyproject.toml' without TOML support" + with self.assertRaisesRegex(CoverageException, msg): + coverage.Coverage() + + def test_no_toml_installed_pyproject_no_coverage(self): + # It's ok to have non-coverage pyproject.toml without toml installed. + self.make_file("pyproject.toml", """\ + # A toml file! + [tool.something] + xyzzy = 17 + """) + with coverage.optional.without('toml'): + cov = coverage.Coverage() + # We get default settings: + self.assertFalse(cov.config.timid) + self.assertFalse(cov.config.branch) + self.assertEqual(cov.config.data_file, ".coverage") |