summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2015-07-27 20:31:00 -0400
committerNed Batchelder <ned@nedbatchelder.com>2015-07-27 20:31:00 -0400
commit7470fe559f2c1fa0c6c87365f115f27c6a4d6ff7 (patch)
treec196528b61f50c4b961cc7be7000138e9a60ce3a
parent5e944cc789a6f068b8ce4fbc255e4d9bfcd72c5f (diff)
downloadpython-coveragepy-git-7470fe559f2c1fa0c6c87365f115f27c6a4d6ff7.tar.gz
Fail on unrecognized configuration options. #386
-rw-r--r--CHANGES.txt5
-rw-r--r--coverage/config.py23
-rw-r--r--tests/test_config.py27
3 files changed, 54 insertions, 1 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index ffa4f32e..1211e8e3 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -20,6 +20,10 @@ Latest
stored in the `runs` section of the data file. You can use this to annotate
the data file with any information you like.
+- Unrecognized configuration options will now print an error message and stop
+ coverage.py. This should help prevent configuration mistakes from passing
+ silently. Finishes `issue 386`_.
+
- The XML report now includes a ``missing-branches`` attribute. Thanks, Steve
Peak. This is not a part of the Cobertura DTD, so the XML report no longer
references the DTD.
@@ -47,6 +51,7 @@ Latest
.. _issue 275: https://bitbucket.org/ned/coveragepy/issues/275/refer-consistently-to-project-as-coverage
.. _issue 313: https://bitbucket.org/ned/coveragepy/issues/313/add-license-file-containing-2-3-or-4
.. _issue 380: https://bitbucket.org/ned/coveragepy/issues/380/code-executed-by-exec-excluded-from
+.. _issue 386: https://bitbucket.org/ned/coveragepy/issues/386/error-on-unrecognised-configuration
.. 41 issues closed in 4.0 below here
diff --git a/coverage/config.py b/coverage/config.py
index edcf13e8..9939d6c0 100644
--- a/coverage/config.py
+++ b/coverage/config.py
@@ -3,7 +3,11 @@
"""Config file for coverage.py"""
-import os, re, sys
+import collections
+import os
+import re
+import sys
+
from coverage.backward import configparser, iitems, string_class
from coverage.misc import CoverageException
@@ -221,6 +225,23 @@ class CoverageConfig(object):
except ValueError as err:
raise CoverageException("Couldn't read config file %s: %s" % (filename, err))
+ # Check that there are no unrecognized options.
+ all_options = collections.defaultdict(set)
+ for option_spec in self.CONFIG_FILE_OPTIONS:
+ section, option = option_spec[1].split(":")
+ all_options[section].add(option)
+
+ for section, options in iitems(all_options):
+ if cp.has_section(section):
+ for unknown in set(cp.options(section)) - options:
+ if section_prefix:
+ section = section_prefix + section
+ raise CoverageException(
+ "Unrecognized option '[%s] %s=' in config file %s" % (
+ section, unknown, filename
+ )
+ )
+
# [paths] is special
if cp.has_section('paths'):
for option in cp.options('paths'):
diff --git a/tests/test_config.py b/tests/test_config.py
index 2b325073..6873e85d 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -182,6 +182,33 @@ class ConfigTest(CoverageTest):
with self.assertRaises(CoverageException):
_ = cov.config["no_such.plugin:foo"]
+ def test_unknown_option(self):
+ self.make_file(".coveragerc", """\
+ [run]
+ xyzzy = 17
+ """)
+ msg = r"Unrecognized option '\[run\] xyzzy=' in config file .coveragerc"
+ with self.assertRaisesRegex(CoverageException, msg):
+ _ = coverage.Coverage()
+
+ def test_misplaced_option(self):
+ self.make_file(".coveragerc", """\
+ [report]
+ branch = True
+ """)
+ msg = r"Unrecognized option '\[report\] branch=' in config file .coveragerc"
+ with self.assertRaisesRegex(CoverageException, msg):
+ _ = coverage.Coverage()
+
+ def test_unknown_option_in_other_ini_file(self):
+ self.make_file("setup.cfg", """\
+ [coverage:run]
+ huh = what?
+ """)
+ msg = r"Unrecognized option '\[coverage:run\] huh=' in config file setup.cfg"
+ with self.assertRaisesRegex(CoverageException, msg):
+ _ = coverage.Coverage()
+
class ConfigFileTest(CoverageTest):
"""Tests of the config file settings in particular."""