blob: cc43684f191442f5f31d36e45b2caeaa02cadf0b [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)))
Benjamin Petersoned1160b2014-06-07 16:44:00 -0700598 elif selfdot:
599 # Create a link for methods like 'self.method(...)'
600 # and use <strong> for attributes like 'self.attr'
601 if text[end:end+1] == '(':
602 results.append('self.' + self.namelink(name, methods))
603 else:
604 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000605 elif text[end:end+1] == '(':
606 results.append(self.namelink(name, methods, funcs, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000607 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000608 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000609 here = end
610 results.append(escape(text[here:]))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000611 return ''.join(results)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000612
613 # ---------------------------------------------- type-specific routines
614
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000615 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000616 """Produce HTML for a class tree as given by inspect.getclasstree()."""
617 result = ''
618 for entry in tree:
619 if type(entry) is type(()):
620 c, bases = entry
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000621 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000622 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000623 if bases and bases != (parent,):
624 parents = []
625 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000626 parents.append(self.classlink(base, modname))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000627 result = result + '(' + ', '.join(parents) + ')'
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000628 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000629 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000630 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000631 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000632 return '<dl>\n%s</dl>\n' % result
633
Tim Peters8dd7ade2001-10-18 19:56:17 +0000634 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000635 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000636 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000637 try:
638 all = object.__all__
639 except AttributeError:
640 all = None
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000641 parts = name.split('.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000642 links = []
643 for i in range(len(parts)-1):
644 links.append(
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000645 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000646 ('.'.join(parts[:i+1]), parts[i]))
647 linkedname = '.'.join(links + parts[-1:])
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000648 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000649 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000650 path = inspect.getabsfile(object)
Ka-Ping Yee6191a232001-04-13 15:00:27 +0000651 url = path
652 if sys.platform == 'win32':
653 import nturl2path
654 url = nturl2path.pathname2url(path)
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000655 filelink = self.filelink(url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000656 except TypeError:
657 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000658 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000659 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000660 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000661 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000662 version = version[11:-1].strip()
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000663 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000664 if hasattr(object, '__date__'):
665 info.append(self.escape(str(object.__date__)))
666 if info:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000667 head = head + ' (%s)' % ', '.join(info)
Skip Montanaro4997a692003-09-10 16:47:51 +0000668 docloc = self.getdocloc(object)
669 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000670 docloc = '<br><a href="%(docloc)s">Module Reference</a>' % locals()
Skip Montanaro4997a692003-09-10 16:47:51 +0000671 else:
672 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000673 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000674 head, '#ffffff', '#7799ee',
675 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000676
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000677 modules = inspect.getmembers(object, inspect.ismodule)
678
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000679 classes, cdict = [], {}
680 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000681 # if __all__ exists, believe it. Otherwise use old heuristic.
682 if (all is not None or
683 (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700684 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000685 classes.append((key, value))
686 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000687 for key, value in classes:
688 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000689 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000690 module = sys.modules.get(modname)
691 if modname != name and module and hasattr(module, key):
692 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000693 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000694 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000695 funcs, fdict = [], {}
696 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000697 # if __all__ exists, believe it. Otherwise use old heuristic.
698 if (all is not None or
699 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700700 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000701 funcs.append((key, value))
702 fdict[key] = '#-' + key
703 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000704 data = []
705 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700706 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000707 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000708
709 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
710 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000711 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000712
713 if hasattr(object, '__path__'):
714 modpkgs = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000715 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
716 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000717 modpkgs.sort()
718 contents = self.multicolumn(modpkgs, self.modpkglink)
719 result = result + self.bigsection(
720 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000721 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000722 contents = self.multicolumn(
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000723 modules, lambda t: self.modulelink(t[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000724 result = result + self.bigsection(
Christian Heimes7131fd92008-02-19 14:21:46 +0000725 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000726
727 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000728 classlist = [value for (key, value) in classes]
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000729 contents = [
730 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000731 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000732 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000733 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000734 'Classes', '#ffffff', '#ee77aa', ' '.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000735 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000736 contents = []
737 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000738 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000739 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000740 'Functions', '#ffffff', '#eeaa77', ' '.join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000741 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000742 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000743 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000744 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000745 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000746 'Data', '#ffffff', '#55aa55', '<br>\n'.join(contents))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000747 if hasattr(object, '__author__'):
748 contents = self.markup(str(object.__author__), self.preformat)
749 result = result + self.bigsection(
750 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000751 if hasattr(object, '__credits__'):
752 contents = self.markup(str(object.__credits__), self.preformat)
753 result = result + self.bigsection(
754 'Credits', '#ffffff', '#7799ee', contents)
755
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000756 return result
757
Tim Peters8dd7ade2001-10-18 19:56:17 +0000758 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
759 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000760 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000761 realname = object.__name__
762 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000763 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000764
Tim Petersb47879b2001-09-24 04:47:19 +0000765 contents = []
766 push = contents.append
767
Tim Petersfa26f7c2001-09-24 08:05:11 +0000768 # Cute little class to pump out a horizontal rule between sections.
769 class HorizontalRule:
770 def __init__(self):
771 self.needone = 0
772 def maybe(self):
773 if self.needone:
774 push('<hr>\n')
775 self.needone = 1
776 hr = HorizontalRule()
777
Tim Petersc86f6ca2001-09-26 21:31:51 +0000778 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000779 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000780 if len(mro) > 2:
781 hr.maybe()
782 push('<dl><dt>Method resolution order:</dt>\n')
783 for base in mro:
784 push('<dd>%s</dd>\n' % self.classlink(base,
785 object.__module__))
786 push('</dl>\n')
787
Tim Petersb47879b2001-09-24 04:47:19 +0000788 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000789 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000790 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000791 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000792 push(msg)
793 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100794 try:
795 value = getattr(object, name)
796 except Exception:
797 # Some descriptors may meet a failure in their __get__.
798 # (bug #1785)
799 push(self._docdescriptor(name, value, mod))
800 else:
801 push(self.document(value, name, mod,
802 funcs, classes, mdict, object))
Tim Petersb47879b2001-09-24 04:47:19 +0000803 push('\n')
804 return attrs
805
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000806 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000807 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000808 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000809 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000810 push(msg)
811 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000812 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000813 return attrs
814
Tim Petersfa26f7c2001-09-24 08:05:11 +0000815 def spilldata(msg, attrs, predicate):
816 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000817 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000818 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000819 push(msg)
820 for name, kind, homecls, value in ok:
821 base = self.docother(getattr(object, name), name, mod)
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200822 if callable(value) or inspect.isdatadescriptor(value):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000823 doc = getattr(value, "__doc__", None)
824 else:
825 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000826 if doc is None:
827 push('<dl><dt>%s</dl>\n' % base)
828 else:
829 doc = self.markup(getdoc(value), self.preformat,
830 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000831 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000832 push('<dl><dt>%s%s</dl>\n' % (base, doc))
833 push('\n')
834 return attrs
835
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000836 attrs = [(name, kind, cls, value)
837 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -0700838 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000839
Tim Petersb47879b2001-09-24 04:47:19 +0000840 mdict = {}
841 for key, kind, homecls, value in attrs:
842 mdict[key] = anchor = '#' + name + '-' + key
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100843 try:
844 value = getattr(object, name)
845 except Exception:
846 # Some descriptors may meet a failure in their __get__.
847 # (bug #1785)
848 pass
Tim Petersb47879b2001-09-24 04:47:19 +0000849 try:
850 # The value may not be hashable (e.g., a data attr with
851 # a dict or list value).
852 mdict[value] = anchor
853 except TypeError:
854 pass
855
Tim Petersfa26f7c2001-09-24 08:05:11 +0000856 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000857 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000858 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000859 else:
860 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000861 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
862
Georg Brandl1a3284e2007-12-02 09:40:06 +0000863 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000864 attrs = inherited
865 continue
866 elif thisclass is object:
867 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000868 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000869 tag = 'inherited from %s' % self.classlink(thisclass,
870 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000871 tag += ':<br>\n'
872
873 # Sort attrs by name.
Raymond Hettingerd4cb56d2008-01-30 02:55:10 +0000874 attrs.sort(key=lambda t: t[0])
Tim Petersb47879b2001-09-24 04:47:19 +0000875
876 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000877 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000878 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000879 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000880 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000881 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000882 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000883 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
884 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000885 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000886 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000887 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000888 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000889
890 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000891
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000892 if name == realname:
893 title = '<a name="%s">class <strong>%s</strong></a>' % (
894 name, realname)
895 else:
896 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
897 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000898 if bases:
899 parents = []
900 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000901 parents.append(self.classlink(base, object.__module__))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000902 title = title + '(%s)' % ', '.join(parents)
Tim Peters2306d242001-09-25 03:18:32 +0000903 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000904 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000905
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000906 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000907
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000908 def formatvalue(self, object):
909 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000910 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000911
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000912 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000913 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000914 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000915 realname = object.__name__
916 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000917 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000918 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000919 skipdocs = 0
Larry Hastings24a882b2014-02-20 23:34:46 -0800920 if _is_bound_method(object):
Christian Heimesff737952007-11-27 10:40:20 +0000921 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000922 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000923 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000924 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000925 else:
Christian Heimesff737952007-11-27 10:40:20 +0000926 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000927 note = ' method of %s instance' % self.classlink(
Christian Heimesff737952007-11-27 10:40:20 +0000928 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000929 else:
930 note = ' unbound %s method' % self.classlink(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000931
932 if name == realname:
933 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
934 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000935 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000936 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000937 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000938 cl.__name__ + '-' + realname, realname)
939 skipdocs = 1
940 else:
941 reallink = realname
942 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
943 anchor, name, reallink)
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800944 argspec = None
Larry Hastings24a882b2014-02-20 23:34:46 -0800945 if inspect.isroutine(object):
Larry Hastings5c661892014-01-24 06:17:25 -0800946 try:
947 signature = inspect.signature(object)
948 except (ValueError, TypeError):
949 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800950 if signature:
951 argspec = str(signature)
952 if realname == '<lambda>':
953 title = '<strong>%s</strong> <em>lambda</em> ' % name
954 # XXX lambda's won't usually have func_annotations['return']
955 # since the syntax doesn't support but it is possible.
956 # So removing parentheses isn't truly safe.
957 argspec = argspec[1:-1] # remove parentheses
958 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +0000959 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000960
Tim Peters2306d242001-09-25 03:18:32 +0000961 decl = title + argspec + (note and self.grey(
962 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000963
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000964 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000965 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000966 else:
967 doc = self.markup(
968 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000969 doc = doc and '<dd><tt>%s</tt></dd>' % doc
970 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000971
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000972 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000973 results = []
974 push = results.append
975
976 if name:
977 push('<dl><dt><strong>%s</strong></dt>\n' % name)
978 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000979 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000980 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000981 push('</dl>\n')
982
983 return ''.join(results)
984
985 def docproperty(self, object, name=None, mod=None, cl=None):
986 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000987 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000988
Tim Peters8dd7ade2001-10-18 19:56:17 +0000989 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000990 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000991 lhs = name and '<strong>%s</strong> = ' % name or ''
992 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000993
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000994 def docdata(self, object, name=None, mod=None, cl=None):
995 """Produce html documentation for a data descriptor."""
996 return self._docdescriptor(name, object, mod)
997
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000998 def index(self, dir, shadowed=None):
999 """Generate an HTML index for a directory of modules."""
1000 modpkgs = []
1001 if shadowed is None: shadowed = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001002 for importer, name, ispkg in pkgutil.iter_modules([dir]):
Victor Stinner4d652242011-04-12 23:41:50 +02001003 if any((0xD800 <= ord(ch) <= 0xDFFF) for ch in name):
1004 # ignore a module if its name contains a surrogate character
1005 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001006 modpkgs.append((name, '', ispkg, name in shadowed))
1007 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001008
1009 modpkgs.sort()
1010 contents = self.multicolumn(modpkgs, self.modpkglink)
1011 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
1012
1013# -------------------------------------------- text documentation generator
1014
1015class TextRepr(Repr):
1016 """Class for safely making a text representation of a Python object."""
1017 def __init__(self):
1018 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001019 self.maxlist = self.maxtuple = 20
1020 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001021 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001022
1023 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001024 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001025 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001026 if hasattr(self, methodname):
1027 return getattr(self, methodname)(x, level)
1028 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001029
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001030 def repr_string(self, x, level):
1031 test = cram(x, self.maxstring)
1032 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001033 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001034 # Backslashes are only literal in the string and are never
1035 # needed to make any special characters, so show a raw string.
1036 return 'r' + testrepr[0] + test + testrepr[0]
1037 return testrepr
1038
Skip Montanarodf708782002-03-07 22:58:02 +00001039 repr_str = repr_string
1040
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001041 def repr_instance(self, x, level):
1042 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001043 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001044 except:
1045 return '<%s instance>' % x.__class__.__name__
1046
1047class TextDoc(Doc):
1048 """Formatter class for text documentation."""
1049
1050 # ------------------------------------------- text formatting utilities
1051
1052 _repr_instance = TextRepr()
1053 repr = _repr_instance.repr
1054
1055 def bold(self, text):
1056 """Format a string in bold by overstriking."""
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001057 return ''.join(ch + '\b' + ch for ch in text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001058
1059 def indent(self, text, prefix=' '):
1060 """Indent text by prepending a given prefix to each line."""
1061 if not text: return ''
Collin Winter72e110c2007-07-17 00:27:30 +00001062 lines = [prefix + line for line in text.split('\n')]
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001063 if lines: lines[-1] = lines[-1].rstrip()
1064 return '\n'.join(lines)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001065
1066 def section(self, title, contents):
1067 """Format a section with a given heading."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001068 clean_contents = self.indent(contents).rstrip()
1069 return self.bold(title) + '\n' + clean_contents + '\n\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001070
1071 # ---------------------------------------------- type-specific routines
1072
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001073 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001074 """Render in text a class tree as returned by inspect.getclasstree()."""
1075 result = ''
1076 for entry in tree:
1077 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001078 c, bases = entry
1079 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001080 if bases and bases != (parent,):
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001081 parents = (classname(c, modname) for c in bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001082 result = result + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001083 result = result + '\n'
1084 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001085 result = result + self.formattree(
1086 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001087 return result
1088
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001089 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001090 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001091 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001092 synop, desc = splitdoc(getdoc(object))
1093 result = self.section('NAME', name + (synop and ' - ' + synop))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001094 all = getattr(object, '__all__', None)
Skip Montanaro4997a692003-09-10 16:47:51 +00001095 docloc = self.getdocloc(object)
1096 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001097 result = result + self.section('MODULE REFERENCE', docloc + """
1098
Éric Araujo647ef8c2011-09-11 00:43:20 +02001099The following documentation is automatically generated from the Python
1100source files. It may be incomplete, incorrect or include features that
1101are considered implementation detail and may vary between Python
1102implementations. When in doubt, consult the module reference at the
1103location listed above.
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001104""")
Skip Montanaro4997a692003-09-10 16:47:51 +00001105
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001106 if desc:
1107 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001108
1109 classes = []
1110 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001111 # if __all__ exists, believe it. Otherwise use old heuristic.
1112 if (all is not None
1113 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001114 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001115 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001116 funcs = []
1117 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001118 # if __all__ exists, believe it. Otherwise use old heuristic.
1119 if (all is not None or
1120 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001121 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001122 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001123 data = []
1124 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001125 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001126 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001127
Christian Heimes1af737c2008-01-23 08:24:23 +00001128 modpkgs = []
1129 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001130 if hasattr(object, '__path__'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001131 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Christian Heimes1af737c2008-01-23 08:24:23 +00001132 modpkgs_names.add(modname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001133 if ispkg:
1134 modpkgs.append(modname + ' (package)')
1135 else:
1136 modpkgs.append(modname)
1137
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001138 modpkgs.sort()
1139 result = result + self.section(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001140 'PACKAGE CONTENTS', '\n'.join(modpkgs))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001141
Christian Heimes1af737c2008-01-23 08:24:23 +00001142 # Detect submodules as sometimes created by C extensions
1143 submodules = []
1144 for key, value in inspect.getmembers(object, inspect.ismodule):
1145 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1146 submodules.append(key)
1147 if submodules:
1148 submodules.sort()
1149 result = result + self.section(
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001150 'SUBMODULES', '\n'.join(submodules))
Christian Heimes1af737c2008-01-23 08:24:23 +00001151
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001152 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001153 classlist = [value for key, value in classes]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001154 contents = [self.formattree(
1155 inspect.getclasstree(classlist, 1), name)]
1156 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001157 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001158 result = result + self.section('CLASSES', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001159
1160 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001161 contents = []
1162 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001163 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001164 result = result + self.section('FUNCTIONS', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001165
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001166 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001167 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001168 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001169 contents.append(self.docother(value, key, name, maxlen=70))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001170 result = result + self.section('DATA', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001171
1172 if hasattr(object, '__version__'):
1173 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001174 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001175 version = version[11:-1].strip()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001176 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001177 if hasattr(object, '__date__'):
1178 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001179 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001180 result = result + self.section('AUTHOR', str(object.__author__))
1181 if hasattr(object, '__credits__'):
1182 result = result + self.section('CREDITS', str(object.__credits__))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001183 try:
1184 file = inspect.getabsfile(object)
1185 except TypeError:
1186 file = '(built-in)'
1187 result = result + self.section('FILE', file)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001188 return result
1189
Georg Brandl9bd45f992010-12-03 09:58:38 +00001190 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001191 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001192 realname = object.__name__
1193 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001194 bases = object.__bases__
1195
Tim Petersc86f6ca2001-09-26 21:31:51 +00001196 def makename(c, m=object.__module__):
1197 return classname(c, m)
1198
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001199 if name == realname:
1200 title = 'class ' + self.bold(realname)
1201 else:
1202 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001203 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001204 parents = map(makename, bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001205 title = title + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001206
1207 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001208 contents = doc and [doc + '\n'] or []
1209 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001210
Tim Petersc86f6ca2001-09-26 21:31:51 +00001211 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001212 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001213 if len(mro) > 2:
1214 push("Method resolution order:")
1215 for base in mro:
1216 push(' ' + makename(base))
1217 push('')
1218
Tim Petersf4aad8e2001-09-24 22:40:47 +00001219 # Cute little class to pump out a horizontal rule between sections.
1220 class HorizontalRule:
1221 def __init__(self):
1222 self.needone = 0
1223 def maybe(self):
1224 if self.needone:
1225 push('-' * 70)
1226 self.needone = 1
1227 hr = HorizontalRule()
1228
Tim Peters28355492001-09-23 21:29:55 +00001229 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001230 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001231 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001232 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001233 push(msg)
1234 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001235 try:
1236 value = getattr(object, name)
1237 except Exception:
1238 # Some descriptors may meet a failure in their __get__.
1239 # (bug #1785)
1240 push(self._docdescriptor(name, value, mod))
1241 else:
1242 push(self.document(value,
1243 name, mod, object))
Tim Peters28355492001-09-23 21:29:55 +00001244 return attrs
1245
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001246 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001247 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001248 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001249 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001250 push(msg)
1251 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001252 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001253 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001254
Tim Petersfa26f7c2001-09-24 08:05:11 +00001255 def spilldata(msg, attrs, predicate):
1256 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001257 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001258 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001259 push(msg)
1260 for name, kind, homecls, value in ok:
Florent Xicluna5d1155c2011-10-28 14:45:05 +02001261 if callable(value) or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001262 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001263 else:
1264 doc = None
Serhiy Storchaka056eb022014-02-19 23:05:12 +02001265 try:
1266 obj = getattr(object, name)
1267 except AttributeError:
1268 obj = homecls.__dict__[name]
1269 push(self.docother(obj, name, mod, maxlen=70, doc=doc) +
1270 '\n')
Tim Peters28355492001-09-23 21:29:55 +00001271 return attrs
1272
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001273 attrs = [(name, kind, cls, value)
1274 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -07001275 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001276
Tim Petersfa26f7c2001-09-24 08:05:11 +00001277 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001278 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001279 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001280 else:
1281 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001282 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1283
Georg Brandl1a3284e2007-12-02 09:40:06 +00001284 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001285 attrs = inherited
1286 continue
1287 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001288 tag = "defined here"
1289 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001290 tag = "inherited from %s" % classname(thisclass,
1291 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001292 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001293 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001294
1295 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001296 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001297 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001298 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001299 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001300 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001301 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001302 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1303 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001304 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1305 lambda t: t[1] == 'data')
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001306
Tim Peters28355492001-09-23 21:29:55 +00001307 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001308 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001309
1310 contents = '\n'.join(contents)
1311 if not contents:
1312 return title + '\n'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001313 return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001314
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001315 def formatvalue(self, object):
1316 """Format an argument default value as text."""
1317 return '=' + self.repr(object)
1318
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001319 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001320 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001321 realname = object.__name__
1322 name = name or realname
1323 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001324 skipdocs = 0
Larry Hastings24a882b2014-02-20 23:34:46 -08001325 if _is_bound_method(object):
Christian Heimesff737952007-11-27 10:40:20 +00001326 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001327 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001328 if imclass is not cl:
1329 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001330 else:
Christian Heimesff737952007-11-27 10:40:20 +00001331 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001332 note = ' method of %s instance' % classname(
Christian Heimesff737952007-11-27 10:40:20 +00001333 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001334 else:
1335 note = ' unbound %s method' % classname(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001336
1337 if name == realname:
1338 title = self.bold(realname)
1339 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001340 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001341 cl.__dict__[realname] is object):
1342 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001343 title = self.bold(name) + ' = ' + realname
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001344 argspec = None
Larry Hastings5c661892014-01-24 06:17:25 -08001345
1346 if inspect.isroutine(object):
1347 try:
1348 signature = inspect.signature(object)
1349 except (ValueError, TypeError):
1350 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001351 if signature:
1352 argspec = str(signature)
1353 if realname == '<lambda>':
1354 title = self.bold(name) + ' lambda '
1355 # XXX lambda's won't usually have func_annotations['return']
1356 # since the syntax doesn't support but it is possible.
1357 # So removing parentheses isn't truly safe.
1358 argspec = argspec[1:-1] # remove parentheses
1359 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +00001360 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001361 decl = title + argspec + note
1362
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001363 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001364 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001365 else:
1366 doc = getdoc(object) or ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001367 return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001368
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001369 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001370 results = []
1371 push = results.append
1372
1373 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001374 push(self.bold(name))
1375 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001376 doc = getdoc(value) or ''
1377 if doc:
1378 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001379 push('\n')
1380 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001381
1382 def docproperty(self, object, name=None, mod=None, cl=None):
1383 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001384 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001385
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001386 def docdata(self, object, name=None, mod=None, cl=None):
1387 """Produce text documentation for a data descriptor."""
1388 return self._docdescriptor(name, object, mod)
1389
Georg Brandl8b813db2005-10-01 16:32:31 +00001390 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001391 """Produce text documentation for a data object."""
1392 repr = self.repr(object)
1393 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001394 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001395 chop = maxlen - len(line)
1396 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001397 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001398 if doc is not None:
1399 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001400 return line
1401
Georg Brandld80d5f42010-12-03 07:47:22 +00001402class _PlainTextDoc(TextDoc):
1403 """Subclass of TextDoc which overrides string styling"""
1404 def bold(self, text):
1405 return text
1406
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001407# --------------------------------------------------------- user interfaces
1408
1409def pager(text):
1410 """The first time this is called, determine what kind of pager to use."""
1411 global pager
Victor Stinner0cc45ba2014-05-13 02:05:35 +02001412 # Escape non-encodable characters to avoid encoding errors later
1413 encoding = sys.getfilesystemencoding()
1414 text = text.encode(encoding, 'backslashreplace').decode(encoding)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001415 pager = getpager()
1416 pager(text)
1417
1418def getpager():
1419 """Decide what method to use for paging through text."""
Benjamin Peterson159824e2014-06-07 20:14:26 -07001420 if not hasattr(sys.stdin, "isatty"):
1421 return plainpager
Guido van Rossuma01a8b62007-05-27 09:20:14 +00001422 if not hasattr(sys.stdout, "isatty"):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001423 return plainpager
1424 if not sys.stdin.isatty() or not sys.stdout.isatty():
1425 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001426 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001427 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001428 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001429 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001430 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001431 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001432 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001433 if os.environ.get('TERM') in ('dumb', 'emacs'):
1434 return plainpager
Jesus Cea4791a242012-10-05 03:15:39 +02001435 if sys.platform == 'win32':
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001436 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001437 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001438 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001439
1440 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001441 (fd, filename) = tempfile.mkstemp()
1442 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001443 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001444 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001445 return lambda text: pipepager(text, 'more')
1446 else:
1447 return ttypager
1448 finally:
1449 os.unlink(filename)
1450
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001451def plain(text):
1452 """Remove boldface formatting from text."""
1453 return re.sub('.\b', '', text)
1454
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001455def pipepager(text, cmd):
1456 """Page through text by feeding it to another program."""
1457 pipe = os.popen(cmd, 'w')
1458 try:
1459 pipe.write(text)
1460 pipe.close()
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001461 except OSError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001462 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001463
1464def tempfilepager(text, cmd):
1465 """Page through text by invoking a program on a temporary file."""
1466 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001467 filename = tempfile.mktemp()
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +01001468 with open(filename, 'w') as file:
1469 file.write(text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001470 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001471 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001472 finally:
1473 os.unlink(filename)
1474
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001475def ttypager(text):
1476 """Page through text on a text terminal."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001477 lines = plain(text).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001478 try:
1479 import tty
1480 fd = sys.stdin.fileno()
1481 old = tty.tcgetattr(fd)
1482 tty.setcbreak(fd)
1483 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001484 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001485 tty = None
1486 getchar = lambda: sys.stdin.readline()[:-1][:1]
1487
1488 try:
1489 r = inc = os.environ.get('LINES', 25) - 1
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001490 sys.stdout.write('\n'.join(lines[:inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001491 while lines[r:]:
1492 sys.stdout.write('-- more --')
1493 sys.stdout.flush()
1494 c = getchar()
1495
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001496 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001497 sys.stdout.write('\r \r')
1498 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001499 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001500 sys.stdout.write('\r \r' + lines[r] + '\n')
1501 r = r + 1
1502 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001503 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001504 r = r - inc - inc
1505 if r < 0: r = 0
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001506 sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001507 r = r + inc
1508
1509 finally:
1510 if tty:
1511 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1512
1513def plainpager(text):
1514 """Simply print unformatted text. This is the ultimate fallback."""
1515 sys.stdout.write(plain(text))
1516
1517def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001518 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001519 if inspect.ismodule(thing):
1520 if thing.__name__ in sys.builtin_module_names:
1521 return 'built-in module ' + thing.__name__
1522 if hasattr(thing, '__path__'):
1523 return 'package ' + thing.__name__
1524 else:
1525 return 'module ' + thing.__name__
1526 if inspect.isbuiltin(thing):
1527 return 'built-in function ' + thing.__name__
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001528 if inspect.isgetsetdescriptor(thing):
1529 return 'getset descriptor %s.%s.%s' % (
1530 thing.__objclass__.__module__, thing.__objclass__.__name__,
1531 thing.__name__)
1532 if inspect.ismemberdescriptor(thing):
1533 return 'member descriptor %s.%s.%s' % (
1534 thing.__objclass__.__module__, thing.__objclass__.__name__,
1535 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001536 if inspect.isclass(thing):
1537 return 'class ' + thing.__name__
1538 if inspect.isfunction(thing):
1539 return 'function ' + thing.__name__
1540 if inspect.ismethod(thing):
1541 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001542 return type(thing).__name__
1543
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001544def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001545 """Locate an object by name or dotted path, importing as necessary."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001546 parts = [part for part in path.split('.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001547 module, n = None, 0
1548 while n < len(parts):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001549 nextmodule = safeimport('.'.join(parts[:n+1]), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001550 if nextmodule: module, n = nextmodule, n + 1
1551 else: break
1552 if module:
1553 object = module
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001554 else:
Éric Araujoe64e51b2011-07-29 17:03:55 +02001555 object = builtins
1556 for part in parts[n:]:
1557 try:
1558 object = getattr(object, part)
1559 except AttributeError:
1560 return None
1561 return object
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001562
1563# --------------------------------------- interactive interpreter interface
1564
1565text = TextDoc()
Georg Brandld80d5f42010-12-03 07:47:22 +00001566plaintext = _PlainTextDoc()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001567html = HTMLDoc()
1568
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001569def resolve(thing, forceload=0):
1570 """Given an object or a path to an object, get the object and its name."""
1571 if isinstance(thing, str):
1572 object = locate(thing, forceload)
1573 if not object:
Collin Winterce36ad82007-08-30 01:19:48 +00001574 raise ImportError('no Python documentation found for %r' % thing)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001575 return object, thing
1576 else:
R David Murrayc43125a2012-04-23 13:23:57 -04001577 name = getattr(thing, '__name__', None)
1578 return thing, name if isinstance(name, str) else None
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001579
Georg Brandld80d5f42010-12-03 07:47:22 +00001580def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
1581 renderer=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001582 """Render text documentation, given an object or a path to an object."""
Georg Brandld80d5f42010-12-03 07:47:22 +00001583 if renderer is None:
1584 renderer = text
Guido van Rossumd8faa362007-04-27 19:54:29 +00001585 object, name = resolve(thing, forceload)
1586 desc = describe(object)
1587 module = inspect.getmodule(object)
1588 if name and '.' in name:
1589 desc += ' in ' + name[:name.rfind('.')]
1590 elif module and module is not object:
1591 desc += ' in module ' + module.__name__
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001592
1593 if not (inspect.ismodule(object) or
Guido van Rossumd8faa362007-04-27 19:54:29 +00001594 inspect.isclass(object) or
1595 inspect.isroutine(object) or
1596 inspect.isgetsetdescriptor(object) or
1597 inspect.ismemberdescriptor(object) or
1598 isinstance(object, property)):
1599 # If the passed object is a piece of data or an instance,
1600 # document its available methods instead of its value.
1601 object = type(object)
1602 desc += ' object'
Georg Brandld80d5f42010-12-03 07:47:22 +00001603 return title % desc + '\n\n' + renderer.document(object, name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001604
Georg Brandld80d5f42010-12-03 07:47:22 +00001605def doc(thing, title='Python Library Documentation: %s', forceload=0,
1606 output=None):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001607 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001608 try:
Georg Brandld80d5f42010-12-03 07:47:22 +00001609 if output is None:
1610 pager(render_doc(thing, title, forceload))
1611 else:
1612 output.write(render_doc(thing, title, forceload, plaintext))
Guido van Rossumb940e112007-01-10 16:19:56 +00001613 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001614 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001615
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001616def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001617 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001618 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001619 object, name = resolve(thing, forceload)
1620 page = html.page(describe(object), html.document(object, name))
Georg Brandl388faac2009-04-10 08:31:48 +00001621 file = open(name + '.html', 'w', encoding='utf-8')
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001622 file.write(page)
1623 file.close()
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001624 print('wrote', name + '.html')
Guido van Rossumb940e112007-01-10 16:19:56 +00001625 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001626 print(value)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001627
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001628def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001629 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001630 if done is None: done = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001631 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1632 writedoc(modname)
1633 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001634
1635class Helper:
Georg Brandl6b38daa2008-06-01 21:05:17 +00001636
1637 # These dictionaries map a topic name to either an alias, or a tuple
1638 # (label, seealso-items). The "label" is the label of the corresponding
1639 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl5617db82009-04-27 16:28:57 +00001640 # in pydoc_data/topics.py.
Georg Brandl6b38daa2008-06-01 21:05:17 +00001641 #
1642 # CAUTION: if you change one of these dictionaries, be sure to adapt the
1643 # list of needed labels in Doc/tools/sphinxext/pyspecific.py and
Georg Brandl5617db82009-04-27 16:28:57 +00001644 # regenerate the pydoc_data/topics.py file by running
Georg Brandl6b38daa2008-06-01 21:05:17 +00001645 # make pydoc-topics
1646 # in Doc/ and copying the output file into the Lib/ directory.
1647
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001648 keywords = {
Ezio Melottib185a042011-04-28 07:42:55 +03001649 'False': '',
1650 'None': '',
1651 'True': '',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001652 'and': 'BOOLEAN',
Guido van Rossumd8faa362007-04-27 19:54:29 +00001653 'as': 'with',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001654 'assert': ('assert', ''),
1655 'break': ('break', 'while for'),
1656 'class': ('class', 'CLASSES SPECIALMETHODS'),
1657 'continue': ('continue', 'while for'),
1658 'def': ('function', ''),
1659 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001660 'elif': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001661 'else': ('else', 'while for'),
Georg Brandl0d855392008-08-30 19:53:05 +00001662 'except': 'try',
1663 'finally': 'try',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001664 'for': ('for', 'break continue while'),
Georg Brandl0d855392008-08-30 19:53:05 +00001665 'from': 'import',
Georg Brandl74abf6f2010-11-20 19:54:36 +00001666 'global': ('global', 'nonlocal NAMESPACES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001667 'if': ('if', 'TRUTHVALUE'),
1668 'import': ('import', 'MODULES'),
Georg Brandl395ed242009-09-04 08:07:32 +00001669 'in': ('in', 'SEQUENCEMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001670 'is': 'COMPARISON',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001671 'lambda': ('lambda', 'FUNCTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001672 'nonlocal': ('nonlocal', 'global NAMESPACES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001673 'not': 'BOOLEAN',
1674 'or': 'BOOLEAN',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001675 'pass': ('pass', ''),
1676 'raise': ('raise', 'EXCEPTIONS'),
1677 'return': ('return', 'FUNCTIONS'),
1678 'try': ('try', 'EXCEPTIONS'),
1679 'while': ('while', 'break continue if TRUTHVALUE'),
1680 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1681 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001682 }
Georg Brandldb7b6b92009-01-01 15:53:14 +00001683 # Either add symbols to this dictionary or to the symbols dictionary
1684 # directly: Whichever is easier. They are merged later.
1685 _symbols_inverse = {
1686 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'),
1687 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1688 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1689 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1690 'UNARY' : ('-', '~'),
1691 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1692 '^=', '<<=', '>>=', '**=', '//='),
1693 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1694 'COMPLEX' : ('j', 'J')
1695 }
1696 symbols = {
1697 '%': 'OPERATORS FORMATTING',
1698 '**': 'POWER',
1699 ',': 'TUPLES LISTS FUNCTIONS',
1700 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1701 '...': 'ELLIPSIS',
1702 ':': 'SLICINGS DICTIONARYLITERALS',
1703 '@': 'def class',
1704 '\\': 'STRINGS',
1705 '_': 'PRIVATENAMES',
1706 '__': 'PRIVATENAMES SPECIALMETHODS',
1707 '`': 'BACKQUOTES',
1708 '(': 'TUPLES FUNCTIONS CALLS',
1709 ')': 'TUPLES FUNCTIONS CALLS',
1710 '[': 'LISTS SUBSCRIPTS SLICINGS',
1711 ']': 'LISTS SUBSCRIPTS SLICINGS'
1712 }
1713 for topic, symbols_ in _symbols_inverse.items():
1714 for symbol in symbols_:
1715 topics = symbols.get(symbol, topic)
1716 if topic not in topics:
1717 topics = topics + ' ' + topic
1718 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001719
1720 topics = {
Georg Brandl6b38daa2008-06-01 21:05:17 +00001721 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1722 'FUNCTIONS CLASSES MODULES FILES inspect'),
1723 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS '
1724 'FORMATTING TYPES'),
1725 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1726 'FORMATTING': ('formatstrings', 'OPERATORS'),
1727 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1728 'FORMATTING TYPES'),
1729 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1730 'INTEGER': ('integers', 'int range'),
1731 'FLOAT': ('floating', 'float math'),
1732 'COMPLEX': ('imaginary', 'complex cmath'),
1733 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING range LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001734 'MAPPINGS': 'DICTIONARIES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001735 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1736 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1737 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1738 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001739 'FRAMEOBJECTS': 'TYPES',
1740 'TRACEBACKS': 'TYPES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001741 'NONE': ('bltin-null-object', ''),
1742 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001743 'SPECIALATTRIBUTES': ('specialattrs', ''),
1744 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1745 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001746 'PACKAGES': 'import',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001747 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1748 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1749 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1750 'LISTS DICTIONARIES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001751 'OPERATORS': 'EXPRESSIONS',
1752 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001753 'OBJECTS': ('objects', 'TYPES'),
1754 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
Georg Brandl395ed242009-09-04 08:07:32 +00001755 'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS '
1756 'NUMBERMETHODS CLASSES'),
Mark Dickinsona56c4672009-01-27 18:17:45 +00001757 'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001758 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1759 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001760 'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS '
Georg Brandl6b38daa2008-06-01 21:05:17 +00001761 'SPECIALMETHODS'),
1762 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1763 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1764 'SPECIALMETHODS'),
1765 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001766 'NAMESPACES': ('naming', 'global nonlocal ASSIGNMENT DELETION DYNAMICFEATURES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001767 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001768 'SCOPING': 'NAMESPACES',
1769 'FRAMES': 'NAMESPACES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001770 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1771 'CONVERSIONS': ('conversions', ''),
1772 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1773 'SPECIALIDENTIFIERS': ('id-classes', ''),
1774 'PRIVATENAMES': ('atom-identifiers', ''),
1775 'LITERALS': ('atom-literals', 'STRINGS NUMBERS TUPLELITERALS '
1776 'LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001777 'TUPLES': 'SEQUENCES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001778 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1779 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1780 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1781 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1782 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1783 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001784 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'),
1785 'SLICINGS': ('slicings', 'SEQUENCEMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001786 'CALLS': ('calls', 'EXPRESSIONS'),
1787 'POWER': ('power', 'EXPRESSIONS'),
1788 'UNARY': ('unary', 'EXPRESSIONS'),
1789 'BINARY': ('binary', 'EXPRESSIONS'),
1790 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1791 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1792 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1793 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001794 'ASSERTION': 'assert',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001795 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1796 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001797 'DELETION': 'del',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001798 'RETURNING': 'return',
1799 'IMPORTING': 'import',
1800 'CONDITIONAL': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001801 'LOOPING': ('compound', 'for while break continue'),
1802 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1803 'DEBUGGING': ('debugger', 'pdb'),
1804 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001805 }
1806
Georg Brandl78aa3962010-07-31 21:51:48 +00001807 def __init__(self, input=None, output=None):
1808 self._input = input
1809 self._output = output
1810
Georg Brandl76ae3972010-08-01 06:32:55 +00001811 input = property(lambda self: self._input or sys.stdin)
1812 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001813
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001814 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001815 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001816 self()
1817 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001818 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001819
Alexander Belopolsky2e733c92010-07-04 17:00:20 +00001820 _GoInteractive = object()
1821 def __call__(self, request=_GoInteractive):
1822 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001823 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001824 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001825 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001826 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001827 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001828You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001829If you want to ask for help on a particular object directly from the
1830interpreter, you can type "help(object)". Executing "help('string')"
1831has the same effect as typing a particular string at the help> prompt.
1832''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001833
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001834 def interact(self):
1835 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001836 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001837 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001838 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001839 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001840 except (KeyboardInterrupt, EOFError):
1841 break
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001842 request = replace(request, '"', '', "'", '').strip()
1843 if request.lower() in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001844 self.help(request)
1845
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001846 def getline(self, prompt):
Guido van Rossum7c086c02008-01-02 03:52:38 +00001847 """Read one line, using input() when appropriate."""
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001848 if self.input is sys.stdin:
Guido van Rossum7c086c02008-01-02 03:52:38 +00001849 return input(prompt)
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001850 else:
1851 self.output.write(prompt)
1852 self.output.flush()
1853 return self.input.readline()
1854
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001855 def help(self, request):
1856 if type(request) is type(''):
R. David Murray1f1b9d32009-05-27 20:56:59 +00001857 request = request.strip()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001858 if request == 'help': self.intro()
1859 elif request == 'keywords': self.listkeywords()
Georg Brandldb7b6b92009-01-01 15:53:14 +00001860 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001861 elif request == 'topics': self.listtopics()
1862 elif request == 'modules': self.listmodules()
1863 elif request[:8] == 'modules ':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001864 self.listmodules(request.split()[1])
Georg Brandldb7b6b92009-01-01 15:53:14 +00001865 elif request in self.symbols: self.showsymbol(request)
Ezio Melottib185a042011-04-28 07:42:55 +03001866 elif request in ['True', 'False', 'None']:
1867 # special case these keywords since they are objects too
1868 doc(eval(request), 'Help on %s:')
Raymond Hettinger54f02222002-06-01 14:18:47 +00001869 elif request in self.keywords: self.showtopic(request)
1870 elif request in self.topics: self.showtopic(request)
Georg Brandld80d5f42010-12-03 07:47:22 +00001871 elif request: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001872 elif isinstance(request, Helper): self()
Georg Brandld80d5f42010-12-03 07:47:22 +00001873 else: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001874 self.output.write('\n')
1875
1876 def intro(self):
1877 self.output.write('''
R David Murray3d050dd2014-04-19 12:59:30 -04001878Welcome to Python %s's help utility!
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001879
1880If this is your first time using Python, you should definitely check out
R David Murrayde0f6292012-03-31 12:06:35 -04001881the tutorial on the Internet at http://docs.python.org/%s/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001882
1883Enter the name of any module, keyword, or topic to get help on writing
1884Python programs and using Python modules. To quit this help utility and
1885return to the interpreter, just type "quit".
1886
Terry Jan Reedy34200572013-02-11 02:23:13 -05001887To get a list of available modules, keywords, symbols, or topics, type
1888"modules", "keywords", "symbols", or "topics". Each module also comes
1889with a one-line summary of what it does; to list the modules whose name
1890or summary contain a given string such as "spam", type "modules spam".
R David Murrayde0f6292012-03-31 12:06:35 -04001891''' % tuple([sys.version[:3]]*2))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001892
1893 def list(self, items, columns=4, width=80):
Guido van Rossum486364b2007-06-30 05:01:58 +00001894 items = list(sorted(items))
1895 colw = width // columns
1896 rows = (len(items) + columns - 1) // columns
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001897 for row in range(rows):
1898 for col in range(columns):
1899 i = col * rows + row
1900 if i < len(items):
1901 self.output.write(items[i])
1902 if col < columns - 1:
Guido van Rossum486364b2007-06-30 05:01:58 +00001903 self.output.write(' ' + ' ' * (colw - 1 - len(items[i])))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001904 self.output.write('\n')
1905
1906 def listkeywords(self):
1907 self.output.write('''
1908Here is a list of the Python keywords. Enter any keyword to get more help.
1909
1910''')
1911 self.list(self.keywords.keys())
1912
Georg Brandldb7b6b92009-01-01 15:53:14 +00001913 def listsymbols(self):
1914 self.output.write('''
1915Here is a list of the punctuation symbols which Python assigns special meaning
1916to. Enter any symbol to get more help.
1917
1918''')
1919 self.list(self.symbols.keys())
1920
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001921 def listtopics(self):
1922 self.output.write('''
1923Here is a list of available topics. Enter any topic name to get more help.
1924
1925''')
1926 self.list(self.topics.keys())
1927
Georg Brandldb7b6b92009-01-01 15:53:14 +00001928 def showtopic(self, topic, more_xrefs=''):
Georg Brandl6b38daa2008-06-01 21:05:17 +00001929 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001930 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04001931 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001932 self.output.write('''
Georg Brandl6b38daa2008-06-01 21:05:17 +00001933Sorry, topic and keyword documentation is not available because the
Georg Brandl5617db82009-04-27 16:28:57 +00001934module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001935''')
1936 return
1937 target = self.topics.get(topic, self.keywords.get(topic))
1938 if not target:
1939 self.output.write('no documentation found for %s\n' % repr(topic))
1940 return
1941 if type(target) is type(''):
Georg Brandldb7b6b92009-01-01 15:53:14 +00001942 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001943
Georg Brandl6b38daa2008-06-01 21:05:17 +00001944 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001945 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001946 doc = pydoc_data.topics.topics[label]
Georg Brandl6b38daa2008-06-01 21:05:17 +00001947 except KeyError:
1948 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001949 return
Georg Brandl6b38daa2008-06-01 21:05:17 +00001950 pager(doc.strip() + '\n')
Georg Brandldb7b6b92009-01-01 15:53:14 +00001951 if more_xrefs:
1952 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001953 if xrefs:
Brett Cannon1448ecf2013-10-04 11:38:59 -04001954 import textwrap
1955 text = 'Related help topics: ' + ', '.join(xrefs.split()) + '\n'
1956 wrapped_text = textwrap.wrap(text, 72)
1957 self.output.write('\n%s\n' % ''.join(wrapped_text))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001958
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001959 def _gettopic(self, topic, more_xrefs=''):
1960 """Return unbuffered tuple of (topic, xrefs).
1961
Georg Brandld2f38572011-01-30 08:37:19 +00001962 If an error occurs here, the exception is caught and displayed by
1963 the url handler.
1964
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001965 This function duplicates the showtopic method but returns its
1966 result directly so it can be formatted for display in an html page.
1967 """
1968 try:
1969 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04001970 except ImportError:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001971 return('''
1972Sorry, topic and keyword documentation is not available because the
1973module "pydoc_data.topics" could not be found.
1974''' , '')
1975 target = self.topics.get(topic, self.keywords.get(topic))
1976 if not target:
Georg Brandld2f38572011-01-30 08:37:19 +00001977 raise ValueError('could not find topic')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001978 if isinstance(target, str):
1979 return self._gettopic(target, more_xrefs)
1980 label, xrefs = target
Georg Brandld2f38572011-01-30 08:37:19 +00001981 doc = pydoc_data.topics.topics[label]
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001982 if more_xrefs:
1983 xrefs = (xrefs or '') + ' ' + more_xrefs
1984 return doc, xrefs
1985
Georg Brandldb7b6b92009-01-01 15:53:14 +00001986 def showsymbol(self, symbol):
1987 target = self.symbols[symbol]
1988 topic, _, xrefs = target.partition(' ')
1989 self.showtopic(topic, xrefs)
1990
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001991 def listmodules(self, key=''):
1992 if key:
1993 self.output.write('''
Terry Jan Reedy34200572013-02-11 02:23:13 -05001994Here is a list of modules whose name or summary contains '{}'.
1995If there are any, enter a module name to get more help.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001996
Terry Jan Reedy34200572013-02-11 02:23:13 -05001997'''.format(key))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001998 apropos(key)
1999 else:
2000 self.output.write('''
2001Please wait a moment while I gather a list of all available modules...
2002
2003''')
2004 modules = {}
2005 def callback(path, modname, desc, modules=modules):
2006 if modname and modname[-9:] == '.__init__':
2007 modname = modname[:-9] + ' (package)'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002008 if modname.find('.') < 0:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002009 modules[modname] = 1
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002010 def onerror(modname):
2011 callback(None, modname, None)
2012 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002013 self.list(modules.keys())
2014 self.output.write('''
2015Enter any module name to get more help. Or, type "modules spam" to search
Terry Jan Reedy34200572013-02-11 02:23:13 -05002016for modules whose name or summary contain the string "spam".
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002017''')
2018
Georg Brandl78aa3962010-07-31 21:51:48 +00002019help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002020
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002021class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002022 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002023
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002024 def run(self, callback, key=None, completer=None, onerror=None):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002025 if key: key = key.lower()
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002026 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002027 seen = {}
2028
2029 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002030 if modname != '__main__':
2031 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00002032 if key is None:
2033 callback(None, modname, '')
2034 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002035 name = __import__(modname).__doc__ or ''
2036 desc = name.split('\n')[0]
2037 name = modname + ' - ' + desc
2038 if name.lower().find(key) >= 0:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002039 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002040
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002041 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002042 if self.quit:
2043 break
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002044
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002045 if key is None:
2046 callback(None, modname, '')
2047 else:
Georg Brandl126c8792009-04-05 15:05:48 +00002048 try:
Eric Snow3a62d142014-01-06 20:42:59 -07002049 spec = pkgutil._get_spec(importer, modname)
Georg Brandl126c8792009-04-05 15:05:48 +00002050 except SyntaxError:
2051 # raised by tests for bad coding cookies or BOM
2052 continue
Eric Snow3a62d142014-01-06 20:42:59 -07002053 loader = spec.loader
Georg Brandl126c8792009-04-05 15:05:48 +00002054 if hasattr(loader, 'get_source'):
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002055 try:
2056 source = loader.get_source(modname)
Nick Coghlan2824cb52012-07-15 22:12:14 +10002057 except Exception:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002058 if onerror:
2059 onerror(modname)
2060 continue
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002061 desc = source_synopsis(io.StringIO(source)) or ''
Georg Brandl126c8792009-04-05 15:05:48 +00002062 if hasattr(loader, 'get_filename'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002063 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002064 else:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002065 path = None
2066 else:
Eric Snow3a62d142014-01-06 20:42:59 -07002067 _spec = importlib._bootstrap._SpecMethods(spec)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002068 try:
Eric Snow3a62d142014-01-06 20:42:59 -07002069 module = _spec.load()
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002070 except ImportError:
2071 if onerror:
2072 onerror(modname)
2073 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002074 desc = (module.__doc__ or '').splitlines()[0]
2075 path = getattr(module,'__file__',None)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002076 name = modname + ' - ' + desc
2077 if name.lower().find(key) >= 0:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002078 callback(path, modname, desc)
2079
2080 if completer:
2081 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002082
2083def apropos(key):
2084 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002085 def callback(path, modname, desc):
2086 if modname[-9:] == '.__init__':
2087 modname = modname[:-9] + ' (package)'
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002088 print(modname, desc and '- ' + desc)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002089 def onerror(modname):
2090 pass
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002091 with warnings.catch_warnings():
2092 warnings.filterwarnings('ignore') # ignore problems during import
2093 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002094
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002095# --------------------------------------- enhanced Web browser interface
2096
2097def _start_server(urlhandler, port):
2098 """Start an HTTP server thread on a specific port.
2099
2100 Start an HTML/text server thread, so HTML or text documents can be
2101 browsed dynamically and interactively with a Web browser. Example use:
2102
2103 >>> import time
2104 >>> import pydoc
2105
2106 Define a URL handler. To determine what the client is asking
2107 for, check the URL and content_type.
2108
2109 Then get or generate some text or HTML code and return it.
2110
2111 >>> def my_url_handler(url, content_type):
2112 ... text = 'the URL sent was: (%s, %s)' % (url, content_type)
2113 ... return text
2114
2115 Start server thread on port 0.
2116 If you use port 0, the server will pick a random port number.
2117 You can then use serverthread.port to get the port number.
2118
2119 >>> port = 0
2120 >>> serverthread = pydoc._start_server(my_url_handler, port)
2121
2122 Check that the server is really started. If it is, open browser
2123 and get first page. Use serverthread.url as the starting page.
2124
2125 >>> if serverthread.serving:
2126 ... import webbrowser
2127
2128 The next two lines are commented out so a browser doesn't open if
2129 doctest is run on this module.
2130
2131 #... webbrowser.open(serverthread.url)
2132 #True
2133
2134 Let the server do its thing. We just need to monitor its status.
2135 Use time.sleep so the loop doesn't hog the CPU.
2136
2137 >>> starttime = time.time()
2138 >>> timeout = 1 #seconds
2139
2140 This is a short timeout for testing purposes.
2141
2142 >>> while serverthread.serving:
2143 ... time.sleep(.01)
2144 ... if serverthread.serving and time.time() - starttime > timeout:
2145 ... serverthread.stop()
2146 ... break
2147
2148 Print any errors that may have occurred.
2149
2150 >>> print(serverthread.error)
2151 None
2152 """
2153 import http.server
2154 import email.message
2155 import select
2156 import threading
2157
2158 class DocHandler(http.server.BaseHTTPRequestHandler):
2159
2160 def do_GET(self):
2161 """Process a request from an HTML browser.
2162
2163 The URL received is in self.path.
2164 Get an HTML page from self.urlhandler and send it.
2165 """
2166 if self.path.endswith('.css'):
2167 content_type = 'text/css'
2168 else:
2169 content_type = 'text/html'
2170 self.send_response(200)
Georg Brandld2f38572011-01-30 08:37:19 +00002171 self.send_header('Content-Type', '%s; charset=UTF-8' % content_type)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002172 self.end_headers()
2173 self.wfile.write(self.urlhandler(
2174 self.path, content_type).encode('utf-8'))
2175
2176 def log_message(self, *args):
2177 # Don't log messages.
2178 pass
2179
2180 class DocServer(http.server.HTTPServer):
2181
2182 def __init__(self, port, callback):
2183 self.host = (sys.platform == 'mac') and '127.0.0.1' or 'localhost'
2184 self.address = ('', port)
2185 self.callback = callback
2186 self.base.__init__(self, self.address, self.handler)
2187 self.quit = False
2188
2189 def serve_until_quit(self):
2190 while not self.quit:
2191 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2192 if rd:
2193 self.handle_request()
Victor Stinnera3abd1d2011-01-03 16:12:39 +00002194 self.server_close()
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002195
2196 def server_activate(self):
2197 self.base.server_activate(self)
2198 if self.callback:
2199 self.callback(self)
2200
2201 class ServerThread(threading.Thread):
2202
2203 def __init__(self, urlhandler, port):
2204 self.urlhandler = urlhandler
2205 self.port = int(port)
2206 threading.Thread.__init__(self)
2207 self.serving = False
2208 self.error = None
2209
2210 def run(self):
2211 """Start the server."""
2212 try:
2213 DocServer.base = http.server.HTTPServer
2214 DocServer.handler = DocHandler
2215 DocHandler.MessageClass = email.message.Message
2216 DocHandler.urlhandler = staticmethod(self.urlhandler)
2217 docsvr = DocServer(self.port, self.ready)
2218 self.docserver = docsvr
2219 docsvr.serve_until_quit()
2220 except Exception as e:
2221 self.error = e
2222
2223 def ready(self, server):
2224 self.serving = True
2225 self.host = server.host
2226 self.port = server.server_port
2227 self.url = 'http://%s:%d/' % (self.host, self.port)
2228
2229 def stop(self):
2230 """Stop the server and this thread nicely"""
2231 self.docserver.quit = True
2232 self.serving = False
2233 self.url = None
2234
2235 thread = ServerThread(urlhandler, port)
2236 thread.start()
2237 # Wait until thread.serving is True to make sure we are
2238 # really up before returning.
2239 while not thread.error and not thread.serving:
2240 time.sleep(.01)
2241 return thread
2242
2243
2244def _url_handler(url, content_type="text/html"):
2245 """The pydoc url handler for use with the pydoc server.
2246
2247 If the content_type is 'text/css', the _pydoc.css style
2248 sheet is read and returned if it exits.
2249
2250 If the content_type is 'text/html', then the result of
2251 get_html_page(url) is returned.
2252 """
2253 class _HTMLDoc(HTMLDoc):
2254
2255 def page(self, title, contents):
2256 """Format an HTML page."""
2257 css_path = "pydoc_data/_pydoc.css"
2258 css_link = (
2259 '<link rel="stylesheet" type="text/css" href="%s">' %
2260 css_path)
2261 return '''\
2262<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Georg Brandld2f38572011-01-30 08:37:19 +00002263<html><head><title>Pydoc: %s</title>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002264<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Georg Brandld2f38572011-01-30 08:37:19 +00002265%s</head><body bgcolor="#f0f0f8">%s<div style="clear:both;padding-top:.5em;">%s</div>
2266</body></html>''' % (title, css_link, html_navbar(), contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002267
2268 def filelink(self, url, path):
2269 return '<a href="getfile?key=%s">%s</a>' % (url, path)
2270
2271
2272 html = _HTMLDoc()
2273
2274 def html_navbar():
Georg Brandld2f38572011-01-30 08:37:19 +00002275 version = html.escape("%s [%s, %s]" % (platform.python_version(),
2276 platform.python_build()[0],
2277 platform.python_compiler()))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002278 return """
2279 <div style='float:left'>
Georg Brandld2f38572011-01-30 08:37:19 +00002280 Python %s<br>%s
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002281 </div>
2282 <div style='float:right'>
2283 <div style='text-align:center'>
2284 <a href="index.html">Module Index</a>
2285 : <a href="topics.html">Topics</a>
2286 : <a href="keywords.html">Keywords</a>
2287 </div>
2288 <div>
Georg Brandld2f38572011-01-30 08:37:19 +00002289 <form action="get" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002290 <input type=text name=key size=15>
2291 <input type=submit value="Get">
Georg Brandld2f38572011-01-30 08:37:19 +00002292 </form>&nbsp;
2293 <form action="search" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002294 <input type=text name=key size=15>
2295 <input type=submit value="Search">
2296 </form>
2297 </div>
2298 </div>
Georg Brandld2f38572011-01-30 08:37:19 +00002299 """ % (version, html.escape(platform.platform(terse=True)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002300
2301 def html_index():
2302 """Module Index page."""
2303
2304 def bltinlink(name):
2305 return '<a href="%s.html">%s</a>' % (name, name)
2306
2307 heading = html.heading(
2308 '<big><big><strong>Index of Modules</strong></big></big>',
2309 '#ffffff', '#7799ee')
2310 names = [name for name in sys.builtin_module_names
2311 if name != '__main__']
2312 contents = html.multicolumn(names, bltinlink)
2313 contents = [heading, '<p>' + html.bigsection(
2314 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2315
2316 seen = {}
2317 for dir in sys.path:
2318 contents.append(html.index(dir, seen))
2319
2320 contents.append(
2321 '<p align=right><font color="#909090" face="helvetica,'
2322 'arial"><strong>pydoc</strong> by Ka-Ping Yee'
2323 '&lt;ping@lfw.org&gt;</font>')
Nick Coghlanecace282010-12-03 16:08:46 +00002324 return 'Index of Modules', ''.join(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002325
2326 def html_search(key):
2327 """Search results page."""
2328 # scan for modules
2329 search_result = []
2330
2331 def callback(path, modname, desc):
2332 if modname[-9:] == '.__init__':
2333 modname = modname[:-9] + ' (package)'
2334 search_result.append((modname, desc and '- ' + desc))
2335
2336 with warnings.catch_warnings():
2337 warnings.filterwarnings('ignore') # ignore problems during import
2338 ModuleScanner().run(callback, key)
2339
2340 # format page
2341 def bltinlink(name):
2342 return '<a href="%s.html">%s</a>' % (name, name)
2343
2344 results = []
2345 heading = html.heading(
2346 '<big><big><strong>Search Results</strong></big></big>',
2347 '#ffffff', '#7799ee')
2348 for name, desc in search_result:
2349 results.append(bltinlink(name) + desc)
2350 contents = heading + html.bigsection(
2351 'key = %s' % key, '#ffffff', '#ee77aa', '<br>'.join(results))
Nick Coghlanecace282010-12-03 16:08:46 +00002352 return 'Search Results', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002353
2354 def html_getfile(path):
2355 """Get and display a source file listing safely."""
Nick Coghlanecace282010-12-03 16:08:46 +00002356 path = path.replace('%20', ' ')
Victor Stinner91e08772011-07-05 14:30:41 +02002357 with tokenize.open(path) as fp:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002358 lines = html.escape(fp.read())
2359 body = '<pre>%s</pre>' % lines
2360 heading = html.heading(
2361 '<big><big><strong>File Listing</strong></big></big>',
2362 '#ffffff', '#7799ee')
2363 contents = heading + html.bigsection(
2364 'File: %s' % path, '#ffffff', '#ee77aa', body)
Nick Coghlanecace282010-12-03 16:08:46 +00002365 return 'getfile %s' % path, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002366
2367 def html_topics():
2368 """Index of topic texts available."""
2369
2370 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002371 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002372
2373 heading = html.heading(
2374 '<big><big><strong>INDEX</strong></big></big>',
2375 '#ffffff', '#7799ee')
2376 names = sorted(Helper.topics.keys())
2377
2378 contents = html.multicolumn(names, bltinlink)
2379 contents = heading + html.bigsection(
2380 'Topics', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002381 return 'Topics', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002382
2383 def html_keywords():
2384 """Index of keywords."""
2385 heading = html.heading(
2386 '<big><big><strong>INDEX</strong></big></big>',
2387 '#ffffff', '#7799ee')
2388 names = sorted(Helper.keywords.keys())
2389
2390 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002391 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002392
2393 contents = html.multicolumn(names, bltinlink)
2394 contents = heading + html.bigsection(
2395 'Keywords', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002396 return 'Keywords', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002397
2398 def html_topicpage(topic):
2399 """Topic or keyword help page."""
2400 buf = io.StringIO()
2401 htmlhelp = Helper(buf, buf)
2402 contents, xrefs = htmlhelp._gettopic(topic)
2403 if topic in htmlhelp.keywords:
2404 title = 'KEYWORD'
2405 else:
2406 title = 'TOPIC'
2407 heading = html.heading(
2408 '<big><big><strong>%s</strong></big></big>' % title,
2409 '#ffffff', '#7799ee')
Georg Brandld2f38572011-01-30 08:37:19 +00002410 contents = '<pre>%s</pre>' % html.markup(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002411 contents = html.bigsection(topic , '#ffffff','#ee77aa', contents)
Georg Brandld2f38572011-01-30 08:37:19 +00002412 if xrefs:
2413 xrefs = sorted(xrefs.split())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002414
Georg Brandld2f38572011-01-30 08:37:19 +00002415 def bltinlink(name):
2416 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002417
Georg Brandld2f38572011-01-30 08:37:19 +00002418 xrefs = html.multicolumn(xrefs, bltinlink)
2419 xrefs = html.section('Related help topics: ',
2420 '#ffffff', '#ee77aa', xrefs)
Nick Coghlanecace282010-12-03 16:08:46 +00002421 return ('%s %s' % (title, topic),
2422 ''.join((heading, contents, xrefs)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002423
Georg Brandld2f38572011-01-30 08:37:19 +00002424 def html_getobj(url):
2425 obj = locate(url, forceload=1)
2426 if obj is None and url != 'None':
2427 raise ValueError('could not find object')
2428 title = describe(obj)
2429 content = html.document(obj, url)
2430 return title, content
2431
2432 def html_error(url, exc):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002433 heading = html.heading(
2434 '<big><big><strong>Error</strong></big></big>',
Georg Brandld2f38572011-01-30 08:37:19 +00002435 '#ffffff', '#7799ee')
2436 contents = '<br>'.join(html.escape(line) for line in
2437 format_exception_only(type(exc), exc))
2438 contents = heading + html.bigsection(url, '#ffffff', '#bb0000',
2439 contents)
2440 return "Error - %s" % url, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002441
2442 def get_html_page(url):
2443 """Generate an HTML page for url."""
Georg Brandld2f38572011-01-30 08:37:19 +00002444 complete_url = url
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002445 if url.endswith('.html'):
2446 url = url[:-5]
Georg Brandld2f38572011-01-30 08:37:19 +00002447 try:
2448 if url in ("", "index"):
2449 title, content = html_index()
2450 elif url == "topics":
2451 title, content = html_topics()
2452 elif url == "keywords":
2453 title, content = html_keywords()
2454 elif '=' in url:
2455 op, _, url = url.partition('=')
2456 if op == "search?key":
2457 title, content = html_search(url)
2458 elif op == "getfile?key":
2459 title, content = html_getfile(url)
2460 elif op == "topic?key":
2461 # try topics first, then objects.
2462 try:
2463 title, content = html_topicpage(url)
2464 except ValueError:
2465 title, content = html_getobj(url)
2466 elif op == "get?key":
2467 # try objects first, then topics.
2468 if url in ("", "index"):
2469 title, content = html_index()
2470 else:
2471 try:
2472 title, content = html_getobj(url)
2473 except ValueError:
2474 title, content = html_topicpage(url)
2475 else:
2476 raise ValueError('bad pydoc url')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002477 else:
Georg Brandld2f38572011-01-30 08:37:19 +00002478 title, content = html_getobj(url)
2479 except Exception as exc:
2480 # Catch any errors and display them in an error page.
2481 title, content = html_error(complete_url, exc)
2482 return html.page(title, content)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002483
2484 if url.startswith('/'):
2485 url = url[1:]
2486 if content_type == 'text/css':
2487 path_here = os.path.dirname(os.path.realpath(__file__))
Georg Brandld2f38572011-01-30 08:37:19 +00002488 css_path = os.path.join(path_here, url)
2489 with open(css_path) as fp:
2490 return ''.join(fp.readlines())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002491 elif content_type == 'text/html':
2492 return get_html_page(url)
Georg Brandld2f38572011-01-30 08:37:19 +00002493 # Errors outside the url handler are caught by the server.
2494 raise TypeError('unknown content type %r for url %s' % (content_type, url))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002495
2496
2497def browse(port=0, *, open_browser=True):
2498 """Start the enhanced pydoc Web server and open a Web browser.
2499
2500 Use port '0' to start the server on an arbitrary port.
2501 Set open_browser to False to suppress opening a browser.
2502 """
2503 import webbrowser
2504 serverthread = _start_server(_url_handler, port)
2505 if serverthread.error:
2506 print(serverthread.error)
2507 return
2508 if serverthread.serving:
2509 server_help_msg = 'Server commands: [b]rowser, [q]uit'
2510 if open_browser:
2511 webbrowser.open(serverthread.url)
2512 try:
2513 print('Server ready at', serverthread.url)
2514 print(server_help_msg)
2515 while serverthread.serving:
2516 cmd = input('server> ')
2517 cmd = cmd.lower()
2518 if cmd == 'q':
2519 break
2520 elif cmd == 'b':
2521 webbrowser.open(serverthread.url)
2522 else:
2523 print(server_help_msg)
2524 except (KeyboardInterrupt, EOFError):
2525 print()
2526 finally:
2527 if serverthread.serving:
2528 serverthread.stop()
2529 print('Server stopped')
2530
2531
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002532# -------------------------------------------------- command-line interface
2533
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002534def ispath(x):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002535 return isinstance(x, str) and x.find(os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002536
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002537def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002538 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002539 import getopt
Guido van Rossum756aa932007-04-07 03:04:01 +00002540 class BadUsage(Exception): pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002541
Nick Coghlan106274b2009-11-15 23:04:33 +00002542 # Scripts don't get the current directory in their path by default
2543 # unless they are run with the '-m' switch
2544 if '' not in sys.path:
2545 scriptdir = os.path.dirname(sys.argv[0])
2546 if scriptdir in sys.path:
2547 sys.path.remove(scriptdir)
2548 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002549
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002550 try:
Victor Stinner383c3fc2011-05-25 01:35:05 +02002551 opts, args = getopt.getopt(sys.argv[1:], 'bk:p:w')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002552 writing = False
2553 start_server = False
2554 open_browser = False
2555 port = None
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002556 for opt, val in opts:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002557 if opt == '-b':
2558 start_server = True
2559 open_browser = True
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002560 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002561 apropos(val)
2562 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002563 if opt == '-p':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002564 start_server = True
2565 port = val
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002566 if opt == '-w':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002567 writing = True
2568
Benjamin Petersonb29614e2012-10-09 11:16:03 -04002569 if start_server:
2570 if port is None:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002571 port = 0
2572 browse(port, open_browser=open_browser)
2573 return
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002574
2575 if not args: raise BadUsage
2576 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002577 if ispath(arg) and not os.path.exists(arg):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002578 print('file %r does not exist' % arg)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002579 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002580 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002581 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002582 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002583 if writing:
2584 if ispath(arg) and os.path.isdir(arg):
2585 writedocs(arg)
2586 else:
2587 writedoc(arg)
2588 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002589 help.help(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +00002590 except ErrorDuringImport as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002591 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002592
2593 except (getopt.error, BadUsage):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002594 cmd = os.path.splitext(os.path.basename(sys.argv[0]))[0]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002595 print("""pydoc - the Python documentation tool
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002596
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002597{cmd} <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002598 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002599 Python keyword, topic, function, module, or package, or a dotted
2600 reference to a class or function within a module or module in a
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002601 package. If <name> contains a '{sep}', it is used as the path to a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002602 Python source file to document. If name is 'keywords', 'topics',
2603 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002604
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002605{cmd} -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002606 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002607
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002608{cmd} -p <port>
2609 Start an HTTP server on the given port on the local machine. Port
2610 number 0 can be used to get an arbitrary unused port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002611
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002612{cmd} -b
2613 Start an HTTP server on an arbitrary unused port and open a Web browser
2614 to interactively browse documentation. The -p option can be used with
2615 the -b option to explicitly specify the server port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002616
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002617{cmd} -w <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002618 Write out the HTML documentation for a module to a file in the current
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002619 directory. If <name> contains a '{sep}', it is treated as a filename; if
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002620 it names a directory, documentation is written for all the contents.
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002621""".format(cmd=cmd, sep=os.sep))
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002622
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002623if __name__ == '__main__':
2624 cli()