diff options
author | Prince Roshan <princekrroshan01@gmail.com> | 2024-03-06 14:05:54 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-06 14:05:54 (GMT) |
commit | e800265aa1f3451855a2fc14fbafc4d89392e35c (patch) | |
tree | 8cd6eb829895313aacae2c12f33f12b1345aa0c7 /Lib | |
parent | 27858e2a17924dfac9a10efc17caee1f5126ea19 (diff) | |
download | cpython-e800265aa1f3451855a2fc14fbafc4d89392e35c.zip cpython-e800265aa1f3451855a2fc14fbafc4d89392e35c.tar.gz cpython-e800265aa1f3451855a2fc14fbafc4d89392e35c.tar.bz2 |
gh-107625: configparser: Raise error if a missing value is continued (GH-107651)
Co-authored-by: Éric <merwok@netwok.org>
Co-authored-by: Petr Viktorin <encukou@gmail.com>
Co-authored-by: Jason R. Coombs <jaraco@jaraco.com>
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/configparser.py | 16 | ||||
-rw-r--r-- | Lib/test/test_configparser.py | 24 |
2 files changed, 40 insertions, 0 deletions
diff --git a/Lib/configparser.py b/Lib/configparser.py index 71362d2..241f10a 100644 --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -152,6 +152,7 @@ __all__ = ("NoSectionError", "DuplicateOptionError", "DuplicateSectionError", "NoOptionError", "InterpolationError", "InterpolationDepthError", "InterpolationMissingOptionError", "InterpolationSyntaxError", "ParsingError", "MissingSectionHeaderError", + "MultilineContinuationError", "ConfigParser", "RawConfigParser", "Interpolation", "BasicInterpolation", "ExtendedInterpolation", "SectionProxy", "ConverterMapping", @@ -322,6 +323,19 @@ class MissingSectionHeaderError(ParsingError): self.args = (filename, lineno, line) +class MultilineContinuationError(ParsingError): + """Raised when a key without value is followed by continuation line""" + def __init__(self, filename, lineno, line): + Error.__init__( + self, + "Key without value continued with an indented line.\n" + "file: %r, line: %d\n%r" + %(filename, lineno, line)) + self.source = filename + self.lineno = lineno + self.line = line + self.args = (filename, lineno, line) + # Used in parser getters to indicate the default behaviour when a specific # option is not found it to raise an exception. Created to enable `None` as # a valid fallback value. @@ -987,6 +1001,8 @@ class RawConfigParser(MutableMapping): cur_indent_level = first_nonspace.start() if first_nonspace else 0 if (cursect is not None and optname and cur_indent_level > indent_level): + if cursect[optname] is None: + raise MultilineContinuationError(fpname, lineno, line) cursect[optname].append(value) # a section header or option header? else: diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py index 2d7dfbd..5d58e34 100644 --- a/Lib/test/test_configparser.py +++ b/Lib/test/test_configparser.py @@ -1555,6 +1555,30 @@ class ReadFileTestCase(unittest.TestCase): "'[badbad'" ) + def test_keys_without_value_with_extra_whitespace(self): + lines = [ + '[SECT]\n', + 'KEY1\n', + ' KEY2 = VAL2\n', # note the Space before the key! + ] + parser = configparser.ConfigParser( + comment_prefixes="", + allow_no_value=True, + strict=False, + delimiters=('=',), + interpolation=None, + ) + with self.assertRaises(configparser.MultilineContinuationError) as dse: + parser.read_file(lines) + self.assertEqual( + str(dse.exception), + "Key without value continued with an indented line.\n" + "file: '<???>', line: 3\n" + "' KEY2 = VAL2\\n'" + ) + + + class CoverageOneHundredTestCase(unittest.TestCase): """Covers edge cases in the codebase.""" |