mirror of
https://github.com/python/cpython.git
synced 2025-10-09 08:31:26 +00:00
Issue #11666: Teach pydoc to display full help for named tuples
This commit is contained in:
commit
007bdbd7ab
3 changed files with 26 additions and 10 deletions
21
Lib/pydoc.py
21
Lib/pydoc.py
|
@ -165,7 +165,7 @@ def _split_list(s, predicate):
|
||||||
no.append(x)
|
no.append(x)
|
||||||
return yes, no
|
return yes, no
|
||||||
|
|
||||||
def visiblename(name, all=None):
|
def visiblename(name, all=None, obj=None):
|
||||||
"""Decide whether to show documentation on a variable."""
|
"""Decide whether to show documentation on a variable."""
|
||||||
# Certain special names are redundant.
|
# Certain special names are redundant.
|
||||||
if name in {'__builtins__', '__doc__', '__file__', '__path__',
|
if name in {'__builtins__', '__doc__', '__file__', '__path__',
|
||||||
|
@ -175,6 +175,9 @@ def visiblename(name, all=None):
|
||||||
return 0
|
return 0
|
||||||
# Private names are hidden, but special names are displayed.
|
# Private names are hidden, but special names are displayed.
|
||||||
if name.startswith('__') and name.endswith('__'): return 1
|
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 True
|
||||||
if all is not None:
|
if all is not None:
|
||||||
# only document that which the programmer exported in __all__
|
# only document that which the programmer exported in __all__
|
||||||
return name in all
|
return name in all
|
||||||
|
@ -642,7 +645,7 @@ class HTMLDoc(Doc):
|
||||||
# if __all__ exists, believe it. Otherwise use old heuristic.
|
# if __all__ exists, believe it. Otherwise use old heuristic.
|
||||||
if (all is not None or
|
if (all is not None or
|
||||||
(inspect.getmodule(value) or object) is object):
|
(inspect.getmodule(value) or object) is object):
|
||||||
if visiblename(key, all):
|
if visiblename(key, all, object):
|
||||||
classes.append((key, value))
|
classes.append((key, value))
|
||||||
cdict[key] = cdict[value] = '#' + key
|
cdict[key] = cdict[value] = '#' + key
|
||||||
for key, value in classes:
|
for key, value in classes:
|
||||||
|
@ -658,13 +661,13 @@ class HTMLDoc(Doc):
|
||||||
# if __all__ exists, believe it. Otherwise use old heuristic.
|
# if __all__ exists, believe it. Otherwise use old heuristic.
|
||||||
if (all is not None or
|
if (all is not None or
|
||||||
inspect.isbuiltin(value) or inspect.getmodule(value) is object):
|
inspect.isbuiltin(value) or inspect.getmodule(value) is object):
|
||||||
if visiblename(key, all):
|
if visiblename(key, all, object):
|
||||||
funcs.append((key, value))
|
funcs.append((key, value))
|
||||||
fdict[key] = '#-' + key
|
fdict[key] = '#-' + key
|
||||||
if inspect.isfunction(value): fdict[value] = fdict[key]
|
if inspect.isfunction(value): fdict[value] = fdict[key]
|
||||||
data = []
|
data = []
|
||||||
for key, value in inspect.getmembers(object, isdata):
|
for key, value in inspect.getmembers(object, isdata):
|
||||||
if visiblename(key, all):
|
if visiblename(key, all, object):
|
||||||
data.append((key, value))
|
data.append((key, value))
|
||||||
|
|
||||||
doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
|
doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
|
||||||
|
@ -789,7 +792,7 @@ class HTMLDoc(Doc):
|
||||||
|
|
||||||
attrs = [(name, kind, cls, value)
|
attrs = [(name, kind, cls, value)
|
||||||
for name, kind, cls, value in classify_class_attrs(object)
|
for name, kind, cls, value in classify_class_attrs(object)
|
||||||
if visiblename(name)]
|
if visiblename(name, obj=object)]
|
||||||
|
|
||||||
mdict = {}
|
mdict = {}
|
||||||
for key, kind, homecls, value in attrs:
|
for key, kind, homecls, value in attrs:
|
||||||
|
@ -1056,18 +1059,18 @@ doubt, consult the module reference at the location listed above.
|
||||||
# if __all__ exists, believe it. Otherwise use old heuristic.
|
# if __all__ exists, believe it. Otherwise use old heuristic.
|
||||||
if (all is not None
|
if (all is not None
|
||||||
or (inspect.getmodule(value) or object) is object):
|
or (inspect.getmodule(value) or object) is object):
|
||||||
if visiblename(key, all):
|
if visiblename(key, all, object):
|
||||||
classes.append((key, value))
|
classes.append((key, value))
|
||||||
funcs = []
|
funcs = []
|
||||||
for key, value in inspect.getmembers(object, inspect.isroutine):
|
for key, value in inspect.getmembers(object, inspect.isroutine):
|
||||||
# if __all__ exists, believe it. Otherwise use old heuristic.
|
# if __all__ exists, believe it. Otherwise use old heuristic.
|
||||||
if (all is not None or
|
if (all is not None or
|
||||||
inspect.isbuiltin(value) or inspect.getmodule(value) is object):
|
inspect.isbuiltin(value) or inspect.getmodule(value) is object):
|
||||||
if visiblename(key, all):
|
if visiblename(key, all, object):
|
||||||
funcs.append((key, value))
|
funcs.append((key, value))
|
||||||
data = []
|
data = []
|
||||||
for key, value in inspect.getmembers(object, isdata):
|
for key, value in inspect.getmembers(object, isdata):
|
||||||
if visiblename(key, all):
|
if visiblename(key, all, object):
|
||||||
data.append((key, value))
|
data.append((key, value))
|
||||||
|
|
||||||
modpkgs = []
|
modpkgs = []
|
||||||
|
@ -1206,7 +1209,7 @@ doubt, consult the module reference at the location listed above.
|
||||||
|
|
||||||
attrs = [(name, kind, cls, value)
|
attrs = [(name, kind, cls, value)
|
||||||
for name, kind, cls, value in classify_class_attrs(object)
|
for name, kind, cls, value in classify_class_attrs(object)
|
||||||
if visiblename(name)]
|
if visiblename(name, obj=object)]
|
||||||
|
|
||||||
while attrs:
|
while attrs:
|
||||||
if mro:
|
if mro:
|
||||||
|
|
|
@ -12,9 +12,10 @@ import unittest
|
||||||
import xml.etree
|
import xml.etree
|
||||||
import textwrap
|
import textwrap
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
from collections import namedtuple
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from test.support import TESTFN, forget, rmtree, EnvironmentVarGuard, \
|
from test.support import TESTFN, forget, rmtree, EnvironmentVarGuard, \
|
||||||
reap_children, captured_output
|
reap_children, captured_output, captured_stdout
|
||||||
|
|
||||||
from test import pydoc_mod
|
from test import pydoc_mod
|
||||||
|
|
||||||
|
@ -379,6 +380,15 @@ class PydocDocTest(unittest.TestCase):
|
||||||
finally:
|
finally:
|
||||||
pydoc.getpager = getpager_old
|
pydoc.getpager = getpager_old
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
class TestDescriptions(unittest.TestCase):
|
class TestDescriptions(unittest.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,9 @@ Library
|
||||||
|
|
||||||
- Issue #11628: cmp_to_key generated class should use __slots__.
|
- Issue #11628: cmp_to_key generated class should use __slots__.
|
||||||
|
|
||||||
|
- Issue #11666: let help() display named tuple attributes and methods
|
||||||
|
that start with a leading underscore.
|
||||||
|
|
||||||
- Issue #5537: Fix time2isoz() and time2netscape() functions of
|
- Issue #5537: Fix time2isoz() and time2netscape() functions of
|
||||||
httplib.cookiejar for expiration year greater than 2038 on 32-bit systems.
|
httplib.cookiejar for expiration year greater than 2038 on 32-bit systems.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue