Skip to content

Commit f973bd9

Browse files
sundeep8967encukou
andauthored
gh-156353: Fix configparser space delimiter parsing (#156382)
Co-authored-by: Petr Viktorin <encukou@gmail.com> Signed-off-by: sundeep8967 <sundeep8967@gmail.com>
1 parent 6c425f1 commit f973bd9

3 files changed

Lines changed: 35 additions & 5 deletions

File tree

Lib/configparser.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,8 @@ class RawConfigParser(MutableMapping):
618618
_OPT_TMPL = r"""
619619
(?P<option> # very permissive!
620620
(?:(?!{delim})\S)* # non-delimiter non-whitespace
621-
(?:\s+(?:(?!{delim})\S)+)*) # optionally more words
621+
(?:(?:(?!{delim})\s)+ # optionally more
622+
(?:(?!{delim})\S)+)*) # space-separated words
622623
\s*(?P<vi>{delim})\s* # any number of space/tab,
623624
# followed by any of the
624625
# allowed delimiters,
@@ -628,7 +629,8 @@ class RawConfigParser(MutableMapping):
628629
_OPT_NV_TMPL = r"""
629630
(?P<option> # very permissive!
630631
(?:(?!{delim})\S)* # non-delimiter non-whitespace
631-
(?:\s+(?:(?!{delim})\S)+)*) # optionally more words
632+
(?:(?:(?!{delim})\s)+ # optionally more
633+
(?:(?!{delim})\S)+)*) # space-separated words
632634
\s*(?: # any number of space/tab,
633635
(?P<vi>{delim})\s* # optionally followed by
634636
# any of the allowed

Lib/test/test_configparser.py

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class CfgParserTestCaseClass:
4343
default_section = configparser.DEFAULTSECT
4444
interpolation = configparser._UNSET
4545

46-
def newconfig(self, defaults=None):
46+
def newconfig(self, defaults=None, **kwargs):
4747
arguments = dict(
4848
defaults=defaults,
4949
allow_no_value=self.allow_no_value,
@@ -56,6 +56,7 @@ def newconfig(self, defaults=None):
5656
default_section=self.default_section,
5757
interpolation=self.interpolation,
5858
)
59+
arguments.update(kwargs)
5960
instance = self.config_class(**arguments)
6061
return instance
6162

@@ -358,6 +359,32 @@ def test_basic(self):
358359
the larch {0[1]} 1
359360
""".format(self.delimiters)))
360361

362+
@support.subTests('data', [
363+
'foo bar=baz',
364+
'foo bar=baz',
365+
'foo=bar=baz',
366+
'foo = bar=baz',
367+
'foo\t \t=\t \tbar=baz',
368+
])
369+
def test_space_delimiter(self, data):
370+
# gh-156353: Space should be accepted as a delimiter
371+
cf = self.newconfig(delimiters=(' ', '='))
372+
cf.read_string(f"[all]\n{data}")
373+
self.assertEqual(cf.options('all'), ['foo'])
374+
self.assertEqual(cf.get('all', 'foo'), 'bar=baz')
375+
376+
@support.subTests('delimiter', ' =:;#x\t\0\N{RS}\N{CEDILLA}\N{CAT}')
377+
@support.subTests('space_before', ['', ' ', '\t', ' \t'])
378+
@support.subTests('space_after', ['', ' ', '\t', ' \t'])
379+
def test_any_delimiter(self, delimiter, space_before, space_after):
380+
cf = self.newconfig(
381+
delimiters=(delimiter,),
382+
inline_comment_prefixes=None,
383+
)
384+
cf.read_string(f"[all]\nfoo{space_before}{delimiter}{space_after}bar=baz")
385+
self.assertEqual(cf.options('all'), ['foo'])
386+
self.assertEqual(cf.get('all', 'foo'), 'bar=baz')
387+
361388
def test_basic_from_dict(self):
362389
config = {
363390
"Foo Bar": {
@@ -1991,8 +2018,8 @@ class ConvertersTestCase(BasicTestCase, unittest.TestCase):
19912018

19922019
config_class = configparser.ConfigParser
19932020

1994-
def newconfig(self, defaults=None):
1995-
instance = super().newconfig(defaults=defaults)
2021+
def newconfig(self, defaults=None, **kwargs):
2022+
instance = super().newconfig(defaults=defaults, **kwargs)
19962023
instance.converters['list'] = lambda v: [e.strip() for e in v.split()
19972024
if e.strip()]
19982025
return instance
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix :mod:`configparser` parsing when using whitespace in *delimiters*.

0 commit comments

Comments
 (0)