]> granicus.if.org Git - python/commitdiff
Issue #24931: Resolve __dict__ conflict in namedtuple subclasses.
authorRaymond Hettinger <python@rcn.com>
Sun, 30 Aug 2015 16:13:48 +0000 (09:13 -0700)
committerRaymond Hettinger <python@rcn.com>
Sun, 30 Aug 2015 16:13:48 +0000 (09:13 -0700)
Doc/library/collections.rst
Lib/collections/__init__.py
Lib/test/test_collections.py
Misc/NEWS

index 766bd38c59a85bec6064b6e1d863ba5944c71eec..347cf1fca5c5890d3fad746f50de9d138a530bd8 100644 (file)
@@ -816,10 +816,10 @@ field names, the method and attribute names start with an underscore.
 .. method:: somenamedtuple._asdict()
 
     Return a new :class:`OrderedDict` which maps field names to their corresponding
-    values.  Note, this method is no longer needed now that the same effect can
-    be achieved by using the built-in :func:`vars` function::
+    values::
 
-        >>> vars(p)
+        >>> p = Point(x=11, y=22)
+        >>> p._asdict()
         OrderedDict([('x', 11), ('y', 22)])
 
     .. versionchanged:: 3.1
index 565ae86f8841ec43d44726fd15d3045a7feb2c01..09afc8a38ec8f23fdb66b15d7662a165eb03efaf 100644 (file)
@@ -272,23 +272,14 @@ class {typename}(tuple):
         'Return a nicely formatted representation string'
         return self.__class__.__name__ + '({repr_fmt})' % self
 
-    @property
-    def __dict__(self):
-        'A new OrderedDict mapping field names to their values'
-        return OrderedDict(zip(self._fields, self))
-
     def _asdict(self):
         'Return a new OrderedDict which maps field names to their values.'
-        return self.__dict__
+        return OrderedDict(zip(self._fields, self))
 
     def __getnewargs__(self):
         'Return self as a plain tuple.  Used by copy and pickle.'
         return tuple(self)
 
-    def __getstate__(self):
-        'Exclude the OrderedDict from pickling'
-        return None
-
 {field_defs}
 """
 
index df1c63c833bcc53228a463d173d4b84207a4b2b3..66db90f993f1416a770469f6a839cff441d01ace 100644 (file)
@@ -225,7 +225,6 @@ class TestNamedTuple(unittest.TestCase):
         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)
@@ -380,6 +379,17 @@ class TestNamedTuple(unittest.TestCase):
         globals().pop('NTColor', None)          # clean-up after this test
 
 
+    def test_namedtuple_subclass_issue_24931(self):
+        class Point(namedtuple('_Point', ['x', 'y'])):
+            pass
+
+        a = Point(3, 4)
+        self.assertEqual(a._asdict(), OrderedDict([('x', 3), ('y', 4)]))
+
+        a.w = 5
+        self.assertEqual(a.__dict__, {'w': 5})
+
+
 ################################################################################
 ### Abstract Base Classes
 ################################################################################
index b74b15ce18f56000edb382223b52ea010aa57e5a..0b464518373b7759151a36eebfba2891dd80536a 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -78,6 +78,10 @@ Library
 - Issue #21112: Fix regression in unittest.expectedFailure on subclasses.
   Patch from Berker Peksag.
 
+- Issue #24931: Instances of subclasses of namedtuples have their own __dict__
+  which breaks the inherited __dict__ property and breaks the _asdict() method.
+  Removed the __dict__ property to prevent the conflict and fixed _asdict().
+
 - Issue #24764: cgi.FieldStorage.read_multi() now ignores the Content-Length
   header in part headers. Patch written by Peter Landry and reviewed by Pierre
   Quentel.