(original) (raw)

changeset: 74545:5ecf650ede7c branch: 2.7 parent: 74537:b60c789c4ccd user: Ɓukasz Langa lukasz@langa.pl date: Fri Jan 20 17:02:08 2012 +0100 files: Lib/ConfigParser.py Lib/test/test_cfgparser.py description: Fixes #13760: picklability of ConfigParser exceptions diff -r b60c789c4ccd -r 5ecf650ede7c Lib/ConfigParser.py --- a/Lib/ConfigParser.py Fri Jan 20 11:20:12 2012 +0000 +++ b/Lib/ConfigParser.py Fri Jan 20 17:02:08 2012 +0100 @@ -134,6 +134,9 @@ def __repr__(self): return self.message + def __reduce__(self): + return self.__class__, (self.message,) + __str__ = __repr__ class NoSectionError(Error): @@ -143,6 +146,9 @@ 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 @@ 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 @@ 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 @@ 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 @@ % (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 @@ "\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 @@ 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 -r b60c789c4ccd -r 5ecf650ede7c Lib/test/test_cfgparser.py --- a/Lib/test/test_cfgparser.py Fri Jan 20 11:20:12 2012 +0000 +++ b/Lib/test/test_cfgparser.py Fri Jan 20 17:02:08 2012 +0100 @@ -604,6 +604,122 @@ "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 @@ SortedTestCase, Issue7005TestCase, TestChainMap, + ExceptionPicklingTestCase, ) /lukasz@langa.pl