]> granicus.if.org Git - python/commitdiff
Issue #11666: Teach pydoc to display full help for named tuples
authorRaymond Hettinger <python@rcn.com>
Fri, 25 Mar 2011 23:00:13 +0000 (16:00 -0700)
committerRaymond Hettinger <python@rcn.com>
Fri, 25 Mar 2011 23:00:13 +0000 (16:00 -0700)
Lib/pydoc.py
Lib/test/test_pydoc.py
Misc/NEWS

index ff9a5f4ec89aa469ffbaa3050b615727a8fa43b7..8b6f7ee2e3ec073a0440402fe7250c395c62de64 100755 (executable)
@@ -156,7 +156,7 @@ def _split_list(s, predicate):
             no.append(x)
     return yes, no
 
-def visiblename(name, all=None):
+def visiblename(name, all=None, obj=None):
     """Decide whether to show documentation on a variable."""
     # Certain special names are redundant.
     _hidden_names = ('__builtins__', '__doc__', '__file__', '__path__',
@@ -164,6 +164,9 @@ def visiblename(name, all=None):
     if name in _hidden_names: return 0
     # Private names are hidden, but special names are displayed.
     if name.startswith('__') and name.endswith('__'): return 1
+    # Namedtuples have public fields and methods with a single leading underscore
+    if name.startswith('_') and hasattr(obj, '_fields'):
+        return 1
     if all is not None:
         # only document that which the programmer exported in __all__
         return name in all
@@ -627,7 +630,7 @@ class HTMLDoc(Doc):
             # if __all__ exists, believe it.  Otherwise use old heuristic.
             if (all is not None or
                 (inspect.getmodule(value) or object) is object):
-                if visiblename(key, all):
+                if visiblename(key, all, object):
                     classes.append((key, value))
                     cdict[key] = cdict[value] = '#' + key
         for key, value in classes:
@@ -643,13 +646,13 @@ class HTMLDoc(Doc):
             # if __all__ exists, believe it.  Otherwise use old heuristic.
             if (all is not None or
                 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
-                if visiblename(key, all):
+                if visiblename(key, all, object):
                     funcs.append((key, value))
                     fdict[key] = '#-' + key
                     if inspect.isfunction(value): fdict[value] = fdict[key]
         data = []
         for key, value in inspect.getmembers(object, isdata):
-            if visiblename(key, all):
+            if visiblename(key, all, object):
                 data.append((key, value))
 
         doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
@@ -773,7 +776,7 @@ class HTMLDoc(Doc):
                     push('\n')
             return attrs
 
-        attrs = filter(lambda data: visiblename(data[0]),
+        attrs = filter(lambda data: visiblename(data[0], obj=object),
                        classify_class_attrs(object))
         mdict = {}
         for key, kind, homecls, value in attrs:
@@ -1042,18 +1045,18 @@ class TextDoc(Doc):
             # if __all__ exists, believe it.  Otherwise use old heuristic.
             if (all is not None
                 or (inspect.getmodule(value) or object) is object):
-                if visiblename(key, all):
+                if visiblename(key, all, object):
                     classes.append((key, value))
         funcs = []
         for key, value in inspect.getmembers(object, inspect.isroutine):
             # if __all__ exists, believe it.  Otherwise use old heuristic.
             if (all is not None or
                 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
-                if visiblename(key, all):
+                if visiblename(key, all, object):
                     funcs.append((key, value))
         data = []
         for key, value in inspect.getmembers(object, isdata):
-            if visiblename(key, all):
+            if visiblename(key, all, object):
                 data.append((key, value))
 
         modpkgs = []
@@ -1186,7 +1189,7 @@ class TextDoc(Doc):
                                        name, mod, maxlen=70, doc=doc) + '\n')
             return attrs
 
-        attrs = filter(lambda data: visiblename(data[0]),
+        attrs = filter(lambda data: visiblename(data[0], obj=object),
                        classify_class_attrs(object))
         while attrs:
             if mro:
index 0685488edb29767f4815cf45450c9a3919dc2a15..2e67290d00ec41bd9b8332dd7abc81ef9e7696b3 100644 (file)
@@ -10,8 +10,9 @@ import unittest
 import xml.etree
 import test.test_support
 from contextlib import contextmanager
+from collections import namedtuple
 from test.test_support import (
-    TESTFN, forget, rmtree, EnvironmentVarGuard, reap_children)
+    TESTFN, forget, rmtree, EnvironmentVarGuard, reap_children, captured_stdout)
 
 from test import pydoc_mod
 
@@ -340,6 +341,15 @@ class TestDescriptions(unittest.TestCase):
         expected = 'C in module %s object' % __name__
         self.assertIn(expected, pydoc.render_doc(c))
 
+    def test_namedtuple_public_underscore(self):
+        NT = namedtuple('NT', ['abc', 'def'], rename=True)
+        with captured_stdout() as help_io:
+            help(NT)
+        helptext = help_io.getvalue()
+        self.assertIn('_1', helptext)
+        self.assertIn('_replace', helptext)
+        self.assertIn('_asdict', helptext)
+
 
 def test_main():
     test.test_support.run_unittest(PyDocDocTest,
index 4344e37b0238c248d29a9ada0cde537af6790b23..444728966da4dfd5d1c86a1203c1f5b64afba0cf 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -43,6 +43,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #11666: let help() display named tuple attributes and methods
+  that start with a leading underscore.
+
 - Issue #11673: Fix multiprocessing Array and RawArray constructors to accept a
   size of type 'long', rather than only accepting 'int'.