blob: f4f253010f49d35994376dacf03dfba99d6a4600 [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
Eric Snow32439d62015-05-02 19:15:18 -060056import importlib._bootstrap_external
Brett Cannoncb66eb02012-05-11 12:58:42 -040057import importlib.machinery
Brett Cannonf4ba4ec2013-06-15 14:25:04 -040058import importlib.util
Nick Coghlan7bb30b72010-12-03 09:29:11 +000059import inspect
Victor Stinnere6c910e2011-06-30 15:55:43 +020060import io
61import os
Nick Coghlan7bb30b72010-12-03 09:29:11 +000062import pkgutil
63import platform
64import re
Victor Stinnere6c910e2011-06-30 15:55:43 +020065import sys
Nick Coghlan7bb30b72010-12-03 09:29:11 +000066import time
Victor Stinnere6c910e2011-06-30 15:55:43 +020067import tokenize
Zachary Wareeb432142014-07-10 11:18:00 -050068import urllib.parse
Nick Coghlan7bb30b72010-12-03 09:29:11 +000069import warnings
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000070from collections import deque
Nick Coghlan7bb30b72010-12-03 09:29:11 +000071from reprlib import Repr
Victor Stinner7fa767e2014-03-20 09:16:38 +010072from traceback import format_exception_only
Nick Coghlan7bb30b72010-12-03 09:29:11 +000073
74
Ka-Ping Yeedd175342001-02-27 14:43:46 +000075# --------------------------------------------------------- common routines
76
Ka-Ping Yeedd175342001-02-27 14:43:46 +000077def pathdirs():
78 """Convert sys.path into a list of absolute, existing, unique paths."""
79 dirs = []
Ka-Ping Yee1d384632001-03-01 00:24:32 +000080 normdirs = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +000081 for dir in sys.path:
82 dir = os.path.abspath(dir or '.')
Ka-Ping Yee1d384632001-03-01 00:24:32 +000083 normdir = os.path.normcase(dir)
84 if normdir not in normdirs and os.path.isdir(dir):
Ka-Ping Yeedd175342001-02-27 14:43:46 +000085 dirs.append(dir)
Ka-Ping Yee1d384632001-03-01 00:24:32 +000086 normdirs.append(normdir)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000087 return dirs
88
89def getdoc(object):
90 """Get the doc string or comments for an object."""
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000091 result = inspect.getdoc(object) or inspect.getcomments(object)
Neal Norwitz9d72bb42007-04-17 08:48:32 +000092 return result and re.sub('^ *\n', '', result.rstrip()) or ''
Ka-Ping Yeedd175342001-02-27 14:43:46 +000093
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000094def splitdoc(doc):
95 """Split a doc string into a synopsis line (if any) and the rest."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +000096 lines = doc.strip().split('\n')
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000097 if len(lines) == 1:
98 return lines[0], ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +000099 elif len(lines) >= 2 and not lines[1].rstrip():
100 return lines[0], '\n'.join(lines[2:])
101 return '', '\n'.join(lines)
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000102
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000103def classname(object, modname):
104 """Get a class name and qualify it with a module name if necessary."""
105 name = object.__name__
106 if object.__module__ != modname:
107 name = object.__module__ + '.' + name
108 return name
109
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000110def isdata(object):
Georg Brandl94432422005-07-22 21:52:25 +0000111 """Check if an object is of a type that probably means it's data."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000112 return not (inspect.ismodule(object) or inspect.isclass(object) or
113 inspect.isroutine(object) or inspect.isframe(object) or
114 inspect.istraceback(object) or inspect.iscode(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000115
116def replace(text, *pairs):
117 """Do a series of global replacements on a string."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000118 while pairs:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000119 text = pairs[1].join(text.split(pairs[0]))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000120 pairs = pairs[2:]
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000121 return text
122
123def cram(text, maxlen):
124 """Omit part of a string if needed to make it fit in a maximum length."""
125 if len(text) > maxlen:
Raymond Hettingerfca3bb62002-10-21 04:44:11 +0000126 pre = max(0, (maxlen-3)//2)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000127 post = max(0, maxlen-3-pre)
128 return text[:pre] + '...' + text[len(text)-post:]
129 return text
130
Brett Cannon84601f12004-06-19 01:22:48 +0000131_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000132def stripid(text):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000133 """Remove the hexadecimal id from a Python object representation."""
Brett Cannonc6c1f472004-06-19 01:02:51 +0000134 # The behaviour of %p is implementation-dependent in terms of case.
Ezio Melotti412c95a2010-02-16 23:31:04 +0000135 return _re_stripid.sub(r'\1', text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000136
Brett Cannonc6c1f472004-06-19 01:02:51 +0000137def _is_some_method(obj):
R David Murrayac0cea52013-03-19 02:47:44 -0400138 return (inspect.isfunction(obj) or
139 inspect.ismethod(obj) or
140 inspect.isbuiltin(obj) or
141 inspect.ismethoddescriptor(obj))
Tim Peters536d2262001-09-20 05:13:38 +0000142
Larry Hastings24a882b2014-02-20 23:34:46 -0800143def _is_bound_method(fn):
144 """
145 Returns True if fn is a bound method, regardless of whether
146 fn was implemented in Python or in C.
147 """
148 if inspect.ismethod(fn):
149 return True
150 if inspect.isbuiltin(fn):
151 self = getattr(fn, '__self__', None)
152 return not (inspect.ismodule(self) or (self is None))
153 return False
154
155
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000156def allmethods(cl):
157 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000158 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000159 methods[key] = 1
160 for base in cl.__bases__:
161 methods.update(allmethods(base)) # all your base are belong to us
162 for key in methods.keys():
163 methods[key] = getattr(cl, key)
164 return methods
165
Tim Petersfa26f7c2001-09-24 08:05:11 +0000166def _split_list(s, predicate):
167 """Split sequence s via predicate, and return pair ([true], [false]).
168
169 The return value is a 2-tuple of lists,
170 ([x for x in s if predicate(x)],
171 [x for x in s if not predicate(x)])
172 """
173
Tim Peters28355492001-09-23 21:29:55 +0000174 yes = []
175 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000176 for x in s:
177 if predicate(x):
178 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000179 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000180 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000181 return yes, no
182
Raymond Hettinger1103d052011-03-25 14:15:24 -0700183def visiblename(name, all=None, obj=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000184 """Decide whether to show documentation on a variable."""
Brett Cannond340b432012-08-06 17:19:22 -0400185 # Certain special names are redundant or internal.
Eric Snowb523f842013-11-22 09:05:39 -0700186 # XXX Remove __initializing__?
Brett Cannond340b432012-08-06 17:19:22 -0400187 if name in {'__author__', '__builtins__', '__cached__', '__credits__',
Eric Snowb523f842013-11-22 09:05:39 -0700188 '__date__', '__doc__', '__file__', '__spec__',
Brett Cannond340b432012-08-06 17:19:22 -0400189 '__loader__', '__module__', '__name__', '__package__',
190 '__path__', '__qualname__', '__slots__', '__version__'}:
Raymond Hettinger68272942011-03-18 02:22:15 -0700191 return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000192 # Private names are hidden, but special names are displayed.
193 if name.startswith('__') and name.endswith('__'): return 1
Raymond Hettinger1103d052011-03-25 14:15:24 -0700194 # Namedtuples have public fields and methods with a single leading underscore
195 if name.startswith('_') and hasattr(obj, '_fields'):
196 return True
Skip Montanaroa5616d22004-06-11 04:46:12 +0000197 if all is not None:
198 # only document that which the programmer exported in __all__
199 return name in all
200 else:
201 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000202
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000203def classify_class_attrs(object):
204 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000205 results = []
206 for (name, kind, cls, value) in inspect.classify_class_attrs(object):
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000207 if inspect.isdatadescriptor(value):
208 kind = 'data descriptor'
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000209 results.append((name, kind, cls, value))
210 return results
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000211
Raymond Hettinger95801bb2015-08-18 22:25:16 -0700212def sort_attributes(attrs, object):
213 'Sort the attrs list in-place by _fields and then alphabetically by name'
214 # This allows data descriptors to be ordered according
215 # to a _fields attribute if present.
216 fields = getattr(object, '_fields', [])
217 try:
218 field_order = {name : i-len(fields) for (i, name) in enumerate(fields)}
219 except TypeError:
220 field_order = {}
221 keyfunc = lambda attr: (field_order.get(attr[0], 0), attr[0])
222 attrs.sort(key=keyfunc)
223
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000224# ----------------------------------------------------- module manipulation
225
226def ispackage(path):
227 """Guess whether a path refers to a package directory."""
228 if os.path.isdir(path):
Brett Cannonf299abd2015-04-13 14:21:02 -0400229 for ext in ('.py', '.pyc'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000230 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000231 return True
232 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000233
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000234def source_synopsis(file):
235 line = file.readline()
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000236 while line[:1] == '#' or not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000237 line = file.readline()
238 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000239 line = line.strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000240 if line[:4] == 'r"""': line = line[1:]
241 if line[:3] == '"""':
242 line = line[3:]
243 if line[-1:] == '\\': line = line[:-1]
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000244 while not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000245 line = file.readline()
246 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000247 result = line.split('"""')[0].strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000248 else: result = None
249 return result
250
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000251def synopsis(filename, cache={}):
252 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000253 mtime = os.stat(filename).st_mtime
Charles-François Natali27c4e882011-07-27 19:40:02 +0200254 lastupdate, result = cache.get(filename, (None, None))
255 if lastupdate is None or lastupdate < mtime:
Eric Snowaed5b222014-01-04 20:38:11 -0700256 # Look for binary suffixes first, falling back to source.
257 if filename.endswith(tuple(importlib.machinery.BYTECODE_SUFFIXES)):
258 loader_cls = importlib.machinery.SourcelessFileLoader
259 elif filename.endswith(tuple(importlib.machinery.EXTENSION_SUFFIXES)):
260 loader_cls = importlib.machinery.ExtensionFileLoader
261 else:
262 loader_cls = None
263 # Now handle the choice.
264 if loader_cls is None:
265 # Must be a source file.
266 try:
267 file = tokenize.open(filename)
268 except OSError:
269 # module can't be opened, so skip it
270 return None
271 # text modules can be directly examined
272 with file:
273 result = source_synopsis(file)
274 else:
275 # Must be a binary module, which has to be imported.
276 loader = loader_cls('__temp__', filename)
Eric Snow3a62d142014-01-06 20:42:59 -0700277 # XXX We probably don't need to pass in the loader here.
278 spec = importlib.util.spec_from_file_location('__temp__', filename,
279 loader=loader)
Brett Cannoncb66eb02012-05-11 12:58:42 -0400280 try:
Brett Cannon2a17bde2014-05-30 14:55:29 -0400281 module = importlib._bootstrap._load(spec)
Brett Cannoncb66eb02012-05-11 12:58:42 -0400282 except:
283 return None
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000284 del sys.modules['__temp__']
Benjamin Peterson54237f92015-02-16 19:45:01 -0500285 result = module.__doc__.splitlines()[0] if module.__doc__ else None
Eric Snowaed5b222014-01-04 20:38:11 -0700286 # Cache the result.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000287 cache[filename] = (mtime, result)
288 return result
289
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000290class ErrorDuringImport(Exception):
291 """Errors that occurred while trying to import something to document it."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000292 def __init__(self, filename, exc_info):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000293 self.filename = filename
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000294 self.exc, self.value, self.tb = exc_info
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000295
296 def __str__(self):
Guido van Rossuma01a8b62007-05-27 09:20:14 +0000297 exc = self.exc.__name__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000298 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000299
300def importfile(path):
301 """Import a Python source file or compiled file given its path."""
Brett Cannonf4ba4ec2013-06-15 14:25:04 -0400302 magic = importlib.util.MAGIC_NUMBER
Victor Stinnere975af62011-07-04 02:08:50 +0200303 with open(path, 'rb') as file:
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400304 is_bytecode = magic == file.read(len(magic))
305 filename = os.path.basename(path)
306 name, ext = os.path.splitext(filename)
307 if is_bytecode:
Eric Snow32439d62015-05-02 19:15:18 -0600308 loader = importlib._bootstrap_external.SourcelessFileLoader(name, path)
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400309 else:
Eric Snow32439d62015-05-02 19:15:18 -0600310 loader = importlib._bootstrap_external.SourceFileLoader(name, path)
Eric Snow3a62d142014-01-06 20:42:59 -0700311 # XXX We probably don't need to pass in the loader here.
312 spec = importlib.util.spec_from_file_location(name, path, loader=loader)
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400313 try:
Brett Cannon2a17bde2014-05-30 14:55:29 -0400314 return importlib._bootstrap._load(spec)
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400315 except:
316 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000317
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000318def safeimport(path, forceload=0, cache={}):
319 """Import a module; handle errors; return None if the module isn't found.
320
321 If the module *is* found but an exception occurs, it's wrapped in an
322 ErrorDuringImport exception and reraised. Unlike __import__, if a
323 package path is specified, the module at the end of the path is returned,
324 not the package at the beginning. If the optional 'forceload' argument
325 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000326 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000327 # If forceload is 1 and the module has been previously loaded from
328 # disk, we always have to reload the module. Checking the file's
329 # mtime isn't good enough (e.g. the module could contain a class
330 # that inherits from another module that has changed).
331 if forceload and path in sys.modules:
332 if path not in sys.builtin_module_names:
Guido van Rossume7ba4952007-06-06 23:52:48 +0000333 # Remove the module from sys.modules and re-import to try
334 # and avoid problems with partially loaded modules.
335 # Also remove any submodules because they won't appear
336 # in the newly loaded module's namespace if they're already
337 # in sys.modules.
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000338 subs = [m for m in sys.modules if m.startswith(path + '.')]
339 for key in [path] + subs:
340 # Prevent garbage collection.
341 cache[key] = sys.modules[key]
342 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000343 module = __import__(path)
344 except:
345 # Did the error occur before or after the module was found?
346 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000347 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000348 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000349 raise ErrorDuringImport(sys.modules[path].__file__, info)
350 elif exc is SyntaxError:
351 # A SyntaxError occurred before we could execute the module.
352 raise ErrorDuringImport(value.filename, info)
Brett Cannon679ecb52013-07-04 17:51:50 -0400353 elif exc is ImportError and value.name == path:
Brett Cannonfd074152012-04-14 14:10:13 -0400354 # No such module in the path.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000355 return None
356 else:
357 # Some other error occurred during the importing process.
358 raise ErrorDuringImport(path, sys.exc_info())
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000359 for part in path.split('.')[1:]:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000360 try: module = getattr(module, part)
361 except AttributeError: return None
362 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000363
364# ---------------------------------------------------- formatter base class
365
366class Doc:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000367
368 PYTHONDOCS = os.environ.get("PYTHONDOCS",
369 "http://docs.python.org/%d.%d/library"
370 % sys.version_info[:2])
371
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000372 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000373 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000374 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000375 # 'try' clause is to attempt to handle the possibility that inspect
376 # identifies something in a way that pydoc itself has issues handling;
377 # think 'super' and how it is a descriptor (which raises the exception
378 # by lacking a __name__ attribute) and an instance.
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000379 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
380 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000381 try:
382 if inspect.ismodule(object): return self.docmodule(*args)
383 if inspect.isclass(object): return self.docclass(*args)
384 if inspect.isroutine(object): return self.docroutine(*args)
385 except AttributeError:
386 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000387 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000388 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000389
390 def fail(self, object, name=None, *args):
391 """Raise an exception for unimplemented types."""
392 message = "don't know how to document object%s of type %s" % (
393 name and ' ' + repr(name), type(object).__name__)
Collin Winterce36ad82007-08-30 01:19:48 +0000394 raise TypeError(message)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000395
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000396 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000397
Skip Montanaro4997a692003-09-10 16:47:51 +0000398 def getdocloc(self, object):
399 """Return the location of module docs or None"""
400
401 try:
402 file = inspect.getabsfile(object)
403 except TypeError:
404 file = '(built-in)'
405
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000406 docloc = os.environ.get("PYTHONDOCS", self.PYTHONDOCS)
407
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100408 basedir = os.path.join(sys.base_exec_prefix, "lib",
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000409 "python%d.%d" % sys.version_info[:2])
Skip Montanaro4997a692003-09-10 16:47:51 +0000410 if (isinstance(object, type(os)) and
411 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
412 'marshal', 'posix', 'signal', 'sys',
Georg Brandl2067bfd2008-05-25 13:05:15 +0000413 '_thread', 'zipimport') or
Skip Montanaro4997a692003-09-10 16:47:51 +0000414 (file.startswith(basedir) and
Brian Curtin49c284c2010-03-31 03:19:28 +0000415 not file.startswith(os.path.join(basedir, 'site-packages')))) and
Brian Curtinedef05b2010-04-01 04:05:25 +0000416 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
Skip Montanaro4997a692003-09-10 16:47:51 +0000417 if docloc.startswith("http://"):
Georg Brandl86def6c2008-01-21 20:36:10 +0000418 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
Skip Montanaro4997a692003-09-10 16:47:51 +0000419 else:
Georg Brandl86def6c2008-01-21 20:36:10 +0000420 docloc = os.path.join(docloc, object.__name__ + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000421 else:
422 docloc = None
423 return docloc
424
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000425# -------------------------------------------- HTML documentation generator
426
427class HTMLRepr(Repr):
428 """Class for safely making an HTML representation of a Python object."""
429 def __init__(self):
430 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000431 self.maxlist = self.maxtuple = 20
432 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000433 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000434
435 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000436 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000437
438 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000439 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000440
441 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000442 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000443 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000444 if hasattr(self, methodname):
445 return getattr(self, methodname)(x, level)
446 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000447
448 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000449 test = cram(x, self.maxstring)
450 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000451 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000452 # Backslashes are only literal in the string and are never
453 # needed to make any special characters, so show a raw string.
454 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000455 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000456 r'<font color="#c040c0">\1</font>',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000457 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000458
Skip Montanarodf708782002-03-07 22:58:02 +0000459 repr_str = repr_string
460
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000461 def repr_instance(self, x, level):
462 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000463 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000464 except:
465 return self.escape('<%s instance>' % x.__class__.__name__)
466
467 repr_unicode = repr_string
468
469class HTMLDoc(Doc):
470 """Formatter class for HTML documentation."""
471
472 # ------------------------------------------- HTML formatting utilities
473
474 _repr_instance = HTMLRepr()
475 repr = _repr_instance.repr
476 escape = _repr_instance.escape
477
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000478 def page(self, title, contents):
479 """Format an HTML page."""
Georg Brandl388faac2009-04-10 08:31:48 +0000480 return '''\
Georg Brandle6066942009-04-10 08:28:28 +0000481<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000482<html><head><title>Python: %s</title>
Georg Brandl388faac2009-04-10 08:31:48 +0000483<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000484</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000485%s
486</body></html>''' % (title, contents)
487
488 def heading(self, title, fgcol, bgcol, extras=''):
489 """Format a page heading."""
490 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000491<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000492<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000493<td valign=bottom>&nbsp;<br>
494<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000495><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000496><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000497 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
498
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000499 def section(self, title, fgcol, bgcol, contents, width=6,
500 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000501 """Format a section with a heading."""
502 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000503 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000504 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000505<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000506<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000507<td colspan=3 valign=bottom>&nbsp;<br>
508<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000509 ''' % (bgcol, fgcol, title)
510 if prelude:
511 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000512<tr bgcolor="%s"><td rowspan=2>%s</td>
513<td colspan=2>%s</td></tr>
514<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
515 else:
516 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000517<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000518
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000519 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000520
521 def bigsection(self, title, *args):
522 """Format a section with a big heading."""
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000523 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000524 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000525
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000526 def preformat(self, text):
527 """Format literal preformatted text."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000528 text = self.escape(text.expandtabs())
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000529 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
530 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000531
532 def multicolumn(self, list, format, cols=4):
533 """Format a list of items into a multi-column list."""
534 result = ''
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000535 rows = (len(list)+cols-1)//cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000536 for col in range(cols):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000537 result = result + '<td width="%d%%" valign=top>' % (100//cols)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000538 for i in range(rows*col, rows*col+rows):
539 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000540 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000541 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000542 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000543
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000544 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000545
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000546 def namelink(self, name, *dicts):
547 """Make a link for an identifier, given name-to-URL mappings."""
548 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000549 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000550 return '<a href="%s">%s</a>' % (dict[name], name)
551 return name
552
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000553 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000554 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000555 name, module = object.__name__, sys.modules.get(object.__module__)
556 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000557 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000558 module.__name__, name, classname(object, modname))
559 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000560
561 def modulelink(self, object):
562 """Make a link for a module."""
563 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
564
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000565 def modpkglink(self, modpkginfo):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000566 """Make a link for a module or package to display in an index."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000567 name, path, ispackage, shadowed = modpkginfo
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000568 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000569 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000570 if path:
571 url = '%s.%s.html' % (path, name)
572 else:
573 url = '%s.html' % name
574 if ispackage:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000575 text = '<strong>%s</strong>&nbsp;(package)' % name
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000576 else:
577 text = name
578 return '<a href="%s">%s</a>' % (url, text)
579
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000580 def filelink(self, url, path):
581 """Make a link to source file."""
582 return '<a href="file:%s">%s</a>' % (url, path)
583
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000584 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
585 """Mark up some plain text, given a context of symbols to look for.
586 Each context dictionary maps object names to anchor names."""
587 escape = escape or self.escape
588 results = []
589 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000590 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
591 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000592 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000593 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000594 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000595 match = pattern.search(text, here)
596 if not match: break
597 start, end = match.span()
598 results.append(escape(text[here:start]))
599
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000600 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000601 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000602 url = escape(all).replace('"', '&quot;')
603 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000604 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000605 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
606 results.append('<a href="%s">%s</a>' % (url, escape(all)))
607 elif pep:
Christian Heimes2202f872008-02-06 14:31:34 +0000608 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000609 results.append('<a href="%s">%s</a>' % (url, escape(all)))
Benjamin Petersoned1160b2014-06-07 16:44:00 -0700610 elif selfdot:
611 # Create a link for methods like 'self.method(...)'
612 # and use <strong> for attributes like 'self.attr'
613 if text[end:end+1] == '(':
614 results.append('self.' + self.namelink(name, methods))
615 else:
616 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000617 elif text[end:end+1] == '(':
618 results.append(self.namelink(name, methods, funcs, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000619 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000620 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000621 here = end
622 results.append(escape(text[here:]))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000623 return ''.join(results)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000624
625 # ---------------------------------------------- type-specific routines
626
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000627 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000628 """Produce HTML for a class tree as given by inspect.getclasstree()."""
629 result = ''
630 for entry in tree:
631 if type(entry) is type(()):
632 c, bases = entry
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000633 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000634 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000635 if bases and bases != (parent,):
636 parents = []
637 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000638 parents.append(self.classlink(base, modname))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000639 result = result + '(' + ', '.join(parents) + ')'
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000640 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000641 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000642 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000643 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000644 return '<dl>\n%s</dl>\n' % result
645
Tim Peters8dd7ade2001-10-18 19:56:17 +0000646 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000647 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000648 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000649 try:
650 all = object.__all__
651 except AttributeError:
652 all = None
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000653 parts = name.split('.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000654 links = []
655 for i in range(len(parts)-1):
656 links.append(
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000657 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000658 ('.'.join(parts[:i+1]), parts[i]))
659 linkedname = '.'.join(links + parts[-1:])
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000660 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000661 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000662 path = inspect.getabsfile(object)
Zachary Wareeb432142014-07-10 11:18:00 -0500663 url = urllib.parse.quote(path)
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000664 filelink = self.filelink(url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000665 except TypeError:
666 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000667 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000668 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000669 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000670 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000671 version = version[11:-1].strip()
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000672 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000673 if hasattr(object, '__date__'):
674 info.append(self.escape(str(object.__date__)))
675 if info:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000676 head = head + ' (%s)' % ', '.join(info)
Skip Montanaro4997a692003-09-10 16:47:51 +0000677 docloc = self.getdocloc(object)
678 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000679 docloc = '<br><a href="%(docloc)s">Module Reference</a>' % locals()
Skip Montanaro4997a692003-09-10 16:47:51 +0000680 else:
681 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000682 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000683 head, '#ffffff', '#7799ee',
684 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000685
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000686 modules = inspect.getmembers(object, inspect.ismodule)
687
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000688 classes, cdict = [], {}
689 for key, value in inspect.getmembers(object, inspect.isclass):
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.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700693 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000694 classes.append((key, value))
695 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000696 for key, value in classes:
697 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000698 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000699 module = sys.modules.get(modname)
700 if modname != name and module and hasattr(module, key):
701 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000702 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000703 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000704 funcs, fdict = [], {}
705 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000706 # if __all__ exists, believe it. Otherwise use old heuristic.
707 if (all is not None or
708 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700709 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000710 funcs.append((key, value))
711 fdict[key] = '#-' + key
712 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000713 data = []
714 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700715 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000716 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000717
718 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
719 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000720 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000721
722 if hasattr(object, '__path__'):
723 modpkgs = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000724 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
725 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000726 modpkgs.sort()
727 contents = self.multicolumn(modpkgs, self.modpkglink)
728 result = result + self.bigsection(
729 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000730 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000731 contents = self.multicolumn(
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000732 modules, lambda t: self.modulelink(t[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000733 result = result + self.bigsection(
Christian Heimes7131fd92008-02-19 14:21:46 +0000734 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000735
736 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000737 classlist = [value for (key, value) in classes]
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000738 contents = [
739 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000740 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000741 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000742 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000743 'Classes', '#ffffff', '#ee77aa', ' '.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000744 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000745 contents = []
746 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000747 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000748 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000749 'Functions', '#ffffff', '#eeaa77', ' '.join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000750 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000751 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000752 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000753 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000754 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000755 'Data', '#ffffff', '#55aa55', '<br>\n'.join(contents))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000756 if hasattr(object, '__author__'):
757 contents = self.markup(str(object.__author__), self.preformat)
758 result = result + self.bigsection(
759 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000760 if hasattr(object, '__credits__'):
761 contents = self.markup(str(object.__credits__), self.preformat)
762 result = result + self.bigsection(
763 'Credits', '#ffffff', '#7799ee', contents)
764
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000765 return result
766
Tim Peters8dd7ade2001-10-18 19:56:17 +0000767 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
768 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000769 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000770 realname = object.__name__
771 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000772 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000773
Tim Petersb47879b2001-09-24 04:47:19 +0000774 contents = []
775 push = contents.append
776
Tim Petersfa26f7c2001-09-24 08:05:11 +0000777 # Cute little class to pump out a horizontal rule between sections.
778 class HorizontalRule:
779 def __init__(self):
780 self.needone = 0
781 def maybe(self):
782 if self.needone:
783 push('<hr>\n')
784 self.needone = 1
785 hr = HorizontalRule()
786
Tim Petersc86f6ca2001-09-26 21:31:51 +0000787 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000788 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000789 if len(mro) > 2:
790 hr.maybe()
791 push('<dl><dt>Method resolution order:</dt>\n')
792 for base in mro:
793 push('<dd>%s</dd>\n' % self.classlink(base,
794 object.__module__))
795 push('</dl>\n')
796
Tim Petersb47879b2001-09-24 04:47:19 +0000797 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000798 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000799 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000800 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000801 push(msg)
802 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100803 try:
804 value = getattr(object, name)
805 except Exception:
806 # Some descriptors may meet a failure in their __get__.
807 # (bug #1785)
808 push(self._docdescriptor(name, value, mod))
809 else:
810 push(self.document(value, name, mod,
811 funcs, classes, mdict, object))
Tim Petersb47879b2001-09-24 04:47:19 +0000812 push('\n')
813 return attrs
814
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000815 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000816 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000817 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000818 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000819 push(msg)
820 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000821 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000822 return attrs
823
Tim Petersfa26f7c2001-09-24 08:05:11 +0000824 def spilldata(msg, attrs, predicate):
825 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000826 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000827 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000828 push(msg)
829 for name, kind, homecls, value in ok:
830 base = self.docother(getattr(object, name), name, mod)
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200831 if callable(value) or inspect.isdatadescriptor(value):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000832 doc = getattr(value, "__doc__", None)
833 else:
834 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000835 if doc is None:
836 push('<dl><dt>%s</dl>\n' % base)
837 else:
838 doc = self.markup(getdoc(value), self.preformat,
839 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000840 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000841 push('<dl><dt>%s%s</dl>\n' % (base, doc))
842 push('\n')
843 return attrs
844
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000845 attrs = [(name, kind, cls, value)
846 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -0700847 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000848
Tim Petersb47879b2001-09-24 04:47:19 +0000849 mdict = {}
850 for key, kind, homecls, value in attrs:
851 mdict[key] = anchor = '#' + name + '-' + key
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100852 try:
853 value = getattr(object, name)
854 except Exception:
855 # Some descriptors may meet a failure in their __get__.
856 # (bug #1785)
857 pass
Tim Petersb47879b2001-09-24 04:47:19 +0000858 try:
859 # The value may not be hashable (e.g., a data attr with
860 # a dict or list value).
861 mdict[value] = anchor
862 except TypeError:
863 pass
864
Tim Petersfa26f7c2001-09-24 08:05:11 +0000865 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000866 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000867 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000868 else:
869 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000870 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
871
Georg Brandl1a3284e2007-12-02 09:40:06 +0000872 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000873 attrs = inherited
874 continue
875 elif thisclass is object:
876 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000877 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000878 tag = 'inherited from %s' % self.classlink(thisclass,
879 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000880 tag += ':<br>\n'
881
Raymond Hettinger95801bb2015-08-18 22:25:16 -0700882 sort_attributes(attrs, object)
Tim Petersb47879b2001-09-24 04:47:19 +0000883
884 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000885 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000886 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000887 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000888 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000889 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000890 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000891 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
892 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000893 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000894 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000895 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000896 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000897
898 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000899
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000900 if name == realname:
901 title = '<a name="%s">class <strong>%s</strong></a>' % (
902 name, realname)
903 else:
904 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
905 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000906 if bases:
907 parents = []
908 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000909 parents.append(self.classlink(base, object.__module__))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000910 title = title + '(%s)' % ', '.join(parents)
Tim Peters2306d242001-09-25 03:18:32 +0000911 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000912 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000913
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000914 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000915
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000916 def formatvalue(self, object):
917 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000918 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000919
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000920 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000921 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000922 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000923 realname = object.__name__
924 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000925 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000926 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000927 skipdocs = 0
Larry Hastings24a882b2014-02-20 23:34:46 -0800928 if _is_bound_method(object):
Christian Heimesff737952007-11-27 10:40:20 +0000929 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000930 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000931 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000932 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000933 else:
Christian Heimesff737952007-11-27 10:40:20 +0000934 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000935 note = ' method of %s instance' % self.classlink(
Christian Heimesff737952007-11-27 10:40:20 +0000936 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000937 else:
938 note = ' unbound %s method' % self.classlink(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000939
940 if name == realname:
941 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
942 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000943 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000944 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000945 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000946 cl.__name__ + '-' + realname, realname)
947 skipdocs = 1
948 else:
949 reallink = realname
950 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
951 anchor, name, reallink)
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800952 argspec = None
Larry Hastings24a882b2014-02-20 23:34:46 -0800953 if inspect.isroutine(object):
Larry Hastings5c661892014-01-24 06:17:25 -0800954 try:
955 signature = inspect.signature(object)
956 except (ValueError, TypeError):
957 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800958 if signature:
959 argspec = str(signature)
960 if realname == '<lambda>':
961 title = '<strong>%s</strong> <em>lambda</em> ' % name
962 # XXX lambda's won't usually have func_annotations['return']
963 # since the syntax doesn't support but it is possible.
964 # So removing parentheses isn't truly safe.
965 argspec = argspec[1:-1] # remove parentheses
966 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +0000967 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000968
Serhiy Storchaka66dd4aa2014-11-17 23:48:02 +0200969 decl = title + self.escape(argspec) + (note and self.grey(
Tim Peters2306d242001-09-25 03:18:32 +0000970 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000971
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000972 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000973 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000974 else:
975 doc = self.markup(
976 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000977 doc = doc and '<dd><tt>%s</tt></dd>' % doc
978 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000979
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000980 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000981 results = []
982 push = results.append
983
984 if name:
985 push('<dl><dt><strong>%s</strong></dt>\n' % name)
986 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000987 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000988 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000989 push('</dl>\n')
990
991 return ''.join(results)
992
993 def docproperty(self, object, name=None, mod=None, cl=None):
994 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000995 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000996
Tim Peters8dd7ade2001-10-18 19:56:17 +0000997 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000998 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000999 lhs = name and '<strong>%s</strong> = ' % name or ''
1000 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001001
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001002 def docdata(self, object, name=None, mod=None, cl=None):
1003 """Produce html documentation for a data descriptor."""
1004 return self._docdescriptor(name, object, mod)
1005
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001006 def index(self, dir, shadowed=None):
1007 """Generate an HTML index for a directory of modules."""
1008 modpkgs = []
1009 if shadowed is None: shadowed = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001010 for importer, name, ispkg in pkgutil.iter_modules([dir]):
Victor Stinner4d652242011-04-12 23:41:50 +02001011 if any((0xD800 <= ord(ch) <= 0xDFFF) for ch in name):
1012 # ignore a module if its name contains a surrogate character
1013 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001014 modpkgs.append((name, '', ispkg, name in shadowed))
1015 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001016
1017 modpkgs.sort()
1018 contents = self.multicolumn(modpkgs, self.modpkglink)
1019 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
1020
1021# -------------------------------------------- text documentation generator
1022
1023class TextRepr(Repr):
1024 """Class for safely making a text representation of a Python object."""
1025 def __init__(self):
1026 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001027 self.maxlist = self.maxtuple = 20
1028 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001029 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001030
1031 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001032 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001033 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001034 if hasattr(self, methodname):
1035 return getattr(self, methodname)(x, level)
1036 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001037
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001038 def repr_string(self, x, level):
1039 test = cram(x, self.maxstring)
1040 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001041 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001042 # Backslashes are only literal in the string and are never
1043 # needed to make any special characters, so show a raw string.
1044 return 'r' + testrepr[0] + test + testrepr[0]
1045 return testrepr
1046
Skip Montanarodf708782002-03-07 22:58:02 +00001047 repr_str = repr_string
1048
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001049 def repr_instance(self, x, level):
1050 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001051 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001052 except:
1053 return '<%s instance>' % x.__class__.__name__
1054
1055class TextDoc(Doc):
1056 """Formatter class for text documentation."""
1057
1058 # ------------------------------------------- text formatting utilities
1059
1060 _repr_instance = TextRepr()
1061 repr = _repr_instance.repr
1062
1063 def bold(self, text):
1064 """Format a string in bold by overstriking."""
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001065 return ''.join(ch + '\b' + ch for ch in text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001066
1067 def indent(self, text, prefix=' '):
1068 """Indent text by prepending a given prefix to each line."""
1069 if not text: return ''
Collin Winter72e110c2007-07-17 00:27:30 +00001070 lines = [prefix + line for line in text.split('\n')]
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001071 if lines: lines[-1] = lines[-1].rstrip()
1072 return '\n'.join(lines)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001073
1074 def section(self, title, contents):
1075 """Format a section with a given heading."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001076 clean_contents = self.indent(contents).rstrip()
1077 return self.bold(title) + '\n' + clean_contents + '\n\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001078
1079 # ---------------------------------------------- type-specific routines
1080
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001081 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001082 """Render in text a class tree as returned by inspect.getclasstree()."""
1083 result = ''
1084 for entry in tree:
1085 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001086 c, bases = entry
1087 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001088 if bases and bases != (parent,):
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001089 parents = (classname(c, modname) for c in bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001090 result = result + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001091 result = result + '\n'
1092 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001093 result = result + self.formattree(
1094 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001095 return result
1096
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001097 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001098 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001099 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001100 synop, desc = splitdoc(getdoc(object))
1101 result = self.section('NAME', name + (synop and ' - ' + synop))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001102 all = getattr(object, '__all__', None)
Skip Montanaro4997a692003-09-10 16:47:51 +00001103 docloc = self.getdocloc(object)
1104 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001105 result = result + self.section('MODULE REFERENCE', docloc + """
1106
Éric Araujo647ef8c2011-09-11 00:43:20 +02001107The following documentation is automatically generated from the Python
1108source files. It may be incomplete, incorrect or include features that
1109are considered implementation detail and may vary between Python
1110implementations. When in doubt, consult the module reference at the
1111location listed above.
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001112""")
Skip Montanaro4997a692003-09-10 16:47:51 +00001113
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001114 if desc:
1115 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001116
1117 classes = []
1118 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001119 # if __all__ exists, believe it. Otherwise use old heuristic.
1120 if (all is not None
1121 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001122 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001123 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001124 funcs = []
1125 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001126 # if __all__ exists, believe it. Otherwise use old heuristic.
1127 if (all is not None or
1128 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001129 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001130 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001131 data = []
1132 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001133 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001134 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001135
Christian Heimes1af737c2008-01-23 08:24:23 +00001136 modpkgs = []
1137 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001138 if hasattr(object, '__path__'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001139 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Christian Heimes1af737c2008-01-23 08:24:23 +00001140 modpkgs_names.add(modname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001141 if ispkg:
1142 modpkgs.append(modname + ' (package)')
1143 else:
1144 modpkgs.append(modname)
1145
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001146 modpkgs.sort()
1147 result = result + self.section(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001148 'PACKAGE CONTENTS', '\n'.join(modpkgs))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001149
Christian Heimes1af737c2008-01-23 08:24:23 +00001150 # Detect submodules as sometimes created by C extensions
1151 submodules = []
1152 for key, value in inspect.getmembers(object, inspect.ismodule):
1153 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1154 submodules.append(key)
1155 if submodules:
1156 submodules.sort()
1157 result = result + self.section(
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001158 'SUBMODULES', '\n'.join(submodules))
Christian Heimes1af737c2008-01-23 08:24:23 +00001159
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001160 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001161 classlist = [value for key, value in classes]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001162 contents = [self.formattree(
1163 inspect.getclasstree(classlist, 1), name)]
1164 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001165 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001166 result = result + self.section('CLASSES', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001167
1168 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001169 contents = []
1170 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001171 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001172 result = result + self.section('FUNCTIONS', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001173
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001174 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001175 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001176 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001177 contents.append(self.docother(value, key, name, maxlen=70))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001178 result = result + self.section('DATA', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001179
1180 if hasattr(object, '__version__'):
1181 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001182 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001183 version = version[11:-1].strip()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001184 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001185 if hasattr(object, '__date__'):
1186 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001187 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001188 result = result + self.section('AUTHOR', str(object.__author__))
1189 if hasattr(object, '__credits__'):
1190 result = result + self.section('CREDITS', str(object.__credits__))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001191 try:
1192 file = inspect.getabsfile(object)
1193 except TypeError:
1194 file = '(built-in)'
1195 result = result + self.section('FILE', file)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001196 return result
1197
Georg Brandl9bd45f992010-12-03 09:58:38 +00001198 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001199 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001200 realname = object.__name__
1201 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001202 bases = object.__bases__
1203
Tim Petersc86f6ca2001-09-26 21:31:51 +00001204 def makename(c, m=object.__module__):
1205 return classname(c, m)
1206
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001207 if name == realname:
1208 title = 'class ' + self.bold(realname)
1209 else:
1210 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001211 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001212 parents = map(makename, bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001213 title = title + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001214
1215 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001216 contents = doc and [doc + '\n'] or []
1217 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001218
Tim Petersc86f6ca2001-09-26 21:31:51 +00001219 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001220 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001221 if len(mro) > 2:
1222 push("Method resolution order:")
1223 for base in mro:
1224 push(' ' + makename(base))
1225 push('')
1226
Tim Petersf4aad8e2001-09-24 22:40:47 +00001227 # Cute little class to pump out a horizontal rule between sections.
1228 class HorizontalRule:
1229 def __init__(self):
1230 self.needone = 0
1231 def maybe(self):
1232 if self.needone:
1233 push('-' * 70)
1234 self.needone = 1
1235 hr = HorizontalRule()
1236
Tim Peters28355492001-09-23 21:29:55 +00001237 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001238 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001239 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001240 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001241 push(msg)
1242 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001243 try:
1244 value = getattr(object, name)
1245 except Exception:
1246 # Some descriptors may meet a failure in their __get__.
1247 # (bug #1785)
1248 push(self._docdescriptor(name, value, mod))
1249 else:
1250 push(self.document(value,
1251 name, mod, object))
Tim Peters28355492001-09-23 21:29:55 +00001252 return attrs
1253
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001254 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001255 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001256 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001257 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001258 push(msg)
1259 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001260 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001261 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001262
Tim Petersfa26f7c2001-09-24 08:05:11 +00001263 def spilldata(msg, attrs, predicate):
1264 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001265 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001266 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001267 push(msg)
1268 for name, kind, homecls, value in ok:
Florent Xicluna5d1155c2011-10-28 14:45:05 +02001269 if callable(value) or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001270 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001271 else:
1272 doc = None
Serhiy Storchaka056eb022014-02-19 23:05:12 +02001273 try:
1274 obj = getattr(object, name)
1275 except AttributeError:
1276 obj = homecls.__dict__[name]
1277 push(self.docother(obj, name, mod, maxlen=70, doc=doc) +
1278 '\n')
Tim Peters28355492001-09-23 21:29:55 +00001279 return attrs
1280
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001281 attrs = [(name, kind, cls, value)
1282 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -07001283 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001284
Tim Petersfa26f7c2001-09-24 08:05:11 +00001285 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001286 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001287 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001288 else:
1289 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001290 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1291
Georg Brandl1a3284e2007-12-02 09:40:06 +00001292 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001293 attrs = inherited
1294 continue
1295 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001296 tag = "defined here"
1297 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001298 tag = "inherited from %s" % classname(thisclass,
1299 object.__module__)
Raymond Hettinger95801bb2015-08-18 22:25:16 -07001300
1301 sort_attributes(attrs, object)
Tim Peters28355492001-09-23 21:29:55 +00001302
1303 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001304 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001305 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001306 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001307 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001308 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001309 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001310 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1311 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001312 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1313 lambda t: t[1] == 'data')
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001314
Tim Peters28355492001-09-23 21:29:55 +00001315 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001316 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001317
1318 contents = '\n'.join(contents)
1319 if not contents:
1320 return title + '\n'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001321 return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001322
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001323 def formatvalue(self, object):
1324 """Format an argument default value as text."""
1325 return '=' + self.repr(object)
1326
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001327 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001328 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001329 realname = object.__name__
1330 name = name or realname
1331 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001332 skipdocs = 0
Larry Hastings24a882b2014-02-20 23:34:46 -08001333 if _is_bound_method(object):
Christian Heimesff737952007-11-27 10:40:20 +00001334 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001335 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001336 if imclass is not cl:
1337 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001338 else:
Christian Heimesff737952007-11-27 10:40:20 +00001339 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001340 note = ' method of %s instance' % classname(
Christian Heimesff737952007-11-27 10:40:20 +00001341 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001342 else:
1343 note = ' unbound %s method' % classname(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001344
1345 if name == realname:
1346 title = self.bold(realname)
1347 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001348 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001349 cl.__dict__[realname] is object):
1350 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001351 title = self.bold(name) + ' = ' + realname
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001352 argspec = None
Larry Hastings5c661892014-01-24 06:17:25 -08001353
1354 if inspect.isroutine(object):
1355 try:
1356 signature = inspect.signature(object)
1357 except (ValueError, TypeError):
1358 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001359 if signature:
1360 argspec = str(signature)
1361 if realname == '<lambda>':
1362 title = self.bold(name) + ' lambda '
1363 # XXX lambda's won't usually have func_annotations['return']
1364 # since the syntax doesn't support but it is possible.
1365 # So removing parentheses isn't truly safe.
1366 argspec = argspec[1:-1] # remove parentheses
1367 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +00001368 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001369 decl = title + argspec + note
1370
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001371 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001372 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001373 else:
1374 doc = getdoc(object) or ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001375 return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001376
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001377 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001378 results = []
1379 push = results.append
1380
1381 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001382 push(self.bold(name))
1383 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001384 doc = getdoc(value) or ''
1385 if doc:
1386 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001387 push('\n')
1388 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001389
1390 def docproperty(self, object, name=None, mod=None, cl=None):
1391 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001392 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001393
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001394 def docdata(self, object, name=None, mod=None, cl=None):
1395 """Produce text documentation for a data descriptor."""
1396 return self._docdescriptor(name, object, mod)
1397
Georg Brandl8b813db2005-10-01 16:32:31 +00001398 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001399 """Produce text documentation for a data object."""
1400 repr = self.repr(object)
1401 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001402 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001403 chop = maxlen - len(line)
1404 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001405 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001406 if doc is not None:
1407 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001408 return line
1409
Georg Brandld80d5f42010-12-03 07:47:22 +00001410class _PlainTextDoc(TextDoc):
1411 """Subclass of TextDoc which overrides string styling"""
1412 def bold(self, text):
1413 return text
1414
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001415# --------------------------------------------------------- user interfaces
1416
1417def pager(text):
1418 """The first time this is called, determine what kind of pager to use."""
1419 global pager
1420 pager = getpager()
1421 pager(text)
1422
1423def getpager():
1424 """Decide what method to use for paging through text."""
Benjamin Peterson159824e2014-06-07 20:14:26 -07001425 if not hasattr(sys.stdin, "isatty"):
1426 return plainpager
Guido van Rossuma01a8b62007-05-27 09:20:14 +00001427 if not hasattr(sys.stdout, "isatty"):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001428 return plainpager
1429 if not sys.stdin.isatty() or not sys.stdout.isatty():
1430 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001431 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001432 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001433 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001434 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001435 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001436 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001437 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001438 if os.environ.get('TERM') in ('dumb', 'emacs'):
1439 return plainpager
Jesus Cea4791a242012-10-05 03:15:39 +02001440 if sys.platform == 'win32':
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001441 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001442 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001443 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001444
1445 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001446 (fd, filename) = tempfile.mkstemp()
1447 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001448 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001449 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001450 return lambda text: pipepager(text, 'more')
1451 else:
1452 return ttypager
1453 finally:
1454 os.unlink(filename)
1455
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001456def plain(text):
1457 """Remove boldface formatting from text."""
1458 return re.sub('.\b', '', text)
1459
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001460def pipepager(text, cmd):
1461 """Page through text by feeding it to another program."""
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001462 import subprocess
1463 proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001464 try:
R David Murray1058cda2015-03-29 15:15:40 -04001465 with io.TextIOWrapper(proc.stdin, errors='backslashreplace') as pipe:
R David Murraye7f5e142015-03-30 10:14:47 -04001466 try:
1467 pipe.write(text)
1468 except KeyboardInterrupt:
1469 # We've hereby abandoned whatever text hasn't been written,
1470 # but the pager is still in control of the terminal.
1471 pass
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001472 except OSError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001473 pass # Ignore broken pipes caused by quitting the pager program.
R David Murray1058cda2015-03-29 15:15:40 -04001474 while True:
1475 try:
1476 proc.wait()
1477 break
1478 except KeyboardInterrupt:
1479 # Ignore ctl-c like the pager itself does. Otherwise the pager is
1480 # left running and the terminal is in raw mode and unusable.
1481 pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001482
1483def tempfilepager(text, cmd):
1484 """Page through text by invoking a program on a temporary file."""
1485 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001486 filename = tempfile.mktemp()
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001487 with open(filename, 'w', errors='backslashreplace') as file:
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +01001488 file.write(text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001489 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001490 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001491 finally:
1492 os.unlink(filename)
1493
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001494def _escape_stdout(text):
1495 # Escape non-encodable characters to avoid encoding errors later
1496 encoding = getattr(sys.stdout, 'encoding', None) or 'utf-8'
1497 return text.encode(encoding, 'backslashreplace').decode(encoding)
1498
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001499def ttypager(text):
1500 """Page through text on a text terminal."""
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001501 lines = plain(_escape_stdout(text)).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001502 try:
1503 import tty
1504 fd = sys.stdin.fileno()
1505 old = tty.tcgetattr(fd)
1506 tty.setcbreak(fd)
1507 getchar = lambda: sys.stdin.read(1)
Serhiy Storchakaab5e9b92014-11-28 00:09:29 +02001508 except (ImportError, AttributeError, io.UnsupportedOperation):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001509 tty = None
1510 getchar = lambda: sys.stdin.readline()[:-1][:1]
1511
1512 try:
Serhiy Storchakaab5e9b92014-11-28 00:09:29 +02001513 try:
1514 h = int(os.environ.get('LINES', 0))
1515 except ValueError:
1516 h = 0
1517 if h <= 1:
1518 h = 25
1519 r = inc = h - 1
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001520 sys.stdout.write('\n'.join(lines[:inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001521 while lines[r:]:
1522 sys.stdout.write('-- more --')
1523 sys.stdout.flush()
1524 c = getchar()
1525
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001526 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001527 sys.stdout.write('\r \r')
1528 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001529 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001530 sys.stdout.write('\r \r' + lines[r] + '\n')
1531 r = r + 1
1532 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001533 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001534 r = r - inc - inc
1535 if r < 0: r = 0
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001536 sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001537 r = r + inc
1538
1539 finally:
1540 if tty:
1541 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1542
1543def plainpager(text):
1544 """Simply print unformatted text. This is the ultimate fallback."""
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001545 sys.stdout.write(plain(_escape_stdout(text)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001546
1547def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001548 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001549 if inspect.ismodule(thing):
1550 if thing.__name__ in sys.builtin_module_names:
1551 return 'built-in module ' + thing.__name__
1552 if hasattr(thing, '__path__'):
1553 return 'package ' + thing.__name__
1554 else:
1555 return 'module ' + thing.__name__
1556 if inspect.isbuiltin(thing):
1557 return 'built-in function ' + thing.__name__
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001558 if inspect.isgetsetdescriptor(thing):
1559 return 'getset descriptor %s.%s.%s' % (
1560 thing.__objclass__.__module__, thing.__objclass__.__name__,
1561 thing.__name__)
1562 if inspect.ismemberdescriptor(thing):
1563 return 'member descriptor %s.%s.%s' % (
1564 thing.__objclass__.__module__, thing.__objclass__.__name__,
1565 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001566 if inspect.isclass(thing):
1567 return 'class ' + thing.__name__
1568 if inspect.isfunction(thing):
1569 return 'function ' + thing.__name__
1570 if inspect.ismethod(thing):
1571 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001572 return type(thing).__name__
1573
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001574def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001575 """Locate an object by name or dotted path, importing as necessary."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001576 parts = [part for part in path.split('.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001577 module, n = None, 0
1578 while n < len(parts):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001579 nextmodule = safeimport('.'.join(parts[:n+1]), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001580 if nextmodule: module, n = nextmodule, n + 1
1581 else: break
1582 if module:
1583 object = module
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001584 else:
Éric Araujoe64e51b2011-07-29 17:03:55 +02001585 object = builtins
1586 for part in parts[n:]:
1587 try:
1588 object = getattr(object, part)
1589 except AttributeError:
1590 return None
1591 return object
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001592
1593# --------------------------------------- interactive interpreter interface
1594
1595text = TextDoc()
Georg Brandld80d5f42010-12-03 07:47:22 +00001596plaintext = _PlainTextDoc()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001597html = HTMLDoc()
1598
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001599def resolve(thing, forceload=0):
1600 """Given an object or a path to an object, get the object and its name."""
1601 if isinstance(thing, str):
1602 object = locate(thing, forceload)
Serhiy Storchakab6076fb2015-04-21 21:09:48 +03001603 if object is None:
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001604 raise ImportError('''\
1605No Python documentation found for %r.
1606Use help() to get the interactive help utility.
1607Use help(str) for help on the str class.''' % thing)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001608 return object, thing
1609 else:
R David Murrayc43125a2012-04-23 13:23:57 -04001610 name = getattr(thing, '__name__', None)
1611 return thing, name if isinstance(name, str) else None
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001612
Georg Brandld80d5f42010-12-03 07:47:22 +00001613def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
1614 renderer=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001615 """Render text documentation, given an object or a path to an object."""
Georg Brandld80d5f42010-12-03 07:47:22 +00001616 if renderer is None:
1617 renderer = text
Guido van Rossumd8faa362007-04-27 19:54:29 +00001618 object, name = resolve(thing, forceload)
1619 desc = describe(object)
1620 module = inspect.getmodule(object)
1621 if name and '.' in name:
1622 desc += ' in ' + name[:name.rfind('.')]
1623 elif module and module is not object:
1624 desc += ' in module ' + module.__name__
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001625
1626 if not (inspect.ismodule(object) or
Guido van Rossumd8faa362007-04-27 19:54:29 +00001627 inspect.isclass(object) or
1628 inspect.isroutine(object) or
1629 inspect.isgetsetdescriptor(object) or
1630 inspect.ismemberdescriptor(object) or
1631 isinstance(object, property)):
1632 # If the passed object is a piece of data or an instance,
1633 # document its available methods instead of its value.
1634 object = type(object)
1635 desc += ' object'
Georg Brandld80d5f42010-12-03 07:47:22 +00001636 return title % desc + '\n\n' + renderer.document(object, name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001637
Georg Brandld80d5f42010-12-03 07:47:22 +00001638def doc(thing, title='Python Library Documentation: %s', forceload=0,
1639 output=None):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001640 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001641 try:
Georg Brandld80d5f42010-12-03 07:47:22 +00001642 if output is None:
1643 pager(render_doc(thing, title, forceload))
1644 else:
1645 output.write(render_doc(thing, title, forceload, plaintext))
Guido van Rossumb940e112007-01-10 16:19:56 +00001646 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001647 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001648
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001649def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001650 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001651 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001652 object, name = resolve(thing, forceload)
1653 page = html.page(describe(object), html.document(object, name))
Serhiy Storchaka46ba6c82015-04-04 11:01:02 +03001654 with open(name + '.html', 'w', encoding='utf-8') as file:
1655 file.write(page)
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001656 print('wrote', name + '.html')
Guido van Rossumb940e112007-01-10 16:19:56 +00001657 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001658 print(value)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001659
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001660def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001661 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001662 if done is None: done = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001663 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1664 writedoc(modname)
1665 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001666
1667class Helper:
Georg Brandl6b38daa2008-06-01 21:05:17 +00001668
1669 # These dictionaries map a topic name to either an alias, or a tuple
1670 # (label, seealso-items). The "label" is the label of the corresponding
1671 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl5617db82009-04-27 16:28:57 +00001672 # in pydoc_data/topics.py.
Georg Brandl6b38daa2008-06-01 21:05:17 +00001673 #
1674 # CAUTION: if you change one of these dictionaries, be sure to adapt the
Georg Brandl61bd1dc2014-09-30 22:56:38 +02001675 # list of needed labels in Doc/tools/pyspecific.py and
Georg Brandl5617db82009-04-27 16:28:57 +00001676 # regenerate the pydoc_data/topics.py file by running
Georg Brandl6b38daa2008-06-01 21:05:17 +00001677 # make pydoc-topics
1678 # in Doc/ and copying the output file into the Lib/ directory.
1679
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001680 keywords = {
Ezio Melottib185a042011-04-28 07:42:55 +03001681 'False': '',
1682 'None': '',
1683 'True': '',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001684 'and': 'BOOLEAN',
Guido van Rossumd8faa362007-04-27 19:54:29 +00001685 'as': 'with',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001686 'assert': ('assert', ''),
1687 'break': ('break', 'while for'),
1688 'class': ('class', 'CLASSES SPECIALMETHODS'),
1689 'continue': ('continue', 'while for'),
1690 'def': ('function', ''),
1691 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001692 'elif': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001693 'else': ('else', 'while for'),
Georg Brandl0d855392008-08-30 19:53:05 +00001694 'except': 'try',
1695 'finally': 'try',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001696 'for': ('for', 'break continue while'),
Georg Brandl0d855392008-08-30 19:53:05 +00001697 'from': 'import',
Georg Brandl74abf6f2010-11-20 19:54:36 +00001698 'global': ('global', 'nonlocal NAMESPACES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001699 'if': ('if', 'TRUTHVALUE'),
1700 'import': ('import', 'MODULES'),
Georg Brandl395ed242009-09-04 08:07:32 +00001701 'in': ('in', 'SEQUENCEMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001702 'is': 'COMPARISON',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001703 'lambda': ('lambda', 'FUNCTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001704 'nonlocal': ('nonlocal', 'global NAMESPACES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001705 'not': 'BOOLEAN',
1706 'or': 'BOOLEAN',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001707 'pass': ('pass', ''),
1708 'raise': ('raise', 'EXCEPTIONS'),
1709 'return': ('return', 'FUNCTIONS'),
1710 'try': ('try', 'EXCEPTIONS'),
1711 'while': ('while', 'break continue if TRUTHVALUE'),
1712 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1713 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001714 }
Georg Brandldb7b6b92009-01-01 15:53:14 +00001715 # Either add symbols to this dictionary or to the symbols dictionary
1716 # directly: Whichever is easier. They are merged later.
1717 _symbols_inverse = {
1718 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'),
1719 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1720 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1721 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1722 'UNARY' : ('-', '~'),
1723 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1724 '^=', '<<=', '>>=', '**=', '//='),
1725 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1726 'COMPLEX' : ('j', 'J')
1727 }
1728 symbols = {
1729 '%': 'OPERATORS FORMATTING',
1730 '**': 'POWER',
1731 ',': 'TUPLES LISTS FUNCTIONS',
1732 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1733 '...': 'ELLIPSIS',
1734 ':': 'SLICINGS DICTIONARYLITERALS',
1735 '@': 'def class',
1736 '\\': 'STRINGS',
1737 '_': 'PRIVATENAMES',
1738 '__': 'PRIVATENAMES SPECIALMETHODS',
1739 '`': 'BACKQUOTES',
1740 '(': 'TUPLES FUNCTIONS CALLS',
1741 ')': 'TUPLES FUNCTIONS CALLS',
1742 '[': 'LISTS SUBSCRIPTS SLICINGS',
1743 ']': 'LISTS SUBSCRIPTS SLICINGS'
1744 }
1745 for topic, symbols_ in _symbols_inverse.items():
1746 for symbol in symbols_:
1747 topics = symbols.get(symbol, topic)
1748 if topic not in topics:
1749 topics = topics + ' ' + topic
1750 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001751
1752 topics = {
Georg Brandl6b38daa2008-06-01 21:05:17 +00001753 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1754 'FUNCTIONS CLASSES MODULES FILES inspect'),
1755 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS '
1756 'FORMATTING TYPES'),
1757 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1758 'FORMATTING': ('formatstrings', 'OPERATORS'),
1759 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1760 'FORMATTING TYPES'),
1761 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1762 'INTEGER': ('integers', 'int range'),
1763 'FLOAT': ('floating', 'float math'),
1764 'COMPLEX': ('imaginary', 'complex cmath'),
1765 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING range LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001766 'MAPPINGS': 'DICTIONARIES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001767 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1768 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1769 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1770 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001771 'FRAMEOBJECTS': 'TYPES',
1772 'TRACEBACKS': 'TYPES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001773 'NONE': ('bltin-null-object', ''),
1774 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001775 'SPECIALATTRIBUTES': ('specialattrs', ''),
1776 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1777 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001778 'PACKAGES': 'import',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001779 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1780 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1781 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1782 'LISTS DICTIONARIES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001783 'OPERATORS': 'EXPRESSIONS',
1784 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001785 'OBJECTS': ('objects', 'TYPES'),
1786 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
Georg Brandl395ed242009-09-04 08:07:32 +00001787 'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS '
1788 'NUMBERMETHODS CLASSES'),
Mark Dickinsona56c4672009-01-27 18:17:45 +00001789 'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001790 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1791 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001792 'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS '
Georg Brandl6b38daa2008-06-01 21:05:17 +00001793 'SPECIALMETHODS'),
1794 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1795 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1796 'SPECIALMETHODS'),
1797 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001798 'NAMESPACES': ('naming', 'global nonlocal ASSIGNMENT DELETION DYNAMICFEATURES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001799 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001800 'SCOPING': 'NAMESPACES',
1801 'FRAMES': 'NAMESPACES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001802 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1803 'CONVERSIONS': ('conversions', ''),
1804 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1805 'SPECIALIDENTIFIERS': ('id-classes', ''),
1806 'PRIVATENAMES': ('atom-identifiers', ''),
1807 'LITERALS': ('atom-literals', 'STRINGS NUMBERS TUPLELITERALS '
1808 'LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001809 'TUPLES': 'SEQUENCES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001810 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1811 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1812 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1813 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1814 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1815 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001816 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'),
1817 'SLICINGS': ('slicings', 'SEQUENCEMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001818 'CALLS': ('calls', 'EXPRESSIONS'),
1819 'POWER': ('power', 'EXPRESSIONS'),
1820 'UNARY': ('unary', 'EXPRESSIONS'),
1821 'BINARY': ('binary', 'EXPRESSIONS'),
1822 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1823 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1824 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1825 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001826 'ASSERTION': 'assert',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001827 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1828 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001829 'DELETION': 'del',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001830 'RETURNING': 'return',
1831 'IMPORTING': 'import',
1832 'CONDITIONAL': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001833 'LOOPING': ('compound', 'for while break continue'),
1834 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1835 'DEBUGGING': ('debugger', 'pdb'),
1836 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001837 }
1838
Georg Brandl78aa3962010-07-31 21:51:48 +00001839 def __init__(self, input=None, output=None):
1840 self._input = input
1841 self._output = output
1842
Georg Brandl76ae3972010-08-01 06:32:55 +00001843 input = property(lambda self: self._input or sys.stdin)
1844 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001845
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001846 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001847 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001848 self()
1849 return ''
Serhiy Storchaka465e60e2014-07-25 23:36:00 +03001850 return '<%s.%s instance>' % (self.__class__.__module__,
1851 self.__class__.__qualname__)
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001852
Alexander Belopolsky2e733c92010-07-04 17:00:20 +00001853 _GoInteractive = object()
1854 def __call__(self, request=_GoInteractive):
1855 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001856 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001857 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001858 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001859 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001860 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001861You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001862If you want to ask for help on a particular object directly from the
1863interpreter, you can type "help(object)". Executing "help('string')"
1864has the same effect as typing a particular string at the help> prompt.
1865''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001866
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001867 def interact(self):
1868 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001869 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001870 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001871 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001872 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001873 except (KeyboardInterrupt, EOFError):
1874 break
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001875 request = replace(request, '"', '', "'", '').strip()
1876 if request.lower() in ('q', 'quit'): break
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001877 if request == 'help':
1878 self.intro()
1879 else:
1880 self.help(request)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001881
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001882 def getline(self, prompt):
Guido van Rossum7c086c02008-01-02 03:52:38 +00001883 """Read one line, using input() when appropriate."""
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001884 if self.input is sys.stdin:
Guido van Rossum7c086c02008-01-02 03:52:38 +00001885 return input(prompt)
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001886 else:
1887 self.output.write(prompt)
1888 self.output.flush()
1889 return self.input.readline()
1890
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001891 def help(self, request):
1892 if type(request) is type(''):
R. David Murray1f1b9d32009-05-27 20:56:59 +00001893 request = request.strip()
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001894 if request == 'keywords': self.listkeywords()
Georg Brandldb7b6b92009-01-01 15:53:14 +00001895 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001896 elif request == 'topics': self.listtopics()
1897 elif request == 'modules': self.listmodules()
1898 elif request[:8] == 'modules ':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001899 self.listmodules(request.split()[1])
Georg Brandldb7b6b92009-01-01 15:53:14 +00001900 elif request in self.symbols: self.showsymbol(request)
Ezio Melottib185a042011-04-28 07:42:55 +03001901 elif request in ['True', 'False', 'None']:
1902 # special case these keywords since they are objects too
1903 doc(eval(request), 'Help on %s:')
Raymond Hettinger54f02222002-06-01 14:18:47 +00001904 elif request in self.keywords: self.showtopic(request)
1905 elif request in self.topics: self.showtopic(request)
Georg Brandld80d5f42010-12-03 07:47:22 +00001906 elif request: doc(request, 'Help on %s:', output=self._output)
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001907 else: doc(str, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001908 elif isinstance(request, Helper): self()
Georg Brandld80d5f42010-12-03 07:47:22 +00001909 else: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001910 self.output.write('\n')
1911
1912 def intro(self):
1913 self.output.write('''
R David Murray3d050dd2014-04-19 12:59:30 -04001914Welcome to Python %s's help utility!
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001915
1916If this is your first time using Python, you should definitely check out
R David Murrayde0f6292012-03-31 12:06:35 -04001917the tutorial on the Internet at http://docs.python.org/%s/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001918
1919Enter the name of any module, keyword, or topic to get help on writing
1920Python programs and using Python modules. To quit this help utility and
1921return to the interpreter, just type "quit".
1922
Terry Jan Reedy34200572013-02-11 02:23:13 -05001923To get a list of available modules, keywords, symbols, or topics, type
1924"modules", "keywords", "symbols", or "topics". Each module also comes
1925with a one-line summary of what it does; to list the modules whose name
1926or summary contain a given string such as "spam", type "modules spam".
R David Murrayde0f6292012-03-31 12:06:35 -04001927''' % tuple([sys.version[:3]]*2))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001928
1929 def list(self, items, columns=4, width=80):
Guido van Rossum486364b2007-06-30 05:01:58 +00001930 items = list(sorted(items))
1931 colw = width // columns
1932 rows = (len(items) + columns - 1) // columns
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001933 for row in range(rows):
1934 for col in range(columns):
1935 i = col * rows + row
1936 if i < len(items):
1937 self.output.write(items[i])
1938 if col < columns - 1:
Guido van Rossum486364b2007-06-30 05:01:58 +00001939 self.output.write(' ' + ' ' * (colw - 1 - len(items[i])))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001940 self.output.write('\n')
1941
1942 def listkeywords(self):
1943 self.output.write('''
1944Here is a list of the Python keywords. Enter any keyword to get more help.
1945
1946''')
1947 self.list(self.keywords.keys())
1948
Georg Brandldb7b6b92009-01-01 15:53:14 +00001949 def listsymbols(self):
1950 self.output.write('''
1951Here is a list of the punctuation symbols which Python assigns special meaning
1952to. Enter any symbol to get more help.
1953
1954''')
1955 self.list(self.symbols.keys())
1956
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001957 def listtopics(self):
1958 self.output.write('''
1959Here is a list of available topics. Enter any topic name to get more help.
1960
1961''')
1962 self.list(self.topics.keys())
1963
Georg Brandldb7b6b92009-01-01 15:53:14 +00001964 def showtopic(self, topic, more_xrefs=''):
Georg Brandl6b38daa2008-06-01 21:05:17 +00001965 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001966 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04001967 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001968 self.output.write('''
Georg Brandl6b38daa2008-06-01 21:05:17 +00001969Sorry, topic and keyword documentation is not available because the
Georg Brandl5617db82009-04-27 16:28:57 +00001970module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001971''')
1972 return
1973 target = self.topics.get(topic, self.keywords.get(topic))
1974 if not target:
1975 self.output.write('no documentation found for %s\n' % repr(topic))
1976 return
1977 if type(target) is type(''):
Georg Brandldb7b6b92009-01-01 15:53:14 +00001978 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001979
Georg Brandl6b38daa2008-06-01 21:05:17 +00001980 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001981 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001982 doc = pydoc_data.topics.topics[label]
Georg Brandl6b38daa2008-06-01 21:05:17 +00001983 except KeyError:
1984 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001985 return
Georg Brandl6b38daa2008-06-01 21:05:17 +00001986 pager(doc.strip() + '\n')
Georg Brandldb7b6b92009-01-01 15:53:14 +00001987 if more_xrefs:
1988 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001989 if xrefs:
Brett Cannon1448ecf2013-10-04 11:38:59 -04001990 import textwrap
1991 text = 'Related help topics: ' + ', '.join(xrefs.split()) + '\n'
1992 wrapped_text = textwrap.wrap(text, 72)
1993 self.output.write('\n%s\n' % ''.join(wrapped_text))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001994
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001995 def _gettopic(self, topic, more_xrefs=''):
1996 """Return unbuffered tuple of (topic, xrefs).
1997
Georg Brandld2f38572011-01-30 08:37:19 +00001998 If an error occurs here, the exception is caught and displayed by
1999 the url handler.
2000
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002001 This function duplicates the showtopic method but returns its
2002 result directly so it can be formatted for display in an html page.
2003 """
2004 try:
2005 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04002006 except ImportError:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002007 return('''
2008Sorry, topic and keyword documentation is not available because the
2009module "pydoc_data.topics" could not be found.
2010''' , '')
2011 target = self.topics.get(topic, self.keywords.get(topic))
2012 if not target:
Georg Brandld2f38572011-01-30 08:37:19 +00002013 raise ValueError('could not find topic')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002014 if isinstance(target, str):
2015 return self._gettopic(target, more_xrefs)
2016 label, xrefs = target
Georg Brandld2f38572011-01-30 08:37:19 +00002017 doc = pydoc_data.topics.topics[label]
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002018 if more_xrefs:
2019 xrefs = (xrefs or '') + ' ' + more_xrefs
2020 return doc, xrefs
2021
Georg Brandldb7b6b92009-01-01 15:53:14 +00002022 def showsymbol(self, symbol):
2023 target = self.symbols[symbol]
2024 topic, _, xrefs = target.partition(' ')
2025 self.showtopic(topic, xrefs)
2026
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002027 def listmodules(self, key=''):
2028 if key:
2029 self.output.write('''
Terry Jan Reedy34200572013-02-11 02:23:13 -05002030Here is a list of modules whose name or summary contains '{}'.
2031If there are any, enter a module name to get more help.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002032
Terry Jan Reedy34200572013-02-11 02:23:13 -05002033'''.format(key))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002034 apropos(key)
2035 else:
2036 self.output.write('''
2037Please wait a moment while I gather a list of all available modules...
2038
2039''')
2040 modules = {}
2041 def callback(path, modname, desc, modules=modules):
2042 if modname and modname[-9:] == '.__init__':
2043 modname = modname[:-9] + ' (package)'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002044 if modname.find('.') < 0:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002045 modules[modname] = 1
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002046 def onerror(modname):
2047 callback(None, modname, None)
2048 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002049 self.list(modules.keys())
2050 self.output.write('''
2051Enter any module name to get more help. Or, type "modules spam" to search
Terry Jan Reedy34200572013-02-11 02:23:13 -05002052for modules whose name or summary contain the string "spam".
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002053''')
2054
Georg Brandl78aa3962010-07-31 21:51:48 +00002055help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002056
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002057class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002058 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002059
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002060 def run(self, callback, key=None, completer=None, onerror=None):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002061 if key: key = key.lower()
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002062 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002063 seen = {}
2064
2065 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002066 if modname != '__main__':
2067 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00002068 if key is None:
2069 callback(None, modname, '')
2070 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002071 name = __import__(modname).__doc__ or ''
2072 desc = name.split('\n')[0]
2073 name = modname + ' - ' + desc
2074 if name.lower().find(key) >= 0:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002075 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002076
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002077 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002078 if self.quit:
2079 break
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002080
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002081 if key is None:
2082 callback(None, modname, '')
2083 else:
Georg Brandl126c8792009-04-05 15:05:48 +00002084 try:
Eric Snow3a62d142014-01-06 20:42:59 -07002085 spec = pkgutil._get_spec(importer, modname)
Georg Brandl126c8792009-04-05 15:05:48 +00002086 except SyntaxError:
2087 # raised by tests for bad coding cookies or BOM
2088 continue
Eric Snow3a62d142014-01-06 20:42:59 -07002089 loader = spec.loader
Georg Brandl126c8792009-04-05 15:05:48 +00002090 if hasattr(loader, 'get_source'):
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002091 try:
2092 source = loader.get_source(modname)
Nick Coghlan2824cb52012-07-15 22:12:14 +10002093 except Exception:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002094 if onerror:
2095 onerror(modname)
2096 continue
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002097 desc = source_synopsis(io.StringIO(source)) or ''
Georg Brandl126c8792009-04-05 15:05:48 +00002098 if hasattr(loader, 'get_filename'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002099 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002100 else:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002101 path = None
2102 else:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002103 try:
Brett Cannon2a17bde2014-05-30 14:55:29 -04002104 module = importlib._bootstrap._load(spec)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002105 except ImportError:
2106 if onerror:
2107 onerror(modname)
2108 continue
Benjamin Peterson54237f92015-02-16 19:45:01 -05002109 desc = module.__doc__.splitlines()[0] if module.__doc__ else ''
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002110 path = getattr(module,'__file__',None)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002111 name = modname + ' - ' + desc
2112 if name.lower().find(key) >= 0:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002113 callback(path, modname, desc)
2114
2115 if completer:
2116 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002117
2118def apropos(key):
2119 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002120 def callback(path, modname, desc):
2121 if modname[-9:] == '.__init__':
2122 modname = modname[:-9] + ' (package)'
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002123 print(modname, desc and '- ' + desc)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002124 def onerror(modname):
2125 pass
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002126 with warnings.catch_warnings():
2127 warnings.filterwarnings('ignore') # ignore problems during import
2128 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002129
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002130# --------------------------------------- enhanced Web browser interface
2131
2132def _start_server(urlhandler, port):
2133 """Start an HTTP server thread on a specific port.
2134
2135 Start an HTML/text server thread, so HTML or text documents can be
2136 browsed dynamically and interactively with a Web browser. Example use:
2137
2138 >>> import time
2139 >>> import pydoc
2140
2141 Define a URL handler. To determine what the client is asking
2142 for, check the URL and content_type.
2143
2144 Then get or generate some text or HTML code and return it.
2145
2146 >>> def my_url_handler(url, content_type):
2147 ... text = 'the URL sent was: (%s, %s)' % (url, content_type)
2148 ... return text
2149
2150 Start server thread on port 0.
2151 If you use port 0, the server will pick a random port number.
2152 You can then use serverthread.port to get the port number.
2153
2154 >>> port = 0
2155 >>> serverthread = pydoc._start_server(my_url_handler, port)
2156
2157 Check that the server is really started. If it is, open browser
2158 and get first page. Use serverthread.url as the starting page.
2159
2160 >>> if serverthread.serving:
2161 ... import webbrowser
2162
2163 The next two lines are commented out so a browser doesn't open if
2164 doctest is run on this module.
2165
2166 #... webbrowser.open(serverthread.url)
2167 #True
2168
2169 Let the server do its thing. We just need to monitor its status.
2170 Use time.sleep so the loop doesn't hog the CPU.
2171
2172 >>> starttime = time.time()
2173 >>> timeout = 1 #seconds
2174
2175 This is a short timeout for testing purposes.
2176
2177 >>> while serverthread.serving:
2178 ... time.sleep(.01)
2179 ... if serverthread.serving and time.time() - starttime > timeout:
2180 ... serverthread.stop()
2181 ... break
2182
2183 Print any errors that may have occurred.
2184
2185 >>> print(serverthread.error)
2186 None
2187 """
2188 import http.server
2189 import email.message
2190 import select
2191 import threading
2192
2193 class DocHandler(http.server.BaseHTTPRequestHandler):
2194
2195 def do_GET(self):
2196 """Process a request from an HTML browser.
2197
2198 The URL received is in self.path.
2199 Get an HTML page from self.urlhandler and send it.
2200 """
2201 if self.path.endswith('.css'):
2202 content_type = 'text/css'
2203 else:
2204 content_type = 'text/html'
2205 self.send_response(200)
Georg Brandld2f38572011-01-30 08:37:19 +00002206 self.send_header('Content-Type', '%s; charset=UTF-8' % content_type)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002207 self.end_headers()
2208 self.wfile.write(self.urlhandler(
2209 self.path, content_type).encode('utf-8'))
2210
2211 def log_message(self, *args):
2212 # Don't log messages.
2213 pass
2214
2215 class DocServer(http.server.HTTPServer):
2216
2217 def __init__(self, port, callback):
Senthil Kumaran2a42a0b2014-09-17 13:17:58 +08002218 self.host = 'localhost'
2219 self.address = (self.host, port)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002220 self.callback = callback
2221 self.base.__init__(self, self.address, self.handler)
2222 self.quit = False
2223
2224 def serve_until_quit(self):
2225 while not self.quit:
2226 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2227 if rd:
2228 self.handle_request()
Victor Stinnera3abd1d2011-01-03 16:12:39 +00002229 self.server_close()
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002230
2231 def server_activate(self):
2232 self.base.server_activate(self)
2233 if self.callback:
2234 self.callback(self)
2235
2236 class ServerThread(threading.Thread):
2237
2238 def __init__(self, urlhandler, port):
2239 self.urlhandler = urlhandler
2240 self.port = int(port)
2241 threading.Thread.__init__(self)
2242 self.serving = False
2243 self.error = None
2244
2245 def run(self):
2246 """Start the server."""
2247 try:
2248 DocServer.base = http.server.HTTPServer
2249 DocServer.handler = DocHandler
2250 DocHandler.MessageClass = email.message.Message
2251 DocHandler.urlhandler = staticmethod(self.urlhandler)
2252 docsvr = DocServer(self.port, self.ready)
2253 self.docserver = docsvr
2254 docsvr.serve_until_quit()
2255 except Exception as e:
2256 self.error = e
2257
2258 def ready(self, server):
2259 self.serving = True
2260 self.host = server.host
2261 self.port = server.server_port
2262 self.url = 'http://%s:%d/' % (self.host, self.port)
2263
2264 def stop(self):
2265 """Stop the server and this thread nicely"""
2266 self.docserver.quit = True
2267 self.serving = False
2268 self.url = None
2269
2270 thread = ServerThread(urlhandler, port)
2271 thread.start()
2272 # Wait until thread.serving is True to make sure we are
2273 # really up before returning.
2274 while not thread.error and not thread.serving:
2275 time.sleep(.01)
2276 return thread
2277
2278
2279def _url_handler(url, content_type="text/html"):
2280 """The pydoc url handler for use with the pydoc server.
2281
2282 If the content_type is 'text/css', the _pydoc.css style
2283 sheet is read and returned if it exits.
2284
2285 If the content_type is 'text/html', then the result of
2286 get_html_page(url) is returned.
2287 """
2288 class _HTMLDoc(HTMLDoc):
2289
2290 def page(self, title, contents):
2291 """Format an HTML page."""
2292 css_path = "pydoc_data/_pydoc.css"
2293 css_link = (
2294 '<link rel="stylesheet" type="text/css" href="%s">' %
2295 css_path)
2296 return '''\
2297<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Georg Brandld2f38572011-01-30 08:37:19 +00002298<html><head><title>Pydoc: %s</title>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002299<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Georg Brandld2f38572011-01-30 08:37:19 +00002300%s</head><body bgcolor="#f0f0f8">%s<div style="clear:both;padding-top:.5em;">%s</div>
2301</body></html>''' % (title, css_link, html_navbar(), contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002302
2303 def filelink(self, url, path):
2304 return '<a href="getfile?key=%s">%s</a>' % (url, path)
2305
2306
2307 html = _HTMLDoc()
2308
2309 def html_navbar():
Georg Brandld2f38572011-01-30 08:37:19 +00002310 version = html.escape("%s [%s, %s]" % (platform.python_version(),
2311 platform.python_build()[0],
2312 platform.python_compiler()))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002313 return """
2314 <div style='float:left'>
Georg Brandld2f38572011-01-30 08:37:19 +00002315 Python %s<br>%s
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002316 </div>
2317 <div style='float:right'>
2318 <div style='text-align:center'>
2319 <a href="index.html">Module Index</a>
2320 : <a href="topics.html">Topics</a>
2321 : <a href="keywords.html">Keywords</a>
2322 </div>
2323 <div>
Georg Brandld2f38572011-01-30 08:37:19 +00002324 <form action="get" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002325 <input type=text name=key size=15>
2326 <input type=submit value="Get">
Georg Brandld2f38572011-01-30 08:37:19 +00002327 </form>&nbsp;
2328 <form action="search" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002329 <input type=text name=key size=15>
2330 <input type=submit value="Search">
2331 </form>
2332 </div>
2333 </div>
Georg Brandld2f38572011-01-30 08:37:19 +00002334 """ % (version, html.escape(platform.platform(terse=True)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002335
2336 def html_index():
2337 """Module Index page."""
2338
2339 def bltinlink(name):
2340 return '<a href="%s.html">%s</a>' % (name, name)
2341
2342 heading = html.heading(
2343 '<big><big><strong>Index of Modules</strong></big></big>',
2344 '#ffffff', '#7799ee')
2345 names = [name for name in sys.builtin_module_names
2346 if name != '__main__']
2347 contents = html.multicolumn(names, bltinlink)
2348 contents = [heading, '<p>' + html.bigsection(
2349 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2350
2351 seen = {}
2352 for dir in sys.path:
2353 contents.append(html.index(dir, seen))
2354
2355 contents.append(
2356 '<p align=right><font color="#909090" face="helvetica,'
2357 'arial"><strong>pydoc</strong> by Ka-Ping Yee'
2358 '&lt;ping@lfw.org&gt;</font>')
Nick Coghlanecace282010-12-03 16:08:46 +00002359 return 'Index of Modules', ''.join(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002360
2361 def html_search(key):
2362 """Search results page."""
2363 # scan for modules
2364 search_result = []
2365
2366 def callback(path, modname, desc):
2367 if modname[-9:] == '.__init__':
2368 modname = modname[:-9] + ' (package)'
2369 search_result.append((modname, desc and '- ' + desc))
2370
2371 with warnings.catch_warnings():
2372 warnings.filterwarnings('ignore') # ignore problems during import
2373 ModuleScanner().run(callback, key)
2374
2375 # format page
2376 def bltinlink(name):
2377 return '<a href="%s.html">%s</a>' % (name, name)
2378
2379 results = []
2380 heading = html.heading(
2381 '<big><big><strong>Search Results</strong></big></big>',
2382 '#ffffff', '#7799ee')
2383 for name, desc in search_result:
2384 results.append(bltinlink(name) + desc)
2385 contents = heading + html.bigsection(
2386 'key = %s' % key, '#ffffff', '#ee77aa', '<br>'.join(results))
Nick Coghlanecace282010-12-03 16:08:46 +00002387 return 'Search Results', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002388
2389 def html_getfile(path):
2390 """Get and display a source file listing safely."""
Zachary Wareeb432142014-07-10 11:18:00 -05002391 path = urllib.parse.unquote(path)
Victor Stinner91e08772011-07-05 14:30:41 +02002392 with tokenize.open(path) as fp:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002393 lines = html.escape(fp.read())
2394 body = '<pre>%s</pre>' % lines
2395 heading = html.heading(
2396 '<big><big><strong>File Listing</strong></big></big>',
2397 '#ffffff', '#7799ee')
2398 contents = heading + html.bigsection(
2399 'File: %s' % path, '#ffffff', '#ee77aa', body)
Nick Coghlanecace282010-12-03 16:08:46 +00002400 return 'getfile %s' % path, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002401
2402 def html_topics():
2403 """Index of topic texts available."""
2404
2405 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002406 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002407
2408 heading = html.heading(
2409 '<big><big><strong>INDEX</strong></big></big>',
2410 '#ffffff', '#7799ee')
2411 names = sorted(Helper.topics.keys())
2412
2413 contents = html.multicolumn(names, bltinlink)
2414 contents = heading + html.bigsection(
2415 'Topics', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002416 return 'Topics', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002417
2418 def html_keywords():
2419 """Index of keywords."""
2420 heading = html.heading(
2421 '<big><big><strong>INDEX</strong></big></big>',
2422 '#ffffff', '#7799ee')
2423 names = sorted(Helper.keywords.keys())
2424
2425 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002426 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002427
2428 contents = html.multicolumn(names, bltinlink)
2429 contents = heading + html.bigsection(
2430 'Keywords', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002431 return 'Keywords', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002432
2433 def html_topicpage(topic):
2434 """Topic or keyword help page."""
2435 buf = io.StringIO()
2436 htmlhelp = Helper(buf, buf)
2437 contents, xrefs = htmlhelp._gettopic(topic)
2438 if topic in htmlhelp.keywords:
2439 title = 'KEYWORD'
2440 else:
2441 title = 'TOPIC'
2442 heading = html.heading(
2443 '<big><big><strong>%s</strong></big></big>' % title,
2444 '#ffffff', '#7799ee')
Georg Brandld2f38572011-01-30 08:37:19 +00002445 contents = '<pre>%s</pre>' % html.markup(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002446 contents = html.bigsection(topic , '#ffffff','#ee77aa', contents)
Georg Brandld2f38572011-01-30 08:37:19 +00002447 if xrefs:
2448 xrefs = sorted(xrefs.split())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002449
Georg Brandld2f38572011-01-30 08:37:19 +00002450 def bltinlink(name):
2451 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002452
Georg Brandld2f38572011-01-30 08:37:19 +00002453 xrefs = html.multicolumn(xrefs, bltinlink)
2454 xrefs = html.section('Related help topics: ',
2455 '#ffffff', '#ee77aa', xrefs)
Nick Coghlanecace282010-12-03 16:08:46 +00002456 return ('%s %s' % (title, topic),
2457 ''.join((heading, contents, xrefs)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002458
Georg Brandld2f38572011-01-30 08:37:19 +00002459 def html_getobj(url):
2460 obj = locate(url, forceload=1)
2461 if obj is None and url != 'None':
2462 raise ValueError('could not find object')
2463 title = describe(obj)
2464 content = html.document(obj, url)
2465 return title, content
2466
2467 def html_error(url, exc):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002468 heading = html.heading(
2469 '<big><big><strong>Error</strong></big></big>',
Georg Brandld2f38572011-01-30 08:37:19 +00002470 '#ffffff', '#7799ee')
2471 contents = '<br>'.join(html.escape(line) for line in
2472 format_exception_only(type(exc), exc))
2473 contents = heading + html.bigsection(url, '#ffffff', '#bb0000',
2474 contents)
2475 return "Error - %s" % url, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002476
2477 def get_html_page(url):
2478 """Generate an HTML page for url."""
Georg Brandld2f38572011-01-30 08:37:19 +00002479 complete_url = url
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002480 if url.endswith('.html'):
2481 url = url[:-5]
Georg Brandld2f38572011-01-30 08:37:19 +00002482 try:
2483 if url in ("", "index"):
2484 title, content = html_index()
2485 elif url == "topics":
2486 title, content = html_topics()
2487 elif url == "keywords":
2488 title, content = html_keywords()
2489 elif '=' in url:
2490 op, _, url = url.partition('=')
2491 if op == "search?key":
2492 title, content = html_search(url)
2493 elif op == "getfile?key":
2494 title, content = html_getfile(url)
2495 elif op == "topic?key":
2496 # try topics first, then objects.
2497 try:
2498 title, content = html_topicpage(url)
2499 except ValueError:
2500 title, content = html_getobj(url)
2501 elif op == "get?key":
2502 # try objects first, then topics.
2503 if url in ("", "index"):
2504 title, content = html_index()
2505 else:
2506 try:
2507 title, content = html_getobj(url)
2508 except ValueError:
2509 title, content = html_topicpage(url)
2510 else:
2511 raise ValueError('bad pydoc url')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002512 else:
Georg Brandld2f38572011-01-30 08:37:19 +00002513 title, content = html_getobj(url)
2514 except Exception as exc:
2515 # Catch any errors and display them in an error page.
2516 title, content = html_error(complete_url, exc)
2517 return html.page(title, content)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002518
2519 if url.startswith('/'):
2520 url = url[1:]
2521 if content_type == 'text/css':
2522 path_here = os.path.dirname(os.path.realpath(__file__))
Georg Brandld2f38572011-01-30 08:37:19 +00002523 css_path = os.path.join(path_here, url)
2524 with open(css_path) as fp:
2525 return ''.join(fp.readlines())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002526 elif content_type == 'text/html':
2527 return get_html_page(url)
Georg Brandld2f38572011-01-30 08:37:19 +00002528 # Errors outside the url handler are caught by the server.
2529 raise TypeError('unknown content type %r for url %s' % (content_type, url))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002530
2531
2532def browse(port=0, *, open_browser=True):
2533 """Start the enhanced pydoc Web server and open a Web browser.
2534
2535 Use port '0' to start the server on an arbitrary port.
2536 Set open_browser to False to suppress opening a browser.
2537 """
2538 import webbrowser
2539 serverthread = _start_server(_url_handler, port)
2540 if serverthread.error:
2541 print(serverthread.error)
2542 return
2543 if serverthread.serving:
2544 server_help_msg = 'Server commands: [b]rowser, [q]uit'
2545 if open_browser:
2546 webbrowser.open(serverthread.url)
2547 try:
2548 print('Server ready at', serverthread.url)
2549 print(server_help_msg)
2550 while serverthread.serving:
2551 cmd = input('server> ')
2552 cmd = cmd.lower()
2553 if cmd == 'q':
2554 break
2555 elif cmd == 'b':
2556 webbrowser.open(serverthread.url)
2557 else:
2558 print(server_help_msg)
2559 except (KeyboardInterrupt, EOFError):
2560 print()
2561 finally:
2562 if serverthread.serving:
2563 serverthread.stop()
2564 print('Server stopped')
2565
2566
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002567# -------------------------------------------------- command-line interface
2568
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002569def ispath(x):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002570 return isinstance(x, str) and x.find(os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002571
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002572def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002573 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002574 import getopt
Guido van Rossum756aa932007-04-07 03:04:01 +00002575 class BadUsage(Exception): pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002576
Nick Coghlan106274b2009-11-15 23:04:33 +00002577 # Scripts don't get the current directory in their path by default
2578 # unless they are run with the '-m' switch
2579 if '' not in sys.path:
2580 scriptdir = os.path.dirname(sys.argv[0])
2581 if scriptdir in sys.path:
2582 sys.path.remove(scriptdir)
2583 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002584
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002585 try:
Victor Stinner383c3fc2011-05-25 01:35:05 +02002586 opts, args = getopt.getopt(sys.argv[1:], 'bk:p:w')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002587 writing = False
2588 start_server = False
2589 open_browser = False
2590 port = None
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002591 for opt, val in opts:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002592 if opt == '-b':
2593 start_server = True
2594 open_browser = True
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002595 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002596 apropos(val)
2597 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002598 if opt == '-p':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002599 start_server = True
2600 port = val
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002601 if opt == '-w':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002602 writing = True
2603
Benjamin Petersonb29614e2012-10-09 11:16:03 -04002604 if start_server:
2605 if port is None:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002606 port = 0
2607 browse(port, open_browser=open_browser)
2608 return
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002609
2610 if not args: raise BadUsage
2611 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002612 if ispath(arg) and not os.path.exists(arg):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002613 print('file %r does not exist' % arg)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002614 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002615 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002616 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002617 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002618 if writing:
2619 if ispath(arg) and os.path.isdir(arg):
2620 writedocs(arg)
2621 else:
2622 writedoc(arg)
2623 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002624 help.help(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +00002625 except ErrorDuringImport as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002626 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002627
2628 except (getopt.error, BadUsage):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002629 cmd = os.path.splitext(os.path.basename(sys.argv[0]))[0]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002630 print("""pydoc - the Python documentation tool
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002631
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002632{cmd} <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002633 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002634 Python keyword, topic, function, module, or package, or a dotted
2635 reference to a class or function within a module or module in a
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002636 package. If <name> contains a '{sep}', it is used as the path to a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002637 Python source file to document. If name is 'keywords', 'topics',
2638 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002639
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002640{cmd} -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002641 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002642
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002643{cmd} -p <port>
2644 Start an HTTP server on the given port on the local machine. Port
2645 number 0 can be used to get an arbitrary unused port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002646
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002647{cmd} -b
2648 Start an HTTP server on an arbitrary unused port and open a Web browser
2649 to interactively browse documentation. The -p option can be used with
2650 the -b option to explicitly specify the server port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002651
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002652{cmd} -w <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002653 Write out the HTML documentation for a module to a file in the current
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002654 directory. If <name> contains a '{sep}', it is treated as a filename; if
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002655 it names a directory, documentation is written for all the contents.
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002656""".format(cmd=cmd, sep=os.sep))
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002657
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002658if __name__ == '__main__':
2659 cli()