blob: 42f65dcf794028a6691fe27a1fae0c73dc711d20 [file] [log] [blame]
Benjamin Peterson90f5ba52010-03-11 22:53:45 +00001#!/usr/bin/env python3
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002"""Generate Python documentation in HTML or text for interactive use.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00003
R David Murray3d050dd2014-04-19 12:59:30 -04004At the Python interactive prompt, calling help(thing) on a Python object
5documents the object, and calling help() starts up an interactive
6help session.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00007
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00008Or, at the shell command line outside of Python:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00009
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000010Run "pydoc <name>" to show documentation on something. <name> may be
11the name of a function, module, package, or a dotted reference to a
12class or function within a module or module in a package. If the
13argument contains a path segment delimiter (e.g. slash on Unix,
14backslash on Windows) it is treated as the path to a Python source file.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000015
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000016Run "pydoc -k <keyword>" to search for a keyword in the synopsis lines
17of all available modules.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000018
Nick Coghlan7bb30b72010-12-03 09:29:11 +000019Run "pydoc -p <port>" to start an HTTP server on the given port on the
20local machine. Port number 0 can be used to get an arbitrary unused port.
21
22Run "pydoc -b" to start an HTTP server on an arbitrary unused port and
23open a Web browser to interactively browse documentation. The -p option
24can be used with the -b option to explicitly specify the server port.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000025
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000026Run "pydoc -w <name>" to write out the HTML documentation for a module
27to a file named "<name>.html".
Skip Montanaro4997a692003-09-10 16:47:51 +000028
29Module docs for core modules are assumed to be in
30
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000031 http://docs.python.org/X.Y/library/
Skip Montanaro4997a692003-09-10 16:47:51 +000032
33This can be overridden by setting the PYTHONDOCS environment variable
34to a different URL or to a local directory containing the Library
35Reference Manual pages.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000036"""
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000037__all__ = ['help']
Ka-Ping Yeedd175342001-02-27 14:43:46 +000038__author__ = "Ka-Ping Yee <ping@lfw.org>"
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000039__date__ = "26 February 2001"
Jeremy Hylton3e0055f2005-10-20 19:59:25 +000040
Martin v. Löwis6fe8f192004-11-14 10:21:04 +000041__credits__ = """Guido van Rossum, for an excellent programming language.
Ka-Ping Yee5e2b1732001-02-27 23:35:09 +000042Tommy Burnette, the original creator of manpy.
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000043Paul Prescod, for all his work on onlinehelp.
44Richard Chamberlain, for the first implementation of textdoc.
Raymond Hettingered2dbe32005-01-01 07:51:01 +000045"""
Ka-Ping Yeedd175342001-02-27 14:43:46 +000046
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000047# Known bugs that can't be fixed here:
Brett Cannonf4ba4ec2013-06-15 14:25:04 -040048# - synopsis() cannot be prevented from clobbering existing
49# loaded modules.
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000050# - If the __file__ attribute on a module is a relative path and
51# the current directory is changed with os.chdir(), an incorrect
52# path will be displayed.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000053
Nick Coghlan7bb30b72010-12-03 09:29:11 +000054import builtins
Brett Cannond5e6f2e2013-06-11 17:09:36 -040055import importlib._bootstrap
Brett Cannoncb66eb02012-05-11 12:58:42 -040056import importlib.machinery
Brett Cannonf4ba4ec2013-06-15 14:25:04 -040057import importlib.util
Nick Coghlan7bb30b72010-12-03 09:29:11 +000058import inspect
Victor Stinnere6c910e2011-06-30 15:55:43 +020059import io
60import os
Nick Coghlan7bb30b72010-12-03 09:29:11 +000061import pkgutil
62import platform
63import re
Victor Stinnere6c910e2011-06-30 15:55:43 +020064import sys
Nick Coghlan7bb30b72010-12-03 09:29:11 +000065import time
Victor Stinnere6c910e2011-06-30 15:55:43 +020066import tokenize
Nick Coghlan7bb30b72010-12-03 09:29:11 +000067import warnings
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000068from collections import deque
Nick Coghlan7bb30b72010-12-03 09:29:11 +000069from reprlib import Repr
Victor Stinner7fa767e2014-03-20 09:16:38 +010070from traceback import format_exception_only
Nick Coghlan7bb30b72010-12-03 09:29:11 +000071
72
Ka-Ping Yeedd175342001-02-27 14:43:46 +000073# --------------------------------------------------------- common routines
74
Ka-Ping Yeedd175342001-02-27 14:43:46 +000075def pathdirs():
76 """Convert sys.path into a list of absolute, existing, unique paths."""
77 dirs = []
Ka-Ping Yee1d384632001-03-01 00:24:32 +000078 normdirs = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +000079 for dir in sys.path:
80 dir = os.path.abspath(dir or '.')
Ka-Ping Yee1d384632001-03-01 00:24:32 +000081 normdir = os.path.normcase(dir)
82 if normdir not in normdirs and os.path.isdir(dir):
Ka-Ping Yeedd175342001-02-27 14:43:46 +000083 dirs.append(dir)
Ka-Ping Yee1d384632001-03-01 00:24:32 +000084 normdirs.append(normdir)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000085 return dirs
86
87def getdoc(object):
88 """Get the doc string or comments for an object."""
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000089 result = inspect.getdoc(object) or inspect.getcomments(object)
Neal Norwitz9d72bb42007-04-17 08:48:32 +000090 return result and re.sub('^ *\n', '', result.rstrip()) or ''
Ka-Ping Yeedd175342001-02-27 14:43:46 +000091
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000092def splitdoc(doc):
93 """Split a doc string into a synopsis line (if any) and the rest."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +000094 lines = doc.strip().split('\n')
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000095 if len(lines) == 1:
96 return lines[0], ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +000097 elif len(lines) >= 2 and not lines[1].rstrip():
98 return lines[0], '\n'.join(lines[2:])
99 return '', '\n'.join(lines)
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000101def classname(object, modname):
102 """Get a class name and qualify it with a module name if necessary."""
103 name = object.__name__
104 if object.__module__ != modname:
105 name = object.__module__ + '.' + name
106 return name
107
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000108def isdata(object):
Georg Brandl94432422005-07-22 21:52:25 +0000109 """Check if an object is of a type that probably means it's data."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000110 return not (inspect.ismodule(object) or inspect.isclass(object) or
111 inspect.isroutine(object) or inspect.isframe(object) or
112 inspect.istraceback(object) or inspect.iscode(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000113
114def replace(text, *pairs):
115 """Do a series of global replacements on a string."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000116 while pairs:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000117 text = pairs[1].join(text.split(pairs[0]))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000118 pairs = pairs[2:]
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000119 return text
120
121def cram(text, maxlen):
122 """Omit part of a string if needed to make it fit in a maximum length."""
123 if len(text) > maxlen:
Raymond Hettingerfca3bb62002-10-21 04:44:11 +0000124 pre = max(0, (maxlen-3)//2)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000125 post = max(0, maxlen-3-pre)
126 return text[:pre] + '...' + text[len(text)-post:]
127 return text
128
Brett Cannon84601f12004-06-19 01:22:48 +0000129_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000130def stripid(text):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000131 """Remove the hexadecimal id from a Python object representation."""
Brett Cannonc6c1f472004-06-19 01:02:51 +0000132 # The behaviour of %p is implementation-dependent in terms of case.
Ezio Melotti412c95a2010-02-16 23:31:04 +0000133 return _re_stripid.sub(r'\1', text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000134
Brett Cannonc6c1f472004-06-19 01:02:51 +0000135def _is_some_method(obj):
R David Murrayac0cea52013-03-19 02:47:44 -0400136 return (inspect.isfunction(obj) or
137 inspect.ismethod(obj) or
138 inspect.isbuiltin(obj) or
139 inspect.ismethoddescriptor(obj))
Tim Peters536d2262001-09-20 05:13:38 +0000140
Larry Hastings24a882b2014-02-20 23:34:46 -0800141def _is_bound_method(fn):
142 """
143 Returns True if fn is a bound method, regardless of whether
144 fn was implemented in Python or in C.
145 """
146 if inspect.ismethod(fn):
147 return True
148 if inspect.isbuiltin(fn):
149 self = getattr(fn, '__self__', None)
150 return not (inspect.ismodule(self) or (self is None))
151 return False
152
153
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000154def allmethods(cl):
155 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000156 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000157 methods[key] = 1
158 for base in cl.__bases__:
159 methods.update(allmethods(base)) # all your base are belong to us
160 for key in methods.keys():
161 methods[key] = getattr(cl, key)
162 return methods
163
Tim Petersfa26f7c2001-09-24 08:05:11 +0000164def _split_list(s, predicate):
165 """Split sequence s via predicate, and return pair ([true], [false]).
166
167 The return value is a 2-tuple of lists,
168 ([x for x in s if predicate(x)],
169 [x for x in s if not predicate(x)])
170 """
171
Tim Peters28355492001-09-23 21:29:55 +0000172 yes = []
173 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000174 for x in s:
175 if predicate(x):
176 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000177 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000178 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000179 return yes, no
180
Raymond Hettinger1103d052011-03-25 14:15:24 -0700181def visiblename(name, all=None, obj=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000182 """Decide whether to show documentation on a variable."""
Brett Cannond340b432012-08-06 17:19:22 -0400183 # Certain special names are redundant or internal.
Eric Snowb523f842013-11-22 09:05:39 -0700184 # XXX Remove __initializing__?
Brett Cannond340b432012-08-06 17:19:22 -0400185 if name in {'__author__', '__builtins__', '__cached__', '__credits__',
Eric Snowb523f842013-11-22 09:05:39 -0700186 '__date__', '__doc__', '__file__', '__spec__',
Brett Cannond340b432012-08-06 17:19:22 -0400187 '__loader__', '__module__', '__name__', '__package__',
188 '__path__', '__qualname__', '__slots__', '__version__'}:
Raymond Hettinger68272942011-03-18 02:22:15 -0700189 return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000190 # Private names are hidden, but special names are displayed.
191 if name.startswith('__') and name.endswith('__'): return 1
Raymond Hettinger1103d052011-03-25 14:15:24 -0700192 # Namedtuples have public fields and methods with a single leading underscore
193 if name.startswith('_') and hasattr(obj, '_fields'):
194 return True
Skip Montanaroa5616d22004-06-11 04:46:12 +0000195 if all is not None:
196 # only document that which the programmer exported in __all__
197 return name in all
198 else:
199 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000200
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000201def classify_class_attrs(object):
202 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000203 results = []
204 for (name, kind, cls, value) in inspect.classify_class_attrs(object):
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000205 if inspect.isdatadescriptor(value):
206 kind = 'data descriptor'
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000207 results.append((name, kind, cls, value))
208 return results
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000209
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000210# ----------------------------------------------------- module manipulation
211
212def ispackage(path):
213 """Guess whether a path refers to a package directory."""
214 if os.path.isdir(path):
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000215 for ext in ('.py', '.pyc', '.pyo'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000216 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000217 return True
218 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000219
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000220def source_synopsis(file):
221 line = file.readline()
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000222 while line[:1] == '#' or not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000223 line = file.readline()
224 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000225 line = line.strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000226 if line[:4] == 'r"""': line = line[1:]
227 if line[:3] == '"""':
228 line = line[3:]
229 if line[-1:] == '\\': line = line[:-1]
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000230 while not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000231 line = file.readline()
232 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000233 result = line.split('"""')[0].strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000234 else: result = None
235 return result
236
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000237def synopsis(filename, cache={}):
238 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000239 mtime = os.stat(filename).st_mtime
Charles-François Natali27c4e882011-07-27 19:40:02 +0200240 lastupdate, result = cache.get(filename, (None, None))
241 if lastupdate is None or lastupdate < mtime:
Eric Snowaed5b222014-01-04 20:38:11 -0700242 # Look for binary suffixes first, falling back to source.
243 if filename.endswith(tuple(importlib.machinery.BYTECODE_SUFFIXES)):
244 loader_cls = importlib.machinery.SourcelessFileLoader
245 elif filename.endswith(tuple(importlib.machinery.EXTENSION_SUFFIXES)):
246 loader_cls = importlib.machinery.ExtensionFileLoader
247 else:
248 loader_cls = None
249 # Now handle the choice.
250 if loader_cls is None:
251 # Must be a source file.
252 try:
253 file = tokenize.open(filename)
254 except OSError:
255 # module can't be opened, so skip it
256 return None
257 # text modules can be directly examined
258 with file:
259 result = source_synopsis(file)
260 else:
261 # Must be a binary module, which has to be imported.
262 loader = loader_cls('__temp__', filename)
Eric Snow3a62d142014-01-06 20:42:59 -0700263 # XXX We probably don't need to pass in the loader here.
264 spec = importlib.util.spec_from_file_location('__temp__', filename,
265 loader=loader)
Brett Cannoncb66eb02012-05-11 12:58:42 -0400266 try:
Brett Cannon2a17bde2014-05-30 14:55:29 -0400267 module = importlib._bootstrap._load(spec)
Brett Cannoncb66eb02012-05-11 12:58:42 -0400268 except:
269 return None
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000270 del sys.modules['__temp__']
Eric Snowaed5b222014-01-04 20:38:11 -0700271 result = (module.__doc__ or '').splitlines()[0]
272 # Cache the result.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000273 cache[filename] = (mtime, result)
274 return result
275
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000276class ErrorDuringImport(Exception):
277 """Errors that occurred while trying to import something to document it."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000278 def __init__(self, filename, exc_info):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000279 self.filename = filename
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000280 self.exc, self.value, self.tb = exc_info
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000281
282 def __str__(self):
Guido van Rossuma01a8b62007-05-27 09:20:14 +0000283 exc = self.exc.__name__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000284 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000285
286def importfile(path):
287 """Import a Python source file or compiled file given its path."""
Brett Cannonf4ba4ec2013-06-15 14:25:04 -0400288 magic = importlib.util.MAGIC_NUMBER
Victor Stinnere975af62011-07-04 02:08:50 +0200289 with open(path, 'rb') as file:
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400290 is_bytecode = magic == file.read(len(magic))
291 filename = os.path.basename(path)
292 name, ext = os.path.splitext(filename)
293 if is_bytecode:
294 loader = importlib._bootstrap.SourcelessFileLoader(name, path)
295 else:
296 loader = importlib._bootstrap.SourceFileLoader(name, path)
Eric Snow3a62d142014-01-06 20:42:59 -0700297 # XXX We probably don't need to pass in the loader here.
298 spec = importlib.util.spec_from_file_location(name, path, loader=loader)
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400299 try:
Brett Cannon2a17bde2014-05-30 14:55:29 -0400300 return importlib._bootstrap._load(spec)
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400301 except:
302 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000303
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000304def safeimport(path, forceload=0, cache={}):
305 """Import a module; handle errors; return None if the module isn't found.
306
307 If the module *is* found but an exception occurs, it's wrapped in an
308 ErrorDuringImport exception and reraised. Unlike __import__, if a
309 package path is specified, the module at the end of the path is returned,
310 not the package at the beginning. If the optional 'forceload' argument
311 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000312 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000313 # If forceload is 1 and the module has been previously loaded from
314 # disk, we always have to reload the module. Checking the file's
315 # mtime isn't good enough (e.g. the module could contain a class
316 # that inherits from another module that has changed).
317 if forceload and path in sys.modules:
318 if path not in sys.builtin_module_names:
Guido van Rossume7ba4952007-06-06 23:52:48 +0000319 # Remove the module from sys.modules and re-import to try
320 # and avoid problems with partially loaded modules.
321 # Also remove any submodules because they won't appear
322 # in the newly loaded module's namespace if they're already
323 # in sys.modules.
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000324 subs = [m for m in sys.modules if m.startswith(path + '.')]
325 for key in [path] + subs:
326 # Prevent garbage collection.
327 cache[key] = sys.modules[key]
328 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000329 module = __import__(path)
330 except:
331 # Did the error occur before or after the module was found?
332 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000333 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000334 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000335 raise ErrorDuringImport(sys.modules[path].__file__, info)
336 elif exc is SyntaxError:
337 # A SyntaxError occurred before we could execute the module.
338 raise ErrorDuringImport(value.filename, info)
Brett Cannon679ecb52013-07-04 17:51:50 -0400339 elif exc is ImportError and value.name == path:
Brett Cannonfd074152012-04-14 14:10:13 -0400340 # No such module in the path.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000341 return None
342 else:
343 # Some other error occurred during the importing process.
344 raise ErrorDuringImport(path, sys.exc_info())
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000345 for part in path.split('.')[1:]:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000346 try: module = getattr(module, part)
347 except AttributeError: return None
348 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000349
350# ---------------------------------------------------- formatter base class
351
352class Doc:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000353
354 PYTHONDOCS = os.environ.get("PYTHONDOCS",
355 "http://docs.python.org/%d.%d/library"
356 % sys.version_info[:2])
357
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000358 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000359 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000360 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000361 # 'try' clause is to attempt to handle the possibility that inspect
362 # identifies something in a way that pydoc itself has issues handling;
363 # think 'super' and how it is a descriptor (which raises the exception
364 # by lacking a __name__ attribute) and an instance.
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000365 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
366 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000367 try:
368 if inspect.ismodule(object): return self.docmodule(*args)
369 if inspect.isclass(object): return self.docclass(*args)
370 if inspect.isroutine(object): return self.docroutine(*args)
371 except AttributeError:
372 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000373 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000374 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000375
376 def fail(self, object, name=None, *args):
377 """Raise an exception for unimplemented types."""
378 message = "don't know how to document object%s of type %s" % (
379 name and ' ' + repr(name), type(object).__name__)
Collin Winterce36ad82007-08-30 01:19:48 +0000380 raise TypeError(message)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000381
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000382 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000383
Skip Montanaro4997a692003-09-10 16:47:51 +0000384 def getdocloc(self, object):
385 """Return the location of module docs or None"""
386
387 try:
388 file = inspect.getabsfile(object)
389 except TypeError:
390 file = '(built-in)'
391
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000392 docloc = os.environ.get("PYTHONDOCS", self.PYTHONDOCS)
393
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100394 basedir = os.path.join(sys.base_exec_prefix, "lib",
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000395 "python%d.%d" % sys.version_info[:2])
Skip Montanaro4997a692003-09-10 16:47:51 +0000396 if (isinstance(object, type(os)) and
397 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
398 'marshal', 'posix', 'signal', 'sys',
Georg Brandl2067bfd2008-05-25 13:05:15 +0000399 '_thread', 'zipimport') or
Skip Montanaro4997a692003-09-10 16:47:51 +0000400 (file.startswith(basedir) and
Brian Curtin49c284c2010-03-31 03:19:28 +0000401 not file.startswith(os.path.join(basedir, 'site-packages')))) and
Brian Curtinedef05b2010-04-01 04:05:25 +0000402 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
Skip Montanaro4997a692003-09-10 16:47:51 +0000403 if docloc.startswith("http://"):
Georg Brandl86def6c2008-01-21 20:36:10 +0000404 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
Skip Montanaro4997a692003-09-10 16:47:51 +0000405 else:
Georg Brandl86def6c2008-01-21 20:36:10 +0000406 docloc = os.path.join(docloc, object.__name__ + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000407 else:
408 docloc = None
409 return docloc
410
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000411# -------------------------------------------- HTML documentation generator
412
413class HTMLRepr(Repr):
414 """Class for safely making an HTML representation of a Python object."""
415 def __init__(self):
416 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000417 self.maxlist = self.maxtuple = 20
418 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000419 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000420
421 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000422 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000423
424 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000425 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000426
427 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000428 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000429 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000430 if hasattr(self, methodname):
431 return getattr(self, methodname)(x, level)
432 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000433
434 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000435 test = cram(x, self.maxstring)
436 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000437 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000438 # Backslashes are only literal in the string and are never
439 # needed to make any special characters, so show a raw string.
440 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000441 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000442 r'<font color="#c040c0">\1</font>',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000443 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000444
Skip Montanarodf708782002-03-07 22:58:02 +0000445 repr_str = repr_string
446
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000447 def repr_instance(self, x, level):
448 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000449 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000450 except:
451 return self.escape('<%s instance>' % x.__class__.__name__)
452
453 repr_unicode = repr_string
454
455class HTMLDoc(Doc):
456 """Formatter class for HTML documentation."""
457
458 # ------------------------------------------- HTML formatting utilities
459
460 _repr_instance = HTMLRepr()
461 repr = _repr_instance.repr
462 escape = _repr_instance.escape
463
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000464 def page(self, title, contents):
465 """Format an HTML page."""
Georg Brandl388faac2009-04-10 08:31:48 +0000466 return '''\
Georg Brandle6066942009-04-10 08:28:28 +0000467<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000468<html><head><title>Python: %s</title>
Georg Brandl388faac2009-04-10 08:31:48 +0000469<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000470</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000471%s
472</body></html>''' % (title, contents)
473
474 def heading(self, title, fgcol, bgcol, extras=''):
475 """Format a page heading."""
476 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000477<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000478<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000479<td valign=bottom>&nbsp;<br>
480<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000481><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000482><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000483 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
484
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000485 def section(self, title, fgcol, bgcol, contents, width=6,
486 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000487 """Format a section with a heading."""
488 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000489 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000490 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000491<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000492<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000493<td colspan=3 valign=bottom>&nbsp;<br>
494<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000495 ''' % (bgcol, fgcol, title)
496 if prelude:
497 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000498<tr bgcolor="%s"><td rowspan=2>%s</td>
499<td colspan=2>%s</td></tr>
500<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
501 else:
502 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000503<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000504
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000505 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000506
507 def bigsection(self, title, *args):
508 """Format a section with a big heading."""
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000509 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000510 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000511
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000512 def preformat(self, text):
513 """Format literal preformatted text."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000514 text = self.escape(text.expandtabs())
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000515 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
516 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000517
518 def multicolumn(self, list, format, cols=4):
519 """Format a list of items into a multi-column list."""
520 result = ''
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000521 rows = (len(list)+cols-1)//cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000522 for col in range(cols):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000523 result = result + '<td width="%d%%" valign=top>' % (100//cols)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000524 for i in range(rows*col, rows*col+rows):
525 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000526 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000527 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000528 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000529
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000530 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000531
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000532 def namelink(self, name, *dicts):
533 """Make a link for an identifier, given name-to-URL mappings."""
534 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000535 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000536 return '<a href="%s">%s</a>' % (dict[name], name)
537 return name
538
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000539 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000540 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000541 name, module = object.__name__, sys.modules.get(object.__module__)
542 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000543 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000544 module.__name__, name, classname(object, modname))
545 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000546
547 def modulelink(self, object):
548 """Make a link for a module."""
549 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
550
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000551 def modpkglink(self, modpkginfo):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000552 """Make a link for a module or package to display in an index."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000553 name, path, ispackage, shadowed = modpkginfo
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000554 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000555 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000556 if path:
557 url = '%s.%s.html' % (path, name)
558 else:
559 url = '%s.html' % name
560 if ispackage:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000561 text = '<strong>%s</strong>&nbsp;(package)' % name
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000562 else:
563 text = name
564 return '<a href="%s">%s</a>' % (url, text)
565
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000566 def filelink(self, url, path):
567 """Make a link to source file."""
568 return '<a href="file:%s">%s</a>' % (url, path)
569
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000570 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
571 """Mark up some plain text, given a context of symbols to look for.
572 Each context dictionary maps object names to anchor names."""
573 escape = escape or self.escape
574 results = []
575 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000576 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
577 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000578 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000579 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000580 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000581 match = pattern.search(text, here)
582 if not match: break
583 start, end = match.span()
584 results.append(escape(text[here:start]))
585
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000586 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000587 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000588 url = escape(all).replace('"', '&quot;')
589 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000590 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000591 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
592 results.append('<a href="%s">%s</a>' % (url, escape(all)))
593 elif pep:
Christian Heimes2202f872008-02-06 14:31:34 +0000594 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000595 results.append('<a href="%s">%s</a>' % (url, escape(all)))
596 elif text[end:end+1] == '(':
597 results.append(self.namelink(name, methods, funcs, classes))
598 elif selfdot:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000599 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000600 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000601 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000602 here = end
603 results.append(escape(text[here:]))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000604 return ''.join(results)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000605
606 # ---------------------------------------------- type-specific routines
607
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000608 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000609 """Produce HTML for a class tree as given by inspect.getclasstree()."""
610 result = ''
611 for entry in tree:
612 if type(entry) is type(()):
613 c, bases = entry
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000614 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000615 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000616 if bases and bases != (parent,):
617 parents = []
618 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000619 parents.append(self.classlink(base, modname))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000620 result = result + '(' + ', '.join(parents) + ')'
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000621 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000622 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000623 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000624 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000625 return '<dl>\n%s</dl>\n' % result
626
Tim Peters8dd7ade2001-10-18 19:56:17 +0000627 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000628 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000629 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000630 try:
631 all = object.__all__
632 except AttributeError:
633 all = None
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000634 parts = name.split('.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000635 links = []
636 for i in range(len(parts)-1):
637 links.append(
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000638 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000639 ('.'.join(parts[:i+1]), parts[i]))
640 linkedname = '.'.join(links + parts[-1:])
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000641 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000642 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000643 path = inspect.getabsfile(object)
Ka-Ping Yee6191a232001-04-13 15:00:27 +0000644 url = path
645 if sys.platform == 'win32':
646 import nturl2path
647 url = nturl2path.pathname2url(path)
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000648 filelink = self.filelink(url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000649 except TypeError:
650 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000651 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000652 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000653 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000654 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000655 version = version[11:-1].strip()
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000656 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000657 if hasattr(object, '__date__'):
658 info.append(self.escape(str(object.__date__)))
659 if info:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000660 head = head + ' (%s)' % ', '.join(info)
Skip Montanaro4997a692003-09-10 16:47:51 +0000661 docloc = self.getdocloc(object)
662 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000663 docloc = '<br><a href="%(docloc)s">Module Reference</a>' % locals()
Skip Montanaro4997a692003-09-10 16:47:51 +0000664 else:
665 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000666 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000667 head, '#ffffff', '#7799ee',
668 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000669
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000670 modules = inspect.getmembers(object, inspect.ismodule)
671
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000672 classes, cdict = [], {}
673 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000674 # if __all__ exists, believe it. Otherwise use old heuristic.
675 if (all is not None or
676 (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700677 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000678 classes.append((key, value))
679 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000680 for key, value in classes:
681 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000682 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000683 module = sys.modules.get(modname)
684 if modname != name and module and hasattr(module, key):
685 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000686 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000687 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000688 funcs, fdict = [], {}
689 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000690 # if __all__ exists, believe it. Otherwise use old heuristic.
691 if (all is not None or
692 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700693 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000694 funcs.append((key, value))
695 fdict[key] = '#-' + key
696 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000697 data = []
698 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700699 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000700 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000701
702 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
703 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000704 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000705
706 if hasattr(object, '__path__'):
707 modpkgs = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000708 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
709 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000710 modpkgs.sort()
711 contents = self.multicolumn(modpkgs, self.modpkglink)
712 result = result + self.bigsection(
713 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000714 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000715 contents = self.multicolumn(
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000716 modules, lambda t: self.modulelink(t[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000717 result = result + self.bigsection(
Christian Heimes7131fd92008-02-19 14:21:46 +0000718 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000719
720 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000721 classlist = [value for (key, value) in classes]
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000722 contents = [
723 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000724 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000725 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000726 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000727 'Classes', '#ffffff', '#ee77aa', ' '.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000728 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000729 contents = []
730 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000731 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000732 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000733 'Functions', '#ffffff', '#eeaa77', ' '.join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000734 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000735 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000736 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000737 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000738 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000739 'Data', '#ffffff', '#55aa55', '<br>\n'.join(contents))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000740 if hasattr(object, '__author__'):
741 contents = self.markup(str(object.__author__), self.preformat)
742 result = result + self.bigsection(
743 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000744 if hasattr(object, '__credits__'):
745 contents = self.markup(str(object.__credits__), self.preformat)
746 result = result + self.bigsection(
747 'Credits', '#ffffff', '#7799ee', contents)
748
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000749 return result
750
Tim Peters8dd7ade2001-10-18 19:56:17 +0000751 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
752 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000753 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000754 realname = object.__name__
755 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000756 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000757
Tim Petersb47879b2001-09-24 04:47:19 +0000758 contents = []
759 push = contents.append
760
Tim Petersfa26f7c2001-09-24 08:05:11 +0000761 # Cute little class to pump out a horizontal rule between sections.
762 class HorizontalRule:
763 def __init__(self):
764 self.needone = 0
765 def maybe(self):
766 if self.needone:
767 push('<hr>\n')
768 self.needone = 1
769 hr = HorizontalRule()
770
Tim Petersc86f6ca2001-09-26 21:31:51 +0000771 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000772 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000773 if len(mro) > 2:
774 hr.maybe()
775 push('<dl><dt>Method resolution order:</dt>\n')
776 for base in mro:
777 push('<dd>%s</dd>\n' % self.classlink(base,
778 object.__module__))
779 push('</dl>\n')
780
Tim Petersb47879b2001-09-24 04:47:19 +0000781 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000782 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000783 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000784 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000785 push(msg)
786 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100787 try:
788 value = getattr(object, name)
789 except Exception:
790 # Some descriptors may meet a failure in their __get__.
791 # (bug #1785)
792 push(self._docdescriptor(name, value, mod))
793 else:
794 push(self.document(value, name, mod,
795 funcs, classes, mdict, object))
Tim Petersb47879b2001-09-24 04:47:19 +0000796 push('\n')
797 return attrs
798
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000799 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000800 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000801 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000802 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000803 push(msg)
804 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000805 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000806 return attrs
807
Tim Petersfa26f7c2001-09-24 08:05:11 +0000808 def spilldata(msg, attrs, predicate):
809 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000810 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000811 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000812 push(msg)
813 for name, kind, homecls, value in ok:
814 base = self.docother(getattr(object, name), name, mod)
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200815 if callable(value) or inspect.isdatadescriptor(value):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000816 doc = getattr(value, "__doc__", None)
817 else:
818 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000819 if doc is None:
820 push('<dl><dt>%s</dl>\n' % base)
821 else:
822 doc = self.markup(getdoc(value), self.preformat,
823 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000824 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000825 push('<dl><dt>%s%s</dl>\n' % (base, doc))
826 push('\n')
827 return attrs
828
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000829 attrs = [(name, kind, cls, value)
830 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -0700831 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000832
Tim Petersb47879b2001-09-24 04:47:19 +0000833 mdict = {}
834 for key, kind, homecls, value in attrs:
835 mdict[key] = anchor = '#' + name + '-' + key
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100836 try:
837 value = getattr(object, name)
838 except Exception:
839 # Some descriptors may meet a failure in their __get__.
840 # (bug #1785)
841 pass
Tim Petersb47879b2001-09-24 04:47:19 +0000842 try:
843 # The value may not be hashable (e.g., a data attr with
844 # a dict or list value).
845 mdict[value] = anchor
846 except TypeError:
847 pass
848
Tim Petersfa26f7c2001-09-24 08:05:11 +0000849 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000850 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000851 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000852 else:
853 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000854 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
855
Georg Brandl1a3284e2007-12-02 09:40:06 +0000856 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000857 attrs = inherited
858 continue
859 elif thisclass is object:
860 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000861 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000862 tag = 'inherited from %s' % self.classlink(thisclass,
863 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000864 tag += ':<br>\n'
865
866 # Sort attrs by name.
Raymond Hettingerd4cb56d2008-01-30 02:55:10 +0000867 attrs.sort(key=lambda t: t[0])
Tim Petersb47879b2001-09-24 04:47:19 +0000868
869 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000870 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000871 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000872 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000873 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000874 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000875 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000876 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
877 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000878 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000879 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000880 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000881 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000882
883 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000884
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000885 if name == realname:
886 title = '<a name="%s">class <strong>%s</strong></a>' % (
887 name, realname)
888 else:
889 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
890 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000891 if bases:
892 parents = []
893 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000894 parents.append(self.classlink(base, object.__module__))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000895 title = title + '(%s)' % ', '.join(parents)
Tim Peters2306d242001-09-25 03:18:32 +0000896 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000897 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000898
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000899 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000900
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000901 def formatvalue(self, object):
902 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000903 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000904
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000905 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000906 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000907 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000908 realname = object.__name__
909 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000910 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000911 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000912 skipdocs = 0
Larry Hastings24a882b2014-02-20 23:34:46 -0800913 if _is_bound_method(object):
Christian Heimesff737952007-11-27 10:40:20 +0000914 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000915 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000916 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000917 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000918 else:
Christian Heimesff737952007-11-27 10:40:20 +0000919 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000920 note = ' method of %s instance' % self.classlink(
Christian Heimesff737952007-11-27 10:40:20 +0000921 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000922 else:
923 note = ' unbound %s method' % self.classlink(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000924
925 if name == realname:
926 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
927 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000928 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000929 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000930 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000931 cl.__name__ + '-' + realname, realname)
932 skipdocs = 1
933 else:
934 reallink = realname
935 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
936 anchor, name, reallink)
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800937 argspec = None
Larry Hastings24a882b2014-02-20 23:34:46 -0800938 if inspect.isroutine(object):
Larry Hastings5c661892014-01-24 06:17:25 -0800939 try:
940 signature = inspect.signature(object)
941 except (ValueError, TypeError):
942 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800943 if signature:
944 argspec = str(signature)
945 if realname == '<lambda>':
946 title = '<strong>%s</strong> <em>lambda</em> ' % name
947 # XXX lambda's won't usually have func_annotations['return']
948 # since the syntax doesn't support but it is possible.
949 # So removing parentheses isn't truly safe.
950 argspec = argspec[1:-1] # remove parentheses
951 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +0000952 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000953
Tim Peters2306d242001-09-25 03:18:32 +0000954 decl = title + argspec + (note and self.grey(
955 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000956
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000957 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000958 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000959 else:
960 doc = self.markup(
961 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000962 doc = doc and '<dd><tt>%s</tt></dd>' % doc
963 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000964
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000965 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000966 results = []
967 push = results.append
968
969 if name:
970 push('<dl><dt><strong>%s</strong></dt>\n' % name)
971 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000972 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000973 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000974 push('</dl>\n')
975
976 return ''.join(results)
977
978 def docproperty(self, object, name=None, mod=None, cl=None):
979 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000980 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000981
Tim Peters8dd7ade2001-10-18 19:56:17 +0000982 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000983 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000984 lhs = name and '<strong>%s</strong> = ' % name or ''
985 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000986
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000987 def docdata(self, object, name=None, mod=None, cl=None):
988 """Produce html documentation for a data descriptor."""
989 return self._docdescriptor(name, object, mod)
990
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000991 def index(self, dir, shadowed=None):
992 """Generate an HTML index for a directory of modules."""
993 modpkgs = []
994 if shadowed is None: shadowed = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000995 for importer, name, ispkg in pkgutil.iter_modules([dir]):
Victor Stinner4d652242011-04-12 23:41:50 +0200996 if any((0xD800 <= ord(ch) <= 0xDFFF) for ch in name):
997 # ignore a module if its name contains a surrogate character
998 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000999 modpkgs.append((name, '', ispkg, name in shadowed))
1000 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001001
1002 modpkgs.sort()
1003 contents = self.multicolumn(modpkgs, self.modpkglink)
1004 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
1005
1006# -------------------------------------------- text documentation generator
1007
1008class TextRepr(Repr):
1009 """Class for safely making a text representation of a Python object."""
1010 def __init__(self):
1011 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001012 self.maxlist = self.maxtuple = 20
1013 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001014 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001015
1016 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001017 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001018 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001019 if hasattr(self, methodname):
1020 return getattr(self, methodname)(x, level)
1021 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001022
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001023 def repr_string(self, x, level):
1024 test = cram(x, self.maxstring)
1025 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001026 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001027 # Backslashes are only literal in the string and are never
1028 # needed to make any special characters, so show a raw string.
1029 return 'r' + testrepr[0] + test + testrepr[0]
1030 return testrepr
1031
Skip Montanarodf708782002-03-07 22:58:02 +00001032 repr_str = repr_string
1033
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001034 def repr_instance(self, x, level):
1035 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001036 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001037 except:
1038 return '<%s instance>' % x.__class__.__name__
1039
1040class TextDoc(Doc):
1041 """Formatter class for text documentation."""
1042
1043 # ------------------------------------------- text formatting utilities
1044
1045 _repr_instance = TextRepr()
1046 repr = _repr_instance.repr
1047
1048 def bold(self, text):
1049 """Format a string in bold by overstriking."""
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001050 return ''.join(ch + '\b' + ch for ch in text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001051
1052 def indent(self, text, prefix=' '):
1053 """Indent text by prepending a given prefix to each line."""
1054 if not text: return ''
Collin Winter72e110c2007-07-17 00:27:30 +00001055 lines = [prefix + line for line in text.split('\n')]
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001056 if lines: lines[-1] = lines[-1].rstrip()
1057 return '\n'.join(lines)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001058
1059 def section(self, title, contents):
1060 """Format a section with a given heading."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001061 clean_contents = self.indent(contents).rstrip()
1062 return self.bold(title) + '\n' + clean_contents + '\n\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001063
1064 # ---------------------------------------------- type-specific routines
1065
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001066 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001067 """Render in text a class tree as returned by inspect.getclasstree()."""
1068 result = ''
1069 for entry in tree:
1070 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001071 c, bases = entry
1072 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001073 if bases and bases != (parent,):
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001074 parents = (classname(c, modname) for c in bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001075 result = result + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001076 result = result + '\n'
1077 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001078 result = result + self.formattree(
1079 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001080 return result
1081
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001082 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001083 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001084 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001085 synop, desc = splitdoc(getdoc(object))
1086 result = self.section('NAME', name + (synop and ' - ' + synop))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001087 all = getattr(object, '__all__', None)
Skip Montanaro4997a692003-09-10 16:47:51 +00001088 docloc = self.getdocloc(object)
1089 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001090 result = result + self.section('MODULE REFERENCE', docloc + """
1091
Éric Araujo647ef8c2011-09-11 00:43:20 +02001092The following documentation is automatically generated from the Python
1093source files. It may be incomplete, incorrect or include features that
1094are considered implementation detail and may vary between Python
1095implementations. When in doubt, consult the module reference at the
1096location listed above.
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001097""")
Skip Montanaro4997a692003-09-10 16:47:51 +00001098
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001099 if desc:
1100 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001101
1102 classes = []
1103 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001104 # if __all__ exists, believe it. Otherwise use old heuristic.
1105 if (all is not None
1106 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001107 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001108 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001109 funcs = []
1110 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001111 # if __all__ exists, believe it. Otherwise use old heuristic.
1112 if (all is not None or
1113 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001114 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001115 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001116 data = []
1117 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001118 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001119 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001120
Christian Heimes1af737c2008-01-23 08:24:23 +00001121 modpkgs = []
1122 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001123 if hasattr(object, '__path__'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001124 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Christian Heimes1af737c2008-01-23 08:24:23 +00001125 modpkgs_names.add(modname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001126 if ispkg:
1127 modpkgs.append(modname + ' (package)')
1128 else:
1129 modpkgs.append(modname)
1130
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001131 modpkgs.sort()
1132 result = result + self.section(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001133 'PACKAGE CONTENTS', '\n'.join(modpkgs))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001134
Christian Heimes1af737c2008-01-23 08:24:23 +00001135 # Detect submodules as sometimes created by C extensions
1136 submodules = []
1137 for key, value in inspect.getmembers(object, inspect.ismodule):
1138 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1139 submodules.append(key)
1140 if submodules:
1141 submodules.sort()
1142 result = result + self.section(
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001143 'SUBMODULES', '\n'.join(submodules))
Christian Heimes1af737c2008-01-23 08:24:23 +00001144
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001145 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001146 classlist = [value for key, value in classes]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001147 contents = [self.formattree(
1148 inspect.getclasstree(classlist, 1), name)]
1149 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001150 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001151 result = result + self.section('CLASSES', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001152
1153 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001154 contents = []
1155 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001156 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001157 result = result + self.section('FUNCTIONS', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001158
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001159 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001160 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001161 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001162 contents.append(self.docother(value, key, name, maxlen=70))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001163 result = result + self.section('DATA', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001164
1165 if hasattr(object, '__version__'):
1166 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001167 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001168 version = version[11:-1].strip()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001169 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001170 if hasattr(object, '__date__'):
1171 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001172 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001173 result = result + self.section('AUTHOR', str(object.__author__))
1174 if hasattr(object, '__credits__'):
1175 result = result + self.section('CREDITS', str(object.__credits__))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001176 try:
1177 file = inspect.getabsfile(object)
1178 except TypeError:
1179 file = '(built-in)'
1180 result = result + self.section('FILE', file)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001181 return result
1182
Georg Brandl9bd45f992010-12-03 09:58:38 +00001183 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001184 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001185 realname = object.__name__
1186 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001187 bases = object.__bases__
1188
Tim Petersc86f6ca2001-09-26 21:31:51 +00001189 def makename(c, m=object.__module__):
1190 return classname(c, m)
1191
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001192 if name == realname:
1193 title = 'class ' + self.bold(realname)
1194 else:
1195 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001196 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001197 parents = map(makename, bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001198 title = title + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001199
1200 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001201 contents = doc and [doc + '\n'] or []
1202 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001203
Tim Petersc86f6ca2001-09-26 21:31:51 +00001204 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001205 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001206 if len(mro) > 2:
1207 push("Method resolution order:")
1208 for base in mro:
1209 push(' ' + makename(base))
1210 push('')
1211
Tim Petersf4aad8e2001-09-24 22:40:47 +00001212 # Cute little class to pump out a horizontal rule between sections.
1213 class HorizontalRule:
1214 def __init__(self):
1215 self.needone = 0
1216 def maybe(self):
1217 if self.needone:
1218 push('-' * 70)
1219 self.needone = 1
1220 hr = HorizontalRule()
1221
Tim Peters28355492001-09-23 21:29:55 +00001222 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001223 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001224 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001225 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001226 push(msg)
1227 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001228 try:
1229 value = getattr(object, name)
1230 except Exception:
1231 # Some descriptors may meet a failure in their __get__.
1232 # (bug #1785)
1233 push(self._docdescriptor(name, value, mod))
1234 else:
1235 push(self.document(value,
1236 name, mod, object))
Tim Peters28355492001-09-23 21:29:55 +00001237 return attrs
1238
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001239 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001240 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001241 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001242 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001243 push(msg)
1244 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001245 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001246 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001247
Tim Petersfa26f7c2001-09-24 08:05:11 +00001248 def spilldata(msg, attrs, predicate):
1249 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001250 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001251 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001252 push(msg)
1253 for name, kind, homecls, value in ok:
Florent Xicluna5d1155c2011-10-28 14:45:05 +02001254 if callable(value) or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001255 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001256 else:
1257 doc = None
Serhiy Storchaka056eb022014-02-19 23:05:12 +02001258 try:
1259 obj = getattr(object, name)
1260 except AttributeError:
1261 obj = homecls.__dict__[name]
1262 push(self.docother(obj, name, mod, maxlen=70, doc=doc) +
1263 '\n')
Tim Peters28355492001-09-23 21:29:55 +00001264 return attrs
1265
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001266 attrs = [(name, kind, cls, value)
1267 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -07001268 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001269
Tim Petersfa26f7c2001-09-24 08:05:11 +00001270 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001271 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001272 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001273 else:
1274 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001275 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1276
Georg Brandl1a3284e2007-12-02 09:40:06 +00001277 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001278 attrs = inherited
1279 continue
1280 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001281 tag = "defined here"
1282 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001283 tag = "inherited from %s" % classname(thisclass,
1284 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001285 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001286 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001287
1288 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001289 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001290 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001291 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001292 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001293 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001294 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001295 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1296 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001297 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1298 lambda t: t[1] == 'data')
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001299
Tim Peters28355492001-09-23 21:29:55 +00001300 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001301 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001302
1303 contents = '\n'.join(contents)
1304 if not contents:
1305 return title + '\n'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001306 return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001307
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001308 def formatvalue(self, object):
1309 """Format an argument default value as text."""
1310 return '=' + self.repr(object)
1311
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001312 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001313 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001314 realname = object.__name__
1315 name = name or realname
1316 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001317 skipdocs = 0
Larry Hastings24a882b2014-02-20 23:34:46 -08001318 if _is_bound_method(object):
Christian Heimesff737952007-11-27 10:40:20 +00001319 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001320 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001321 if imclass is not cl:
1322 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001323 else:
Christian Heimesff737952007-11-27 10:40:20 +00001324 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001325 note = ' method of %s instance' % classname(
Christian Heimesff737952007-11-27 10:40:20 +00001326 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001327 else:
1328 note = ' unbound %s method' % classname(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001329
1330 if name == realname:
1331 title = self.bold(realname)
1332 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001333 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001334 cl.__dict__[realname] is object):
1335 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001336 title = self.bold(name) + ' = ' + realname
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001337 argspec = None
Larry Hastings5c661892014-01-24 06:17:25 -08001338
1339 if inspect.isroutine(object):
1340 try:
1341 signature = inspect.signature(object)
1342 except (ValueError, TypeError):
1343 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001344 if signature:
1345 argspec = str(signature)
1346 if realname == '<lambda>':
1347 title = self.bold(name) + ' lambda '
1348 # XXX lambda's won't usually have func_annotations['return']
1349 # since the syntax doesn't support but it is possible.
1350 # So removing parentheses isn't truly safe.
1351 argspec = argspec[1:-1] # remove parentheses
1352 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +00001353 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001354 decl = title + argspec + note
1355
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001356 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001357 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001358 else:
1359 doc = getdoc(object) or ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001360 return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001361
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001362 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001363 results = []
1364 push = results.append
1365
1366 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001367 push(self.bold(name))
1368 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001369 doc = getdoc(value) or ''
1370 if doc:
1371 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001372 push('\n')
1373 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001374
1375 def docproperty(self, object, name=None, mod=None, cl=None):
1376 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001377 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001378
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001379 def docdata(self, object, name=None, mod=None, cl=None):
1380 """Produce text documentation for a data descriptor."""
1381 return self._docdescriptor(name, object, mod)
1382
Georg Brandl8b813db2005-10-01 16:32:31 +00001383 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001384 """Produce text documentation for a data object."""
1385 repr = self.repr(object)
1386 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001387 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001388 chop = maxlen - len(line)
1389 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001390 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001391 if doc is not None:
1392 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001393 return line
1394
Georg Brandld80d5f42010-12-03 07:47:22 +00001395class _PlainTextDoc(TextDoc):
1396 """Subclass of TextDoc which overrides string styling"""
1397 def bold(self, text):
1398 return text
1399
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001400# --------------------------------------------------------- user interfaces
1401
1402def pager(text):
1403 """The first time this is called, determine what kind of pager to use."""
1404 global pager
Victor Stinner0cc45ba2014-05-13 02:05:35 +02001405 # Escape non-encodable characters to avoid encoding errors later
1406 encoding = sys.getfilesystemencoding()
1407 text = text.encode(encoding, 'backslashreplace').decode(encoding)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001408 pager = getpager()
1409 pager(text)
1410
1411def getpager():
1412 """Decide what method to use for paging through text."""
Guido van Rossuma01a8b62007-05-27 09:20:14 +00001413 if not hasattr(sys.stdout, "isatty"):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001414 return plainpager
1415 if not sys.stdin.isatty() or not sys.stdout.isatty():
1416 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001417 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001418 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001419 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001420 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001421 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001422 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001423 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001424 if os.environ.get('TERM') in ('dumb', 'emacs'):
1425 return plainpager
Jesus Cea4791a242012-10-05 03:15:39 +02001426 if sys.platform == 'win32':
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001427 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001428 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001429 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001430
1431 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001432 (fd, filename) = tempfile.mkstemp()
1433 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001434 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001435 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001436 return lambda text: pipepager(text, 'more')
1437 else:
1438 return ttypager
1439 finally:
1440 os.unlink(filename)
1441
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001442def plain(text):
1443 """Remove boldface formatting from text."""
1444 return re.sub('.\b', '', text)
1445
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001446def pipepager(text, cmd):
1447 """Page through text by feeding it to another program."""
1448 pipe = os.popen(cmd, 'w')
1449 try:
1450 pipe.write(text)
1451 pipe.close()
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001452 except OSError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001453 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001454
1455def tempfilepager(text, cmd):
1456 """Page through text by invoking a program on a temporary file."""
1457 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001458 filename = tempfile.mktemp()
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +01001459 with open(filename, 'w') as file:
1460 file.write(text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001461 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001462 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001463 finally:
1464 os.unlink(filename)
1465
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001466def ttypager(text):
1467 """Page through text on a text terminal."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001468 lines = plain(text).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001469 try:
1470 import tty
1471 fd = sys.stdin.fileno()
1472 old = tty.tcgetattr(fd)
1473 tty.setcbreak(fd)
1474 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001475 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001476 tty = None
1477 getchar = lambda: sys.stdin.readline()[:-1][:1]
1478
1479 try:
1480 r = inc = os.environ.get('LINES', 25) - 1
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001481 sys.stdout.write('\n'.join(lines[:inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001482 while lines[r:]:
1483 sys.stdout.write('-- more --')
1484 sys.stdout.flush()
1485 c = getchar()
1486
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001487 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001488 sys.stdout.write('\r \r')
1489 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001490 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001491 sys.stdout.write('\r \r' + lines[r] + '\n')
1492 r = r + 1
1493 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001494 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001495 r = r - inc - inc
1496 if r < 0: r = 0
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001497 sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001498 r = r + inc
1499
1500 finally:
1501 if tty:
1502 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1503
1504def plainpager(text):
1505 """Simply print unformatted text. This is the ultimate fallback."""
1506 sys.stdout.write(plain(text))
1507
1508def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001509 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001510 if inspect.ismodule(thing):
1511 if thing.__name__ in sys.builtin_module_names:
1512 return 'built-in module ' + thing.__name__
1513 if hasattr(thing, '__path__'):
1514 return 'package ' + thing.__name__
1515 else:
1516 return 'module ' + thing.__name__
1517 if inspect.isbuiltin(thing):
1518 return 'built-in function ' + thing.__name__
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001519 if inspect.isgetsetdescriptor(thing):
1520 return 'getset descriptor %s.%s.%s' % (
1521 thing.__objclass__.__module__, thing.__objclass__.__name__,
1522 thing.__name__)
1523 if inspect.ismemberdescriptor(thing):
1524 return 'member descriptor %s.%s.%s' % (
1525 thing.__objclass__.__module__, thing.__objclass__.__name__,
1526 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001527 if inspect.isclass(thing):
1528 return 'class ' + thing.__name__
1529 if inspect.isfunction(thing):
1530 return 'function ' + thing.__name__
1531 if inspect.ismethod(thing):
1532 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001533 return type(thing).__name__
1534
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001535def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001536 """Locate an object by name or dotted path, importing as necessary."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001537 parts = [part for part in path.split('.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001538 module, n = None, 0
1539 while n < len(parts):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001540 nextmodule = safeimport('.'.join(parts[:n+1]), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001541 if nextmodule: module, n = nextmodule, n + 1
1542 else: break
1543 if module:
1544 object = module
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001545 else:
Éric Araujoe64e51b2011-07-29 17:03:55 +02001546 object = builtins
1547 for part in parts[n:]:
1548 try:
1549 object = getattr(object, part)
1550 except AttributeError:
1551 return None
1552 return object
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001553
1554# --------------------------------------- interactive interpreter interface
1555
1556text = TextDoc()
Georg Brandld80d5f42010-12-03 07:47:22 +00001557plaintext = _PlainTextDoc()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001558html = HTMLDoc()
1559
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001560def resolve(thing, forceload=0):
1561 """Given an object or a path to an object, get the object and its name."""
1562 if isinstance(thing, str):
1563 object = locate(thing, forceload)
1564 if not object:
Collin Winterce36ad82007-08-30 01:19:48 +00001565 raise ImportError('no Python documentation found for %r' % thing)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001566 return object, thing
1567 else:
R David Murrayc43125a2012-04-23 13:23:57 -04001568 name = getattr(thing, '__name__', None)
1569 return thing, name if isinstance(name, str) else None
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001570
Georg Brandld80d5f42010-12-03 07:47:22 +00001571def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
1572 renderer=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001573 """Render text documentation, given an object or a path to an object."""
Georg Brandld80d5f42010-12-03 07:47:22 +00001574 if renderer is None:
1575 renderer = text
Guido van Rossumd8faa362007-04-27 19:54:29 +00001576 object, name = resolve(thing, forceload)
1577 desc = describe(object)
1578 module = inspect.getmodule(object)
1579 if name and '.' in name:
1580 desc += ' in ' + name[:name.rfind('.')]
1581 elif module and module is not object:
1582 desc += ' in module ' + module.__name__
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001583
1584 if not (inspect.ismodule(object) or
Guido van Rossumd8faa362007-04-27 19:54:29 +00001585 inspect.isclass(object) or
1586 inspect.isroutine(object) or
1587 inspect.isgetsetdescriptor(object) or
1588 inspect.ismemberdescriptor(object) or
1589 isinstance(object, property)):
1590 # If the passed object is a piece of data or an instance,
1591 # document its available methods instead of its value.
1592 object = type(object)
1593 desc += ' object'
Georg Brandld80d5f42010-12-03 07:47:22 +00001594 return title % desc + '\n\n' + renderer.document(object, name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001595
Georg Brandld80d5f42010-12-03 07:47:22 +00001596def doc(thing, title='Python Library Documentation: %s', forceload=0,
1597 output=None):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001598 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001599 try:
Georg Brandld80d5f42010-12-03 07:47:22 +00001600 if output is None:
1601 pager(render_doc(thing, title, forceload))
1602 else:
1603 output.write(render_doc(thing, title, forceload, plaintext))
Guido van Rossumb940e112007-01-10 16:19:56 +00001604 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001605 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001606
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001607def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001608 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001609 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001610 object, name = resolve(thing, forceload)
1611 page = html.page(describe(object), html.document(object, name))
Georg Brandl388faac2009-04-10 08:31:48 +00001612 file = open(name + '.html', 'w', encoding='utf-8')
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001613 file.write(page)
1614 file.close()
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001615 print('wrote', name + '.html')
Guido van Rossumb940e112007-01-10 16:19:56 +00001616 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001617 print(value)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001618
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001619def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001620 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001621 if done is None: done = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001622 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1623 writedoc(modname)
1624 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001625
1626class Helper:
Georg Brandl6b38daa2008-06-01 21:05:17 +00001627
1628 # These dictionaries map a topic name to either an alias, or a tuple
1629 # (label, seealso-items). The "label" is the label of the corresponding
1630 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl5617db82009-04-27 16:28:57 +00001631 # in pydoc_data/topics.py.
Georg Brandl6b38daa2008-06-01 21:05:17 +00001632 #
1633 # CAUTION: if you change one of these dictionaries, be sure to adapt the
1634 # list of needed labels in Doc/tools/sphinxext/pyspecific.py and
Georg Brandl5617db82009-04-27 16:28:57 +00001635 # regenerate the pydoc_data/topics.py file by running
Georg Brandl6b38daa2008-06-01 21:05:17 +00001636 # make pydoc-topics
1637 # in Doc/ and copying the output file into the Lib/ directory.
1638
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001639 keywords = {
Ezio Melottib185a042011-04-28 07:42:55 +03001640 'False': '',
1641 'None': '',
1642 'True': '',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001643 'and': 'BOOLEAN',
Guido van Rossumd8faa362007-04-27 19:54:29 +00001644 'as': 'with',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001645 'assert': ('assert', ''),
1646 'break': ('break', 'while for'),
1647 'class': ('class', 'CLASSES SPECIALMETHODS'),
1648 'continue': ('continue', 'while for'),
1649 'def': ('function', ''),
1650 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001651 'elif': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001652 'else': ('else', 'while for'),
Georg Brandl0d855392008-08-30 19:53:05 +00001653 'except': 'try',
1654 'finally': 'try',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001655 'for': ('for', 'break continue while'),
Georg Brandl0d855392008-08-30 19:53:05 +00001656 'from': 'import',
Georg Brandl74abf6f2010-11-20 19:54:36 +00001657 'global': ('global', 'nonlocal NAMESPACES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001658 'if': ('if', 'TRUTHVALUE'),
1659 'import': ('import', 'MODULES'),
Georg Brandl395ed242009-09-04 08:07:32 +00001660 'in': ('in', 'SEQUENCEMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001661 'is': 'COMPARISON',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001662 'lambda': ('lambda', 'FUNCTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001663 'nonlocal': ('nonlocal', 'global NAMESPACES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001664 'not': 'BOOLEAN',
1665 'or': 'BOOLEAN',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001666 'pass': ('pass', ''),
1667 'raise': ('raise', 'EXCEPTIONS'),
1668 'return': ('return', 'FUNCTIONS'),
1669 'try': ('try', 'EXCEPTIONS'),
1670 'while': ('while', 'break continue if TRUTHVALUE'),
1671 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1672 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001673 }
Georg Brandldb7b6b92009-01-01 15:53:14 +00001674 # Either add symbols to this dictionary or to the symbols dictionary
1675 # directly: Whichever is easier. They are merged later.
1676 _symbols_inverse = {
1677 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'),
1678 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1679 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1680 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1681 'UNARY' : ('-', '~'),
1682 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1683 '^=', '<<=', '>>=', '**=', '//='),
1684 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1685 'COMPLEX' : ('j', 'J')
1686 }
1687 symbols = {
1688 '%': 'OPERATORS FORMATTING',
1689 '**': 'POWER',
1690 ',': 'TUPLES LISTS FUNCTIONS',
1691 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1692 '...': 'ELLIPSIS',
1693 ':': 'SLICINGS DICTIONARYLITERALS',
1694 '@': 'def class',
1695 '\\': 'STRINGS',
1696 '_': 'PRIVATENAMES',
1697 '__': 'PRIVATENAMES SPECIALMETHODS',
1698 '`': 'BACKQUOTES',
1699 '(': 'TUPLES FUNCTIONS CALLS',
1700 ')': 'TUPLES FUNCTIONS CALLS',
1701 '[': 'LISTS SUBSCRIPTS SLICINGS',
1702 ']': 'LISTS SUBSCRIPTS SLICINGS'
1703 }
1704 for topic, symbols_ in _symbols_inverse.items():
1705 for symbol in symbols_:
1706 topics = symbols.get(symbol, topic)
1707 if topic not in topics:
1708 topics = topics + ' ' + topic
1709 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001710
1711 topics = {
Georg Brandl6b38daa2008-06-01 21:05:17 +00001712 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1713 'FUNCTIONS CLASSES MODULES FILES inspect'),
1714 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS '
1715 'FORMATTING TYPES'),
1716 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1717 'FORMATTING': ('formatstrings', 'OPERATORS'),
1718 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1719 'FORMATTING TYPES'),
1720 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1721 'INTEGER': ('integers', 'int range'),
1722 'FLOAT': ('floating', 'float math'),
1723 'COMPLEX': ('imaginary', 'complex cmath'),
1724 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING range LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001725 'MAPPINGS': 'DICTIONARIES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001726 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1727 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1728 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1729 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001730 'FRAMEOBJECTS': 'TYPES',
1731 'TRACEBACKS': 'TYPES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001732 'NONE': ('bltin-null-object', ''),
1733 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001734 'SPECIALATTRIBUTES': ('specialattrs', ''),
1735 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1736 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001737 'PACKAGES': 'import',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001738 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1739 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1740 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1741 'LISTS DICTIONARIES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001742 'OPERATORS': 'EXPRESSIONS',
1743 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001744 'OBJECTS': ('objects', 'TYPES'),
1745 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
Georg Brandl395ed242009-09-04 08:07:32 +00001746 'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS '
1747 'NUMBERMETHODS CLASSES'),
Mark Dickinsona56c4672009-01-27 18:17:45 +00001748 'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001749 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1750 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001751 'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS '
Georg Brandl6b38daa2008-06-01 21:05:17 +00001752 'SPECIALMETHODS'),
1753 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1754 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1755 'SPECIALMETHODS'),
1756 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001757 'NAMESPACES': ('naming', 'global nonlocal ASSIGNMENT DELETION DYNAMICFEATURES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001758 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001759 'SCOPING': 'NAMESPACES',
1760 'FRAMES': 'NAMESPACES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001761 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1762 'CONVERSIONS': ('conversions', ''),
1763 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1764 'SPECIALIDENTIFIERS': ('id-classes', ''),
1765 'PRIVATENAMES': ('atom-identifiers', ''),
1766 'LITERALS': ('atom-literals', 'STRINGS NUMBERS TUPLELITERALS '
1767 'LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001768 'TUPLES': 'SEQUENCES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001769 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1770 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1771 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1772 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1773 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1774 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001775 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'),
1776 'SLICINGS': ('slicings', 'SEQUENCEMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001777 'CALLS': ('calls', 'EXPRESSIONS'),
1778 'POWER': ('power', 'EXPRESSIONS'),
1779 'UNARY': ('unary', 'EXPRESSIONS'),
1780 'BINARY': ('binary', 'EXPRESSIONS'),
1781 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1782 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1783 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1784 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001785 'ASSERTION': 'assert',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001786 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1787 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001788 'DELETION': 'del',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001789 'RETURNING': 'return',
1790 'IMPORTING': 'import',
1791 'CONDITIONAL': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001792 'LOOPING': ('compound', 'for while break continue'),
1793 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1794 'DEBUGGING': ('debugger', 'pdb'),
1795 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001796 }
1797
Georg Brandl78aa3962010-07-31 21:51:48 +00001798 def __init__(self, input=None, output=None):
1799 self._input = input
1800 self._output = output
1801
Georg Brandl76ae3972010-08-01 06:32:55 +00001802 input = property(lambda self: self._input or sys.stdin)
1803 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001804
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001805 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001806 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001807 self()
1808 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001809 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001810
Alexander Belopolsky2e733c92010-07-04 17:00:20 +00001811 _GoInteractive = object()
1812 def __call__(self, request=_GoInteractive):
1813 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001814 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001815 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001816 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001817 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001818 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001819You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001820If you want to ask for help on a particular object directly from the
1821interpreter, you can type "help(object)". Executing "help('string')"
1822has the same effect as typing a particular string at the help> prompt.
1823''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001824
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001825 def interact(self):
1826 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001827 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001828 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001829 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001830 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001831 except (KeyboardInterrupt, EOFError):
1832 break
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001833 request = replace(request, '"', '', "'", '').strip()
1834 if request.lower() in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001835 self.help(request)
1836
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001837 def getline(self, prompt):
Guido van Rossum7c086c02008-01-02 03:52:38 +00001838 """Read one line, using input() when appropriate."""
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001839 if self.input is sys.stdin:
Guido van Rossum7c086c02008-01-02 03:52:38 +00001840 return input(prompt)
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001841 else:
1842 self.output.write(prompt)
1843 self.output.flush()
1844 return self.input.readline()
1845
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001846 def help(self, request):
1847 if type(request) is type(''):
R. David Murray1f1b9d32009-05-27 20:56:59 +00001848 request = request.strip()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001849 if request == 'help': self.intro()
1850 elif request == 'keywords': self.listkeywords()
Georg Brandldb7b6b92009-01-01 15:53:14 +00001851 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001852 elif request == 'topics': self.listtopics()
1853 elif request == 'modules': self.listmodules()
1854 elif request[:8] == 'modules ':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001855 self.listmodules(request.split()[1])
Georg Brandldb7b6b92009-01-01 15:53:14 +00001856 elif request in self.symbols: self.showsymbol(request)
Ezio Melottib185a042011-04-28 07:42:55 +03001857 elif request in ['True', 'False', 'None']:
1858 # special case these keywords since they are objects too
1859 doc(eval(request), 'Help on %s:')
Raymond Hettinger54f02222002-06-01 14:18:47 +00001860 elif request in self.keywords: self.showtopic(request)
1861 elif request in self.topics: self.showtopic(request)
Georg Brandld80d5f42010-12-03 07:47:22 +00001862 elif request: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001863 elif isinstance(request, Helper): self()
Georg Brandld80d5f42010-12-03 07:47:22 +00001864 else: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001865 self.output.write('\n')
1866
1867 def intro(self):
1868 self.output.write('''
R David Murray3d050dd2014-04-19 12:59:30 -04001869Welcome to Python %s's help utility!
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001870
1871If this is your first time using Python, you should definitely check out
R David Murrayde0f6292012-03-31 12:06:35 -04001872the tutorial on the Internet at http://docs.python.org/%s/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001873
1874Enter the name of any module, keyword, or topic to get help on writing
1875Python programs and using Python modules. To quit this help utility and
1876return to the interpreter, just type "quit".
1877
Terry Jan Reedy34200572013-02-11 02:23:13 -05001878To get a list of available modules, keywords, symbols, or topics, type
1879"modules", "keywords", "symbols", or "topics". Each module also comes
1880with a one-line summary of what it does; to list the modules whose name
1881or summary contain a given string such as "spam", type "modules spam".
R David Murrayde0f6292012-03-31 12:06:35 -04001882''' % tuple([sys.version[:3]]*2))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001883
1884 def list(self, items, columns=4, width=80):
Guido van Rossum486364b2007-06-30 05:01:58 +00001885 items = list(sorted(items))
1886 colw = width // columns
1887 rows = (len(items) + columns - 1) // columns
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001888 for row in range(rows):
1889 for col in range(columns):
1890 i = col * rows + row
1891 if i < len(items):
1892 self.output.write(items[i])
1893 if col < columns - 1:
Guido van Rossum486364b2007-06-30 05:01:58 +00001894 self.output.write(' ' + ' ' * (colw - 1 - len(items[i])))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001895 self.output.write('\n')
1896
1897 def listkeywords(self):
1898 self.output.write('''
1899Here is a list of the Python keywords. Enter any keyword to get more help.
1900
1901''')
1902 self.list(self.keywords.keys())
1903
Georg Brandldb7b6b92009-01-01 15:53:14 +00001904 def listsymbols(self):
1905 self.output.write('''
1906Here is a list of the punctuation symbols which Python assigns special meaning
1907to. Enter any symbol to get more help.
1908
1909''')
1910 self.list(self.symbols.keys())
1911
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001912 def listtopics(self):
1913 self.output.write('''
1914Here is a list of available topics. Enter any topic name to get more help.
1915
1916''')
1917 self.list(self.topics.keys())
1918
Georg Brandldb7b6b92009-01-01 15:53:14 +00001919 def showtopic(self, topic, more_xrefs=''):
Georg Brandl6b38daa2008-06-01 21:05:17 +00001920 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001921 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04001922 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001923 self.output.write('''
Georg Brandl6b38daa2008-06-01 21:05:17 +00001924Sorry, topic and keyword documentation is not available because the
Georg Brandl5617db82009-04-27 16:28:57 +00001925module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001926''')
1927 return
1928 target = self.topics.get(topic, self.keywords.get(topic))
1929 if not target:
1930 self.output.write('no documentation found for %s\n' % repr(topic))
1931 return
1932 if type(target) is type(''):
Georg Brandldb7b6b92009-01-01 15:53:14 +00001933 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001934
Georg Brandl6b38daa2008-06-01 21:05:17 +00001935 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001936 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001937 doc = pydoc_data.topics.topics[label]
Georg Brandl6b38daa2008-06-01 21:05:17 +00001938 except KeyError:
1939 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001940 return
Georg Brandl6b38daa2008-06-01 21:05:17 +00001941 pager(doc.strip() + '\n')
Georg Brandldb7b6b92009-01-01 15:53:14 +00001942 if more_xrefs:
1943 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001944 if xrefs:
Brett Cannon1448ecf2013-10-04 11:38:59 -04001945 import textwrap
1946 text = 'Related help topics: ' + ', '.join(xrefs.split()) + '\n'
1947 wrapped_text = textwrap.wrap(text, 72)
1948 self.output.write('\n%s\n' % ''.join(wrapped_text))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001949
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001950 def _gettopic(self, topic, more_xrefs=''):
1951 """Return unbuffered tuple of (topic, xrefs).
1952
Georg Brandld2f38572011-01-30 08:37:19 +00001953 If an error occurs here, the exception is caught and displayed by
1954 the url handler.
1955
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001956 This function duplicates the showtopic method but returns its
1957 result directly so it can be formatted for display in an html page.
1958 """
1959 try:
1960 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04001961 except ImportError:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001962 return('''
1963Sorry, topic and keyword documentation is not available because the
1964module "pydoc_data.topics" could not be found.
1965''' , '')
1966 target = self.topics.get(topic, self.keywords.get(topic))
1967 if not target:
Georg Brandld2f38572011-01-30 08:37:19 +00001968 raise ValueError('could not find topic')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001969 if isinstance(target, str):
1970 return self._gettopic(target, more_xrefs)
1971 label, xrefs = target
Georg Brandld2f38572011-01-30 08:37:19 +00001972 doc = pydoc_data.topics.topics[label]
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001973 if more_xrefs:
1974 xrefs = (xrefs or '') + ' ' + more_xrefs
1975 return doc, xrefs
1976
Georg Brandldb7b6b92009-01-01 15:53:14 +00001977 def showsymbol(self, symbol):
1978 target = self.symbols[symbol]
1979 topic, _, xrefs = target.partition(' ')
1980 self.showtopic(topic, xrefs)
1981
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001982 def listmodules(self, key=''):
1983 if key:
1984 self.output.write('''
Terry Jan Reedy34200572013-02-11 02:23:13 -05001985Here is a list of modules whose name or summary contains '{}'.
1986If there are any, enter a module name to get more help.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001987
Terry Jan Reedy34200572013-02-11 02:23:13 -05001988'''.format(key))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001989 apropos(key)
1990 else:
1991 self.output.write('''
1992Please wait a moment while I gather a list of all available modules...
1993
1994''')
1995 modules = {}
1996 def callback(path, modname, desc, modules=modules):
1997 if modname and modname[-9:] == '.__init__':
1998 modname = modname[:-9] + ' (package)'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001999 if modname.find('.') < 0:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002000 modules[modname] = 1
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002001 def onerror(modname):
2002 callback(None, modname, None)
2003 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002004 self.list(modules.keys())
2005 self.output.write('''
2006Enter any module name to get more help. Or, type "modules spam" to search
Terry Jan Reedy34200572013-02-11 02:23:13 -05002007for modules whose name or summary contain the string "spam".
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002008''')
2009
Georg Brandl78aa3962010-07-31 21:51:48 +00002010help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002011
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002012class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002013 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002014
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002015 def run(self, callback, key=None, completer=None, onerror=None):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002016 if key: key = key.lower()
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002017 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002018 seen = {}
2019
2020 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002021 if modname != '__main__':
2022 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00002023 if key is None:
2024 callback(None, modname, '')
2025 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002026 name = __import__(modname).__doc__ or ''
2027 desc = name.split('\n')[0]
2028 name = modname + ' - ' + desc
2029 if name.lower().find(key) >= 0:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002030 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002031
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002032 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002033 if self.quit:
2034 break
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002035
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002036 if key is None:
2037 callback(None, modname, '')
2038 else:
Georg Brandl126c8792009-04-05 15:05:48 +00002039 try:
Eric Snow3a62d142014-01-06 20:42:59 -07002040 spec = pkgutil._get_spec(importer, modname)
Georg Brandl126c8792009-04-05 15:05:48 +00002041 except SyntaxError:
2042 # raised by tests for bad coding cookies or BOM
2043 continue
Eric Snow3a62d142014-01-06 20:42:59 -07002044 loader = spec.loader
Georg Brandl126c8792009-04-05 15:05:48 +00002045 if hasattr(loader, 'get_source'):
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002046 try:
2047 source = loader.get_source(modname)
Nick Coghlan2824cb52012-07-15 22:12:14 +10002048 except Exception:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002049 if onerror:
2050 onerror(modname)
2051 continue
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002052 desc = source_synopsis(io.StringIO(source)) or ''
Georg Brandl126c8792009-04-05 15:05:48 +00002053 if hasattr(loader, 'get_filename'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002054 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002055 else:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002056 path = None
2057 else:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002058 try:
Brett Cannon2a17bde2014-05-30 14:55:29 -04002059 module = importlib._bootstrap._load(spec)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002060 except ImportError:
2061 if onerror:
2062 onerror(modname)
2063 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002064 desc = (module.__doc__ or '').splitlines()[0]
2065 path = getattr(module,'__file__',None)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002066 name = modname + ' - ' + desc
2067 if name.lower().find(key) >= 0:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002068 callback(path, modname, desc)
2069
2070 if completer:
2071 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002072
2073def apropos(key):
2074 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002075 def callback(path, modname, desc):
2076 if modname[-9:] == '.__init__':
2077 modname = modname[:-9] + ' (package)'
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002078 print(modname, desc and '- ' + desc)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002079 def onerror(modname):
2080 pass
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002081 with warnings.catch_warnings():
2082 warnings.filterwarnings('ignore') # ignore problems during import
2083 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002084
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002085# --------------------------------------- enhanced Web browser interface
2086
2087def _start_server(urlhandler, port):
2088 """Start an HTTP server thread on a specific port.
2089
2090 Start an HTML/text server thread, so HTML or text documents can be
2091 browsed dynamically and interactively with a Web browser. Example use:
2092
2093 >>> import time
2094 >>> import pydoc
2095
2096 Define a URL handler. To determine what the client is asking
2097 for, check the URL and content_type.
2098
2099 Then get or generate some text or HTML code and return it.
2100
2101 >>> def my_url_handler(url, content_type):
2102 ... text = 'the URL sent was: (%s, %s)' % (url, content_type)
2103 ... return text
2104
2105 Start server thread on port 0.
2106 If you use port 0, the server will pick a random port number.
2107 You can then use serverthread.port to get the port number.
2108
2109 >>> port = 0
2110 >>> serverthread = pydoc._start_server(my_url_handler, port)
2111
2112 Check that the server is really started. If it is, open browser
2113 and get first page. Use serverthread.url as the starting page.
2114
2115 >>> if serverthread.serving:
2116 ... import webbrowser
2117
2118 The next two lines are commented out so a browser doesn't open if
2119 doctest is run on this module.
2120
2121 #... webbrowser.open(serverthread.url)
2122 #True
2123
2124 Let the server do its thing. We just need to monitor its status.
2125 Use time.sleep so the loop doesn't hog the CPU.
2126
2127 >>> starttime = time.time()
2128 >>> timeout = 1 #seconds
2129
2130 This is a short timeout for testing purposes.
2131
2132 >>> while serverthread.serving:
2133 ... time.sleep(.01)
2134 ... if serverthread.serving and time.time() - starttime > timeout:
2135 ... serverthread.stop()
2136 ... break
2137
2138 Print any errors that may have occurred.
2139
2140 >>> print(serverthread.error)
2141 None
2142 """
2143 import http.server
2144 import email.message
2145 import select
2146 import threading
2147
2148 class DocHandler(http.server.BaseHTTPRequestHandler):
2149
2150 def do_GET(self):
2151 """Process a request from an HTML browser.
2152
2153 The URL received is in self.path.
2154 Get an HTML page from self.urlhandler and send it.
2155 """
2156 if self.path.endswith('.css'):
2157 content_type = 'text/css'
2158 else:
2159 content_type = 'text/html'
2160 self.send_response(200)
Georg Brandld2f38572011-01-30 08:37:19 +00002161 self.send_header('Content-Type', '%s; charset=UTF-8' % content_type)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002162 self.end_headers()
2163 self.wfile.write(self.urlhandler(
2164 self.path, content_type).encode('utf-8'))
2165
2166 def log_message(self, *args):
2167 # Don't log messages.
2168 pass
2169
2170 class DocServer(http.server.HTTPServer):
2171
2172 def __init__(self, port, callback):
2173 self.host = (sys.platform == 'mac') and '127.0.0.1' or 'localhost'
2174 self.address = ('', port)
2175 self.callback = callback
2176 self.base.__init__(self, self.address, self.handler)
2177 self.quit = False
2178
2179 def serve_until_quit(self):
2180 while not self.quit:
2181 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2182 if rd:
2183 self.handle_request()
Victor Stinnera3abd1d2011-01-03 16:12:39 +00002184 self.server_close()
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002185
2186 def server_activate(self):
2187 self.base.server_activate(self)
2188 if self.callback:
2189 self.callback(self)
2190
2191 class ServerThread(threading.Thread):
2192
2193 def __init__(self, urlhandler, port):
2194 self.urlhandler = urlhandler
2195 self.port = int(port)
2196 threading.Thread.__init__(self)
2197 self.serving = False
2198 self.error = None
2199
2200 def run(self):
2201 """Start the server."""
2202 try:
2203 DocServer.base = http.server.HTTPServer
2204 DocServer.handler = DocHandler
2205 DocHandler.MessageClass = email.message.Message
2206 DocHandler.urlhandler = staticmethod(self.urlhandler)
2207 docsvr = DocServer(self.port, self.ready)
2208 self.docserver = docsvr
2209 docsvr.serve_until_quit()
2210 except Exception as e:
2211 self.error = e
2212
2213 def ready(self, server):
2214 self.serving = True
2215 self.host = server.host
2216 self.port = server.server_port
2217 self.url = 'http://%s:%d/' % (self.host, self.port)
2218
2219 def stop(self):
2220 """Stop the server and this thread nicely"""
2221 self.docserver.quit = True
2222 self.serving = False
2223 self.url = None
2224
2225 thread = ServerThread(urlhandler, port)
2226 thread.start()
2227 # Wait until thread.serving is True to make sure we are
2228 # really up before returning.
2229 while not thread.error and not thread.serving:
2230 time.sleep(.01)
2231 return thread
2232
2233
2234def _url_handler(url, content_type="text/html"):
2235 """The pydoc url handler for use with the pydoc server.
2236
2237 If the content_type is 'text/css', the _pydoc.css style
2238 sheet is read and returned if it exits.
2239
2240 If the content_type is 'text/html', then the result of
2241 get_html_page(url) is returned.
2242 """
2243 class _HTMLDoc(HTMLDoc):
2244
2245 def page(self, title, contents):
2246 """Format an HTML page."""
2247 css_path = "pydoc_data/_pydoc.css"
2248 css_link = (
2249 '<link rel="stylesheet" type="text/css" href="%s">' %
2250 css_path)
2251 return '''\
2252<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Georg Brandld2f38572011-01-30 08:37:19 +00002253<html><head><title>Pydoc: %s</title>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002254<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Georg Brandld2f38572011-01-30 08:37:19 +00002255%s</head><body bgcolor="#f0f0f8">%s<div style="clear:both;padding-top:.5em;">%s</div>
2256</body></html>''' % (title, css_link, html_navbar(), contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002257
2258 def filelink(self, url, path):
2259 return '<a href="getfile?key=%s">%s</a>' % (url, path)
2260
2261
2262 html = _HTMLDoc()
2263
2264 def html_navbar():
Georg Brandld2f38572011-01-30 08:37:19 +00002265 version = html.escape("%s [%s, %s]" % (platform.python_version(),
2266 platform.python_build()[0],
2267 platform.python_compiler()))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002268 return """
2269 <div style='float:left'>
Georg Brandld2f38572011-01-30 08:37:19 +00002270 Python %s<br>%s
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002271 </div>
2272 <div style='float:right'>
2273 <div style='text-align:center'>
2274 <a href="index.html">Module Index</a>
2275 : <a href="topics.html">Topics</a>
2276 : <a href="keywords.html">Keywords</a>
2277 </div>
2278 <div>
Georg Brandld2f38572011-01-30 08:37:19 +00002279 <form action="get" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002280 <input type=text name=key size=15>
2281 <input type=submit value="Get">
Georg Brandld2f38572011-01-30 08:37:19 +00002282 </form>&nbsp;
2283 <form action="search" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002284 <input type=text name=key size=15>
2285 <input type=submit value="Search">
2286 </form>
2287 </div>
2288 </div>
Georg Brandld2f38572011-01-30 08:37:19 +00002289 """ % (version, html.escape(platform.platform(terse=True)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002290
2291 def html_index():
2292 """Module Index page."""
2293
2294 def bltinlink(name):
2295 return '<a href="%s.html">%s</a>' % (name, name)
2296
2297 heading = html.heading(
2298 '<big><big><strong>Index of Modules</strong></big></big>',
2299 '#ffffff', '#7799ee')
2300 names = [name for name in sys.builtin_module_names
2301 if name != '__main__']
2302 contents = html.multicolumn(names, bltinlink)
2303 contents = [heading, '<p>' + html.bigsection(
2304 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2305
2306 seen = {}
2307 for dir in sys.path:
2308 contents.append(html.index(dir, seen))
2309
2310 contents.append(
2311 '<p align=right><font color="#909090" face="helvetica,'
2312 'arial"><strong>pydoc</strong> by Ka-Ping Yee'
2313 '&lt;ping@lfw.org&gt;</font>')
Nick Coghlanecace282010-12-03 16:08:46 +00002314 return 'Index of Modules', ''.join(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002315
2316 def html_search(key):
2317 """Search results page."""
2318 # scan for modules
2319 search_result = []
2320
2321 def callback(path, modname, desc):
2322 if modname[-9:] == '.__init__':
2323 modname = modname[:-9] + ' (package)'
2324 search_result.append((modname, desc and '- ' + desc))
2325
2326 with warnings.catch_warnings():
2327 warnings.filterwarnings('ignore') # ignore problems during import
2328 ModuleScanner().run(callback, key)
2329
2330 # format page
2331 def bltinlink(name):
2332 return '<a href="%s.html">%s</a>' % (name, name)
2333
2334 results = []
2335 heading = html.heading(
2336 '<big><big><strong>Search Results</strong></big></big>',
2337 '#ffffff', '#7799ee')
2338 for name, desc in search_result:
2339 results.append(bltinlink(name) + desc)
2340 contents = heading + html.bigsection(
2341 'key = %s' % key, '#ffffff', '#ee77aa', '<br>'.join(results))
Nick Coghlanecace282010-12-03 16:08:46 +00002342 return 'Search Results', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002343
2344 def html_getfile(path):
2345 """Get and display a source file listing safely."""
Nick Coghlanecace282010-12-03 16:08:46 +00002346 path = path.replace('%20', ' ')
Victor Stinner91e08772011-07-05 14:30:41 +02002347 with tokenize.open(path) as fp:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002348 lines = html.escape(fp.read())
2349 body = '<pre>%s</pre>' % lines
2350 heading = html.heading(
2351 '<big><big><strong>File Listing</strong></big></big>',
2352 '#ffffff', '#7799ee')
2353 contents = heading + html.bigsection(
2354 'File: %s' % path, '#ffffff', '#ee77aa', body)
Nick Coghlanecace282010-12-03 16:08:46 +00002355 return 'getfile %s' % path, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002356
2357 def html_topics():
2358 """Index of topic texts available."""
2359
2360 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002361 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002362
2363 heading = html.heading(
2364 '<big><big><strong>INDEX</strong></big></big>',
2365 '#ffffff', '#7799ee')
2366 names = sorted(Helper.topics.keys())
2367
2368 contents = html.multicolumn(names, bltinlink)
2369 contents = heading + html.bigsection(
2370 'Topics', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002371 return 'Topics', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002372
2373 def html_keywords():
2374 """Index of keywords."""
2375 heading = html.heading(
2376 '<big><big><strong>INDEX</strong></big></big>',
2377 '#ffffff', '#7799ee')
2378 names = sorted(Helper.keywords.keys())
2379
2380 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002381 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002382
2383 contents = html.multicolumn(names, bltinlink)
2384 contents = heading + html.bigsection(
2385 'Keywords', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002386 return 'Keywords', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002387
2388 def html_topicpage(topic):
2389 """Topic or keyword help page."""
2390 buf = io.StringIO()
2391 htmlhelp = Helper(buf, buf)
2392 contents, xrefs = htmlhelp._gettopic(topic)
2393 if topic in htmlhelp.keywords:
2394 title = 'KEYWORD'
2395 else:
2396 title = 'TOPIC'
2397 heading = html.heading(
2398 '<big><big><strong>%s</strong></big></big>' % title,
2399 '#ffffff', '#7799ee')
Georg Brandld2f38572011-01-30 08:37:19 +00002400 contents = '<pre>%s</pre>' % html.markup(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002401 contents = html.bigsection(topic , '#ffffff','#ee77aa', contents)
Georg Brandld2f38572011-01-30 08:37:19 +00002402 if xrefs:
2403 xrefs = sorted(xrefs.split())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002404
Georg Brandld2f38572011-01-30 08:37:19 +00002405 def bltinlink(name):
2406 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002407
Georg Brandld2f38572011-01-30 08:37:19 +00002408 xrefs = html.multicolumn(xrefs, bltinlink)
2409 xrefs = html.section('Related help topics: ',
2410 '#ffffff', '#ee77aa', xrefs)
Nick Coghlanecace282010-12-03 16:08:46 +00002411 return ('%s %s' % (title, topic),
2412 ''.join((heading, contents, xrefs)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002413
Georg Brandld2f38572011-01-30 08:37:19 +00002414 def html_getobj(url):
2415 obj = locate(url, forceload=1)
2416 if obj is None and url != 'None':
2417 raise ValueError('could not find object')
2418 title = describe(obj)
2419 content = html.document(obj, url)
2420 return title, content
2421
2422 def html_error(url, exc):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002423 heading = html.heading(
2424 '<big><big><strong>Error</strong></big></big>',
Georg Brandld2f38572011-01-30 08:37:19 +00002425 '#ffffff', '#7799ee')
2426 contents = '<br>'.join(html.escape(line) for line in
2427 format_exception_only(type(exc), exc))
2428 contents = heading + html.bigsection(url, '#ffffff', '#bb0000',
2429 contents)
2430 return "Error - %s" % url, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002431
2432 def get_html_page(url):
2433 """Generate an HTML page for url."""
Georg Brandld2f38572011-01-30 08:37:19 +00002434 complete_url = url
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002435 if url.endswith('.html'):
2436 url = url[:-5]
Georg Brandld2f38572011-01-30 08:37:19 +00002437 try:
2438 if url in ("", "index"):
2439 title, content = html_index()
2440 elif url == "topics":
2441 title, content = html_topics()
2442 elif url == "keywords":
2443 title, content = html_keywords()
2444 elif '=' in url:
2445 op, _, url = url.partition('=')
2446 if op == "search?key":
2447 title, content = html_search(url)
2448 elif op == "getfile?key":
2449 title, content = html_getfile(url)
2450 elif op == "topic?key":
2451 # try topics first, then objects.
2452 try:
2453 title, content = html_topicpage(url)
2454 except ValueError:
2455 title, content = html_getobj(url)
2456 elif op == "get?key":
2457 # try objects first, then topics.
2458 if url in ("", "index"):
2459 title, content = html_index()
2460 else:
2461 try:
2462 title, content = html_getobj(url)
2463 except ValueError:
2464 title, content = html_topicpage(url)
2465 else:
2466 raise ValueError('bad pydoc url')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002467 else:
Georg Brandld2f38572011-01-30 08:37:19 +00002468 title, content = html_getobj(url)
2469 except Exception as exc:
2470 # Catch any errors and display them in an error page.
2471 title, content = html_error(complete_url, exc)
2472 return html.page(title, content)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002473
2474 if url.startswith('/'):
2475 url = url[1:]
2476 if content_type == 'text/css':
2477 path_here = os.path.dirname(os.path.realpath(__file__))
Georg Brandld2f38572011-01-30 08:37:19 +00002478 css_path = os.path.join(path_here, url)
2479 with open(css_path) as fp:
2480 return ''.join(fp.readlines())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002481 elif content_type == 'text/html':
2482 return get_html_page(url)
Georg Brandld2f38572011-01-30 08:37:19 +00002483 # Errors outside the url handler are caught by the server.
2484 raise TypeError('unknown content type %r for url %s' % (content_type, url))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002485
2486
2487def browse(port=0, *, open_browser=True):
2488 """Start the enhanced pydoc Web server and open a Web browser.
2489
2490 Use port '0' to start the server on an arbitrary port.
2491 Set open_browser to False to suppress opening a browser.
2492 """
2493 import webbrowser
2494 serverthread = _start_server(_url_handler, port)
2495 if serverthread.error:
2496 print(serverthread.error)
2497 return
2498 if serverthread.serving:
2499 server_help_msg = 'Server commands: [b]rowser, [q]uit'
2500 if open_browser:
2501 webbrowser.open(serverthread.url)
2502 try:
2503 print('Server ready at', serverthread.url)
2504 print(server_help_msg)
2505 while serverthread.serving:
2506 cmd = input('server> ')
2507 cmd = cmd.lower()
2508 if cmd == 'q':
2509 break
2510 elif cmd == 'b':
2511 webbrowser.open(serverthread.url)
2512 else:
2513 print(server_help_msg)
2514 except (KeyboardInterrupt, EOFError):
2515 print()
2516 finally:
2517 if serverthread.serving:
2518 serverthread.stop()
2519 print('Server stopped')
2520
2521
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002522# -------------------------------------------------- command-line interface
2523
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002524def ispath(x):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002525 return isinstance(x, str) and x.find(os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002526
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002527def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002528 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002529 import getopt
Guido van Rossum756aa932007-04-07 03:04:01 +00002530 class BadUsage(Exception): pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002531
Nick Coghlan106274b2009-11-15 23:04:33 +00002532 # Scripts don't get the current directory in their path by default
2533 # unless they are run with the '-m' switch
2534 if '' not in sys.path:
2535 scriptdir = os.path.dirname(sys.argv[0])
2536 if scriptdir in sys.path:
2537 sys.path.remove(scriptdir)
2538 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002539
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002540 try:
Victor Stinner383c3fc2011-05-25 01:35:05 +02002541 opts, args = getopt.getopt(sys.argv[1:], 'bk:p:w')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002542 writing = False
2543 start_server = False
2544 open_browser = False
2545 port = None
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002546 for opt, val in opts:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002547 if opt == '-b':
2548 start_server = True
2549 open_browser = True
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002550 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002551 apropos(val)
2552 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002553 if opt == '-p':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002554 start_server = True
2555 port = val
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002556 if opt == '-w':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002557 writing = True
2558
Benjamin Petersonb29614e2012-10-09 11:16:03 -04002559 if start_server:
2560 if port is None:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002561 port = 0
2562 browse(port, open_browser=open_browser)
2563 return
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002564
2565 if not args: raise BadUsage
2566 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002567 if ispath(arg) and not os.path.exists(arg):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002568 print('file %r does not exist' % arg)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002569 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002570 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002571 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002572 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002573 if writing:
2574 if ispath(arg) and os.path.isdir(arg):
2575 writedocs(arg)
2576 else:
2577 writedoc(arg)
2578 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002579 help.help(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +00002580 except ErrorDuringImport as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002581 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002582
2583 except (getopt.error, BadUsage):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002584 cmd = os.path.splitext(os.path.basename(sys.argv[0]))[0]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002585 print("""pydoc - the Python documentation tool
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002586
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002587{cmd} <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002588 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002589 Python keyword, topic, function, module, or package, or a dotted
2590 reference to a class or function within a module or module in a
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002591 package. If <name> contains a '{sep}', it is used as the path to a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002592 Python source file to document. If name is 'keywords', 'topics',
2593 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002594
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002595{cmd} -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002596 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002597
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002598{cmd} -p <port>
2599 Start an HTTP server on the given port on the local machine. Port
2600 number 0 can be used to get an arbitrary unused port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002601
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002602{cmd} -b
2603 Start an HTTP server on an arbitrary unused port and open a Web browser
2604 to interactively browse documentation. The -p option can be used with
2605 the -b option to explicitly specify the server port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002606
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002607{cmd} -w <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002608 Write out the HTML documentation for a module to a file in the current
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002609 directory. If <name> contains a '{sep}', it is treated as a filename; if
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002610 it names a directory, documentation is written for all the contents.
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002611""".format(cmd=cmd, sep=os.sep))
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002612
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002613if __name__ == '__main__':
2614 cli()