From e27c657f06841941939d766cb8f089c445d9163c Mon Sep 17 00:00:00 2001 From: Dylan Lloyd Date: Thu, 20 Oct 2016 15:24:20 -0400 Subject: [PATCH 1/3] added validate() strict_spec option support error reporting when a configuration file contains entries that are not defined by the validator definitions. --- docs/configobj.rst | 2 +- src/configobj/__init__.py | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/docs/configobj.rst b/docs/configobj.rst index 17dcddf..391fd26 100644 --- a/docs/configobj.rst +++ b/docs/configobj.rst @@ -522,7 +522,7 @@ validate .. code-block:: python - validate(validator, preserve_errors=False, copy=False) + validate(validator, preserve_errors=False, copy=False, strict_spec=False) .. code-block:: python diff --git a/src/configobj/__init__.py b/src/configobj/__init__.py index 26239c6..7dd66de 100644 --- a/src/configobj/__init__.py +++ b/src/configobj/__init__.py @@ -2098,7 +2098,7 @@ def write(self, outfile=None, section=None): h.write(output_bytes) def validate(self, validator, preserve_errors=False, copy=False, - section=None): + section=None, strict_spec=False): """ Test the ConfigObj against a configspec. @@ -2129,6 +2129,13 @@ def validate(self, validator, preserve_errors=False, copy=False, You must have the validate module to use ``preserve_errors=True``. + If ``strict_spec`` is ``True`` (``False`` is default) then instead of + ignoring entries undefined by the configspec, unrecognized entries will + fail validation and be inserted into the return dictionary with an + informational ``ValidateError``. + + You must have the validate module to use ``strict_spec=True``. + You can then use the ``flatten_errors`` function to turn your nested results dictionary into a flattened list of failures - useful for displaying meaningful error messages. @@ -2263,6 +2270,15 @@ def validate_entry(entry, spec, val, missing, ret_true, ret_false): ret_false = False msg = 'Section %r was provided as a single value' % entry out[entry] = validator.baseErrorClass(msg) + if strict_spec: + for entry in unvalidated: + if not preserve_errors: + out[entry] = False + else: + ret_false = False + msg = 'Value %r was unrecognized' % entry + out[entry] = validator.baseErrorClass(msg) + # Missing sections will have been created as empty ones when the # configspec was read. From ac7f720df6481d4c0cb7c5facb2db3a309c39798 Mon Sep 17 00:00:00 2001 From: Dylan Lloyd Date: Thu, 20 Oct 2016 15:27:06 -0400 Subject: [PATCH 2/3] add VdtMissingDefinition Exception for strict_spec errors --- src/configobj/__init__.py | 5 +++-- src/configobj/validate.py | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/configobj/__init__.py b/src/configobj/__init__.py index 7dd66de..d0430a9 100644 --- a/src/configobj/__init__.py +++ b/src/configobj/__init__.py @@ -2146,7 +2146,8 @@ def validate(self, validator, preserve_errors=False, copy=False, if preserve_errors: # We do this once to remove a top level dependency on the validate module # Which makes importing configobj faster - from configobj.validate import VdtMissingValue + from configobj.validate import VdtMissingDefinition, VdtMissingValue + self._vdtMissingDefinition = VdtMissingDefinition self._vdtMissingValue = VdtMissingValue section = self @@ -2277,7 +2278,7 @@ def validate_entry(entry, spec, val, missing, ret_true, ret_false): else: ret_false = False msg = 'Value %r was unrecognized' % entry - out[entry] = validator.baseErrorClass(msg) + out[entry] = self._vdtMissingDefinition(msg) # Missing sections will have been created as empty ones when the diff --git a/src/configobj/validate.py b/src/configobj/validate.py index b4873fb..25cb4fc 100644 --- a/src/configobj/validate.py +++ b/src/configobj/validate.py @@ -147,6 +147,7 @@ 'VdtValueTooBigError', 'VdtValueTooShortError', 'VdtValueTooLongError', + 'VdtMissingDefinition', 'VdtMissingValue', 'Validator', 'is_integer', @@ -368,6 +369,10 @@ class ValidateError(Exception): """ +class VdtMissingDefinition(ValidateError): + """A check was requested on an undefined entry""" + + class VdtMissingValue(ValidateError): """No value was supplied to a check that needed one.""" From 02293ef296fa0bc171ff01e7dc810c82a9fe357a Mon Sep 17 00:00:00 2001 From: Dylan Lloyd Date: Thu, 20 Oct 2016 16:34:46 -0400 Subject: [PATCH 3/3] add strict_spec failure test case --- src/tests/test_validate_errors.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tests/test_validate_errors.py b/src/tests/test_validate_errors.py index b256efa..8fed86b 100644 --- a/src/tests/test_validate_errors.py +++ b/src/tests/test_validate_errors.py @@ -48,6 +48,11 @@ def test_validate_preserve_errors(conf): assert not section['missing-subsection'] +def test_validate_strict_spec(conf): + conf['undefined-entry'] = True + assert not conf.validate(Validator(), strict_spec=True) + + def test_validate_extra_values(conf): conf.validate(Validator(), preserve_errors=True)