https://github.com/python/cpython/commit/c95e3de17e94db75f8b98e6141a51ed0dc41459c commit: c95e3de17e94db75f8b98e6141a51ed0dc41459c branch: 3.15 author: Miss Islington (bot) <[email protected]> committer: hugovk <[email protected]> date: 2026-08-29T11:05:39Z summary:
[3.15] gh-156353: Fix configparser space delimiter parsing (GH-156382) (#156557) Co-authored-by: sundeep8967 <[email protected]> Co-authored-by: Petr Viktorin <[email protected]> Signed-off-by: sundeep8967 <[email protected]> files: A Misc/NEWS.d/next/Library/2026-08-26-02-30-00.gh-issue-156353.abcdef.rst M Lib/configparser.py M Lib/test/test_configparser.py diff --git a/Lib/configparser.py b/Lib/configparser.py index 3c452afe8ade48..88015ef6086569 100644 --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -618,7 +618,8 @@ class RawConfigParser(MutableMapping): _OPT_TMPL = r""" (?P<option> # very permissive! (?:(?!{delim})\S)* # non-delimiter non-whitespace - (?:\s+(?:(?!{delim})\S)+)*) # optionally more words + (?:(?:(?!{delim})\s)+ # optionally more + (?:(?!{delim})\S)+)*) # space-separated words \s*(?P<vi>{delim})\s* # any number of space/tab, # followed by any of the # allowed delimiters, @@ -628,7 +629,8 @@ class RawConfigParser(MutableMapping): _OPT_NV_TMPL = r""" (?P<option> # very permissive! (?:(?!{delim})\S)* # non-delimiter non-whitespace - (?:\s+(?:(?!{delim})\S)+)*) # optionally more words + (?:(?:(?!{delim})\s)+ # optionally more + (?:(?!{delim})\S)+)*) # space-separated words \s*(?: # any number of space/tab, (?P<vi>{delim})\s* # optionally followed by # any of the allowed diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py index 4783943f71a109..7d1e68fe38100e 100644 --- a/Lib/test/test_configparser.py +++ b/Lib/test/test_configparser.py @@ -43,7 +43,7 @@ class CfgParserTestCaseClass: default_section = configparser.DEFAULTSECT interpolation = configparser._UNSET - def newconfig(self, defaults=None): + def newconfig(self, defaults=None, **kwargs): arguments = dict( defaults=defaults, allow_no_value=self.allow_no_value, @@ -56,6 +56,7 @@ def newconfig(self, defaults=None): default_section=self.default_section, interpolation=self.interpolation, ) + arguments.update(kwargs) instance = self.config_class(**arguments) return instance @@ -358,6 +359,32 @@ def test_basic(self): the larch {0[1]} 1 """.format(self.delimiters))) + @support.subTests('data', [ + 'foo bar=baz', + 'foo bar=baz', + 'foo=bar=baz', + 'foo = bar=baz', + 'foo\t \t=\t \tbar=baz', + ]) + def test_space_delimiter(self, data): + # gh-156353: Space should be accepted as a delimiter + cf = self.newconfig(delimiters=(' ', '=')) + cf.read_string(f"[all]\n{data}") + self.assertEqual(cf.options('all'), ['foo']) + self.assertEqual(cf.get('all', 'foo'), 'bar=baz') + + @support.subTests('delimiter', ' =:;#x\t\0\N{RS}\N{CEDILLA}\N{CAT}') + @support.subTests('space_before', ['', ' ', '\t', ' \t']) + @support.subTests('space_after', ['', ' ', '\t', ' \t']) + def test_any_delimiter(self, delimiter, space_before, space_after): + cf = self.newconfig( + delimiters=(delimiter,), + inline_comment_prefixes=None, + ) + cf.read_string(f"[all]\nfoo{space_before}{delimiter}{space_after}bar=baz") + self.assertEqual(cf.options('all'), ['foo']) + self.assertEqual(cf.get('all', 'foo'), 'bar=baz') + def test_basic_from_dict(self): config = { "Foo Bar": { @@ -1991,8 +2018,8 @@ class ConvertersTestCase(BasicTestCase, unittest.TestCase): config_class = configparser.ConfigParser - def newconfig(self, defaults=None): - instance = super().newconfig(defaults=defaults) + def newconfig(self, defaults=None, **kwargs): + instance = super().newconfig(defaults=defaults, **kwargs) instance.converters['list'] = lambda v: [e.strip() for e in v.split() if e.strip()] return instance diff --git a/Misc/NEWS.d/next/Library/2026-08-26-02-30-00.gh-issue-156353.abcdef.rst b/Misc/NEWS.d/next/Library/2026-08-26-02-30-00.gh-issue-156353.abcdef.rst new file mode 100644 index 00000000000000..0dd925cf596277 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-08-26-02-30-00.gh-issue-156353.abcdef.rst @@ -0,0 +1 @@ +Fix :mod:`configparser` parsing when using whitespace in *delimiters*. _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]
