changeset: 97454:f5c40ab9e233 user: Raymond Hettinger date: Tue Aug 18 22:25:16 2015 -0700 files: Lib/pydoc.py Lib/test/test_pydoc.py Misc/NEWS description: Issue #24879: Teach pydoc to display named tuple fields in the order they were defined. diff -r e10a34f8c23f -r f5c40ab9e233 Lib/pydoc.py --- a/Lib/pydoc.py Tue Aug 18 22:03:08 2015 -0700 +++ b/Lib/pydoc.py Tue Aug 18 22:25:16 2015 -0700 @@ -209,6 +209,18 @@ results.append((name, kind, cls, value)) return results +def sort_attributes(attrs, object): + 'Sort the attrs list in-place by _fields and then alphabetically by name' + # This allows data descriptors to be ordered according + # to a _fields attribute if present. + fields = getattr(object, '_fields', []) + try: + field_order = {name : i-len(fields) for (i, name) in enumerate(fields)} + except TypeError: + field_order = {} + keyfunc = lambda attr: (field_order.get(attr[0], 0), attr[0]) + attrs.sort(key=keyfunc) + # ----------------------------------------------------- module manipulation def ispackage(path): @@ -867,8 +879,7 @@ object.__module__) tag += ':
\n' - # Sort attrs by name. - attrs.sort(key=lambda t: t[0]) + sort_attributes(attrs, object) # Pump out the attrs, segregated by kind. attrs = spill('Methods %s' % tag, attrs, @@ -1286,8 +1297,8 @@ else: tag = "inherited from %s" % classname(thisclass, object.__module__) - # Sort attrs by name. - attrs.sort() + + sort_attributes(attrs, object) # Pump out the attrs, segregated by kind. attrs = spill("Methods %s:\n" % tag, attrs, diff -r e10a34f8c23f -r f5c40ab9e233 Lib/test/test_pydoc.py --- a/Lib/test/test_pydoc.py Tue Aug 18 22:03:08 2015 -0700 +++ b/Lib/test/test_pydoc.py Tue Aug 18 22:25:16 2015 -0700 @@ -811,6 +811,22 @@ self.assertEqual(self._get_summary_line(t.wrap), "wrap(text) method of textwrap.TextWrapper instance") + def test_field_order_for_named_tuples(self): + Person = namedtuple('Person', ['nickname', 'firstname', 'agegroup']) + s = pydoc.render_doc(Person) + self.assertLess(s.index('nickname'), s.index('firstname')) + self.assertLess(s.index('firstname'), s.index('agegroup')) + + class NonIterableFields: + _fields = None + + class NonHashableFields: + _fields = [[]] + + # Make sure these doesn't fail + pydoc.render_doc(NonIterableFields) + pydoc.render_doc(NonHashableFields) + @requires_docstrings def test_bound_builtin_method(self): s = StringIO() diff -r e10a34f8c23f -r f5c40ab9e233 Misc/NEWS --- a/Misc/NEWS Tue Aug 18 22:03:08 2015 -0700 +++ b/Misc/NEWS Tue Aug 18 22:25:16 2015 -0700 @@ -26,6 +26,10 @@ header in part headers. Patch written by Peter Landry and reviewed by Pierre Quentel. +- Issue #24879: help() and pydoc can now list named tuple fields in the + order they were defined rather than alphabetically. The ordering is + determined by the _fields attribute if present. + - Issue #24774: Fix docstring in http.server.test. Patch from Chiu-Hsiang Hsu. - Issue #21159: Improve message in configparser.InterpolationMissingOptionError.