blob: 39db3915dc2cac938153ce5fce56fb0b82d17e93 [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)
Tim Peters2306d242001-09-25 03:18:32 +0000912 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000913 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000914
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000915 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000916
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000917 def formatvalue(self, object):
918 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000919 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000920
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000921 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000922 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000923 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000924 realname = object.__name__
925 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000926 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000927 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000928 skipdocs = 0
Larry Hastings24a882b2014-02-20 23:34:46 -0800929 if _is_bound_method(object):
Christian Heimesff737952007-11-27 10:40:20 +0000930 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000931 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000932 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000933 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000934 else:
Christian Heimesff737952007-11-27 10:40:20 +0000935 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000936 note = ' method of %s instance' % self.classlink(
Christian Heimesff737952007-11-27 10:40:20 +0000937 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000938 else:
939 note = ' unbound %s method' % self.classlink(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000940
941 if name == realname:
942 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
943 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000944 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000945 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000946 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000947 cl.__name__ + '-' + realname, realname)
948 skipdocs = 1
949 else:
950 reallink = realname
951 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
952 anchor, name, reallink)
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800953 argspec = None
Larry Hastings24a882b2014-02-20 23:34:46 -0800954 if inspect.isroutine(object):
Larry Hastings5c661892014-01-24 06:17:25 -0800955 try:
956 signature = inspect.signature(object)
957 except (ValueError, TypeError):
958 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800959 if signature:
960 argspec = str(signature)
961 if realname == '<lambda>':
962 title = '<strong>%s</strong> <em>lambda</em> ' % name
963 # XXX lambda's won't usually have func_annotations['return']
964 # since the syntax doesn't support but it is possible.
965 # So removing parentheses isn't truly safe.
966 argspec = argspec[1:-1] # remove parentheses
967 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +0000968 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000969
Serhiy Storchaka66dd4aa2014-11-17 23:48:02 +0200970 decl = title + self.escape(argspec) + (note and self.grey(
Tim Peters2306d242001-09-25 03:18:32 +0000971 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000972
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000973 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000974 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000975 else:
976 doc = self.markup(
977 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000978 doc = doc and '<dd><tt>%s</tt></dd>' % doc
979 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000980
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000981 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000982 results = []
983 push = results.append
984
985 if name:
986 push('<dl><dt><strong>%s</strong></dt>\n' % name)
987 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000988 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000989 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000990 push('</dl>\n')
991
992 return ''.join(results)
993
994 def docproperty(self, object, name=None, mod=None, cl=None):
995 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000996 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000997
Tim Peters8dd7ade2001-10-18 19:56:17 +0000998 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000999 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001000 lhs = name and '<strong>%s</strong> = ' % name or ''
1001 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001002
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001003 def docdata(self, object, name=None, mod=None, cl=None):
1004 """Produce html documentation for a data descriptor."""
1005 return self._docdescriptor(name, object, mod)
1006
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001007 def index(self, dir, shadowed=None):
1008 """Generate an HTML index for a directory of modules."""
1009 modpkgs = []
1010 if shadowed is None: shadowed = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001011 for importer, name, ispkg in pkgutil.iter_modules([dir]):
Victor Stinner4d652242011-04-12 23:41:50 +02001012 if any((0xD800 <= ord(ch) <= 0xDFFF) for ch in name):
1013 # ignore a module if its name contains a surrogate character
1014 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001015 modpkgs.append((name, '', ispkg, name in shadowed))
1016 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001017
1018 modpkgs.sort()
1019 contents = self.multicolumn(modpkgs, self.modpkglink)
1020 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
1021
1022# -------------------------------------------- text documentation generator
1023
1024class TextRepr(Repr):
1025 """Class for safely making a text representation of a Python object."""
1026 def __init__(self):
1027 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001028 self.maxlist = self.maxtuple = 20
1029 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001030 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001031
1032 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001033 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001034 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001035 if hasattr(self, methodname):
1036 return getattr(self, methodname)(x, level)
1037 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001038
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001039 def repr_string(self, x, level):
1040 test = cram(x, self.maxstring)
1041 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001042 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001043 # Backslashes are only literal in the string and are never
1044 # needed to make any special characters, so show a raw string.
1045 return 'r' + testrepr[0] + test + testrepr[0]
1046 return testrepr
1047
Skip Montanarodf708782002-03-07 22:58:02 +00001048 repr_str = repr_string
1049
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001050 def repr_instance(self, x, level):
1051 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001052 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001053 except:
1054 return '<%s instance>' % x.__class__.__name__
1055
1056class TextDoc(Doc):
1057 """Formatter class for text documentation."""
1058
1059 # ------------------------------------------- text formatting utilities
1060
1061 _repr_instance = TextRepr()
1062 repr = _repr_instance.repr
1063
1064 def bold(self, text):
1065 """Format a string in bold by overstriking."""
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001066 return ''.join(ch + '\b' + ch for ch in text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001067
1068 def indent(self, text, prefix=' '):
1069 """Indent text by prepending a given prefix to each line."""
1070 if not text: return ''
Collin Winter72e110c2007-07-17 00:27:30 +00001071 lines = [prefix + line for line in text.split('\n')]
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001072 if lines: lines[-1] = lines[-1].rstrip()
1073 return '\n'.join(lines)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001074
1075 def section(self, title, contents):
1076 """Format a section with a given heading."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001077 clean_contents = self.indent(contents).rstrip()
1078 return self.bold(title) + '\n' + clean_contents + '\n\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001079
1080 # ---------------------------------------------- type-specific routines
1081
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001082 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001083 """Render in text a class tree as returned by inspect.getclasstree()."""
1084 result = ''
1085 for entry in tree:
1086 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001087 c, bases = entry
1088 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001089 if bases and bases != (parent,):
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001090 parents = (classname(c, modname) for c in bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001091 result = result + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001092 result = result + '\n'
1093 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001094 result = result + self.formattree(
1095 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001096 return result
1097
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001098 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001099 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001100 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001101 synop, desc = splitdoc(getdoc(object))
1102 result = self.section('NAME', name + (synop and ' - ' + synop))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001103 all = getattr(object, '__all__', None)
Skip Montanaro4997a692003-09-10 16:47:51 +00001104 docloc = self.getdocloc(object)
1105 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001106 result = result + self.section('MODULE REFERENCE', docloc + """
1107
Éric Araujo647ef8c2011-09-11 00:43:20 +02001108The following documentation is automatically generated from the Python
1109source files. It may be incomplete, incorrect or include features that
1110are considered implementation detail and may vary between Python
1111implementations. When in doubt, consult the module reference at the
1112location listed above.
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001113""")
Skip Montanaro4997a692003-09-10 16:47:51 +00001114
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001115 if desc:
1116 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001117
1118 classes = []
1119 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001120 # if __all__ exists, believe it. Otherwise use old heuristic.
1121 if (all is not None
1122 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001123 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001124 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001125 funcs = []
1126 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001127 # if __all__ exists, believe it. Otherwise use old heuristic.
1128 if (all is not None or
1129 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001130 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001131 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001132 data = []
1133 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001134 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001135 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001136
Christian Heimes1af737c2008-01-23 08:24:23 +00001137 modpkgs = []
1138 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001139 if hasattr(object, '__path__'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001140 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Christian Heimes1af737c2008-01-23 08:24:23 +00001141 modpkgs_names.add(modname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001142 if ispkg:
1143 modpkgs.append(modname + ' (package)')
1144 else:
1145 modpkgs.append(modname)
1146
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001147 modpkgs.sort()
1148 result = result + self.section(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001149 'PACKAGE CONTENTS', '\n'.join(modpkgs))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001150
Christian Heimes1af737c2008-01-23 08:24:23 +00001151 # Detect submodules as sometimes created by C extensions
1152 submodules = []
1153 for key, value in inspect.getmembers(object, inspect.ismodule):
1154 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1155 submodules.append(key)
1156 if submodules:
1157 submodules.sort()
1158 result = result + self.section(
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001159 'SUBMODULES', '\n'.join(submodules))
Christian Heimes1af737c2008-01-23 08:24:23 +00001160
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001161 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001162 classlist = [value for key, value in classes]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001163 contents = [self.formattree(
1164 inspect.getclasstree(classlist, 1), name)]
1165 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001166 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001167 result = result + self.section('CLASSES', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001168
1169 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001170 contents = []
1171 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001172 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001173 result = result + self.section('FUNCTIONS', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001174
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001175 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001176 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001177 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001178 contents.append(self.docother(value, key, name, maxlen=70))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001179 result = result + self.section('DATA', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001180
1181 if hasattr(object, '__version__'):
1182 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001183 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001184 version = version[11:-1].strip()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001185 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001186 if hasattr(object, '__date__'):
1187 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001188 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001189 result = result + self.section('AUTHOR', str(object.__author__))
1190 if hasattr(object, '__credits__'):
1191 result = result + self.section('CREDITS', str(object.__credits__))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001192 try:
1193 file = inspect.getabsfile(object)
1194 except TypeError:
1195 file = '(built-in)'
1196 result = result + self.section('FILE', file)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001197 return result
1198
Georg Brandl9bd45f992010-12-03 09:58:38 +00001199 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001200 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001201 realname = object.__name__
1202 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001203 bases = object.__bases__
1204
Tim Petersc86f6ca2001-09-26 21:31:51 +00001205 def makename(c, m=object.__module__):
1206 return classname(c, m)
1207
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001208 if name == realname:
1209 title = 'class ' + self.bold(realname)
1210 else:
1211 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001212 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001213 parents = map(makename, bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001214 title = title + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001215
1216 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001217 contents = doc and [doc + '\n'] or []
1218 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001219
Tim Petersc86f6ca2001-09-26 21:31:51 +00001220 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001221 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001222 if len(mro) > 2:
1223 push("Method resolution order:")
1224 for base in mro:
1225 push(' ' + makename(base))
1226 push('')
1227
Tim Petersf4aad8e2001-09-24 22:40:47 +00001228 # Cute little class to pump out a horizontal rule between sections.
1229 class HorizontalRule:
1230 def __init__(self):
1231 self.needone = 0
1232 def maybe(self):
1233 if self.needone:
1234 push('-' * 70)
1235 self.needone = 1
1236 hr = HorizontalRule()
1237
Tim Peters28355492001-09-23 21:29:55 +00001238 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001239 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001240 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001241 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001242 push(msg)
1243 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001244 try:
1245 value = getattr(object, name)
1246 except Exception:
1247 # Some descriptors may meet a failure in their __get__.
1248 # (bug #1785)
1249 push(self._docdescriptor(name, value, mod))
1250 else:
1251 push(self.document(value,
1252 name, mod, object))
Tim Peters28355492001-09-23 21:29:55 +00001253 return attrs
1254
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001255 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001256 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001257 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001258 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001259 push(msg)
1260 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001261 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001262 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001263
Tim Petersfa26f7c2001-09-24 08:05:11 +00001264 def spilldata(msg, attrs, predicate):
1265 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:
Florent Xicluna5d1155c2011-10-28 14:45:05 +02001270 if callable(value) or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001271 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001272 else:
1273 doc = None
Serhiy Storchaka056eb022014-02-19 23:05:12 +02001274 try:
1275 obj = getattr(object, name)
1276 except AttributeError:
1277 obj = homecls.__dict__[name]
1278 push(self.docother(obj, name, mod, maxlen=70, doc=doc) +
1279 '\n')
Tim Peters28355492001-09-23 21:29:55 +00001280 return attrs
1281
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001282 attrs = [(name, kind, cls, value)
1283 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -07001284 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001285
Tim Petersfa26f7c2001-09-24 08:05:11 +00001286 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001287 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001288 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001289 else:
1290 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001291 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1292
Georg Brandl1a3284e2007-12-02 09:40:06 +00001293 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001294 attrs = inherited
1295 continue
1296 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001297 tag = "defined here"
1298 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001299 tag = "inherited from %s" % classname(thisclass,
1300 object.__module__)
Raymond Hettinger95801bb2015-08-18 22:25:16 -07001301
1302 sort_attributes(attrs, object)
Tim Peters28355492001-09-23 21:29:55 +00001303
1304 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001305 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001306 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001307 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001308 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001309 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001310 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001311 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1312 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001313 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1314 lambda t: t[1] == 'data')
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001315
Tim Peters28355492001-09-23 21:29:55 +00001316 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001317 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001318
1319 contents = '\n'.join(contents)
1320 if not contents:
1321 return title + '\n'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001322 return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001323
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001324 def formatvalue(self, object):
1325 """Format an argument default value as text."""
1326 return '=' + self.repr(object)
1327
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001328 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001329 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001330 realname = object.__name__
1331 name = name or realname
1332 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001333 skipdocs = 0
Larry Hastings24a882b2014-02-20 23:34:46 -08001334 if _is_bound_method(object):
Christian Heimesff737952007-11-27 10:40:20 +00001335 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001336 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001337 if imclass is not cl:
1338 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001339 else:
Christian Heimesff737952007-11-27 10:40:20 +00001340 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001341 note = ' method of %s instance' % classname(
Christian Heimesff737952007-11-27 10:40:20 +00001342 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001343 else:
1344 note = ' unbound %s method' % classname(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001345
1346 if name == realname:
1347 title = self.bold(realname)
1348 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001349 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001350 cl.__dict__[realname] is object):
1351 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001352 title = self.bold(name) + ' = ' + realname
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001353 argspec = None
Larry Hastings5c661892014-01-24 06:17:25 -08001354
1355 if inspect.isroutine(object):
1356 try:
1357 signature = inspect.signature(object)
1358 except (ValueError, TypeError):
1359 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001360 if signature:
1361 argspec = str(signature)
1362 if realname == '<lambda>':
1363 title = self.bold(name) + ' lambda '
1364 # XXX lambda's won't usually have func_annotations['return']
1365 # since the syntax doesn't support but it is possible.
1366 # So removing parentheses isn't truly safe.
1367 argspec = argspec[1:-1] # remove parentheses
1368 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +00001369 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001370 decl = title + argspec + note
1371
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001372 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001373 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001374 else:
1375 doc = getdoc(object) or ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001376 return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001377
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001378 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001379 results = []
1380 push = results.append
1381
1382 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001383 push(self.bold(name))
1384 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001385 doc = getdoc(value) or ''
1386 if doc:
1387 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001388 push('\n')
1389 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001390
1391 def docproperty(self, object, name=None, mod=None, cl=None):
1392 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001393 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001394
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001395 def docdata(self, object, name=None, mod=None, cl=None):
1396 """Produce text documentation for a data descriptor."""
1397 return self._docdescriptor(name, object, mod)
1398
Georg Brandl8b813db2005-10-01 16:32:31 +00001399 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001400 """Produce text documentation for a data object."""
1401 repr = self.repr(object)
1402 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001403 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001404 chop = maxlen - len(line)
1405 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001406 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001407 if doc is not None:
1408 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001409 return line
1410
Georg Brandld80d5f42010-12-03 07:47:22 +00001411class _PlainTextDoc(TextDoc):
1412 """Subclass of TextDoc which overrides string styling"""
1413 def bold(self, text):
1414 return text
1415
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001416# --------------------------------------------------------- user interfaces
1417
1418def pager(text):
1419 """The first time this is called, determine what kind of pager to use."""
1420 global pager
1421 pager = getpager()
1422 pager(text)
1423
1424def getpager():
1425 """Decide what method to use for paging through text."""
Benjamin Peterson159824e2014-06-07 20:14:26 -07001426 if not hasattr(sys.stdin, "isatty"):
1427 return plainpager
Guido van Rossuma01a8b62007-05-27 09:20:14 +00001428 if not hasattr(sys.stdout, "isatty"):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001429 return plainpager
1430 if not sys.stdin.isatty() or not sys.stdout.isatty():
1431 return plainpager
doko@ubuntu.com96575452016-06-14 08:39:31 +02001432 use_pager = os.environ.get('MANPAGER') or os.environ.get('PAGER')
1433 if use_pager:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001434 if sys.platform == 'win32': # pipes completely broken in Windows
doko@ubuntu.comc8fd1922016-06-14 09:03:52 +02001435 return lambda text: tempfilepager(plain(text), use_pager)
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001436 elif os.environ.get('TERM') in ('dumb', 'emacs'):
doko@ubuntu.comc8fd1922016-06-14 09:03:52 +02001437 return lambda text: pipepager(plain(text), use_pager)
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001438 else:
doko@ubuntu.comc8fd1922016-06-14 09:03:52 +02001439 return lambda text: pipepager(text, use_pager)
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001440 if os.environ.get('TERM') in ('dumb', 'emacs'):
1441 return plainpager
Jesus Cea4791a242012-10-05 03:15:39 +02001442 if sys.platform == 'win32':
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001443 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001444 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001445 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001446
1447 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001448 (fd, filename) = tempfile.mkstemp()
1449 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001450 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001451 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001452 return lambda text: pipepager(text, 'more')
1453 else:
1454 return ttypager
1455 finally:
1456 os.unlink(filename)
1457
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001458def plain(text):
1459 """Remove boldface formatting from text."""
1460 return re.sub('.\b', '', text)
1461
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001462def pipepager(text, cmd):
1463 """Page through text by feeding it to another program."""
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001464 import subprocess
1465 proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001466 try:
R David Murray1058cda2015-03-29 15:15:40 -04001467 with io.TextIOWrapper(proc.stdin, errors='backslashreplace') as pipe:
R David Murraye7f5e142015-03-30 10:14:47 -04001468 try:
1469 pipe.write(text)
1470 except KeyboardInterrupt:
1471 # We've hereby abandoned whatever text hasn't been written,
1472 # but the pager is still in control of the terminal.
1473 pass
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001474 except OSError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001475 pass # Ignore broken pipes caused by quitting the pager program.
R David Murray1058cda2015-03-29 15:15:40 -04001476 while True:
1477 try:
1478 proc.wait()
1479 break
1480 except KeyboardInterrupt:
1481 # Ignore ctl-c like the pager itself does. Otherwise the pager is
1482 # left running and the terminal is in raw mode and unusable.
1483 pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001484
1485def tempfilepager(text, cmd):
1486 """Page through text by invoking a program on a temporary file."""
1487 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001488 filename = tempfile.mktemp()
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001489 with open(filename, 'w', errors='backslashreplace') as file:
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +01001490 file.write(text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001491 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001492 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001493 finally:
1494 os.unlink(filename)
1495
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001496def _escape_stdout(text):
1497 # Escape non-encodable characters to avoid encoding errors later
1498 encoding = getattr(sys.stdout, 'encoding', None) or 'utf-8'
1499 return text.encode(encoding, 'backslashreplace').decode(encoding)
1500
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001501def ttypager(text):
1502 """Page through text on a text terminal."""
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001503 lines = plain(_escape_stdout(text)).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001504 try:
1505 import tty
1506 fd = sys.stdin.fileno()
1507 old = tty.tcgetattr(fd)
1508 tty.setcbreak(fd)
1509 getchar = lambda: sys.stdin.read(1)
Serhiy Storchakaab5e9b92014-11-28 00:09:29 +02001510 except (ImportError, AttributeError, io.UnsupportedOperation):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001511 tty = None
1512 getchar = lambda: sys.stdin.readline()[:-1][:1]
1513
1514 try:
Serhiy Storchakaab5e9b92014-11-28 00:09:29 +02001515 try:
1516 h = int(os.environ.get('LINES', 0))
1517 except ValueError:
1518 h = 0
1519 if h <= 1:
1520 h = 25
1521 r = inc = h - 1
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001522 sys.stdout.write('\n'.join(lines[:inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001523 while lines[r:]:
1524 sys.stdout.write('-- more --')
1525 sys.stdout.flush()
1526 c = getchar()
1527
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001528 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001529 sys.stdout.write('\r \r')
1530 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001531 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001532 sys.stdout.write('\r \r' + lines[r] + '\n')
1533 r = r + 1
1534 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001535 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001536 r = r - inc - inc
1537 if r < 0: r = 0
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001538 sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001539 r = r + inc
1540
1541 finally:
1542 if tty:
1543 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1544
1545def plainpager(text):
1546 """Simply print unformatted text. This is the ultimate fallback."""
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001547 sys.stdout.write(plain(_escape_stdout(text)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001548
1549def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001550 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001551 if inspect.ismodule(thing):
1552 if thing.__name__ in sys.builtin_module_names:
1553 return 'built-in module ' + thing.__name__
1554 if hasattr(thing, '__path__'):
1555 return 'package ' + thing.__name__
1556 else:
1557 return 'module ' + thing.__name__
1558 if inspect.isbuiltin(thing):
1559 return 'built-in function ' + thing.__name__
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001560 if inspect.isgetsetdescriptor(thing):
1561 return 'getset descriptor %s.%s.%s' % (
1562 thing.__objclass__.__module__, thing.__objclass__.__name__,
1563 thing.__name__)
1564 if inspect.ismemberdescriptor(thing):
1565 return 'member descriptor %s.%s.%s' % (
1566 thing.__objclass__.__module__, thing.__objclass__.__name__,
1567 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001568 if inspect.isclass(thing):
1569 return 'class ' + thing.__name__
1570 if inspect.isfunction(thing):
1571 return 'function ' + thing.__name__
1572 if inspect.ismethod(thing):
1573 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001574 return type(thing).__name__
1575
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001576def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001577 """Locate an object by name or dotted path, importing as necessary."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001578 parts = [part for part in path.split('.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001579 module, n = None, 0
1580 while n < len(parts):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001581 nextmodule = safeimport('.'.join(parts[:n+1]), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001582 if nextmodule: module, n = nextmodule, n + 1
1583 else: break
1584 if module:
1585 object = module
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001586 else:
Éric Araujoe64e51b2011-07-29 17:03:55 +02001587 object = builtins
1588 for part in parts[n:]:
1589 try:
1590 object = getattr(object, part)
1591 except AttributeError:
1592 return None
1593 return object
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001594
1595# --------------------------------------- interactive interpreter interface
1596
1597text = TextDoc()
Georg Brandld80d5f42010-12-03 07:47:22 +00001598plaintext = _PlainTextDoc()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001599html = HTMLDoc()
1600
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001601def resolve(thing, forceload=0):
1602 """Given an object or a path to an object, get the object and its name."""
1603 if isinstance(thing, str):
1604 object = locate(thing, forceload)
Serhiy Storchakab6076fb2015-04-21 21:09:48 +03001605 if object is None:
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001606 raise ImportError('''\
1607No Python documentation found for %r.
1608Use help() to get the interactive help utility.
1609Use help(str) for help on the str class.''' % thing)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001610 return object, thing
1611 else:
R David Murrayc43125a2012-04-23 13:23:57 -04001612 name = getattr(thing, '__name__', None)
1613 return thing, name if isinstance(name, str) else None
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001614
Georg Brandld80d5f42010-12-03 07:47:22 +00001615def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
1616 renderer=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001617 """Render text documentation, given an object or a path to an object."""
Georg Brandld80d5f42010-12-03 07:47:22 +00001618 if renderer is None:
1619 renderer = text
Guido van Rossumd8faa362007-04-27 19:54:29 +00001620 object, name = resolve(thing, forceload)
1621 desc = describe(object)
1622 module = inspect.getmodule(object)
1623 if name and '.' in name:
1624 desc += ' in ' + name[:name.rfind('.')]
1625 elif module and module is not object:
1626 desc += ' in module ' + module.__name__
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001627
1628 if not (inspect.ismodule(object) or
Guido van Rossumd8faa362007-04-27 19:54:29 +00001629 inspect.isclass(object) or
1630 inspect.isroutine(object) or
1631 inspect.isgetsetdescriptor(object) or
1632 inspect.ismemberdescriptor(object) or
1633 isinstance(object, property)):
1634 # If the passed object is a piece of data or an instance,
1635 # document its available methods instead of its value.
1636 object = type(object)
1637 desc += ' object'
Georg Brandld80d5f42010-12-03 07:47:22 +00001638 return title % desc + '\n\n' + renderer.document(object, name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001639
Georg Brandld80d5f42010-12-03 07:47:22 +00001640def doc(thing, title='Python Library Documentation: %s', forceload=0,
1641 output=None):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001642 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001643 try:
Georg Brandld80d5f42010-12-03 07:47:22 +00001644 if output is None:
1645 pager(render_doc(thing, title, forceload))
1646 else:
1647 output.write(render_doc(thing, title, forceload, plaintext))
Guido van Rossumb940e112007-01-10 16:19:56 +00001648 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001649 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001650
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001651def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001652 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001653 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001654 object, name = resolve(thing, forceload)
1655 page = html.page(describe(object), html.document(object, name))
Serhiy Storchaka46ba6c82015-04-04 11:01:02 +03001656 with open(name + '.html', 'w', encoding='utf-8') as file:
1657 file.write(page)
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001658 print('wrote', name + '.html')
Guido van Rossumb940e112007-01-10 16:19:56 +00001659 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001660 print(value)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001661
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001662def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001663 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001664 if done is None: done = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001665 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1666 writedoc(modname)
1667 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001668
1669class Helper:
Georg Brandl6b38daa2008-06-01 21:05:17 +00001670
1671 # These dictionaries map a topic name to either an alias, or a tuple
1672 # (label, seealso-items). The "label" is the label of the corresponding
1673 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl5617db82009-04-27 16:28:57 +00001674 # in pydoc_data/topics.py.
Georg Brandl6b38daa2008-06-01 21:05:17 +00001675 #
1676 # CAUTION: if you change one of these dictionaries, be sure to adapt the
Georg Brandl61bd1dc2014-09-30 22:56:38 +02001677 # list of needed labels in Doc/tools/pyspecific.py and
Georg Brandl5617db82009-04-27 16:28:57 +00001678 # regenerate the pydoc_data/topics.py file by running
Georg Brandl6b38daa2008-06-01 21:05:17 +00001679 # make pydoc-topics
1680 # in Doc/ and copying the output file into the Lib/ directory.
1681
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001682 keywords = {
Ezio Melottib185a042011-04-28 07:42:55 +03001683 'False': '',
1684 'None': '',
1685 'True': '',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001686 'and': 'BOOLEAN',
Guido van Rossumd8faa362007-04-27 19:54:29 +00001687 'as': 'with',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001688 'assert': ('assert', ''),
1689 'break': ('break', 'while for'),
1690 'class': ('class', 'CLASSES SPECIALMETHODS'),
1691 'continue': ('continue', 'while for'),
1692 'def': ('function', ''),
1693 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001694 'elif': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001695 'else': ('else', 'while for'),
Georg Brandl0d855392008-08-30 19:53:05 +00001696 'except': 'try',
1697 'finally': 'try',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001698 'for': ('for', 'break continue while'),
Georg Brandl0d855392008-08-30 19:53:05 +00001699 'from': 'import',
Georg Brandl74abf6f2010-11-20 19:54:36 +00001700 'global': ('global', 'nonlocal NAMESPACES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001701 'if': ('if', 'TRUTHVALUE'),
1702 'import': ('import', 'MODULES'),
Georg Brandl395ed242009-09-04 08:07:32 +00001703 'in': ('in', 'SEQUENCEMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001704 'is': 'COMPARISON',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001705 'lambda': ('lambda', 'FUNCTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001706 'nonlocal': ('nonlocal', 'global NAMESPACES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001707 'not': 'BOOLEAN',
1708 'or': 'BOOLEAN',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001709 'pass': ('pass', ''),
1710 'raise': ('raise', 'EXCEPTIONS'),
1711 'return': ('return', 'FUNCTIONS'),
1712 'try': ('try', 'EXCEPTIONS'),
1713 'while': ('while', 'break continue if TRUTHVALUE'),
1714 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1715 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001716 }
Georg Brandldb7b6b92009-01-01 15:53:14 +00001717 # Either add symbols to this dictionary or to the symbols dictionary
1718 # directly: Whichever is easier. They are merged later.
1719 _symbols_inverse = {
1720 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'),
1721 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1722 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1723 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1724 'UNARY' : ('-', '~'),
1725 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1726 '^=', '<<=', '>>=', '**=', '//='),
1727 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1728 'COMPLEX' : ('j', 'J')
1729 }
1730 symbols = {
1731 '%': 'OPERATORS FORMATTING',
1732 '**': 'POWER',
1733 ',': 'TUPLES LISTS FUNCTIONS',
1734 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1735 '...': 'ELLIPSIS',
1736 ':': 'SLICINGS DICTIONARYLITERALS',
1737 '@': 'def class',
1738 '\\': 'STRINGS',
1739 '_': 'PRIVATENAMES',
1740 '__': 'PRIVATENAMES SPECIALMETHODS',
1741 '`': 'BACKQUOTES',
1742 '(': 'TUPLES FUNCTIONS CALLS',
1743 ')': 'TUPLES FUNCTIONS CALLS',
1744 '[': 'LISTS SUBSCRIPTS SLICINGS',
1745 ']': 'LISTS SUBSCRIPTS SLICINGS'
1746 }
1747 for topic, symbols_ in _symbols_inverse.items():
1748 for symbol in symbols_:
1749 topics = symbols.get(symbol, topic)
1750 if topic not in topics:
1751 topics = topics + ' ' + topic
1752 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001753
1754 topics = {
Georg Brandl6b38daa2008-06-01 21:05:17 +00001755 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1756 'FUNCTIONS CLASSES MODULES FILES inspect'),
1757 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS '
1758 'FORMATTING TYPES'),
1759 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1760 'FORMATTING': ('formatstrings', 'OPERATORS'),
1761 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1762 'FORMATTING TYPES'),
1763 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1764 'INTEGER': ('integers', 'int range'),
1765 'FLOAT': ('floating', 'float math'),
1766 'COMPLEX': ('imaginary', 'complex cmath'),
1767 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING range LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001768 'MAPPINGS': 'DICTIONARIES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001769 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1770 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1771 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1772 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001773 'FRAMEOBJECTS': 'TYPES',
1774 'TRACEBACKS': 'TYPES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001775 'NONE': ('bltin-null-object', ''),
1776 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001777 'SPECIALATTRIBUTES': ('specialattrs', ''),
1778 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1779 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001780 'PACKAGES': 'import',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001781 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1782 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1783 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1784 'LISTS DICTIONARIES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001785 'OPERATORS': 'EXPRESSIONS',
1786 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001787 'OBJECTS': ('objects', 'TYPES'),
1788 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
Georg Brandl395ed242009-09-04 08:07:32 +00001789 'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS '
1790 'NUMBERMETHODS CLASSES'),
Mark Dickinsona56c4672009-01-27 18:17:45 +00001791 'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001792 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1793 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001794 'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS '
Georg Brandl6b38daa2008-06-01 21:05:17 +00001795 'SPECIALMETHODS'),
1796 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1797 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1798 'SPECIALMETHODS'),
1799 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001800 'NAMESPACES': ('naming', 'global nonlocal ASSIGNMENT DELETION DYNAMICFEATURES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001801 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001802 'SCOPING': 'NAMESPACES',
1803 'FRAMES': 'NAMESPACES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001804 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1805 'CONVERSIONS': ('conversions', ''),
1806 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1807 'SPECIALIDENTIFIERS': ('id-classes', ''),
1808 'PRIVATENAMES': ('atom-identifiers', ''),
1809 'LITERALS': ('atom-literals', 'STRINGS NUMBERS TUPLELITERALS '
1810 'LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001811 'TUPLES': 'SEQUENCES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001812 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1813 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1814 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1815 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1816 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1817 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001818 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'),
1819 'SLICINGS': ('slicings', 'SEQUENCEMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001820 'CALLS': ('calls', 'EXPRESSIONS'),
1821 'POWER': ('power', 'EXPRESSIONS'),
1822 'UNARY': ('unary', 'EXPRESSIONS'),
1823 'BINARY': ('binary', 'EXPRESSIONS'),
1824 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1825 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1826 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1827 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001828 'ASSERTION': 'assert',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001829 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1830 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001831 'DELETION': 'del',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001832 'RETURNING': 'return',
1833 'IMPORTING': 'import',
1834 'CONDITIONAL': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001835 'LOOPING': ('compound', 'for while break continue'),
1836 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1837 'DEBUGGING': ('debugger', 'pdb'),
1838 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001839 }
1840
Georg Brandl78aa3962010-07-31 21:51:48 +00001841 def __init__(self, input=None, output=None):
1842 self._input = input
1843 self._output = output
1844
Georg Brandl76ae3972010-08-01 06:32:55 +00001845 input = property(lambda self: self._input or sys.stdin)
1846 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001847
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001848 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001849 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001850 self()
1851 return ''
Serhiy Storchaka465e60e2014-07-25 23:36:00 +03001852 return '<%s.%s instance>' % (self.__class__.__module__,
1853 self.__class__.__qualname__)
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001854
Alexander Belopolsky2e733c92010-07-04 17:00:20 +00001855 _GoInteractive = object()
1856 def __call__(self, request=_GoInteractive):
1857 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001858 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001859 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001860 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001861 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001862 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001863You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001864If you want to ask for help on a particular object directly from the
1865interpreter, you can type "help(object)". Executing "help('string')"
1866has the same effect as typing a particular string at the help> prompt.
1867''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001868
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001869 def interact(self):
1870 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001871 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001872 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001873 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001874 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001875 except (KeyboardInterrupt, EOFError):
1876 break
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001877 request = replace(request, '"', '', "'", '').strip()
1878 if request.lower() in ('q', 'quit'): break
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001879 if request == 'help':
1880 self.intro()
1881 else:
1882 self.help(request)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001883
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001884 def getline(self, prompt):
Guido van Rossum7c086c02008-01-02 03:52:38 +00001885 """Read one line, using input() when appropriate."""
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001886 if self.input is sys.stdin:
Guido van Rossum7c086c02008-01-02 03:52:38 +00001887 return input(prompt)
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001888 else:
1889 self.output.write(prompt)
1890 self.output.flush()
1891 return self.input.readline()
1892
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001893 def help(self, request):
1894 if type(request) is type(''):
R. David Murray1f1b9d32009-05-27 20:56:59 +00001895 request = request.strip()
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001896 if request == 'keywords': self.listkeywords()
Georg Brandldb7b6b92009-01-01 15:53:14 +00001897 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001898 elif request == 'topics': self.listtopics()
1899 elif request == 'modules': self.listmodules()
1900 elif request[:8] == 'modules ':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001901 self.listmodules(request.split()[1])
Georg Brandldb7b6b92009-01-01 15:53:14 +00001902 elif request in self.symbols: self.showsymbol(request)
Ezio Melottib185a042011-04-28 07:42:55 +03001903 elif request in ['True', 'False', 'None']:
1904 # special case these keywords since they are objects too
1905 doc(eval(request), 'Help on %s:')
Raymond Hettinger54f02222002-06-01 14:18:47 +00001906 elif request in self.keywords: self.showtopic(request)
1907 elif request in self.topics: self.showtopic(request)
Georg Brandld80d5f42010-12-03 07:47:22 +00001908 elif request: doc(request, 'Help on %s:', output=self._output)
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001909 else: doc(str, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001910 elif isinstance(request, Helper): self()
Georg Brandld80d5f42010-12-03 07:47:22 +00001911 else: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001912 self.output.write('\n')
1913
1914 def intro(self):
1915 self.output.write('''
Serhiy Storchaka885bdc42016-02-11 13:10:36 +02001916Welcome to Python {0}'s help utility!
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001917
1918If this is your first time using Python, you should definitely check out
Serhiy Storchaka885bdc42016-02-11 13:10:36 +02001919the tutorial on the Internet at http://docs.python.org/{0}/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001920
1921Enter the name of any module, keyword, or topic to get help on writing
1922Python programs and using Python modules. To quit this help utility and
1923return to the interpreter, just type "quit".
1924
Terry Jan Reedy34200572013-02-11 02:23:13 -05001925To get a list of available modules, keywords, symbols, or topics, type
1926"modules", "keywords", "symbols", or "topics". Each module also comes
1927with a one-line summary of what it does; to list the modules whose name
1928or summary contain a given string such as "spam", type "modules spam".
Serhiy Storchaka885bdc42016-02-11 13:10:36 +02001929'''.format('%d.%d' % sys.version_info[:2]))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001930
1931 def list(self, items, columns=4, width=80):
Guido van Rossum486364b2007-06-30 05:01:58 +00001932 items = list(sorted(items))
1933 colw = width // columns
1934 rows = (len(items) + columns - 1) // columns
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001935 for row in range(rows):
1936 for col in range(columns):
1937 i = col * rows + row
1938 if i < len(items):
1939 self.output.write(items[i])
1940 if col < columns - 1:
Guido van Rossum486364b2007-06-30 05:01:58 +00001941 self.output.write(' ' + ' ' * (colw - 1 - len(items[i])))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001942 self.output.write('\n')
1943
1944 def listkeywords(self):
1945 self.output.write('''
1946Here is a list of the Python keywords. Enter any keyword to get more help.
1947
1948''')
1949 self.list(self.keywords.keys())
1950
Georg Brandldb7b6b92009-01-01 15:53:14 +00001951 def listsymbols(self):
1952 self.output.write('''
1953Here is a list of the punctuation symbols which Python assigns special meaning
1954to. Enter any symbol to get more help.
1955
1956''')
1957 self.list(self.symbols.keys())
1958
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001959 def listtopics(self):
1960 self.output.write('''
1961Here is a list of available topics. Enter any topic name to get more help.
1962
1963''')
1964 self.list(self.topics.keys())
1965
Georg Brandldb7b6b92009-01-01 15:53:14 +00001966 def showtopic(self, topic, more_xrefs=''):
Georg Brandl6b38daa2008-06-01 21:05:17 +00001967 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001968 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04001969 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001970 self.output.write('''
Georg Brandl6b38daa2008-06-01 21:05:17 +00001971Sorry, topic and keyword documentation is not available because the
Georg Brandl5617db82009-04-27 16:28:57 +00001972module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001973''')
1974 return
1975 target = self.topics.get(topic, self.keywords.get(topic))
1976 if not target:
1977 self.output.write('no documentation found for %s\n' % repr(topic))
1978 return
1979 if type(target) is type(''):
Georg Brandldb7b6b92009-01-01 15:53:14 +00001980 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001981
Georg Brandl6b38daa2008-06-01 21:05:17 +00001982 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001983 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001984 doc = pydoc_data.topics.topics[label]
Georg Brandl6b38daa2008-06-01 21:05:17 +00001985 except KeyError:
1986 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001987 return
Georg Brandl6b38daa2008-06-01 21:05:17 +00001988 pager(doc.strip() + '\n')
Georg Brandldb7b6b92009-01-01 15:53:14 +00001989 if more_xrefs:
1990 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001991 if xrefs:
Brett Cannon1448ecf2013-10-04 11:38:59 -04001992 import textwrap
1993 text = 'Related help topics: ' + ', '.join(xrefs.split()) + '\n'
1994 wrapped_text = textwrap.wrap(text, 72)
1995 self.output.write('\n%s\n' % ''.join(wrapped_text))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001996
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001997 def _gettopic(self, topic, more_xrefs=''):
1998 """Return unbuffered tuple of (topic, xrefs).
1999
Georg Brandld2f38572011-01-30 08:37:19 +00002000 If an error occurs here, the exception is caught and displayed by
2001 the url handler.
2002
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002003 This function duplicates the showtopic method but returns its
2004 result directly so it can be formatted for display in an html page.
2005 """
2006 try:
2007 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04002008 except ImportError:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002009 return('''
2010Sorry, topic and keyword documentation is not available because the
2011module "pydoc_data.topics" could not be found.
2012''' , '')
2013 target = self.topics.get(topic, self.keywords.get(topic))
2014 if not target:
Georg Brandld2f38572011-01-30 08:37:19 +00002015 raise ValueError('could not find topic')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002016 if isinstance(target, str):
2017 return self._gettopic(target, more_xrefs)
2018 label, xrefs = target
Georg Brandld2f38572011-01-30 08:37:19 +00002019 doc = pydoc_data.topics.topics[label]
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002020 if more_xrefs:
2021 xrefs = (xrefs or '') + ' ' + more_xrefs
2022 return doc, xrefs
2023
Georg Brandldb7b6b92009-01-01 15:53:14 +00002024 def showsymbol(self, symbol):
2025 target = self.symbols[symbol]
2026 topic, _, xrefs = target.partition(' ')
2027 self.showtopic(topic, xrefs)
2028
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002029 def listmodules(self, key=''):
2030 if key:
2031 self.output.write('''
Terry Jan Reedy34200572013-02-11 02:23:13 -05002032Here is a list of modules whose name or summary contains '{}'.
2033If there are any, enter a module name to get more help.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002034
Terry Jan Reedy34200572013-02-11 02:23:13 -05002035'''.format(key))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002036 apropos(key)
2037 else:
2038 self.output.write('''
2039Please wait a moment while I gather a list of all available modules...
2040
2041''')
2042 modules = {}
2043 def callback(path, modname, desc, modules=modules):
2044 if modname and modname[-9:] == '.__init__':
2045 modname = modname[:-9] + ' (package)'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002046 if modname.find('.') < 0:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002047 modules[modname] = 1
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002048 def onerror(modname):
2049 callback(None, modname, None)
2050 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002051 self.list(modules.keys())
2052 self.output.write('''
2053Enter any module name to get more help. Or, type "modules spam" to search
Terry Jan Reedy34200572013-02-11 02:23:13 -05002054for modules whose name or summary contain the string "spam".
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002055''')
2056
Georg Brandl78aa3962010-07-31 21:51:48 +00002057help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002058
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002059class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002060 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002061
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002062 def run(self, callback, key=None, completer=None, onerror=None):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002063 if key: key = key.lower()
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002064 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002065 seen = {}
2066
2067 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002068 if modname != '__main__':
2069 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00002070 if key is None:
2071 callback(None, modname, '')
2072 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002073 name = __import__(modname).__doc__ or ''
2074 desc = name.split('\n')[0]
2075 name = modname + ' - ' + desc
2076 if name.lower().find(key) >= 0:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002077 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002078
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002079 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002080 if self.quit:
2081 break
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002082
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002083 if key is None:
2084 callback(None, modname, '')
2085 else:
Georg Brandl126c8792009-04-05 15:05:48 +00002086 try:
Eric Snow3a62d142014-01-06 20:42:59 -07002087 spec = pkgutil._get_spec(importer, modname)
Georg Brandl126c8792009-04-05 15:05:48 +00002088 except SyntaxError:
2089 # raised by tests for bad coding cookies or BOM
2090 continue
Eric Snow3a62d142014-01-06 20:42:59 -07002091 loader = spec.loader
Georg Brandl126c8792009-04-05 15:05:48 +00002092 if hasattr(loader, 'get_source'):
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002093 try:
2094 source = loader.get_source(modname)
Nick Coghlan2824cb52012-07-15 22:12:14 +10002095 except Exception:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002096 if onerror:
2097 onerror(modname)
2098 continue
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002099 desc = source_synopsis(io.StringIO(source)) or ''
Georg Brandl126c8792009-04-05 15:05:48 +00002100 if hasattr(loader, 'get_filename'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002101 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002102 else:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002103 path = None
2104 else:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002105 try:
Brett Cannon2a17bde2014-05-30 14:55:29 -04002106 module = importlib._bootstrap._load(spec)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002107 except ImportError:
2108 if onerror:
2109 onerror(modname)
2110 continue
Benjamin Peterson54237f92015-02-16 19:45:01 -05002111 desc = module.__doc__.splitlines()[0] if module.__doc__ else ''
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002112 path = getattr(module,'__file__',None)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002113 name = modname + ' - ' + desc
2114 if name.lower().find(key) >= 0:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002115 callback(path, modname, desc)
2116
2117 if completer:
2118 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002119
2120def apropos(key):
2121 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002122 def callback(path, modname, desc):
2123 if modname[-9:] == '.__init__':
2124 modname = modname[:-9] + ' (package)'
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002125 print(modname, desc and '- ' + desc)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002126 def onerror(modname):
2127 pass
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002128 with warnings.catch_warnings():
2129 warnings.filterwarnings('ignore') # ignore problems during import
2130 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002131
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002132# --------------------------------------- enhanced Web browser interface
2133
2134def _start_server(urlhandler, port):
2135 """Start an HTTP server thread on a specific port.
2136
2137 Start an HTML/text server thread, so HTML or text documents can be
2138 browsed dynamically and interactively with a Web browser. Example use:
2139
2140 >>> import time
2141 >>> import pydoc
2142
2143 Define a URL handler. To determine what the client is asking
2144 for, check the URL and content_type.
2145
2146 Then get or generate some text or HTML code and return it.
2147
2148 >>> def my_url_handler(url, content_type):
2149 ... text = 'the URL sent was: (%s, %s)' % (url, content_type)
2150 ... return text
2151
2152 Start server thread on port 0.
2153 If you use port 0, the server will pick a random port number.
2154 You can then use serverthread.port to get the port number.
2155
2156 >>> port = 0
2157 >>> serverthread = pydoc._start_server(my_url_handler, port)
2158
2159 Check that the server is really started. If it is, open browser
2160 and get first page. Use serverthread.url as the starting page.
2161
2162 >>> if serverthread.serving:
2163 ... import webbrowser
2164
2165 The next two lines are commented out so a browser doesn't open if
2166 doctest is run on this module.
2167
2168 #... webbrowser.open(serverthread.url)
2169 #True
2170
2171 Let the server do its thing. We just need to monitor its status.
2172 Use time.sleep so the loop doesn't hog the CPU.
2173
2174 >>> starttime = time.time()
2175 >>> timeout = 1 #seconds
2176
2177 This is a short timeout for testing purposes.
2178
2179 >>> while serverthread.serving:
2180 ... time.sleep(.01)
2181 ... if serverthread.serving and time.time() - starttime > timeout:
2182 ... serverthread.stop()
2183 ... break
2184
2185 Print any errors that may have occurred.
2186
2187 >>> print(serverthread.error)
2188 None
2189 """
2190 import http.server
2191 import email.message
2192 import select
2193 import threading
2194
2195 class DocHandler(http.server.BaseHTTPRequestHandler):
2196
2197 def do_GET(self):
2198 """Process a request from an HTML browser.
2199
2200 The URL received is in self.path.
2201 Get an HTML page from self.urlhandler and send it.
2202 """
2203 if self.path.endswith('.css'):
2204 content_type = 'text/css'
2205 else:
2206 content_type = 'text/html'
2207 self.send_response(200)
Georg Brandld2f38572011-01-30 08:37:19 +00002208 self.send_header('Content-Type', '%s; charset=UTF-8' % content_type)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002209 self.end_headers()
2210 self.wfile.write(self.urlhandler(
2211 self.path, content_type).encode('utf-8'))
2212
2213 def log_message(self, *args):
2214 # Don't log messages.
2215 pass
2216
2217 class DocServer(http.server.HTTPServer):
2218
2219 def __init__(self, port, callback):
Senthil Kumaran2a42a0b2014-09-17 13:17:58 +08002220 self.host = 'localhost'
2221 self.address = (self.host, port)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002222 self.callback = callback
2223 self.base.__init__(self, self.address, self.handler)
2224 self.quit = False
2225
2226 def serve_until_quit(self):
2227 while not self.quit:
2228 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2229 if rd:
2230 self.handle_request()
Victor Stinnera3abd1d2011-01-03 16:12:39 +00002231 self.server_close()
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002232
2233 def server_activate(self):
2234 self.base.server_activate(self)
2235 if self.callback:
2236 self.callback(self)
2237
2238 class ServerThread(threading.Thread):
2239
2240 def __init__(self, urlhandler, port):
2241 self.urlhandler = urlhandler
2242 self.port = int(port)
2243 threading.Thread.__init__(self)
2244 self.serving = False
2245 self.error = None
2246
2247 def run(self):
2248 """Start the server."""
2249 try:
2250 DocServer.base = http.server.HTTPServer
2251 DocServer.handler = DocHandler
2252 DocHandler.MessageClass = email.message.Message
2253 DocHandler.urlhandler = staticmethod(self.urlhandler)
2254 docsvr = DocServer(self.port, self.ready)
2255 self.docserver = docsvr
2256 docsvr.serve_until_quit()
2257 except Exception as e:
2258 self.error = e
2259
2260 def ready(self, server):
2261 self.serving = True
2262 self.host = server.host
2263 self.port = server.server_port
2264 self.url = 'http://%s:%d/' % (self.host, self.port)
2265
2266 def stop(self):
2267 """Stop the server and this thread nicely"""
2268 self.docserver.quit = True
2269 self.serving = False
2270 self.url = None
2271
2272 thread = ServerThread(urlhandler, port)
2273 thread.start()
2274 # Wait until thread.serving is True to make sure we are
2275 # really up before returning.
2276 while not thread.error and not thread.serving:
2277 time.sleep(.01)
2278 return thread
2279
2280
2281def _url_handler(url, content_type="text/html"):
2282 """The pydoc url handler for use with the pydoc server.
2283
2284 If the content_type is 'text/css', the _pydoc.css style
2285 sheet is read and returned if it exits.
2286
2287 If the content_type is 'text/html', then the result of
2288 get_html_page(url) is returned.
2289 """
2290 class _HTMLDoc(HTMLDoc):
2291
2292 def page(self, title, contents):
2293 """Format an HTML page."""
2294 css_path = "pydoc_data/_pydoc.css"
2295 css_link = (
2296 '<link rel="stylesheet" type="text/css" href="%s">' %
2297 css_path)
2298 return '''\
2299<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Georg Brandld2f38572011-01-30 08:37:19 +00002300<html><head><title>Pydoc: %s</title>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002301<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Georg Brandld2f38572011-01-30 08:37:19 +00002302%s</head><body bgcolor="#f0f0f8">%s<div style="clear:both;padding-top:.5em;">%s</div>
2303</body></html>''' % (title, css_link, html_navbar(), contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002304
2305 def filelink(self, url, path):
2306 return '<a href="getfile?key=%s">%s</a>' % (url, path)
2307
2308
2309 html = _HTMLDoc()
2310
2311 def html_navbar():
Georg Brandld2f38572011-01-30 08:37:19 +00002312 version = html.escape("%s [%s, %s]" % (platform.python_version(),
2313 platform.python_build()[0],
2314 platform.python_compiler()))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002315 return """
2316 <div style='float:left'>
Georg Brandld2f38572011-01-30 08:37:19 +00002317 Python %s<br>%s
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002318 </div>
2319 <div style='float:right'>
2320 <div style='text-align:center'>
2321 <a href="index.html">Module Index</a>
2322 : <a href="topics.html">Topics</a>
2323 : <a href="keywords.html">Keywords</a>
2324 </div>
2325 <div>
Georg Brandld2f38572011-01-30 08:37:19 +00002326 <form action="get" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002327 <input type=text name=key size=15>
2328 <input type=submit value="Get">
Georg Brandld2f38572011-01-30 08:37:19 +00002329 </form>&nbsp;
2330 <form action="search" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002331 <input type=text name=key size=15>
2332 <input type=submit value="Search">
2333 </form>
2334 </div>
2335 </div>
Georg Brandld2f38572011-01-30 08:37:19 +00002336 """ % (version, html.escape(platform.platform(terse=True)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002337
2338 def html_index():
2339 """Module Index page."""
2340
2341 def bltinlink(name):
2342 return '<a href="%s.html">%s</a>' % (name, name)
2343
2344 heading = html.heading(
2345 '<big><big><strong>Index of Modules</strong></big></big>',
2346 '#ffffff', '#7799ee')
2347 names = [name for name in sys.builtin_module_names
2348 if name != '__main__']
2349 contents = html.multicolumn(names, bltinlink)
2350 contents = [heading, '<p>' + html.bigsection(
2351 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2352
2353 seen = {}
2354 for dir in sys.path:
2355 contents.append(html.index(dir, seen))
2356
2357 contents.append(
2358 '<p align=right><font color="#909090" face="helvetica,'
2359 'arial"><strong>pydoc</strong> by Ka-Ping Yee'
2360 '&lt;ping@lfw.org&gt;</font>')
Nick Coghlanecace282010-12-03 16:08:46 +00002361 return 'Index of Modules', ''.join(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002362
2363 def html_search(key):
2364 """Search results page."""
2365 # scan for modules
2366 search_result = []
2367
2368 def callback(path, modname, desc):
2369 if modname[-9:] == '.__init__':
2370 modname = modname[:-9] + ' (package)'
2371 search_result.append((modname, desc and '- ' + desc))
2372
2373 with warnings.catch_warnings():
2374 warnings.filterwarnings('ignore') # ignore problems during import
Martin Panter9ad0aae2015-11-06 00:27:14 +00002375 def onerror(modname):
2376 pass
2377 ModuleScanner().run(callback, key, onerror=onerror)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002378
2379 # format page
2380 def bltinlink(name):
2381 return '<a href="%s.html">%s</a>' % (name, name)
2382
2383 results = []
2384 heading = html.heading(
2385 '<big><big><strong>Search Results</strong></big></big>',
2386 '#ffffff', '#7799ee')
2387 for name, desc in search_result:
2388 results.append(bltinlink(name) + desc)
2389 contents = heading + html.bigsection(
2390 'key = %s' % key, '#ffffff', '#ee77aa', '<br>'.join(results))
Nick Coghlanecace282010-12-03 16:08:46 +00002391 return 'Search Results', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002392
2393 def html_getfile(path):
2394 """Get and display a source file listing safely."""
Zachary Wareeb432142014-07-10 11:18:00 -05002395 path = urllib.parse.unquote(path)
Victor Stinner91e08772011-07-05 14:30:41 +02002396 with tokenize.open(path) as fp:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002397 lines = html.escape(fp.read())
2398 body = '<pre>%s</pre>' % lines
2399 heading = html.heading(
2400 '<big><big><strong>File Listing</strong></big></big>',
2401 '#ffffff', '#7799ee')
2402 contents = heading + html.bigsection(
2403 'File: %s' % path, '#ffffff', '#ee77aa', body)
Nick Coghlanecace282010-12-03 16:08:46 +00002404 return 'getfile %s' % path, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002405
2406 def html_topics():
2407 """Index of topic texts available."""
2408
2409 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002410 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002411
2412 heading = html.heading(
2413 '<big><big><strong>INDEX</strong></big></big>',
2414 '#ffffff', '#7799ee')
2415 names = sorted(Helper.topics.keys())
2416
2417 contents = html.multicolumn(names, bltinlink)
2418 contents = heading + html.bigsection(
2419 'Topics', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002420 return 'Topics', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002421
2422 def html_keywords():
2423 """Index of keywords."""
2424 heading = html.heading(
2425 '<big><big><strong>INDEX</strong></big></big>',
2426 '#ffffff', '#7799ee')
2427 names = sorted(Helper.keywords.keys())
2428
2429 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002430 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002431
2432 contents = html.multicolumn(names, bltinlink)
2433 contents = heading + html.bigsection(
2434 'Keywords', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002435 return 'Keywords', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002436
2437 def html_topicpage(topic):
2438 """Topic or keyword help page."""
2439 buf = io.StringIO()
2440 htmlhelp = Helper(buf, buf)
2441 contents, xrefs = htmlhelp._gettopic(topic)
2442 if topic in htmlhelp.keywords:
2443 title = 'KEYWORD'
2444 else:
2445 title = 'TOPIC'
2446 heading = html.heading(
2447 '<big><big><strong>%s</strong></big></big>' % title,
2448 '#ffffff', '#7799ee')
Georg Brandld2f38572011-01-30 08:37:19 +00002449 contents = '<pre>%s</pre>' % html.markup(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002450 contents = html.bigsection(topic , '#ffffff','#ee77aa', contents)
Georg Brandld2f38572011-01-30 08:37:19 +00002451 if xrefs:
2452 xrefs = sorted(xrefs.split())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002453
Georg Brandld2f38572011-01-30 08:37:19 +00002454 def bltinlink(name):
2455 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002456
Georg Brandld2f38572011-01-30 08:37:19 +00002457 xrefs = html.multicolumn(xrefs, bltinlink)
2458 xrefs = html.section('Related help topics: ',
2459 '#ffffff', '#ee77aa', xrefs)
Nick Coghlanecace282010-12-03 16:08:46 +00002460 return ('%s %s' % (title, topic),
2461 ''.join((heading, contents, xrefs)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002462
Georg Brandld2f38572011-01-30 08:37:19 +00002463 def html_getobj(url):
2464 obj = locate(url, forceload=1)
2465 if obj is None and url != 'None':
2466 raise ValueError('could not find object')
2467 title = describe(obj)
2468 content = html.document(obj, url)
2469 return title, content
2470
2471 def html_error(url, exc):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002472 heading = html.heading(
2473 '<big><big><strong>Error</strong></big></big>',
Georg Brandld2f38572011-01-30 08:37:19 +00002474 '#ffffff', '#7799ee')
2475 contents = '<br>'.join(html.escape(line) for line in
2476 format_exception_only(type(exc), exc))
2477 contents = heading + html.bigsection(url, '#ffffff', '#bb0000',
2478 contents)
2479 return "Error - %s" % url, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002480
2481 def get_html_page(url):
2482 """Generate an HTML page for url."""
Georg Brandld2f38572011-01-30 08:37:19 +00002483 complete_url = url
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002484 if url.endswith('.html'):
2485 url = url[:-5]
Georg Brandld2f38572011-01-30 08:37:19 +00002486 try:
2487 if url in ("", "index"):
2488 title, content = html_index()
2489 elif url == "topics":
2490 title, content = html_topics()
2491 elif url == "keywords":
2492 title, content = html_keywords()
2493 elif '=' in url:
2494 op, _, url = url.partition('=')
2495 if op == "search?key":
2496 title, content = html_search(url)
2497 elif op == "getfile?key":
2498 title, content = html_getfile(url)
2499 elif op == "topic?key":
2500 # try topics first, then objects.
2501 try:
2502 title, content = html_topicpage(url)
2503 except ValueError:
2504 title, content = html_getobj(url)
2505 elif op == "get?key":
2506 # try objects first, then topics.
2507 if url in ("", "index"):
2508 title, content = html_index()
2509 else:
2510 try:
2511 title, content = html_getobj(url)
2512 except ValueError:
2513 title, content = html_topicpage(url)
2514 else:
2515 raise ValueError('bad pydoc url')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002516 else:
Georg Brandld2f38572011-01-30 08:37:19 +00002517 title, content = html_getobj(url)
2518 except Exception as exc:
2519 # Catch any errors and display them in an error page.
2520 title, content = html_error(complete_url, exc)
2521 return html.page(title, content)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002522
2523 if url.startswith('/'):
2524 url = url[1:]
2525 if content_type == 'text/css':
2526 path_here = os.path.dirname(os.path.realpath(__file__))
Georg Brandld2f38572011-01-30 08:37:19 +00002527 css_path = os.path.join(path_here, url)
2528 with open(css_path) as fp:
2529 return ''.join(fp.readlines())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002530 elif content_type == 'text/html':
2531 return get_html_page(url)
Georg Brandld2f38572011-01-30 08:37:19 +00002532 # Errors outside the url handler are caught by the server.
2533 raise TypeError('unknown content type %r for url %s' % (content_type, url))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002534
2535
2536def browse(port=0, *, open_browser=True):
2537 """Start the enhanced pydoc Web server and open a Web browser.
2538
2539 Use port '0' to start the server on an arbitrary port.
2540 Set open_browser to False to suppress opening a browser.
2541 """
2542 import webbrowser
2543 serverthread = _start_server(_url_handler, port)
2544 if serverthread.error:
2545 print(serverthread.error)
2546 return
2547 if serverthread.serving:
2548 server_help_msg = 'Server commands: [b]rowser, [q]uit'
2549 if open_browser:
2550 webbrowser.open(serverthread.url)
2551 try:
2552 print('Server ready at', serverthread.url)
2553 print(server_help_msg)
2554 while serverthread.serving:
2555 cmd = input('server> ')
2556 cmd = cmd.lower()
2557 if cmd == 'q':
2558 break
2559 elif cmd == 'b':
2560 webbrowser.open(serverthread.url)
2561 else:
2562 print(server_help_msg)
2563 except (KeyboardInterrupt, EOFError):
2564 print()
2565 finally:
2566 if serverthread.serving:
2567 serverthread.stop()
2568 print('Server stopped')
2569
2570
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002571# -------------------------------------------------- command-line interface
2572
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002573def ispath(x):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002574 return isinstance(x, str) and x.find(os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002575
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002576def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002577 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002578 import getopt
Guido van Rossum756aa932007-04-07 03:04:01 +00002579 class BadUsage(Exception): pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002580
Nick Coghlan106274b2009-11-15 23:04:33 +00002581 # Scripts don't get the current directory in their path by default
2582 # unless they are run with the '-m' switch
2583 if '' not in sys.path:
2584 scriptdir = os.path.dirname(sys.argv[0])
2585 if scriptdir in sys.path:
2586 sys.path.remove(scriptdir)
2587 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002588
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002589 try:
Victor Stinner383c3fc2011-05-25 01:35:05 +02002590 opts, args = getopt.getopt(sys.argv[1:], 'bk:p:w')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002591 writing = False
2592 start_server = False
2593 open_browser = False
2594 port = None
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002595 for opt, val in opts:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002596 if opt == '-b':
2597 start_server = True
2598 open_browser = True
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002599 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002600 apropos(val)
2601 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002602 if opt == '-p':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002603 start_server = True
2604 port = val
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002605 if opt == '-w':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002606 writing = True
2607
Benjamin Petersonb29614e2012-10-09 11:16:03 -04002608 if start_server:
2609 if port is None:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002610 port = 0
2611 browse(port, open_browser=open_browser)
2612 return
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002613
2614 if not args: raise BadUsage
2615 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002616 if ispath(arg) and not os.path.exists(arg):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002617 print('file %r does not exist' % arg)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002618 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002619 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002620 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002621 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002622 if writing:
2623 if ispath(arg) and os.path.isdir(arg):
2624 writedocs(arg)
2625 else:
2626 writedoc(arg)
2627 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002628 help.help(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +00002629 except ErrorDuringImport as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002630 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002631
2632 except (getopt.error, BadUsage):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002633 cmd = os.path.splitext(os.path.basename(sys.argv[0]))[0]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002634 print("""pydoc - the Python documentation tool
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002635
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002636{cmd} <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002637 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002638 Python keyword, topic, function, module, or package, or a dotted
2639 reference to a class or function within a module or module in a
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002640 package. If <name> contains a '{sep}', it is used as the path to a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002641 Python source file to document. If name is 'keywords', 'topics',
2642 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002643
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002644{cmd} -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002645 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002646
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002647{cmd} -p <port>
2648 Start an HTTP server on the given port on the local machine. Port
2649 number 0 can be used to get an arbitrary unused port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002650
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002651{cmd} -b
2652 Start an HTTP server on an arbitrary unused port and open a Web browser
2653 to interactively browse documentation. The -p option can be used with
2654 the -b option to explicitly specify the server port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002655
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002656{cmd} -w <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002657 Write out the HTML documentation for a module to a file in the current
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002658 directory. If <name> contains a '{sep}', it is treated as a filename; if
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002659 it names a directory, documentation is written for all the contents.
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002660""".format(cmd=cmd, sep=os.sep))
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002661
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002662if __name__ == '__main__':
2663 cli()