From ec49bca2e65950b1ee67b8b98e96c0c40c2f521f Mon Sep 17 00:00:00 2001 From: Prince Roshan Date: Sat, 5 Aug 2023 13:42:13 +0530 Subject: [PATCH] gh-107625: Raise ParsingError if a key contains empty value - raise ParsingError instaed of AttributeError if a key contains empty value in a non recommended scenario where extra space and blankline is present within the section --- Doc/library/configparser.rst | 26 ++++++++++++++++++++++++++ Lib/configparser.py | 7 +++++-- Lib/test/test_configparser.py | 16 ++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/Doc/library/configparser.rst b/Doc/library/configparser.rst index a7f75fd6e84f4c..ad25c7cc3686d8 100644 --- a/Doc/library/configparser.rst +++ b/Doc/library/configparser.rst @@ -1036,6 +1036,12 @@ ConfigParser Objects files using :meth:`read_file` before calling :meth:`read` for any optional files:: + Raise a :exc:`ParsingError` instead of an :exc:`AttributeError` + when the configuration contains a key without a corresponding value. + This change is intended to handle scenarios where a key lacks a value + in a configuration. Please note that it's not recommended to have extra + spaces or blank lines within sections of the configuration. + import configparser, os config = configparser.ConfigParser() @@ -1053,6 +1059,12 @@ ConfigParser Objects .. versionadded:: 3.7 The *filenames* parameter accepts a :class:`bytes` object. + .. versionchanged:: 3.13 + Parsing errors will result in a ParsingError being raised instead + of an AttributeError when encountering a key without a corresponding + value. This change is designed to handle situations where a key is + present without a value, particularly in scenarios not recommended, + such as having extra spaces or blank lines within sections. .. method:: read_file(f, source=None) @@ -1063,9 +1075,23 @@ ConfigParser Objects not given and *f* has a :attr:`name` attribute, that is used for *source*; the default is ``''``. + Raise a :exc:`ParsingError` instead of an :exc:`AttributeError` + when the configuration contains a key without a corresponding value. + This change is intended to handle scenarios where a key lacks a value + in a configuration. Please note that it's not recommended to have extra + spaces or blank lines within sections of the configuration. + .. versionadded:: 3.2 Replaces :meth:`readfp`. + .. versionchanged:: 3.13 + Parsing errors will result in a ParsingError being raised instead + of an AttributeError when encountering a key without a corresponding + value. This change is designed to handle situations where a key is + present without a value, particularly in scenarios not recommended, + such as having extra spaces or blank lines within sections. + + .. method:: read_string(string, source='') Parse configuration data from a string. diff --git a/Lib/configparser.py b/Lib/configparser.py index 71362d23ec3757..0539c7393696b2 100644 --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -986,8 +986,11 @@ def _read(self, fp, fpname): first_nonspace = self.NONSPACECRE.search(line) cur_indent_level = first_nonspace.start() if first_nonspace else 0 if (cursect is not None and optname and - cur_indent_level > indent_level): - cursect[optname].append(value) + cur_indent_level > indent_level): + if cursect[optname]: + cursect[optname].append(value) + else: + raise ParsingError(f"No-value option {optname} cannot be continued") # a section header or option header? else: indent_level = cur_indent_level diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py index 53163d7528b64a..4f71b6d11eb4c6 100644 --- a/Lib/test/test_configparser.py +++ b/Lib/test/test_configparser.py @@ -1555,6 +1555,22 @@ def test_source_as_bytes(self): "'[badbad'" ) + def test_gh_107625(self): + #test key without value with extra whitespace within sections + lines = [ + '[SECT]\n', + 'KEY1\n', + ' KEY2 = VAL2\n', # note the Space before the key! + ] + with self.assertRaises(configparser.ParsingError): + parser = configparser.ConfigParser( + comment_prefixes ="", + allow_no_value =True, + strict =False, + delimiters =( '=', ), + interpolation =None, + ) + class CoverageOneHundredTestCase(unittest.TestCase): """Covers edge cases in the codebase."""