Issue #10446: Several changes to module documentation generated by pydoc:

1. Online reference manual link is now version-specific and the
   'MODULE DOCS' section renamed to 'MODULE REFERENCE'.

2. 'FILE' section is moved to the end of the file.

3. Special names processed by pydoc such as __version__ or __credits__
   are now excluded from the DATA section.

4. Defined __all__ to prevent pydoc from exposing undocumented details
   about itself.

5. Removed Python 2.3 compatibility code.
This commit is contained in:
Alexander Belopolsky 2010-11-18 01:52:54 +00:00
parent f609654b0e
commit a47bbf5a4b
4 changed files with 39 additions and 42 deletions

View File

@ -63,7 +63,9 @@ documents precisely the version of the module you would get if you started the
Python interpreter and typed ``import spam``. Python interpreter and typed ``import spam``.
Module docs for core modules are assumed to reside in Module docs for core modules are assumed to reside in
http://docs.python.org/library/. This can be overridden by setting the ``http://docs.python.org/X.Y/library/`` where ``X`` and ``Y`` are the
:envvar:`PYTHONDOCS` environment variable to a different URL or to a local major and minor version numbers of the Python interpreter. This can
directory containing the Library Reference Manual pages. be overridden by setting the :envvar:`PYTHONDOCS` environment variable
to a different URL or to a local directory containing the Library
Reference Manual pages.

View File

@ -26,13 +26,13 @@ to a file named "<name>.html".
Module docs for core modules are assumed to be in Module docs for core modules are assumed to be in
http://docs.python.org/library/ http://docs.python.org/X.Y/library/
This can be overridden by setting the PYTHONDOCS environment variable This can be overridden by setting the PYTHONDOCS environment variable
to a different URL or to a local directory containing the Library to a different URL or to a local directory containing the Library
Reference Manual pages. Reference Manual pages.
""" """
__all__ = ['help']
__author__ = "Ka-Ping Yee <ping@lfw.org>" __author__ = "Ka-Ping Yee <ping@lfw.org>"
__date__ = "26 February 2001" __date__ = "26 February 2001"
@ -54,14 +54,7 @@ Richard Chamberlain, for the first implementation of textdoc.
import sys, imp, os, re, inspect, builtins, pkgutil import sys, imp, os, re, inspect, builtins, pkgutil
from reprlib import Repr from reprlib import Repr
from traceback import extract_tb as _extract_tb from traceback import extract_tb as _extract_tb
try: from collections import deque
from collections import deque
except ImportError:
# Python 2.3 compatibility
class deque(list):
def popleft(self):
return self.pop(0)
# --------------------------------------------------------- common routines # --------------------------------------------------------- common routines
def pathdirs(): def pathdirs():
@ -159,7 +152,8 @@ def visiblename(name, all=None):
# Certain special names are redundant. # Certain special names are redundant.
_hidden_names = ('__builtins__', '__doc__', '__file__', '__path__', _hidden_names = ('__builtins__', '__doc__', '__file__', '__path__',
'__module__', '__name__', '__slots__', '__package__', '__module__', '__name__', '__slots__', '__package__',
'__cached__') '__cached__', '__author__', '__credits__', '__date__',
'__version__')
if name in _hidden_names: return 0 if name in _hidden_names: 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
@ -306,6 +300,11 @@ def safeimport(path, forceload=0, cache={}):
# ---------------------------------------------------- formatter base class # ---------------------------------------------------- formatter base class
class Doc: class Doc:
PYTHONDOCS = os.environ.get("PYTHONDOCS",
"http://docs.python.org/%d.%d/library"
% sys.version_info[:2])
def document(self, object, name=None, *args): def document(self, object, name=None, *args):
"""Generate documentation for an object.""" """Generate documentation for an object."""
args = (object, name) + args args = (object, name) + args
@ -340,10 +339,10 @@ class Doc:
except TypeError: except TypeError:
file = '(built-in)' file = '(built-in)'
docloc = os.environ.get("PYTHONDOCS", docloc = os.environ.get("PYTHONDOCS", self.PYTHONDOCS)
"http://docs.python.org/library")
basedir = os.path.join(sys.exec_prefix, "lib", basedir = os.path.join(sys.exec_prefix, "lib",
"python"+sys.version[0:3]) "python%d.%d" % sys.version_info[:2])
if (isinstance(object, type(os)) and if (isinstance(object, type(os)) and
(object.__name__ in ('errno', 'exceptions', 'gc', 'imp', (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
'marshal', 'posix', 'signal', 'sys', 'marshal', 'posix', 'signal', 'sys',
@ -607,7 +606,7 @@ class HTMLDoc(Doc):
head = head + ' (%s)' % ', '.join(info) head = head + ' (%s)' % ', '.join(info)
docloc = self.getdocloc(object) docloc = self.getdocloc(object)
if docloc is not None: if docloc is not None:
docloc = '<br><a href="%(docloc)s">Module Docs</a>' % locals() docloc = '<br><a href="%(docloc)s">Module Reference</a>' % locals()
else: else:
docloc = '' docloc = ''
result = self.heading( result = self.heading(
@ -1016,21 +1015,16 @@ class TextDoc(Doc):
name = object.__name__ # ignore the passed-in name name = object.__name__ # ignore the passed-in name
synop, desc = splitdoc(getdoc(object)) synop, desc = splitdoc(getdoc(object))
result = self.section('NAME', name + (synop and ' - ' + synop)) result = self.section('NAME', name + (synop and ' - ' + synop))
all = getattr(object, '__all__', None)
try:
all = object.__all__
except AttributeError:
all = None
try:
file = inspect.getabsfile(object)
except TypeError:
file = '(built-in)'
result = result + self.section('FILE', file)
docloc = self.getdocloc(object) docloc = self.getdocloc(object)
if docloc is not None: if docloc is not None:
result = result + self.section('MODULE DOCS', docloc) result = result + self.section('MODULE REFERENCE', docloc + """
The following documentation is automatically generated from the Python source
files. It may be incomplete, incorrect or include features that are considered
implementation detail and may vary between Python implementations. When in
doubt, consult the module reference at the location listed above.
""")
if desc: if desc:
result = result + self.section('DESCRIPTION', desc) result = result + self.section('DESCRIPTION', desc)
@ -1109,6 +1103,11 @@ class TextDoc(Doc):
result = result + self.section('AUTHOR', str(object.__author__)) result = result + self.section('AUTHOR', str(object.__author__))
if hasattr(object, '__credits__'): if hasattr(object, '__credits__'):
result = result + self.section('CREDITS', str(object.__credits__)) result = result + self.section('CREDITS', str(object.__credits__))
try:
file = inspect.getabsfile(object)
except TypeError:
file = '(built-in)'
result = result + self.section('FILE', file)
return result return result
def docclass(self, object, name=None, mod=None): def docclass(self, object, name=None, mod=None):

View File

@ -3,7 +3,7 @@
__author__ = "Benjamin Peterson" __author__ = "Benjamin Peterson"
__credits__ = "Nobody" __credits__ = "Nobody"
__version__ = "1.2.3.4" __version__ = "1.2.3.4"
__xyz__ = "X, Y and Z"
class A: class A:
"""Hello and goodbye""" """Hello and goodbye"""

View File

@ -22,9 +22,6 @@ if hasattr(pydoc_mod, "__loader__"):
expected_text_pattern = """ expected_text_pattern = """
NAME NAME
test.pydoc_mod - This is a test module for test_pydoc test.pydoc_mod - This is a test module for test_pydoc
FILE
%s
%s %s
CLASSES CLASSES
builtins.object builtins.object
@ -72,9 +69,7 @@ FUNCTIONS
nodoc_func() nodoc_func()
DATA DATA
__author__ = 'Benjamin Peterson' __xyz__ = 'X, Y and Z'
__credits__ = 'Nobody'
__version__ = '1.2.3.4'
VERSION VERSION
1.2.3.4 1.2.3.4
@ -84,6 +79,9 @@ AUTHOR
CREDITS CREDITS
Nobody Nobody
FILE
%s
""".strip() """.strip()
expected_html_pattern = """ expected_html_pattern = """
@ -167,9 +165,7 @@ war</tt></dd></dl>
<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr> <font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
\x20\x20\x20\x20 \x20\x20\x20\x20
<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td> <tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%%"><strong>__author__</strong> = 'Benjamin Peterson'<br> <td width="100%%"><strong>__xyz__</strong> = 'X, Y and Z'</td></tr></table><p>
<strong>__credits__</strong> = 'Nobody'<br>
<strong>__version__</strong> = '1.2.3.4'</td></tr></table><p>
<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section"> <table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#7799ee"> <tr bgcolor="#7799ee">
<td colspan=3 valign=bottom>&nbsp;<br> <td colspan=3 valign=bottom>&nbsp;<br>
@ -259,7 +255,7 @@ class PyDocDocTest(unittest.TestCase):
def test_text_doc(self): def test_text_doc(self):
result, doc_loc = get_pydoc_text(pydoc_mod) result, doc_loc = get_pydoc_text(pydoc_mod)
expected_text = expected_text_pattern % \ expected_text = expected_text_pattern % \
(inspect.getabsfile(pydoc_mod), doc_loc) (doc_loc, inspect.getabsfile(pydoc_mod))
if result != expected_text: if result != expected_text:
print_diffs(expected_text, result) print_diffs(expected_text, result)
self.fail("outputs are not equal, see diff above") self.fail("outputs are not equal, see diff above")