blob: 220a3cb1ccc8071a3933c73b6e4048267dd8ae9d [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
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000031 http://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
Brett Cannoncb66eb02012-05-11 12:58:42 -040056import importlib.machinery
Brett Cannonf4ba4ec2013-06-15 14:25:04 -040057import importlib.util
Nick Coghlan7bb30b72010-12-03 09:29:11 +000058import inspect
Victor Stinnere6c910e2011-06-30 15:55:43 +020059import io
60import os
Nick Coghlan7bb30b72010-12-03 09:29:11 +000061import pkgutil
62import platform
63import re
Victor Stinnere6c910e2011-06-30 15:55:43 +020064import sys
Nick Coghlan7bb30b72010-12-03 09:29:11 +000065import time
Victor Stinnere6c910e2011-06-30 15:55:43 +020066import tokenize
Nick Coghlan7bb30b72010-12-03 09:29:11 +000067import warnings
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000068from collections import deque
Nick Coghlan7bb30b72010-12-03 09:29:11 +000069from reprlib import Repr
Victor Stinner7fa767e2014-03-20 09:16:38 +010070from traceback import format_exception_only
Nick Coghlan7bb30b72010-12-03 09:29:11 +000071
72
Ka-Ping Yeedd175342001-02-27 14:43:46 +000073# --------------------------------------------------------- common routines
74
Ka-Ping Yeedd175342001-02-27 14:43:46 +000075def pathdirs():
76 """Convert sys.path into a list of absolute, existing, unique paths."""
77 dirs = []
Ka-Ping Yee1d384632001-03-01 00:24:32 +000078 normdirs = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +000079 for dir in sys.path:
80 dir = os.path.abspath(dir or '.')
Ka-Ping Yee1d384632001-03-01 00:24:32 +000081 normdir = os.path.normcase(dir)
82 if normdir not in normdirs and os.path.isdir(dir):
Ka-Ping Yeedd175342001-02-27 14:43:46 +000083 dirs.append(dir)
Ka-Ping Yee1d384632001-03-01 00:24:32 +000084 normdirs.append(normdir)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000085 return dirs
86
87def getdoc(object):
88 """Get the doc string or comments for an object."""
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000089 result = inspect.getdoc(object) or inspect.getcomments(object)
Neal Norwitz9d72bb42007-04-17 08:48:32 +000090 return result and re.sub('^ *\n', '', result.rstrip()) or ''
Ka-Ping Yeedd175342001-02-27 14:43:46 +000091
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000092def splitdoc(doc):
93 """Split a doc string into a synopsis line (if any) and the rest."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +000094 lines = doc.strip().split('\n')
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000095 if len(lines) == 1:
96 return lines[0], ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +000097 elif len(lines) >= 2 and not lines[1].rstrip():
98 return lines[0], '\n'.join(lines[2:])
99 return '', '\n'.join(lines)
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000101def classname(object, modname):
102 """Get a class name and qualify it with a module name if necessary."""
103 name = object.__name__
104 if object.__module__ != modname:
105 name = object.__module__ + '.' + name
106 return name
107
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000108def isdata(object):
Georg Brandl94432422005-07-22 21:52:25 +0000109 """Check if an object is of a type that probably means it's data."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000110 return not (inspect.ismodule(object) or inspect.isclass(object) or
111 inspect.isroutine(object) or inspect.isframe(object) or
112 inspect.istraceback(object) or inspect.iscode(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000113
114def replace(text, *pairs):
115 """Do a series of global replacements on a string."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000116 while pairs:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000117 text = pairs[1].join(text.split(pairs[0]))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000118 pairs = pairs[2:]
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000119 return text
120
121def cram(text, maxlen):
122 """Omit part of a string if needed to make it fit in a maximum length."""
123 if len(text) > maxlen:
Raymond Hettingerfca3bb62002-10-21 04:44:11 +0000124 pre = max(0, (maxlen-3)//2)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000125 post = max(0, maxlen-3-pre)
126 return text[:pre] + '...' + text[len(text)-post:]
127 return text
128
Brett Cannon84601f12004-06-19 01:22:48 +0000129_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000130def stripid(text):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000131 """Remove the hexadecimal id from a Python object representation."""
Brett Cannonc6c1f472004-06-19 01:02:51 +0000132 # The behaviour of %p is implementation-dependent in terms of case.
Ezio Melotti412c95a2010-02-16 23:31:04 +0000133 return _re_stripid.sub(r'\1', text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000134
Brett Cannonc6c1f472004-06-19 01:02:51 +0000135def _is_some_method(obj):
R David Murrayac0cea52013-03-19 02:47:44 -0400136 return (inspect.isfunction(obj) or
137 inspect.ismethod(obj) or
138 inspect.isbuiltin(obj) or
139 inspect.ismethoddescriptor(obj))
Tim Peters536d2262001-09-20 05:13:38 +0000140
Larry Hastings24a882b2014-02-20 23:34:46 -0800141def _is_bound_method(fn):
142 """
143 Returns True if fn is a bound method, regardless of whether
144 fn was implemented in Python or in C.
145 """
146 if inspect.ismethod(fn):
147 return True
148 if inspect.isbuiltin(fn):
149 self = getattr(fn, '__self__', None)
150 return not (inspect.ismodule(self) or (self is None))
151 return False
152
153
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000154def allmethods(cl):
155 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000156 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000157 methods[key] = 1
158 for base in cl.__bases__:
159 methods.update(allmethods(base)) # all your base are belong to us
160 for key in methods.keys():
161 methods[key] = getattr(cl, key)
162 return methods
163
Tim Petersfa26f7c2001-09-24 08:05:11 +0000164def _split_list(s, predicate):
165 """Split sequence s via predicate, and return pair ([true], [false]).
166
167 The return value is a 2-tuple of lists,
168 ([x for x in s if predicate(x)],
169 [x for x in s if not predicate(x)])
170 """
171
Tim Peters28355492001-09-23 21:29:55 +0000172 yes = []
173 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000174 for x in s:
175 if predicate(x):
176 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000177 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000178 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000179 return yes, no
180
Raymond Hettinger1103d052011-03-25 14:15:24 -0700181def visiblename(name, all=None, obj=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000182 """Decide whether to show documentation on a variable."""
Brett Cannond340b432012-08-06 17:19:22 -0400183 # Certain special names are redundant or internal.
Eric Snowb523f842013-11-22 09:05:39 -0700184 # XXX Remove __initializing__?
Brett Cannond340b432012-08-06 17:19:22 -0400185 if name in {'__author__', '__builtins__', '__cached__', '__credits__',
Eric Snowb523f842013-11-22 09:05:39 -0700186 '__date__', '__doc__', '__file__', '__spec__',
Brett Cannond340b432012-08-06 17:19:22 -0400187 '__loader__', '__module__', '__name__', '__package__',
188 '__path__', '__qualname__', '__slots__', '__version__'}:
Raymond Hettinger68272942011-03-18 02:22:15 -0700189 return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000190 # Private names are hidden, but special names are displayed.
191 if name.startswith('__') and name.endswith('__'): return 1
Raymond Hettinger1103d052011-03-25 14:15:24 -0700192 # Namedtuples have public fields and methods with a single leading underscore
193 if name.startswith('_') and hasattr(obj, '_fields'):
194 return True
Skip Montanaroa5616d22004-06-11 04:46:12 +0000195 if all is not None:
196 # only document that which the programmer exported in __all__
197 return name in all
198 else:
199 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000200
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000201def classify_class_attrs(object):
202 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000203 results = []
204 for (name, kind, cls, value) in inspect.classify_class_attrs(object):
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000205 if inspect.isdatadescriptor(value):
206 kind = 'data descriptor'
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000207 results.append((name, kind, cls, value))
208 return results
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000209
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000210# ----------------------------------------------------- module manipulation
211
212def ispackage(path):
213 """Guess whether a path refers to a package directory."""
214 if os.path.isdir(path):
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000215 for ext in ('.py', '.pyc', '.pyo'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000216 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000217 return True
218 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000219
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000220def source_synopsis(file):
221 line = file.readline()
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000222 while line[:1] == '#' or not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000223 line = file.readline()
224 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000225 line = line.strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000226 if line[:4] == 'r"""': line = line[1:]
227 if line[:3] == '"""':
228 line = line[3:]
229 if line[-1:] == '\\': line = line[:-1]
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000230 while not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000231 line = file.readline()
232 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000233 result = line.split('"""')[0].strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000234 else: result = None
235 return result
236
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000237def synopsis(filename, cache={}):
238 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000239 mtime = os.stat(filename).st_mtime
Charles-François Natali27c4e882011-07-27 19:40:02 +0200240 lastupdate, result = cache.get(filename, (None, None))
241 if lastupdate is None or lastupdate < mtime:
Eric Snowaed5b222014-01-04 20:38:11 -0700242 # Look for binary suffixes first, falling back to source.
243 if filename.endswith(tuple(importlib.machinery.BYTECODE_SUFFIXES)):
244 loader_cls = importlib.machinery.SourcelessFileLoader
245 elif filename.endswith(tuple(importlib.machinery.EXTENSION_SUFFIXES)):
246 loader_cls = importlib.machinery.ExtensionFileLoader
247 else:
248 loader_cls = None
249 # Now handle the choice.
250 if loader_cls is None:
251 # Must be a source file.
252 try:
253 file = tokenize.open(filename)
254 except OSError:
255 # module can't be opened, so skip it
256 return None
257 # text modules can be directly examined
258 with file:
259 result = source_synopsis(file)
260 else:
261 # Must be a binary module, which has to be imported.
262 loader = loader_cls('__temp__', filename)
Eric Snow3a62d142014-01-06 20:42:59 -0700263 # XXX We probably don't need to pass in the loader here.
264 spec = importlib.util.spec_from_file_location('__temp__', filename,
265 loader=loader)
266 _spec = importlib._bootstrap._SpecMethods(spec)
Brett Cannoncb66eb02012-05-11 12:58:42 -0400267 try:
Eric Snow3a62d142014-01-06 20:42:59 -0700268 module = _spec.load()
Brett Cannoncb66eb02012-05-11 12:58:42 -0400269 except:
270 return None
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000271 del sys.modules['__temp__']
Eric Snowaed5b222014-01-04 20:38:11 -0700272 result = (module.__doc__ or '').splitlines()[0]
273 # Cache the result.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000274 cache[filename] = (mtime, result)
275 return result
276
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000277class ErrorDuringImport(Exception):
278 """Errors that occurred while trying to import something to document it."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000279 def __init__(self, filename, exc_info):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000280 self.filename = filename
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000281 self.exc, self.value, self.tb = exc_info
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000282
283 def __str__(self):
Guido van Rossuma01a8b62007-05-27 09:20:14 +0000284 exc = self.exc.__name__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000285 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000286
287def importfile(path):
288 """Import a Python source file or compiled file given its path."""
Brett Cannonf4ba4ec2013-06-15 14:25:04 -0400289 magic = importlib.util.MAGIC_NUMBER
Victor Stinnere975af62011-07-04 02:08:50 +0200290 with open(path, 'rb') as file:
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400291 is_bytecode = magic == file.read(len(magic))
292 filename = os.path.basename(path)
293 name, ext = os.path.splitext(filename)
294 if is_bytecode:
295 loader = importlib._bootstrap.SourcelessFileLoader(name, path)
296 else:
297 loader = importlib._bootstrap.SourceFileLoader(name, path)
Eric Snow3a62d142014-01-06 20:42:59 -0700298 # XXX We probably don't need to pass in the loader here.
299 spec = importlib.util.spec_from_file_location(name, path, loader=loader)
300 _spec = importlib._bootstrap._SpecMethods(spec)
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400301 try:
Eric Snow3a62d142014-01-06 20:42:59 -0700302 return _spec.load()
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400303 except:
304 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000305
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000306def safeimport(path, forceload=0, cache={}):
307 """Import a module; handle errors; return None if the module isn't found.
308
309 If the module *is* found but an exception occurs, it's wrapped in an
310 ErrorDuringImport exception and reraised. Unlike __import__, if a
311 package path is specified, the module at the end of the path is returned,
312 not the package at the beginning. If the optional 'forceload' argument
313 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000314 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000315 # If forceload is 1 and the module has been previously loaded from
316 # disk, we always have to reload the module. Checking the file's
317 # mtime isn't good enough (e.g. the module could contain a class
318 # that inherits from another module that has changed).
319 if forceload and path in sys.modules:
320 if path not in sys.builtin_module_names:
Guido van Rossume7ba4952007-06-06 23:52:48 +0000321 # Remove the module from sys.modules and re-import to try
322 # and avoid problems with partially loaded modules.
323 # Also remove any submodules because they won't appear
324 # in the newly loaded module's namespace if they're already
325 # in sys.modules.
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000326 subs = [m for m in sys.modules if m.startswith(path + '.')]
327 for key in [path] + subs:
328 # Prevent garbage collection.
329 cache[key] = sys.modules[key]
330 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000331 module = __import__(path)
332 except:
333 # Did the error occur before or after the module was found?
334 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000335 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000336 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000337 raise ErrorDuringImport(sys.modules[path].__file__, info)
338 elif exc is SyntaxError:
339 # A SyntaxError occurred before we could execute the module.
340 raise ErrorDuringImport(value.filename, info)
Brett Cannon679ecb52013-07-04 17:51:50 -0400341 elif exc is ImportError and value.name == path:
Brett Cannonfd074152012-04-14 14:10:13 -0400342 # No such module in the path.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000343 return None
344 else:
345 # Some other error occurred during the importing process.
346 raise ErrorDuringImport(path, sys.exc_info())
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000347 for part in path.split('.')[1:]:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000348 try: module = getattr(module, part)
349 except AttributeError: return None
350 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000351
352# ---------------------------------------------------- formatter base class
353
354class Doc:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000355
356 PYTHONDOCS = os.environ.get("PYTHONDOCS",
357 "http://docs.python.org/%d.%d/library"
358 % sys.version_info[:2])
359
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000360 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000361 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000362 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000363 # 'try' clause is to attempt to handle the possibility that inspect
364 # identifies something in a way that pydoc itself has issues handling;
365 # think 'super' and how it is a descriptor (which raises the exception
366 # by lacking a __name__ attribute) and an instance.
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000367 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
368 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000369 try:
370 if inspect.ismodule(object): return self.docmodule(*args)
371 if inspect.isclass(object): return self.docclass(*args)
372 if inspect.isroutine(object): return self.docroutine(*args)
373 except AttributeError:
374 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000375 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000376 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000377
378 def fail(self, object, name=None, *args):
379 """Raise an exception for unimplemented types."""
380 message = "don't know how to document object%s of type %s" % (
381 name and ' ' + repr(name), type(object).__name__)
Collin Winterce36ad82007-08-30 01:19:48 +0000382 raise TypeError(message)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000383
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000384 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000385
Skip Montanaro4997a692003-09-10 16:47:51 +0000386 def getdocloc(self, object):
387 """Return the location of module docs or None"""
388
389 try:
390 file = inspect.getabsfile(object)
391 except TypeError:
392 file = '(built-in)'
393
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000394 docloc = os.environ.get("PYTHONDOCS", self.PYTHONDOCS)
395
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100396 basedir = os.path.join(sys.base_exec_prefix, "lib",
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000397 "python%d.%d" % sys.version_info[:2])
Skip Montanaro4997a692003-09-10 16:47:51 +0000398 if (isinstance(object, type(os)) and
399 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
400 'marshal', 'posix', 'signal', 'sys',
Georg Brandl2067bfd2008-05-25 13:05:15 +0000401 '_thread', 'zipimport') or
Skip Montanaro4997a692003-09-10 16:47:51 +0000402 (file.startswith(basedir) and
Brian Curtin49c284c2010-03-31 03:19:28 +0000403 not file.startswith(os.path.join(basedir, 'site-packages')))) and
Brian Curtinedef05b2010-04-01 04:05:25 +0000404 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
Skip Montanaro4997a692003-09-10 16:47:51 +0000405 if docloc.startswith("http://"):
Georg Brandl86def6c2008-01-21 20:36:10 +0000406 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
Skip Montanaro4997a692003-09-10 16:47:51 +0000407 else:
Georg Brandl86def6c2008-01-21 20:36:10 +0000408 docloc = os.path.join(docloc, object.__name__ + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000409 else:
410 docloc = None
411 return docloc
412
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000413# -------------------------------------------- HTML documentation generator
414
415class HTMLRepr(Repr):
416 """Class for safely making an HTML representation of a Python object."""
417 def __init__(self):
418 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000419 self.maxlist = self.maxtuple = 20
420 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000421 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000422
423 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000424 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000425
426 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000427 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000428
429 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000430 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000431 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000432 if hasattr(self, methodname):
433 return getattr(self, methodname)(x, level)
434 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000435
436 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000437 test = cram(x, self.maxstring)
438 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000439 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000440 # Backslashes are only literal in the string and are never
441 # needed to make any special characters, so show a raw string.
442 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000443 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000444 r'<font color="#c040c0">\1</font>',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000445 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000446
Skip Montanarodf708782002-03-07 22:58:02 +0000447 repr_str = repr_string
448
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000449 def repr_instance(self, x, level):
450 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000451 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000452 except:
453 return self.escape('<%s instance>' % x.__class__.__name__)
454
455 repr_unicode = repr_string
456
457class HTMLDoc(Doc):
458 """Formatter class for HTML documentation."""
459
460 # ------------------------------------------- HTML formatting utilities
461
462 _repr_instance = HTMLRepr()
463 repr = _repr_instance.repr
464 escape = _repr_instance.escape
465
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000466 def page(self, title, contents):
467 """Format an HTML page."""
Georg Brandl388faac2009-04-10 08:31:48 +0000468 return '''\
Georg Brandle6066942009-04-10 08:28:28 +0000469<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000470<html><head><title>Python: %s</title>
Georg Brandl388faac2009-04-10 08:31:48 +0000471<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000472</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000473%s
474</body></html>''' % (title, contents)
475
476 def heading(self, title, fgcol, bgcol, extras=''):
477 """Format a page heading."""
478 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000479<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000480<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000481<td valign=bottom>&nbsp;<br>
482<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000483><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000484><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000485 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
486
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000487 def section(self, title, fgcol, bgcol, contents, width=6,
488 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000489 """Format a section with a heading."""
490 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000491 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000492 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000493<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000494<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000495<td colspan=3 valign=bottom>&nbsp;<br>
496<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000497 ''' % (bgcol, fgcol, title)
498 if prelude:
499 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000500<tr bgcolor="%s"><td rowspan=2>%s</td>
501<td colspan=2>%s</td></tr>
502<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
503 else:
504 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000505<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000506
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000507 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000508
509 def bigsection(self, title, *args):
510 """Format a section with a big heading."""
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000511 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000512 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000513
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000514 def preformat(self, text):
515 """Format literal preformatted text."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000516 text = self.escape(text.expandtabs())
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000517 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
518 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000519
520 def multicolumn(self, list, format, cols=4):
521 """Format a list of items into a multi-column list."""
522 result = ''
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000523 rows = (len(list)+cols-1)//cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000524 for col in range(cols):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000525 result = result + '<td width="%d%%" valign=top>' % (100//cols)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000526 for i in range(rows*col, rows*col+rows):
527 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000528 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000529 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000530 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000531
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000532 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000533
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000534 def namelink(self, name, *dicts):
535 """Make a link for an identifier, given name-to-URL mappings."""
536 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000537 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000538 return '<a href="%s">%s</a>' % (dict[name], name)
539 return name
540
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000541 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000542 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000543 name, module = object.__name__, sys.modules.get(object.__module__)
544 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000545 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000546 module.__name__, name, classname(object, modname))
547 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000548
549 def modulelink(self, object):
550 """Make a link for a module."""
551 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
552
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000553 def modpkglink(self, modpkginfo):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000554 """Make a link for a module or package to display in an index."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000555 name, path, ispackage, shadowed = modpkginfo
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000556 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000557 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000558 if path:
559 url = '%s.%s.html' % (path, name)
560 else:
561 url = '%s.html' % name
562 if ispackage:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000563 text = '<strong>%s</strong>&nbsp;(package)' % name
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000564 else:
565 text = name
566 return '<a href="%s">%s</a>' % (url, text)
567
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000568 def filelink(self, url, path):
569 """Make a link to source file."""
570 return '<a href="file:%s">%s</a>' % (url, path)
571
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000572 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
573 """Mark up some plain text, given a context of symbols to look for.
574 Each context dictionary maps object names to anchor names."""
575 escape = escape or self.escape
576 results = []
577 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000578 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
579 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000580 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000581 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000582 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000583 match = pattern.search(text, here)
584 if not match: break
585 start, end = match.span()
586 results.append(escape(text[here:start]))
587
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000588 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000589 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000590 url = escape(all).replace('"', '&quot;')
591 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000592 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000593 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
594 results.append('<a href="%s">%s</a>' % (url, escape(all)))
595 elif pep:
Christian Heimes2202f872008-02-06 14:31:34 +0000596 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000597 results.append('<a href="%s">%s</a>' % (url, escape(all)))
598 elif text[end:end+1] == '(':
599 results.append(self.namelink(name, methods, funcs, classes))
600 elif selfdot:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000601 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000602 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000603 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000604 here = end
605 results.append(escape(text[here:]))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000606 return ''.join(results)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000607
608 # ---------------------------------------------- type-specific routines
609
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000610 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000611 """Produce HTML for a class tree as given by inspect.getclasstree()."""
612 result = ''
613 for entry in tree:
614 if type(entry) is type(()):
615 c, bases = entry
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000616 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000617 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000618 if bases and bases != (parent,):
619 parents = []
620 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000621 parents.append(self.classlink(base, modname))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000622 result = result + '(' + ', '.join(parents) + ')'
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000623 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000624 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000625 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000626 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000627 return '<dl>\n%s</dl>\n' % result
628
Tim Peters8dd7ade2001-10-18 19:56:17 +0000629 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000630 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000631 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000632 try:
633 all = object.__all__
634 except AttributeError:
635 all = None
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000636 parts = name.split('.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000637 links = []
638 for i in range(len(parts)-1):
639 links.append(
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000640 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000641 ('.'.join(parts[:i+1]), parts[i]))
642 linkedname = '.'.join(links + parts[-1:])
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000643 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000644 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000645 path = inspect.getabsfile(object)
Ka-Ping Yee6191a232001-04-13 15:00:27 +0000646 url = path
647 if sys.platform == 'win32':
648 import nturl2path
649 url = nturl2path.pathname2url(path)
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000650 filelink = self.filelink(url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000651 except TypeError:
652 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000653 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000654 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000655 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000656 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000657 version = version[11:-1].strip()
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000658 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000659 if hasattr(object, '__date__'):
660 info.append(self.escape(str(object.__date__)))
661 if info:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000662 head = head + ' (%s)' % ', '.join(info)
Skip Montanaro4997a692003-09-10 16:47:51 +0000663 docloc = self.getdocloc(object)
664 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000665 docloc = '<br><a href="%(docloc)s">Module Reference</a>' % locals()
Skip Montanaro4997a692003-09-10 16:47:51 +0000666 else:
667 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000668 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000669 head, '#ffffff', '#7799ee',
670 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000671
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000672 modules = inspect.getmembers(object, inspect.ismodule)
673
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000674 classes, cdict = [], {}
675 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000676 # if __all__ exists, believe it. Otherwise use old heuristic.
677 if (all is not None or
678 (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700679 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000680 classes.append((key, value))
681 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000682 for key, value in classes:
683 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000684 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000685 module = sys.modules.get(modname)
686 if modname != name and module and hasattr(module, key):
687 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000688 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000689 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000690 funcs, fdict = [], {}
691 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000692 # if __all__ exists, believe it. Otherwise use old heuristic.
693 if (all is not None or
694 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700695 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000696 funcs.append((key, value))
697 fdict[key] = '#-' + key
698 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000699 data = []
700 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700701 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000702 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000703
704 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
705 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000706 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000707
708 if hasattr(object, '__path__'):
709 modpkgs = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000710 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
711 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000712 modpkgs.sort()
713 contents = self.multicolumn(modpkgs, self.modpkglink)
714 result = result + self.bigsection(
715 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000716 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000717 contents = self.multicolumn(
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000718 modules, lambda t: self.modulelink(t[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000719 result = result + self.bigsection(
Christian Heimes7131fd92008-02-19 14:21:46 +0000720 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000721
722 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000723 classlist = [value for (key, value) in classes]
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000724 contents = [
725 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000726 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000727 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000728 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000729 'Classes', '#ffffff', '#ee77aa', ' '.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000730 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000731 contents = []
732 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000733 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000734 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000735 'Functions', '#ffffff', '#eeaa77', ' '.join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000736 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000737 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000738 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000739 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000740 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000741 'Data', '#ffffff', '#55aa55', '<br>\n'.join(contents))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000742 if hasattr(object, '__author__'):
743 contents = self.markup(str(object.__author__), self.preformat)
744 result = result + self.bigsection(
745 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000746 if hasattr(object, '__credits__'):
747 contents = self.markup(str(object.__credits__), self.preformat)
748 result = result + self.bigsection(
749 'Credits', '#ffffff', '#7799ee', contents)
750
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000751 return result
752
Tim Peters8dd7ade2001-10-18 19:56:17 +0000753 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
754 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000755 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000756 realname = object.__name__
757 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000758 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000759
Tim Petersb47879b2001-09-24 04:47:19 +0000760 contents = []
761 push = contents.append
762
Tim Petersfa26f7c2001-09-24 08:05:11 +0000763 # Cute little class to pump out a horizontal rule between sections.
764 class HorizontalRule:
765 def __init__(self):
766 self.needone = 0
767 def maybe(self):
768 if self.needone:
769 push('<hr>\n')
770 self.needone = 1
771 hr = HorizontalRule()
772
Tim Petersc86f6ca2001-09-26 21:31:51 +0000773 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000774 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000775 if len(mro) > 2:
776 hr.maybe()
777 push('<dl><dt>Method resolution order:</dt>\n')
778 for base in mro:
779 push('<dd>%s</dd>\n' % self.classlink(base,
780 object.__module__))
781 push('</dl>\n')
782
Tim Petersb47879b2001-09-24 04:47:19 +0000783 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000784 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000785 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000786 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000787 push(msg)
788 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100789 try:
790 value = getattr(object, name)
791 except Exception:
792 # Some descriptors may meet a failure in their __get__.
793 # (bug #1785)
794 push(self._docdescriptor(name, value, mod))
795 else:
796 push(self.document(value, name, mod,
797 funcs, classes, mdict, object))
Tim Petersb47879b2001-09-24 04:47:19 +0000798 push('\n')
799 return attrs
800
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000801 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000802 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000803 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000804 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000805 push(msg)
806 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000807 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000808 return attrs
809
Tim Petersfa26f7c2001-09-24 08:05:11 +0000810 def spilldata(msg, attrs, predicate):
811 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000812 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000813 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000814 push(msg)
815 for name, kind, homecls, value in ok:
816 base = self.docother(getattr(object, name), name, mod)
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200817 if callable(value) or inspect.isdatadescriptor(value):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000818 doc = getattr(value, "__doc__", None)
819 else:
820 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000821 if doc is None:
822 push('<dl><dt>%s</dl>\n' % base)
823 else:
824 doc = self.markup(getdoc(value), self.preformat,
825 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000826 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000827 push('<dl><dt>%s%s</dl>\n' % (base, doc))
828 push('\n')
829 return attrs
830
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000831 attrs = [(name, kind, cls, value)
832 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -0700833 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000834
Tim Petersb47879b2001-09-24 04:47:19 +0000835 mdict = {}
836 for key, kind, homecls, value in attrs:
837 mdict[key] = anchor = '#' + name + '-' + key
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100838 try:
839 value = getattr(object, name)
840 except Exception:
841 # Some descriptors may meet a failure in their __get__.
842 # (bug #1785)
843 pass
Tim Petersb47879b2001-09-24 04:47:19 +0000844 try:
845 # The value may not be hashable (e.g., a data attr with
846 # a dict or list value).
847 mdict[value] = anchor
848 except TypeError:
849 pass
850
Tim Petersfa26f7c2001-09-24 08:05:11 +0000851 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000852 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000853 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000854 else:
855 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000856 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
857
Georg Brandl1a3284e2007-12-02 09:40:06 +0000858 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000859 attrs = inherited
860 continue
861 elif thisclass is object:
862 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000863 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000864 tag = 'inherited from %s' % self.classlink(thisclass,
865 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000866 tag += ':<br>\n'
867
868 # Sort attrs by name.
Raymond Hettingerd4cb56d2008-01-30 02:55:10 +0000869 attrs.sort(key=lambda t: t[0])
Tim Petersb47879b2001-09-24 04:47:19 +0000870
871 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000872 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000873 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000874 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000875 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000876 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000877 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000878 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
879 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000880 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000881 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000882 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000883 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000884
885 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000886
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000887 if name == realname:
888 title = '<a name="%s">class <strong>%s</strong></a>' % (
889 name, realname)
890 else:
891 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
892 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000893 if bases:
894 parents = []
895 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000896 parents.append(self.classlink(base, object.__module__))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000897 title = title + '(%s)' % ', '.join(parents)
Tim Peters2306d242001-09-25 03:18:32 +0000898 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000899 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000900
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000901 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000902
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000903 def formatvalue(self, object):
904 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000905 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000906
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000907 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000908 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000909 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000910 realname = object.__name__
911 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000912 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000913 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000914 skipdocs = 0
Larry Hastings24a882b2014-02-20 23:34:46 -0800915 if _is_bound_method(object):
Christian Heimesff737952007-11-27 10:40:20 +0000916 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000917 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000918 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000919 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000920 else:
Christian Heimesff737952007-11-27 10:40:20 +0000921 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000922 note = ' method of %s instance' % self.classlink(
Christian Heimesff737952007-11-27 10:40:20 +0000923 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000924 else:
925 note = ' unbound %s method' % self.classlink(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000926
927 if name == realname:
928 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
929 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000930 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000931 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000932 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000933 cl.__name__ + '-' + realname, realname)
934 skipdocs = 1
935 else:
936 reallink = realname
937 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
938 anchor, name, reallink)
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800939 argspec = None
Larry Hastings24a882b2014-02-20 23:34:46 -0800940 if inspect.isroutine(object):
Larry Hastings5c661892014-01-24 06:17:25 -0800941 try:
942 signature = inspect.signature(object)
943 except (ValueError, TypeError):
944 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800945 if signature:
946 argspec = str(signature)
947 if realname == '<lambda>':
948 title = '<strong>%s</strong> <em>lambda</em> ' % name
949 # XXX lambda's won't usually have func_annotations['return']
950 # since the syntax doesn't support but it is possible.
951 # So removing parentheses isn't truly safe.
952 argspec = argspec[1:-1] # remove parentheses
953 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +0000954 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000955
Tim Peters2306d242001-09-25 03:18:32 +0000956 decl = title + argspec + (note and self.grey(
957 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000958
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000959 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000960 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000961 else:
962 doc = self.markup(
963 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000964 doc = doc and '<dd><tt>%s</tt></dd>' % doc
965 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000966
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000967 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000968 results = []
969 push = results.append
970
971 if name:
972 push('<dl><dt><strong>%s</strong></dt>\n' % name)
973 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000974 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000975 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000976 push('</dl>\n')
977
978 return ''.join(results)
979
980 def docproperty(self, object, name=None, mod=None, cl=None):
981 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000982 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000983
Tim Peters8dd7ade2001-10-18 19:56:17 +0000984 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000985 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000986 lhs = name and '<strong>%s</strong> = ' % name or ''
987 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000988
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000989 def docdata(self, object, name=None, mod=None, cl=None):
990 """Produce html documentation for a data descriptor."""
991 return self._docdescriptor(name, object, mod)
992
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000993 def index(self, dir, shadowed=None):
994 """Generate an HTML index for a directory of modules."""
995 modpkgs = []
996 if shadowed is None: shadowed = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000997 for importer, name, ispkg in pkgutil.iter_modules([dir]):
Victor Stinner4d652242011-04-12 23:41:50 +0200998 if any((0xD800 <= ord(ch) <= 0xDFFF) for ch in name):
999 # ignore a module if its name contains a surrogate character
1000 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001001 modpkgs.append((name, '', ispkg, name in shadowed))
1002 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001003
1004 modpkgs.sort()
1005 contents = self.multicolumn(modpkgs, self.modpkglink)
1006 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
1007
1008# -------------------------------------------- text documentation generator
1009
1010class TextRepr(Repr):
1011 """Class for safely making a text representation of a Python object."""
1012 def __init__(self):
1013 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001014 self.maxlist = self.maxtuple = 20
1015 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001016 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001017
1018 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001019 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001020 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001021 if hasattr(self, methodname):
1022 return getattr(self, methodname)(x, level)
1023 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001024
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001025 def repr_string(self, x, level):
1026 test = cram(x, self.maxstring)
1027 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001028 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001029 # Backslashes are only literal in the string and are never
1030 # needed to make any special characters, so show a raw string.
1031 return 'r' + testrepr[0] + test + testrepr[0]
1032 return testrepr
1033
Skip Montanarodf708782002-03-07 22:58:02 +00001034 repr_str = repr_string
1035
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001036 def repr_instance(self, x, level):
1037 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001038 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001039 except:
1040 return '<%s instance>' % x.__class__.__name__
1041
1042class TextDoc(Doc):
1043 """Formatter class for text documentation."""
1044
1045 # ------------------------------------------- text formatting utilities
1046
1047 _repr_instance = TextRepr()
1048 repr = _repr_instance.repr
1049
1050 def bold(self, text):
1051 """Format a string in bold by overstriking."""
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001052 return ''.join(ch + '\b' + ch for ch in text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001053
1054 def indent(self, text, prefix=' '):
1055 """Indent text by prepending a given prefix to each line."""
1056 if not text: return ''
Collin Winter72e110c2007-07-17 00:27:30 +00001057 lines = [prefix + line for line in text.split('\n')]
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001058 if lines: lines[-1] = lines[-1].rstrip()
1059 return '\n'.join(lines)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001060
1061 def section(self, title, contents):
1062 """Format a section with a given heading."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001063 clean_contents = self.indent(contents).rstrip()
1064 return self.bold(title) + '\n' + clean_contents + '\n\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001065
1066 # ---------------------------------------------- type-specific routines
1067
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001068 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001069 """Render in text a class tree as returned by inspect.getclasstree()."""
1070 result = ''
1071 for entry in tree:
1072 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001073 c, bases = entry
1074 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001075 if bases and bases != (parent,):
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001076 parents = (classname(c, modname) for c in bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001077 result = result + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001078 result = result + '\n'
1079 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001080 result = result + self.formattree(
1081 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001082 return result
1083
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001084 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001085 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001086 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001087 synop, desc = splitdoc(getdoc(object))
1088 result = self.section('NAME', name + (synop and ' - ' + synop))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001089 all = getattr(object, '__all__', None)
Skip Montanaro4997a692003-09-10 16:47:51 +00001090 docloc = self.getdocloc(object)
1091 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001092 result = result + self.section('MODULE REFERENCE', docloc + """
1093
Éric Araujo647ef8c2011-09-11 00:43:20 +02001094The following documentation is automatically generated from the Python
1095source files. It may be incomplete, incorrect or include features that
1096are considered implementation detail and may vary between Python
1097implementations. When in doubt, consult the module reference at the
1098location listed above.
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001099""")
Skip Montanaro4997a692003-09-10 16:47:51 +00001100
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001101 if desc:
1102 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001103
1104 classes = []
1105 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001106 # if __all__ exists, believe it. Otherwise use old heuristic.
1107 if (all is not None
1108 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001109 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001110 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001111 funcs = []
1112 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001113 # if __all__ exists, believe it. Otherwise use old heuristic.
1114 if (all is not None or
1115 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001116 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001117 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001118 data = []
1119 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001120 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001121 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001122
Christian Heimes1af737c2008-01-23 08:24:23 +00001123 modpkgs = []
1124 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001125 if hasattr(object, '__path__'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001126 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Christian Heimes1af737c2008-01-23 08:24:23 +00001127 modpkgs_names.add(modname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001128 if ispkg:
1129 modpkgs.append(modname + ' (package)')
1130 else:
1131 modpkgs.append(modname)
1132
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001133 modpkgs.sort()
1134 result = result + self.section(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001135 'PACKAGE CONTENTS', '\n'.join(modpkgs))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001136
Christian Heimes1af737c2008-01-23 08:24:23 +00001137 # Detect submodules as sometimes created by C extensions
1138 submodules = []
1139 for key, value in inspect.getmembers(object, inspect.ismodule):
1140 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1141 submodules.append(key)
1142 if submodules:
1143 submodules.sort()
1144 result = result + self.section(
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001145 'SUBMODULES', '\n'.join(submodules))
Christian Heimes1af737c2008-01-23 08:24:23 +00001146
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001147 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001148 classlist = [value for key, value in classes]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001149 contents = [self.formattree(
1150 inspect.getclasstree(classlist, 1), name)]
1151 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001152 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001153 result = result + self.section('CLASSES', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001154
1155 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001156 contents = []
1157 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001158 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001159 result = result + self.section('FUNCTIONS', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001160
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001161 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001162 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001163 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001164 contents.append(self.docother(value, key, name, maxlen=70))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001165 result = result + self.section('DATA', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001166
1167 if hasattr(object, '__version__'):
1168 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001169 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001170 version = version[11:-1].strip()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001171 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001172 if hasattr(object, '__date__'):
1173 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001174 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001175 result = result + self.section('AUTHOR', str(object.__author__))
1176 if hasattr(object, '__credits__'):
1177 result = result + self.section('CREDITS', str(object.__credits__))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001178 try:
1179 file = inspect.getabsfile(object)
1180 except TypeError:
1181 file = '(built-in)'
1182 result = result + self.section('FILE', file)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001183 return result
1184
Georg Brandl9bd45f992010-12-03 09:58:38 +00001185 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001186 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001187 realname = object.__name__
1188 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001189 bases = object.__bases__
1190
Tim Petersc86f6ca2001-09-26 21:31:51 +00001191 def makename(c, m=object.__module__):
1192 return classname(c, m)
1193
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001194 if name == realname:
1195 title = 'class ' + self.bold(realname)
1196 else:
1197 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001198 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001199 parents = map(makename, bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001200 title = title + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001201
1202 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001203 contents = doc and [doc + '\n'] or []
1204 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001205
Tim Petersc86f6ca2001-09-26 21:31:51 +00001206 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001207 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001208 if len(mro) > 2:
1209 push("Method resolution order:")
1210 for base in mro:
1211 push(' ' + makename(base))
1212 push('')
1213
Tim Petersf4aad8e2001-09-24 22:40:47 +00001214 # Cute little class to pump out a horizontal rule between sections.
1215 class HorizontalRule:
1216 def __init__(self):
1217 self.needone = 0
1218 def maybe(self):
1219 if self.needone:
1220 push('-' * 70)
1221 self.needone = 1
1222 hr = HorizontalRule()
1223
Tim Peters28355492001-09-23 21:29:55 +00001224 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001225 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001226 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001227 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001228 push(msg)
1229 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001230 try:
1231 value = getattr(object, name)
1232 except Exception:
1233 # Some descriptors may meet a failure in their __get__.
1234 # (bug #1785)
1235 push(self._docdescriptor(name, value, mod))
1236 else:
1237 push(self.document(value,
1238 name, mod, object))
Tim Peters28355492001-09-23 21:29:55 +00001239 return attrs
1240
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001241 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001242 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001243 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001244 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001245 push(msg)
1246 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001247 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001248 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001249
Tim Petersfa26f7c2001-09-24 08:05:11 +00001250 def spilldata(msg, attrs, predicate):
1251 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001252 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001253 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001254 push(msg)
1255 for name, kind, homecls, value in ok:
Florent Xicluna5d1155c2011-10-28 14:45:05 +02001256 if callable(value) or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001257 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001258 else:
1259 doc = None
Serhiy Storchaka056eb022014-02-19 23:05:12 +02001260 try:
1261 obj = getattr(object, name)
1262 except AttributeError:
1263 obj = homecls.__dict__[name]
1264 push(self.docother(obj, name, mod, maxlen=70, doc=doc) +
1265 '\n')
Tim Peters28355492001-09-23 21:29:55 +00001266 return attrs
1267
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001268 attrs = [(name, kind, cls, value)
1269 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -07001270 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001271
Tim Petersfa26f7c2001-09-24 08:05:11 +00001272 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001273 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001274 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001275 else:
1276 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001277 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1278
Georg Brandl1a3284e2007-12-02 09:40:06 +00001279 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001280 attrs = inherited
1281 continue
1282 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001283 tag = "defined here"
1284 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001285 tag = "inherited from %s" % classname(thisclass,
1286 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001287 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001288 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001289
1290 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001291 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001292 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001293 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001294 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001295 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001296 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001297 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1298 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001299 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1300 lambda t: t[1] == 'data')
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001301
Tim Peters28355492001-09-23 21:29:55 +00001302 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001303 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001304
1305 contents = '\n'.join(contents)
1306 if not contents:
1307 return title + '\n'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001308 return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001309
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001310 def formatvalue(self, object):
1311 """Format an argument default value as text."""
1312 return '=' + self.repr(object)
1313
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001314 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001315 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001316 realname = object.__name__
1317 name = name or realname
1318 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001319 skipdocs = 0
Larry Hastings24a882b2014-02-20 23:34:46 -08001320 if _is_bound_method(object):
Christian Heimesff737952007-11-27 10:40:20 +00001321 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001322 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001323 if imclass is not cl:
1324 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001325 else:
Christian Heimesff737952007-11-27 10:40:20 +00001326 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001327 note = ' method of %s instance' % classname(
Christian Heimesff737952007-11-27 10:40:20 +00001328 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001329 else:
1330 note = ' unbound %s method' % classname(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001331
1332 if name == realname:
1333 title = self.bold(realname)
1334 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001335 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001336 cl.__dict__[realname] is object):
1337 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001338 title = self.bold(name) + ' = ' + realname
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001339 argspec = None
Larry Hastings5c661892014-01-24 06:17:25 -08001340
1341 if inspect.isroutine(object):
1342 try:
1343 signature = inspect.signature(object)
1344 except (ValueError, TypeError):
1345 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001346 if signature:
1347 argspec = str(signature)
1348 if realname == '<lambda>':
1349 title = self.bold(name) + ' lambda '
1350 # XXX lambda's won't usually have func_annotations['return']
1351 # since the syntax doesn't support but it is possible.
1352 # So removing parentheses isn't truly safe.
1353 argspec = argspec[1:-1] # remove parentheses
1354 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +00001355 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001356 decl = title + argspec + note
1357
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001358 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001359 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001360 else:
1361 doc = getdoc(object) or ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001362 return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001363
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001364 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001365 results = []
1366 push = results.append
1367
1368 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001369 push(self.bold(name))
1370 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001371 doc = getdoc(value) or ''
1372 if doc:
1373 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001374 push('\n')
1375 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001376
1377 def docproperty(self, object, name=None, mod=None, cl=None):
1378 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001379 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001380
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001381 def docdata(self, object, name=None, mod=None, cl=None):
1382 """Produce text documentation for a data descriptor."""
1383 return self._docdescriptor(name, object, mod)
1384
Georg Brandl8b813db2005-10-01 16:32:31 +00001385 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001386 """Produce text documentation for a data object."""
1387 repr = self.repr(object)
1388 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001389 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001390 chop = maxlen - len(line)
1391 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001392 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001393 if doc is not None:
1394 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001395 return line
1396
Georg Brandld80d5f42010-12-03 07:47:22 +00001397class _PlainTextDoc(TextDoc):
1398 """Subclass of TextDoc which overrides string styling"""
1399 def bold(self, text):
1400 return text
1401
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001402# --------------------------------------------------------- user interfaces
1403
1404def pager(text):
1405 """The first time this is called, determine what kind of pager to use."""
1406 global pager
Victor Stinner0cc45ba2014-05-13 02:05:35 +02001407 # Escape non-encodable characters to avoid encoding errors later
1408 encoding = sys.getfilesystemencoding()
1409 text = text.encode(encoding, 'backslashreplace').decode(encoding)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001410 pager = getpager()
1411 pager(text)
1412
1413def getpager():
1414 """Decide what method to use for paging through text."""
Guido van Rossuma01a8b62007-05-27 09:20:14 +00001415 if not hasattr(sys.stdout, "isatty"):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001416 return plainpager
1417 if not sys.stdin.isatty() or not sys.stdout.isatty():
1418 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001419 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001420 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001421 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001422 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001423 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001424 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001425 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001426 if os.environ.get('TERM') in ('dumb', 'emacs'):
1427 return plainpager
Jesus Cea4791a242012-10-05 03:15:39 +02001428 if sys.platform == 'win32':
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001429 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001430 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001431 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001432
1433 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001434 (fd, filename) = tempfile.mkstemp()
1435 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001436 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001437 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001438 return lambda text: pipepager(text, 'more')
1439 else:
1440 return ttypager
1441 finally:
1442 os.unlink(filename)
1443
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001444def plain(text):
1445 """Remove boldface formatting from text."""
1446 return re.sub('.\b', '', text)
1447
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001448def pipepager(text, cmd):
1449 """Page through text by feeding it to another program."""
1450 pipe = os.popen(cmd, 'w')
1451 try:
1452 pipe.write(text)
1453 pipe.close()
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001454 except OSError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001455 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001456
1457def tempfilepager(text, cmd):
1458 """Page through text by invoking a program on a temporary file."""
1459 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001460 filename = tempfile.mktemp()
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +01001461 with open(filename, 'w') as file:
1462 file.write(text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001463 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001464 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001465 finally:
1466 os.unlink(filename)
1467
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001468def ttypager(text):
1469 """Page through text on a text terminal."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001470 lines = plain(text).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001471 try:
1472 import tty
1473 fd = sys.stdin.fileno()
1474 old = tty.tcgetattr(fd)
1475 tty.setcbreak(fd)
1476 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001477 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001478 tty = None
1479 getchar = lambda: sys.stdin.readline()[:-1][:1]
1480
1481 try:
1482 r = inc = os.environ.get('LINES', 25) - 1
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001483 sys.stdout.write('\n'.join(lines[:inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001484 while lines[r:]:
1485 sys.stdout.write('-- more --')
1486 sys.stdout.flush()
1487 c = getchar()
1488
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001489 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001490 sys.stdout.write('\r \r')
1491 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001492 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001493 sys.stdout.write('\r \r' + lines[r] + '\n')
1494 r = r + 1
1495 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001496 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001497 r = r - inc - inc
1498 if r < 0: r = 0
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001499 sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001500 r = r + inc
1501
1502 finally:
1503 if tty:
1504 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1505
1506def plainpager(text):
1507 """Simply print unformatted text. This is the ultimate fallback."""
1508 sys.stdout.write(plain(text))
1509
1510def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001511 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001512 if inspect.ismodule(thing):
1513 if thing.__name__ in sys.builtin_module_names:
1514 return 'built-in module ' + thing.__name__
1515 if hasattr(thing, '__path__'):
1516 return 'package ' + thing.__name__
1517 else:
1518 return 'module ' + thing.__name__
1519 if inspect.isbuiltin(thing):
1520 return 'built-in function ' + thing.__name__
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001521 if inspect.isgetsetdescriptor(thing):
1522 return 'getset descriptor %s.%s.%s' % (
1523 thing.__objclass__.__module__, thing.__objclass__.__name__,
1524 thing.__name__)
1525 if inspect.ismemberdescriptor(thing):
1526 return 'member descriptor %s.%s.%s' % (
1527 thing.__objclass__.__module__, thing.__objclass__.__name__,
1528 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001529 if inspect.isclass(thing):
1530 return 'class ' + thing.__name__
1531 if inspect.isfunction(thing):
1532 return 'function ' + thing.__name__
1533 if inspect.ismethod(thing):
1534 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001535 return type(thing).__name__
1536
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001537def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001538 """Locate an object by name or dotted path, importing as necessary."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001539 parts = [part for part in path.split('.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001540 module, n = None, 0
1541 while n < len(parts):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001542 nextmodule = safeimport('.'.join(parts[:n+1]), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001543 if nextmodule: module, n = nextmodule, n + 1
1544 else: break
1545 if module:
1546 object = module
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001547 else:
Éric Araujoe64e51b2011-07-29 17:03:55 +02001548 object = builtins
1549 for part in parts[n:]:
1550 try:
1551 object = getattr(object, part)
1552 except AttributeError:
1553 return None
1554 return object
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001555
1556# --------------------------------------- interactive interpreter interface
1557
1558text = TextDoc()
Georg Brandld80d5f42010-12-03 07:47:22 +00001559plaintext = _PlainTextDoc()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001560html = HTMLDoc()
1561
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001562def resolve(thing, forceload=0):
1563 """Given an object or a path to an object, get the object and its name."""
1564 if isinstance(thing, str):
1565 object = locate(thing, forceload)
1566 if not object:
Collin Winterce36ad82007-08-30 01:19:48 +00001567 raise ImportError('no Python documentation found for %r' % thing)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001568 return object, thing
1569 else:
R David Murrayc43125a2012-04-23 13:23:57 -04001570 name = getattr(thing, '__name__', None)
1571 return thing, name if isinstance(name, str) else None
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001572
Georg Brandld80d5f42010-12-03 07:47:22 +00001573def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
1574 renderer=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001575 """Render text documentation, given an object or a path to an object."""
Georg Brandld80d5f42010-12-03 07:47:22 +00001576 if renderer is None:
1577 renderer = text
Guido van Rossumd8faa362007-04-27 19:54:29 +00001578 object, name = resolve(thing, forceload)
1579 desc = describe(object)
1580 module = inspect.getmodule(object)
1581 if name and '.' in name:
1582 desc += ' in ' + name[:name.rfind('.')]
1583 elif module and module is not object:
1584 desc += ' in module ' + module.__name__
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001585
1586 if not (inspect.ismodule(object) or
Guido van Rossumd8faa362007-04-27 19:54:29 +00001587 inspect.isclass(object) or
1588 inspect.isroutine(object) or
1589 inspect.isgetsetdescriptor(object) or
1590 inspect.ismemberdescriptor(object) or
1591 isinstance(object, property)):
1592 # If the passed object is a piece of data or an instance,
1593 # document its available methods instead of its value.
1594 object = type(object)
1595 desc += ' object'
Georg Brandld80d5f42010-12-03 07:47:22 +00001596 return title % desc + '\n\n' + renderer.document(object, name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001597
Georg Brandld80d5f42010-12-03 07:47:22 +00001598def doc(thing, title='Python Library Documentation: %s', forceload=0,
1599 output=None):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001600 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001601 try:
Georg Brandld80d5f42010-12-03 07:47:22 +00001602 if output is None:
1603 pager(render_doc(thing, title, forceload))
1604 else:
1605 output.write(render_doc(thing, title, forceload, plaintext))
Guido van Rossumb940e112007-01-10 16:19:56 +00001606 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001607 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001608
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001609def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001610 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001611 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001612 object, name = resolve(thing, forceload)
1613 page = html.page(describe(object), html.document(object, name))
Georg Brandl388faac2009-04-10 08:31:48 +00001614 file = open(name + '.html', 'w', encoding='utf-8')
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001615 file.write(page)
1616 file.close()
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001617 print('wrote', name + '.html')
Guido van Rossumb940e112007-01-10 16:19:56 +00001618 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001619 print(value)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001620
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001621def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001622 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001623 if done is None: done = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001624 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1625 writedoc(modname)
1626 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001627
1628class Helper:
Georg Brandl6b38daa2008-06-01 21:05:17 +00001629
1630 # These dictionaries map a topic name to either an alias, or a tuple
1631 # (label, seealso-items). The "label" is the label of the corresponding
1632 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl5617db82009-04-27 16:28:57 +00001633 # in pydoc_data/topics.py.
Georg Brandl6b38daa2008-06-01 21:05:17 +00001634 #
1635 # CAUTION: if you change one of these dictionaries, be sure to adapt the
1636 # list of needed labels in Doc/tools/sphinxext/pyspecific.py and
Georg Brandl5617db82009-04-27 16:28:57 +00001637 # regenerate the pydoc_data/topics.py file by running
Georg Brandl6b38daa2008-06-01 21:05:17 +00001638 # make pydoc-topics
1639 # in Doc/ and copying the output file into the Lib/ directory.
1640
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001641 keywords = {
Ezio Melottib185a042011-04-28 07:42:55 +03001642 'False': '',
1643 'None': '',
1644 'True': '',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001645 'and': 'BOOLEAN',
Guido van Rossumd8faa362007-04-27 19:54:29 +00001646 'as': 'with',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001647 'assert': ('assert', ''),
1648 'break': ('break', 'while for'),
1649 'class': ('class', 'CLASSES SPECIALMETHODS'),
1650 'continue': ('continue', 'while for'),
1651 'def': ('function', ''),
1652 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001653 'elif': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001654 'else': ('else', 'while for'),
Georg Brandl0d855392008-08-30 19:53:05 +00001655 'except': 'try',
1656 'finally': 'try',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001657 'for': ('for', 'break continue while'),
Georg Brandl0d855392008-08-30 19:53:05 +00001658 'from': 'import',
Georg Brandl74abf6f2010-11-20 19:54:36 +00001659 'global': ('global', 'nonlocal NAMESPACES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001660 'if': ('if', 'TRUTHVALUE'),
1661 'import': ('import', 'MODULES'),
Georg Brandl395ed242009-09-04 08:07:32 +00001662 'in': ('in', 'SEQUENCEMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001663 'is': 'COMPARISON',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001664 'lambda': ('lambda', 'FUNCTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001665 'nonlocal': ('nonlocal', 'global NAMESPACES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001666 'not': 'BOOLEAN',
1667 'or': 'BOOLEAN',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001668 'pass': ('pass', ''),
1669 'raise': ('raise', 'EXCEPTIONS'),
1670 'return': ('return', 'FUNCTIONS'),
1671 'try': ('try', 'EXCEPTIONS'),
1672 'while': ('while', 'break continue if TRUTHVALUE'),
1673 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1674 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001675 }
Georg Brandldb7b6b92009-01-01 15:53:14 +00001676 # Either add symbols to this dictionary or to the symbols dictionary
1677 # directly: Whichever is easier. They are merged later.
1678 _symbols_inverse = {
1679 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'),
1680 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1681 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1682 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1683 'UNARY' : ('-', '~'),
1684 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1685 '^=', '<<=', '>>=', '**=', '//='),
1686 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1687 'COMPLEX' : ('j', 'J')
1688 }
1689 symbols = {
1690 '%': 'OPERATORS FORMATTING',
1691 '**': 'POWER',
1692 ',': 'TUPLES LISTS FUNCTIONS',
1693 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1694 '...': 'ELLIPSIS',
1695 ':': 'SLICINGS DICTIONARYLITERALS',
1696 '@': 'def class',
1697 '\\': 'STRINGS',
1698 '_': 'PRIVATENAMES',
1699 '__': 'PRIVATENAMES SPECIALMETHODS',
1700 '`': 'BACKQUOTES',
1701 '(': 'TUPLES FUNCTIONS CALLS',
1702 ')': 'TUPLES FUNCTIONS CALLS',
1703 '[': 'LISTS SUBSCRIPTS SLICINGS',
1704 ']': 'LISTS SUBSCRIPTS SLICINGS'
1705 }
1706 for topic, symbols_ in _symbols_inverse.items():
1707 for symbol in symbols_:
1708 topics = symbols.get(symbol, topic)
1709 if topic not in topics:
1710 topics = topics + ' ' + topic
1711 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001712
1713 topics = {
Georg Brandl6b38daa2008-06-01 21:05:17 +00001714 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1715 'FUNCTIONS CLASSES MODULES FILES inspect'),
1716 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS '
1717 'FORMATTING TYPES'),
1718 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1719 'FORMATTING': ('formatstrings', 'OPERATORS'),
1720 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1721 'FORMATTING TYPES'),
1722 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1723 'INTEGER': ('integers', 'int range'),
1724 'FLOAT': ('floating', 'float math'),
1725 'COMPLEX': ('imaginary', 'complex cmath'),
1726 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING range LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001727 'MAPPINGS': 'DICTIONARIES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001728 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1729 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1730 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1731 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001732 'FRAMEOBJECTS': 'TYPES',
1733 'TRACEBACKS': 'TYPES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001734 'NONE': ('bltin-null-object', ''),
1735 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001736 'SPECIALATTRIBUTES': ('specialattrs', ''),
1737 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1738 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001739 'PACKAGES': 'import',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001740 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1741 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1742 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1743 'LISTS DICTIONARIES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001744 'OPERATORS': 'EXPRESSIONS',
1745 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001746 'OBJECTS': ('objects', 'TYPES'),
1747 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
Georg Brandl395ed242009-09-04 08:07:32 +00001748 'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS '
1749 'NUMBERMETHODS CLASSES'),
Mark Dickinsona56c4672009-01-27 18:17:45 +00001750 'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001751 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1752 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001753 'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS '
Georg Brandl6b38daa2008-06-01 21:05:17 +00001754 'SPECIALMETHODS'),
1755 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1756 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1757 'SPECIALMETHODS'),
1758 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001759 'NAMESPACES': ('naming', 'global nonlocal ASSIGNMENT DELETION DYNAMICFEATURES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001760 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001761 'SCOPING': 'NAMESPACES',
1762 'FRAMES': 'NAMESPACES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001763 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1764 'CONVERSIONS': ('conversions', ''),
1765 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1766 'SPECIALIDENTIFIERS': ('id-classes', ''),
1767 'PRIVATENAMES': ('atom-identifiers', ''),
1768 'LITERALS': ('atom-literals', 'STRINGS NUMBERS TUPLELITERALS '
1769 'LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001770 'TUPLES': 'SEQUENCES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001771 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1772 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1773 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1774 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1775 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1776 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001777 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'),
1778 'SLICINGS': ('slicings', 'SEQUENCEMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001779 'CALLS': ('calls', 'EXPRESSIONS'),
1780 'POWER': ('power', 'EXPRESSIONS'),
1781 'UNARY': ('unary', 'EXPRESSIONS'),
1782 'BINARY': ('binary', 'EXPRESSIONS'),
1783 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1784 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1785 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1786 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001787 'ASSERTION': 'assert',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001788 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1789 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001790 'DELETION': 'del',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001791 'RETURNING': 'return',
1792 'IMPORTING': 'import',
1793 'CONDITIONAL': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001794 'LOOPING': ('compound', 'for while break continue'),
1795 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1796 'DEBUGGING': ('debugger', 'pdb'),
1797 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001798 }
1799
Georg Brandl78aa3962010-07-31 21:51:48 +00001800 def __init__(self, input=None, output=None):
1801 self._input = input
1802 self._output = output
1803
Georg Brandl76ae3972010-08-01 06:32:55 +00001804 input = property(lambda self: self._input or sys.stdin)
1805 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001806
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001807 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001808 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001809 self()
1810 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001811 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001812
Alexander Belopolsky2e733c92010-07-04 17:00:20 +00001813 _GoInteractive = object()
1814 def __call__(self, request=_GoInteractive):
1815 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001816 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001817 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001818 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001819 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001820 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001821You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001822If you want to ask for help on a particular object directly from the
1823interpreter, you can type "help(object)". Executing "help('string')"
1824has the same effect as typing a particular string at the help> prompt.
1825''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001826
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001827 def interact(self):
1828 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001829 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001830 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001831 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001832 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001833 except (KeyboardInterrupt, EOFError):
1834 break
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001835 request = replace(request, '"', '', "'", '').strip()
1836 if request.lower() in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001837 self.help(request)
1838
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001839 def getline(self, prompt):
Guido van Rossum7c086c02008-01-02 03:52:38 +00001840 """Read one line, using input() when appropriate."""
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001841 if self.input is sys.stdin:
Guido van Rossum7c086c02008-01-02 03:52:38 +00001842 return input(prompt)
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001843 else:
1844 self.output.write(prompt)
1845 self.output.flush()
1846 return self.input.readline()
1847
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001848 def help(self, request):
1849 if type(request) is type(''):
R. David Murray1f1b9d32009-05-27 20:56:59 +00001850 request = request.strip()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001851 if request == 'help': self.intro()
1852 elif request == 'keywords': self.listkeywords()
Georg Brandldb7b6b92009-01-01 15:53:14 +00001853 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001854 elif request == 'topics': self.listtopics()
1855 elif request == 'modules': self.listmodules()
1856 elif request[:8] == 'modules ':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001857 self.listmodules(request.split()[1])
Georg Brandldb7b6b92009-01-01 15:53:14 +00001858 elif request in self.symbols: self.showsymbol(request)
Ezio Melottib185a042011-04-28 07:42:55 +03001859 elif request in ['True', 'False', 'None']:
1860 # special case these keywords since they are objects too
1861 doc(eval(request), 'Help on %s:')
Raymond Hettinger54f02222002-06-01 14:18:47 +00001862 elif request in self.keywords: self.showtopic(request)
1863 elif request in self.topics: self.showtopic(request)
Georg Brandld80d5f42010-12-03 07:47:22 +00001864 elif request: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001865 elif isinstance(request, Helper): self()
Georg Brandld80d5f42010-12-03 07:47:22 +00001866 else: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001867 self.output.write('\n')
1868
1869 def intro(self):
1870 self.output.write('''
R David Murray3d050dd2014-04-19 12:59:30 -04001871Welcome to Python %s's help utility!
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001872
1873If this is your first time using Python, you should definitely check out
R David Murrayde0f6292012-03-31 12:06:35 -04001874the tutorial on the Internet at http://docs.python.org/%s/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001875
1876Enter the name of any module, keyword, or topic to get help on writing
1877Python programs and using Python modules. To quit this help utility and
1878return to the interpreter, just type "quit".
1879
Terry Jan Reedy34200572013-02-11 02:23:13 -05001880To get a list of available modules, keywords, symbols, or topics, type
1881"modules", "keywords", "symbols", or "topics". Each module also comes
1882with a one-line summary of what it does; to list the modules whose name
1883or summary contain a given string such as "spam", type "modules spam".
R David Murrayde0f6292012-03-31 12:06:35 -04001884''' % tuple([sys.version[:3]]*2))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001885
1886 def list(self, items, columns=4, width=80):
Guido van Rossum486364b2007-06-30 05:01:58 +00001887 items = list(sorted(items))
1888 colw = width // columns
1889 rows = (len(items) + columns - 1) // columns
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001890 for row in range(rows):
1891 for col in range(columns):
1892 i = col * rows + row
1893 if i < len(items):
1894 self.output.write(items[i])
1895 if col < columns - 1:
Guido van Rossum486364b2007-06-30 05:01:58 +00001896 self.output.write(' ' + ' ' * (colw - 1 - len(items[i])))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001897 self.output.write('\n')
1898
1899 def listkeywords(self):
1900 self.output.write('''
1901Here is a list of the Python keywords. Enter any keyword to get more help.
1902
1903''')
1904 self.list(self.keywords.keys())
1905
Georg Brandldb7b6b92009-01-01 15:53:14 +00001906 def listsymbols(self):
1907 self.output.write('''
1908Here is a list of the punctuation symbols which Python assigns special meaning
1909to. Enter any symbol to get more help.
1910
1911''')
1912 self.list(self.symbols.keys())
1913
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001914 def listtopics(self):
1915 self.output.write('''
1916Here is a list of available topics. Enter any topic name to get more help.
1917
1918''')
1919 self.list(self.topics.keys())
1920
Georg Brandldb7b6b92009-01-01 15:53:14 +00001921 def showtopic(self, topic, more_xrefs=''):
Georg Brandl6b38daa2008-06-01 21:05:17 +00001922 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001923 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04001924 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001925 self.output.write('''
Georg Brandl6b38daa2008-06-01 21:05:17 +00001926Sorry, topic and keyword documentation is not available because the
Georg Brandl5617db82009-04-27 16:28:57 +00001927module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001928''')
1929 return
1930 target = self.topics.get(topic, self.keywords.get(topic))
1931 if not target:
1932 self.output.write('no documentation found for %s\n' % repr(topic))
1933 return
1934 if type(target) is type(''):
Georg Brandldb7b6b92009-01-01 15:53:14 +00001935 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001936
Georg Brandl6b38daa2008-06-01 21:05:17 +00001937 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001938 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001939 doc = pydoc_data.topics.topics[label]
Georg Brandl6b38daa2008-06-01 21:05:17 +00001940 except KeyError:
1941 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001942 return
Georg Brandl6b38daa2008-06-01 21:05:17 +00001943 pager(doc.strip() + '\n')
Georg Brandldb7b6b92009-01-01 15:53:14 +00001944 if more_xrefs:
1945 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001946 if xrefs:
Brett Cannon1448ecf2013-10-04 11:38:59 -04001947 import textwrap
1948 text = 'Related help topics: ' + ', '.join(xrefs.split()) + '\n'
1949 wrapped_text = textwrap.wrap(text, 72)
1950 self.output.write('\n%s\n' % ''.join(wrapped_text))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001951
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001952 def _gettopic(self, topic, more_xrefs=''):
1953 """Return unbuffered tuple of (topic, xrefs).
1954
Georg Brandld2f38572011-01-30 08:37:19 +00001955 If an error occurs here, the exception is caught and displayed by
1956 the url handler.
1957
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001958 This function duplicates the showtopic method but returns its
1959 result directly so it can be formatted for display in an html page.
1960 """
1961 try:
1962 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04001963 except ImportError:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001964 return('''
1965Sorry, topic and keyword documentation is not available because the
1966module "pydoc_data.topics" could not be found.
1967''' , '')
1968 target = self.topics.get(topic, self.keywords.get(topic))
1969 if not target:
Georg Brandld2f38572011-01-30 08:37:19 +00001970 raise ValueError('could not find topic')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001971 if isinstance(target, str):
1972 return self._gettopic(target, more_xrefs)
1973 label, xrefs = target
Georg Brandld2f38572011-01-30 08:37:19 +00001974 doc = pydoc_data.topics.topics[label]
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001975 if more_xrefs:
1976 xrefs = (xrefs or '') + ' ' + more_xrefs
1977 return doc, xrefs
1978
Georg Brandldb7b6b92009-01-01 15:53:14 +00001979 def showsymbol(self, symbol):
1980 target = self.symbols[symbol]
1981 topic, _, xrefs = target.partition(' ')
1982 self.showtopic(topic, xrefs)
1983
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001984 def listmodules(self, key=''):
1985 if key:
1986 self.output.write('''
Terry Jan Reedy34200572013-02-11 02:23:13 -05001987Here is a list of modules whose name or summary contains '{}'.
1988If there are any, enter a module name to get more help.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001989
Terry Jan Reedy34200572013-02-11 02:23:13 -05001990'''.format(key))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001991 apropos(key)
1992 else:
1993 self.output.write('''
1994Please wait a moment while I gather a list of all available modules...
1995
1996''')
1997 modules = {}
1998 def callback(path, modname, desc, modules=modules):
1999 if modname and modname[-9:] == '.__init__':
2000 modname = modname[:-9] + ' (package)'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002001 if modname.find('.') < 0:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002002 modules[modname] = 1
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002003 def onerror(modname):
2004 callback(None, modname, None)
2005 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002006 self.list(modules.keys())
2007 self.output.write('''
2008Enter any module name to get more help. Or, type "modules spam" to search
Terry Jan Reedy34200572013-02-11 02:23:13 -05002009for modules whose name or summary contain the string "spam".
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002010''')
2011
Georg Brandl78aa3962010-07-31 21:51:48 +00002012help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002013
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002014class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002015 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002016
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002017 def run(self, callback, key=None, completer=None, onerror=None):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002018 if key: key = key.lower()
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002019 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002020 seen = {}
2021
2022 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002023 if modname != '__main__':
2024 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00002025 if key is None:
2026 callback(None, modname, '')
2027 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002028 name = __import__(modname).__doc__ or ''
2029 desc = name.split('\n')[0]
2030 name = modname + ' - ' + desc
2031 if name.lower().find(key) >= 0:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002032 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002033
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002034 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002035 if self.quit:
2036 break
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002037
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002038 if key is None:
2039 callback(None, modname, '')
2040 else:
Georg Brandl126c8792009-04-05 15:05:48 +00002041 try:
Eric Snow3a62d142014-01-06 20:42:59 -07002042 spec = pkgutil._get_spec(importer, modname)
Georg Brandl126c8792009-04-05 15:05:48 +00002043 except SyntaxError:
2044 # raised by tests for bad coding cookies or BOM
2045 continue
Eric Snow3a62d142014-01-06 20:42:59 -07002046 loader = spec.loader
Georg Brandl126c8792009-04-05 15:05:48 +00002047 if hasattr(loader, 'get_source'):
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002048 try:
2049 source = loader.get_source(modname)
Nick Coghlan2824cb52012-07-15 22:12:14 +10002050 except Exception:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002051 if onerror:
2052 onerror(modname)
2053 continue
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002054 desc = source_synopsis(io.StringIO(source)) or ''
Georg Brandl126c8792009-04-05 15:05:48 +00002055 if hasattr(loader, 'get_filename'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002056 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002057 else:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002058 path = None
2059 else:
Eric Snow3a62d142014-01-06 20:42:59 -07002060 _spec = importlib._bootstrap._SpecMethods(spec)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002061 try:
Eric Snow3a62d142014-01-06 20:42:59 -07002062 module = _spec.load()
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002063 except ImportError:
2064 if onerror:
2065 onerror(modname)
2066 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002067 desc = (module.__doc__ or '').splitlines()[0]
2068 path = getattr(module,'__file__',None)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002069 name = modname + ' - ' + desc
2070 if name.lower().find(key) >= 0:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002071 callback(path, modname, desc)
2072
2073 if completer:
2074 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002075
2076def apropos(key):
2077 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002078 def callback(path, modname, desc):
2079 if modname[-9:] == '.__init__':
2080 modname = modname[:-9] + ' (package)'
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002081 print(modname, desc and '- ' + desc)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002082 def onerror(modname):
2083 pass
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002084 with warnings.catch_warnings():
2085 warnings.filterwarnings('ignore') # ignore problems during import
2086 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002087
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002088# --------------------------------------- enhanced Web browser interface
2089
2090def _start_server(urlhandler, port):
2091 """Start an HTTP server thread on a specific port.
2092
2093 Start an HTML/text server thread, so HTML or text documents can be
2094 browsed dynamically and interactively with a Web browser. Example use:
2095
2096 >>> import time
2097 >>> import pydoc
2098
2099 Define a URL handler. To determine what the client is asking
2100 for, check the URL and content_type.
2101
2102 Then get or generate some text or HTML code and return it.
2103
2104 >>> def my_url_handler(url, content_type):
2105 ... text = 'the URL sent was: (%s, %s)' % (url, content_type)
2106 ... return text
2107
2108 Start server thread on port 0.
2109 If you use port 0, the server will pick a random port number.
2110 You can then use serverthread.port to get the port number.
2111
2112 >>> port = 0
2113 >>> serverthread = pydoc._start_server(my_url_handler, port)
2114
2115 Check that the server is really started. If it is, open browser
2116 and get first page. Use serverthread.url as the starting page.
2117
2118 >>> if serverthread.serving:
2119 ... import webbrowser
2120
2121 The next two lines are commented out so a browser doesn't open if
2122 doctest is run on this module.
2123
2124 #... webbrowser.open(serverthread.url)
2125 #True
2126
2127 Let the server do its thing. We just need to monitor its status.
2128 Use time.sleep so the loop doesn't hog the CPU.
2129
2130 >>> starttime = time.time()
2131 >>> timeout = 1 #seconds
2132
2133 This is a short timeout for testing purposes.
2134
2135 >>> while serverthread.serving:
2136 ... time.sleep(.01)
2137 ... if serverthread.serving and time.time() - starttime > timeout:
2138 ... serverthread.stop()
2139 ... break
2140
2141 Print any errors that may have occurred.
2142
2143 >>> print(serverthread.error)
2144 None
2145 """
2146 import http.server
2147 import email.message
2148 import select
2149 import threading
2150
2151 class DocHandler(http.server.BaseHTTPRequestHandler):
2152
2153 def do_GET(self):
2154 """Process a request from an HTML browser.
2155
2156 The URL received is in self.path.
2157 Get an HTML page from self.urlhandler and send it.
2158 """
2159 if self.path.endswith('.css'):
2160 content_type = 'text/css'
2161 else:
2162 content_type = 'text/html'
2163 self.send_response(200)
Georg Brandld2f38572011-01-30 08:37:19 +00002164 self.send_header('Content-Type', '%s; charset=UTF-8' % content_type)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002165 self.end_headers()
2166 self.wfile.write(self.urlhandler(
2167 self.path, content_type).encode('utf-8'))
2168
2169 def log_message(self, *args):
2170 # Don't log messages.
2171 pass
2172
2173 class DocServer(http.server.HTTPServer):
2174
2175 def __init__(self, port, callback):
2176 self.host = (sys.platform == 'mac') and '127.0.0.1' or 'localhost'
2177 self.address = ('', port)
2178 self.callback = callback
2179 self.base.__init__(self, self.address, self.handler)
2180 self.quit = False
2181
2182 def serve_until_quit(self):
2183 while not self.quit:
2184 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2185 if rd:
2186 self.handle_request()
Victor Stinnera3abd1d2011-01-03 16:12:39 +00002187 self.server_close()
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002188
2189 def server_activate(self):
2190 self.base.server_activate(self)
2191 if self.callback:
2192 self.callback(self)
2193
2194 class ServerThread(threading.Thread):
2195
2196 def __init__(self, urlhandler, port):
2197 self.urlhandler = urlhandler
2198 self.port = int(port)
2199 threading.Thread.__init__(self)
2200 self.serving = False
2201 self.error = None
2202
2203 def run(self):
2204 """Start the server."""
2205 try:
2206 DocServer.base = http.server.HTTPServer
2207 DocServer.handler = DocHandler
2208 DocHandler.MessageClass = email.message.Message
2209 DocHandler.urlhandler = staticmethod(self.urlhandler)
2210 docsvr = DocServer(self.port, self.ready)
2211 self.docserver = docsvr
2212 docsvr.serve_until_quit()
2213 except Exception as e:
2214 self.error = e
2215
2216 def ready(self, server):
2217 self.serving = True
2218 self.host = server.host
2219 self.port = server.server_port
2220 self.url = 'http://%s:%d/' % (self.host, self.port)
2221
2222 def stop(self):
2223 """Stop the server and this thread nicely"""
2224 self.docserver.quit = True
2225 self.serving = False
2226 self.url = None
2227
2228 thread = ServerThread(urlhandler, port)
2229 thread.start()
2230 # Wait until thread.serving is True to make sure we are
2231 # really up before returning.
2232 while not thread.error and not thread.serving:
2233 time.sleep(.01)
2234 return thread
2235
2236
2237def _url_handler(url, content_type="text/html"):
2238 """The pydoc url handler for use with the pydoc server.
2239
2240 If the content_type is 'text/css', the _pydoc.css style
2241 sheet is read and returned if it exits.
2242
2243 If the content_type is 'text/html', then the result of
2244 get_html_page(url) is returned.
2245 """
2246 class _HTMLDoc(HTMLDoc):
2247
2248 def page(self, title, contents):
2249 """Format an HTML page."""
2250 css_path = "pydoc_data/_pydoc.css"
2251 css_link = (
2252 '<link rel="stylesheet" type="text/css" href="%s">' %
2253 css_path)
2254 return '''\
2255<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Georg Brandld2f38572011-01-30 08:37:19 +00002256<html><head><title>Pydoc: %s</title>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002257<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Georg Brandld2f38572011-01-30 08:37:19 +00002258%s</head><body bgcolor="#f0f0f8">%s<div style="clear:both;padding-top:.5em;">%s</div>
2259</body></html>''' % (title, css_link, html_navbar(), contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002260
2261 def filelink(self, url, path):
2262 return '<a href="getfile?key=%s">%s</a>' % (url, path)
2263
2264
2265 html = _HTMLDoc()
2266
2267 def html_navbar():
Georg Brandld2f38572011-01-30 08:37:19 +00002268 version = html.escape("%s [%s, %s]" % (platform.python_version(),
2269 platform.python_build()[0],
2270 platform.python_compiler()))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002271 return """
2272 <div style='float:left'>
Georg Brandld2f38572011-01-30 08:37:19 +00002273 Python %s<br>%s
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002274 </div>
2275 <div style='float:right'>
2276 <div style='text-align:center'>
2277 <a href="index.html">Module Index</a>
2278 : <a href="topics.html">Topics</a>
2279 : <a href="keywords.html">Keywords</a>
2280 </div>
2281 <div>
Georg Brandld2f38572011-01-30 08:37:19 +00002282 <form action="get" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002283 <input type=text name=key size=15>
2284 <input type=submit value="Get">
Georg Brandld2f38572011-01-30 08:37:19 +00002285 </form>&nbsp;
2286 <form action="search" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002287 <input type=text name=key size=15>
2288 <input type=submit value="Search">
2289 </form>
2290 </div>
2291 </div>
Georg Brandld2f38572011-01-30 08:37:19 +00002292 """ % (version, html.escape(platform.platform(terse=True)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002293
2294 def html_index():
2295 """Module Index page."""
2296
2297 def bltinlink(name):
2298 return '<a href="%s.html">%s</a>' % (name, name)
2299
2300 heading = html.heading(
2301 '<big><big><strong>Index of Modules</strong></big></big>',
2302 '#ffffff', '#7799ee')
2303 names = [name for name in sys.builtin_module_names
2304 if name != '__main__']
2305 contents = html.multicolumn(names, bltinlink)
2306 contents = [heading, '<p>' + html.bigsection(
2307 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2308
2309 seen = {}
2310 for dir in sys.path:
2311 contents.append(html.index(dir, seen))
2312
2313 contents.append(
2314 '<p align=right><font color="#909090" face="helvetica,'
2315 'arial"><strong>pydoc</strong> by Ka-Ping Yee'
2316 '&lt;ping@lfw.org&gt;</font>')
Nick Coghlanecace282010-12-03 16:08:46 +00002317 return 'Index of Modules', ''.join(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002318
2319 def html_search(key):
2320 """Search results page."""
2321 # scan for modules
2322 search_result = []
2323
2324 def callback(path, modname, desc):
2325 if modname[-9:] == '.__init__':
2326 modname = modname[:-9] + ' (package)'
2327 search_result.append((modname, desc and '- ' + desc))
2328
2329 with warnings.catch_warnings():
2330 warnings.filterwarnings('ignore') # ignore problems during import
2331 ModuleScanner().run(callback, key)
2332
2333 # format page
2334 def bltinlink(name):
2335 return '<a href="%s.html">%s</a>' % (name, name)
2336
2337 results = []
2338 heading = html.heading(
2339 '<big><big><strong>Search Results</strong></big></big>',
2340 '#ffffff', '#7799ee')
2341 for name, desc in search_result:
2342 results.append(bltinlink(name) + desc)
2343 contents = heading + html.bigsection(
2344 'key = %s' % key, '#ffffff', '#ee77aa', '<br>'.join(results))
Nick Coghlanecace282010-12-03 16:08:46 +00002345 return 'Search Results', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002346
2347 def html_getfile(path):
2348 """Get and display a source file listing safely."""
Nick Coghlanecace282010-12-03 16:08:46 +00002349 path = path.replace('%20', ' ')
Victor Stinner91e08772011-07-05 14:30:41 +02002350 with tokenize.open(path) as fp:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002351 lines = html.escape(fp.read())
2352 body = '<pre>%s</pre>' % lines
2353 heading = html.heading(
2354 '<big><big><strong>File Listing</strong></big></big>',
2355 '#ffffff', '#7799ee')
2356 contents = heading + html.bigsection(
2357 'File: %s' % path, '#ffffff', '#ee77aa', body)
Nick Coghlanecace282010-12-03 16:08:46 +00002358 return 'getfile %s' % path, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002359
2360 def html_topics():
2361 """Index of topic texts available."""
2362
2363 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002364 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002365
2366 heading = html.heading(
2367 '<big><big><strong>INDEX</strong></big></big>',
2368 '#ffffff', '#7799ee')
2369 names = sorted(Helper.topics.keys())
2370
2371 contents = html.multicolumn(names, bltinlink)
2372 contents = heading + html.bigsection(
2373 'Topics', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002374 return 'Topics', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002375
2376 def html_keywords():
2377 """Index of keywords."""
2378 heading = html.heading(
2379 '<big><big><strong>INDEX</strong></big></big>',
2380 '#ffffff', '#7799ee')
2381 names = sorted(Helper.keywords.keys())
2382
2383 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002384 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002385
2386 contents = html.multicolumn(names, bltinlink)
2387 contents = heading + html.bigsection(
2388 'Keywords', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002389 return 'Keywords', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002390
2391 def html_topicpage(topic):
2392 """Topic or keyword help page."""
2393 buf = io.StringIO()
2394 htmlhelp = Helper(buf, buf)
2395 contents, xrefs = htmlhelp._gettopic(topic)
2396 if topic in htmlhelp.keywords:
2397 title = 'KEYWORD'
2398 else:
2399 title = 'TOPIC'
2400 heading = html.heading(
2401 '<big><big><strong>%s</strong></big></big>' % title,
2402 '#ffffff', '#7799ee')
Georg Brandld2f38572011-01-30 08:37:19 +00002403 contents = '<pre>%s</pre>' % html.markup(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002404 contents = html.bigsection(topic , '#ffffff','#ee77aa', contents)
Georg Brandld2f38572011-01-30 08:37:19 +00002405 if xrefs:
2406 xrefs = sorted(xrefs.split())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002407
Georg Brandld2f38572011-01-30 08:37:19 +00002408 def bltinlink(name):
2409 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002410
Georg Brandld2f38572011-01-30 08:37:19 +00002411 xrefs = html.multicolumn(xrefs, bltinlink)
2412 xrefs = html.section('Related help topics: ',
2413 '#ffffff', '#ee77aa', xrefs)
Nick Coghlanecace282010-12-03 16:08:46 +00002414 return ('%s %s' % (title, topic),
2415 ''.join((heading, contents, xrefs)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002416
Georg Brandld2f38572011-01-30 08:37:19 +00002417 def html_getobj(url):
2418 obj = locate(url, forceload=1)
2419 if obj is None and url != 'None':
2420 raise ValueError('could not find object')
2421 title = describe(obj)
2422 content = html.document(obj, url)
2423 return title, content
2424
2425 def html_error(url, exc):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002426 heading = html.heading(
2427 '<big><big><strong>Error</strong></big></big>',
Georg Brandld2f38572011-01-30 08:37:19 +00002428 '#ffffff', '#7799ee')
2429 contents = '<br>'.join(html.escape(line) for line in
2430 format_exception_only(type(exc), exc))
2431 contents = heading + html.bigsection(url, '#ffffff', '#bb0000',
2432 contents)
2433 return "Error - %s" % url, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002434
2435 def get_html_page(url):
2436 """Generate an HTML page for url."""
Georg Brandld2f38572011-01-30 08:37:19 +00002437 complete_url = url
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002438 if url.endswith('.html'):
2439 url = url[:-5]
Georg Brandld2f38572011-01-30 08:37:19 +00002440 try:
2441 if url in ("", "index"):
2442 title, content = html_index()
2443 elif url == "topics":
2444 title, content = html_topics()
2445 elif url == "keywords":
2446 title, content = html_keywords()
2447 elif '=' in url:
2448 op, _, url = url.partition('=')
2449 if op == "search?key":
2450 title, content = html_search(url)
2451 elif op == "getfile?key":
2452 title, content = html_getfile(url)
2453 elif op == "topic?key":
2454 # try topics first, then objects.
2455 try:
2456 title, content = html_topicpage(url)
2457 except ValueError:
2458 title, content = html_getobj(url)
2459 elif op == "get?key":
2460 # try objects first, then topics.
2461 if url in ("", "index"):
2462 title, content = html_index()
2463 else:
2464 try:
2465 title, content = html_getobj(url)
2466 except ValueError:
2467 title, content = html_topicpage(url)
2468 else:
2469 raise ValueError('bad pydoc url')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002470 else:
Georg Brandld2f38572011-01-30 08:37:19 +00002471 title, content = html_getobj(url)
2472 except Exception as exc:
2473 # Catch any errors and display them in an error page.
2474 title, content = html_error(complete_url, exc)
2475 return html.page(title, content)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002476
2477 if url.startswith('/'):
2478 url = url[1:]
2479 if content_type == 'text/css':
2480 path_here = os.path.dirname(os.path.realpath(__file__))
Georg Brandld2f38572011-01-30 08:37:19 +00002481 css_path = os.path.join(path_here, url)
2482 with open(css_path) as fp:
2483 return ''.join(fp.readlines())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002484 elif content_type == 'text/html':
2485 return get_html_page(url)
Georg Brandld2f38572011-01-30 08:37:19 +00002486 # Errors outside the url handler are caught by the server.
2487 raise TypeError('unknown content type %r for url %s' % (content_type, url))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002488
2489
2490def browse(port=0, *, open_browser=True):
2491 """Start the enhanced pydoc Web server and open a Web browser.
2492
2493 Use port '0' to start the server on an arbitrary port.
2494 Set open_browser to False to suppress opening a browser.
2495 """
2496 import webbrowser
2497 serverthread = _start_server(_url_handler, port)
2498 if serverthread.error:
2499 print(serverthread.error)
2500 return
2501 if serverthread.serving:
2502 server_help_msg = 'Server commands: [b]rowser, [q]uit'
2503 if open_browser:
2504 webbrowser.open(serverthread.url)
2505 try:
2506 print('Server ready at', serverthread.url)
2507 print(server_help_msg)
2508 while serverthread.serving:
2509 cmd = input('server> ')
2510 cmd = cmd.lower()
2511 if cmd == 'q':
2512 break
2513 elif cmd == 'b':
2514 webbrowser.open(serverthread.url)
2515 else:
2516 print(server_help_msg)
2517 except (KeyboardInterrupt, EOFError):
2518 print()
2519 finally:
2520 if serverthread.serving:
2521 serverthread.stop()
2522 print('Server stopped')
2523
2524
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002525# -------------------------------------------------- command-line interface
2526
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002527def ispath(x):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002528 return isinstance(x, str) and x.find(os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002529
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002530def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002531 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002532 import getopt
Guido van Rossum756aa932007-04-07 03:04:01 +00002533 class BadUsage(Exception): pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002534
Nick Coghlan106274b2009-11-15 23:04:33 +00002535 # Scripts don't get the current directory in their path by default
2536 # unless they are run with the '-m' switch
2537 if '' not in sys.path:
2538 scriptdir = os.path.dirname(sys.argv[0])
2539 if scriptdir in sys.path:
2540 sys.path.remove(scriptdir)
2541 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002542
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002543 try:
Victor Stinner383c3fc2011-05-25 01:35:05 +02002544 opts, args = getopt.getopt(sys.argv[1:], 'bk:p:w')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002545 writing = False
2546 start_server = False
2547 open_browser = False
2548 port = None
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002549 for opt, val in opts:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002550 if opt == '-b':
2551 start_server = True
2552 open_browser = True
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002553 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002554 apropos(val)
2555 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002556 if opt == '-p':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002557 start_server = True
2558 port = val
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002559 if opt == '-w':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002560 writing = True
2561
Benjamin Petersonb29614e2012-10-09 11:16:03 -04002562 if start_server:
2563 if port is None:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002564 port = 0
2565 browse(port, open_browser=open_browser)
2566 return
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002567
2568 if not args: raise BadUsage
2569 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002570 if ispath(arg) and not os.path.exists(arg):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002571 print('file %r does not exist' % arg)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002572 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002573 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002574 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002575 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002576 if writing:
2577 if ispath(arg) and os.path.isdir(arg):
2578 writedocs(arg)
2579 else:
2580 writedoc(arg)
2581 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002582 help.help(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +00002583 except ErrorDuringImport as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002584 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002585
2586 except (getopt.error, BadUsage):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002587 cmd = os.path.splitext(os.path.basename(sys.argv[0]))[0]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002588 print("""pydoc - the Python documentation tool
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002589
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002590{cmd} <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002591 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002592 Python keyword, topic, function, module, or package, or a dotted
2593 reference to a class or function within a module or module in a
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002594 package. If <name> contains a '{sep}', it is used as the path to a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002595 Python source file to document. If name is 'keywords', 'topics',
2596 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002597
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002598{cmd} -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002599 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002600
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002601{cmd} -p <port>
2602 Start an HTTP server on the given port on the local machine. Port
2603 number 0 can be used to get an arbitrary unused port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002604
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002605{cmd} -b
2606 Start an HTTP server on an arbitrary unused port and open a Web browser
2607 to interactively browse documentation. The -p option can be used with
2608 the -b option to explicitly specify the server port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002609
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002610{cmd} -w <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002611 Write out the HTML documentation for a module to a file in the current
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002612 directory. If <name> contains a '{sep}', it is treated as a filename; if
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002613 it names a directory, documentation is written for all the contents.
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002614""".format(cmd=cmd, sep=os.sep))
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002615
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002616if __name__ == '__main__':
2617 cli()