Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1103d05

Browse files
committed
Issue #11666: Teach pydoc to display full help for named tuples
1 parent 66a4e12 commit 1103d05

3 files changed

Lines changed: 26 additions & 10 deletions

File tree

Lib/pydoc.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ def _split_list(s, predicate):
165165
no.append(x)
166166
return yes, no
167167

168-
def visiblename(name, all=None):
168+
def visiblename(name, all=None, obj=None):
169169
"""Decide whether to show documentation on a variable."""
170170
# Certain special names are redundant.
171171
_hidden_names = ('__builtins__', '__doc__', '__file__', '__path__',
@@ -175,6 +175,9 @@ def visiblename(name, all=None):
175175
if name in _hidden_names: return 0
176176
# Private names are hidden, but special names are displayed.
177177
if name.startswith('__') and name.endswith('__'): return 1
178+
# Namedtuples have public fields and methods with a single leading underscore
179+
if name.startswith('_') and hasattr(obj, '_fields'):
180+
return True
178181
if all is not None:
179182
# only document that which the programmer exported in __all__
180183
return name in all
@@ -642,7 +645,7 @@ def docmodule(self, object, name=None, mod=None, *ignored):
642645
# if __all__ exists, believe it. Otherwise use old heuristic.
643646
if (all is not None or
644647
(inspect.getmodule(value) or object) is object):
645-
if visiblename(key, all):
648+
if visiblename(key, all, object):
646649
classes.append((key, value))
647650
cdict[key] = cdict[value] = '#' + key
648651
for key, value in classes:
@@ -658,13 +661,13 @@ def docmodule(self, object, name=None, mod=None, *ignored):
658661
# if __all__ exists, believe it. Otherwise use old heuristic.
659662
if (all is not None or
660663
inspect.isbuiltin(value) or inspect.getmodule(value) is object):
661-
if visiblename(key, all):
664+
if visiblename(key, all, object):
662665
funcs.append((key, value))
663666
fdict[key] = '#-' + key
664667
if inspect.isfunction(value): fdict[value] = fdict[key]
665668
data = []
666669
for key, value in inspect.getmembers(object, isdata):
667-
if visiblename(key, all):
670+
if visiblename(key, all, object):
668671
data.append((key, value))
669672

670673
doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
@@ -789,7 +792,7 @@ def spilldata(msg, attrs, predicate):
789792

790793
attrs = [(name, kind, cls, value)
791794
for name, kind, cls, value in classify_class_attrs(object)
792-
if visiblename(name)]
795+
if visiblename(name, obj=object)]
793796

794797
mdict = {}
795798
for key, kind, homecls, value in attrs:
@@ -1056,18 +1059,18 @@ def docmodule(self, object, name=None, mod=None):
10561059
# if __all__ exists, believe it. Otherwise use old heuristic.
10571060
if (all is not None
10581061
or (inspect.getmodule(value) or object) is object):
1059-
if visiblename(key, all):
1062+
if visiblename(key, all, object):
10601063
classes.append((key, value))
10611064
funcs = []
10621065
for key, value in inspect.getmembers(object, inspect.isroutine):
10631066
# if __all__ exists, believe it. Otherwise use old heuristic.
10641067
if (all is not None or
10651068
inspect.isbuiltin(value) or inspect.getmodule(value) is object):
1066-
if visiblename(key, all):
1069+
if visiblename(key, all, object):
10671070
funcs.append((key, value))
10681071
data = []
10691072
for key, value in inspect.getmembers(object, isdata):
1070-
if visiblename(key, all):
1073+
if visiblename(key, all, object):
10711074
data.append((key, value))
10721075

10731076
modpkgs = []
@@ -1206,7 +1209,7 @@ def spilldata(msg, attrs, predicate):
12061209

12071210
attrs = [(name, kind, cls, value)
12081211
for name, kind, cls, value in classify_class_attrs(object)
1209-
if visiblename(name)]
1212+
if visiblename(name, obj=object)]
12101213

12111214
while attrs:
12121215
if mro:

Lib/test/test_pydoc.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212
import xml.etree
1313
import textwrap
1414
from io import StringIO
15+
from collections import namedtuple
1516
from contextlib import contextmanager
1617
from test.support import TESTFN, forget, rmtree, EnvironmentVarGuard, \
17-
reap_children, captured_output
18+
reap_children, captured_output, captured_stdout
1819

1920
from test import pydoc_mod
2021

@@ -373,6 +374,15 @@ def test_help_output_redirect(self):
373374
finally:
374375
pydoc.getpager = getpager_old
375376

377+
def test_namedtuple_public_underscore(self):
378+
NT = namedtuple('NT', ['abc', 'def'], rename=True)
379+
with captured_stdout() as help_io:
380+
help(NT)
381+
helptext = help_io.getvalue()
382+
self.assertIn('_1', helptext)
383+
self.assertIn('_replace', helptext)
384+
self.assertIn('_asdict', helptext)
385+
376386

377387
class TestDescriptions(unittest.TestCase):
378388

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ Library
5151

5252
- Issue #11628: cmp_to_key generated class should use __slots__
5353

54+
- Issue #11666: let help() display named tuple attributes and methods
55+
that start with a leading underscore.
56+
5457
- Issue #5537: Fix time2isoz() and time2netscape() functions of
5558
httplib.cookiejar for expiration year greater than 2038 on 32-bit systems.
5659

0 commit comments

Comments
 (0)