]> granicus.if.org Git - python/commitdiff
Fixes #24142: [configparser] always join multiline values to not leave the parser...
authorŁukasz Langa <lukasz@langa.pl>
Sat, 26 Nov 2016 22:00:39 +0000 (14:00 -0800)
committerŁukasz Langa <lukasz@langa.pl>
Sat, 26 Nov 2016 22:00:39 +0000 (14:00 -0800)
Lib/configparser.py
Lib/test/test_configparser.py
Misc/ACKS
Misc/NEWS

index 3a9fb56dc632c99776bd567694d646aeaa138505..af5aca1feae34a4ff38d20b461f7b1ecbfe338dc 100644 (file)
@@ -1102,10 +1102,10 @@ class RawConfigParser(MutableMapping):
                         # raised at the end of the file and will contain a
                         # list of all bogus lines
                         e = self._handle_error(e, fpname, lineno, line)
+        self._join_multiline_values()
         # if any parsing errors occurred, raise an exception
         if e:
             raise e
-        self._join_multiline_values()
 
     def _join_multiline_values(self):
         defaults = self.default_section, self._defaults
index 71a8f3f8d96db559751e4787eeb6402a4298c84b..864a1d0802f5d20a4d75519d33213e17d88eee95 100644 (file)
@@ -9,6 +9,7 @@ import warnings
 
 from test import support
 
+
 class SortedDict(collections.UserDict):
 
     def items(self):
@@ -64,6 +65,7 @@ class CfgParserTestCaseClass:
         cf.read_string(string)
         return cf
 
+
 class BasicTestCase(CfgParserTestCaseClass):
 
     def basic_test(self, cf):
@@ -828,6 +830,21 @@ boolean {0[0]} NO
         self.assertEqual(set(cf['section3'].keys()), set())
         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):
     config_class = configparser.RawConfigParser
@@ -981,14 +998,17 @@ class ConfigParserTestCaseLegacyInterpolation(ConfigParserTestCase):
         cf.set("sect", "option2", "foo%%bar")
         self.assertEqual(cf.get("sect", "option2"), "foo%%bar")
 
+
 class ConfigParserTestCaseNonStandardDelimiters(ConfigParserTestCase):
     delimiters = (':=', '$')
     comment_prefixes = ('//', '"')
     inline_comment_prefixes = ('//', '"')
 
+
 class ConfigParserTestCaseNonStandardDefaultSection(ConfigParserTestCase):
     default_section = 'general'
 
+
 class MultilineValuesTestCase(BasicTestCase, unittest.TestCase):
     config_class = configparser.ConfigParser
     wonderful_spam = ("I'm having spam spam spam spam "
@@ -1017,6 +1037,7 @@ class MultilineValuesTestCase(BasicTestCase, unittest.TestCase):
         self.assertEqual(cf_from_file.get('section8', 'lovely_spam4'),
                          self.wonderful_spam.replace('\t\n', '\n'))
 
+
 class RawConfigParserTestCase(BasicTestCase, unittest.TestCase):
     config_class = configparser.RawConfigParser
 
@@ -1059,11 +1080,13 @@ class RawConfigParserTestCase(BasicTestCase, unittest.TestCase):
             cf.set('non-string', 1, 1)
             self.assertEqual(cf.get('non-string', 1), 1)
 
+
 class RawConfigParserTestCaseNonStandardDelimiters(RawConfigParserTestCase):
     delimiters = (':=', '$')
     comment_prefixes = ('//', '"')
     inline_comment_prefixes = ('//', '"')
 
+
 class RawConfigParserTestSambaConf(CfgParserTestCaseClass, unittest.TestCase):
     config_class = configparser.RawConfigParser
     comment_prefixes = ('#', ';', '----')
@@ -1258,6 +1281,7 @@ class ConfigParserTestCaseExtendedInterpolation(BasicTestCase, unittest.TestCase
 class ConfigParserTestCaseNoValue(ConfigParserTestCase):
     allow_no_value = True
 
+
 class ConfigParserTestCaseTrickyFile(CfgParserTestCaseClass, unittest.TestCase):
     config_class = configparser.ConfigParser
     delimiters = {'='}
index c8c63f142ca199744bdc1a6dcc7dc02c9889cd6d..08d06e75c524d5485820153841327298d24c3482 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -655,6 +655,7 @@ Jeremy Hylton
 Ludwig Hähne
 Gerhard Häring
 Fredrik Håård
+Florian Höch
 Catalin Iacob
 Mihai Ibanescu
 Ali Ikinci
index 785f3616e16e6404bbbe97ef044b1f048f6c1abf..3b8ca5e68b813a56c0ecf7739c9105732790edf5 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -472,6 +472,9 @@ Library
 
 - 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
 ----