mirror of https://github.com/python/cpython
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>
This commit is contained in:
parent
27858e2a17
commit
e800265aa1
|
@ -978,6 +978,10 @@ ConfigParser Objects
|
|||
The default *dict_type* is :class:`dict`, since it now preserves
|
||||
insertion order.
|
||||
|
||||
.. versionchanged:: 3.13
|
||||
Raise a :exc:`MultilineContinuationError` when *allow_no_value* is
|
||||
``True``, and a key without a value is continued with an indented line.
|
||||
|
||||
.. method:: defaults()
|
||||
|
||||
Return a dictionary containing the instance-wide defaults.
|
||||
|
@ -1349,6 +1353,13 @@ Exceptions
|
|||
The ``filename`` attribute and :meth:`!__init__` constructor argument were
|
||||
removed. They have been available using the name ``source`` since 3.2.
|
||||
|
||||
.. exception:: MultilineContinuationError
|
||||
|
||||
Exception raised when a key without a corresponding value is continued with
|
||||
an indented line.
|
||||
|
||||
.. versionadded:: 3.13
|
||||
|
||||
.. rubric:: Footnotes
|
||||
|
||||
.. [1] Config parsers allow for heavy customization. If you are interested in
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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."""
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Raise :exc:`configparser.ParsingError` from :meth:`~configparser.ConfigParser.read`
|
||||
and :meth:`~configparser.ConfigParser.read_file` methods of
|
||||
:class:`configparser.ConfigParser` if a key without a corresponding value
|
||||
is continued (that is, followed by an indented line).
|
Loading…
Reference in New Issue