diff options
-rw-r--r-- | Lib/ConfigParser.py | 34 | ||||
-rw-r--r-- | Lib/test/test_cfgparser.py | 117 |
2 files changed, 150 insertions, 1 deletions
diff --git a/Lib/ConfigParser.py b/Lib/ConfigParser.py index 963a4187e4..049373948b 100644 --- a/Lib/ConfigParser.py +++ b/Lib/ConfigParser.py @@ -134,6 +134,9 @@ class Error(Exception): def __repr__(self): return self.message + def __reduce__(self): + return self.__class__, (self.message,) + __str__ = __repr__ class NoSectionError(Error): @@ -143,6 +146,9 @@ class NoSectionError(Error): Error.__init__(self, 'No section: %r' % (section,)) self.section = section + def __reduce__(self): + return self.__class__, (self.section,) + class DuplicateSectionError(Error): """Raised when a section is multiply-created.""" @@ -150,6 +156,9 @@ class DuplicateSectionError(Error): Error.__init__(self, "Section %r already exists" % section) self.section = section + def __reduce__(self): + return self.__class__, (self.section,) + class NoOptionError(Error): """A requested option was not found.""" @@ -159,6 +168,9 @@ class NoOptionError(Error): self.option = option self.section = section + def __reduce__(self): + return self.__class__, (self.option, self.section) + class InterpolationError(Error): """Base class for interpolation-related exceptions.""" @@ -167,6 +179,9 @@ class InterpolationError(Error): self.option = option self.section = section + def __reduce__(self): + return self.__class__, (self.option, self.section, self.message) + class InterpolationMissingOptionError(InterpolationError): """A string substitution required a setting which was not available.""" @@ -179,6 +194,11 @@ class InterpolationMissingOptionError(InterpolationError): % (section, option, reference, rawval)) InterpolationError.__init__(self, option, section, msg) self.reference = reference + self._rawval = rawval + + def __reduce__(self): + return self.__class__, (self.option, self.section, self._rawval, + self.reference) class InterpolationSyntaxError(InterpolationError): """Raised when the source text into which substitutions are made @@ -194,19 +214,28 @@ class InterpolationDepthError(InterpolationError): "\trawval : %s\n" % (section, option, rawval)) InterpolationError.__init__(self, option, section, msg) + self._rawval = rawval + + def __reduce__(self): + return self.__class__, (self.option, self.section, self._rawval) class ParsingError(Error): """Raised when a configuration file does not follow legal syntax.""" - def __init__(self, filename): + def __init__(self, filename, _errors=[]): Error.__init__(self, 'File contains parsing errors: %s' % filename) self.filename = filename self.errors = [] + for lineno, line in _errors: + self.append(lineno, line) def append(self, lineno, line): self.errors.append((lineno, line)) self.message += '\n\t[line %2d]: %s' % (lineno, line) + def __reduce__(self): + return self.__class__, (self.filename, self.errors) + class MissingSectionHeaderError(ParsingError): """Raised when a key-value pair is found before any section header.""" @@ -219,6 +248,9 @@ class MissingSectionHeaderError(ParsingError): self.lineno = lineno self.line = line + def __reduce__(self): + return self.__class__, (self.filename, self.lineno, self.line) + class RawConfigParser: def __init__(self, defaults=None, dict_type=_default_dict, diff --git a/Lib/test/test_cfgparser.py b/Lib/test/test_cfgparser.py index a7ad18dc0f..f0073f04af 100644 --- a/Lib/test/test_cfgparser.py +++ b/Lib/test/test_cfgparser.py @@ -604,6 +604,122 @@ class SortedTestCase(RawConfigParserTestCase): "o4 = 1\n\n") +class ExceptionPicklingTestCase(unittest.TestCase): + """Tests for issue #13760: ConfigParser exceptions are not picklable.""" + + def test_error(self): + import pickle + e1 = ConfigParser.Error('value') + pickled = pickle.dumps(e1) + e2 = pickle.loads(pickled) + self.assertEqual(e1.message, e2.message) + self.assertEqual(repr(e1), repr(e2)) + + def test_nosectionerror(self): + import pickle + e1 = ConfigParser.NoSectionError('section') + pickled = pickle.dumps(e1) + e2 = pickle.loads(pickled) + self.assertEqual(e1.message, e2.message) + self.assertEqual(e1.args, e2.args) + self.assertEqual(e1.section, e2.section) + self.assertEqual(repr(e1), repr(e2)) + + def test_nooptionerror(self): + import pickle + e1 = ConfigParser.NoOptionError('option', 'section') + pickled = pickle.dumps(e1) + e2 = pickle.loads(pickled) + self.assertEqual(e1.message, e2.message) + self.assertEqual(e1.args, e2.args) + self.assertEqual(e1.section, e2.section) + self.assertEqual(e1.option, e2.option) + self.assertEqual(repr(e1), repr(e2)) + + def test_duplicatesectionerror(self): + import pickle + e1 = ConfigParser.DuplicateSectionError('section') + pickled = pickle.dumps(e1) + e2 = pickle.loads(pickled) + self.assertEqual(e1.message, e2.message) + self.assertEqual(e1.args, e2.args) + self.assertEqual(e1.section, e2.section) + self.assertEqual(repr(e1), repr(e2)) + + def test_interpolationerror(self): + import pickle + e1 = ConfigParser.InterpolationError('option', 'section', 'msg') + pickled = pickle.dumps(e1) + e2 = pickle.loads(pickled) + self.assertEqual(e1.message, e2.message) + self.assertEqual(e1.args, e2.args) + self.assertEqual(e1.section, e2.section) + self.assertEqual(e1.option, e2.option) + self.assertEqual(repr(e1), repr(e2)) + + def test_interpolationmissingoptionerror(self): + import pickle + e1 = ConfigParser.InterpolationMissingOptionError('option', 'section', + 'rawval', 'reference') + pickled = pickle.dumps(e1) + e2 = pickle.loads(pickled) + self.assertEqual(e1.message, e2.message) + self.assertEqual(e1.args, e2.args) + self.assertEqual(e1.section, e2.section) + self.assertEqual(e1.option, e2.option) + self.assertEqual(e1.reference, e2.reference) + self.assertEqual(repr(e1), repr(e2)) + + def test_interpolationsyntaxerror(self): + import pickle + e1 = ConfigParser.InterpolationSyntaxError('option', 'section', 'msg') + pickled = pickle.dumps(e1) + e2 = pickle.loads(pickled) + self.assertEqual(e1.message, e2.message) + self.assertEqual(e1.args, e2.args) + self.assertEqual(e1.section, e2.section) + self.assertEqual(e1.option, e2.option) + self.assertEqual(repr(e1), repr(e2)) + + def test_interpolationdeptherror(self): + import pickle + e1 = ConfigParser.InterpolationDepthError('option', 'section', + 'rawval') + pickled = pickle.dumps(e1) + e2 = pickle.loads(pickled) + self.assertEqual(e1.message, e2.message) + self.assertEqual(e1.args, e2.args) + self.assertEqual(e1.section, e2.section) + self.assertEqual(e1.option, e2.option) + self.assertEqual(repr(e1), repr(e2)) + + def test_parsingerror(self): + import pickle + e1 = ConfigParser.ParsingError('source') + e1.append(1, 'line1') + e1.append(2, 'line2') + e1.append(3, 'line3') + pickled = pickle.dumps(e1) + e2 = pickle.loads(pickled) + self.assertEqual(e1.message, e2.message) + self.assertEqual(e1.args, e2.args) + self.assertEqual(e1.filename, e2.filename) + self.assertEqual(e1.errors, e2.errors) + self.assertEqual(repr(e1), repr(e2)) + + def test_missingsectionheadererror(self): + import pickle + e1 = ConfigParser.MissingSectionHeaderError('filename', 123, 'line') + pickled = pickle.dumps(e1) + e2 = pickle.loads(pickled) + self.assertEqual(e1.message, e2.message) + self.assertEqual(e1.args, e2.args) + self.assertEqual(e1.line, e2.line) + self.assertEqual(e1.filename, e2.filename) + self.assertEqual(e1.lineno, e2.lineno) + self.assertEqual(repr(e1), repr(e2)) + + def test_main(): test_support.run_unittest( ConfigParserTestCase, @@ -614,6 +730,7 @@ def test_main(): SortedTestCase, Issue7005TestCase, TestChainMap, + ExceptionPicklingTestCase, ) |