]> granicus.if.org Git - python/commitdiff
Issue #24879: Teach pydoc to display named tuple fields in the order they were defined.
authorRaymond Hettinger <python@rcn.com>
Wed, 19 Aug 2015 05:25:16 +0000 (22:25 -0700)
committerRaymond Hettinger <python@rcn.com>
Wed, 19 Aug 2015 05:25:16 +0000 (22:25 -0700)
Lib/pydoc.py
Lib/test/test_pydoc.py
Misc/NEWS

index ee558bfea3b58a1b9489c5252cbb1d042a7f3918..f4f253010f49d35994376dacf03dfba99d6a4600 100755 (executable)
@@ -209,6 +209,18 @@ def classify_class_attrs(object):
         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 @@ class HTMLDoc(Doc):
                                                            object.__module__)
             tag += ':<br>\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 @@ location listed above.
             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,
index ec5c31ba7216e5f2b1c57dd1ab254d7efc0a9288..0533a03fa778406dc80bb44ef836e2260af890fa 100644 (file)
@@ -811,6 +811,22 @@ class TestDescriptions(unittest.TestCase):
         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()
index b2ec4f94793329a67058243eab5f87c23989ffb8..0bb5697c3b2fd3a3f2b7aecb8f43c66f9301712d 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -26,6 +26,10 @@ Library
   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.