blob: d0240ffeac6ebcda70a39dbb032497eec1862bfe [file] [log] [blame]
Benjamin Peterson90f5ba52010-03-11 22:53:45 +00001#!/usr/bin/env python3
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002"""Generate Python documentation in HTML or text for interactive use.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00003
Georg Brandlc645c6a2012-06-24 17:24:26 +02004In the Python interpreter, do "from pydoc import help" to provide
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00005help. Calling help(thing) on a Python object documents the object.
6
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00007Or, at the shell command line outside of Python:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00008
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00009Run "pydoc <name>" to show documentation on something. <name> may be
10the name of a function, module, package, or a dotted reference to a
11class or function within a module or module in a package. If the
12argument contains a path segment delimiter (e.g. slash on Unix,
13backslash on Windows) it is treated as the path to a Python source file.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000014
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000015Run "pydoc -k <keyword>" to search for a keyword in the synopsis lines
16of all available modules.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000017
Nick Coghlan7bb30b72010-12-03 09:29:11 +000018Run "pydoc -p <port>" to start an HTTP server on the given port on the
19local machine. Port number 0 can be used to get an arbitrary unused port.
20
21Run "pydoc -b" to start an HTTP server on an arbitrary unused port and
22open a Web browser to interactively browse documentation. The -p option
23can be used with the -b option to explicitly specify the server port.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000024
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000025Run "pydoc -w <name>" to write out the HTML documentation for a module
26to a file named "<name>.html".
Skip Montanaro4997a692003-09-10 16:47:51 +000027
28Module docs for core modules are assumed to be in
29
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000030 http://docs.python.org/X.Y/library/
Skip Montanaro4997a692003-09-10 16:47:51 +000031
32This can be overridden by setting the PYTHONDOCS environment variable
33to a different URL or to a local directory containing the Library
34Reference Manual pages.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000035"""
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000036__all__ = ['help']
Ka-Ping Yeedd175342001-02-27 14:43:46 +000037__author__ = "Ka-Ping Yee <ping@lfw.org>"
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000038__date__ = "26 February 2001"
Jeremy Hylton3e0055f2005-10-20 19:59:25 +000039
Martin v. Löwis6fe8f192004-11-14 10:21:04 +000040__credits__ = """Guido van Rossum, for an excellent programming language.
Ka-Ping Yee5e2b1732001-02-27 23:35:09 +000041Tommy Burnette, the original creator of manpy.
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000042Paul Prescod, for all his work on onlinehelp.
43Richard Chamberlain, for the first implementation of textdoc.
Raymond Hettingered2dbe32005-01-01 07:51:01 +000044"""
Ka-Ping Yeedd175342001-02-27 14:43:46 +000045
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000046# Known bugs that can't be fixed here:
Brett Cannonf4ba4ec2013-06-15 14:25:04 -040047# - synopsis() cannot be prevented from clobbering existing
48# loaded modules.
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000049# - If the __file__ attribute on a module is a relative path and
50# the current directory is changed with os.chdir(), an incorrect
51# path will be displayed.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000052
Nick Coghlan7bb30b72010-12-03 09:29:11 +000053import builtins
Brett Cannond5e6f2e2013-06-11 17:09:36 -040054import importlib._bootstrap
Brett Cannoncb66eb02012-05-11 12:58:42 -040055import importlib.machinery
Brett Cannonf4ba4ec2013-06-15 14:25:04 -040056import importlib.util
Nick Coghlan7bb30b72010-12-03 09:29:11 +000057import inspect
Victor Stinnere6c910e2011-06-30 15:55:43 +020058import io
59import os
Nick Coghlan7bb30b72010-12-03 09:29:11 +000060import pkgutil
61import platform
62import re
Victor Stinnere6c910e2011-06-30 15:55:43 +020063import sys
Nick Coghlan7bb30b72010-12-03 09:29:11 +000064import time
Victor Stinnere6c910e2011-06-30 15:55:43 +020065import tokenize
Nick Coghlan7bb30b72010-12-03 09:29:11 +000066import warnings
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000067from collections import deque
Nick Coghlan7bb30b72010-12-03 09:29:11 +000068from reprlib import Repr
Georg Brandld2f38572011-01-30 08:37:19 +000069from traceback import extract_tb, format_exception_only
Nick Coghlan7bb30b72010-12-03 09:29:11 +000070
71
Ka-Ping Yeedd175342001-02-27 14:43:46 +000072# --------------------------------------------------------- common routines
73
Ka-Ping Yeedd175342001-02-27 14:43:46 +000074def pathdirs():
75 """Convert sys.path into a list of absolute, existing, unique paths."""
76 dirs = []
Ka-Ping Yee1d384632001-03-01 00:24:32 +000077 normdirs = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +000078 for dir in sys.path:
79 dir = os.path.abspath(dir or '.')
Ka-Ping Yee1d384632001-03-01 00:24:32 +000080 normdir = os.path.normcase(dir)
81 if normdir not in normdirs and os.path.isdir(dir):
Ka-Ping Yeedd175342001-02-27 14:43:46 +000082 dirs.append(dir)
Ka-Ping Yee1d384632001-03-01 00:24:32 +000083 normdirs.append(normdir)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000084 return dirs
85
86def getdoc(object):
87 """Get the doc string or comments for an object."""
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000088 result = inspect.getdoc(object) or inspect.getcomments(object)
Neal Norwitz9d72bb42007-04-17 08:48:32 +000089 return result and re.sub('^ *\n', '', result.rstrip()) or ''
Ka-Ping Yeedd175342001-02-27 14:43:46 +000090
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000091def splitdoc(doc):
92 """Split a doc string into a synopsis line (if any) and the rest."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +000093 lines = doc.strip().split('\n')
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000094 if len(lines) == 1:
95 return lines[0], ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +000096 elif len(lines) >= 2 and not lines[1].rstrip():
97 return lines[0], '\n'.join(lines[2:])
98 return '', '\n'.join(lines)
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000099
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000100def classname(object, modname):
101 """Get a class name and qualify it with a module name if necessary."""
102 name = object.__name__
103 if object.__module__ != modname:
104 name = object.__module__ + '.' + name
105 return name
106
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000107def isdata(object):
Georg Brandl94432422005-07-22 21:52:25 +0000108 """Check if an object is of a type that probably means it's data."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000109 return not (inspect.ismodule(object) or inspect.isclass(object) or
110 inspect.isroutine(object) or inspect.isframe(object) or
111 inspect.istraceback(object) or inspect.iscode(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000112
113def replace(text, *pairs):
114 """Do a series of global replacements on a string."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000115 while pairs:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000116 text = pairs[1].join(text.split(pairs[0]))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000117 pairs = pairs[2:]
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000118 return text
119
120def cram(text, maxlen):
121 """Omit part of a string if needed to make it fit in a maximum length."""
122 if len(text) > maxlen:
Raymond Hettingerfca3bb62002-10-21 04:44:11 +0000123 pre = max(0, (maxlen-3)//2)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000124 post = max(0, maxlen-3-pre)
125 return text[:pre] + '...' + text[len(text)-post:]
126 return text
127
Brett Cannon84601f12004-06-19 01:22:48 +0000128_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000129def stripid(text):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000130 """Remove the hexadecimal id from a Python object representation."""
Brett Cannonc6c1f472004-06-19 01:02:51 +0000131 # The behaviour of %p is implementation-dependent in terms of case.
Ezio Melotti412c95a2010-02-16 23:31:04 +0000132 return _re_stripid.sub(r'\1', text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000133
Brett Cannonc6c1f472004-06-19 01:02:51 +0000134def _is_some_method(obj):
R David Murrayac0cea52013-03-19 02:47:44 -0400135 return (inspect.isfunction(obj) or
136 inspect.ismethod(obj) or
137 inspect.isbuiltin(obj) or
138 inspect.ismethoddescriptor(obj))
Tim Peters536d2262001-09-20 05:13:38 +0000139
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000140def allmethods(cl):
141 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000142 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000143 methods[key] = 1
144 for base in cl.__bases__:
145 methods.update(allmethods(base)) # all your base are belong to us
146 for key in methods.keys():
147 methods[key] = getattr(cl, key)
148 return methods
149
Tim Petersfa26f7c2001-09-24 08:05:11 +0000150def _split_list(s, predicate):
151 """Split sequence s via predicate, and return pair ([true], [false]).
152
153 The return value is a 2-tuple of lists,
154 ([x for x in s if predicate(x)],
155 [x for x in s if not predicate(x)])
156 """
157
Tim Peters28355492001-09-23 21:29:55 +0000158 yes = []
159 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000160 for x in s:
161 if predicate(x):
162 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000163 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000164 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000165 return yes, no
166
Raymond Hettinger1103d052011-03-25 14:15:24 -0700167def visiblename(name, all=None, obj=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000168 """Decide whether to show documentation on a variable."""
Brett Cannond340b432012-08-06 17:19:22 -0400169 # Certain special names are redundant or internal.
170 if name in {'__author__', '__builtins__', '__cached__', '__credits__',
171 '__date__', '__doc__', '__file__', '__initializing__',
172 '__loader__', '__module__', '__name__', '__package__',
173 '__path__', '__qualname__', '__slots__', '__version__'}:
Raymond Hettinger68272942011-03-18 02:22:15 -0700174 return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000175 # Private names are hidden, but special names are displayed.
176 if name.startswith('__') and name.endswith('__'): return 1
Raymond Hettinger1103d052011-03-25 14:15:24 -0700177 # Namedtuples have public fields and methods with a single leading underscore
178 if name.startswith('_') and hasattr(obj, '_fields'):
179 return True
Skip Montanaroa5616d22004-06-11 04:46:12 +0000180 if all is not None:
181 # only document that which the programmer exported in __all__
182 return name in all
183 else:
184 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000185
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000186def classify_class_attrs(object):
187 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000188 results = []
189 for (name, kind, cls, value) in inspect.classify_class_attrs(object):
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000190 if inspect.isdatadescriptor(value):
191 kind = 'data descriptor'
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000192 results.append((name, kind, cls, value))
193 return results
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000194
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000195# ----------------------------------------------------- module manipulation
196
197def ispackage(path):
198 """Guess whether a path refers to a package directory."""
199 if os.path.isdir(path):
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000200 for ext in ('.py', '.pyc', '.pyo'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000201 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000202 return True
203 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000204
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000205def source_synopsis(file):
206 line = file.readline()
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000207 while line[:1] == '#' or not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000208 line = file.readline()
209 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000210 line = line.strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000211 if line[:4] == 'r"""': line = line[1:]
212 if line[:3] == '"""':
213 line = line[3:]
214 if line[-1:] == '\\': line = line[:-1]
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000215 while not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000216 line = file.readline()
217 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000218 result = line.split('"""')[0].strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000219 else: result = None
220 return result
221
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000222def synopsis(filename, cache={}):
223 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000224 mtime = os.stat(filename).st_mtime
Charles-François Natali27c4e882011-07-27 19:40:02 +0200225 lastupdate, result = cache.get(filename, (None, None))
226 if lastupdate is None or lastupdate < mtime:
Georg Brandl26fd2e12006-03-08 09:34:53 +0000227 try:
Victor Stinnere6c910e2011-06-30 15:55:43 +0200228 file = tokenize.open(filename)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200229 except OSError:
Georg Brandl26fd2e12006-03-08 09:34:53 +0000230 # module can't be opened, so skip it
231 return None
Brett Cannoncb66eb02012-05-11 12:58:42 -0400232 binary_suffixes = importlib.machinery.BYTECODE_SUFFIXES[:]
233 binary_suffixes += importlib.machinery.EXTENSION_SUFFIXES[:]
234 if any(filename.endswith(x) for x in binary_suffixes):
235 # binary modules have to be imported
236 file.close()
237 if any(filename.endswith(x) for x in
238 importlib.machinery.BYTECODE_SUFFIXES):
239 loader = importlib.machinery.SourcelessFileLoader('__temp__',
240 filename)
241 else:
242 loader = importlib.machinery.ExtensionFileLoader('__temp__',
243 filename)
244 try:
245 module = loader.load_module('__temp__')
246 except:
247 return None
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000248 result = (module.__doc__ or '').splitlines()[0]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000249 del sys.modules['__temp__']
Brett Cannoncb66eb02012-05-11 12:58:42 -0400250 else:
251 # text modules can be directly examined
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000252 result = source_synopsis(file)
253 file.close()
Brett Cannoncb66eb02012-05-11 12:58:42 -0400254
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000255 cache[filename] = (mtime, result)
256 return result
257
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000258class ErrorDuringImport(Exception):
259 """Errors that occurred while trying to import something to document it."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000260 def __init__(self, filename, exc_info):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000261 self.filename = filename
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000262 self.exc, self.value, self.tb = exc_info
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000263
264 def __str__(self):
Guido van Rossuma01a8b62007-05-27 09:20:14 +0000265 exc = self.exc.__name__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000266 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000267
268def importfile(path):
269 """Import a Python source file or compiled file given its path."""
Brett Cannonf4ba4ec2013-06-15 14:25:04 -0400270 magic = importlib.util.MAGIC_NUMBER
Victor Stinnere975af62011-07-04 02:08:50 +0200271 with open(path, 'rb') as file:
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400272 is_bytecode = magic == file.read(len(magic))
273 filename = os.path.basename(path)
274 name, ext = os.path.splitext(filename)
275 if is_bytecode:
276 loader = importlib._bootstrap.SourcelessFileLoader(name, path)
277 else:
278 loader = importlib._bootstrap.SourceFileLoader(name, path)
279 try:
280 return loader.load_module(name)
281 except:
282 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000283
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000284def safeimport(path, forceload=0, cache={}):
285 """Import a module; handle errors; return None if the module isn't found.
286
287 If the module *is* found but an exception occurs, it's wrapped in an
288 ErrorDuringImport exception and reraised. Unlike __import__, if a
289 package path is specified, the module at the end of the path is returned,
290 not the package at the beginning. If the optional 'forceload' argument
291 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000292 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000293 # If forceload is 1 and the module has been previously loaded from
294 # disk, we always have to reload the module. Checking the file's
295 # mtime isn't good enough (e.g. the module could contain a class
296 # that inherits from another module that has changed).
297 if forceload and path in sys.modules:
298 if path not in sys.builtin_module_names:
Guido van Rossume7ba4952007-06-06 23:52:48 +0000299 # Remove the module from sys.modules and re-import to try
300 # and avoid problems with partially loaded modules.
301 # Also remove any submodules because they won't appear
302 # in the newly loaded module's namespace if they're already
303 # in sys.modules.
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000304 subs = [m for m in sys.modules if m.startswith(path + '.')]
305 for key in [path] + subs:
306 # Prevent garbage collection.
307 cache[key] = sys.modules[key]
308 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000309 module = __import__(path)
310 except:
311 # Did the error occur before or after the module was found?
312 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000313 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000314 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000315 raise ErrorDuringImport(sys.modules[path].__file__, info)
316 elif exc is SyntaxError:
317 # A SyntaxError occurred before we could execute the module.
318 raise ErrorDuringImport(value.filename, info)
Brett Cannon679ecb52013-07-04 17:51:50 -0400319 elif exc is ImportError and value.name == path:
Brett Cannonfd074152012-04-14 14:10:13 -0400320 # No such module in the path.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000321 return None
322 else:
323 # Some other error occurred during the importing process.
324 raise ErrorDuringImport(path, sys.exc_info())
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000325 for part in path.split('.')[1:]:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000326 try: module = getattr(module, part)
327 except AttributeError: return None
328 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000329
330# ---------------------------------------------------- formatter base class
331
332class Doc:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000333
334 PYTHONDOCS = os.environ.get("PYTHONDOCS",
335 "http://docs.python.org/%d.%d/library"
336 % sys.version_info[:2])
337
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000338 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000339 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000340 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000341 # 'try' clause is to attempt to handle the possibility that inspect
342 # identifies something in a way that pydoc itself has issues handling;
343 # think 'super' and how it is a descriptor (which raises the exception
344 # by lacking a __name__ attribute) and an instance.
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000345 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
346 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000347 try:
348 if inspect.ismodule(object): return self.docmodule(*args)
349 if inspect.isclass(object): return self.docclass(*args)
350 if inspect.isroutine(object): return self.docroutine(*args)
351 except AttributeError:
352 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000353 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000354 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000355
356 def fail(self, object, name=None, *args):
357 """Raise an exception for unimplemented types."""
358 message = "don't know how to document object%s of type %s" % (
359 name and ' ' + repr(name), type(object).__name__)
Collin Winterce36ad82007-08-30 01:19:48 +0000360 raise TypeError(message)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000361
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000362 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000363
Skip Montanaro4997a692003-09-10 16:47:51 +0000364 def getdocloc(self, object):
365 """Return the location of module docs or None"""
366
367 try:
368 file = inspect.getabsfile(object)
369 except TypeError:
370 file = '(built-in)'
371
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000372 docloc = os.environ.get("PYTHONDOCS", self.PYTHONDOCS)
373
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100374 basedir = os.path.join(sys.base_exec_prefix, "lib",
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000375 "python%d.%d" % sys.version_info[:2])
Skip Montanaro4997a692003-09-10 16:47:51 +0000376 if (isinstance(object, type(os)) and
377 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
378 'marshal', 'posix', 'signal', 'sys',
Georg Brandl2067bfd2008-05-25 13:05:15 +0000379 '_thread', 'zipimport') or
Skip Montanaro4997a692003-09-10 16:47:51 +0000380 (file.startswith(basedir) and
Brian Curtin49c284c2010-03-31 03:19:28 +0000381 not file.startswith(os.path.join(basedir, 'site-packages')))) and
Brian Curtinedef05b2010-04-01 04:05:25 +0000382 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
Skip Montanaro4997a692003-09-10 16:47:51 +0000383 if docloc.startswith("http://"):
Georg Brandl86def6c2008-01-21 20:36:10 +0000384 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
Skip Montanaro4997a692003-09-10 16:47:51 +0000385 else:
Georg Brandl86def6c2008-01-21 20:36:10 +0000386 docloc = os.path.join(docloc, object.__name__ + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000387 else:
388 docloc = None
389 return docloc
390
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000391# -------------------------------------------- HTML documentation generator
392
393class HTMLRepr(Repr):
394 """Class for safely making an HTML representation of a Python object."""
395 def __init__(self):
396 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000397 self.maxlist = self.maxtuple = 20
398 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000399 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000400
401 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000402 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000403
404 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000405 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000406
407 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000408 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000409 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000410 if hasattr(self, methodname):
411 return getattr(self, methodname)(x, level)
412 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000413
414 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000415 test = cram(x, self.maxstring)
416 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000417 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000418 # Backslashes are only literal in the string and are never
419 # needed to make any special characters, so show a raw string.
420 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000421 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000422 r'<font color="#c040c0">\1</font>',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000423 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000424
Skip Montanarodf708782002-03-07 22:58:02 +0000425 repr_str = repr_string
426
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000427 def repr_instance(self, x, level):
428 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000429 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000430 except:
431 return self.escape('<%s instance>' % x.__class__.__name__)
432
433 repr_unicode = repr_string
434
435class HTMLDoc(Doc):
436 """Formatter class for HTML documentation."""
437
438 # ------------------------------------------- HTML formatting utilities
439
440 _repr_instance = HTMLRepr()
441 repr = _repr_instance.repr
442 escape = _repr_instance.escape
443
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000444 def page(self, title, contents):
445 """Format an HTML page."""
Georg Brandl388faac2009-04-10 08:31:48 +0000446 return '''\
Georg Brandle6066942009-04-10 08:28:28 +0000447<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000448<html><head><title>Python: %s</title>
Georg Brandl388faac2009-04-10 08:31:48 +0000449<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000450</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000451%s
452</body></html>''' % (title, contents)
453
454 def heading(self, title, fgcol, bgcol, extras=''):
455 """Format a page heading."""
456 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000457<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000458<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000459<td valign=bottom>&nbsp;<br>
460<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000461><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000462><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000463 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
464
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000465 def section(self, title, fgcol, bgcol, contents, width=6,
466 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000467 """Format a section with a heading."""
468 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000469 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000470 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000471<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000472<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000473<td colspan=3 valign=bottom>&nbsp;<br>
474<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000475 ''' % (bgcol, fgcol, title)
476 if prelude:
477 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000478<tr bgcolor="%s"><td rowspan=2>%s</td>
479<td colspan=2>%s</td></tr>
480<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
481 else:
482 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000483<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000484
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000485 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000486
487 def bigsection(self, title, *args):
488 """Format a section with a big heading."""
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000489 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000490 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000491
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000492 def preformat(self, text):
493 """Format literal preformatted text."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000494 text = self.escape(text.expandtabs())
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000495 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
496 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000497
498 def multicolumn(self, list, format, cols=4):
499 """Format a list of items into a multi-column list."""
500 result = ''
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000501 rows = (len(list)+cols-1)//cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000502 for col in range(cols):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000503 result = result + '<td width="%d%%" valign=top>' % (100//cols)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000504 for i in range(rows*col, rows*col+rows):
505 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000506 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000507 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000508 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000509
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000510 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000511
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000512 def namelink(self, name, *dicts):
513 """Make a link for an identifier, given name-to-URL mappings."""
514 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000515 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000516 return '<a href="%s">%s</a>' % (dict[name], name)
517 return name
518
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000519 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000520 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000521 name, module = object.__name__, sys.modules.get(object.__module__)
522 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000523 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000524 module.__name__, name, classname(object, modname))
525 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000526
527 def modulelink(self, object):
528 """Make a link for a module."""
529 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
530
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000531 def modpkglink(self, modpkginfo):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000532 """Make a link for a module or package to display in an index."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000533 name, path, ispackage, shadowed = modpkginfo
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000534 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000535 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000536 if path:
537 url = '%s.%s.html' % (path, name)
538 else:
539 url = '%s.html' % name
540 if ispackage:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000541 text = '<strong>%s</strong>&nbsp;(package)' % name
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000542 else:
543 text = name
544 return '<a href="%s">%s</a>' % (url, text)
545
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000546 def filelink(self, url, path):
547 """Make a link to source file."""
548 return '<a href="file:%s">%s</a>' % (url, path)
549
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000550 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
551 """Mark up some plain text, given a context of symbols to look for.
552 Each context dictionary maps object names to anchor names."""
553 escape = escape or self.escape
554 results = []
555 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000556 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
557 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000558 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000559 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000560 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000561 match = pattern.search(text, here)
562 if not match: break
563 start, end = match.span()
564 results.append(escape(text[here:start]))
565
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000566 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000567 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000568 url = escape(all).replace('"', '&quot;')
569 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000570 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000571 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
572 results.append('<a href="%s">%s</a>' % (url, escape(all)))
573 elif pep:
Christian Heimes2202f872008-02-06 14:31:34 +0000574 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000575 results.append('<a href="%s">%s</a>' % (url, escape(all)))
576 elif text[end:end+1] == '(':
577 results.append(self.namelink(name, methods, funcs, classes))
578 elif selfdot:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000579 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000580 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000581 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000582 here = end
583 results.append(escape(text[here:]))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000584 return ''.join(results)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000585
586 # ---------------------------------------------- type-specific routines
587
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000588 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000589 """Produce HTML for a class tree as given by inspect.getclasstree()."""
590 result = ''
591 for entry in tree:
592 if type(entry) is type(()):
593 c, bases = entry
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000594 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000595 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000596 if bases and bases != (parent,):
597 parents = []
598 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000599 parents.append(self.classlink(base, modname))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000600 result = result + '(' + ', '.join(parents) + ')'
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000601 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000602 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000603 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000604 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000605 return '<dl>\n%s</dl>\n' % result
606
Tim Peters8dd7ade2001-10-18 19:56:17 +0000607 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000608 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000609 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000610 try:
611 all = object.__all__
612 except AttributeError:
613 all = None
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000614 parts = name.split('.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000615 links = []
616 for i in range(len(parts)-1):
617 links.append(
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000618 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000619 ('.'.join(parts[:i+1]), parts[i]))
620 linkedname = '.'.join(links + parts[-1:])
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000621 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000622 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000623 path = inspect.getabsfile(object)
Ka-Ping Yee6191a232001-04-13 15:00:27 +0000624 url = path
625 if sys.platform == 'win32':
626 import nturl2path
627 url = nturl2path.pathname2url(path)
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000628 filelink = self.filelink(url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000629 except TypeError:
630 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000631 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000632 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000633 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000634 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000635 version = version[11:-1].strip()
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000636 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000637 if hasattr(object, '__date__'):
638 info.append(self.escape(str(object.__date__)))
639 if info:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000640 head = head + ' (%s)' % ', '.join(info)
Skip Montanaro4997a692003-09-10 16:47:51 +0000641 docloc = self.getdocloc(object)
642 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000643 docloc = '<br><a href="%(docloc)s">Module Reference</a>' % locals()
Skip Montanaro4997a692003-09-10 16:47:51 +0000644 else:
645 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000646 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000647 head, '#ffffff', '#7799ee',
648 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000649
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000650 modules = inspect.getmembers(object, inspect.ismodule)
651
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000652 classes, cdict = [], {}
653 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000654 # if __all__ exists, believe it. Otherwise use old heuristic.
655 if (all is not None or
656 (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700657 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000658 classes.append((key, value))
659 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000660 for key, value in classes:
661 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000662 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000663 module = sys.modules.get(modname)
664 if modname != name and module and hasattr(module, key):
665 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000666 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000667 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000668 funcs, fdict = [], {}
669 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000670 # if __all__ exists, believe it. Otherwise use old heuristic.
671 if (all is not None or
672 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700673 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000674 funcs.append((key, value))
675 fdict[key] = '#-' + key
676 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000677 data = []
678 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700679 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000680 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000681
682 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
683 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000684 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000685
686 if hasattr(object, '__path__'):
687 modpkgs = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000688 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
689 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000690 modpkgs.sort()
691 contents = self.multicolumn(modpkgs, self.modpkglink)
692 result = result + self.bigsection(
693 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000694 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000695 contents = self.multicolumn(
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000696 modules, lambda t: self.modulelink(t[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000697 result = result + self.bigsection(
Christian Heimes7131fd92008-02-19 14:21:46 +0000698 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000699
700 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000701 classlist = [value for (key, value) in classes]
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000702 contents = [
703 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000704 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000705 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000706 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000707 'Classes', '#ffffff', '#ee77aa', ' '.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000708 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000709 contents = []
710 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000711 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000712 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000713 'Functions', '#ffffff', '#eeaa77', ' '.join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000714 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000715 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000716 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000717 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000718 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000719 'Data', '#ffffff', '#55aa55', '<br>\n'.join(contents))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000720 if hasattr(object, '__author__'):
721 contents = self.markup(str(object.__author__), self.preformat)
722 result = result + self.bigsection(
723 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000724 if hasattr(object, '__credits__'):
725 contents = self.markup(str(object.__credits__), self.preformat)
726 result = result + self.bigsection(
727 'Credits', '#ffffff', '#7799ee', contents)
728
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000729 return result
730
Tim Peters8dd7ade2001-10-18 19:56:17 +0000731 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
732 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000733 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000734 realname = object.__name__
735 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000736 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000737
Tim Petersb47879b2001-09-24 04:47:19 +0000738 contents = []
739 push = contents.append
740
Tim Petersfa26f7c2001-09-24 08:05:11 +0000741 # Cute little class to pump out a horizontal rule between sections.
742 class HorizontalRule:
743 def __init__(self):
744 self.needone = 0
745 def maybe(self):
746 if self.needone:
747 push('<hr>\n')
748 self.needone = 1
749 hr = HorizontalRule()
750
Tim Petersc86f6ca2001-09-26 21:31:51 +0000751 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000752 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000753 if len(mro) > 2:
754 hr.maybe()
755 push('<dl><dt>Method resolution order:</dt>\n')
756 for base in mro:
757 push('<dd>%s</dd>\n' % self.classlink(base,
758 object.__module__))
759 push('</dl>\n')
760
Tim Petersb47879b2001-09-24 04:47:19 +0000761 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000762 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000763 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000764 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000765 push(msg)
766 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100767 try:
768 value = getattr(object, name)
769 except Exception:
770 # Some descriptors may meet a failure in their __get__.
771 # (bug #1785)
772 push(self._docdescriptor(name, value, mod))
773 else:
774 push(self.document(value, name, mod,
775 funcs, classes, mdict, object))
Tim Petersb47879b2001-09-24 04:47:19 +0000776 push('\n')
777 return attrs
778
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000779 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000780 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000781 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000782 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000783 push(msg)
784 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000785 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000786 return attrs
787
Tim Petersfa26f7c2001-09-24 08:05:11 +0000788 def spilldata(msg, attrs, predicate):
789 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000790 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000791 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000792 push(msg)
793 for name, kind, homecls, value in ok:
794 base = self.docother(getattr(object, name), name, mod)
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200795 if callable(value) or inspect.isdatadescriptor(value):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000796 doc = getattr(value, "__doc__", None)
797 else:
798 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000799 if doc is None:
800 push('<dl><dt>%s</dl>\n' % base)
801 else:
802 doc = self.markup(getdoc(value), self.preformat,
803 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000804 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000805 push('<dl><dt>%s%s</dl>\n' % (base, doc))
806 push('\n')
807 return attrs
808
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000809 attrs = [(name, kind, cls, value)
810 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -0700811 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000812
Tim Petersb47879b2001-09-24 04:47:19 +0000813 mdict = {}
814 for key, kind, homecls, value in attrs:
815 mdict[key] = anchor = '#' + name + '-' + key
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100816 try:
817 value = getattr(object, name)
818 except Exception:
819 # Some descriptors may meet a failure in their __get__.
820 # (bug #1785)
821 pass
Tim Petersb47879b2001-09-24 04:47:19 +0000822 try:
823 # The value may not be hashable (e.g., a data attr with
824 # a dict or list value).
825 mdict[value] = anchor
826 except TypeError:
827 pass
828
Tim Petersfa26f7c2001-09-24 08:05:11 +0000829 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000830 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000831 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000832 else:
833 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000834 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
835
Georg Brandl1a3284e2007-12-02 09:40:06 +0000836 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000837 attrs = inherited
838 continue
839 elif thisclass is object:
840 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000841 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000842 tag = 'inherited from %s' % self.classlink(thisclass,
843 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000844 tag += ':<br>\n'
845
846 # Sort attrs by name.
Raymond Hettingerd4cb56d2008-01-30 02:55:10 +0000847 attrs.sort(key=lambda t: t[0])
Tim Petersb47879b2001-09-24 04:47:19 +0000848
849 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000850 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000851 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000852 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000853 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000854 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000855 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000856 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
857 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000858 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000859 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000860 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000861 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000862
863 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000864
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000865 if name == realname:
866 title = '<a name="%s">class <strong>%s</strong></a>' % (
867 name, realname)
868 else:
869 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
870 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000871 if bases:
872 parents = []
873 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000874 parents.append(self.classlink(base, object.__module__))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000875 title = title + '(%s)' % ', '.join(parents)
Tim Peters2306d242001-09-25 03:18:32 +0000876 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000877 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000878
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000879 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000880
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000881 def formatvalue(self, object):
882 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000883 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000884
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000885 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000886 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000887 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000888 realname = object.__name__
889 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000890 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000891 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000892 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000893 if inspect.ismethod(object):
Christian Heimesff737952007-11-27 10:40:20 +0000894 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000895 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000896 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000897 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000898 else:
Christian Heimesff737952007-11-27 10:40:20 +0000899 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000900 note = ' method of %s instance' % self.classlink(
Christian Heimesff737952007-11-27 10:40:20 +0000901 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000902 else:
903 note = ' unbound %s method' % self.classlink(imclass,mod)
Christian Heimesff737952007-11-27 10:40:20 +0000904 object = object.__func__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000905
906 if name == realname:
907 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
908 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000909 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000910 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000911 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000912 cl.__name__ + '-' + realname, realname)
913 skipdocs = 1
914 else:
915 reallink = realname
916 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
917 anchor, name, reallink)
Tim Peters4bcfa312001-09-20 06:08:24 +0000918 if inspect.isfunction(object):
Guido van Rossum2e65f892007-02-28 22:03:49 +0000919 args, varargs, kwonlyargs, kwdefaults, varkw, defaults, ann = \
920 inspect.getfullargspec(object)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000921 argspec = inspect.formatargspec(
Guido van Rossum2e65f892007-02-28 22:03:49 +0000922 args, varargs, kwonlyargs, kwdefaults, varkw, defaults, ann,
923 formatvalue=self.formatvalue,
924 formatannotation=inspect.formatannotationrelativeto(object))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000925 if realname == '<lambda>':
Tim Peters59ed4482001-10-31 04:20:26 +0000926 title = '<strong>%s</strong> <em>lambda</em> ' % name
Guido van Rossum2e65f892007-02-28 22:03:49 +0000927 # XXX lambda's won't usually have func_annotations['return']
928 # since the syntax doesn't support but it is possible.
929 # So removing parentheses isn't truly safe.
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000930 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +0000931 else:
932 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000933
Tim Peters2306d242001-09-25 03:18:32 +0000934 decl = title + argspec + (note and self.grey(
935 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000936
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000937 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000938 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000939 else:
940 doc = self.markup(
941 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000942 doc = doc and '<dd><tt>%s</tt></dd>' % doc
943 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000944
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000945 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000946 results = []
947 push = results.append
948
949 if name:
950 push('<dl><dt><strong>%s</strong></dt>\n' % name)
951 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000952 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000953 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000954 push('</dl>\n')
955
956 return ''.join(results)
957
958 def docproperty(self, object, name=None, mod=None, cl=None):
959 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000960 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000961
Tim Peters8dd7ade2001-10-18 19:56:17 +0000962 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000963 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000964 lhs = name and '<strong>%s</strong> = ' % name or ''
965 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000966
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000967 def docdata(self, object, name=None, mod=None, cl=None):
968 """Produce html documentation for a data descriptor."""
969 return self._docdescriptor(name, object, mod)
970
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000971 def index(self, dir, shadowed=None):
972 """Generate an HTML index for a directory of modules."""
973 modpkgs = []
974 if shadowed is None: shadowed = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000975 for importer, name, ispkg in pkgutil.iter_modules([dir]):
Victor Stinner4d652242011-04-12 23:41:50 +0200976 if any((0xD800 <= ord(ch) <= 0xDFFF) for ch in name):
977 # ignore a module if its name contains a surrogate character
978 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000979 modpkgs.append((name, '', ispkg, name in shadowed))
980 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000981
982 modpkgs.sort()
983 contents = self.multicolumn(modpkgs, self.modpkglink)
984 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
985
986# -------------------------------------------- text documentation generator
987
988class TextRepr(Repr):
989 """Class for safely making a text representation of a Python object."""
990 def __init__(self):
991 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000992 self.maxlist = self.maxtuple = 20
993 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000994 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000995
996 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000997 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000998 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000999 if hasattr(self, methodname):
1000 return getattr(self, methodname)(x, level)
1001 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001002
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001003 def repr_string(self, x, level):
1004 test = cram(x, self.maxstring)
1005 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001006 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001007 # Backslashes are only literal in the string and are never
1008 # needed to make any special characters, so show a raw string.
1009 return 'r' + testrepr[0] + test + testrepr[0]
1010 return testrepr
1011
Skip Montanarodf708782002-03-07 22:58:02 +00001012 repr_str = repr_string
1013
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001014 def repr_instance(self, x, level):
1015 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001016 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001017 except:
1018 return '<%s instance>' % x.__class__.__name__
1019
1020class TextDoc(Doc):
1021 """Formatter class for text documentation."""
1022
1023 # ------------------------------------------- text formatting utilities
1024
1025 _repr_instance = TextRepr()
1026 repr = _repr_instance.repr
1027
1028 def bold(self, text):
1029 """Format a string in bold by overstriking."""
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001030 return ''.join(ch + '\b' + ch for ch in text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001031
1032 def indent(self, text, prefix=' '):
1033 """Indent text by prepending a given prefix to each line."""
1034 if not text: return ''
Collin Winter72e110c2007-07-17 00:27:30 +00001035 lines = [prefix + line for line in text.split('\n')]
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001036 if lines: lines[-1] = lines[-1].rstrip()
1037 return '\n'.join(lines)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001038
1039 def section(self, title, contents):
1040 """Format a section with a given heading."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001041 clean_contents = self.indent(contents).rstrip()
1042 return self.bold(title) + '\n' + clean_contents + '\n\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001043
1044 # ---------------------------------------------- type-specific routines
1045
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001046 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001047 """Render in text a class tree as returned by inspect.getclasstree()."""
1048 result = ''
1049 for entry in tree:
1050 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001051 c, bases = entry
1052 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001053 if bases and bases != (parent,):
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001054 parents = (classname(c, modname) for c in bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001055 result = result + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001056 result = result + '\n'
1057 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001058 result = result + self.formattree(
1059 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001060 return result
1061
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001062 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001063 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001064 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001065 synop, desc = splitdoc(getdoc(object))
1066 result = self.section('NAME', name + (synop and ' - ' + synop))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001067 all = getattr(object, '__all__', None)
Skip Montanaro4997a692003-09-10 16:47:51 +00001068 docloc = self.getdocloc(object)
1069 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001070 result = result + self.section('MODULE REFERENCE', docloc + """
1071
Éric Araujo647ef8c2011-09-11 00:43:20 +02001072The following documentation is automatically generated from the Python
1073source files. It may be incomplete, incorrect or include features that
1074are considered implementation detail and may vary between Python
1075implementations. When in doubt, consult the module reference at the
1076location listed above.
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001077""")
Skip Montanaro4997a692003-09-10 16:47:51 +00001078
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001079 if desc:
1080 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001081
1082 classes = []
1083 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001084 # if __all__ exists, believe it. Otherwise use old heuristic.
1085 if (all is not None
1086 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001087 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001088 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001089 funcs = []
1090 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001091 # if __all__ exists, believe it. Otherwise use old heuristic.
1092 if (all is not None or
1093 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001094 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001095 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001096 data = []
1097 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001098 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001099 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001100
Christian Heimes1af737c2008-01-23 08:24:23 +00001101 modpkgs = []
1102 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001103 if hasattr(object, '__path__'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001104 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Christian Heimes1af737c2008-01-23 08:24:23 +00001105 modpkgs_names.add(modname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001106 if ispkg:
1107 modpkgs.append(modname + ' (package)')
1108 else:
1109 modpkgs.append(modname)
1110
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001111 modpkgs.sort()
1112 result = result + self.section(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001113 'PACKAGE CONTENTS', '\n'.join(modpkgs))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001114
Christian Heimes1af737c2008-01-23 08:24:23 +00001115 # Detect submodules as sometimes created by C extensions
1116 submodules = []
1117 for key, value in inspect.getmembers(object, inspect.ismodule):
1118 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1119 submodules.append(key)
1120 if submodules:
1121 submodules.sort()
1122 result = result + self.section(
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001123 'SUBMODULES', '\n'.join(submodules))
Christian Heimes1af737c2008-01-23 08:24:23 +00001124
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001125 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001126 classlist = [value for key, value in classes]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001127 contents = [self.formattree(
1128 inspect.getclasstree(classlist, 1), name)]
1129 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001130 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001131 result = result + self.section('CLASSES', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001132
1133 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001134 contents = []
1135 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001136 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001137 result = result + self.section('FUNCTIONS', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001138
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001139 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001140 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001141 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001142 contents.append(self.docother(value, key, name, maxlen=70))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001143 result = result + self.section('DATA', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001144
1145 if hasattr(object, '__version__'):
1146 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001147 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001148 version = version[11:-1].strip()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001149 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001150 if hasattr(object, '__date__'):
1151 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001152 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001153 result = result + self.section('AUTHOR', str(object.__author__))
1154 if hasattr(object, '__credits__'):
1155 result = result + self.section('CREDITS', str(object.__credits__))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001156 try:
1157 file = inspect.getabsfile(object)
1158 except TypeError:
1159 file = '(built-in)'
1160 result = result + self.section('FILE', file)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001161 return result
1162
Georg Brandl9bd45f992010-12-03 09:58:38 +00001163 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001164 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001165 realname = object.__name__
1166 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001167 bases = object.__bases__
1168
Tim Petersc86f6ca2001-09-26 21:31:51 +00001169 def makename(c, m=object.__module__):
1170 return classname(c, m)
1171
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001172 if name == realname:
1173 title = 'class ' + self.bold(realname)
1174 else:
1175 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001176 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001177 parents = map(makename, bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001178 title = title + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001179
1180 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001181 contents = doc and [doc + '\n'] or []
1182 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001183
Tim Petersc86f6ca2001-09-26 21:31:51 +00001184 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001185 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001186 if len(mro) > 2:
1187 push("Method resolution order:")
1188 for base in mro:
1189 push(' ' + makename(base))
1190 push('')
1191
Tim Petersf4aad8e2001-09-24 22:40:47 +00001192 # Cute little class to pump out a horizontal rule between sections.
1193 class HorizontalRule:
1194 def __init__(self):
1195 self.needone = 0
1196 def maybe(self):
1197 if self.needone:
1198 push('-' * 70)
1199 self.needone = 1
1200 hr = HorizontalRule()
1201
Tim Peters28355492001-09-23 21:29:55 +00001202 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001203 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001204 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001205 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001206 push(msg)
1207 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001208 try:
1209 value = getattr(object, name)
1210 except Exception:
1211 # Some descriptors may meet a failure in their __get__.
1212 # (bug #1785)
1213 push(self._docdescriptor(name, value, mod))
1214 else:
1215 push(self.document(value,
1216 name, mod, object))
Tim Peters28355492001-09-23 21:29:55 +00001217 return attrs
1218
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001219 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001220 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001221 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001222 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001223 push(msg)
1224 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001225 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001226 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001227
Tim Petersfa26f7c2001-09-24 08:05:11 +00001228 def spilldata(msg, attrs, predicate):
1229 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001230 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001231 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001232 push(msg)
1233 for name, kind, homecls, value in ok:
Florent Xicluna5d1155c2011-10-28 14:45:05 +02001234 if callable(value) or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001235 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001236 else:
1237 doc = None
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001238 push(self.docother(
1239 getattr(object, name, None) or homecls.__dict__[name],
1240 name, mod, maxlen=70, doc=doc) + '\n')
Tim Peters28355492001-09-23 21:29:55 +00001241 return attrs
1242
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001243 attrs = [(name, kind, cls, value)
1244 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -07001245 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001246
Tim Petersfa26f7c2001-09-24 08:05:11 +00001247 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001248 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001249 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001250 else:
1251 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001252 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1253
Georg Brandl1a3284e2007-12-02 09:40:06 +00001254 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001255 attrs = inherited
1256 continue
1257 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001258 tag = "defined here"
1259 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001260 tag = "inherited from %s" % classname(thisclass,
1261 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001262 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001263 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001264
1265 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001266 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001267 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001268 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001269 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001270 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001271 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001272 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1273 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001274 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1275 lambda t: t[1] == 'data')
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001276
Tim Peters28355492001-09-23 21:29:55 +00001277 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001278 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001279
1280 contents = '\n'.join(contents)
1281 if not contents:
1282 return title + '\n'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001283 return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001284
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001285 def formatvalue(self, object):
1286 """Format an argument default value as text."""
1287 return '=' + self.repr(object)
1288
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001289 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001290 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001291 realname = object.__name__
1292 name = name or realname
1293 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001294 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001295 if inspect.ismethod(object):
Christian Heimesff737952007-11-27 10:40:20 +00001296 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001297 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001298 if imclass is not cl:
1299 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001300 else:
Christian Heimesff737952007-11-27 10:40:20 +00001301 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001302 note = ' method of %s instance' % classname(
Christian Heimesff737952007-11-27 10:40:20 +00001303 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001304 else:
1305 note = ' unbound %s method' % classname(imclass,mod)
Christian Heimesff737952007-11-27 10:40:20 +00001306 object = object.__func__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001307
1308 if name == realname:
1309 title = self.bold(realname)
1310 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001311 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001312 cl.__dict__[realname] is object):
1313 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001314 title = self.bold(name) + ' = ' + realname
Tim Peters4bcfa312001-09-20 06:08:24 +00001315 if inspect.isfunction(object):
Guido van Rossum2e65f892007-02-28 22:03:49 +00001316 args, varargs, varkw, defaults, kwonlyargs, kwdefaults, ann = \
1317 inspect.getfullargspec(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001318 argspec = inspect.formatargspec(
Guido van Rossum2e65f892007-02-28 22:03:49 +00001319 args, varargs, varkw, defaults, kwonlyargs, kwdefaults, ann,
1320 formatvalue=self.formatvalue,
1321 formatannotation=inspect.formatannotationrelativeto(object))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001322 if realname == '<lambda>':
Georg Brandl501dd0d2006-02-17 09:45:40 +00001323 title = self.bold(name) + ' lambda '
Guido van Rossum2e65f892007-02-28 22:03:49 +00001324 # XXX lambda's won't usually have func_annotations['return']
1325 # since the syntax doesn't support but it is possible.
1326 # So removing parentheses isn't truly safe.
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001327 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +00001328 else:
1329 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001330 decl = title + argspec + note
1331
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001332 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001333 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001334 else:
1335 doc = getdoc(object) or ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001336 return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001337
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001338 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001339 results = []
1340 push = results.append
1341
1342 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001343 push(self.bold(name))
1344 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001345 doc = getdoc(value) or ''
1346 if doc:
1347 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001348 push('\n')
1349 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001350
1351 def docproperty(self, object, name=None, mod=None, cl=None):
1352 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001353 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001354
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001355 def docdata(self, object, name=None, mod=None, cl=None):
1356 """Produce text documentation for a data descriptor."""
1357 return self._docdescriptor(name, object, mod)
1358
Georg Brandl8b813db2005-10-01 16:32:31 +00001359 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001360 """Produce text documentation for a data object."""
1361 repr = self.repr(object)
1362 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001363 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001364 chop = maxlen - len(line)
1365 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001366 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001367 if doc is not None:
1368 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001369 return line
1370
Georg Brandld80d5f42010-12-03 07:47:22 +00001371class _PlainTextDoc(TextDoc):
1372 """Subclass of TextDoc which overrides string styling"""
1373 def bold(self, text):
1374 return text
1375
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001376# --------------------------------------------------------- user interfaces
1377
1378def pager(text):
1379 """The first time this is called, determine what kind of pager to use."""
1380 global pager
1381 pager = getpager()
1382 pager(text)
1383
1384def getpager():
1385 """Decide what method to use for paging through text."""
Guido van Rossuma01a8b62007-05-27 09:20:14 +00001386 if not hasattr(sys.stdout, "isatty"):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001387 return plainpager
1388 if not sys.stdin.isatty() or not sys.stdout.isatty():
1389 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001390 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001391 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001392 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001393 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001394 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001395 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001396 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001397 if os.environ.get('TERM') in ('dumb', 'emacs'):
1398 return plainpager
Jesus Cea4791a242012-10-05 03:15:39 +02001399 if sys.platform == 'win32':
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001400 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001401 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001402 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001403
1404 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001405 (fd, filename) = tempfile.mkstemp()
1406 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001407 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001408 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001409 return lambda text: pipepager(text, 'more')
1410 else:
1411 return ttypager
1412 finally:
1413 os.unlink(filename)
1414
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001415def plain(text):
1416 """Remove boldface formatting from text."""
1417 return re.sub('.\b', '', text)
1418
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001419def pipepager(text, cmd):
1420 """Page through text by feeding it to another program."""
1421 pipe = os.popen(cmd, 'w')
1422 try:
1423 pipe.write(text)
1424 pipe.close()
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001425 except OSError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001426 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001427
1428def tempfilepager(text, cmd):
1429 """Page through text by invoking a program on a temporary file."""
1430 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001431 filename = tempfile.mktemp()
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +01001432 with open(filename, 'w') as file:
1433 file.write(text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001434 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001435 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001436 finally:
1437 os.unlink(filename)
1438
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001439def ttypager(text):
1440 """Page through text on a text terminal."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001441 lines = plain(text).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001442 try:
1443 import tty
1444 fd = sys.stdin.fileno()
1445 old = tty.tcgetattr(fd)
1446 tty.setcbreak(fd)
1447 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001448 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001449 tty = None
1450 getchar = lambda: sys.stdin.readline()[:-1][:1]
1451
1452 try:
1453 r = inc = os.environ.get('LINES', 25) - 1
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001454 sys.stdout.write('\n'.join(lines[:inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001455 while lines[r:]:
1456 sys.stdout.write('-- more --')
1457 sys.stdout.flush()
1458 c = getchar()
1459
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001460 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001461 sys.stdout.write('\r \r')
1462 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001463 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001464 sys.stdout.write('\r \r' + lines[r] + '\n')
1465 r = r + 1
1466 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001467 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001468 r = r - inc - inc
1469 if r < 0: r = 0
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001470 sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001471 r = r + inc
1472
1473 finally:
1474 if tty:
1475 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1476
1477def plainpager(text):
1478 """Simply print unformatted text. This is the ultimate fallback."""
1479 sys.stdout.write(plain(text))
1480
1481def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001482 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001483 if inspect.ismodule(thing):
1484 if thing.__name__ in sys.builtin_module_names:
1485 return 'built-in module ' + thing.__name__
1486 if hasattr(thing, '__path__'):
1487 return 'package ' + thing.__name__
1488 else:
1489 return 'module ' + thing.__name__
1490 if inspect.isbuiltin(thing):
1491 return 'built-in function ' + thing.__name__
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001492 if inspect.isgetsetdescriptor(thing):
1493 return 'getset descriptor %s.%s.%s' % (
1494 thing.__objclass__.__module__, thing.__objclass__.__name__,
1495 thing.__name__)
1496 if inspect.ismemberdescriptor(thing):
1497 return 'member descriptor %s.%s.%s' % (
1498 thing.__objclass__.__module__, thing.__objclass__.__name__,
1499 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001500 if inspect.isclass(thing):
1501 return 'class ' + thing.__name__
1502 if inspect.isfunction(thing):
1503 return 'function ' + thing.__name__
1504 if inspect.ismethod(thing):
1505 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001506 return type(thing).__name__
1507
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001508def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001509 """Locate an object by name or dotted path, importing as necessary."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001510 parts = [part for part in path.split('.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001511 module, n = None, 0
1512 while n < len(parts):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001513 nextmodule = safeimport('.'.join(parts[:n+1]), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001514 if nextmodule: module, n = nextmodule, n + 1
1515 else: break
1516 if module:
1517 object = module
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001518 else:
Éric Araujoe64e51b2011-07-29 17:03:55 +02001519 object = builtins
1520 for part in parts[n:]:
1521 try:
1522 object = getattr(object, part)
1523 except AttributeError:
1524 return None
1525 return object
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001526
1527# --------------------------------------- interactive interpreter interface
1528
1529text = TextDoc()
Georg Brandld80d5f42010-12-03 07:47:22 +00001530plaintext = _PlainTextDoc()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001531html = HTMLDoc()
1532
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001533def resolve(thing, forceload=0):
1534 """Given an object or a path to an object, get the object and its name."""
1535 if isinstance(thing, str):
1536 object = locate(thing, forceload)
1537 if not object:
Collin Winterce36ad82007-08-30 01:19:48 +00001538 raise ImportError('no Python documentation found for %r' % thing)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001539 return object, thing
1540 else:
R David Murrayc43125a2012-04-23 13:23:57 -04001541 name = getattr(thing, '__name__', None)
1542 return thing, name if isinstance(name, str) else None
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001543
Georg Brandld80d5f42010-12-03 07:47:22 +00001544def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
1545 renderer=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001546 """Render text documentation, given an object or a path to an object."""
Georg Brandld80d5f42010-12-03 07:47:22 +00001547 if renderer is None:
1548 renderer = text
Guido van Rossumd8faa362007-04-27 19:54:29 +00001549 object, name = resolve(thing, forceload)
1550 desc = describe(object)
1551 module = inspect.getmodule(object)
1552 if name and '.' in name:
1553 desc += ' in ' + name[:name.rfind('.')]
1554 elif module and module is not object:
1555 desc += ' in module ' + module.__name__
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001556
1557 if not (inspect.ismodule(object) or
Guido van Rossumd8faa362007-04-27 19:54:29 +00001558 inspect.isclass(object) or
1559 inspect.isroutine(object) or
1560 inspect.isgetsetdescriptor(object) or
1561 inspect.ismemberdescriptor(object) or
1562 isinstance(object, property)):
1563 # If the passed object is a piece of data or an instance,
1564 # document its available methods instead of its value.
1565 object = type(object)
1566 desc += ' object'
Georg Brandld80d5f42010-12-03 07:47:22 +00001567 return title % desc + '\n\n' + renderer.document(object, name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001568
Georg Brandld80d5f42010-12-03 07:47:22 +00001569def doc(thing, title='Python Library Documentation: %s', forceload=0,
1570 output=None):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001571 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001572 try:
Georg Brandld80d5f42010-12-03 07:47:22 +00001573 if output is None:
1574 pager(render_doc(thing, title, forceload))
1575 else:
1576 output.write(render_doc(thing, title, forceload, plaintext))
Guido van Rossumb940e112007-01-10 16:19:56 +00001577 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001578 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001579
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001580def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001581 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001582 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001583 object, name = resolve(thing, forceload)
1584 page = html.page(describe(object), html.document(object, name))
Georg Brandl388faac2009-04-10 08:31:48 +00001585 file = open(name + '.html', 'w', encoding='utf-8')
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001586 file.write(page)
1587 file.close()
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001588 print('wrote', name + '.html')
Guido van Rossumb940e112007-01-10 16:19:56 +00001589 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001590 print(value)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001591
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001592def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001593 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001594 if done is None: done = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001595 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1596 writedoc(modname)
1597 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001598
1599class Helper:
Georg Brandl6b38daa2008-06-01 21:05:17 +00001600
1601 # These dictionaries map a topic name to either an alias, or a tuple
1602 # (label, seealso-items). The "label" is the label of the corresponding
1603 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl5617db82009-04-27 16:28:57 +00001604 # in pydoc_data/topics.py.
Georg Brandl6b38daa2008-06-01 21:05:17 +00001605 #
1606 # CAUTION: if you change one of these dictionaries, be sure to adapt the
1607 # list of needed labels in Doc/tools/sphinxext/pyspecific.py and
Georg Brandl5617db82009-04-27 16:28:57 +00001608 # regenerate the pydoc_data/topics.py file by running
Georg Brandl6b38daa2008-06-01 21:05:17 +00001609 # make pydoc-topics
1610 # in Doc/ and copying the output file into the Lib/ directory.
1611
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001612 keywords = {
Ezio Melottib185a042011-04-28 07:42:55 +03001613 'False': '',
1614 'None': '',
1615 'True': '',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001616 'and': 'BOOLEAN',
Guido van Rossumd8faa362007-04-27 19:54:29 +00001617 'as': 'with',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001618 'assert': ('assert', ''),
1619 'break': ('break', 'while for'),
1620 'class': ('class', 'CLASSES SPECIALMETHODS'),
1621 'continue': ('continue', 'while for'),
1622 'def': ('function', ''),
1623 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001624 'elif': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001625 'else': ('else', 'while for'),
Georg Brandl0d855392008-08-30 19:53:05 +00001626 'except': 'try',
1627 'finally': 'try',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001628 'for': ('for', 'break continue while'),
Georg Brandl0d855392008-08-30 19:53:05 +00001629 'from': 'import',
Georg Brandl74abf6f2010-11-20 19:54:36 +00001630 'global': ('global', 'nonlocal NAMESPACES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001631 'if': ('if', 'TRUTHVALUE'),
1632 'import': ('import', 'MODULES'),
Georg Brandl395ed242009-09-04 08:07:32 +00001633 'in': ('in', 'SEQUENCEMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001634 'is': 'COMPARISON',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001635 'lambda': ('lambda', 'FUNCTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001636 'nonlocal': ('nonlocal', 'global NAMESPACES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001637 'not': 'BOOLEAN',
1638 'or': 'BOOLEAN',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001639 'pass': ('pass', ''),
1640 'raise': ('raise', 'EXCEPTIONS'),
1641 'return': ('return', 'FUNCTIONS'),
1642 'try': ('try', 'EXCEPTIONS'),
1643 'while': ('while', 'break continue if TRUTHVALUE'),
1644 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1645 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001646 }
Georg Brandldb7b6b92009-01-01 15:53:14 +00001647 # Either add symbols to this dictionary or to the symbols dictionary
1648 # directly: Whichever is easier. They are merged later.
1649 _symbols_inverse = {
1650 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'),
1651 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1652 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1653 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1654 'UNARY' : ('-', '~'),
1655 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1656 '^=', '<<=', '>>=', '**=', '//='),
1657 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1658 'COMPLEX' : ('j', 'J')
1659 }
1660 symbols = {
1661 '%': 'OPERATORS FORMATTING',
1662 '**': 'POWER',
1663 ',': 'TUPLES LISTS FUNCTIONS',
1664 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1665 '...': 'ELLIPSIS',
1666 ':': 'SLICINGS DICTIONARYLITERALS',
1667 '@': 'def class',
1668 '\\': 'STRINGS',
1669 '_': 'PRIVATENAMES',
1670 '__': 'PRIVATENAMES SPECIALMETHODS',
1671 '`': 'BACKQUOTES',
1672 '(': 'TUPLES FUNCTIONS CALLS',
1673 ')': 'TUPLES FUNCTIONS CALLS',
1674 '[': 'LISTS SUBSCRIPTS SLICINGS',
1675 ']': 'LISTS SUBSCRIPTS SLICINGS'
1676 }
1677 for topic, symbols_ in _symbols_inverse.items():
1678 for symbol in symbols_:
1679 topics = symbols.get(symbol, topic)
1680 if topic not in topics:
1681 topics = topics + ' ' + topic
1682 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001683
1684 topics = {
Georg Brandl6b38daa2008-06-01 21:05:17 +00001685 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1686 'FUNCTIONS CLASSES MODULES FILES inspect'),
1687 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS '
1688 'FORMATTING TYPES'),
1689 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1690 'FORMATTING': ('formatstrings', 'OPERATORS'),
1691 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1692 'FORMATTING TYPES'),
1693 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1694 'INTEGER': ('integers', 'int range'),
1695 'FLOAT': ('floating', 'float math'),
1696 'COMPLEX': ('imaginary', 'complex cmath'),
1697 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING range LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001698 'MAPPINGS': 'DICTIONARIES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001699 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1700 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1701 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1702 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001703 'FRAMEOBJECTS': 'TYPES',
1704 'TRACEBACKS': 'TYPES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001705 'NONE': ('bltin-null-object', ''),
1706 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
1707 'FILES': ('bltin-file-objects', ''),
1708 'SPECIALATTRIBUTES': ('specialattrs', ''),
1709 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1710 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001711 'PACKAGES': 'import',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001712 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1713 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1714 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1715 'LISTS DICTIONARIES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001716 'OPERATORS': 'EXPRESSIONS',
1717 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001718 'OBJECTS': ('objects', 'TYPES'),
1719 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
Georg Brandl395ed242009-09-04 08:07:32 +00001720 'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS '
1721 'NUMBERMETHODS CLASSES'),
Mark Dickinsona56c4672009-01-27 18:17:45 +00001722 'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001723 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1724 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001725 'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS '
Georg Brandl6b38daa2008-06-01 21:05:17 +00001726 'SPECIALMETHODS'),
1727 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1728 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1729 'SPECIALMETHODS'),
1730 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001731 'NAMESPACES': ('naming', 'global nonlocal ASSIGNMENT DELETION DYNAMICFEATURES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001732 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001733 'SCOPING': 'NAMESPACES',
1734 'FRAMES': 'NAMESPACES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001735 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1736 'CONVERSIONS': ('conversions', ''),
1737 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1738 'SPECIALIDENTIFIERS': ('id-classes', ''),
1739 'PRIVATENAMES': ('atom-identifiers', ''),
1740 'LITERALS': ('atom-literals', 'STRINGS NUMBERS TUPLELITERALS '
1741 'LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001742 'TUPLES': 'SEQUENCES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001743 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1744 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1745 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1746 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1747 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1748 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001749 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'),
1750 'SLICINGS': ('slicings', 'SEQUENCEMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001751 'CALLS': ('calls', 'EXPRESSIONS'),
1752 'POWER': ('power', 'EXPRESSIONS'),
1753 'UNARY': ('unary', 'EXPRESSIONS'),
1754 'BINARY': ('binary', 'EXPRESSIONS'),
1755 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1756 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1757 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1758 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001759 'ASSERTION': 'assert',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001760 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1761 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001762 'DELETION': 'del',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001763 'RETURNING': 'return',
1764 'IMPORTING': 'import',
1765 'CONDITIONAL': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001766 'LOOPING': ('compound', 'for while break continue'),
1767 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1768 'DEBUGGING': ('debugger', 'pdb'),
1769 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001770 }
1771
Georg Brandl78aa3962010-07-31 21:51:48 +00001772 def __init__(self, input=None, output=None):
1773 self._input = input
1774 self._output = output
1775
Georg Brandl76ae3972010-08-01 06:32:55 +00001776 input = property(lambda self: self._input or sys.stdin)
1777 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001778
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001779 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001780 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001781 self()
1782 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001783 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001784
Alexander Belopolsky2e733c92010-07-04 17:00:20 +00001785 _GoInteractive = object()
1786 def __call__(self, request=_GoInteractive):
1787 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001788 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001789 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001790 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001791 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001792 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001793You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001794If you want to ask for help on a particular object directly from the
1795interpreter, you can type "help(object)". Executing "help('string')"
1796has the same effect as typing a particular string at the help> prompt.
1797''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001798
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001799 def interact(self):
1800 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001801 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001802 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001803 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001804 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001805 except (KeyboardInterrupt, EOFError):
1806 break
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001807 request = replace(request, '"', '', "'", '').strip()
1808 if request.lower() in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001809 self.help(request)
1810
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001811 def getline(self, prompt):
Guido van Rossum7c086c02008-01-02 03:52:38 +00001812 """Read one line, using input() when appropriate."""
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001813 if self.input is sys.stdin:
Guido van Rossum7c086c02008-01-02 03:52:38 +00001814 return input(prompt)
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001815 else:
1816 self.output.write(prompt)
1817 self.output.flush()
1818 return self.input.readline()
1819
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001820 def help(self, request):
1821 if type(request) is type(''):
R. David Murray1f1b9d32009-05-27 20:56:59 +00001822 request = request.strip()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001823 if request == 'help': self.intro()
1824 elif request == 'keywords': self.listkeywords()
Georg Brandldb7b6b92009-01-01 15:53:14 +00001825 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001826 elif request == 'topics': self.listtopics()
1827 elif request == 'modules': self.listmodules()
1828 elif request[:8] == 'modules ':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001829 self.listmodules(request.split()[1])
Georg Brandldb7b6b92009-01-01 15:53:14 +00001830 elif request in self.symbols: self.showsymbol(request)
Ezio Melottib185a042011-04-28 07:42:55 +03001831 elif request in ['True', 'False', 'None']:
1832 # special case these keywords since they are objects too
1833 doc(eval(request), 'Help on %s:')
Raymond Hettinger54f02222002-06-01 14:18:47 +00001834 elif request in self.keywords: self.showtopic(request)
1835 elif request in self.topics: self.showtopic(request)
Georg Brandld80d5f42010-12-03 07:47:22 +00001836 elif request: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001837 elif isinstance(request, Helper): self()
Georg Brandld80d5f42010-12-03 07:47:22 +00001838 else: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001839 self.output.write('\n')
1840
1841 def intro(self):
1842 self.output.write('''
Georg Brandlc645c6a2012-06-24 17:24:26 +02001843Welcome to Python %s! This is the interactive help utility.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001844
1845If this is your first time using Python, you should definitely check out
R David Murrayde0f6292012-03-31 12:06:35 -04001846the tutorial on the Internet at http://docs.python.org/%s/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001847
1848Enter the name of any module, keyword, or topic to get help on writing
1849Python programs and using Python modules. To quit this help utility and
1850return to the interpreter, just type "quit".
1851
Terry Jan Reedy34200572013-02-11 02:23:13 -05001852To get a list of available modules, keywords, symbols, or topics, type
1853"modules", "keywords", "symbols", or "topics". Each module also comes
1854with a one-line summary of what it does; to list the modules whose name
1855or summary contain a given string such as "spam", type "modules spam".
R David Murrayde0f6292012-03-31 12:06:35 -04001856''' % tuple([sys.version[:3]]*2))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001857
1858 def list(self, items, columns=4, width=80):
Guido van Rossum486364b2007-06-30 05:01:58 +00001859 items = list(sorted(items))
1860 colw = width // columns
1861 rows = (len(items) + columns - 1) // columns
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001862 for row in range(rows):
1863 for col in range(columns):
1864 i = col * rows + row
1865 if i < len(items):
1866 self.output.write(items[i])
1867 if col < columns - 1:
Guido van Rossum486364b2007-06-30 05:01:58 +00001868 self.output.write(' ' + ' ' * (colw - 1 - len(items[i])))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001869 self.output.write('\n')
1870
1871 def listkeywords(self):
1872 self.output.write('''
1873Here is a list of the Python keywords. Enter any keyword to get more help.
1874
1875''')
1876 self.list(self.keywords.keys())
1877
Georg Brandldb7b6b92009-01-01 15:53:14 +00001878 def listsymbols(self):
1879 self.output.write('''
1880Here is a list of the punctuation symbols which Python assigns special meaning
1881to. Enter any symbol to get more help.
1882
1883''')
1884 self.list(self.symbols.keys())
1885
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001886 def listtopics(self):
1887 self.output.write('''
1888Here is a list of available topics. Enter any topic name to get more help.
1889
1890''')
1891 self.list(self.topics.keys())
1892
Georg Brandldb7b6b92009-01-01 15:53:14 +00001893 def showtopic(self, topic, more_xrefs=''):
Georg Brandl6b38daa2008-06-01 21:05:17 +00001894 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001895 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04001896 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001897 self.output.write('''
Georg Brandl6b38daa2008-06-01 21:05:17 +00001898Sorry, topic and keyword documentation is not available because the
Georg Brandl5617db82009-04-27 16:28:57 +00001899module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001900''')
1901 return
1902 target = self.topics.get(topic, self.keywords.get(topic))
1903 if not target:
1904 self.output.write('no documentation found for %s\n' % repr(topic))
1905 return
1906 if type(target) is type(''):
Georg Brandldb7b6b92009-01-01 15:53:14 +00001907 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001908
Georg Brandl6b38daa2008-06-01 21:05:17 +00001909 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001910 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001911 doc = pydoc_data.topics.topics[label]
Georg Brandl6b38daa2008-06-01 21:05:17 +00001912 except KeyError:
1913 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001914 return
Georg Brandl6b38daa2008-06-01 21:05:17 +00001915 pager(doc.strip() + '\n')
Georg Brandldb7b6b92009-01-01 15:53:14 +00001916 if more_xrefs:
1917 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001918 if xrefs:
Brett Cannon1448ecf2013-10-04 11:38:59 -04001919 import textwrap
1920 text = 'Related help topics: ' + ', '.join(xrefs.split()) + '\n'
1921 wrapped_text = textwrap.wrap(text, 72)
1922 self.output.write('\n%s\n' % ''.join(wrapped_text))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001923
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001924 def _gettopic(self, topic, more_xrefs=''):
1925 """Return unbuffered tuple of (topic, xrefs).
1926
Georg Brandld2f38572011-01-30 08:37:19 +00001927 If an error occurs here, the exception is caught and displayed by
1928 the url handler.
1929
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001930 This function duplicates the showtopic method but returns its
1931 result directly so it can be formatted for display in an html page.
1932 """
1933 try:
1934 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04001935 except ImportError:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001936 return('''
1937Sorry, topic and keyword documentation is not available because the
1938module "pydoc_data.topics" could not be found.
1939''' , '')
1940 target = self.topics.get(topic, self.keywords.get(topic))
1941 if not target:
Georg Brandld2f38572011-01-30 08:37:19 +00001942 raise ValueError('could not find topic')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001943 if isinstance(target, str):
1944 return self._gettopic(target, more_xrefs)
1945 label, xrefs = target
Georg Brandld2f38572011-01-30 08:37:19 +00001946 doc = pydoc_data.topics.topics[label]
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001947 if more_xrefs:
1948 xrefs = (xrefs or '') + ' ' + more_xrefs
1949 return doc, xrefs
1950
Georg Brandldb7b6b92009-01-01 15:53:14 +00001951 def showsymbol(self, symbol):
1952 target = self.symbols[symbol]
1953 topic, _, xrefs = target.partition(' ')
1954 self.showtopic(topic, xrefs)
1955
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001956 def listmodules(self, key=''):
1957 if key:
1958 self.output.write('''
Terry Jan Reedy34200572013-02-11 02:23:13 -05001959Here is a list of modules whose name or summary contains '{}'.
1960If there are any, enter a module name to get more help.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001961
Terry Jan Reedy34200572013-02-11 02:23:13 -05001962'''.format(key))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001963 apropos(key)
1964 else:
1965 self.output.write('''
1966Please wait a moment while I gather a list of all available modules...
1967
1968''')
1969 modules = {}
1970 def callback(path, modname, desc, modules=modules):
1971 if modname and modname[-9:] == '.__init__':
1972 modname = modname[:-9] + ' (package)'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001973 if modname.find('.') < 0:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001974 modules[modname] = 1
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001975 def onerror(modname):
1976 callback(None, modname, None)
1977 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001978 self.list(modules.keys())
1979 self.output.write('''
1980Enter any module name to get more help. Or, type "modules spam" to search
Terry Jan Reedy34200572013-02-11 02:23:13 -05001981for modules whose name or summary contain the string "spam".
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001982''')
1983
Georg Brandl78aa3962010-07-31 21:51:48 +00001984help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001985
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001986class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001987 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001988
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001989 def run(self, callback, key=None, completer=None, onerror=None):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001990 if key: key = key.lower()
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001991 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001992 seen = {}
1993
1994 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001995 if modname != '__main__':
1996 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00001997 if key is None:
1998 callback(None, modname, '')
1999 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002000 name = __import__(modname).__doc__ or ''
2001 desc = name.split('\n')[0]
2002 name = modname + ' - ' + desc
2003 if name.lower().find(key) >= 0:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002004 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002005
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002006 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002007 if self.quit:
2008 break
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002009
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002010 if key is None:
2011 callback(None, modname, '')
2012 else:
Georg Brandl126c8792009-04-05 15:05:48 +00002013 try:
2014 loader = importer.find_module(modname)
2015 except SyntaxError:
2016 # raised by tests for bad coding cookies or BOM
2017 continue
2018 if hasattr(loader, 'get_source'):
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002019 try:
2020 source = loader.get_source(modname)
Nick Coghlan2824cb52012-07-15 22:12:14 +10002021 except Exception:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002022 if onerror:
2023 onerror(modname)
2024 continue
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002025 desc = source_synopsis(io.StringIO(source)) or ''
Georg Brandl126c8792009-04-05 15:05:48 +00002026 if hasattr(loader, 'get_filename'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002027 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002028 else:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002029 path = None
2030 else:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002031 try:
2032 module = loader.load_module(modname)
2033 except ImportError:
2034 if onerror:
2035 onerror(modname)
2036 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002037 desc = (module.__doc__ or '').splitlines()[0]
2038 path = getattr(module,'__file__',None)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002039 name = modname + ' - ' + desc
2040 if name.lower().find(key) >= 0:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002041 callback(path, modname, desc)
2042
2043 if completer:
2044 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002045
2046def apropos(key):
2047 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002048 def callback(path, modname, desc):
2049 if modname[-9:] == '.__init__':
2050 modname = modname[:-9] + ' (package)'
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002051 print(modname, desc and '- ' + desc)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002052 def onerror(modname):
2053 pass
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002054 with warnings.catch_warnings():
2055 warnings.filterwarnings('ignore') # ignore problems during import
2056 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002057
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002058# --------------------------------------- enhanced Web browser interface
2059
2060def _start_server(urlhandler, port):
2061 """Start an HTTP server thread on a specific port.
2062
2063 Start an HTML/text server thread, so HTML or text documents can be
2064 browsed dynamically and interactively with a Web browser. Example use:
2065
2066 >>> import time
2067 >>> import pydoc
2068
2069 Define a URL handler. To determine what the client is asking
2070 for, check the URL and content_type.
2071
2072 Then get or generate some text or HTML code and return it.
2073
2074 >>> def my_url_handler(url, content_type):
2075 ... text = 'the URL sent was: (%s, %s)' % (url, content_type)
2076 ... return text
2077
2078 Start server thread on port 0.
2079 If you use port 0, the server will pick a random port number.
2080 You can then use serverthread.port to get the port number.
2081
2082 >>> port = 0
2083 >>> serverthread = pydoc._start_server(my_url_handler, port)
2084
2085 Check that the server is really started. If it is, open browser
2086 and get first page. Use serverthread.url as the starting page.
2087
2088 >>> if serverthread.serving:
2089 ... import webbrowser
2090
2091 The next two lines are commented out so a browser doesn't open if
2092 doctest is run on this module.
2093
2094 #... webbrowser.open(serverthread.url)
2095 #True
2096
2097 Let the server do its thing. We just need to monitor its status.
2098 Use time.sleep so the loop doesn't hog the CPU.
2099
2100 >>> starttime = time.time()
2101 >>> timeout = 1 #seconds
2102
2103 This is a short timeout for testing purposes.
2104
2105 >>> while serverthread.serving:
2106 ... time.sleep(.01)
2107 ... if serverthread.serving and time.time() - starttime > timeout:
2108 ... serverthread.stop()
2109 ... break
2110
2111 Print any errors that may have occurred.
2112
2113 >>> print(serverthread.error)
2114 None
2115 """
2116 import http.server
2117 import email.message
2118 import select
2119 import threading
2120
2121 class DocHandler(http.server.BaseHTTPRequestHandler):
2122
2123 def do_GET(self):
2124 """Process a request from an HTML browser.
2125
2126 The URL received is in self.path.
2127 Get an HTML page from self.urlhandler and send it.
2128 """
2129 if self.path.endswith('.css'):
2130 content_type = 'text/css'
2131 else:
2132 content_type = 'text/html'
2133 self.send_response(200)
Georg Brandld2f38572011-01-30 08:37:19 +00002134 self.send_header('Content-Type', '%s; charset=UTF-8' % content_type)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002135 self.end_headers()
2136 self.wfile.write(self.urlhandler(
2137 self.path, content_type).encode('utf-8'))
2138
2139 def log_message(self, *args):
2140 # Don't log messages.
2141 pass
2142
2143 class DocServer(http.server.HTTPServer):
2144
2145 def __init__(self, port, callback):
2146 self.host = (sys.platform == 'mac') and '127.0.0.1' or 'localhost'
2147 self.address = ('', port)
2148 self.callback = callback
2149 self.base.__init__(self, self.address, self.handler)
2150 self.quit = False
2151
2152 def serve_until_quit(self):
2153 while not self.quit:
2154 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2155 if rd:
2156 self.handle_request()
Victor Stinnera3abd1d2011-01-03 16:12:39 +00002157 self.server_close()
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002158
2159 def server_activate(self):
2160 self.base.server_activate(self)
2161 if self.callback:
2162 self.callback(self)
2163
2164 class ServerThread(threading.Thread):
2165
2166 def __init__(self, urlhandler, port):
2167 self.urlhandler = urlhandler
2168 self.port = int(port)
2169 threading.Thread.__init__(self)
2170 self.serving = False
2171 self.error = None
2172
2173 def run(self):
2174 """Start the server."""
2175 try:
2176 DocServer.base = http.server.HTTPServer
2177 DocServer.handler = DocHandler
2178 DocHandler.MessageClass = email.message.Message
2179 DocHandler.urlhandler = staticmethod(self.urlhandler)
2180 docsvr = DocServer(self.port, self.ready)
2181 self.docserver = docsvr
2182 docsvr.serve_until_quit()
2183 except Exception as e:
2184 self.error = e
2185
2186 def ready(self, server):
2187 self.serving = True
2188 self.host = server.host
2189 self.port = server.server_port
2190 self.url = 'http://%s:%d/' % (self.host, self.port)
2191
2192 def stop(self):
2193 """Stop the server and this thread nicely"""
2194 self.docserver.quit = True
2195 self.serving = False
2196 self.url = None
2197
2198 thread = ServerThread(urlhandler, port)
2199 thread.start()
2200 # Wait until thread.serving is True to make sure we are
2201 # really up before returning.
2202 while not thread.error and not thread.serving:
2203 time.sleep(.01)
2204 return thread
2205
2206
2207def _url_handler(url, content_type="text/html"):
2208 """The pydoc url handler for use with the pydoc server.
2209
2210 If the content_type is 'text/css', the _pydoc.css style
2211 sheet is read and returned if it exits.
2212
2213 If the content_type is 'text/html', then the result of
2214 get_html_page(url) is returned.
2215 """
2216 class _HTMLDoc(HTMLDoc):
2217
2218 def page(self, title, contents):
2219 """Format an HTML page."""
2220 css_path = "pydoc_data/_pydoc.css"
2221 css_link = (
2222 '<link rel="stylesheet" type="text/css" href="%s">' %
2223 css_path)
2224 return '''\
2225<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Georg Brandld2f38572011-01-30 08:37:19 +00002226<html><head><title>Pydoc: %s</title>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002227<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Georg Brandld2f38572011-01-30 08:37:19 +00002228%s</head><body bgcolor="#f0f0f8">%s<div style="clear:both;padding-top:.5em;">%s</div>
2229</body></html>''' % (title, css_link, html_navbar(), contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002230
2231 def filelink(self, url, path):
2232 return '<a href="getfile?key=%s">%s</a>' % (url, path)
2233
2234
2235 html = _HTMLDoc()
2236
2237 def html_navbar():
Georg Brandld2f38572011-01-30 08:37:19 +00002238 version = html.escape("%s [%s, %s]" % (platform.python_version(),
2239 platform.python_build()[0],
2240 platform.python_compiler()))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002241 return """
2242 <div style='float:left'>
Georg Brandld2f38572011-01-30 08:37:19 +00002243 Python %s<br>%s
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002244 </div>
2245 <div style='float:right'>
2246 <div style='text-align:center'>
2247 <a href="index.html">Module Index</a>
2248 : <a href="topics.html">Topics</a>
2249 : <a href="keywords.html">Keywords</a>
2250 </div>
2251 <div>
Georg Brandld2f38572011-01-30 08:37:19 +00002252 <form action="get" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002253 <input type=text name=key size=15>
2254 <input type=submit value="Get">
Georg Brandld2f38572011-01-30 08:37:19 +00002255 </form>&nbsp;
2256 <form action="search" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002257 <input type=text name=key size=15>
2258 <input type=submit value="Search">
2259 </form>
2260 </div>
2261 </div>
Georg Brandld2f38572011-01-30 08:37:19 +00002262 """ % (version, html.escape(platform.platform(terse=True)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002263
2264 def html_index():
2265 """Module Index page."""
2266
2267 def bltinlink(name):
2268 return '<a href="%s.html">%s</a>' % (name, name)
2269
2270 heading = html.heading(
2271 '<big><big><strong>Index of Modules</strong></big></big>',
2272 '#ffffff', '#7799ee')
2273 names = [name for name in sys.builtin_module_names
2274 if name != '__main__']
2275 contents = html.multicolumn(names, bltinlink)
2276 contents = [heading, '<p>' + html.bigsection(
2277 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2278
2279 seen = {}
2280 for dir in sys.path:
2281 contents.append(html.index(dir, seen))
2282
2283 contents.append(
2284 '<p align=right><font color="#909090" face="helvetica,'
2285 'arial"><strong>pydoc</strong> by Ka-Ping Yee'
2286 '&lt;ping@lfw.org&gt;</font>')
Nick Coghlanecace282010-12-03 16:08:46 +00002287 return 'Index of Modules', ''.join(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002288
2289 def html_search(key):
2290 """Search results page."""
2291 # scan for modules
2292 search_result = []
2293
2294 def callback(path, modname, desc):
2295 if modname[-9:] == '.__init__':
2296 modname = modname[:-9] + ' (package)'
2297 search_result.append((modname, desc and '- ' + desc))
2298
2299 with warnings.catch_warnings():
2300 warnings.filterwarnings('ignore') # ignore problems during import
2301 ModuleScanner().run(callback, key)
2302
2303 # format page
2304 def bltinlink(name):
2305 return '<a href="%s.html">%s</a>' % (name, name)
2306
2307 results = []
2308 heading = html.heading(
2309 '<big><big><strong>Search Results</strong></big></big>',
2310 '#ffffff', '#7799ee')
2311 for name, desc in search_result:
2312 results.append(bltinlink(name) + desc)
2313 contents = heading + html.bigsection(
2314 'key = %s' % key, '#ffffff', '#ee77aa', '<br>'.join(results))
Nick Coghlanecace282010-12-03 16:08:46 +00002315 return 'Search Results', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002316
2317 def html_getfile(path):
2318 """Get and display a source file listing safely."""
Nick Coghlanecace282010-12-03 16:08:46 +00002319 path = path.replace('%20', ' ')
Victor Stinner91e08772011-07-05 14:30:41 +02002320 with tokenize.open(path) as fp:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002321 lines = html.escape(fp.read())
2322 body = '<pre>%s</pre>' % lines
2323 heading = html.heading(
2324 '<big><big><strong>File Listing</strong></big></big>',
2325 '#ffffff', '#7799ee')
2326 contents = heading + html.bigsection(
2327 'File: %s' % path, '#ffffff', '#ee77aa', body)
Nick Coghlanecace282010-12-03 16:08:46 +00002328 return 'getfile %s' % path, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002329
2330 def html_topics():
2331 """Index of topic texts available."""
2332
2333 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002334 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002335
2336 heading = html.heading(
2337 '<big><big><strong>INDEX</strong></big></big>',
2338 '#ffffff', '#7799ee')
2339 names = sorted(Helper.topics.keys())
2340
2341 contents = html.multicolumn(names, bltinlink)
2342 contents = heading + html.bigsection(
2343 'Topics', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002344 return 'Topics', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002345
2346 def html_keywords():
2347 """Index of keywords."""
2348 heading = html.heading(
2349 '<big><big><strong>INDEX</strong></big></big>',
2350 '#ffffff', '#7799ee')
2351 names = sorted(Helper.keywords.keys())
2352
2353 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002354 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002355
2356 contents = html.multicolumn(names, bltinlink)
2357 contents = heading + html.bigsection(
2358 'Keywords', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002359 return 'Keywords', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002360
2361 def html_topicpage(topic):
2362 """Topic or keyword help page."""
2363 buf = io.StringIO()
2364 htmlhelp = Helper(buf, buf)
2365 contents, xrefs = htmlhelp._gettopic(topic)
2366 if topic in htmlhelp.keywords:
2367 title = 'KEYWORD'
2368 else:
2369 title = 'TOPIC'
2370 heading = html.heading(
2371 '<big><big><strong>%s</strong></big></big>' % title,
2372 '#ffffff', '#7799ee')
Georg Brandld2f38572011-01-30 08:37:19 +00002373 contents = '<pre>%s</pre>' % html.markup(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002374 contents = html.bigsection(topic , '#ffffff','#ee77aa', contents)
Georg Brandld2f38572011-01-30 08:37:19 +00002375 if xrefs:
2376 xrefs = sorted(xrefs.split())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002377
Georg Brandld2f38572011-01-30 08:37:19 +00002378 def bltinlink(name):
2379 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002380
Georg Brandld2f38572011-01-30 08:37:19 +00002381 xrefs = html.multicolumn(xrefs, bltinlink)
2382 xrefs = html.section('Related help topics: ',
2383 '#ffffff', '#ee77aa', xrefs)
Nick Coghlanecace282010-12-03 16:08:46 +00002384 return ('%s %s' % (title, topic),
2385 ''.join((heading, contents, xrefs)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002386
Georg Brandld2f38572011-01-30 08:37:19 +00002387 def html_getobj(url):
2388 obj = locate(url, forceload=1)
2389 if obj is None and url != 'None':
2390 raise ValueError('could not find object')
2391 title = describe(obj)
2392 content = html.document(obj, url)
2393 return title, content
2394
2395 def html_error(url, exc):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002396 heading = html.heading(
2397 '<big><big><strong>Error</strong></big></big>',
Georg Brandld2f38572011-01-30 08:37:19 +00002398 '#ffffff', '#7799ee')
2399 contents = '<br>'.join(html.escape(line) for line in
2400 format_exception_only(type(exc), exc))
2401 contents = heading + html.bigsection(url, '#ffffff', '#bb0000',
2402 contents)
2403 return "Error - %s" % url, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002404
2405 def get_html_page(url):
2406 """Generate an HTML page for url."""
Georg Brandld2f38572011-01-30 08:37:19 +00002407 complete_url = url
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002408 if url.endswith('.html'):
2409 url = url[:-5]
Georg Brandld2f38572011-01-30 08:37:19 +00002410 try:
2411 if url in ("", "index"):
2412 title, content = html_index()
2413 elif url == "topics":
2414 title, content = html_topics()
2415 elif url == "keywords":
2416 title, content = html_keywords()
2417 elif '=' in url:
2418 op, _, url = url.partition('=')
2419 if op == "search?key":
2420 title, content = html_search(url)
2421 elif op == "getfile?key":
2422 title, content = html_getfile(url)
2423 elif op == "topic?key":
2424 # try topics first, then objects.
2425 try:
2426 title, content = html_topicpage(url)
2427 except ValueError:
2428 title, content = html_getobj(url)
2429 elif op == "get?key":
2430 # try objects first, then topics.
2431 if url in ("", "index"):
2432 title, content = html_index()
2433 else:
2434 try:
2435 title, content = html_getobj(url)
2436 except ValueError:
2437 title, content = html_topicpage(url)
2438 else:
2439 raise ValueError('bad pydoc url')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002440 else:
Georg Brandld2f38572011-01-30 08:37:19 +00002441 title, content = html_getobj(url)
2442 except Exception as exc:
2443 # Catch any errors and display them in an error page.
2444 title, content = html_error(complete_url, exc)
2445 return html.page(title, content)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002446
2447 if url.startswith('/'):
2448 url = url[1:]
2449 if content_type == 'text/css':
2450 path_here = os.path.dirname(os.path.realpath(__file__))
Georg Brandld2f38572011-01-30 08:37:19 +00002451 css_path = os.path.join(path_here, url)
2452 with open(css_path) as fp:
2453 return ''.join(fp.readlines())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002454 elif content_type == 'text/html':
2455 return get_html_page(url)
Georg Brandld2f38572011-01-30 08:37:19 +00002456 # Errors outside the url handler are caught by the server.
2457 raise TypeError('unknown content type %r for url %s' % (content_type, url))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002458
2459
2460def browse(port=0, *, open_browser=True):
2461 """Start the enhanced pydoc Web server and open a Web browser.
2462
2463 Use port '0' to start the server on an arbitrary port.
2464 Set open_browser to False to suppress opening a browser.
2465 """
2466 import webbrowser
2467 serverthread = _start_server(_url_handler, port)
2468 if serverthread.error:
2469 print(serverthread.error)
2470 return
2471 if serverthread.serving:
2472 server_help_msg = 'Server commands: [b]rowser, [q]uit'
2473 if open_browser:
2474 webbrowser.open(serverthread.url)
2475 try:
2476 print('Server ready at', serverthread.url)
2477 print(server_help_msg)
2478 while serverthread.serving:
2479 cmd = input('server> ')
2480 cmd = cmd.lower()
2481 if cmd == 'q':
2482 break
2483 elif cmd == 'b':
2484 webbrowser.open(serverthread.url)
2485 else:
2486 print(server_help_msg)
2487 except (KeyboardInterrupt, EOFError):
2488 print()
2489 finally:
2490 if serverthread.serving:
2491 serverthread.stop()
2492 print('Server stopped')
2493
2494
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002495# -------------------------------------------------- command-line interface
2496
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002497def ispath(x):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002498 return isinstance(x, str) and x.find(os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002499
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002500def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002501 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002502 import getopt
Guido van Rossum756aa932007-04-07 03:04:01 +00002503 class BadUsage(Exception): pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002504
Nick Coghlan106274b2009-11-15 23:04:33 +00002505 # Scripts don't get the current directory in their path by default
2506 # unless they are run with the '-m' switch
2507 if '' not in sys.path:
2508 scriptdir = os.path.dirname(sys.argv[0])
2509 if scriptdir in sys.path:
2510 sys.path.remove(scriptdir)
2511 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002512
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002513 try:
Victor Stinner383c3fc2011-05-25 01:35:05 +02002514 opts, args = getopt.getopt(sys.argv[1:], 'bk:p:w')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002515 writing = False
2516 start_server = False
2517 open_browser = False
2518 port = None
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002519 for opt, val in opts:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002520 if opt == '-b':
2521 start_server = True
2522 open_browser = True
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002523 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002524 apropos(val)
2525 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002526 if opt == '-p':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002527 start_server = True
2528 port = val
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002529 if opt == '-w':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002530 writing = True
2531
Benjamin Petersonb29614e2012-10-09 11:16:03 -04002532 if start_server:
2533 if port is None:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002534 port = 0
2535 browse(port, open_browser=open_browser)
2536 return
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002537
2538 if not args: raise BadUsage
2539 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002540 if ispath(arg) and not os.path.exists(arg):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002541 print('file %r does not exist' % arg)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002542 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002543 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002544 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002545 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002546 if writing:
2547 if ispath(arg) and os.path.isdir(arg):
2548 writedocs(arg)
2549 else:
2550 writedoc(arg)
2551 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002552 help.help(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +00002553 except ErrorDuringImport as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002554 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002555
2556 except (getopt.error, BadUsage):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002557 cmd = os.path.splitext(os.path.basename(sys.argv[0]))[0]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002558 print("""pydoc - the Python documentation tool
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002559
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002560{cmd} <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002561 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002562 Python keyword, topic, function, module, or package, or a dotted
2563 reference to a class or function within a module or module in a
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002564 package. If <name> contains a '{sep}', it is used as the path to a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002565 Python source file to document. If name is 'keywords', 'topics',
2566 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002567
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002568{cmd} -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002569 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002570
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002571{cmd} -p <port>
2572 Start an HTTP server on the given port on the local machine. Port
2573 number 0 can be used to get an arbitrary unused port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002574
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002575{cmd} -b
2576 Start an HTTP server on an arbitrary unused port and open a Web browser
2577 to interactively browse documentation. The -p option can be used with
2578 the -b option to explicitly specify the server port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002579
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002580{cmd} -w <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002581 Write out the HTML documentation for a module to a file in the current
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002582 directory. If <name> contains a '{sep}', it is treated as a filename; if
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002583 it names a directory, documentation is written for all the contents.
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002584""".format(cmd=cmd, sep=os.sep))
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002585
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002586if __name__ == '__main__':
2587 cli()