From 7393c69d6da61c3756ec424d709f6cfdd2866e3e Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Mon, 27 May 2013 10:58:55 -0700 Subject: [PATCH] Issue #18015: Fix unpickling of 2.7.3 and 2.7.4 namedtuples. --- Doc/library/collections.rst | 6 +++++ Lib/collections.py | 6 +++++ Lib/test/test_collections.py | 44 +++++++++++++++++++++++++++++++++++- Misc/NEWS | 2 ++ 4 files changed, 57 insertions(+), 1 deletion(-) diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index ab290e79f358..b7628bb8deb7 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -638,6 +638,12 @@ Example: def __getnewargs__(self): 'Return self as a plain tuple. Used by copy and pickle.' return tuple(self) + + __dict__ = _property(_asdict) + + def __getstate__(self): + 'Exclude the OrderedDict from pickling' + pass x = _property(_itemgetter(0), doc='Alias for field number 0') diff --git a/Lib/collections.py b/Lib/collections.py index af32e448a9ce..b9df2c14c915 100644 --- a/Lib/collections.py +++ b/Lib/collections.py @@ -270,6 +270,12 @@ class {typename}(tuple): 'Return self as a plain tuple. Used by copy and pickle.' return tuple(self) + __dict__ = _property(_asdict) + + def __getstate__(self): + 'Exclude the OrderedDict from pickling' + pass + {field_defs} ''' diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index 8bdeb3d8f1f9..3aaecb2a6f9b 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -17,6 +17,43 @@ from collections import Sequence, MutableSequence TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests +py273_named_tuple_pickle = '''\ +ccopy_reg +_reconstructor +p0 +(ctest.test_collections +TestNT +p1 +c__builtin__ +tuple +p2 +(I10 +I20 +I30 +tp3 +tp4 +Rp5 +ccollections +OrderedDict +p6 +((lp7 +(lp8 +S'x' +p9 +aI10 +aa(lp10 +S'y' +p11 +aI20 +aa(lp12 +S'z' +p13 +aI30 +aatp14 +Rp15 +b. +''' + class TestNamedTuple(unittest.TestCase): def test_factory(self): @@ -78,12 +115,12 @@ class TestNamedTuple(unittest.TestCase): self.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals()) # wrong keyword argument self.assertRaises(TypeError, eval, 'Point(x=1)', locals()) # missing keyword argument self.assertEqual(repr(p), 'Point(x=11, y=22)') - self.assertNotIn('__dict__', dir(p)) # verify instance has no dict self.assertNotIn('__weakref__', dir(p)) self.assertEqual(p, Point._make([11, 22])) # test _make classmethod self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method + self.assertEqual(vars(p), p._asdict()) # verify that vars() works try: p._replace(x=1, error=2) @@ -215,6 +252,11 @@ class TestNamedTuple(unittest.TestCase): # test __getnewargs__ self.assertEqual(t.__getnewargs__(), values) + def test_pickling_bug_18015(self): + # http://bugs.python.org/issue18015 + pt = pickle.loads(py273_named_tuple_pickle) + self.assertEqual(pt.x, 10) + class ABCTestCase(unittest.TestCase): def validate_abstract_methods(self, abc, *names): diff --git a/Misc/NEWS b/Misc/NEWS index 8fdc8810a80f..13f7cc360a34 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,8 @@ Library - Issue #17981: Closed socket on error in SysLogHandler. +- Issue #18015: Fix unpickling of 2.7.3 and 2.7.4 namedtuples. + - Issue #17754: Make ctypes.util.find_library() independent of the locale. - Fix typos in the multiprocessing module. -- 2.47.3