blob: 3873d5554acf4753e4405a115415970f402491c7 [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
Georg Brandlc645c6a2012-06-24 17:24:26 +02004In the Python interpreter, do "from pydoc import help" to provide
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00005help. Calling help(thing) on a Python object documents the object.
6
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00007Or, at the shell command line outside of Python:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00008
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00009Run "pydoc <name>" to show documentation on something. <name> may be
10the name of a function, module, package, or a dotted reference to a
11class or function within a module or module in a package. If the
12argument contains a path segment delimiter (e.g. slash on Unix,
13backslash on Windows) it is treated as the path to a Python source file.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000014
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000015Run "pydoc -k <keyword>" to search for a keyword in the synopsis lines
16of all available modules.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000017
Nick Coghlan7bb30b72010-12-03 09:29:11 +000018Run "pydoc -p <port>" to start an HTTP server on the given port on the
19local machine. Port number 0 can be used to get an arbitrary unused port.
20
21Run "pydoc -b" to start an HTTP server on an arbitrary unused port and
22open a Web browser to interactively browse documentation. The -p option
23can be used with the -b option to explicitly specify the server port.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000024
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000025Run "pydoc -w <name>" to write out the HTML documentation for a module
26to a file named "<name>.html".
Skip Montanaro4997a692003-09-10 16:47:51 +000027
28Module docs for core modules are assumed to be in
29
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000030 http://docs.python.org/X.Y/library/
Skip Montanaro4997a692003-09-10 16:47:51 +000031
32This can be overridden by setting the PYTHONDOCS environment variable
33to a different URL or to a local directory containing the Library
34Reference Manual pages.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000035"""
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000036__all__ = ['help']
Ka-Ping Yeedd175342001-02-27 14:43:46 +000037__author__ = "Ka-Ping Yee <ping@lfw.org>"
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000038__date__ = "26 February 2001"
Jeremy Hylton3e0055f2005-10-20 19:59:25 +000039
Martin v. Löwis6fe8f192004-11-14 10:21:04 +000040__credits__ = """Guido van Rossum, for an excellent programming language.
Ka-Ping Yee5e2b1732001-02-27 23:35:09 +000041Tommy Burnette, the original creator of manpy.
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000042Paul Prescod, for all his work on onlinehelp.
43Richard Chamberlain, for the first implementation of textdoc.
Raymond Hettingered2dbe32005-01-01 07:51:01 +000044"""
Ka-Ping Yeedd175342001-02-27 14:43:46 +000045
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000046# Known bugs that can't be fixed here:
Brett Cannonf4ba4ec2013-06-15 14:25:04 -040047# - synopsis() cannot be prevented from clobbering existing
48# loaded modules.
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000049# - If the __file__ attribute on a module is a relative path and
50# the current directory is changed with os.chdir(), an incorrect
51# path will be displayed.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000052
Nick Coghlan7bb30b72010-12-03 09:29:11 +000053import builtins
Brett Cannond5e6f2e2013-06-11 17:09:36 -040054import importlib._bootstrap
Brett Cannoncb66eb02012-05-11 12:58:42 -040055import importlib.machinery
Brett Cannonf4ba4ec2013-06-15 14:25:04 -040056import importlib.util
Nick Coghlan7bb30b72010-12-03 09:29:11 +000057import inspect
Victor Stinnere6c910e2011-06-30 15:55:43 +020058import io
59import os
Nick Coghlan7bb30b72010-12-03 09:29:11 +000060import pkgutil
61import platform
62import re
Victor Stinnere6c910e2011-06-30 15:55:43 +020063import sys
Nick Coghlan7bb30b72010-12-03 09:29:11 +000064import time
Victor Stinnere6c910e2011-06-30 15:55:43 +020065import tokenize
Nick Coghlan7bb30b72010-12-03 09:29:11 +000066import warnings
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000067from collections import deque
Nick Coghlan7bb30b72010-12-03 09:29:11 +000068from reprlib import Repr
Georg Brandld2f38572011-01-30 08:37:19 +000069from traceback import extract_tb, format_exception_only
Nick Coghlan7bb30b72010-12-03 09:29:11 +000070
71
Ka-Ping Yeedd175342001-02-27 14:43:46 +000072# --------------------------------------------------------- common routines
73
Ka-Ping Yeedd175342001-02-27 14:43:46 +000074def pathdirs():
75 """Convert sys.path into a list of absolute, existing, unique paths."""
76 dirs = []
Ka-Ping Yee1d384632001-03-01 00:24:32 +000077 normdirs = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +000078 for dir in sys.path:
79 dir = os.path.abspath(dir or '.')
Ka-Ping Yee1d384632001-03-01 00:24:32 +000080 normdir = os.path.normcase(dir)
81 if normdir not in normdirs and os.path.isdir(dir):
Ka-Ping Yeedd175342001-02-27 14:43:46 +000082 dirs.append(dir)
Ka-Ping Yee1d384632001-03-01 00:24:32 +000083 normdirs.append(normdir)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000084 return dirs
85
86def getdoc(object):
87 """Get the doc string or comments for an object."""
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000088 result = inspect.getdoc(object) or inspect.getcomments(object)
Neal Norwitz9d72bb42007-04-17 08:48:32 +000089 return result and re.sub('^ *\n', '', result.rstrip()) or ''
Ka-Ping Yeedd175342001-02-27 14:43:46 +000090
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000091def splitdoc(doc):
92 """Split a doc string into a synopsis line (if any) and the rest."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +000093 lines = doc.strip().split('\n')
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000094 if len(lines) == 1:
95 return lines[0], ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +000096 elif len(lines) >= 2 and not lines[1].rstrip():
97 return lines[0], '\n'.join(lines[2:])
98 return '', '\n'.join(lines)
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000099
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000100def classname(object, modname):
101 """Get a class name and qualify it with a module name if necessary."""
102 name = object.__name__
103 if object.__module__ != modname:
104 name = object.__module__ + '.' + name
105 return name
106
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000107def isdata(object):
Georg Brandl94432422005-07-22 21:52:25 +0000108 """Check if an object is of a type that probably means it's data."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000109 return not (inspect.ismodule(object) or inspect.isclass(object) or
110 inspect.isroutine(object) or inspect.isframe(object) or
111 inspect.istraceback(object) or inspect.iscode(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000112
113def replace(text, *pairs):
114 """Do a series of global replacements on a string."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000115 while pairs:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000116 text = pairs[1].join(text.split(pairs[0]))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000117 pairs = pairs[2:]
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000118 return text
119
120def cram(text, maxlen):
121 """Omit part of a string if needed to make it fit in a maximum length."""
122 if len(text) > maxlen:
Raymond Hettingerfca3bb62002-10-21 04:44:11 +0000123 pre = max(0, (maxlen-3)//2)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000124 post = max(0, maxlen-3-pre)
125 return text[:pre] + '...' + text[len(text)-post:]
126 return text
127
Brett Cannon84601f12004-06-19 01:22:48 +0000128_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000129def stripid(text):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000130 """Remove the hexadecimal id from a Python object representation."""
Brett Cannonc6c1f472004-06-19 01:02:51 +0000131 # The behaviour of %p is implementation-dependent in terms of case.
Ezio Melotti412c95a2010-02-16 23:31:04 +0000132 return _re_stripid.sub(r'\1', text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000133
Brett Cannonc6c1f472004-06-19 01:02:51 +0000134def _is_some_method(obj):
R David Murrayac0cea52013-03-19 02:47:44 -0400135 return (inspect.isfunction(obj) or
136 inspect.ismethod(obj) or
137 inspect.isbuiltin(obj) or
138 inspect.ismethoddescriptor(obj))
Tim Peters536d2262001-09-20 05:13:38 +0000139
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000140def allmethods(cl):
141 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000142 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000143 methods[key] = 1
144 for base in cl.__bases__:
145 methods.update(allmethods(base)) # all your base are belong to us
146 for key in methods.keys():
147 methods[key] = getattr(cl, key)
148 return methods
149
Tim Petersfa26f7c2001-09-24 08:05:11 +0000150def _split_list(s, predicate):
151 """Split sequence s via predicate, and return pair ([true], [false]).
152
153 The return value is a 2-tuple of lists,
154 ([x for x in s if predicate(x)],
155 [x for x in s if not predicate(x)])
156 """
157
Tim Peters28355492001-09-23 21:29:55 +0000158 yes = []
159 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000160 for x in s:
161 if predicate(x):
162 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000163 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000164 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000165 return yes, no
166
Raymond Hettinger1103d052011-03-25 14:15:24 -0700167def visiblename(name, all=None, obj=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000168 """Decide whether to show documentation on a variable."""
Brett Cannond340b432012-08-06 17:19:22 -0400169 # Certain special names are redundant or internal.
Eric Snowb523f842013-11-22 09:05:39 -0700170 # XXX Remove __initializing__?
Brett Cannond340b432012-08-06 17:19:22 -0400171 if name in {'__author__', '__builtins__', '__cached__', '__credits__',
Eric Snowb523f842013-11-22 09:05:39 -0700172 '__date__', '__doc__', '__file__', '__spec__',
Brett Cannond340b432012-08-06 17:19:22 -0400173 '__loader__', '__module__', '__name__', '__package__',
174 '__path__', '__qualname__', '__slots__', '__version__'}:
Raymond Hettinger68272942011-03-18 02:22:15 -0700175 return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000176 # Private names are hidden, but special names are displayed.
177 if name.startswith('__') and name.endswith('__'): return 1
Raymond Hettinger1103d052011-03-25 14:15:24 -0700178 # Namedtuples have public fields and methods with a single leading underscore
179 if name.startswith('_') and hasattr(obj, '_fields'):
180 return True
Skip Montanaroa5616d22004-06-11 04:46:12 +0000181 if all is not None:
182 # only document that which the programmer exported in __all__
183 return name in all
184 else:
185 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000186
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000187def classify_class_attrs(object):
188 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000189 results = []
190 for (name, kind, cls, value) in inspect.classify_class_attrs(object):
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000191 if inspect.isdatadescriptor(value):
192 kind = 'data descriptor'
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000193 results.append((name, kind, cls, value))
194 return results
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000195
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000196# ----------------------------------------------------- module manipulation
197
198def ispackage(path):
199 """Guess whether a path refers to a package directory."""
200 if os.path.isdir(path):
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000201 for ext in ('.py', '.pyc', '.pyo'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000202 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000203 return True
204 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000205
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000206def source_synopsis(file):
207 line = file.readline()
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000208 while line[:1] == '#' or not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000209 line = file.readline()
210 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000211 line = line.strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000212 if line[:4] == 'r"""': line = line[1:]
213 if line[:3] == '"""':
214 line = line[3:]
215 if line[-1:] == '\\': line = line[:-1]
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000216 while not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000217 line = file.readline()
218 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000219 result = line.split('"""')[0].strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000220 else: result = None
221 return result
222
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000223def synopsis(filename, cache={}):
224 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000225 mtime = os.stat(filename).st_mtime
Charles-François Natali27c4e882011-07-27 19:40:02 +0200226 lastupdate, result = cache.get(filename, (None, None))
227 if lastupdate is None or lastupdate < mtime:
Eric Snowaed5b222014-01-04 20:38:11 -0700228 # Look for binary suffixes first, falling back to source.
229 if filename.endswith(tuple(importlib.machinery.BYTECODE_SUFFIXES)):
230 loader_cls = importlib.machinery.SourcelessFileLoader
231 elif filename.endswith(tuple(importlib.machinery.EXTENSION_SUFFIXES)):
232 loader_cls = importlib.machinery.ExtensionFileLoader
233 else:
234 loader_cls = None
235 # Now handle the choice.
236 if loader_cls is None:
237 # Must be a source file.
238 try:
239 file = tokenize.open(filename)
240 except OSError:
241 # module can't be opened, so skip it
242 return None
243 # text modules can be directly examined
244 with file:
245 result = source_synopsis(file)
246 else:
247 # Must be a binary module, which has to be imported.
248 loader = loader_cls('__temp__', filename)
Eric Snow3a62d142014-01-06 20:42:59 -0700249 # XXX We probably don't need to pass in the loader here.
250 spec = importlib.util.spec_from_file_location('__temp__', filename,
251 loader=loader)
252 _spec = importlib._bootstrap._SpecMethods(spec)
Brett Cannoncb66eb02012-05-11 12:58:42 -0400253 try:
Eric Snow3a62d142014-01-06 20:42:59 -0700254 module = _spec.load()
Brett Cannoncb66eb02012-05-11 12:58:42 -0400255 except:
256 return None
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000257 del sys.modules['__temp__']
Eric Snowaed5b222014-01-04 20:38:11 -0700258 result = (module.__doc__ or '').splitlines()[0]
259 # Cache the result.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000260 cache[filename] = (mtime, result)
261 return result
262
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000263class ErrorDuringImport(Exception):
264 """Errors that occurred while trying to import something to document it."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000265 def __init__(self, filename, exc_info):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000266 self.filename = filename
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000267 self.exc, self.value, self.tb = exc_info
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000268
269 def __str__(self):
Guido van Rossuma01a8b62007-05-27 09:20:14 +0000270 exc = self.exc.__name__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000271 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000272
273def importfile(path):
274 """Import a Python source file or compiled file given its path."""
Brett Cannonf4ba4ec2013-06-15 14:25:04 -0400275 magic = importlib.util.MAGIC_NUMBER
Victor Stinnere975af62011-07-04 02:08:50 +0200276 with open(path, 'rb') as file:
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400277 is_bytecode = magic == file.read(len(magic))
278 filename = os.path.basename(path)
279 name, ext = os.path.splitext(filename)
280 if is_bytecode:
281 loader = importlib._bootstrap.SourcelessFileLoader(name, path)
282 else:
283 loader = importlib._bootstrap.SourceFileLoader(name, path)
Eric Snow3a62d142014-01-06 20:42:59 -0700284 # XXX We probably don't need to pass in the loader here.
285 spec = importlib.util.spec_from_file_location(name, path, loader=loader)
286 _spec = importlib._bootstrap._SpecMethods(spec)
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400287 try:
Eric Snow3a62d142014-01-06 20:42:59 -0700288 return _spec.load()
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400289 except:
290 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000291
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000292def safeimport(path, forceload=0, cache={}):
293 """Import a module; handle errors; return None if the module isn't found.
294
295 If the module *is* found but an exception occurs, it's wrapped in an
296 ErrorDuringImport exception and reraised. Unlike __import__, if a
297 package path is specified, the module at the end of the path is returned,
298 not the package at the beginning. If the optional 'forceload' argument
299 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000300 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000301 # If forceload is 1 and the module has been previously loaded from
302 # disk, we always have to reload the module. Checking the file's
303 # mtime isn't good enough (e.g. the module could contain a class
304 # that inherits from another module that has changed).
305 if forceload and path in sys.modules:
306 if path not in sys.builtin_module_names:
Guido van Rossume7ba4952007-06-06 23:52:48 +0000307 # Remove the module from sys.modules and re-import to try
308 # and avoid problems with partially loaded modules.
309 # Also remove any submodules because they won't appear
310 # in the newly loaded module's namespace if they're already
311 # in sys.modules.
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000312 subs = [m for m in sys.modules if m.startswith(path + '.')]
313 for key in [path] + subs:
314 # Prevent garbage collection.
315 cache[key] = sys.modules[key]
316 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000317 module = __import__(path)
318 except:
319 # Did the error occur before or after the module was found?
320 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000321 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000322 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000323 raise ErrorDuringImport(sys.modules[path].__file__, info)
324 elif exc is SyntaxError:
325 # A SyntaxError occurred before we could execute the module.
326 raise ErrorDuringImport(value.filename, info)
Brett Cannon679ecb52013-07-04 17:51:50 -0400327 elif exc is ImportError and value.name == path:
Brett Cannonfd074152012-04-14 14:10:13 -0400328 # No such module in the path.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000329 return None
330 else:
331 # Some other error occurred during the importing process.
332 raise ErrorDuringImport(path, sys.exc_info())
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000333 for part in path.split('.')[1:]:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000334 try: module = getattr(module, part)
335 except AttributeError: return None
336 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000337
338# ---------------------------------------------------- formatter base class
339
340class Doc:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000341
342 PYTHONDOCS = os.environ.get("PYTHONDOCS",
343 "http://docs.python.org/%d.%d/library"
344 % sys.version_info[:2])
345
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000346 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000347 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000348 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000349 # 'try' clause is to attempt to handle the possibility that inspect
350 # identifies something in a way that pydoc itself has issues handling;
351 # think 'super' and how it is a descriptor (which raises the exception
352 # by lacking a __name__ attribute) and an instance.
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000353 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
354 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000355 try:
356 if inspect.ismodule(object): return self.docmodule(*args)
357 if inspect.isclass(object): return self.docclass(*args)
358 if inspect.isroutine(object): return self.docroutine(*args)
359 except AttributeError:
360 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000361 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000362 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000363
364 def fail(self, object, name=None, *args):
365 """Raise an exception for unimplemented types."""
366 message = "don't know how to document object%s of type %s" % (
367 name and ' ' + repr(name), type(object).__name__)
Collin Winterce36ad82007-08-30 01:19:48 +0000368 raise TypeError(message)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000369
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000370 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000371
Skip Montanaro4997a692003-09-10 16:47:51 +0000372 def getdocloc(self, object):
373 """Return the location of module docs or None"""
374
375 try:
376 file = inspect.getabsfile(object)
377 except TypeError:
378 file = '(built-in)'
379
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000380 docloc = os.environ.get("PYTHONDOCS", self.PYTHONDOCS)
381
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100382 basedir = os.path.join(sys.base_exec_prefix, "lib",
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000383 "python%d.%d" % sys.version_info[:2])
Skip Montanaro4997a692003-09-10 16:47:51 +0000384 if (isinstance(object, type(os)) and
385 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
386 'marshal', 'posix', 'signal', 'sys',
Georg Brandl2067bfd2008-05-25 13:05:15 +0000387 '_thread', 'zipimport') or
Skip Montanaro4997a692003-09-10 16:47:51 +0000388 (file.startswith(basedir) and
Brian Curtin49c284c2010-03-31 03:19:28 +0000389 not file.startswith(os.path.join(basedir, 'site-packages')))) and
Brian Curtinedef05b2010-04-01 04:05:25 +0000390 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
Skip Montanaro4997a692003-09-10 16:47:51 +0000391 if docloc.startswith("http://"):
Georg Brandl86def6c2008-01-21 20:36:10 +0000392 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
Skip Montanaro4997a692003-09-10 16:47:51 +0000393 else:
Georg Brandl86def6c2008-01-21 20:36:10 +0000394 docloc = os.path.join(docloc, object.__name__ + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000395 else:
396 docloc = None
397 return docloc
398
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000399# -------------------------------------------- HTML documentation generator
400
401class HTMLRepr(Repr):
402 """Class for safely making an HTML representation of a Python object."""
403 def __init__(self):
404 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000405 self.maxlist = self.maxtuple = 20
406 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000407 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000408
409 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000410 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000411
412 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000413 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000414
415 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000416 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000417 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000418 if hasattr(self, methodname):
419 return getattr(self, methodname)(x, level)
420 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000421
422 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000423 test = cram(x, self.maxstring)
424 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000425 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000426 # Backslashes are only literal in the string and are never
427 # needed to make any special characters, so show a raw string.
428 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000429 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000430 r'<font color="#c040c0">\1</font>',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000431 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000432
Skip Montanarodf708782002-03-07 22:58:02 +0000433 repr_str = repr_string
434
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000435 def repr_instance(self, x, level):
436 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000437 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000438 except:
439 return self.escape('<%s instance>' % x.__class__.__name__)
440
441 repr_unicode = repr_string
442
443class HTMLDoc(Doc):
444 """Formatter class for HTML documentation."""
445
446 # ------------------------------------------- HTML formatting utilities
447
448 _repr_instance = HTMLRepr()
449 repr = _repr_instance.repr
450 escape = _repr_instance.escape
451
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000452 def page(self, title, contents):
453 """Format an HTML page."""
Georg Brandl388faac2009-04-10 08:31:48 +0000454 return '''\
Georg Brandle6066942009-04-10 08:28:28 +0000455<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000456<html><head><title>Python: %s</title>
Georg Brandl388faac2009-04-10 08:31:48 +0000457<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000458</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000459%s
460</body></html>''' % (title, contents)
461
462 def heading(self, title, fgcol, bgcol, extras=''):
463 """Format a page heading."""
464 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000465<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000466<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000467<td valign=bottom>&nbsp;<br>
468<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000469><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000470><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000471 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
472
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000473 def section(self, title, fgcol, bgcol, contents, width=6,
474 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000475 """Format a section with a heading."""
476 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000477 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000478 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000479<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000480<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000481<td colspan=3 valign=bottom>&nbsp;<br>
482<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000483 ''' % (bgcol, fgcol, title)
484 if prelude:
485 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000486<tr bgcolor="%s"><td rowspan=2>%s</td>
487<td colspan=2>%s</td></tr>
488<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
489 else:
490 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000491<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000492
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000493 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000494
495 def bigsection(self, title, *args):
496 """Format a section with a big heading."""
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000497 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000498 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000499
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000500 def preformat(self, text):
501 """Format literal preformatted text."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000502 text = self.escape(text.expandtabs())
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000503 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
504 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000505
506 def multicolumn(self, list, format, cols=4):
507 """Format a list of items into a multi-column list."""
508 result = ''
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000509 rows = (len(list)+cols-1)//cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000510 for col in range(cols):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000511 result = result + '<td width="%d%%" valign=top>' % (100//cols)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000512 for i in range(rows*col, rows*col+rows):
513 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000514 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000515 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000516 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000517
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000518 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000519
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000520 def namelink(self, name, *dicts):
521 """Make a link for an identifier, given name-to-URL mappings."""
522 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000523 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000524 return '<a href="%s">%s</a>' % (dict[name], name)
525 return name
526
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000527 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000528 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000529 name, module = object.__name__, sys.modules.get(object.__module__)
530 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000531 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000532 module.__name__, name, classname(object, modname))
533 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000534
535 def modulelink(self, object):
536 """Make a link for a module."""
537 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
538
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000539 def modpkglink(self, modpkginfo):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000540 """Make a link for a module or package to display in an index."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000541 name, path, ispackage, shadowed = modpkginfo
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000542 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000543 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000544 if path:
545 url = '%s.%s.html' % (path, name)
546 else:
547 url = '%s.html' % name
548 if ispackage:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000549 text = '<strong>%s</strong>&nbsp;(package)' % name
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000550 else:
551 text = name
552 return '<a href="%s">%s</a>' % (url, text)
553
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000554 def filelink(self, url, path):
555 """Make a link to source file."""
556 return '<a href="file:%s">%s</a>' % (url, path)
557
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000558 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
559 """Mark up some plain text, given a context of symbols to look for.
560 Each context dictionary maps object names to anchor names."""
561 escape = escape or self.escape
562 results = []
563 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000564 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
565 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000566 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000567 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000568 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000569 match = pattern.search(text, here)
570 if not match: break
571 start, end = match.span()
572 results.append(escape(text[here:start]))
573
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000574 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000575 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000576 url = escape(all).replace('"', '&quot;')
577 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000578 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000579 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
580 results.append('<a href="%s">%s</a>' % (url, escape(all)))
581 elif pep:
Christian Heimes2202f872008-02-06 14:31:34 +0000582 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000583 results.append('<a href="%s">%s</a>' % (url, escape(all)))
584 elif text[end:end+1] == '(':
585 results.append(self.namelink(name, methods, funcs, classes))
586 elif selfdot:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000587 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000588 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000589 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000590 here = end
591 results.append(escape(text[here:]))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000592 return ''.join(results)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000593
594 # ---------------------------------------------- type-specific routines
595
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000596 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000597 """Produce HTML for a class tree as given by inspect.getclasstree()."""
598 result = ''
599 for entry in tree:
600 if type(entry) is type(()):
601 c, bases = entry
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000602 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000603 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000604 if bases and bases != (parent,):
605 parents = []
606 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000607 parents.append(self.classlink(base, modname))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000608 result = result + '(' + ', '.join(parents) + ')'
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000609 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000610 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000611 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000612 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000613 return '<dl>\n%s</dl>\n' % result
614
Tim Peters8dd7ade2001-10-18 19:56:17 +0000615 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000616 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000617 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000618 try:
619 all = object.__all__
620 except AttributeError:
621 all = None
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000622 parts = name.split('.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000623 links = []
624 for i in range(len(parts)-1):
625 links.append(
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000626 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000627 ('.'.join(parts[:i+1]), parts[i]))
628 linkedname = '.'.join(links + parts[-1:])
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000629 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000630 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000631 path = inspect.getabsfile(object)
Ka-Ping Yee6191a232001-04-13 15:00:27 +0000632 url = path
633 if sys.platform == 'win32':
634 import nturl2path
635 url = nturl2path.pathname2url(path)
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000636 filelink = self.filelink(url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000637 except TypeError:
638 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000639 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000640 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000641 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000642 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000643 version = version[11:-1].strip()
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000644 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000645 if hasattr(object, '__date__'):
646 info.append(self.escape(str(object.__date__)))
647 if info:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000648 head = head + ' (%s)' % ', '.join(info)
Skip Montanaro4997a692003-09-10 16:47:51 +0000649 docloc = self.getdocloc(object)
650 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000651 docloc = '<br><a href="%(docloc)s">Module Reference</a>' % locals()
Skip Montanaro4997a692003-09-10 16:47:51 +0000652 else:
653 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000654 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000655 head, '#ffffff', '#7799ee',
656 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000657
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000658 modules = inspect.getmembers(object, inspect.ismodule)
659
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000660 classes, cdict = [], {}
661 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000662 # if __all__ exists, believe it. Otherwise use old heuristic.
663 if (all is not None or
664 (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700665 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000666 classes.append((key, value))
667 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000668 for key, value in classes:
669 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000670 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000671 module = sys.modules.get(modname)
672 if modname != name and module and hasattr(module, key):
673 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000674 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000675 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000676 funcs, fdict = [], {}
677 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000678 # if __all__ exists, believe it. Otherwise use old heuristic.
679 if (all is not None or
680 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700681 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000682 funcs.append((key, value))
683 fdict[key] = '#-' + key
684 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000685 data = []
686 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700687 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000688 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000689
690 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
691 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000692 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000693
694 if hasattr(object, '__path__'):
695 modpkgs = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000696 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
697 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000698 modpkgs.sort()
699 contents = self.multicolumn(modpkgs, self.modpkglink)
700 result = result + self.bigsection(
701 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000702 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000703 contents = self.multicolumn(
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000704 modules, lambda t: self.modulelink(t[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000705 result = result + self.bigsection(
Christian Heimes7131fd92008-02-19 14:21:46 +0000706 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000707
708 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000709 classlist = [value for (key, value) in classes]
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000710 contents = [
711 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000712 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000713 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000714 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000715 'Classes', '#ffffff', '#ee77aa', ' '.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000716 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000717 contents = []
718 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000719 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000720 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000721 'Functions', '#ffffff', '#eeaa77', ' '.join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000722 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000723 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000724 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000725 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000726 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000727 'Data', '#ffffff', '#55aa55', '<br>\n'.join(contents))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000728 if hasattr(object, '__author__'):
729 contents = self.markup(str(object.__author__), self.preformat)
730 result = result + self.bigsection(
731 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000732 if hasattr(object, '__credits__'):
733 contents = self.markup(str(object.__credits__), self.preformat)
734 result = result + self.bigsection(
735 'Credits', '#ffffff', '#7799ee', contents)
736
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000737 return result
738
Tim Peters8dd7ade2001-10-18 19:56:17 +0000739 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
740 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000741 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000742 realname = object.__name__
743 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000744 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000745
Tim Petersb47879b2001-09-24 04:47:19 +0000746 contents = []
747 push = contents.append
748
Tim Petersfa26f7c2001-09-24 08:05:11 +0000749 # Cute little class to pump out a horizontal rule between sections.
750 class HorizontalRule:
751 def __init__(self):
752 self.needone = 0
753 def maybe(self):
754 if self.needone:
755 push('<hr>\n')
756 self.needone = 1
757 hr = HorizontalRule()
758
Tim Petersc86f6ca2001-09-26 21:31:51 +0000759 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000760 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000761 if len(mro) > 2:
762 hr.maybe()
763 push('<dl><dt>Method resolution order:</dt>\n')
764 for base in mro:
765 push('<dd>%s</dd>\n' % self.classlink(base,
766 object.__module__))
767 push('</dl>\n')
768
Tim Petersb47879b2001-09-24 04:47:19 +0000769 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000770 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000771 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000772 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000773 push(msg)
774 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100775 try:
776 value = getattr(object, name)
777 except Exception:
778 # Some descriptors may meet a failure in their __get__.
779 # (bug #1785)
780 push(self._docdescriptor(name, value, mod))
781 else:
782 push(self.document(value, name, mod,
783 funcs, classes, mdict, object))
Tim Petersb47879b2001-09-24 04:47:19 +0000784 push('\n')
785 return attrs
786
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000787 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000788 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000789 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000790 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000791 push(msg)
792 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000793 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000794 return attrs
795
Tim Petersfa26f7c2001-09-24 08:05:11 +0000796 def spilldata(msg, attrs, predicate):
797 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000798 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000799 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000800 push(msg)
801 for name, kind, homecls, value in ok:
802 base = self.docother(getattr(object, name), name, mod)
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200803 if callable(value) or inspect.isdatadescriptor(value):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000804 doc = getattr(value, "__doc__", None)
805 else:
806 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000807 if doc is None:
808 push('<dl><dt>%s</dl>\n' % base)
809 else:
810 doc = self.markup(getdoc(value), self.preformat,
811 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000812 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000813 push('<dl><dt>%s%s</dl>\n' % (base, doc))
814 push('\n')
815 return attrs
816
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000817 attrs = [(name, kind, cls, value)
818 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -0700819 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000820
Tim Petersb47879b2001-09-24 04:47:19 +0000821 mdict = {}
822 for key, kind, homecls, value in attrs:
823 mdict[key] = anchor = '#' + name + '-' + key
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100824 try:
825 value = getattr(object, name)
826 except Exception:
827 # Some descriptors may meet a failure in their __get__.
828 # (bug #1785)
829 pass
Tim Petersb47879b2001-09-24 04:47:19 +0000830 try:
831 # The value may not be hashable (e.g., a data attr with
832 # a dict or list value).
833 mdict[value] = anchor
834 except TypeError:
835 pass
836
Tim Petersfa26f7c2001-09-24 08:05:11 +0000837 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000838 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000839 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000840 else:
841 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000842 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
843
Georg Brandl1a3284e2007-12-02 09:40:06 +0000844 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000845 attrs = inherited
846 continue
847 elif thisclass is object:
848 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000849 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000850 tag = 'inherited from %s' % self.classlink(thisclass,
851 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000852 tag += ':<br>\n'
853
854 # Sort attrs by name.
Raymond Hettingerd4cb56d2008-01-30 02:55:10 +0000855 attrs.sort(key=lambda t: t[0])
Tim Petersb47879b2001-09-24 04:47:19 +0000856
857 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000858 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000859 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000860 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000861 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000862 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000863 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000864 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
865 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000866 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000867 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000868 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000869 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000870
871 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000872
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000873 if name == realname:
874 title = '<a name="%s">class <strong>%s</strong></a>' % (
875 name, realname)
876 else:
877 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
878 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000879 if bases:
880 parents = []
881 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000882 parents.append(self.classlink(base, object.__module__))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000883 title = title + '(%s)' % ', '.join(parents)
Tim Peters2306d242001-09-25 03:18:32 +0000884 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000885 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000886
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000887 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000888
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000889 def formatvalue(self, object):
890 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000891 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000892
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000893 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000894 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000895 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000896 realname = object.__name__
897 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000898 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000899 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000900 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000901 if inspect.ismethod(object):
Christian Heimesff737952007-11-27 10:40:20 +0000902 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000903 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000904 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000905 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000906 else:
Christian Heimesff737952007-11-27 10:40:20 +0000907 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000908 note = ' method of %s instance' % self.classlink(
Christian Heimesff737952007-11-27 10:40:20 +0000909 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000910 else:
911 note = ' unbound %s method' % self.classlink(imclass,mod)
Christian Heimesff737952007-11-27 10:40:20 +0000912 object = object.__func__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000913
914 if name == realname:
915 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
916 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000917 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000918 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000919 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000920 cl.__name__ + '-' + realname, realname)
921 skipdocs = 1
922 else:
923 reallink = realname
924 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
925 anchor, name, reallink)
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800926 argspec = None
927 if inspect.isfunction(object) or inspect.isbuiltin(object):
Larry Hastings5c661892014-01-24 06:17:25 -0800928 try:
929 signature = inspect.signature(object)
930 except (ValueError, TypeError):
931 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800932 if signature:
933 argspec = str(signature)
934 if realname == '<lambda>':
935 title = '<strong>%s</strong> <em>lambda</em> ' % name
936 # XXX lambda's won't usually have func_annotations['return']
937 # since the syntax doesn't support but it is possible.
938 # So removing parentheses isn't truly safe.
939 argspec = argspec[1:-1] # remove parentheses
940 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +0000941 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000942
Tim Peters2306d242001-09-25 03:18:32 +0000943 decl = title + argspec + (note and self.grey(
944 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000945
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000946 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000947 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000948 else:
949 doc = self.markup(
950 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000951 doc = doc and '<dd><tt>%s</tt></dd>' % doc
952 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000953
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000954 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000955 results = []
956 push = results.append
957
958 if name:
959 push('<dl><dt><strong>%s</strong></dt>\n' % name)
960 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000961 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000962 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000963 push('</dl>\n')
964
965 return ''.join(results)
966
967 def docproperty(self, object, name=None, mod=None, cl=None):
968 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000969 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000970
Tim Peters8dd7ade2001-10-18 19:56:17 +0000971 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000972 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000973 lhs = name and '<strong>%s</strong> = ' % name or ''
974 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000975
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000976 def docdata(self, object, name=None, mod=None, cl=None):
977 """Produce html documentation for a data descriptor."""
978 return self._docdescriptor(name, object, mod)
979
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000980 def index(self, dir, shadowed=None):
981 """Generate an HTML index for a directory of modules."""
982 modpkgs = []
983 if shadowed is None: shadowed = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000984 for importer, name, ispkg in pkgutil.iter_modules([dir]):
Victor Stinner4d652242011-04-12 23:41:50 +0200985 if any((0xD800 <= ord(ch) <= 0xDFFF) for ch in name):
986 # ignore a module if its name contains a surrogate character
987 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000988 modpkgs.append((name, '', ispkg, name in shadowed))
989 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000990
991 modpkgs.sort()
992 contents = self.multicolumn(modpkgs, self.modpkglink)
993 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
994
995# -------------------------------------------- text documentation generator
996
997class TextRepr(Repr):
998 """Class for safely making a text representation of a Python object."""
999 def __init__(self):
1000 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001001 self.maxlist = self.maxtuple = 20
1002 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001003 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001004
1005 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001006 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001007 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001008 if hasattr(self, methodname):
1009 return getattr(self, methodname)(x, level)
1010 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001011
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001012 def repr_string(self, x, level):
1013 test = cram(x, self.maxstring)
1014 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001015 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001016 # Backslashes are only literal in the string and are never
1017 # needed to make any special characters, so show a raw string.
1018 return 'r' + testrepr[0] + test + testrepr[0]
1019 return testrepr
1020
Skip Montanarodf708782002-03-07 22:58:02 +00001021 repr_str = repr_string
1022
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001023 def repr_instance(self, x, level):
1024 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001025 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001026 except:
1027 return '<%s instance>' % x.__class__.__name__
1028
1029class TextDoc(Doc):
1030 """Formatter class for text documentation."""
1031
1032 # ------------------------------------------- text formatting utilities
1033
1034 _repr_instance = TextRepr()
1035 repr = _repr_instance.repr
1036
1037 def bold(self, text):
1038 """Format a string in bold by overstriking."""
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001039 return ''.join(ch + '\b' + ch for ch in text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001040
1041 def indent(self, text, prefix=' '):
1042 """Indent text by prepending a given prefix to each line."""
1043 if not text: return ''
Collin Winter72e110c2007-07-17 00:27:30 +00001044 lines = [prefix + line for line in text.split('\n')]
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001045 if lines: lines[-1] = lines[-1].rstrip()
1046 return '\n'.join(lines)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001047
1048 def section(self, title, contents):
1049 """Format a section with a given heading."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001050 clean_contents = self.indent(contents).rstrip()
1051 return self.bold(title) + '\n' + clean_contents + '\n\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001052
1053 # ---------------------------------------------- type-specific routines
1054
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001055 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001056 """Render in text a class tree as returned by inspect.getclasstree()."""
1057 result = ''
1058 for entry in tree:
1059 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001060 c, bases = entry
1061 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001062 if bases and bases != (parent,):
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001063 parents = (classname(c, modname) for c in bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001064 result = result + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001065 result = result + '\n'
1066 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001067 result = result + self.formattree(
1068 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001069 return result
1070
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001071 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001072 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001073 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001074 synop, desc = splitdoc(getdoc(object))
1075 result = self.section('NAME', name + (synop and ' - ' + synop))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001076 all = getattr(object, '__all__', None)
Skip Montanaro4997a692003-09-10 16:47:51 +00001077 docloc = self.getdocloc(object)
1078 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001079 result = result + self.section('MODULE REFERENCE', docloc + """
1080
Éric Araujo647ef8c2011-09-11 00:43:20 +02001081The following documentation is automatically generated from the Python
1082source files. It may be incomplete, incorrect or include features that
1083are considered implementation detail and may vary between Python
1084implementations. When in doubt, consult the module reference at the
1085location listed above.
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001086""")
Skip Montanaro4997a692003-09-10 16:47:51 +00001087
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001088 if desc:
1089 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001090
1091 classes = []
1092 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001093 # if __all__ exists, believe it. Otherwise use old heuristic.
1094 if (all is not None
1095 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001096 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001097 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001098 funcs = []
1099 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001100 # if __all__ exists, believe it. Otherwise use old heuristic.
1101 if (all is not None or
1102 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001103 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001104 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001105 data = []
1106 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001107 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001108 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001109
Christian Heimes1af737c2008-01-23 08:24:23 +00001110 modpkgs = []
1111 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001112 if hasattr(object, '__path__'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001113 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Christian Heimes1af737c2008-01-23 08:24:23 +00001114 modpkgs_names.add(modname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001115 if ispkg:
1116 modpkgs.append(modname + ' (package)')
1117 else:
1118 modpkgs.append(modname)
1119
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001120 modpkgs.sort()
1121 result = result + self.section(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001122 'PACKAGE CONTENTS', '\n'.join(modpkgs))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001123
Christian Heimes1af737c2008-01-23 08:24:23 +00001124 # Detect submodules as sometimes created by C extensions
1125 submodules = []
1126 for key, value in inspect.getmembers(object, inspect.ismodule):
1127 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1128 submodules.append(key)
1129 if submodules:
1130 submodules.sort()
1131 result = result + self.section(
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001132 'SUBMODULES', '\n'.join(submodules))
Christian Heimes1af737c2008-01-23 08:24:23 +00001133
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001134 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001135 classlist = [value for key, value in classes]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001136 contents = [self.formattree(
1137 inspect.getclasstree(classlist, 1), name)]
1138 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001139 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001140 result = result + self.section('CLASSES', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001141
1142 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001143 contents = []
1144 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001145 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001146 result = result + self.section('FUNCTIONS', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001147
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001148 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001149 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001150 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001151 contents.append(self.docother(value, key, name, maxlen=70))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001152 result = result + self.section('DATA', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001153
1154 if hasattr(object, '__version__'):
1155 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001156 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001157 version = version[11:-1].strip()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001158 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001159 if hasattr(object, '__date__'):
1160 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001161 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001162 result = result + self.section('AUTHOR', str(object.__author__))
1163 if hasattr(object, '__credits__'):
1164 result = result + self.section('CREDITS', str(object.__credits__))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001165 try:
1166 file = inspect.getabsfile(object)
1167 except TypeError:
1168 file = '(built-in)'
1169 result = result + self.section('FILE', file)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001170 return result
1171
Georg Brandl9bd45f992010-12-03 09:58:38 +00001172 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001173 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001174 realname = object.__name__
1175 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001176 bases = object.__bases__
1177
Tim Petersc86f6ca2001-09-26 21:31:51 +00001178 def makename(c, m=object.__module__):
1179 return classname(c, m)
1180
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001181 if name == realname:
1182 title = 'class ' + self.bold(realname)
1183 else:
1184 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001185 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001186 parents = map(makename, bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001187 title = title + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001188
1189 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001190 contents = doc and [doc + '\n'] or []
1191 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001192
Tim Petersc86f6ca2001-09-26 21:31:51 +00001193 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001194 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001195 if len(mro) > 2:
1196 push("Method resolution order:")
1197 for base in mro:
1198 push(' ' + makename(base))
1199 push('')
1200
Tim Petersf4aad8e2001-09-24 22:40:47 +00001201 # Cute little class to pump out a horizontal rule between sections.
1202 class HorizontalRule:
1203 def __init__(self):
1204 self.needone = 0
1205 def maybe(self):
1206 if self.needone:
1207 push('-' * 70)
1208 self.needone = 1
1209 hr = HorizontalRule()
1210
Tim Peters28355492001-09-23 21:29:55 +00001211 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001212 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001213 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001214 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001215 push(msg)
1216 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001217 try:
1218 value = getattr(object, name)
1219 except Exception:
1220 # Some descriptors may meet a failure in their __get__.
1221 # (bug #1785)
1222 push(self._docdescriptor(name, value, mod))
1223 else:
1224 push(self.document(value,
1225 name, mod, object))
Tim Peters28355492001-09-23 21:29:55 +00001226 return attrs
1227
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001228 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001229 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001230 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001231 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001232 push(msg)
1233 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001234 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001235 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001236
Tim Petersfa26f7c2001-09-24 08:05:11 +00001237 def spilldata(msg, attrs, predicate):
1238 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001239 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001240 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001241 push(msg)
1242 for name, kind, homecls, value in ok:
Florent Xicluna5d1155c2011-10-28 14:45:05 +02001243 if callable(value) or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001244 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001245 else:
1246 doc = None
Serhiy Storchaka056eb022014-02-19 23:05:12 +02001247 try:
1248 obj = getattr(object, name)
1249 except AttributeError:
1250 obj = homecls.__dict__[name]
1251 push(self.docother(obj, name, mod, maxlen=70, doc=doc) +
1252 '\n')
Tim Peters28355492001-09-23 21:29:55 +00001253 return attrs
1254
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001255 attrs = [(name, kind, cls, value)
1256 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -07001257 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001258
Tim Petersfa26f7c2001-09-24 08:05:11 +00001259 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001260 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001261 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001262 else:
1263 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001264 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1265
Georg Brandl1a3284e2007-12-02 09:40:06 +00001266 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001267 attrs = inherited
1268 continue
1269 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001270 tag = "defined here"
1271 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001272 tag = "inherited from %s" % classname(thisclass,
1273 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001274 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001275 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001276
1277 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001278 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001279 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001280 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001281 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001282 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001283 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001284 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1285 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001286 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1287 lambda t: t[1] == 'data')
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001288
Tim Peters28355492001-09-23 21:29:55 +00001289 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001290 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001291
1292 contents = '\n'.join(contents)
1293 if not contents:
1294 return title + '\n'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001295 return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001296
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001297 def formatvalue(self, object):
1298 """Format an argument default value as text."""
1299 return '=' + self.repr(object)
1300
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001301 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001302 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001303 realname = object.__name__
1304 name = name or realname
1305 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001306 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001307 if inspect.ismethod(object):
Christian Heimesff737952007-11-27 10:40:20 +00001308 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001309 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001310 if imclass is not cl:
1311 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001312 else:
Christian Heimesff737952007-11-27 10:40:20 +00001313 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001314 note = ' method of %s instance' % classname(
Christian Heimesff737952007-11-27 10:40:20 +00001315 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001316 else:
1317 note = ' unbound %s method' % classname(imclass,mod)
Christian Heimesff737952007-11-27 10:40:20 +00001318 object = object.__func__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001319
1320 if name == realname:
1321 title = self.bold(realname)
1322 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001323 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001324 cl.__dict__[realname] is object):
1325 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001326 title = self.bold(name) + ' = ' + realname
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001327 argspec = None
Larry Hastings5c661892014-01-24 06:17:25 -08001328
1329 if inspect.isroutine(object):
1330 try:
1331 signature = inspect.signature(object)
1332 except (ValueError, TypeError):
1333 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001334 if signature:
1335 argspec = str(signature)
1336 if realname == '<lambda>':
1337 title = self.bold(name) + ' lambda '
1338 # XXX lambda's won't usually have func_annotations['return']
1339 # since the syntax doesn't support but it is possible.
1340 # So removing parentheses isn't truly safe.
1341 argspec = argspec[1:-1] # remove parentheses
1342 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +00001343 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001344 decl = title + argspec + note
1345
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001346 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001347 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001348 else:
1349 doc = getdoc(object) or ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001350 return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001351
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001352 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001353 results = []
1354 push = results.append
1355
1356 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001357 push(self.bold(name))
1358 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001359 doc = getdoc(value) or ''
1360 if doc:
1361 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001362 push('\n')
1363 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001364
1365 def docproperty(self, object, name=None, mod=None, cl=None):
1366 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001367 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001368
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001369 def docdata(self, object, name=None, mod=None, cl=None):
1370 """Produce text documentation for a data descriptor."""
1371 return self._docdescriptor(name, object, mod)
1372
Georg Brandl8b813db2005-10-01 16:32:31 +00001373 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001374 """Produce text documentation for a data object."""
1375 repr = self.repr(object)
1376 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001377 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001378 chop = maxlen - len(line)
1379 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001380 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001381 if doc is not None:
1382 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001383 return line
1384
Georg Brandld80d5f42010-12-03 07:47:22 +00001385class _PlainTextDoc(TextDoc):
1386 """Subclass of TextDoc which overrides string styling"""
1387 def bold(self, text):
1388 return text
1389
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001390# --------------------------------------------------------- user interfaces
1391
1392def pager(text):
1393 """The first time this is called, determine what kind of pager to use."""
1394 global pager
1395 pager = getpager()
1396 pager(text)
1397
1398def getpager():
1399 """Decide what method to use for paging through text."""
Guido van Rossuma01a8b62007-05-27 09:20:14 +00001400 if not hasattr(sys.stdout, "isatty"):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001401 return plainpager
1402 if not sys.stdin.isatty() or not sys.stdout.isatty():
1403 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001404 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001405 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001406 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001407 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001408 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001409 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001410 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001411 if os.environ.get('TERM') in ('dumb', 'emacs'):
1412 return plainpager
Jesus Cea4791a242012-10-05 03:15:39 +02001413 if sys.platform == 'win32':
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001414 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001415 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001416 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001417
1418 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001419 (fd, filename) = tempfile.mkstemp()
1420 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001421 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001422 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001423 return lambda text: pipepager(text, 'more')
1424 else:
1425 return ttypager
1426 finally:
1427 os.unlink(filename)
1428
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001429def plain(text):
1430 """Remove boldface formatting from text."""
1431 return re.sub('.\b', '', text)
1432
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001433def pipepager(text, cmd):
1434 """Page through text by feeding it to another program."""
1435 pipe = os.popen(cmd, 'w')
1436 try:
1437 pipe.write(text)
1438 pipe.close()
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001439 except OSError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001440 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001441
1442def tempfilepager(text, cmd):
1443 """Page through text by invoking a program on a temporary file."""
1444 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001445 filename = tempfile.mktemp()
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +01001446 with open(filename, 'w') as file:
1447 file.write(text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001448 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001449 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001450 finally:
1451 os.unlink(filename)
1452
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001453def ttypager(text):
1454 """Page through text on a text terminal."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001455 lines = plain(text).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001456 try:
1457 import tty
1458 fd = sys.stdin.fileno()
1459 old = tty.tcgetattr(fd)
1460 tty.setcbreak(fd)
1461 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001462 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001463 tty = None
1464 getchar = lambda: sys.stdin.readline()[:-1][:1]
1465
1466 try:
1467 r = inc = os.environ.get('LINES', 25) - 1
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001468 sys.stdout.write('\n'.join(lines[:inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001469 while lines[r:]:
1470 sys.stdout.write('-- more --')
1471 sys.stdout.flush()
1472 c = getchar()
1473
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001474 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001475 sys.stdout.write('\r \r')
1476 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001477 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001478 sys.stdout.write('\r \r' + lines[r] + '\n')
1479 r = r + 1
1480 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001481 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001482 r = r - inc - inc
1483 if r < 0: r = 0
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001484 sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001485 r = r + inc
1486
1487 finally:
1488 if tty:
1489 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1490
1491def plainpager(text):
1492 """Simply print unformatted text. This is the ultimate fallback."""
1493 sys.stdout.write(plain(text))
1494
1495def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001496 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001497 if inspect.ismodule(thing):
1498 if thing.__name__ in sys.builtin_module_names:
1499 return 'built-in module ' + thing.__name__
1500 if hasattr(thing, '__path__'):
1501 return 'package ' + thing.__name__
1502 else:
1503 return 'module ' + thing.__name__
1504 if inspect.isbuiltin(thing):
1505 return 'built-in function ' + thing.__name__
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001506 if inspect.isgetsetdescriptor(thing):
1507 return 'getset descriptor %s.%s.%s' % (
1508 thing.__objclass__.__module__, thing.__objclass__.__name__,
1509 thing.__name__)
1510 if inspect.ismemberdescriptor(thing):
1511 return 'member descriptor %s.%s.%s' % (
1512 thing.__objclass__.__module__, thing.__objclass__.__name__,
1513 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001514 if inspect.isclass(thing):
1515 return 'class ' + thing.__name__
1516 if inspect.isfunction(thing):
1517 return 'function ' + thing.__name__
1518 if inspect.ismethod(thing):
1519 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001520 return type(thing).__name__
1521
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001522def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001523 """Locate an object by name or dotted path, importing as necessary."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001524 parts = [part for part in path.split('.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001525 module, n = None, 0
1526 while n < len(parts):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001527 nextmodule = safeimport('.'.join(parts[:n+1]), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001528 if nextmodule: module, n = nextmodule, n + 1
1529 else: break
1530 if module:
1531 object = module
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001532 else:
Éric Araujoe64e51b2011-07-29 17:03:55 +02001533 object = builtins
1534 for part in parts[n:]:
1535 try:
1536 object = getattr(object, part)
1537 except AttributeError:
1538 return None
1539 return object
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001540
1541# --------------------------------------- interactive interpreter interface
1542
1543text = TextDoc()
Georg Brandld80d5f42010-12-03 07:47:22 +00001544plaintext = _PlainTextDoc()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001545html = HTMLDoc()
1546
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001547def resolve(thing, forceload=0):
1548 """Given an object or a path to an object, get the object and its name."""
1549 if isinstance(thing, str):
1550 object = locate(thing, forceload)
1551 if not object:
Collin Winterce36ad82007-08-30 01:19:48 +00001552 raise ImportError('no Python documentation found for %r' % thing)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001553 return object, thing
1554 else:
R David Murrayc43125a2012-04-23 13:23:57 -04001555 name = getattr(thing, '__name__', None)
1556 return thing, name if isinstance(name, str) else None
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001557
Georg Brandld80d5f42010-12-03 07:47:22 +00001558def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
1559 renderer=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001560 """Render text documentation, given an object or a path to an object."""
Georg Brandld80d5f42010-12-03 07:47:22 +00001561 if renderer is None:
1562 renderer = text
Guido van Rossumd8faa362007-04-27 19:54:29 +00001563 object, name = resolve(thing, forceload)
1564 desc = describe(object)
1565 module = inspect.getmodule(object)
1566 if name and '.' in name:
1567 desc += ' in ' + name[:name.rfind('.')]
1568 elif module and module is not object:
1569 desc += ' in module ' + module.__name__
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001570
1571 if not (inspect.ismodule(object) or
Guido van Rossumd8faa362007-04-27 19:54:29 +00001572 inspect.isclass(object) or
1573 inspect.isroutine(object) or
1574 inspect.isgetsetdescriptor(object) or
1575 inspect.ismemberdescriptor(object) or
1576 isinstance(object, property)):
1577 # If the passed object is a piece of data or an instance,
1578 # document its available methods instead of its value.
1579 object = type(object)
1580 desc += ' object'
Georg Brandld80d5f42010-12-03 07:47:22 +00001581 return title % desc + '\n\n' + renderer.document(object, name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001582
Georg Brandld80d5f42010-12-03 07:47:22 +00001583def doc(thing, title='Python Library Documentation: %s', forceload=0,
1584 output=None):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001585 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001586 try:
Georg Brandld80d5f42010-12-03 07:47:22 +00001587 if output is None:
1588 pager(render_doc(thing, title, forceload))
1589 else:
1590 output.write(render_doc(thing, title, forceload, plaintext))
Guido van Rossumb940e112007-01-10 16:19:56 +00001591 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001592 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001593
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001594def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001595 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001596 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001597 object, name = resolve(thing, forceload)
1598 page = html.page(describe(object), html.document(object, name))
Georg Brandl388faac2009-04-10 08:31:48 +00001599 file = open(name + '.html', 'w', encoding='utf-8')
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001600 file.write(page)
1601 file.close()
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001602 print('wrote', name + '.html')
Guido van Rossumb940e112007-01-10 16:19:56 +00001603 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001604 print(value)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001605
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001606def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001607 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001608 if done is None: done = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001609 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1610 writedoc(modname)
1611 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001612
1613class Helper:
Georg Brandl6b38daa2008-06-01 21:05:17 +00001614
1615 # These dictionaries map a topic name to either an alias, or a tuple
1616 # (label, seealso-items). The "label" is the label of the corresponding
1617 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl5617db82009-04-27 16:28:57 +00001618 # in pydoc_data/topics.py.
Georg Brandl6b38daa2008-06-01 21:05:17 +00001619 #
1620 # CAUTION: if you change one of these dictionaries, be sure to adapt the
1621 # list of needed labels in Doc/tools/sphinxext/pyspecific.py and
Georg Brandl5617db82009-04-27 16:28:57 +00001622 # regenerate the pydoc_data/topics.py file by running
Georg Brandl6b38daa2008-06-01 21:05:17 +00001623 # make pydoc-topics
1624 # in Doc/ and copying the output file into the Lib/ directory.
1625
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001626 keywords = {
Ezio Melottib185a042011-04-28 07:42:55 +03001627 'False': '',
1628 'None': '',
1629 'True': '',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001630 'and': 'BOOLEAN',
Guido van Rossumd8faa362007-04-27 19:54:29 +00001631 'as': 'with',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001632 'assert': ('assert', ''),
1633 'break': ('break', 'while for'),
1634 'class': ('class', 'CLASSES SPECIALMETHODS'),
1635 'continue': ('continue', 'while for'),
1636 'def': ('function', ''),
1637 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001638 'elif': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001639 'else': ('else', 'while for'),
Georg Brandl0d855392008-08-30 19:53:05 +00001640 'except': 'try',
1641 'finally': 'try',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001642 'for': ('for', 'break continue while'),
Georg Brandl0d855392008-08-30 19:53:05 +00001643 'from': 'import',
Georg Brandl74abf6f2010-11-20 19:54:36 +00001644 'global': ('global', 'nonlocal NAMESPACES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001645 'if': ('if', 'TRUTHVALUE'),
1646 'import': ('import', 'MODULES'),
Georg Brandl395ed242009-09-04 08:07:32 +00001647 'in': ('in', 'SEQUENCEMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001648 'is': 'COMPARISON',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001649 'lambda': ('lambda', 'FUNCTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001650 'nonlocal': ('nonlocal', 'global NAMESPACES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001651 'not': 'BOOLEAN',
1652 'or': 'BOOLEAN',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001653 'pass': ('pass', ''),
1654 'raise': ('raise', 'EXCEPTIONS'),
1655 'return': ('return', 'FUNCTIONS'),
1656 'try': ('try', 'EXCEPTIONS'),
1657 'while': ('while', 'break continue if TRUTHVALUE'),
1658 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1659 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001660 }
Georg Brandldb7b6b92009-01-01 15:53:14 +00001661 # Either add symbols to this dictionary or to the symbols dictionary
1662 # directly: Whichever is easier. They are merged later.
1663 _symbols_inverse = {
1664 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'),
1665 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1666 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1667 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1668 'UNARY' : ('-', '~'),
1669 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1670 '^=', '<<=', '>>=', '**=', '//='),
1671 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1672 'COMPLEX' : ('j', 'J')
1673 }
1674 symbols = {
1675 '%': 'OPERATORS FORMATTING',
1676 '**': 'POWER',
1677 ',': 'TUPLES LISTS FUNCTIONS',
1678 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1679 '...': 'ELLIPSIS',
1680 ':': 'SLICINGS DICTIONARYLITERALS',
1681 '@': 'def class',
1682 '\\': 'STRINGS',
1683 '_': 'PRIVATENAMES',
1684 '__': 'PRIVATENAMES SPECIALMETHODS',
1685 '`': 'BACKQUOTES',
1686 '(': 'TUPLES FUNCTIONS CALLS',
1687 ')': 'TUPLES FUNCTIONS CALLS',
1688 '[': 'LISTS SUBSCRIPTS SLICINGS',
1689 ']': 'LISTS SUBSCRIPTS SLICINGS'
1690 }
1691 for topic, symbols_ in _symbols_inverse.items():
1692 for symbol in symbols_:
1693 topics = symbols.get(symbol, topic)
1694 if topic not in topics:
1695 topics = topics + ' ' + topic
1696 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001697
1698 topics = {
Georg Brandl6b38daa2008-06-01 21:05:17 +00001699 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1700 'FUNCTIONS CLASSES MODULES FILES inspect'),
1701 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS '
1702 'FORMATTING TYPES'),
1703 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1704 'FORMATTING': ('formatstrings', 'OPERATORS'),
1705 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1706 'FORMATTING TYPES'),
1707 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1708 'INTEGER': ('integers', 'int range'),
1709 'FLOAT': ('floating', 'float math'),
1710 'COMPLEX': ('imaginary', 'complex cmath'),
1711 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING range LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001712 'MAPPINGS': 'DICTIONARIES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001713 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1714 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1715 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1716 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001717 'FRAMEOBJECTS': 'TYPES',
1718 'TRACEBACKS': 'TYPES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001719 'NONE': ('bltin-null-object', ''),
1720 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
1721 'FILES': ('bltin-file-objects', ''),
1722 'SPECIALATTRIBUTES': ('specialattrs', ''),
1723 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1724 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001725 'PACKAGES': 'import',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001726 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1727 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1728 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1729 'LISTS DICTIONARIES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001730 'OPERATORS': 'EXPRESSIONS',
1731 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001732 'OBJECTS': ('objects', 'TYPES'),
1733 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
Georg Brandl395ed242009-09-04 08:07:32 +00001734 'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS '
1735 'NUMBERMETHODS CLASSES'),
Mark Dickinsona56c4672009-01-27 18:17:45 +00001736 'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001737 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1738 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001739 'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS '
Georg Brandl6b38daa2008-06-01 21:05:17 +00001740 'SPECIALMETHODS'),
1741 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1742 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1743 'SPECIALMETHODS'),
1744 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001745 'NAMESPACES': ('naming', 'global nonlocal ASSIGNMENT DELETION DYNAMICFEATURES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001746 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001747 'SCOPING': 'NAMESPACES',
1748 'FRAMES': 'NAMESPACES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001749 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1750 'CONVERSIONS': ('conversions', ''),
1751 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1752 'SPECIALIDENTIFIERS': ('id-classes', ''),
1753 'PRIVATENAMES': ('atom-identifiers', ''),
1754 'LITERALS': ('atom-literals', 'STRINGS NUMBERS TUPLELITERALS '
1755 'LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001756 'TUPLES': 'SEQUENCES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001757 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1758 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1759 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1760 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1761 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1762 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001763 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'),
1764 'SLICINGS': ('slicings', 'SEQUENCEMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001765 'CALLS': ('calls', 'EXPRESSIONS'),
1766 'POWER': ('power', 'EXPRESSIONS'),
1767 'UNARY': ('unary', 'EXPRESSIONS'),
1768 'BINARY': ('binary', 'EXPRESSIONS'),
1769 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1770 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1771 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1772 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001773 'ASSERTION': 'assert',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001774 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1775 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001776 'DELETION': 'del',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001777 'RETURNING': 'return',
1778 'IMPORTING': 'import',
1779 'CONDITIONAL': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001780 'LOOPING': ('compound', 'for while break continue'),
1781 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1782 'DEBUGGING': ('debugger', 'pdb'),
1783 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001784 }
1785
Georg Brandl78aa3962010-07-31 21:51:48 +00001786 def __init__(self, input=None, output=None):
1787 self._input = input
1788 self._output = output
1789
Georg Brandl76ae3972010-08-01 06:32:55 +00001790 input = property(lambda self: self._input or sys.stdin)
1791 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001792
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001793 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001794 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001795 self()
1796 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001797 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001798
Alexander Belopolsky2e733c92010-07-04 17:00:20 +00001799 _GoInteractive = object()
1800 def __call__(self, request=_GoInteractive):
1801 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001802 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001803 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001804 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001805 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001806 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001807You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001808If you want to ask for help on a particular object directly from the
1809interpreter, you can type "help(object)". Executing "help('string')"
1810has the same effect as typing a particular string at the help> prompt.
1811''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001812
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001813 def interact(self):
1814 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001815 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001816 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001817 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001818 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001819 except (KeyboardInterrupt, EOFError):
1820 break
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001821 request = replace(request, '"', '', "'", '').strip()
1822 if request.lower() in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001823 self.help(request)
1824
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001825 def getline(self, prompt):
Guido van Rossum7c086c02008-01-02 03:52:38 +00001826 """Read one line, using input() when appropriate."""
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001827 if self.input is sys.stdin:
Guido van Rossum7c086c02008-01-02 03:52:38 +00001828 return input(prompt)
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001829 else:
1830 self.output.write(prompt)
1831 self.output.flush()
1832 return self.input.readline()
1833
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001834 def help(self, request):
1835 if type(request) is type(''):
R. David Murray1f1b9d32009-05-27 20:56:59 +00001836 request = request.strip()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001837 if request == 'help': self.intro()
1838 elif request == 'keywords': self.listkeywords()
Georg Brandldb7b6b92009-01-01 15:53:14 +00001839 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001840 elif request == 'topics': self.listtopics()
1841 elif request == 'modules': self.listmodules()
1842 elif request[:8] == 'modules ':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001843 self.listmodules(request.split()[1])
Georg Brandldb7b6b92009-01-01 15:53:14 +00001844 elif request in self.symbols: self.showsymbol(request)
Ezio Melottib185a042011-04-28 07:42:55 +03001845 elif request in ['True', 'False', 'None']:
1846 # special case these keywords since they are objects too
1847 doc(eval(request), 'Help on %s:')
Raymond Hettinger54f02222002-06-01 14:18:47 +00001848 elif request in self.keywords: self.showtopic(request)
1849 elif request in self.topics: self.showtopic(request)
Georg Brandld80d5f42010-12-03 07:47:22 +00001850 elif request: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001851 elif isinstance(request, Helper): self()
Georg Brandld80d5f42010-12-03 07:47:22 +00001852 else: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001853 self.output.write('\n')
1854
1855 def intro(self):
1856 self.output.write('''
Georg Brandlc645c6a2012-06-24 17:24:26 +02001857Welcome to Python %s! This is the interactive help utility.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001858
1859If this is your first time using Python, you should definitely check out
R David Murrayde0f6292012-03-31 12:06:35 -04001860the tutorial on the Internet at http://docs.python.org/%s/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001861
1862Enter the name of any module, keyword, or topic to get help on writing
1863Python programs and using Python modules. To quit this help utility and
1864return to the interpreter, just type "quit".
1865
Terry Jan Reedy34200572013-02-11 02:23:13 -05001866To get a list of available modules, keywords, symbols, or topics, type
1867"modules", "keywords", "symbols", or "topics". Each module also comes
1868with a one-line summary of what it does; to list the modules whose name
1869or summary contain a given string such as "spam", type "modules spam".
R David Murrayde0f6292012-03-31 12:06:35 -04001870''' % tuple([sys.version[:3]]*2))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001871
1872 def list(self, items, columns=4, width=80):
Guido van Rossum486364b2007-06-30 05:01:58 +00001873 items = list(sorted(items))
1874 colw = width // columns
1875 rows = (len(items) + columns - 1) // columns
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001876 for row in range(rows):
1877 for col in range(columns):
1878 i = col * rows + row
1879 if i < len(items):
1880 self.output.write(items[i])
1881 if col < columns - 1:
Guido van Rossum486364b2007-06-30 05:01:58 +00001882 self.output.write(' ' + ' ' * (colw - 1 - len(items[i])))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001883 self.output.write('\n')
1884
1885 def listkeywords(self):
1886 self.output.write('''
1887Here is a list of the Python keywords. Enter any keyword to get more help.
1888
1889''')
1890 self.list(self.keywords.keys())
1891
Georg Brandldb7b6b92009-01-01 15:53:14 +00001892 def listsymbols(self):
1893 self.output.write('''
1894Here is a list of the punctuation symbols which Python assigns special meaning
1895to. Enter any symbol to get more help.
1896
1897''')
1898 self.list(self.symbols.keys())
1899
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001900 def listtopics(self):
1901 self.output.write('''
1902Here is a list of available topics. Enter any topic name to get more help.
1903
1904''')
1905 self.list(self.topics.keys())
1906
Georg Brandldb7b6b92009-01-01 15:53:14 +00001907 def showtopic(self, topic, more_xrefs=''):
Georg Brandl6b38daa2008-06-01 21:05:17 +00001908 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001909 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04001910 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001911 self.output.write('''
Georg Brandl6b38daa2008-06-01 21:05:17 +00001912Sorry, topic and keyword documentation is not available because the
Georg Brandl5617db82009-04-27 16:28:57 +00001913module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001914''')
1915 return
1916 target = self.topics.get(topic, self.keywords.get(topic))
1917 if not target:
1918 self.output.write('no documentation found for %s\n' % repr(topic))
1919 return
1920 if type(target) is type(''):
Georg Brandldb7b6b92009-01-01 15:53:14 +00001921 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001922
Georg Brandl6b38daa2008-06-01 21:05:17 +00001923 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001924 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001925 doc = pydoc_data.topics.topics[label]
Georg Brandl6b38daa2008-06-01 21:05:17 +00001926 except KeyError:
1927 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001928 return
Georg Brandl6b38daa2008-06-01 21:05:17 +00001929 pager(doc.strip() + '\n')
Georg Brandldb7b6b92009-01-01 15:53:14 +00001930 if more_xrefs:
1931 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001932 if xrefs:
Brett Cannon1448ecf2013-10-04 11:38:59 -04001933 import textwrap
1934 text = 'Related help topics: ' + ', '.join(xrefs.split()) + '\n'
1935 wrapped_text = textwrap.wrap(text, 72)
1936 self.output.write('\n%s\n' % ''.join(wrapped_text))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001937
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001938 def _gettopic(self, topic, more_xrefs=''):
1939 """Return unbuffered tuple of (topic, xrefs).
1940
Georg Brandld2f38572011-01-30 08:37:19 +00001941 If an error occurs here, the exception is caught and displayed by
1942 the url handler.
1943
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001944 This function duplicates the showtopic method but returns its
1945 result directly so it can be formatted for display in an html page.
1946 """
1947 try:
1948 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04001949 except ImportError:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001950 return('''
1951Sorry, topic and keyword documentation is not available because the
1952module "pydoc_data.topics" could not be found.
1953''' , '')
1954 target = self.topics.get(topic, self.keywords.get(topic))
1955 if not target:
Georg Brandld2f38572011-01-30 08:37:19 +00001956 raise ValueError('could not find topic')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001957 if isinstance(target, str):
1958 return self._gettopic(target, more_xrefs)
1959 label, xrefs = target
Georg Brandld2f38572011-01-30 08:37:19 +00001960 doc = pydoc_data.topics.topics[label]
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001961 if more_xrefs:
1962 xrefs = (xrefs or '') + ' ' + more_xrefs
1963 return doc, xrefs
1964
Georg Brandldb7b6b92009-01-01 15:53:14 +00001965 def showsymbol(self, symbol):
1966 target = self.symbols[symbol]
1967 topic, _, xrefs = target.partition(' ')
1968 self.showtopic(topic, xrefs)
1969
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001970 def listmodules(self, key=''):
1971 if key:
1972 self.output.write('''
Terry Jan Reedy34200572013-02-11 02:23:13 -05001973Here is a list of modules whose name or summary contains '{}'.
1974If there are any, enter a module name to get more help.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001975
Terry Jan Reedy34200572013-02-11 02:23:13 -05001976'''.format(key))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001977 apropos(key)
1978 else:
1979 self.output.write('''
1980Please wait a moment while I gather a list of all available modules...
1981
1982''')
1983 modules = {}
1984 def callback(path, modname, desc, modules=modules):
1985 if modname and modname[-9:] == '.__init__':
1986 modname = modname[:-9] + ' (package)'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001987 if modname.find('.') < 0:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001988 modules[modname] = 1
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001989 def onerror(modname):
1990 callback(None, modname, None)
1991 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001992 self.list(modules.keys())
1993 self.output.write('''
1994Enter any module name to get more help. Or, type "modules spam" to search
Terry Jan Reedy34200572013-02-11 02:23:13 -05001995for modules whose name or summary contain the string "spam".
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001996''')
1997
Georg Brandl78aa3962010-07-31 21:51:48 +00001998help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001999
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002000class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002001 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002002
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002003 def run(self, callback, key=None, completer=None, onerror=None):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002004 if key: key = key.lower()
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002005 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002006 seen = {}
2007
2008 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002009 if modname != '__main__':
2010 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00002011 if key is None:
2012 callback(None, modname, '')
2013 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002014 name = __import__(modname).__doc__ or ''
2015 desc = name.split('\n')[0]
2016 name = modname + ' - ' + desc
2017 if name.lower().find(key) >= 0:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002018 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002019
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002020 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002021 if self.quit:
2022 break
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002023
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002024 if key is None:
2025 callback(None, modname, '')
2026 else:
Georg Brandl126c8792009-04-05 15:05:48 +00002027 try:
Eric Snow3a62d142014-01-06 20:42:59 -07002028 spec = pkgutil._get_spec(importer, modname)
Georg Brandl126c8792009-04-05 15:05:48 +00002029 except SyntaxError:
2030 # raised by tests for bad coding cookies or BOM
2031 continue
Eric Snow3a62d142014-01-06 20:42:59 -07002032 loader = spec.loader
Georg Brandl126c8792009-04-05 15:05:48 +00002033 if hasattr(loader, 'get_source'):
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002034 try:
2035 source = loader.get_source(modname)
Nick Coghlan2824cb52012-07-15 22:12:14 +10002036 except Exception:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002037 if onerror:
2038 onerror(modname)
2039 continue
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002040 desc = source_synopsis(io.StringIO(source)) or ''
Georg Brandl126c8792009-04-05 15:05:48 +00002041 if hasattr(loader, 'get_filename'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002042 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002043 else:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002044 path = None
2045 else:
Eric Snow3a62d142014-01-06 20:42:59 -07002046 _spec = importlib._bootstrap._SpecMethods(spec)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002047 try:
Eric Snow3a62d142014-01-06 20:42:59 -07002048 module = _spec.load()
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002049 except ImportError:
2050 if onerror:
2051 onerror(modname)
2052 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002053 desc = (module.__doc__ or '').splitlines()[0]
2054 path = getattr(module,'__file__',None)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002055 name = modname + ' - ' + desc
2056 if name.lower().find(key) >= 0:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002057 callback(path, modname, desc)
2058
2059 if completer:
2060 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002061
2062def apropos(key):
2063 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002064 def callback(path, modname, desc):
2065 if modname[-9:] == '.__init__':
2066 modname = modname[:-9] + ' (package)'
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002067 print(modname, desc and '- ' + desc)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002068 def onerror(modname):
2069 pass
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002070 with warnings.catch_warnings():
2071 warnings.filterwarnings('ignore') # ignore problems during import
2072 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002073
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002074# --------------------------------------- enhanced Web browser interface
2075
2076def _start_server(urlhandler, port):
2077 """Start an HTTP server thread on a specific port.
2078
2079 Start an HTML/text server thread, so HTML or text documents can be
2080 browsed dynamically and interactively with a Web browser. Example use:
2081
2082 >>> import time
2083 >>> import pydoc
2084
2085 Define a URL handler. To determine what the client is asking
2086 for, check the URL and content_type.
2087
2088 Then get or generate some text or HTML code and return it.
2089
2090 >>> def my_url_handler(url, content_type):
2091 ... text = 'the URL sent was: (%s, %s)' % (url, content_type)
2092 ... return text
2093
2094 Start server thread on port 0.
2095 If you use port 0, the server will pick a random port number.
2096 You can then use serverthread.port to get the port number.
2097
2098 >>> port = 0
2099 >>> serverthread = pydoc._start_server(my_url_handler, port)
2100
2101 Check that the server is really started. If it is, open browser
2102 and get first page. Use serverthread.url as the starting page.
2103
2104 >>> if serverthread.serving:
2105 ... import webbrowser
2106
2107 The next two lines are commented out so a browser doesn't open if
2108 doctest is run on this module.
2109
2110 #... webbrowser.open(serverthread.url)
2111 #True
2112
2113 Let the server do its thing. We just need to monitor its status.
2114 Use time.sleep so the loop doesn't hog the CPU.
2115
2116 >>> starttime = time.time()
2117 >>> timeout = 1 #seconds
2118
2119 This is a short timeout for testing purposes.
2120
2121 >>> while serverthread.serving:
2122 ... time.sleep(.01)
2123 ... if serverthread.serving and time.time() - starttime > timeout:
2124 ... serverthread.stop()
2125 ... break
2126
2127 Print any errors that may have occurred.
2128
2129 >>> print(serverthread.error)
2130 None
2131 """
2132 import http.server
2133 import email.message
2134 import select
2135 import threading
2136
2137 class DocHandler(http.server.BaseHTTPRequestHandler):
2138
2139 def do_GET(self):
2140 """Process a request from an HTML browser.
2141
2142 The URL received is in self.path.
2143 Get an HTML page from self.urlhandler and send it.
2144 """
2145 if self.path.endswith('.css'):
2146 content_type = 'text/css'
2147 else:
2148 content_type = 'text/html'
2149 self.send_response(200)
Georg Brandld2f38572011-01-30 08:37:19 +00002150 self.send_header('Content-Type', '%s; charset=UTF-8' % content_type)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002151 self.end_headers()
2152 self.wfile.write(self.urlhandler(
2153 self.path, content_type).encode('utf-8'))
2154
2155 def log_message(self, *args):
2156 # Don't log messages.
2157 pass
2158
2159 class DocServer(http.server.HTTPServer):
2160
2161 def __init__(self, port, callback):
2162 self.host = (sys.platform == 'mac') and '127.0.0.1' or 'localhost'
2163 self.address = ('', port)
2164 self.callback = callback
2165 self.base.__init__(self, self.address, self.handler)
2166 self.quit = False
2167
2168 def serve_until_quit(self):
2169 while not self.quit:
2170 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2171 if rd:
2172 self.handle_request()
Victor Stinnera3abd1d2011-01-03 16:12:39 +00002173 self.server_close()
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002174
2175 def server_activate(self):
2176 self.base.server_activate(self)
2177 if self.callback:
2178 self.callback(self)
2179
2180 class ServerThread(threading.Thread):
2181
2182 def __init__(self, urlhandler, port):
2183 self.urlhandler = urlhandler
2184 self.port = int(port)
2185 threading.Thread.__init__(self)
2186 self.serving = False
2187 self.error = None
2188
2189 def run(self):
2190 """Start the server."""
2191 try:
2192 DocServer.base = http.server.HTTPServer
2193 DocServer.handler = DocHandler
2194 DocHandler.MessageClass = email.message.Message
2195 DocHandler.urlhandler = staticmethod(self.urlhandler)
2196 docsvr = DocServer(self.port, self.ready)
2197 self.docserver = docsvr
2198 docsvr.serve_until_quit()
2199 except Exception as e:
2200 self.error = e
2201
2202 def ready(self, server):
2203 self.serving = True
2204 self.host = server.host
2205 self.port = server.server_port
2206 self.url = 'http://%s:%d/' % (self.host, self.port)
2207
2208 def stop(self):
2209 """Stop the server and this thread nicely"""
2210 self.docserver.quit = True
2211 self.serving = False
2212 self.url = None
2213
2214 thread = ServerThread(urlhandler, port)
2215 thread.start()
2216 # Wait until thread.serving is True to make sure we are
2217 # really up before returning.
2218 while not thread.error and not thread.serving:
2219 time.sleep(.01)
2220 return thread
2221
2222
2223def _url_handler(url, content_type="text/html"):
2224 """The pydoc url handler for use with the pydoc server.
2225
2226 If the content_type is 'text/css', the _pydoc.css style
2227 sheet is read and returned if it exits.
2228
2229 If the content_type is 'text/html', then the result of
2230 get_html_page(url) is returned.
2231 """
2232 class _HTMLDoc(HTMLDoc):
2233
2234 def page(self, title, contents):
2235 """Format an HTML page."""
2236 css_path = "pydoc_data/_pydoc.css"
2237 css_link = (
2238 '<link rel="stylesheet" type="text/css" href="%s">' %
2239 css_path)
2240 return '''\
2241<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Georg Brandld2f38572011-01-30 08:37:19 +00002242<html><head><title>Pydoc: %s</title>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002243<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Georg Brandld2f38572011-01-30 08:37:19 +00002244%s</head><body bgcolor="#f0f0f8">%s<div style="clear:both;padding-top:.5em;">%s</div>
2245</body></html>''' % (title, css_link, html_navbar(), contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002246
2247 def filelink(self, url, path):
2248 return '<a href="getfile?key=%s">%s</a>' % (url, path)
2249
2250
2251 html = _HTMLDoc()
2252
2253 def html_navbar():
Georg Brandld2f38572011-01-30 08:37:19 +00002254 version = html.escape("%s [%s, %s]" % (platform.python_version(),
2255 platform.python_build()[0],
2256 platform.python_compiler()))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002257 return """
2258 <div style='float:left'>
Georg Brandld2f38572011-01-30 08:37:19 +00002259 Python %s<br>%s
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002260 </div>
2261 <div style='float:right'>
2262 <div style='text-align:center'>
2263 <a href="index.html">Module Index</a>
2264 : <a href="topics.html">Topics</a>
2265 : <a href="keywords.html">Keywords</a>
2266 </div>
2267 <div>
Georg Brandld2f38572011-01-30 08:37:19 +00002268 <form action="get" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002269 <input type=text name=key size=15>
2270 <input type=submit value="Get">
Georg Brandld2f38572011-01-30 08:37:19 +00002271 </form>&nbsp;
2272 <form action="search" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002273 <input type=text name=key size=15>
2274 <input type=submit value="Search">
2275 </form>
2276 </div>
2277 </div>
Georg Brandld2f38572011-01-30 08:37:19 +00002278 """ % (version, html.escape(platform.platform(terse=True)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002279
2280 def html_index():
2281 """Module Index page."""
2282
2283 def bltinlink(name):
2284 return '<a href="%s.html">%s</a>' % (name, name)
2285
2286 heading = html.heading(
2287 '<big><big><strong>Index of Modules</strong></big></big>',
2288 '#ffffff', '#7799ee')
2289 names = [name for name in sys.builtin_module_names
2290 if name != '__main__']
2291 contents = html.multicolumn(names, bltinlink)
2292 contents = [heading, '<p>' + html.bigsection(
2293 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2294
2295 seen = {}
2296 for dir in sys.path:
2297 contents.append(html.index(dir, seen))
2298
2299 contents.append(
2300 '<p align=right><font color="#909090" face="helvetica,'
2301 'arial"><strong>pydoc</strong> by Ka-Ping Yee'
2302 '&lt;ping@lfw.org&gt;</font>')
Nick Coghlanecace282010-12-03 16:08:46 +00002303 return 'Index of Modules', ''.join(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002304
2305 def html_search(key):
2306 """Search results page."""
2307 # scan for modules
2308 search_result = []
2309
2310 def callback(path, modname, desc):
2311 if modname[-9:] == '.__init__':
2312 modname = modname[:-9] + ' (package)'
2313 search_result.append((modname, desc and '- ' + desc))
2314
2315 with warnings.catch_warnings():
2316 warnings.filterwarnings('ignore') # ignore problems during import
2317 ModuleScanner().run(callback, key)
2318
2319 # format page
2320 def bltinlink(name):
2321 return '<a href="%s.html">%s</a>' % (name, name)
2322
2323 results = []
2324 heading = html.heading(
2325 '<big><big><strong>Search Results</strong></big></big>',
2326 '#ffffff', '#7799ee')
2327 for name, desc in search_result:
2328 results.append(bltinlink(name) + desc)
2329 contents = heading + html.bigsection(
2330 'key = %s' % key, '#ffffff', '#ee77aa', '<br>'.join(results))
Nick Coghlanecace282010-12-03 16:08:46 +00002331 return 'Search Results', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002332
2333 def html_getfile(path):
2334 """Get and display a source file listing safely."""
Nick Coghlanecace282010-12-03 16:08:46 +00002335 path = path.replace('%20', ' ')
Victor Stinner91e08772011-07-05 14:30:41 +02002336 with tokenize.open(path) as fp:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002337 lines = html.escape(fp.read())
2338 body = '<pre>%s</pre>' % lines
2339 heading = html.heading(
2340 '<big><big><strong>File Listing</strong></big></big>',
2341 '#ffffff', '#7799ee')
2342 contents = heading + html.bigsection(
2343 'File: %s' % path, '#ffffff', '#ee77aa', body)
Nick Coghlanecace282010-12-03 16:08:46 +00002344 return 'getfile %s' % path, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002345
2346 def html_topics():
2347 """Index of topic texts available."""
2348
2349 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002350 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002351
2352 heading = html.heading(
2353 '<big><big><strong>INDEX</strong></big></big>',
2354 '#ffffff', '#7799ee')
2355 names = sorted(Helper.topics.keys())
2356
2357 contents = html.multicolumn(names, bltinlink)
2358 contents = heading + html.bigsection(
2359 'Topics', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002360 return 'Topics', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002361
2362 def html_keywords():
2363 """Index of keywords."""
2364 heading = html.heading(
2365 '<big><big><strong>INDEX</strong></big></big>',
2366 '#ffffff', '#7799ee')
2367 names = sorted(Helper.keywords.keys())
2368
2369 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002370 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002371
2372 contents = html.multicolumn(names, bltinlink)
2373 contents = heading + html.bigsection(
2374 'Keywords', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002375 return 'Keywords', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002376
2377 def html_topicpage(topic):
2378 """Topic or keyword help page."""
2379 buf = io.StringIO()
2380 htmlhelp = Helper(buf, buf)
2381 contents, xrefs = htmlhelp._gettopic(topic)
2382 if topic in htmlhelp.keywords:
2383 title = 'KEYWORD'
2384 else:
2385 title = 'TOPIC'
2386 heading = html.heading(
2387 '<big><big><strong>%s</strong></big></big>' % title,
2388 '#ffffff', '#7799ee')
Georg Brandld2f38572011-01-30 08:37:19 +00002389 contents = '<pre>%s</pre>' % html.markup(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002390 contents = html.bigsection(topic , '#ffffff','#ee77aa', contents)
Georg Brandld2f38572011-01-30 08:37:19 +00002391 if xrefs:
2392 xrefs = sorted(xrefs.split())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002393
Georg Brandld2f38572011-01-30 08:37:19 +00002394 def bltinlink(name):
2395 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002396
Georg Brandld2f38572011-01-30 08:37:19 +00002397 xrefs = html.multicolumn(xrefs, bltinlink)
2398 xrefs = html.section('Related help topics: ',
2399 '#ffffff', '#ee77aa', xrefs)
Nick Coghlanecace282010-12-03 16:08:46 +00002400 return ('%s %s' % (title, topic),
2401 ''.join((heading, contents, xrefs)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002402
Georg Brandld2f38572011-01-30 08:37:19 +00002403 def html_getobj(url):
2404 obj = locate(url, forceload=1)
2405 if obj is None and url != 'None':
2406 raise ValueError('could not find object')
2407 title = describe(obj)
2408 content = html.document(obj, url)
2409 return title, content
2410
2411 def html_error(url, exc):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002412 heading = html.heading(
2413 '<big><big><strong>Error</strong></big></big>',
Georg Brandld2f38572011-01-30 08:37:19 +00002414 '#ffffff', '#7799ee')
2415 contents = '<br>'.join(html.escape(line) for line in
2416 format_exception_only(type(exc), exc))
2417 contents = heading + html.bigsection(url, '#ffffff', '#bb0000',
2418 contents)
2419 return "Error - %s" % url, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002420
2421 def get_html_page(url):
2422 """Generate an HTML page for url."""
Georg Brandld2f38572011-01-30 08:37:19 +00002423 complete_url = url
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002424 if url.endswith('.html'):
2425 url = url[:-5]
Georg Brandld2f38572011-01-30 08:37:19 +00002426 try:
2427 if url in ("", "index"):
2428 title, content = html_index()
2429 elif url == "topics":
2430 title, content = html_topics()
2431 elif url == "keywords":
2432 title, content = html_keywords()
2433 elif '=' in url:
2434 op, _, url = url.partition('=')
2435 if op == "search?key":
2436 title, content = html_search(url)
2437 elif op == "getfile?key":
2438 title, content = html_getfile(url)
2439 elif op == "topic?key":
2440 # try topics first, then objects.
2441 try:
2442 title, content = html_topicpage(url)
2443 except ValueError:
2444 title, content = html_getobj(url)
2445 elif op == "get?key":
2446 # try objects first, then topics.
2447 if url in ("", "index"):
2448 title, content = html_index()
2449 else:
2450 try:
2451 title, content = html_getobj(url)
2452 except ValueError:
2453 title, content = html_topicpage(url)
2454 else:
2455 raise ValueError('bad pydoc url')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002456 else:
Georg Brandld2f38572011-01-30 08:37:19 +00002457 title, content = html_getobj(url)
2458 except Exception as exc:
2459 # Catch any errors and display them in an error page.
2460 title, content = html_error(complete_url, exc)
2461 return html.page(title, content)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002462
2463 if url.startswith('/'):
2464 url = url[1:]
2465 if content_type == 'text/css':
2466 path_here = os.path.dirname(os.path.realpath(__file__))
Georg Brandld2f38572011-01-30 08:37:19 +00002467 css_path = os.path.join(path_here, url)
2468 with open(css_path) as fp:
2469 return ''.join(fp.readlines())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002470 elif content_type == 'text/html':
2471 return get_html_page(url)
Georg Brandld2f38572011-01-30 08:37:19 +00002472 # Errors outside the url handler are caught by the server.
2473 raise TypeError('unknown content type %r for url %s' % (content_type, url))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002474
2475
2476def browse(port=0, *, open_browser=True):
2477 """Start the enhanced pydoc Web server and open a Web browser.
2478
2479 Use port '0' to start the server on an arbitrary port.
2480 Set open_browser to False to suppress opening a browser.
2481 """
2482 import webbrowser
2483 serverthread = _start_server(_url_handler, port)
2484 if serverthread.error:
2485 print(serverthread.error)
2486 return
2487 if serverthread.serving:
2488 server_help_msg = 'Server commands: [b]rowser, [q]uit'
2489 if open_browser:
2490 webbrowser.open(serverthread.url)
2491 try:
2492 print('Server ready at', serverthread.url)
2493 print(server_help_msg)
2494 while serverthread.serving:
2495 cmd = input('server> ')
2496 cmd = cmd.lower()
2497 if cmd == 'q':
2498 break
2499 elif cmd == 'b':
2500 webbrowser.open(serverthread.url)
2501 else:
2502 print(server_help_msg)
2503 except (KeyboardInterrupt, EOFError):
2504 print()
2505 finally:
2506 if serverthread.serving:
2507 serverthread.stop()
2508 print('Server stopped')
2509
2510
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002511# -------------------------------------------------- command-line interface
2512
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002513def ispath(x):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002514 return isinstance(x, str) and x.find(os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002515
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002516def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002517 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002518 import getopt
Guido van Rossum756aa932007-04-07 03:04:01 +00002519 class BadUsage(Exception): pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002520
Nick Coghlan106274b2009-11-15 23:04:33 +00002521 # Scripts don't get the current directory in their path by default
2522 # unless they are run with the '-m' switch
2523 if '' not in sys.path:
2524 scriptdir = os.path.dirname(sys.argv[0])
2525 if scriptdir in sys.path:
2526 sys.path.remove(scriptdir)
2527 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002528
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002529 try:
Victor Stinner383c3fc2011-05-25 01:35:05 +02002530 opts, args = getopt.getopt(sys.argv[1:], 'bk:p:w')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002531 writing = False
2532 start_server = False
2533 open_browser = False
2534 port = None
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002535 for opt, val in opts:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002536 if opt == '-b':
2537 start_server = True
2538 open_browser = True
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002539 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002540 apropos(val)
2541 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002542 if opt == '-p':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002543 start_server = True
2544 port = val
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002545 if opt == '-w':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002546 writing = True
2547
Benjamin Petersonb29614e2012-10-09 11:16:03 -04002548 if start_server:
2549 if port is None:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002550 port = 0
2551 browse(port, open_browser=open_browser)
2552 return
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002553
2554 if not args: raise BadUsage
2555 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002556 if ispath(arg) and not os.path.exists(arg):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002557 print('file %r does not exist' % arg)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002558 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002559 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002560 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002561 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002562 if writing:
2563 if ispath(arg) and os.path.isdir(arg):
2564 writedocs(arg)
2565 else:
2566 writedoc(arg)
2567 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002568 help.help(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +00002569 except ErrorDuringImport as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002570 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002571
2572 except (getopt.error, BadUsage):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002573 cmd = os.path.splitext(os.path.basename(sys.argv[0]))[0]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002574 print("""pydoc - the Python documentation tool
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002575
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002576{cmd} <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002577 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002578 Python keyword, topic, function, module, or package, or a dotted
2579 reference to a class or function within a module or module in a
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002580 package. If <name> contains a '{sep}', it is used as the path to a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002581 Python source file to document. If name is 'keywords', 'topics',
2582 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002583
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002584{cmd} -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002585 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002586
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002587{cmd} -p <port>
2588 Start an HTTP server on the given port on the local machine. Port
2589 number 0 can be used to get an arbitrary unused port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002590
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002591{cmd} -b
2592 Start an HTTP server on an arbitrary unused port and open a Web browser
2593 to interactively browse documentation. The -p option can be used with
2594 the -b option to explicitly specify the server port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002595
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002596{cmd} -w <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002597 Write out the HTML documentation for a module to a file in the current
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002598 directory. If <name> contains a '{sep}', it is treated as a filename; if
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002599 it names a directory, documentation is written for all the contents.
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002600""".format(cmd=cmd, sep=os.sep))
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002601
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002602if __name__ == '__main__':
2603 cli()