Commit 7460a717 authored by Łukasz Langa's avatar Łukasz Langa

Fixes #24142: [configparser] always join multiline values to not leave the...

Fixes #24142: [configparser] always join multiline values to not leave the parser in an invalid state
parent 2a353e92
...@@ -1102,10 +1102,10 @@ class RawConfigParser(MutableMapping): ...@@ -1102,10 +1102,10 @@ class RawConfigParser(MutableMapping):
# raised at the end of the file and will contain a # raised at the end of the file and will contain a
# list of all bogus lines # list of all bogus lines
e = self._handle_error(e, fpname, lineno, line) e = self._handle_error(e, fpname, lineno, line)
self._join_multiline_values()
# if any parsing errors occurred, raise an exception # if any parsing errors occurred, raise an exception
if e: if e:
raise e raise e
self._join_multiline_values()
def _join_multiline_values(self): def _join_multiline_values(self):
defaults = self.default_section, self._defaults defaults = self.default_section, self._defaults
......
...@@ -9,6 +9,7 @@ import warnings ...@@ -9,6 +9,7 @@ import warnings
from test import support from test import support
class SortedDict(collections.UserDict): class SortedDict(collections.UserDict):
def items(self): def items(self):
...@@ -64,6 +65,7 @@ class CfgParserTestCaseClass: ...@@ -64,6 +65,7 @@ class CfgParserTestCaseClass:
cf.read_string(string) cf.read_string(string)
return cf return cf
class BasicTestCase(CfgParserTestCaseClass): class BasicTestCase(CfgParserTestCaseClass):
def basic_test(self, cf): def basic_test(self, cf):
...@@ -828,6 +830,21 @@ boolean {0[0]} NO ...@@ -828,6 +830,21 @@ boolean {0[0]} NO
self.assertEqual(set(cf['section3'].keys()), set()) self.assertEqual(set(cf['section3'].keys()), set())
self.assertEqual(cf.sections(), ['section1', 'section2', 'section3']) self.assertEqual(cf.sections(), ['section1', 'section2', 'section3'])
def test_invalid_multiline_value(self):
if self.allow_no_value:
self.skipTest('if no_value is allowed, ParsingError is not raised')
invalid = textwrap.dedent("""\
[DEFAULT]
test {0} test
invalid""".format(self.delimiters[0])
)
cf = self.newconfig()
with self.assertRaises(configparser.ParsingError):
cf.read_string(invalid)
self.assertEqual(cf.get('DEFAULT', 'test'), 'test')
self.assertEqual(cf['DEFAULT']['test'], 'test')
class StrictTestCase(BasicTestCase, unittest.TestCase): class StrictTestCase(BasicTestCase, unittest.TestCase):
config_class = configparser.RawConfigParser config_class = configparser.RawConfigParser
...@@ -981,14 +998,17 @@ class ConfigParserTestCaseLegacyInterpolation(ConfigParserTestCase): ...@@ -981,14 +998,17 @@ class ConfigParserTestCaseLegacyInterpolation(ConfigParserTestCase):
cf.set("sect", "option2", "foo%%bar") cf.set("sect", "option2", "foo%%bar")
self.assertEqual(cf.get("sect", "option2"), "foo%%bar") self.assertEqual(cf.get("sect", "option2"), "foo%%bar")
class ConfigParserTestCaseNonStandardDelimiters(ConfigParserTestCase): class ConfigParserTestCaseNonStandardDelimiters(ConfigParserTestCase):
delimiters = (':=', '$') delimiters = (':=', '$')
comment_prefixes = ('//', '"') comment_prefixes = ('//', '"')
inline_comment_prefixes = ('//', '"') inline_comment_prefixes = ('//', '"')
class ConfigParserTestCaseNonStandardDefaultSection(ConfigParserTestCase): class ConfigParserTestCaseNonStandardDefaultSection(ConfigParserTestCase):
default_section = 'general' default_section = 'general'
class MultilineValuesTestCase(BasicTestCase, unittest.TestCase): class MultilineValuesTestCase(BasicTestCase, unittest.TestCase):
config_class = configparser.ConfigParser config_class = configparser.ConfigParser
wonderful_spam = ("I'm having spam spam spam spam " wonderful_spam = ("I'm having spam spam spam spam "
...@@ -1017,6 +1037,7 @@ class MultilineValuesTestCase(BasicTestCase, unittest.TestCase): ...@@ -1017,6 +1037,7 @@ class MultilineValuesTestCase(BasicTestCase, unittest.TestCase):
self.assertEqual(cf_from_file.get('section8', 'lovely_spam4'), self.assertEqual(cf_from_file.get('section8', 'lovely_spam4'),
self.wonderful_spam.replace('\t\n', '\n')) self.wonderful_spam.replace('\t\n', '\n'))
class RawConfigParserTestCase(BasicTestCase, unittest.TestCase): class RawConfigParserTestCase(BasicTestCase, unittest.TestCase):
config_class = configparser.RawConfigParser config_class = configparser.RawConfigParser
...@@ -1059,11 +1080,13 @@ class RawConfigParserTestCase(BasicTestCase, unittest.TestCase): ...@@ -1059,11 +1080,13 @@ class RawConfigParserTestCase(BasicTestCase, unittest.TestCase):
cf.set('non-string', 1, 1) cf.set('non-string', 1, 1)
self.assertEqual(cf.get('non-string', 1), 1) self.assertEqual(cf.get('non-string', 1), 1)
class RawConfigParserTestCaseNonStandardDelimiters(RawConfigParserTestCase): class RawConfigParserTestCaseNonStandardDelimiters(RawConfigParserTestCase):
delimiters = (':=', '$') delimiters = (':=', '$')
comment_prefixes = ('//', '"') comment_prefixes = ('//', '"')
inline_comment_prefixes = ('//', '"') inline_comment_prefixes = ('//', '"')
class RawConfigParserTestSambaConf(CfgParserTestCaseClass, unittest.TestCase): class RawConfigParserTestSambaConf(CfgParserTestCaseClass, unittest.TestCase):
config_class = configparser.RawConfigParser config_class = configparser.RawConfigParser
comment_prefixes = ('#', ';', '----') comment_prefixes = ('#', ';', '----')
...@@ -1258,6 +1281,7 @@ class ConfigParserTestCaseExtendedInterpolation(BasicTestCase, unittest.TestCase ...@@ -1258,6 +1281,7 @@ class ConfigParserTestCaseExtendedInterpolation(BasicTestCase, unittest.TestCase
class ConfigParserTestCaseNoValue(ConfigParserTestCase): class ConfigParserTestCaseNoValue(ConfigParserTestCase):
allow_no_value = True allow_no_value = True
class ConfigParserTestCaseTrickyFile(CfgParserTestCaseClass, unittest.TestCase): class ConfigParserTestCaseTrickyFile(CfgParserTestCaseClass, unittest.TestCase):
config_class = configparser.ConfigParser config_class = configparser.ConfigParser
delimiters = {'='} delimiters = {'='}
......
...@@ -655,6 +655,7 @@ Jeremy Hylton ...@@ -655,6 +655,7 @@ Jeremy Hylton
Ludwig Hähne Ludwig Hähne
Gerhard Häring Gerhard Häring
Fredrik Håård Fredrik Håård
Florian Höch
Catalin Iacob Catalin Iacob
Mihai Ibanescu Mihai Ibanescu
Ali Ikinci Ali Ikinci
......
...@@ -472,6 +472,9 @@ Library ...@@ -472,6 +472,9 @@ Library
- Issue #28703: Fix asyncio.iscoroutinefunction to handle Mock objects. - Issue #28703: Fix asyncio.iscoroutinefunction to handle Mock objects.
- Issue #24142: Reading a corrupt config file left the parser in an
invalid state. Original patch by Florian Höch.
IDLE IDLE
---- ----
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment