blob: 5edc77005a87140c4707f485c9cc35cffb90e545 [file] [log] [blame]
Benjamin Peterson90f5ba52010-03-11 22:53:45 +00001#!/usr/bin/env python3
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002"""Generate Python documentation in HTML or text for interactive use.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00003
R David Murray3d050dd2014-04-19 12:59:30 -04004At the Python interactive prompt, calling help(thing) on a Python object
5documents the object, and calling help() starts up an interactive
6help session.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00007
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00008Or, at the shell command line outside of Python:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00009
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000010Run "pydoc <name>" to show documentation on something. <name> may be
11the name of a function, module, package, or a dotted reference to a
12class or function within a module or module in a package. If the
13argument contains a path segment delimiter (e.g. slash on Unix,
14backslash on Windows) it is treated as the path to a Python source file.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000015
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000016Run "pydoc -k <keyword>" to search for a keyword in the synopsis lines
17of all available modules.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000018
Nick Coghlan7bb30b72010-12-03 09:29:11 +000019Run "pydoc -p <port>" to start an HTTP server on the given port on the
20local machine. Port number 0 can be used to get an arbitrary unused port.
21
22Run "pydoc -b" to start an HTTP server on an arbitrary unused port and
23open a Web browser to interactively browse documentation. The -p option
24can be used with the -b option to explicitly specify the server port.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000025
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000026Run "pydoc -w <name>" to write out the HTML documentation for a module
27to a file named "<name>.html".
Skip Montanaro4997a692003-09-10 16:47:51 +000028
29Module docs for core modules are assumed to be in
30
Martin Panter4f8aaf62016-06-12 04:24:06 +000031 https://docs.python.org/X.Y/library/
Skip Montanaro4997a692003-09-10 16:47:51 +000032
33This can be overridden by setting the PYTHONDOCS environment variable
34to a different URL or to a local directory containing the Library
35Reference Manual pages.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000036"""
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000037__all__ = ['help']
Ka-Ping Yeedd175342001-02-27 14:43:46 +000038__author__ = "Ka-Ping Yee <ping@lfw.org>"
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000039__date__ = "26 February 2001"
Jeremy Hylton3e0055f2005-10-20 19:59:25 +000040
Martin v. Löwis6fe8f192004-11-14 10:21:04 +000041__credits__ = """Guido van Rossum, for an excellent programming language.
Ka-Ping Yee5e2b1732001-02-27 23:35:09 +000042Tommy Burnette, the original creator of manpy.
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000043Paul Prescod, for all his work on onlinehelp.
44Richard Chamberlain, for the first implementation of textdoc.
Raymond Hettingered2dbe32005-01-01 07:51:01 +000045"""
Ka-Ping Yeedd175342001-02-27 14:43:46 +000046
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000047# Known bugs that can't be fixed here:
Brett Cannonf4ba4ec2013-06-15 14:25:04 -040048# - synopsis() cannot be prevented from clobbering existing
49# loaded modules.
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000050# - If the __file__ attribute on a module is a relative path and
51# the current directory is changed with os.chdir(), an incorrect
52# path will be displayed.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000053
Nick Coghlan7bb30b72010-12-03 09:29:11 +000054import builtins
Brett Cannond5e6f2e2013-06-11 17:09:36 -040055import importlib._bootstrap
Eric Snow32439d62015-05-02 19:15:18 -060056import importlib._bootstrap_external
Brett Cannoncb66eb02012-05-11 12:58:42 -040057import importlib.machinery
Brett Cannonf4ba4ec2013-06-15 14:25:04 -040058import importlib.util
Nick Coghlan7bb30b72010-12-03 09:29:11 +000059import inspect
Victor Stinnere6c910e2011-06-30 15:55:43 +020060import io
61import os
Nick Coghlan7bb30b72010-12-03 09:29:11 +000062import pkgutil
63import platform
64import re
Victor Stinnere6c910e2011-06-30 15:55:43 +020065import sys
Nick Coghlan7bb30b72010-12-03 09:29:11 +000066import time
Victor Stinnere6c910e2011-06-30 15:55:43 +020067import tokenize
Zachary Wareeb432142014-07-10 11:18:00 -050068import urllib.parse
Nick Coghlan7bb30b72010-12-03 09:29:11 +000069import warnings
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000070from collections import deque
Nick Coghlan7bb30b72010-12-03 09:29:11 +000071from reprlib import Repr
Victor Stinner7fa767e2014-03-20 09:16:38 +010072from traceback import format_exception_only
Nick Coghlan7bb30b72010-12-03 09:29:11 +000073
74
Ka-Ping Yeedd175342001-02-27 14:43:46 +000075# --------------------------------------------------------- common routines
76
Ka-Ping Yeedd175342001-02-27 14:43:46 +000077def pathdirs():
78 """Convert sys.path into a list of absolute, existing, unique paths."""
79 dirs = []
Ka-Ping Yee1d384632001-03-01 00:24:32 +000080 normdirs = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +000081 for dir in sys.path:
82 dir = os.path.abspath(dir or '.')
Ka-Ping Yee1d384632001-03-01 00:24:32 +000083 normdir = os.path.normcase(dir)
84 if normdir not in normdirs and os.path.isdir(dir):
Ka-Ping Yeedd175342001-02-27 14:43:46 +000085 dirs.append(dir)
Ka-Ping Yee1d384632001-03-01 00:24:32 +000086 normdirs.append(normdir)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000087 return dirs
88
89def getdoc(object):
90 """Get the doc string or comments for an object."""
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000091 result = inspect.getdoc(object) or inspect.getcomments(object)
Neal Norwitz9d72bb42007-04-17 08:48:32 +000092 return result and re.sub('^ *\n', '', result.rstrip()) or ''
Ka-Ping Yeedd175342001-02-27 14:43:46 +000093
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000094def splitdoc(doc):
95 """Split a doc string into a synopsis line (if any) and the rest."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +000096 lines = doc.strip().split('\n')
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000097 if len(lines) == 1:
98 return lines[0], ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +000099 elif len(lines) >= 2 and not lines[1].rstrip():
100 return lines[0], '\n'.join(lines[2:])
101 return '', '\n'.join(lines)
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000102
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000103def classname(object, modname):
104 """Get a class name and qualify it with a module name if necessary."""
105 name = object.__name__
106 if object.__module__ != modname:
107 name = object.__module__ + '.' + name
108 return name
109
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000110def isdata(object):
Georg Brandl94432422005-07-22 21:52:25 +0000111 """Check if an object is of a type that probably means it's data."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000112 return not (inspect.ismodule(object) or inspect.isclass(object) or
113 inspect.isroutine(object) or inspect.isframe(object) or
114 inspect.istraceback(object) or inspect.iscode(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000115
116def replace(text, *pairs):
117 """Do a series of global replacements on a string."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000118 while pairs:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000119 text = pairs[1].join(text.split(pairs[0]))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000120 pairs = pairs[2:]
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000121 return text
122
123def cram(text, maxlen):
124 """Omit part of a string if needed to make it fit in a maximum length."""
125 if len(text) > maxlen:
Raymond Hettingerfca3bb62002-10-21 04:44:11 +0000126 pre = max(0, (maxlen-3)//2)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000127 post = max(0, maxlen-3-pre)
128 return text[:pre] + '...' + text[len(text)-post:]
129 return text
130
Brett Cannon84601f12004-06-19 01:22:48 +0000131_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000132def stripid(text):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000133 """Remove the hexadecimal id from a Python object representation."""
Brett Cannonc6c1f472004-06-19 01:02:51 +0000134 # The behaviour of %p is implementation-dependent in terms of case.
Ezio Melotti412c95a2010-02-16 23:31:04 +0000135 return _re_stripid.sub(r'\1', text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000136
Brett Cannonc6c1f472004-06-19 01:02:51 +0000137def _is_some_method(obj):
R David Murrayac0cea52013-03-19 02:47:44 -0400138 return (inspect.isfunction(obj) or
139 inspect.ismethod(obj) or
140 inspect.isbuiltin(obj) or
141 inspect.ismethoddescriptor(obj))
Tim Peters536d2262001-09-20 05:13:38 +0000142
Larry Hastings24a882b2014-02-20 23:34:46 -0800143def _is_bound_method(fn):
144 """
145 Returns True if fn is a bound method, regardless of whether
146 fn was implemented in Python or in C.
147 """
148 if inspect.ismethod(fn):
149 return True
150 if inspect.isbuiltin(fn):
151 self = getattr(fn, '__self__', None)
152 return not (inspect.ismodule(self) or (self is None))
153 return False
154
155
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000156def allmethods(cl):
157 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000158 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000159 methods[key] = 1
160 for base in cl.__bases__:
161 methods.update(allmethods(base)) # all your base are belong to us
162 for key in methods.keys():
163 methods[key] = getattr(cl, key)
164 return methods
165
Tim Petersfa26f7c2001-09-24 08:05:11 +0000166def _split_list(s, predicate):
167 """Split sequence s via predicate, and return pair ([true], [false]).
168
169 The return value is a 2-tuple of lists,
170 ([x for x in s if predicate(x)],
171 [x for x in s if not predicate(x)])
172 """
173
Tim Peters28355492001-09-23 21:29:55 +0000174 yes = []
175 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000176 for x in s:
177 if predicate(x):
178 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000179 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000180 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000181 return yes, no
182
Raymond Hettinger1103d052011-03-25 14:15:24 -0700183def visiblename(name, all=None, obj=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000184 """Decide whether to show documentation on a variable."""
Brett Cannond340b432012-08-06 17:19:22 -0400185 # Certain special names are redundant or internal.
Eric Snowb523f842013-11-22 09:05:39 -0700186 # XXX Remove __initializing__?
Brett Cannond340b432012-08-06 17:19:22 -0400187 if name in {'__author__', '__builtins__', '__cached__', '__credits__',
Eric Snowb523f842013-11-22 09:05:39 -0700188 '__date__', '__doc__', '__file__', '__spec__',
Brett Cannond340b432012-08-06 17:19:22 -0400189 '__loader__', '__module__', '__name__', '__package__',
190 '__path__', '__qualname__', '__slots__', '__version__'}:
Raymond Hettinger68272942011-03-18 02:22:15 -0700191 return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000192 # Private names are hidden, but special names are displayed.
193 if name.startswith('__') and name.endswith('__'): return 1
Raymond Hettinger1103d052011-03-25 14:15:24 -0700194 # Namedtuples have public fields and methods with a single leading underscore
195 if name.startswith('_') and hasattr(obj, '_fields'):
196 return True
Skip Montanaroa5616d22004-06-11 04:46:12 +0000197 if all is not None:
198 # only document that which the programmer exported in __all__
199 return name in all
200 else:
201 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000202
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000203def classify_class_attrs(object):
204 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000205 results = []
206 for (name, kind, cls, value) in inspect.classify_class_attrs(object):
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000207 if inspect.isdatadescriptor(value):
208 kind = 'data descriptor'
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000209 results.append((name, kind, cls, value))
210 return results
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000211
Raymond Hettinger95801bb2015-08-18 22:25:16 -0700212def sort_attributes(attrs, object):
213 'Sort the attrs list in-place by _fields and then alphabetically by name'
214 # This allows data descriptors to be ordered according
215 # to a _fields attribute if present.
216 fields = getattr(object, '_fields', [])
217 try:
218 field_order = {name : i-len(fields) for (i, name) in enumerate(fields)}
219 except TypeError:
220 field_order = {}
221 keyfunc = lambda attr: (field_order.get(attr[0], 0), attr[0])
222 attrs.sort(key=keyfunc)
223
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000224# ----------------------------------------------------- module manipulation
225
226def ispackage(path):
227 """Guess whether a path refers to a package directory."""
228 if os.path.isdir(path):
Brett Cannonf299abd2015-04-13 14:21:02 -0400229 for ext in ('.py', '.pyc'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000230 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000231 return True
232 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000233
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000234def source_synopsis(file):
235 line = file.readline()
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000236 while line[:1] == '#' or not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000237 line = file.readline()
238 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000239 line = line.strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000240 if line[:4] == 'r"""': line = line[1:]
241 if line[:3] == '"""':
242 line = line[3:]
243 if line[-1:] == '\\': line = line[:-1]
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000244 while not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000245 line = file.readline()
246 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000247 result = line.split('"""')[0].strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000248 else: result = None
249 return result
250
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000251def synopsis(filename, cache={}):
252 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000253 mtime = os.stat(filename).st_mtime
Charles-François Natali27c4e882011-07-27 19:40:02 +0200254 lastupdate, result = cache.get(filename, (None, None))
255 if lastupdate is None or lastupdate < mtime:
Eric Snowaed5b222014-01-04 20:38:11 -0700256 # Look for binary suffixes first, falling back to source.
257 if filename.endswith(tuple(importlib.machinery.BYTECODE_SUFFIXES)):
258 loader_cls = importlib.machinery.SourcelessFileLoader
259 elif filename.endswith(tuple(importlib.machinery.EXTENSION_SUFFIXES)):
260 loader_cls = importlib.machinery.ExtensionFileLoader
261 else:
262 loader_cls = None
263 # Now handle the choice.
264 if loader_cls is None:
265 # Must be a source file.
266 try:
267 file = tokenize.open(filename)
268 except OSError:
269 # module can't be opened, so skip it
270 return None
271 # text modules can be directly examined
272 with file:
273 result = source_synopsis(file)
274 else:
275 # Must be a binary module, which has to be imported.
276 loader = loader_cls('__temp__', filename)
Eric Snow3a62d142014-01-06 20:42:59 -0700277 # XXX We probably don't need to pass in the loader here.
278 spec = importlib.util.spec_from_file_location('__temp__', filename,
279 loader=loader)
Brett Cannoncb66eb02012-05-11 12:58:42 -0400280 try:
Brett Cannon2a17bde2014-05-30 14:55:29 -0400281 module = importlib._bootstrap._load(spec)
Brett Cannoncb66eb02012-05-11 12:58:42 -0400282 except:
283 return None
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000284 del sys.modules['__temp__']
Benjamin Peterson54237f92015-02-16 19:45:01 -0500285 result = module.__doc__.splitlines()[0] if module.__doc__ else None
Eric Snowaed5b222014-01-04 20:38:11 -0700286 # Cache the result.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000287 cache[filename] = (mtime, result)
288 return result
289
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000290class ErrorDuringImport(Exception):
291 """Errors that occurred while trying to import something to document it."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000292 def __init__(self, filename, exc_info):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000293 self.filename = filename
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000294 self.exc, self.value, self.tb = exc_info
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000295
296 def __str__(self):
Guido van Rossuma01a8b62007-05-27 09:20:14 +0000297 exc = self.exc.__name__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000298 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000299
300def importfile(path):
301 """Import a Python source file or compiled file given its path."""
Brett Cannonf4ba4ec2013-06-15 14:25:04 -0400302 magic = importlib.util.MAGIC_NUMBER
Victor Stinnere975af62011-07-04 02:08:50 +0200303 with open(path, 'rb') as file:
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400304 is_bytecode = magic == file.read(len(magic))
305 filename = os.path.basename(path)
306 name, ext = os.path.splitext(filename)
307 if is_bytecode:
Eric Snow32439d62015-05-02 19:15:18 -0600308 loader = importlib._bootstrap_external.SourcelessFileLoader(name, path)
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400309 else:
Eric Snow32439d62015-05-02 19:15:18 -0600310 loader = importlib._bootstrap_external.SourceFileLoader(name, path)
Eric Snow3a62d142014-01-06 20:42:59 -0700311 # XXX We probably don't need to pass in the loader here.
312 spec = importlib.util.spec_from_file_location(name, path, loader=loader)
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400313 try:
Brett Cannon2a17bde2014-05-30 14:55:29 -0400314 return importlib._bootstrap._load(spec)
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400315 except:
316 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000317
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000318def safeimport(path, forceload=0, cache={}):
319 """Import a module; handle errors; return None if the module isn't found.
320
321 If the module *is* found but an exception occurs, it's wrapped in an
322 ErrorDuringImport exception and reraised. Unlike __import__, if a
323 package path is specified, the module at the end of the path is returned,
324 not the package at the beginning. If the optional 'forceload' argument
325 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000326 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000327 # If forceload is 1 and the module has been previously loaded from
328 # disk, we always have to reload the module. Checking the file's
329 # mtime isn't good enough (e.g. the module could contain a class
330 # that inherits from another module that has changed).
331 if forceload and path in sys.modules:
332 if path not in sys.builtin_module_names:
Guido van Rossume7ba4952007-06-06 23:52:48 +0000333 # Remove the module from sys.modules and re-import to try
334 # and avoid problems with partially loaded modules.
335 # Also remove any submodules because they won't appear
336 # in the newly loaded module's namespace if they're already
337 # in sys.modules.
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000338 subs = [m for m in sys.modules if m.startswith(path + '.')]
339 for key in [path] + subs:
340 # Prevent garbage collection.
341 cache[key] = sys.modules[key]
342 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000343 module = __import__(path)
344 except:
345 # Did the error occur before or after the module was found?
346 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000347 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000348 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000349 raise ErrorDuringImport(sys.modules[path].__file__, info)
350 elif exc is SyntaxError:
351 # A SyntaxError occurred before we could execute the module.
352 raise ErrorDuringImport(value.filename, info)
Eric Snow46f97b82016-09-07 16:56:15 -0700353 elif issubclass(exc, ImportError) and value.name == path:
Brett Cannonfd074152012-04-14 14:10:13 -0400354 # No such module in the path.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000355 return None
356 else:
357 # Some other error occurred during the importing process.
358 raise ErrorDuringImport(path, sys.exc_info())
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000359 for part in path.split('.')[1:]:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000360 try: module = getattr(module, part)
361 except AttributeError: return None
362 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000363
364# ---------------------------------------------------- formatter base class
365
366class Doc:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000367
368 PYTHONDOCS = os.environ.get("PYTHONDOCS",
R David Murrayead9bfc2016-06-03 19:28:35 -0400369 "https://docs.python.org/%d.%d/library"
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000370 % sys.version_info[:2])
371
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000372 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000373 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000374 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000375 # 'try' clause is to attempt to handle the possibility that inspect
376 # identifies something in a way that pydoc itself has issues handling;
377 # think 'super' and how it is a descriptor (which raises the exception
378 # by lacking a __name__ attribute) and an instance.
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000379 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
380 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000381 try:
382 if inspect.ismodule(object): return self.docmodule(*args)
383 if inspect.isclass(object): return self.docclass(*args)
384 if inspect.isroutine(object): return self.docroutine(*args)
385 except AttributeError:
386 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000387 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000388 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000389
390 def fail(self, object, name=None, *args):
391 """Raise an exception for unimplemented types."""
392 message = "don't know how to document object%s of type %s" % (
393 name and ' ' + repr(name), type(object).__name__)
Collin Winterce36ad82007-08-30 01:19:48 +0000394 raise TypeError(message)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000395
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000396 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000397
R David Murrayead9bfc2016-06-03 19:28:35 -0400398 def getdocloc(self, object,
399 basedir=os.path.join(sys.base_exec_prefix, "lib",
400 "python%d.%d" % sys.version_info[:2])):
Skip Montanaro4997a692003-09-10 16:47:51 +0000401 """Return the location of module docs or None"""
402
403 try:
404 file = inspect.getabsfile(object)
405 except TypeError:
406 file = '(built-in)'
407
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000408 docloc = os.environ.get("PYTHONDOCS", self.PYTHONDOCS)
409
Martin Panter4f8aaf62016-06-12 04:24:06 +0000410 basedir = os.path.normcase(basedir)
Skip Montanaro4997a692003-09-10 16:47:51 +0000411 if (isinstance(object, type(os)) and
412 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
413 'marshal', 'posix', 'signal', 'sys',
Georg Brandl2067bfd2008-05-25 13:05:15 +0000414 '_thread', 'zipimport') or
Skip Montanaro4997a692003-09-10 16:47:51 +0000415 (file.startswith(basedir) and
Brian Curtin49c284c2010-03-31 03:19:28 +0000416 not file.startswith(os.path.join(basedir, 'site-packages')))) and
Brian Curtinedef05b2010-04-01 04:05:25 +0000417 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
Martin Panter4f8aaf62016-06-12 04:24:06 +0000418 if docloc.startswith(("http://", "https://")):
R David Murrayead9bfc2016-06-03 19:28:35 -0400419 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__.lower())
Skip Montanaro4997a692003-09-10 16:47:51 +0000420 else:
R David Murrayead9bfc2016-06-03 19:28:35 -0400421 docloc = os.path.join(docloc, object.__name__.lower() + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000422 else:
423 docloc = None
424 return docloc
425
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000426# -------------------------------------------- HTML documentation generator
427
428class HTMLRepr(Repr):
429 """Class for safely making an HTML representation of a Python object."""
430 def __init__(self):
431 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000432 self.maxlist = self.maxtuple = 20
433 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000434 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000435
436 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000437 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000438
439 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000440 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000441
442 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000443 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000444 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000445 if hasattr(self, methodname):
446 return getattr(self, methodname)(x, level)
447 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000448
449 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000450 test = cram(x, self.maxstring)
451 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000452 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000453 # Backslashes are only literal in the string and are never
454 # needed to make any special characters, so show a raw string.
455 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000456 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000457 r'<font color="#c040c0">\1</font>',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000458 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000459
Skip Montanarodf708782002-03-07 22:58:02 +0000460 repr_str = repr_string
461
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000462 def repr_instance(self, x, level):
463 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000464 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000465 except:
466 return self.escape('<%s instance>' % x.__class__.__name__)
467
468 repr_unicode = repr_string
469
470class HTMLDoc(Doc):
471 """Formatter class for HTML documentation."""
472
473 # ------------------------------------------- HTML formatting utilities
474
475 _repr_instance = HTMLRepr()
476 repr = _repr_instance.repr
477 escape = _repr_instance.escape
478
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000479 def page(self, title, contents):
480 """Format an HTML page."""
Georg Brandl388faac2009-04-10 08:31:48 +0000481 return '''\
Georg Brandle6066942009-04-10 08:28:28 +0000482<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000483<html><head><title>Python: %s</title>
Georg Brandl388faac2009-04-10 08:31:48 +0000484<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000485</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000486%s
487</body></html>''' % (title, contents)
488
489 def heading(self, title, fgcol, bgcol, extras=''):
490 """Format a page heading."""
491 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000492<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000493<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000494<td valign=bottom>&nbsp;<br>
495<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000496><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000497><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000498 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
499
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000500 def section(self, title, fgcol, bgcol, contents, width=6,
501 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000502 """Format a section with a heading."""
503 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000504 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000505 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000506<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000507<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000508<td colspan=3 valign=bottom>&nbsp;<br>
509<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000510 ''' % (bgcol, fgcol, title)
511 if prelude:
512 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000513<tr bgcolor="%s"><td rowspan=2>%s</td>
514<td colspan=2>%s</td></tr>
515<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
516 else:
517 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000518<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000519
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000520 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000521
522 def bigsection(self, title, *args):
523 """Format a section with a big heading."""
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000524 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000525 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000526
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000527 def preformat(self, text):
528 """Format literal preformatted text."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000529 text = self.escape(text.expandtabs())
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000530 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
531 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000532
533 def multicolumn(self, list, format, cols=4):
534 """Format a list of items into a multi-column list."""
535 result = ''
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000536 rows = (len(list)+cols-1)//cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000537 for col in range(cols):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000538 result = result + '<td width="%d%%" valign=top>' % (100//cols)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000539 for i in range(rows*col, rows*col+rows):
540 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000541 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000542 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000543 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000544
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000545 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000546
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000547 def namelink(self, name, *dicts):
548 """Make a link for an identifier, given name-to-URL mappings."""
549 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000550 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000551 return '<a href="%s">%s</a>' % (dict[name], name)
552 return name
553
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000554 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000555 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000556 name, module = object.__name__, sys.modules.get(object.__module__)
557 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000558 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000559 module.__name__, name, classname(object, modname))
560 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000561
562 def modulelink(self, object):
563 """Make a link for a module."""
564 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
565
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000566 def modpkglink(self, modpkginfo):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000567 """Make a link for a module or package to display in an index."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000568 name, path, ispackage, shadowed = modpkginfo
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000569 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000570 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000571 if path:
572 url = '%s.%s.html' % (path, name)
573 else:
574 url = '%s.html' % name
575 if ispackage:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000576 text = '<strong>%s</strong>&nbsp;(package)' % name
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000577 else:
578 text = name
579 return '<a href="%s">%s</a>' % (url, text)
580
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000581 def filelink(self, url, path):
582 """Make a link to source file."""
583 return '<a href="file:%s">%s</a>' % (url, path)
584
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000585 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
586 """Mark up some plain text, given a context of symbols to look for.
587 Each context dictionary maps object names to anchor names."""
588 escape = escape or self.escape
589 results = []
590 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000591 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
592 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000593 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000594 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000595 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000596 match = pattern.search(text, here)
597 if not match: break
598 start, end = match.span()
599 results.append(escape(text[here:start]))
600
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000601 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000602 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000603 url = escape(all).replace('"', '&quot;')
604 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000605 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000606 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
607 results.append('<a href="%s">%s</a>' % (url, escape(all)))
608 elif pep:
Christian Heimes2202f872008-02-06 14:31:34 +0000609 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000610 results.append('<a href="%s">%s</a>' % (url, escape(all)))
Benjamin Petersoned1160b2014-06-07 16:44:00 -0700611 elif selfdot:
612 # Create a link for methods like 'self.method(...)'
613 # and use <strong> for attributes like 'self.attr'
614 if text[end:end+1] == '(':
615 results.append('self.' + self.namelink(name, methods))
616 else:
617 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000618 elif text[end:end+1] == '(':
619 results.append(self.namelink(name, methods, funcs, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000620 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000621 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000622 here = end
623 results.append(escape(text[here:]))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000624 return ''.join(results)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000625
626 # ---------------------------------------------- type-specific routines
627
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000628 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000629 """Produce HTML for a class tree as given by inspect.getclasstree()."""
630 result = ''
631 for entry in tree:
632 if type(entry) is type(()):
633 c, bases = entry
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000634 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000635 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000636 if bases and bases != (parent,):
637 parents = []
638 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000639 parents.append(self.classlink(base, modname))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000640 result = result + '(' + ', '.join(parents) + ')'
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000641 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000642 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000643 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000644 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000645 return '<dl>\n%s</dl>\n' % result
646
Tim Peters8dd7ade2001-10-18 19:56:17 +0000647 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000648 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000649 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000650 try:
651 all = object.__all__
652 except AttributeError:
653 all = None
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000654 parts = name.split('.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000655 links = []
656 for i in range(len(parts)-1):
657 links.append(
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000658 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000659 ('.'.join(parts[:i+1]), parts[i]))
660 linkedname = '.'.join(links + parts[-1:])
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000661 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000662 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000663 path = inspect.getabsfile(object)
Zachary Wareeb432142014-07-10 11:18:00 -0500664 url = urllib.parse.quote(path)
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000665 filelink = self.filelink(url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000666 except TypeError:
667 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000668 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000669 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000670 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000671 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000672 version = version[11:-1].strip()
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000673 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000674 if hasattr(object, '__date__'):
675 info.append(self.escape(str(object.__date__)))
676 if info:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000677 head = head + ' (%s)' % ', '.join(info)
Skip Montanaro4997a692003-09-10 16:47:51 +0000678 docloc = self.getdocloc(object)
679 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000680 docloc = '<br><a href="%(docloc)s">Module Reference</a>' % locals()
Skip Montanaro4997a692003-09-10 16:47:51 +0000681 else:
682 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000683 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000684 head, '#ffffff', '#7799ee',
685 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000686
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000687 modules = inspect.getmembers(object, inspect.ismodule)
688
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000689 classes, cdict = [], {}
690 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000691 # if __all__ exists, believe it. Otherwise use old heuristic.
692 if (all is not None or
693 (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700694 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000695 classes.append((key, value))
696 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000697 for key, value in classes:
698 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000699 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000700 module = sys.modules.get(modname)
701 if modname != name and module and hasattr(module, key):
702 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000703 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000704 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000705 funcs, fdict = [], {}
706 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000707 # if __all__ exists, believe it. Otherwise use old heuristic.
708 if (all is not None or
709 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700710 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000711 funcs.append((key, value))
712 fdict[key] = '#-' + key
713 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000714 data = []
715 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700716 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000717 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000718
719 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
720 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000721 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000722
723 if hasattr(object, '__path__'):
724 modpkgs = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000725 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
726 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000727 modpkgs.sort()
728 contents = self.multicolumn(modpkgs, self.modpkglink)
729 result = result + self.bigsection(
730 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000731 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000732 contents = self.multicolumn(
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000733 modules, lambda t: self.modulelink(t[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000734 result = result + self.bigsection(
Christian Heimes7131fd92008-02-19 14:21:46 +0000735 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000736
737 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000738 classlist = [value for (key, value) in classes]
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000739 contents = [
740 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000741 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000742 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000743 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000744 'Classes', '#ffffff', '#ee77aa', ' '.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000745 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000746 contents = []
747 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000748 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000749 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000750 'Functions', '#ffffff', '#eeaa77', ' '.join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000751 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000752 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000753 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000754 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000755 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000756 'Data', '#ffffff', '#55aa55', '<br>\n'.join(contents))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000757 if hasattr(object, '__author__'):
758 contents = self.markup(str(object.__author__), self.preformat)
759 result = result + self.bigsection(
760 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000761 if hasattr(object, '__credits__'):
762 contents = self.markup(str(object.__credits__), self.preformat)
763 result = result + self.bigsection(
764 'Credits', '#ffffff', '#7799ee', contents)
765
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000766 return result
767
Tim Peters8dd7ade2001-10-18 19:56:17 +0000768 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
769 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000770 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000771 realname = object.__name__
772 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000773 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000774
Tim Petersb47879b2001-09-24 04:47:19 +0000775 contents = []
776 push = contents.append
777
Tim Petersfa26f7c2001-09-24 08:05:11 +0000778 # Cute little class to pump out a horizontal rule between sections.
779 class HorizontalRule:
780 def __init__(self):
781 self.needone = 0
782 def maybe(self):
783 if self.needone:
784 push('<hr>\n')
785 self.needone = 1
786 hr = HorizontalRule()
787
Tim Petersc86f6ca2001-09-26 21:31:51 +0000788 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000789 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000790 if len(mro) > 2:
791 hr.maybe()
792 push('<dl><dt>Method resolution order:</dt>\n')
793 for base in mro:
794 push('<dd>%s</dd>\n' % self.classlink(base,
795 object.__module__))
796 push('</dl>\n')
797
Tim Petersb47879b2001-09-24 04:47:19 +0000798 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000799 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000800 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000801 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000802 push(msg)
803 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100804 try:
805 value = getattr(object, name)
806 except Exception:
807 # Some descriptors may meet a failure in their __get__.
808 # (bug #1785)
809 push(self._docdescriptor(name, value, mod))
810 else:
811 push(self.document(value, name, mod,
812 funcs, classes, mdict, object))
Tim Petersb47879b2001-09-24 04:47:19 +0000813 push('\n')
814 return attrs
815
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000816 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000817 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000818 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000819 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000820 push(msg)
821 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000822 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000823 return attrs
824
Tim Petersfa26f7c2001-09-24 08:05:11 +0000825 def spilldata(msg, attrs, predicate):
826 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000827 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000828 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000829 push(msg)
830 for name, kind, homecls, value in ok:
831 base = self.docother(getattr(object, name), name, mod)
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200832 if callable(value) or inspect.isdatadescriptor(value):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000833 doc = getattr(value, "__doc__", None)
834 else:
835 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000836 if doc is None:
837 push('<dl><dt>%s</dl>\n' % base)
838 else:
839 doc = self.markup(getdoc(value), self.preformat,
840 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000841 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000842 push('<dl><dt>%s%s</dl>\n' % (base, doc))
843 push('\n')
844 return attrs
845
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000846 attrs = [(name, kind, cls, value)
847 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -0700848 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000849
Tim Petersb47879b2001-09-24 04:47:19 +0000850 mdict = {}
851 for key, kind, homecls, value in attrs:
852 mdict[key] = anchor = '#' + name + '-' + key
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100853 try:
854 value = getattr(object, name)
855 except Exception:
856 # Some descriptors may meet a failure in their __get__.
857 # (bug #1785)
858 pass
Tim Petersb47879b2001-09-24 04:47:19 +0000859 try:
860 # The value may not be hashable (e.g., a data attr with
861 # a dict or list value).
862 mdict[value] = anchor
863 except TypeError:
864 pass
865
Tim Petersfa26f7c2001-09-24 08:05:11 +0000866 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000867 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000868 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000869 else:
870 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000871 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
872
Georg Brandl1a3284e2007-12-02 09:40:06 +0000873 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000874 attrs = inherited
875 continue
876 elif thisclass is object:
877 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000878 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000879 tag = 'inherited from %s' % self.classlink(thisclass,
880 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000881 tag += ':<br>\n'
882
Raymond Hettinger95801bb2015-08-18 22:25:16 -0700883 sort_attributes(attrs, object)
Tim Petersb47879b2001-09-24 04:47:19 +0000884
885 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000886 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000887 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000888 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000889 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000890 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000891 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000892 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
893 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000894 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000895 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000896 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000897 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000898
899 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000900
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000901 if name == realname:
902 title = '<a name="%s">class <strong>%s</strong></a>' % (
903 name, realname)
904 else:
905 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
906 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000907 if bases:
908 parents = []
909 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000910 parents.append(self.classlink(base, object.__module__))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000911 title = title + '(%s)' % ', '.join(parents)
Serhiy Storchakaccb5f3c2017-01-23 12:37:00 +0200912
913 decl = ''
914 try:
915 signature = inspect.signature(object)
916 except (ValueError, TypeError):
917 signature = None
918 if signature:
919 argspec = str(signature)
Serhiy Storchaka213f2292017-01-23 14:02:35 +0200920 if argspec and argspec != '()':
Serhiy Storchakaccb5f3c2017-01-23 12:37:00 +0200921 decl = name + self.escape(argspec) + '\n\n'
922
923 doc = getdoc(object)
924 if decl:
925 doc = decl + (doc or '')
926 doc = self.markup(doc, self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000927 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000928
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000929 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000930
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000931 def formatvalue(self, object):
932 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000933 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000934
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000935 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000936 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000937 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000938 realname = object.__name__
939 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000940 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000941 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000942 skipdocs = 0
Larry Hastings24a882b2014-02-20 23:34:46 -0800943 if _is_bound_method(object):
Christian Heimesff737952007-11-27 10:40:20 +0000944 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000945 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000946 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000947 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000948 else:
Christian Heimesff737952007-11-27 10:40:20 +0000949 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000950 note = ' method of %s instance' % self.classlink(
Christian Heimesff737952007-11-27 10:40:20 +0000951 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000952 else:
953 note = ' unbound %s method' % self.classlink(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000954
955 if name == realname:
956 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
957 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000958 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000959 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000960 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000961 cl.__name__ + '-' + realname, realname)
962 skipdocs = 1
963 else:
964 reallink = realname
965 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
966 anchor, name, reallink)
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800967 argspec = None
Larry Hastings24a882b2014-02-20 23:34:46 -0800968 if inspect.isroutine(object):
Larry Hastings5c661892014-01-24 06:17:25 -0800969 try:
970 signature = inspect.signature(object)
971 except (ValueError, TypeError):
972 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800973 if signature:
974 argspec = str(signature)
975 if realname == '<lambda>':
976 title = '<strong>%s</strong> <em>lambda</em> ' % name
977 # XXX lambda's won't usually have func_annotations['return']
978 # since the syntax doesn't support but it is possible.
979 # So removing parentheses isn't truly safe.
980 argspec = argspec[1:-1] # remove parentheses
981 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +0000982 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000983
Serhiy Storchaka66dd4aa2014-11-17 23:48:02 +0200984 decl = title + self.escape(argspec) + (note and self.grey(
Tim Peters2306d242001-09-25 03:18:32 +0000985 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000986
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000987 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000988 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000989 else:
990 doc = self.markup(
991 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000992 doc = doc and '<dd><tt>%s</tt></dd>' % doc
993 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000994
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000995 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000996 results = []
997 push = results.append
998
999 if name:
1000 push('<dl><dt><strong>%s</strong></dt>\n' % name)
1001 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001002 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001003 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001004 push('</dl>\n')
1005
1006 return ''.join(results)
1007
1008 def docproperty(self, object, name=None, mod=None, cl=None):
1009 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001010 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001011
Tim Peters8dd7ade2001-10-18 19:56:17 +00001012 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001013 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001014 lhs = name and '<strong>%s</strong> = ' % name or ''
1015 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001016
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001017 def docdata(self, object, name=None, mod=None, cl=None):
1018 """Produce html documentation for a data descriptor."""
1019 return self._docdescriptor(name, object, mod)
1020
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001021 def index(self, dir, shadowed=None):
1022 """Generate an HTML index for a directory of modules."""
1023 modpkgs = []
1024 if shadowed is None: shadowed = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001025 for importer, name, ispkg in pkgutil.iter_modules([dir]):
Victor Stinner4d652242011-04-12 23:41:50 +02001026 if any((0xD800 <= ord(ch) <= 0xDFFF) for ch in name):
1027 # ignore a module if its name contains a surrogate character
1028 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001029 modpkgs.append((name, '', ispkg, name in shadowed))
1030 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001031
1032 modpkgs.sort()
1033 contents = self.multicolumn(modpkgs, self.modpkglink)
1034 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
1035
1036# -------------------------------------------- text documentation generator
1037
1038class TextRepr(Repr):
1039 """Class for safely making a text representation of a Python object."""
1040 def __init__(self):
1041 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001042 self.maxlist = self.maxtuple = 20
1043 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001044 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001045
1046 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001047 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001048 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001049 if hasattr(self, methodname):
1050 return getattr(self, methodname)(x, level)
1051 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001052
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001053 def repr_string(self, x, level):
1054 test = cram(x, self.maxstring)
1055 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001056 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001057 # Backslashes are only literal in the string and are never
1058 # needed to make any special characters, so show a raw string.
1059 return 'r' + testrepr[0] + test + testrepr[0]
1060 return testrepr
1061
Skip Montanarodf708782002-03-07 22:58:02 +00001062 repr_str = repr_string
1063
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001064 def repr_instance(self, x, level):
1065 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001066 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001067 except:
1068 return '<%s instance>' % x.__class__.__name__
1069
1070class TextDoc(Doc):
1071 """Formatter class for text documentation."""
1072
1073 # ------------------------------------------- text formatting utilities
1074
1075 _repr_instance = TextRepr()
1076 repr = _repr_instance.repr
1077
1078 def bold(self, text):
1079 """Format a string in bold by overstriking."""
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001080 return ''.join(ch + '\b' + ch for ch in text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001081
1082 def indent(self, text, prefix=' '):
1083 """Indent text by prepending a given prefix to each line."""
1084 if not text: return ''
Collin Winter72e110c2007-07-17 00:27:30 +00001085 lines = [prefix + line for line in text.split('\n')]
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001086 if lines: lines[-1] = lines[-1].rstrip()
1087 return '\n'.join(lines)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001088
1089 def section(self, title, contents):
1090 """Format a section with a given heading."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001091 clean_contents = self.indent(contents).rstrip()
1092 return self.bold(title) + '\n' + clean_contents + '\n\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001093
1094 # ---------------------------------------------- type-specific routines
1095
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001096 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001097 """Render in text a class tree as returned by inspect.getclasstree()."""
1098 result = ''
1099 for entry in tree:
1100 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001101 c, bases = entry
1102 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001103 if bases and bases != (parent,):
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001104 parents = (classname(c, modname) for c in bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001105 result = result + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001106 result = result + '\n'
1107 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001108 result = result + self.formattree(
1109 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001110 return result
1111
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001112 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001113 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001114 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001115 synop, desc = splitdoc(getdoc(object))
1116 result = self.section('NAME', name + (synop and ' - ' + synop))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001117 all = getattr(object, '__all__', None)
Skip Montanaro4997a692003-09-10 16:47:51 +00001118 docloc = self.getdocloc(object)
1119 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001120 result = result + self.section('MODULE REFERENCE', docloc + """
1121
Éric Araujo647ef8c2011-09-11 00:43:20 +02001122The following documentation is automatically generated from the Python
1123source files. It may be incomplete, incorrect or include features that
1124are considered implementation detail and may vary between Python
1125implementations. When in doubt, consult the module reference at the
1126location listed above.
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001127""")
Skip Montanaro4997a692003-09-10 16:47:51 +00001128
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001129 if desc:
1130 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001131
1132 classes = []
1133 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001134 # if __all__ exists, believe it. Otherwise use old heuristic.
1135 if (all is not None
1136 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001137 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001138 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001139 funcs = []
1140 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001141 # if __all__ exists, believe it. Otherwise use old heuristic.
1142 if (all is not None or
1143 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001144 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001145 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001146 data = []
1147 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001148 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001149 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001150
Christian Heimes1af737c2008-01-23 08:24:23 +00001151 modpkgs = []
1152 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001153 if hasattr(object, '__path__'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001154 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Christian Heimes1af737c2008-01-23 08:24:23 +00001155 modpkgs_names.add(modname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001156 if ispkg:
1157 modpkgs.append(modname + ' (package)')
1158 else:
1159 modpkgs.append(modname)
1160
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001161 modpkgs.sort()
1162 result = result + self.section(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001163 'PACKAGE CONTENTS', '\n'.join(modpkgs))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001164
Christian Heimes1af737c2008-01-23 08:24:23 +00001165 # Detect submodules as sometimes created by C extensions
1166 submodules = []
1167 for key, value in inspect.getmembers(object, inspect.ismodule):
1168 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1169 submodules.append(key)
1170 if submodules:
1171 submodules.sort()
1172 result = result + self.section(
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001173 'SUBMODULES', '\n'.join(submodules))
Christian Heimes1af737c2008-01-23 08:24:23 +00001174
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001175 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001176 classlist = [value for key, value in classes]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001177 contents = [self.formattree(
1178 inspect.getclasstree(classlist, 1), name)]
1179 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001180 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001181 result = result + self.section('CLASSES', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001182
1183 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001184 contents = []
1185 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001186 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001187 result = result + self.section('FUNCTIONS', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001188
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001189 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001190 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001191 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001192 contents.append(self.docother(value, key, name, maxlen=70))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001193 result = result + self.section('DATA', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001194
1195 if hasattr(object, '__version__'):
1196 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001197 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001198 version = version[11:-1].strip()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001199 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001200 if hasattr(object, '__date__'):
1201 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001202 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001203 result = result + self.section('AUTHOR', str(object.__author__))
1204 if hasattr(object, '__credits__'):
1205 result = result + self.section('CREDITS', str(object.__credits__))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001206 try:
1207 file = inspect.getabsfile(object)
1208 except TypeError:
1209 file = '(built-in)'
1210 result = result + self.section('FILE', file)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001211 return result
1212
Georg Brandl9bd45f992010-12-03 09:58:38 +00001213 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001214 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001215 realname = object.__name__
1216 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001217 bases = object.__bases__
1218
Tim Petersc86f6ca2001-09-26 21:31:51 +00001219 def makename(c, m=object.__module__):
1220 return classname(c, m)
1221
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001222 if name == realname:
1223 title = 'class ' + self.bold(realname)
1224 else:
1225 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001226 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001227 parents = map(makename, bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001228 title = title + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001229
Serhiy Storchakaccb5f3c2017-01-23 12:37:00 +02001230 contents = []
Tim Peters28355492001-09-23 21:29:55 +00001231 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001232
Serhiy Storchakaccb5f3c2017-01-23 12:37:00 +02001233 try:
1234 signature = inspect.signature(object)
1235 except (ValueError, TypeError):
1236 signature = None
1237 if signature:
1238 argspec = str(signature)
Serhiy Storchaka213f2292017-01-23 14:02:35 +02001239 if argspec and argspec != '()':
Serhiy Storchakaccb5f3c2017-01-23 12:37:00 +02001240 push(name + argspec + '\n')
1241
1242 doc = getdoc(object)
1243 if doc:
1244 push(doc + '\n')
1245
Tim Petersc86f6ca2001-09-26 21:31:51 +00001246 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001247 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001248 if len(mro) > 2:
1249 push("Method resolution order:")
1250 for base in mro:
1251 push(' ' + makename(base))
1252 push('')
1253
Tim Petersf4aad8e2001-09-24 22:40:47 +00001254 # Cute little class to pump out a horizontal rule between sections.
1255 class HorizontalRule:
1256 def __init__(self):
1257 self.needone = 0
1258 def maybe(self):
1259 if self.needone:
1260 push('-' * 70)
1261 self.needone = 1
1262 hr = HorizontalRule()
1263
Tim Peters28355492001-09-23 21:29:55 +00001264 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001265 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001266 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001267 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001268 push(msg)
1269 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001270 try:
1271 value = getattr(object, name)
1272 except Exception:
1273 # Some descriptors may meet a failure in their __get__.
1274 # (bug #1785)
1275 push(self._docdescriptor(name, value, mod))
1276 else:
1277 push(self.document(value,
1278 name, mod, object))
Tim Peters28355492001-09-23 21:29:55 +00001279 return attrs
1280
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001281 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001282 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001283 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001284 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001285 push(msg)
1286 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001287 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001288 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001289
Tim Petersfa26f7c2001-09-24 08:05:11 +00001290 def spilldata(msg, attrs, predicate):
1291 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001292 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001293 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001294 push(msg)
1295 for name, kind, homecls, value in ok:
Florent Xicluna5d1155c2011-10-28 14:45:05 +02001296 if callable(value) or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001297 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001298 else:
1299 doc = None
Serhiy Storchaka056eb022014-02-19 23:05:12 +02001300 try:
1301 obj = getattr(object, name)
1302 except AttributeError:
1303 obj = homecls.__dict__[name]
1304 push(self.docother(obj, name, mod, maxlen=70, doc=doc) +
1305 '\n')
Tim Peters28355492001-09-23 21:29:55 +00001306 return attrs
1307
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001308 attrs = [(name, kind, cls, value)
1309 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -07001310 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001311
Tim Petersfa26f7c2001-09-24 08:05:11 +00001312 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001313 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001314 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001315 else:
1316 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001317 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1318
Georg Brandl1a3284e2007-12-02 09:40:06 +00001319 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001320 attrs = inherited
1321 continue
1322 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001323 tag = "defined here"
1324 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001325 tag = "inherited from %s" % classname(thisclass,
1326 object.__module__)
Raymond Hettinger95801bb2015-08-18 22:25:16 -07001327
1328 sort_attributes(attrs, object)
Tim Peters28355492001-09-23 21:29:55 +00001329
1330 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001331 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001332 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001333 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001334 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001335 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001336 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001337 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1338 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001339 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1340 lambda t: t[1] == 'data')
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001341
Tim Peters28355492001-09-23 21:29:55 +00001342 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001343 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001344
1345 contents = '\n'.join(contents)
1346 if not contents:
1347 return title + '\n'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001348 return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001349
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001350 def formatvalue(self, object):
1351 """Format an argument default value as text."""
1352 return '=' + self.repr(object)
1353
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001354 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001355 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001356 realname = object.__name__
1357 name = name or realname
1358 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001359 skipdocs = 0
Larry Hastings24a882b2014-02-20 23:34:46 -08001360 if _is_bound_method(object):
Christian Heimesff737952007-11-27 10:40:20 +00001361 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001362 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001363 if imclass is not cl:
1364 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001365 else:
Christian Heimesff737952007-11-27 10:40:20 +00001366 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001367 note = ' method of %s instance' % classname(
Christian Heimesff737952007-11-27 10:40:20 +00001368 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001369 else:
1370 note = ' unbound %s method' % classname(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001371
1372 if name == realname:
1373 title = self.bold(realname)
1374 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001375 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001376 cl.__dict__[realname] is object):
1377 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001378 title = self.bold(name) + ' = ' + realname
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001379 argspec = None
Larry Hastings5c661892014-01-24 06:17:25 -08001380
1381 if inspect.isroutine(object):
1382 try:
1383 signature = inspect.signature(object)
1384 except (ValueError, TypeError):
1385 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001386 if signature:
1387 argspec = str(signature)
1388 if realname == '<lambda>':
1389 title = self.bold(name) + ' lambda '
1390 # XXX lambda's won't usually have func_annotations['return']
1391 # since the syntax doesn't support but it is possible.
1392 # So removing parentheses isn't truly safe.
1393 argspec = argspec[1:-1] # remove parentheses
1394 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +00001395 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001396 decl = title + argspec + note
1397
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001398 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001399 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001400 else:
1401 doc = getdoc(object) or ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001402 return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001403
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001404 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001405 results = []
1406 push = results.append
1407
1408 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001409 push(self.bold(name))
1410 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001411 doc = getdoc(value) or ''
1412 if doc:
1413 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001414 push('\n')
1415 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001416
1417 def docproperty(self, object, name=None, mod=None, cl=None):
1418 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001419 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001420
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001421 def docdata(self, object, name=None, mod=None, cl=None):
1422 """Produce text documentation for a data descriptor."""
1423 return self._docdescriptor(name, object, mod)
1424
Georg Brandl8b813db2005-10-01 16:32:31 +00001425 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001426 """Produce text documentation for a data object."""
1427 repr = self.repr(object)
1428 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001429 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001430 chop = maxlen - len(line)
1431 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001432 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001433 if doc is not None:
1434 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001435 return line
1436
Georg Brandld80d5f42010-12-03 07:47:22 +00001437class _PlainTextDoc(TextDoc):
1438 """Subclass of TextDoc which overrides string styling"""
1439 def bold(self, text):
1440 return text
1441
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001442# --------------------------------------------------------- user interfaces
1443
1444def pager(text):
1445 """The first time this is called, determine what kind of pager to use."""
1446 global pager
1447 pager = getpager()
1448 pager(text)
1449
1450def getpager():
1451 """Decide what method to use for paging through text."""
Benjamin Peterson159824e2014-06-07 20:14:26 -07001452 if not hasattr(sys.stdin, "isatty"):
1453 return plainpager
Guido van Rossuma01a8b62007-05-27 09:20:14 +00001454 if not hasattr(sys.stdout, "isatty"):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001455 return plainpager
1456 if not sys.stdin.isatty() or not sys.stdout.isatty():
1457 return plainpager
doko@ubuntu.com96575452016-06-14 08:39:31 +02001458 use_pager = os.environ.get('MANPAGER') or os.environ.get('PAGER')
1459 if use_pager:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001460 if sys.platform == 'win32': # pipes completely broken in Windows
doko@ubuntu.comc8fd1922016-06-14 09:03:52 +02001461 return lambda text: tempfilepager(plain(text), use_pager)
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001462 elif os.environ.get('TERM') in ('dumb', 'emacs'):
doko@ubuntu.comc8fd1922016-06-14 09:03:52 +02001463 return lambda text: pipepager(plain(text), use_pager)
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001464 else:
doko@ubuntu.comc8fd1922016-06-14 09:03:52 +02001465 return lambda text: pipepager(text, use_pager)
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001466 if os.environ.get('TERM') in ('dumb', 'emacs'):
1467 return plainpager
Jesus Cea4791a242012-10-05 03:15:39 +02001468 if sys.platform == 'win32':
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001469 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001470 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001471 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001472
1473 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001474 (fd, filename) = tempfile.mkstemp()
1475 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001476 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001477 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001478 return lambda text: pipepager(text, 'more')
1479 else:
1480 return ttypager
1481 finally:
1482 os.unlink(filename)
1483
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001484def plain(text):
1485 """Remove boldface formatting from text."""
1486 return re.sub('.\b', '', text)
1487
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001488def pipepager(text, cmd):
1489 """Page through text by feeding it to another program."""
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001490 import subprocess
1491 proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001492 try:
R David Murray1058cda2015-03-29 15:15:40 -04001493 with io.TextIOWrapper(proc.stdin, errors='backslashreplace') as pipe:
R David Murraye7f5e142015-03-30 10:14:47 -04001494 try:
1495 pipe.write(text)
1496 except KeyboardInterrupt:
1497 # We've hereby abandoned whatever text hasn't been written,
1498 # but the pager is still in control of the terminal.
1499 pass
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001500 except OSError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001501 pass # Ignore broken pipes caused by quitting the pager program.
R David Murray1058cda2015-03-29 15:15:40 -04001502 while True:
1503 try:
1504 proc.wait()
1505 break
1506 except KeyboardInterrupt:
1507 # Ignore ctl-c like the pager itself does. Otherwise the pager is
1508 # left running and the terminal is in raw mode and unusable.
1509 pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001510
1511def tempfilepager(text, cmd):
1512 """Page through text by invoking a program on a temporary file."""
1513 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001514 filename = tempfile.mktemp()
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001515 with open(filename, 'w', errors='backslashreplace') as file:
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +01001516 file.write(text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001517 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001518 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001519 finally:
1520 os.unlink(filename)
1521
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001522def _escape_stdout(text):
1523 # Escape non-encodable characters to avoid encoding errors later
1524 encoding = getattr(sys.stdout, 'encoding', None) or 'utf-8'
1525 return text.encode(encoding, 'backslashreplace').decode(encoding)
1526
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001527def ttypager(text):
1528 """Page through text on a text terminal."""
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001529 lines = plain(_escape_stdout(text)).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001530 try:
1531 import tty
1532 fd = sys.stdin.fileno()
1533 old = tty.tcgetattr(fd)
1534 tty.setcbreak(fd)
1535 getchar = lambda: sys.stdin.read(1)
Serhiy Storchakaab5e9b92014-11-28 00:09:29 +02001536 except (ImportError, AttributeError, io.UnsupportedOperation):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001537 tty = None
1538 getchar = lambda: sys.stdin.readline()[:-1][:1]
1539
1540 try:
Serhiy Storchakaab5e9b92014-11-28 00:09:29 +02001541 try:
1542 h = int(os.environ.get('LINES', 0))
1543 except ValueError:
1544 h = 0
1545 if h <= 1:
1546 h = 25
1547 r = inc = h - 1
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001548 sys.stdout.write('\n'.join(lines[:inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001549 while lines[r:]:
1550 sys.stdout.write('-- more --')
1551 sys.stdout.flush()
1552 c = getchar()
1553
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001554 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001555 sys.stdout.write('\r \r')
1556 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001557 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001558 sys.stdout.write('\r \r' + lines[r] + '\n')
1559 r = r + 1
1560 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001561 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001562 r = r - inc - inc
1563 if r < 0: r = 0
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001564 sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001565 r = r + inc
1566
1567 finally:
1568 if tty:
1569 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1570
1571def plainpager(text):
1572 """Simply print unformatted text. This is the ultimate fallback."""
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001573 sys.stdout.write(plain(_escape_stdout(text)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001574
1575def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001576 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001577 if inspect.ismodule(thing):
1578 if thing.__name__ in sys.builtin_module_names:
1579 return 'built-in module ' + thing.__name__
1580 if hasattr(thing, '__path__'):
1581 return 'package ' + thing.__name__
1582 else:
1583 return 'module ' + thing.__name__
1584 if inspect.isbuiltin(thing):
1585 return 'built-in function ' + thing.__name__
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001586 if inspect.isgetsetdescriptor(thing):
1587 return 'getset descriptor %s.%s.%s' % (
1588 thing.__objclass__.__module__, thing.__objclass__.__name__,
1589 thing.__name__)
1590 if inspect.ismemberdescriptor(thing):
1591 return 'member descriptor %s.%s.%s' % (
1592 thing.__objclass__.__module__, thing.__objclass__.__name__,
1593 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001594 if inspect.isclass(thing):
1595 return 'class ' + thing.__name__
1596 if inspect.isfunction(thing):
1597 return 'function ' + thing.__name__
1598 if inspect.ismethod(thing):
1599 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001600 return type(thing).__name__
1601
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001602def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001603 """Locate an object by name or dotted path, importing as necessary."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001604 parts = [part for part in path.split('.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001605 module, n = None, 0
1606 while n < len(parts):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001607 nextmodule = safeimport('.'.join(parts[:n+1]), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001608 if nextmodule: module, n = nextmodule, n + 1
1609 else: break
1610 if module:
1611 object = module
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001612 else:
Éric Araujoe64e51b2011-07-29 17:03:55 +02001613 object = builtins
1614 for part in parts[n:]:
1615 try:
1616 object = getattr(object, part)
1617 except AttributeError:
1618 return None
1619 return object
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001620
1621# --------------------------------------- interactive interpreter interface
1622
1623text = TextDoc()
Georg Brandld80d5f42010-12-03 07:47:22 +00001624plaintext = _PlainTextDoc()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001625html = HTMLDoc()
1626
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001627def resolve(thing, forceload=0):
1628 """Given an object or a path to an object, get the object and its name."""
1629 if isinstance(thing, str):
1630 object = locate(thing, forceload)
Serhiy Storchakab6076fb2015-04-21 21:09:48 +03001631 if object is None:
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001632 raise ImportError('''\
1633No Python documentation found for %r.
1634Use help() to get the interactive help utility.
1635Use help(str) for help on the str class.''' % thing)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001636 return object, thing
1637 else:
R David Murrayc43125a2012-04-23 13:23:57 -04001638 name = getattr(thing, '__name__', None)
1639 return thing, name if isinstance(name, str) else None
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001640
Georg Brandld80d5f42010-12-03 07:47:22 +00001641def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
1642 renderer=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001643 """Render text documentation, given an object or a path to an object."""
Georg Brandld80d5f42010-12-03 07:47:22 +00001644 if renderer is None:
1645 renderer = text
Guido van Rossumd8faa362007-04-27 19:54:29 +00001646 object, name = resolve(thing, forceload)
1647 desc = describe(object)
1648 module = inspect.getmodule(object)
1649 if name and '.' in name:
1650 desc += ' in ' + name[:name.rfind('.')]
1651 elif module and module is not object:
1652 desc += ' in module ' + module.__name__
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001653
1654 if not (inspect.ismodule(object) or
Guido van Rossumd8faa362007-04-27 19:54:29 +00001655 inspect.isclass(object) or
1656 inspect.isroutine(object) or
1657 inspect.isgetsetdescriptor(object) or
1658 inspect.ismemberdescriptor(object) or
1659 isinstance(object, property)):
1660 # If the passed object is a piece of data or an instance,
1661 # document its available methods instead of its value.
1662 object = type(object)
1663 desc += ' object'
Georg Brandld80d5f42010-12-03 07:47:22 +00001664 return title % desc + '\n\n' + renderer.document(object, name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001665
Georg Brandld80d5f42010-12-03 07:47:22 +00001666def doc(thing, title='Python Library Documentation: %s', forceload=0,
1667 output=None):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001668 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001669 try:
Georg Brandld80d5f42010-12-03 07:47:22 +00001670 if output is None:
1671 pager(render_doc(thing, title, forceload))
1672 else:
1673 output.write(render_doc(thing, title, forceload, plaintext))
Guido van Rossumb940e112007-01-10 16:19:56 +00001674 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001675 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001676
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001677def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001678 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001679 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001680 object, name = resolve(thing, forceload)
1681 page = html.page(describe(object), html.document(object, name))
Serhiy Storchaka46ba6c82015-04-04 11:01:02 +03001682 with open(name + '.html', 'w', encoding='utf-8') as file:
1683 file.write(page)
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001684 print('wrote', name + '.html')
Guido van Rossumb940e112007-01-10 16:19:56 +00001685 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001686 print(value)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001687
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001688def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001689 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001690 if done is None: done = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001691 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1692 writedoc(modname)
1693 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001694
1695class Helper:
Georg Brandl6b38daa2008-06-01 21:05:17 +00001696
1697 # These dictionaries map a topic name to either an alias, or a tuple
1698 # (label, seealso-items). The "label" is the label of the corresponding
1699 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl5617db82009-04-27 16:28:57 +00001700 # in pydoc_data/topics.py.
Georg Brandl6b38daa2008-06-01 21:05:17 +00001701 #
1702 # CAUTION: if you change one of these dictionaries, be sure to adapt the
Georg Brandl61bd1dc2014-09-30 22:56:38 +02001703 # list of needed labels in Doc/tools/pyspecific.py and
Georg Brandl5617db82009-04-27 16:28:57 +00001704 # regenerate the pydoc_data/topics.py file by running
Georg Brandl6b38daa2008-06-01 21:05:17 +00001705 # make pydoc-topics
1706 # in Doc/ and copying the output file into the Lib/ directory.
1707
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001708 keywords = {
Ezio Melottib185a042011-04-28 07:42:55 +03001709 'False': '',
1710 'None': '',
1711 'True': '',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001712 'and': 'BOOLEAN',
Guido van Rossumd8faa362007-04-27 19:54:29 +00001713 'as': 'with',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001714 'assert': ('assert', ''),
1715 'break': ('break', 'while for'),
1716 'class': ('class', 'CLASSES SPECIALMETHODS'),
1717 'continue': ('continue', 'while for'),
1718 'def': ('function', ''),
1719 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001720 'elif': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001721 'else': ('else', 'while for'),
Georg Brandl0d855392008-08-30 19:53:05 +00001722 'except': 'try',
1723 'finally': 'try',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001724 'for': ('for', 'break continue while'),
Georg Brandl0d855392008-08-30 19:53:05 +00001725 'from': 'import',
Georg Brandl74abf6f2010-11-20 19:54:36 +00001726 'global': ('global', 'nonlocal NAMESPACES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001727 'if': ('if', 'TRUTHVALUE'),
1728 'import': ('import', 'MODULES'),
Georg Brandl395ed242009-09-04 08:07:32 +00001729 'in': ('in', 'SEQUENCEMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001730 'is': 'COMPARISON',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001731 'lambda': ('lambda', 'FUNCTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001732 'nonlocal': ('nonlocal', 'global NAMESPACES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001733 'not': 'BOOLEAN',
1734 'or': 'BOOLEAN',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001735 'pass': ('pass', ''),
1736 'raise': ('raise', 'EXCEPTIONS'),
1737 'return': ('return', 'FUNCTIONS'),
1738 'try': ('try', 'EXCEPTIONS'),
1739 'while': ('while', 'break continue if TRUTHVALUE'),
1740 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1741 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001742 }
Georg Brandldb7b6b92009-01-01 15:53:14 +00001743 # Either add symbols to this dictionary or to the symbols dictionary
1744 # directly: Whichever is easier. They are merged later.
1745 _symbols_inverse = {
1746 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'),
1747 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1748 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1749 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1750 'UNARY' : ('-', '~'),
1751 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1752 '^=', '<<=', '>>=', '**=', '//='),
1753 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1754 'COMPLEX' : ('j', 'J')
1755 }
1756 symbols = {
1757 '%': 'OPERATORS FORMATTING',
1758 '**': 'POWER',
1759 ',': 'TUPLES LISTS FUNCTIONS',
1760 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1761 '...': 'ELLIPSIS',
1762 ':': 'SLICINGS DICTIONARYLITERALS',
1763 '@': 'def class',
1764 '\\': 'STRINGS',
1765 '_': 'PRIVATENAMES',
1766 '__': 'PRIVATENAMES SPECIALMETHODS',
1767 '`': 'BACKQUOTES',
1768 '(': 'TUPLES FUNCTIONS CALLS',
1769 ')': 'TUPLES FUNCTIONS CALLS',
1770 '[': 'LISTS SUBSCRIPTS SLICINGS',
1771 ']': 'LISTS SUBSCRIPTS SLICINGS'
1772 }
1773 for topic, symbols_ in _symbols_inverse.items():
1774 for symbol in symbols_:
1775 topics = symbols.get(symbol, topic)
1776 if topic not in topics:
1777 topics = topics + ' ' + topic
1778 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001779
1780 topics = {
Georg Brandl6b38daa2008-06-01 21:05:17 +00001781 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1782 'FUNCTIONS CLASSES MODULES FILES inspect'),
1783 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS '
1784 'FORMATTING TYPES'),
1785 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1786 'FORMATTING': ('formatstrings', 'OPERATORS'),
1787 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1788 'FORMATTING TYPES'),
1789 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1790 'INTEGER': ('integers', 'int range'),
1791 'FLOAT': ('floating', 'float math'),
1792 'COMPLEX': ('imaginary', 'complex cmath'),
1793 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING range LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001794 'MAPPINGS': 'DICTIONARIES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001795 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1796 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1797 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1798 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001799 'FRAMEOBJECTS': 'TYPES',
1800 'TRACEBACKS': 'TYPES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001801 'NONE': ('bltin-null-object', ''),
1802 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001803 'SPECIALATTRIBUTES': ('specialattrs', ''),
1804 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1805 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001806 'PACKAGES': 'import',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001807 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1808 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1809 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1810 'LISTS DICTIONARIES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001811 'OPERATORS': 'EXPRESSIONS',
1812 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001813 'OBJECTS': ('objects', 'TYPES'),
1814 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
Georg Brandl395ed242009-09-04 08:07:32 +00001815 'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS '
1816 'NUMBERMETHODS CLASSES'),
Mark Dickinsona56c4672009-01-27 18:17:45 +00001817 'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001818 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1819 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001820 'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS '
Georg Brandl6b38daa2008-06-01 21:05:17 +00001821 'SPECIALMETHODS'),
1822 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1823 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1824 'SPECIALMETHODS'),
1825 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001826 'NAMESPACES': ('naming', 'global nonlocal ASSIGNMENT DELETION DYNAMICFEATURES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001827 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001828 'SCOPING': 'NAMESPACES',
1829 'FRAMES': 'NAMESPACES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001830 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1831 'CONVERSIONS': ('conversions', ''),
1832 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1833 'SPECIALIDENTIFIERS': ('id-classes', ''),
1834 'PRIVATENAMES': ('atom-identifiers', ''),
1835 'LITERALS': ('atom-literals', 'STRINGS NUMBERS TUPLELITERALS '
1836 'LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001837 'TUPLES': 'SEQUENCES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001838 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1839 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1840 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1841 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1842 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1843 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001844 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'),
1845 'SLICINGS': ('slicings', 'SEQUENCEMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001846 'CALLS': ('calls', 'EXPRESSIONS'),
1847 'POWER': ('power', 'EXPRESSIONS'),
1848 'UNARY': ('unary', 'EXPRESSIONS'),
1849 'BINARY': ('binary', 'EXPRESSIONS'),
1850 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1851 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1852 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1853 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001854 'ASSERTION': 'assert',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001855 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1856 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001857 'DELETION': 'del',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001858 'RETURNING': 'return',
1859 'IMPORTING': 'import',
1860 'CONDITIONAL': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001861 'LOOPING': ('compound', 'for while break continue'),
1862 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1863 'DEBUGGING': ('debugger', 'pdb'),
1864 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001865 }
1866
Georg Brandl78aa3962010-07-31 21:51:48 +00001867 def __init__(self, input=None, output=None):
1868 self._input = input
1869 self._output = output
1870
Serhiy Storchakabdf6b912017-03-19 08:40:32 +02001871 @property
1872 def input(self):
1873 return self._input or sys.stdin
1874
1875 @property
1876 def output(self):
1877 return self._output or sys.stdout
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001878
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001879 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001880 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001881 self()
1882 return ''
Serhiy Storchaka465e60e2014-07-25 23:36:00 +03001883 return '<%s.%s instance>' % (self.__class__.__module__,
1884 self.__class__.__qualname__)
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001885
Alexander Belopolsky2e733c92010-07-04 17:00:20 +00001886 _GoInteractive = object()
1887 def __call__(self, request=_GoInteractive):
1888 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001889 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001890 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001891 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001892 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001893 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001894You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001895If you want to ask for help on a particular object directly from the
1896interpreter, you can type "help(object)". Executing "help('string')"
1897has the same effect as typing a particular string at the help> prompt.
1898''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001899
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001900 def interact(self):
1901 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001902 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001903 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001904 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001905 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001906 except (KeyboardInterrupt, EOFError):
1907 break
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001908 request = replace(request, '"', '', "'", '').strip()
1909 if request.lower() in ('q', 'quit'): break
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001910 if request == 'help':
1911 self.intro()
1912 else:
1913 self.help(request)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001914
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001915 def getline(self, prompt):
Guido van Rossum7c086c02008-01-02 03:52:38 +00001916 """Read one line, using input() when appropriate."""
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001917 if self.input is sys.stdin:
Guido van Rossum7c086c02008-01-02 03:52:38 +00001918 return input(prompt)
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001919 else:
1920 self.output.write(prompt)
1921 self.output.flush()
1922 return self.input.readline()
1923
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001924 def help(self, request):
1925 if type(request) is type(''):
R. David Murray1f1b9d32009-05-27 20:56:59 +00001926 request = request.strip()
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001927 if request == 'keywords': self.listkeywords()
Georg Brandldb7b6b92009-01-01 15:53:14 +00001928 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001929 elif request == 'topics': self.listtopics()
1930 elif request == 'modules': self.listmodules()
1931 elif request[:8] == 'modules ':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001932 self.listmodules(request.split()[1])
Georg Brandldb7b6b92009-01-01 15:53:14 +00001933 elif request in self.symbols: self.showsymbol(request)
Ezio Melottib185a042011-04-28 07:42:55 +03001934 elif request in ['True', 'False', 'None']:
1935 # special case these keywords since they are objects too
1936 doc(eval(request), 'Help on %s:')
Raymond Hettinger54f02222002-06-01 14:18:47 +00001937 elif request in self.keywords: self.showtopic(request)
1938 elif request in self.topics: self.showtopic(request)
Georg Brandld80d5f42010-12-03 07:47:22 +00001939 elif request: doc(request, 'Help on %s:', output=self._output)
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001940 else: doc(str, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001941 elif isinstance(request, Helper): self()
Georg Brandld80d5f42010-12-03 07:47:22 +00001942 else: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001943 self.output.write('\n')
1944
1945 def intro(self):
1946 self.output.write('''
Serhiy Storchaka885bdc42016-02-11 13:10:36 +02001947Welcome to Python {0}'s help utility!
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001948
1949If this is your first time using Python, you should definitely check out
Serhiy Storchaka885bdc42016-02-11 13:10:36 +02001950the tutorial on the Internet at http://docs.python.org/{0}/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001951
1952Enter the name of any module, keyword, or topic to get help on writing
1953Python programs and using Python modules. To quit this help utility and
1954return to the interpreter, just type "quit".
1955
Terry Jan Reedy34200572013-02-11 02:23:13 -05001956To get a list of available modules, keywords, symbols, or topics, type
1957"modules", "keywords", "symbols", or "topics". Each module also comes
1958with a one-line summary of what it does; to list the modules whose name
1959or summary contain a given string such as "spam", type "modules spam".
Serhiy Storchaka885bdc42016-02-11 13:10:36 +02001960'''.format('%d.%d' % sys.version_info[:2]))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001961
1962 def list(self, items, columns=4, width=80):
Guido van Rossum486364b2007-06-30 05:01:58 +00001963 items = list(sorted(items))
1964 colw = width // columns
1965 rows = (len(items) + columns - 1) // columns
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001966 for row in range(rows):
1967 for col in range(columns):
1968 i = col * rows + row
1969 if i < len(items):
1970 self.output.write(items[i])
1971 if col < columns - 1:
Guido van Rossum486364b2007-06-30 05:01:58 +00001972 self.output.write(' ' + ' ' * (colw - 1 - len(items[i])))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001973 self.output.write('\n')
1974
1975 def listkeywords(self):
1976 self.output.write('''
1977Here is a list of the Python keywords. Enter any keyword to get more help.
1978
1979''')
1980 self.list(self.keywords.keys())
1981
Georg Brandldb7b6b92009-01-01 15:53:14 +00001982 def listsymbols(self):
1983 self.output.write('''
1984Here is a list of the punctuation symbols which Python assigns special meaning
1985to. Enter any symbol to get more help.
1986
1987''')
1988 self.list(self.symbols.keys())
1989
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001990 def listtopics(self):
1991 self.output.write('''
1992Here is a list of available topics. Enter any topic name to get more help.
1993
1994''')
1995 self.list(self.topics.keys())
1996
Georg Brandldb7b6b92009-01-01 15:53:14 +00001997 def showtopic(self, topic, more_xrefs=''):
Georg Brandl6b38daa2008-06-01 21:05:17 +00001998 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001999 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04002000 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002001 self.output.write('''
Georg Brandl6b38daa2008-06-01 21:05:17 +00002002Sorry, topic and keyword documentation is not available because the
Georg Brandl5617db82009-04-27 16:28:57 +00002003module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002004''')
2005 return
2006 target = self.topics.get(topic, self.keywords.get(topic))
2007 if not target:
2008 self.output.write('no documentation found for %s\n' % repr(topic))
2009 return
2010 if type(target) is type(''):
Georg Brandldb7b6b92009-01-01 15:53:14 +00002011 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002012
Georg Brandl6b38daa2008-06-01 21:05:17 +00002013 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002014 try:
Georg Brandl5617db82009-04-27 16:28:57 +00002015 doc = pydoc_data.topics.topics[label]
Georg Brandl6b38daa2008-06-01 21:05:17 +00002016 except KeyError:
2017 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002018 return
Georg Brandl6b38daa2008-06-01 21:05:17 +00002019 pager(doc.strip() + '\n')
Georg Brandldb7b6b92009-01-01 15:53:14 +00002020 if more_xrefs:
2021 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00002022 if xrefs:
Brett Cannon1448ecf2013-10-04 11:38:59 -04002023 import textwrap
2024 text = 'Related help topics: ' + ', '.join(xrefs.split()) + '\n'
2025 wrapped_text = textwrap.wrap(text, 72)
2026 self.output.write('\n%s\n' % ''.join(wrapped_text))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002027
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002028 def _gettopic(self, topic, more_xrefs=''):
2029 """Return unbuffered tuple of (topic, xrefs).
2030
Georg Brandld2f38572011-01-30 08:37:19 +00002031 If an error occurs here, the exception is caught and displayed by
2032 the url handler.
2033
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002034 This function duplicates the showtopic method but returns its
2035 result directly so it can be formatted for display in an html page.
2036 """
2037 try:
2038 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04002039 except ImportError:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002040 return('''
2041Sorry, topic and keyword documentation is not available because the
2042module "pydoc_data.topics" could not be found.
2043''' , '')
2044 target = self.topics.get(topic, self.keywords.get(topic))
2045 if not target:
Georg Brandld2f38572011-01-30 08:37:19 +00002046 raise ValueError('could not find topic')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002047 if isinstance(target, str):
2048 return self._gettopic(target, more_xrefs)
2049 label, xrefs = target
Georg Brandld2f38572011-01-30 08:37:19 +00002050 doc = pydoc_data.topics.topics[label]
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002051 if more_xrefs:
2052 xrefs = (xrefs or '') + ' ' + more_xrefs
2053 return doc, xrefs
2054
Georg Brandldb7b6b92009-01-01 15:53:14 +00002055 def showsymbol(self, symbol):
2056 target = self.symbols[symbol]
2057 topic, _, xrefs = target.partition(' ')
2058 self.showtopic(topic, xrefs)
2059
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002060 def listmodules(self, key=''):
2061 if key:
2062 self.output.write('''
Terry Jan Reedy34200572013-02-11 02:23:13 -05002063Here is a list of modules whose name or summary contains '{}'.
2064If there are any, enter a module name to get more help.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002065
Terry Jan Reedy34200572013-02-11 02:23:13 -05002066'''.format(key))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002067 apropos(key)
2068 else:
2069 self.output.write('''
2070Please wait a moment while I gather a list of all available modules...
2071
2072''')
2073 modules = {}
2074 def callback(path, modname, desc, modules=modules):
2075 if modname and modname[-9:] == '.__init__':
2076 modname = modname[:-9] + ' (package)'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002077 if modname.find('.') < 0:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002078 modules[modname] = 1
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002079 def onerror(modname):
2080 callback(None, modname, None)
2081 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002082 self.list(modules.keys())
2083 self.output.write('''
2084Enter any module name to get more help. Or, type "modules spam" to search
Terry Jan Reedy34200572013-02-11 02:23:13 -05002085for modules whose name or summary contain the string "spam".
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002086''')
2087
Georg Brandl78aa3962010-07-31 21:51:48 +00002088help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002089
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002090class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002091 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002092
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002093 def run(self, callback, key=None, completer=None, onerror=None):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002094 if key: key = key.lower()
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002095 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002096 seen = {}
2097
2098 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002099 if modname != '__main__':
2100 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00002101 if key is None:
2102 callback(None, modname, '')
2103 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002104 name = __import__(modname).__doc__ or ''
2105 desc = name.split('\n')[0]
2106 name = modname + ' - ' + desc
2107 if name.lower().find(key) >= 0:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002108 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002109
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002110 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002111 if self.quit:
2112 break
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002113
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002114 if key is None:
2115 callback(None, modname, '')
2116 else:
Georg Brandl126c8792009-04-05 15:05:48 +00002117 try:
Eric Snow3a62d142014-01-06 20:42:59 -07002118 spec = pkgutil._get_spec(importer, modname)
Georg Brandl126c8792009-04-05 15:05:48 +00002119 except SyntaxError:
2120 # raised by tests for bad coding cookies or BOM
2121 continue
Eric Snow3a62d142014-01-06 20:42:59 -07002122 loader = spec.loader
Georg Brandl126c8792009-04-05 15:05:48 +00002123 if hasattr(loader, 'get_source'):
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002124 try:
2125 source = loader.get_source(modname)
Nick Coghlan2824cb52012-07-15 22:12:14 +10002126 except Exception:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002127 if onerror:
2128 onerror(modname)
2129 continue
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002130 desc = source_synopsis(io.StringIO(source)) or ''
Georg Brandl126c8792009-04-05 15:05:48 +00002131 if hasattr(loader, 'get_filename'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002132 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002133 else:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002134 path = None
2135 else:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002136 try:
Brett Cannon2a17bde2014-05-30 14:55:29 -04002137 module = importlib._bootstrap._load(spec)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002138 except ImportError:
2139 if onerror:
2140 onerror(modname)
2141 continue
Benjamin Peterson54237f92015-02-16 19:45:01 -05002142 desc = module.__doc__.splitlines()[0] if module.__doc__ else ''
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002143 path = getattr(module,'__file__',None)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002144 name = modname + ' - ' + desc
2145 if name.lower().find(key) >= 0:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002146 callback(path, modname, desc)
2147
2148 if completer:
2149 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002150
2151def apropos(key):
2152 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002153 def callback(path, modname, desc):
2154 if modname[-9:] == '.__init__':
2155 modname = modname[:-9] + ' (package)'
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002156 print(modname, desc and '- ' + desc)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002157 def onerror(modname):
2158 pass
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002159 with warnings.catch_warnings():
2160 warnings.filterwarnings('ignore') # ignore problems during import
2161 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002162
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002163# --------------------------------------- enhanced Web browser interface
2164
2165def _start_server(urlhandler, port):
2166 """Start an HTTP server thread on a specific port.
2167
2168 Start an HTML/text server thread, so HTML or text documents can be
2169 browsed dynamically and interactively with a Web browser. Example use:
2170
2171 >>> import time
2172 >>> import pydoc
2173
2174 Define a URL handler. To determine what the client is asking
2175 for, check the URL and content_type.
2176
2177 Then get or generate some text or HTML code and return it.
2178
2179 >>> def my_url_handler(url, content_type):
2180 ... text = 'the URL sent was: (%s, %s)' % (url, content_type)
2181 ... return text
2182
2183 Start server thread on port 0.
2184 If you use port 0, the server will pick a random port number.
2185 You can then use serverthread.port to get the port number.
2186
2187 >>> port = 0
2188 >>> serverthread = pydoc._start_server(my_url_handler, port)
2189
2190 Check that the server is really started. If it is, open browser
2191 and get first page. Use serverthread.url as the starting page.
2192
2193 >>> if serverthread.serving:
2194 ... import webbrowser
2195
2196 The next two lines are commented out so a browser doesn't open if
2197 doctest is run on this module.
2198
2199 #... webbrowser.open(serverthread.url)
2200 #True
2201
2202 Let the server do its thing. We just need to monitor its status.
2203 Use time.sleep so the loop doesn't hog the CPU.
2204
2205 >>> starttime = time.time()
2206 >>> timeout = 1 #seconds
2207
2208 This is a short timeout for testing purposes.
2209
2210 >>> while serverthread.serving:
2211 ... time.sleep(.01)
2212 ... if serverthread.serving and time.time() - starttime > timeout:
2213 ... serverthread.stop()
2214 ... break
2215
2216 Print any errors that may have occurred.
2217
2218 >>> print(serverthread.error)
2219 None
2220 """
2221 import http.server
2222 import email.message
2223 import select
2224 import threading
2225
2226 class DocHandler(http.server.BaseHTTPRequestHandler):
2227
2228 def do_GET(self):
2229 """Process a request from an HTML browser.
2230
2231 The URL received is in self.path.
2232 Get an HTML page from self.urlhandler and send it.
2233 """
2234 if self.path.endswith('.css'):
2235 content_type = 'text/css'
2236 else:
2237 content_type = 'text/html'
2238 self.send_response(200)
Georg Brandld2f38572011-01-30 08:37:19 +00002239 self.send_header('Content-Type', '%s; charset=UTF-8' % content_type)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002240 self.end_headers()
2241 self.wfile.write(self.urlhandler(
2242 self.path, content_type).encode('utf-8'))
2243
2244 def log_message(self, *args):
2245 # Don't log messages.
2246 pass
2247
2248 class DocServer(http.server.HTTPServer):
2249
2250 def __init__(self, port, callback):
Senthil Kumaran2a42a0b2014-09-17 13:17:58 +08002251 self.host = 'localhost'
2252 self.address = (self.host, port)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002253 self.callback = callback
2254 self.base.__init__(self, self.address, self.handler)
2255 self.quit = False
2256
2257 def serve_until_quit(self):
2258 while not self.quit:
2259 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2260 if rd:
2261 self.handle_request()
Victor Stinnera3abd1d2011-01-03 16:12:39 +00002262 self.server_close()
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002263
2264 def server_activate(self):
2265 self.base.server_activate(self)
2266 if self.callback:
2267 self.callback(self)
2268
2269 class ServerThread(threading.Thread):
2270
2271 def __init__(self, urlhandler, port):
2272 self.urlhandler = urlhandler
2273 self.port = int(port)
2274 threading.Thread.__init__(self)
2275 self.serving = False
2276 self.error = None
2277
2278 def run(self):
2279 """Start the server."""
2280 try:
2281 DocServer.base = http.server.HTTPServer
2282 DocServer.handler = DocHandler
2283 DocHandler.MessageClass = email.message.Message
2284 DocHandler.urlhandler = staticmethod(self.urlhandler)
2285 docsvr = DocServer(self.port, self.ready)
2286 self.docserver = docsvr
2287 docsvr.serve_until_quit()
2288 except Exception as e:
2289 self.error = e
2290
2291 def ready(self, server):
2292 self.serving = True
2293 self.host = server.host
2294 self.port = server.server_port
2295 self.url = 'http://%s:%d/' % (self.host, self.port)
2296
2297 def stop(self):
2298 """Stop the server and this thread nicely"""
2299 self.docserver.quit = True
Victor Stinner4cab2cd2017-08-21 23:24:40 +02002300 self.join()
2301 # explicitly break a reference cycle: DocServer.callback
2302 # has indirectly a reference to ServerThread.
2303 self.docserver = None
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002304 self.serving = False
2305 self.url = None
2306
2307 thread = ServerThread(urlhandler, port)
2308 thread.start()
2309 # Wait until thread.serving is True to make sure we are
2310 # really up before returning.
2311 while not thread.error and not thread.serving:
2312 time.sleep(.01)
2313 return thread
2314
2315
2316def _url_handler(url, content_type="text/html"):
2317 """The pydoc url handler for use with the pydoc server.
2318
2319 If the content_type is 'text/css', the _pydoc.css style
2320 sheet is read and returned if it exits.
2321
2322 If the content_type is 'text/html', then the result of
2323 get_html_page(url) is returned.
2324 """
2325 class _HTMLDoc(HTMLDoc):
2326
2327 def page(self, title, contents):
2328 """Format an HTML page."""
2329 css_path = "pydoc_data/_pydoc.css"
2330 css_link = (
2331 '<link rel="stylesheet" type="text/css" href="%s">' %
2332 css_path)
2333 return '''\
2334<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Georg Brandld2f38572011-01-30 08:37:19 +00002335<html><head><title>Pydoc: %s</title>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002336<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Georg Brandld2f38572011-01-30 08:37:19 +00002337%s</head><body bgcolor="#f0f0f8">%s<div style="clear:both;padding-top:.5em;">%s</div>
2338</body></html>''' % (title, css_link, html_navbar(), contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002339
2340 def filelink(self, url, path):
2341 return '<a href="getfile?key=%s">%s</a>' % (url, path)
2342
2343
2344 html = _HTMLDoc()
2345
2346 def html_navbar():
Georg Brandld2f38572011-01-30 08:37:19 +00002347 version = html.escape("%s [%s, %s]" % (platform.python_version(),
2348 platform.python_build()[0],
2349 platform.python_compiler()))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002350 return """
2351 <div style='float:left'>
Georg Brandld2f38572011-01-30 08:37:19 +00002352 Python %s<br>%s
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002353 </div>
2354 <div style='float:right'>
2355 <div style='text-align:center'>
2356 <a href="index.html">Module Index</a>
2357 : <a href="topics.html">Topics</a>
2358 : <a href="keywords.html">Keywords</a>
2359 </div>
2360 <div>
Georg Brandld2f38572011-01-30 08:37:19 +00002361 <form action="get" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002362 <input type=text name=key size=15>
2363 <input type=submit value="Get">
Georg Brandld2f38572011-01-30 08:37:19 +00002364 </form>&nbsp;
2365 <form action="search" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002366 <input type=text name=key size=15>
2367 <input type=submit value="Search">
2368 </form>
2369 </div>
2370 </div>
Georg Brandld2f38572011-01-30 08:37:19 +00002371 """ % (version, html.escape(platform.platform(terse=True)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002372
2373 def html_index():
2374 """Module Index page."""
2375
2376 def bltinlink(name):
2377 return '<a href="%s.html">%s</a>' % (name, name)
2378
2379 heading = html.heading(
2380 '<big><big><strong>Index of Modules</strong></big></big>',
2381 '#ffffff', '#7799ee')
2382 names = [name for name in sys.builtin_module_names
2383 if name != '__main__']
2384 contents = html.multicolumn(names, bltinlink)
2385 contents = [heading, '<p>' + html.bigsection(
2386 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2387
2388 seen = {}
2389 for dir in sys.path:
2390 contents.append(html.index(dir, seen))
2391
2392 contents.append(
2393 '<p align=right><font color="#909090" face="helvetica,'
2394 'arial"><strong>pydoc</strong> by Ka-Ping Yee'
2395 '&lt;ping@lfw.org&gt;</font>')
Nick Coghlanecace282010-12-03 16:08:46 +00002396 return 'Index of Modules', ''.join(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002397
2398 def html_search(key):
2399 """Search results page."""
2400 # scan for modules
2401 search_result = []
2402
2403 def callback(path, modname, desc):
2404 if modname[-9:] == '.__init__':
2405 modname = modname[:-9] + ' (package)'
2406 search_result.append((modname, desc and '- ' + desc))
2407
2408 with warnings.catch_warnings():
2409 warnings.filterwarnings('ignore') # ignore problems during import
Martin Panter9ad0aae2015-11-06 00:27:14 +00002410 def onerror(modname):
2411 pass
2412 ModuleScanner().run(callback, key, onerror=onerror)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002413
2414 # format page
2415 def bltinlink(name):
2416 return '<a href="%s.html">%s</a>' % (name, name)
2417
2418 results = []
2419 heading = html.heading(
2420 '<big><big><strong>Search Results</strong></big></big>',
2421 '#ffffff', '#7799ee')
2422 for name, desc in search_result:
2423 results.append(bltinlink(name) + desc)
2424 contents = heading + html.bigsection(
2425 'key = %s' % key, '#ffffff', '#ee77aa', '<br>'.join(results))
Nick Coghlanecace282010-12-03 16:08:46 +00002426 return 'Search Results', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002427
2428 def html_getfile(path):
2429 """Get and display a source file listing safely."""
Zachary Wareeb432142014-07-10 11:18:00 -05002430 path = urllib.parse.unquote(path)
Victor Stinner91e08772011-07-05 14:30:41 +02002431 with tokenize.open(path) as fp:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002432 lines = html.escape(fp.read())
2433 body = '<pre>%s</pre>' % lines
2434 heading = html.heading(
2435 '<big><big><strong>File Listing</strong></big></big>',
2436 '#ffffff', '#7799ee')
2437 contents = heading + html.bigsection(
2438 'File: %s' % path, '#ffffff', '#ee77aa', body)
Nick Coghlanecace282010-12-03 16:08:46 +00002439 return 'getfile %s' % path, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002440
2441 def html_topics():
2442 """Index of topic texts available."""
2443
2444 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002445 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002446
2447 heading = html.heading(
2448 '<big><big><strong>INDEX</strong></big></big>',
2449 '#ffffff', '#7799ee')
2450 names = sorted(Helper.topics.keys())
2451
2452 contents = html.multicolumn(names, bltinlink)
2453 contents = heading + html.bigsection(
2454 'Topics', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002455 return 'Topics', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002456
2457 def html_keywords():
2458 """Index of keywords."""
2459 heading = html.heading(
2460 '<big><big><strong>INDEX</strong></big></big>',
2461 '#ffffff', '#7799ee')
2462 names = sorted(Helper.keywords.keys())
2463
2464 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002465 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002466
2467 contents = html.multicolumn(names, bltinlink)
2468 contents = heading + html.bigsection(
2469 'Keywords', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002470 return 'Keywords', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002471
2472 def html_topicpage(topic):
2473 """Topic or keyword help page."""
2474 buf = io.StringIO()
2475 htmlhelp = Helper(buf, buf)
2476 contents, xrefs = htmlhelp._gettopic(topic)
2477 if topic in htmlhelp.keywords:
2478 title = 'KEYWORD'
2479 else:
2480 title = 'TOPIC'
2481 heading = html.heading(
2482 '<big><big><strong>%s</strong></big></big>' % title,
2483 '#ffffff', '#7799ee')
Georg Brandld2f38572011-01-30 08:37:19 +00002484 contents = '<pre>%s</pre>' % html.markup(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002485 contents = html.bigsection(topic , '#ffffff','#ee77aa', contents)
Georg Brandld2f38572011-01-30 08:37:19 +00002486 if xrefs:
2487 xrefs = sorted(xrefs.split())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002488
Georg Brandld2f38572011-01-30 08:37:19 +00002489 def bltinlink(name):
2490 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002491
Georg Brandld2f38572011-01-30 08:37:19 +00002492 xrefs = html.multicolumn(xrefs, bltinlink)
2493 xrefs = html.section('Related help topics: ',
2494 '#ffffff', '#ee77aa', xrefs)
Nick Coghlanecace282010-12-03 16:08:46 +00002495 return ('%s %s' % (title, topic),
2496 ''.join((heading, contents, xrefs)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002497
Georg Brandld2f38572011-01-30 08:37:19 +00002498 def html_getobj(url):
2499 obj = locate(url, forceload=1)
2500 if obj is None and url != 'None':
2501 raise ValueError('could not find object')
2502 title = describe(obj)
2503 content = html.document(obj, url)
2504 return title, content
2505
2506 def html_error(url, exc):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002507 heading = html.heading(
2508 '<big><big><strong>Error</strong></big></big>',
Georg Brandld2f38572011-01-30 08:37:19 +00002509 '#ffffff', '#7799ee')
2510 contents = '<br>'.join(html.escape(line) for line in
2511 format_exception_only(type(exc), exc))
2512 contents = heading + html.bigsection(url, '#ffffff', '#bb0000',
2513 contents)
2514 return "Error - %s" % url, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002515
2516 def get_html_page(url):
2517 """Generate an HTML page for url."""
Georg Brandld2f38572011-01-30 08:37:19 +00002518 complete_url = url
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002519 if url.endswith('.html'):
2520 url = url[:-5]
Georg Brandld2f38572011-01-30 08:37:19 +00002521 try:
2522 if url in ("", "index"):
2523 title, content = html_index()
2524 elif url == "topics":
2525 title, content = html_topics()
2526 elif url == "keywords":
2527 title, content = html_keywords()
2528 elif '=' in url:
2529 op, _, url = url.partition('=')
2530 if op == "search?key":
2531 title, content = html_search(url)
2532 elif op == "getfile?key":
2533 title, content = html_getfile(url)
2534 elif op == "topic?key":
2535 # try topics first, then objects.
2536 try:
2537 title, content = html_topicpage(url)
2538 except ValueError:
2539 title, content = html_getobj(url)
2540 elif op == "get?key":
2541 # try objects first, then topics.
2542 if url in ("", "index"):
2543 title, content = html_index()
2544 else:
2545 try:
2546 title, content = html_getobj(url)
2547 except ValueError:
2548 title, content = html_topicpage(url)
2549 else:
2550 raise ValueError('bad pydoc url')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002551 else:
Georg Brandld2f38572011-01-30 08:37:19 +00002552 title, content = html_getobj(url)
2553 except Exception as exc:
2554 # Catch any errors and display them in an error page.
2555 title, content = html_error(complete_url, exc)
2556 return html.page(title, content)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002557
2558 if url.startswith('/'):
2559 url = url[1:]
2560 if content_type == 'text/css':
2561 path_here = os.path.dirname(os.path.realpath(__file__))
Georg Brandld2f38572011-01-30 08:37:19 +00002562 css_path = os.path.join(path_here, url)
2563 with open(css_path) as fp:
2564 return ''.join(fp.readlines())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002565 elif content_type == 'text/html':
2566 return get_html_page(url)
Georg Brandld2f38572011-01-30 08:37:19 +00002567 # Errors outside the url handler are caught by the server.
2568 raise TypeError('unknown content type %r for url %s' % (content_type, url))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002569
2570
2571def browse(port=0, *, open_browser=True):
2572 """Start the enhanced pydoc Web server and open a Web browser.
2573
2574 Use port '0' to start the server on an arbitrary port.
2575 Set open_browser to False to suppress opening a browser.
2576 """
2577 import webbrowser
2578 serverthread = _start_server(_url_handler, port)
2579 if serverthread.error:
2580 print(serverthread.error)
2581 return
2582 if serverthread.serving:
2583 server_help_msg = 'Server commands: [b]rowser, [q]uit'
2584 if open_browser:
2585 webbrowser.open(serverthread.url)
2586 try:
2587 print('Server ready at', serverthread.url)
2588 print(server_help_msg)
2589 while serverthread.serving:
2590 cmd = input('server> ')
2591 cmd = cmd.lower()
2592 if cmd == 'q':
2593 break
2594 elif cmd == 'b':
2595 webbrowser.open(serverthread.url)
2596 else:
2597 print(server_help_msg)
2598 except (KeyboardInterrupt, EOFError):
2599 print()
2600 finally:
2601 if serverthread.serving:
2602 serverthread.stop()
2603 print('Server stopped')
2604
2605
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002606# -------------------------------------------------- command-line interface
2607
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002608def ispath(x):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002609 return isinstance(x, str) and x.find(os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002610
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002611def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002612 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002613 import getopt
Guido van Rossum756aa932007-04-07 03:04:01 +00002614 class BadUsage(Exception): pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002615
Nick Coghlan106274b2009-11-15 23:04:33 +00002616 # Scripts don't get the current directory in their path by default
2617 # unless they are run with the '-m' switch
2618 if '' not in sys.path:
2619 scriptdir = os.path.dirname(sys.argv[0])
2620 if scriptdir in sys.path:
2621 sys.path.remove(scriptdir)
2622 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002623
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002624 try:
Victor Stinner383c3fc2011-05-25 01:35:05 +02002625 opts, args = getopt.getopt(sys.argv[1:], 'bk:p:w')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002626 writing = False
2627 start_server = False
2628 open_browser = False
2629 port = None
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002630 for opt, val in opts:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002631 if opt == '-b':
2632 start_server = True
2633 open_browser = True
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002634 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002635 apropos(val)
2636 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002637 if opt == '-p':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002638 start_server = True
2639 port = val
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002640 if opt == '-w':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002641 writing = True
2642
Benjamin Petersonb29614e2012-10-09 11:16:03 -04002643 if start_server:
2644 if port is None:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002645 port = 0
2646 browse(port, open_browser=open_browser)
2647 return
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002648
2649 if not args: raise BadUsage
2650 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002651 if ispath(arg) and not os.path.exists(arg):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002652 print('file %r does not exist' % arg)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002653 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002654 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002655 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002656 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002657 if writing:
2658 if ispath(arg) and os.path.isdir(arg):
2659 writedocs(arg)
2660 else:
2661 writedoc(arg)
2662 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002663 help.help(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +00002664 except ErrorDuringImport as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002665 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002666
2667 except (getopt.error, BadUsage):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002668 cmd = os.path.splitext(os.path.basename(sys.argv[0]))[0]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002669 print("""pydoc - the Python documentation tool
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002670
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002671{cmd} <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002672 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002673 Python keyword, topic, function, module, or package, or a dotted
2674 reference to a class or function within a module or module in a
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002675 package. If <name> contains a '{sep}', it is used as the path to a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002676 Python source file to document. If name is 'keywords', 'topics',
2677 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002678
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002679{cmd} -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002680 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002681
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002682{cmd} -p <port>
2683 Start an HTTP server on the given port on the local machine. Port
2684 number 0 can be used to get an arbitrary unused port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002685
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002686{cmd} -b
2687 Start an HTTP server on an arbitrary unused port and open a Web browser
2688 to interactively browse documentation. The -p option can be used with
2689 the -b option to explicitly specify the server port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002690
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002691{cmd} -w <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002692 Write out the HTML documentation for a module to a file in the current
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002693 directory. If <name> contains a '{sep}', it is treated as a filename; if
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002694 it names a directory, documentation is written for all the contents.
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002695""".format(cmd=cmd, sep=os.sep))
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002696
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002697if __name__ == '__main__':
2698 cli()