From a86b522d8f1c8b9c26b5550de221d2227158cf4d Mon Sep 17 00:00:00 2001 From: Ammar Askar Date: Tue, 14 Apr 2020 23:36:08 -0700 Subject: bpo-40277: Add a repr() to namedtuple's _tuplegetter to aid with introspection (GH-19537) --- Lib/test/test_collections.py | 12 ++++++++++++ .../next/Library/2020-04-14-21-53-18.bpo-40277.NknSaf.rst | 2 ++ Modules/_collectionsmodule.c | 10 +++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2020-04-14-21-53-18.bpo-40277.NknSaf.rst diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index 0207823..a8d3337 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -411,6 +411,18 @@ class TestNamedTuple(unittest.TestCase): self.assertIs(P.m.__doc__, Q.o.__doc__) self.assertIs(P.n.__doc__, Q.p.__doc__) + @support.cpython_only + def test_field_repr(self): + Point = namedtuple('Point', 'x y') + self.assertEqual(repr(Point.x), "_tuplegetter(0, 'Alias for field number 0')") + self.assertEqual(repr(Point.y), "_tuplegetter(1, 'Alias for field number 1')") + + Point.x.__doc__ = 'The x-coordinate' + Point.y.__doc__ = 'The y-coordinate' + + self.assertEqual(repr(Point.x), "_tuplegetter(0, 'The x-coordinate')") + self.assertEqual(repr(Point.y), "_tuplegetter(1, 'The y-coordinate')") + def test_name_fixer(self): for spec, renamed in [ [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char diff --git a/Misc/NEWS.d/next/Library/2020-04-14-21-53-18.bpo-40277.NknSaf.rst b/Misc/NEWS.d/next/Library/2020-04-14-21-53-18.bpo-40277.NknSaf.rst new file mode 100644 index 0000000..1fa2999 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-04-14-21-53-18.bpo-40277.NknSaf.rst @@ -0,0 +1,2 @@ +:func:`collections.namedtuple` now provides a human-readable repr for its +field accessors. diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index 978ea03..7120e4d 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -2493,6 +2493,14 @@ tuplegetter_reduce(_tuplegetterobject *self, PyObject *Py_UNUSED(ignored)) return Py_BuildValue("(O(nO))", (PyObject*) Py_TYPE(self), self->index, self->doc); } +static PyObject* +tuplegetter_repr(_tuplegetterobject *self) +{ + return PyUnicode_FromFormat("%s(%zd, %R)", + _PyType_Name(Py_TYPE(self)), + self->index, self->doc); +} + static PyMemberDef tuplegetter_members[] = { {"__doc__", T_OBJECT, offsetof(_tuplegetterobject, doc), 0}, @@ -2515,7 +2523,7 @@ static PyTypeObject tuplegetter_type = { 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - 0, /* tp_repr */ + (reprfunc)tuplegetter_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ -- cgit v0.12