diff options
author | Raymond Hettinger <python@rcn.com> | 2009-05-27 00:38:24 (GMT) |
---|---|---|
committer | Raymond Hettinger <python@rcn.com> | 2009-05-27 00:38:24 (GMT) |
commit | 089ba7f69012a51c3c809a4d7bde62d67ebbb537 (patch) | |
tree | 182fec8a6a1ad8e89bd9605c8c3c11b302bbc7b5 | |
parent | e261ae0d46d610899fd0822ae9277dd6df54fefe (diff) | |
download | cpython-089ba7f69012a51c3c809a4d7bde62d67ebbb537.zip cpython-089ba7f69012a51c3c809a4d7bde62d67ebbb537.tar.gz cpython-089ba7f69012a51c3c809a4d7bde62d67ebbb537.tar.bz2 |
Fix field name conflicts for named tuples.
-rw-r--r-- | Doc/library/collections.rst | 12 | ||||
-rw-r--r-- | Lib/collections.py | 14 | ||||
-rw-r--r-- | Lib/test/test_collections.py | 9 | ||||
-rw-r--r-- | Misc/NEWS | 3 |
4 files changed, 25 insertions, 13 deletions
diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index 4c64d61..779f154 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -647,8 +647,8 @@ Example: <BLANKLINE> _fields = ('x', 'y') <BLANKLINE> - def __new__(cls, x, y): - return tuple.__new__(cls, (x, y)) + def __new__(_cls, x, y): + return _tuple.__new__(_cls, (x, y)) <BLANKLINE> @classmethod def _make(cls, iterable, new=tuple.__new__, len=len): @@ -665,9 +665,9 @@ Example: 'Return a new OrderedDict which maps field names to their values' return OrderedDict(zip(self._fields, self)) <BLANKLINE> - def _replace(self, **kwds): + def _replace(_self, **kwds): 'Return a new Point object replacing specified fields with new values' - result = self._make(map(kwds.pop, ('x', 'y'), self)) + result = _self._make(map(kwds.pop, ('x', 'y'), _self)) if kwds: raise ValueError('Got unexpected field names: %r' % kwds.keys()) return result @@ -675,8 +675,8 @@ Example: def __getnewargs__(self): return tuple(self) <BLANKLINE> - x = property(itemgetter(0)) - y = property(itemgetter(1)) + x = _property(_itemgetter(0)) + y = _property(_itemgetter(1)) >>> p = Point(11, y=22) # instantiate with positional or keyword arguments >>> p[0] + p[1] # indexable like the plain tuple (11, 22) diff --git a/Lib/collections.py b/Lib/collections.py index 6e2fe29..bd5d3e8 100644 --- a/Lib/collections.py +++ b/Lib/collections.py @@ -232,8 +232,8 @@ def namedtuple(typename, field_names, verbose=False, rename=False): '%(typename)s(%(argtxt)s)' \n __slots__ = () \n _fields = %(field_names)r \n - def __new__(cls, %(argtxt)s): - return tuple.__new__(cls, (%(argtxt)s)) \n + def __new__(_cls, %(argtxt)s): + return _tuple.__new__(_cls, (%(argtxt)s)) \n @classmethod def _make(cls, iterable, new=tuple.__new__, len=len): 'Make a new %(typename)s object from a sequence or iterable' @@ -246,23 +246,23 @@ def namedtuple(typename, field_names, verbose=False, rename=False): def _asdict(self): 'Return a new OrderedDict which maps field names to their values' return OrderedDict(zip(self._fields, self)) \n - def _replace(self, **kwds): + def _replace(_self, **kwds): 'Return a new %(typename)s object replacing specified fields with new values' - result = self._make(map(kwds.pop, %(field_names)r, self)) + result = _self._make(map(kwds.pop, %(field_names)r, _self)) if kwds: raise ValueError('Got unexpected field names: %%r' %% kwds.keys()) return result \n def __getnewargs__(self): return tuple(self) \n\n''' % locals() for i, name in enumerate(field_names): - template += ' %s = property(itemgetter(%d))\n' % (name, i) + template += ' %s = _property(_itemgetter(%d))\n' % (name, i) if verbose: print(template) # Execute the template string in a temporary namespace and # support tracing utilities by setting a value for frame.f_globals['__name__'] - namespace = dict(itemgetter=_itemgetter, __name__='namedtuple_%s' % typename, - OrderedDict=OrderedDict) + namespace = dict(_itemgetter=_itemgetter, __name__='namedtuple_%s' % typename, + OrderedDict=OrderedDict, _property=property, _tuple=tuple) try: exec(template, namespace) except SyntaxError as e: diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index c471361..ad79ad5 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -173,6 +173,15 @@ class TestNamedTuple(unittest.TestCase): self.assertEqual(p, q) self.assertEqual(p._fields, q._fields) + def test_name_conflicts(self): + # Some names like "self", "cls", "tuple", "itemgetter", and "property" + # failed when used as field names. Test to make sure these now work. + T = namedtuple('T', 'itemgetter property self cls tuple') + t = T(1, 2, 3, 4, 5) + self.assertEqual(t, (1,2,3,4,5)) + newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50) + self.assertEqual(newt, (10,20,30,40,50)) + class ABCTestCase(unittest.TestCase): def validate_abstract_methods(self, abc, *names): @@ -37,6 +37,9 @@ Library - Issue #6118: urllib.parse.quote_plus ignored the encoding and errors arguments for strings with a space in them. +- collections.namedtuple() was not working with the following field + names: cls, self, tuple, itemgetter, and property. + - In unittest, using a skipping decorator on a class is now equivalent to skipping every test on the class. The ClassTestSuite class has been removed. |