blob: e8127a290908805399b3d6274c540e403efd1f68 [file] [log] [blame]
Benjamin Peterson90f5ba52010-03-11 22:53:45 +00001#!/usr/bin/env python3
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002"""Generate Python documentation in HTML or text for interactive use.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00003
Georg Brandlc645c6a2012-06-24 17:24:26 +02004In the Python interpreter, do "from pydoc import help" to provide
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00005help. Calling help(thing) on a Python object documents the object.
6
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00007Or, at the shell command line outside of Python:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00008
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00009Run "pydoc <name>" to show documentation on something. <name> may be
10the name of a function, module, package, or a dotted reference to a
11class or function within a module or module in a package. If the
12argument contains a path segment delimiter (e.g. slash on Unix,
13backslash on Windows) it is treated as the path to a Python source file.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000014
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000015Run "pydoc -k <keyword>" to search for a keyword in the synopsis lines
16of all available modules.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000017
Nick Coghlan7bb30b72010-12-03 09:29:11 +000018Run "pydoc -p <port>" to start an HTTP server on the given port on the
19local machine. Port number 0 can be used to get an arbitrary unused port.
20
21Run "pydoc -b" to start an HTTP server on an arbitrary unused port and
22open a Web browser to interactively browse documentation. The -p option
23can be used with the -b option to explicitly specify the server port.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000024
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000025Run "pydoc -w <name>" to write out the HTML documentation for a module
26to a file named "<name>.html".
Skip Montanaro4997a692003-09-10 16:47:51 +000027
28Module docs for core modules are assumed to be in
29
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000030 http://docs.python.org/X.Y/library/
Skip Montanaro4997a692003-09-10 16:47:51 +000031
32This can be overridden by setting the PYTHONDOCS environment variable
33to a different URL or to a local directory containing the Library
34Reference Manual pages.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000035"""
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000036__all__ = ['help']
Ka-Ping Yeedd175342001-02-27 14:43:46 +000037__author__ = "Ka-Ping Yee <ping@lfw.org>"
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000038__date__ = "26 February 2001"
Jeremy Hylton3e0055f2005-10-20 19:59:25 +000039
Martin v. Löwis6fe8f192004-11-14 10:21:04 +000040__credits__ = """Guido van Rossum, for an excellent programming language.
Ka-Ping Yee5e2b1732001-02-27 23:35:09 +000041Tommy Burnette, the original creator of manpy.
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000042Paul Prescod, for all his work on onlinehelp.
43Richard Chamberlain, for the first implementation of textdoc.
Raymond Hettingered2dbe32005-01-01 07:51:01 +000044"""
Ka-Ping Yeedd175342001-02-27 14:43:46 +000045
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000046# Known bugs that can't be fixed here:
Brett Cannonf4ba4ec2013-06-15 14:25:04 -040047# - synopsis() cannot be prevented from clobbering existing
48# loaded modules.
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000049# - If the __file__ attribute on a module is a relative path and
50# the current directory is changed with os.chdir(), an incorrect
51# path will be displayed.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000052
Nick Coghlan7bb30b72010-12-03 09:29:11 +000053import builtins
Brett Cannond5e6f2e2013-06-11 17:09:36 -040054import importlib._bootstrap
Brett Cannoncb66eb02012-05-11 12:58:42 -040055import importlib.machinery
Brett Cannonf4ba4ec2013-06-15 14:25:04 -040056import importlib.util
Nick Coghlan7bb30b72010-12-03 09:29:11 +000057import inspect
Victor Stinnere6c910e2011-06-30 15:55:43 +020058import io
59import os
Nick Coghlan7bb30b72010-12-03 09:29:11 +000060import pkgutil
61import platform
62import re
Victor Stinnere6c910e2011-06-30 15:55:43 +020063import sys
Nick Coghlan7bb30b72010-12-03 09:29:11 +000064import time
Victor Stinnere6c910e2011-06-30 15:55:43 +020065import tokenize
Nick Coghlan7bb30b72010-12-03 09:29:11 +000066import warnings
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000067from collections import deque
Nick Coghlan7bb30b72010-12-03 09:29:11 +000068from reprlib import Repr
Georg Brandld2f38572011-01-30 08:37:19 +000069from traceback import extract_tb, format_exception_only
Nick Coghlan7bb30b72010-12-03 09:29:11 +000070
71
Ka-Ping Yeedd175342001-02-27 14:43:46 +000072# --------------------------------------------------------- common routines
73
Ka-Ping Yeedd175342001-02-27 14:43:46 +000074def pathdirs():
75 """Convert sys.path into a list of absolute, existing, unique paths."""
76 dirs = []
Ka-Ping Yee1d384632001-03-01 00:24:32 +000077 normdirs = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +000078 for dir in sys.path:
79 dir = os.path.abspath(dir or '.')
Ka-Ping Yee1d384632001-03-01 00:24:32 +000080 normdir = os.path.normcase(dir)
81 if normdir not in normdirs and os.path.isdir(dir):
Ka-Ping Yeedd175342001-02-27 14:43:46 +000082 dirs.append(dir)
Ka-Ping Yee1d384632001-03-01 00:24:32 +000083 normdirs.append(normdir)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000084 return dirs
85
86def getdoc(object):
87 """Get the doc string or comments for an object."""
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000088 result = inspect.getdoc(object) or inspect.getcomments(object)
Neal Norwitz9d72bb42007-04-17 08:48:32 +000089 return result and re.sub('^ *\n', '', result.rstrip()) or ''
Ka-Ping Yeedd175342001-02-27 14:43:46 +000090
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000091def splitdoc(doc):
92 """Split a doc string into a synopsis line (if any) and the rest."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +000093 lines = doc.strip().split('\n')
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000094 if len(lines) == 1:
95 return lines[0], ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +000096 elif len(lines) >= 2 and not lines[1].rstrip():
97 return lines[0], '\n'.join(lines[2:])
98 return '', '\n'.join(lines)
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000099
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000100def classname(object, modname):
101 """Get a class name and qualify it with a module name if necessary."""
102 name = object.__name__
103 if object.__module__ != modname:
104 name = object.__module__ + '.' + name
105 return name
106
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000107def isdata(object):
Georg Brandl94432422005-07-22 21:52:25 +0000108 """Check if an object is of a type that probably means it's data."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000109 return not (inspect.ismodule(object) or inspect.isclass(object) or
110 inspect.isroutine(object) or inspect.isframe(object) or
111 inspect.istraceback(object) or inspect.iscode(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000112
113def replace(text, *pairs):
114 """Do a series of global replacements on a string."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000115 while pairs:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000116 text = pairs[1].join(text.split(pairs[0]))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000117 pairs = pairs[2:]
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000118 return text
119
120def cram(text, maxlen):
121 """Omit part of a string if needed to make it fit in a maximum length."""
122 if len(text) > maxlen:
Raymond Hettingerfca3bb62002-10-21 04:44:11 +0000123 pre = max(0, (maxlen-3)//2)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000124 post = max(0, maxlen-3-pre)
125 return text[:pre] + '...' + text[len(text)-post:]
126 return text
127
Brett Cannon84601f12004-06-19 01:22:48 +0000128_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000129def stripid(text):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000130 """Remove the hexadecimal id from a Python object representation."""
Brett Cannonc6c1f472004-06-19 01:02:51 +0000131 # The behaviour of %p is implementation-dependent in terms of case.
Ezio Melotti412c95a2010-02-16 23:31:04 +0000132 return _re_stripid.sub(r'\1', text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000133
Brett Cannonc6c1f472004-06-19 01:02:51 +0000134def _is_some_method(obj):
R David Murrayac0cea52013-03-19 02:47:44 -0400135 return (inspect.isfunction(obj) or
136 inspect.ismethod(obj) or
137 inspect.isbuiltin(obj) or
138 inspect.ismethoddescriptor(obj))
Tim Peters536d2262001-09-20 05:13:38 +0000139
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000140def allmethods(cl):
141 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000142 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000143 methods[key] = 1
144 for base in cl.__bases__:
145 methods.update(allmethods(base)) # all your base are belong to us
146 for key in methods.keys():
147 methods[key] = getattr(cl, key)
148 return methods
149
Tim Petersfa26f7c2001-09-24 08:05:11 +0000150def _split_list(s, predicate):
151 """Split sequence s via predicate, and return pair ([true], [false]).
152
153 The return value is a 2-tuple of lists,
154 ([x for x in s if predicate(x)],
155 [x for x in s if not predicate(x)])
156 """
157
Tim Peters28355492001-09-23 21:29:55 +0000158 yes = []
159 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000160 for x in s:
161 if predicate(x):
162 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000163 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000164 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000165 return yes, no
166
Raymond Hettinger1103d052011-03-25 14:15:24 -0700167def visiblename(name, all=None, obj=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000168 """Decide whether to show documentation on a variable."""
Brett Cannond340b432012-08-06 17:19:22 -0400169 # Certain special names are redundant or internal.
Eric Snowb523f842013-11-22 09:05:39 -0700170 # XXX Remove __initializing__?
Brett Cannond340b432012-08-06 17:19:22 -0400171 if name in {'__author__', '__builtins__', '__cached__', '__credits__',
Eric Snowb523f842013-11-22 09:05:39 -0700172 '__date__', '__doc__', '__file__', '__spec__',
Brett Cannond340b432012-08-06 17:19:22 -0400173 '__loader__', '__module__', '__name__', '__package__',
174 '__path__', '__qualname__', '__slots__', '__version__'}:
Raymond Hettinger68272942011-03-18 02:22:15 -0700175 return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000176 # Private names are hidden, but special names are displayed.
177 if name.startswith('__') and name.endswith('__'): return 1
Raymond Hettinger1103d052011-03-25 14:15:24 -0700178 # Namedtuples have public fields and methods with a single leading underscore
179 if name.startswith('_') and hasattr(obj, '_fields'):
180 return True
Skip Montanaroa5616d22004-06-11 04:46:12 +0000181 if all is not None:
182 # only document that which the programmer exported in __all__
183 return name in all
184 else:
185 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000186
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000187def classify_class_attrs(object):
188 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000189 results = []
190 for (name, kind, cls, value) in inspect.classify_class_attrs(object):
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000191 if inspect.isdatadescriptor(value):
192 kind = 'data descriptor'
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000193 results.append((name, kind, cls, value))
194 return results
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000195
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000196# ----------------------------------------------------- module manipulation
197
198def ispackage(path):
199 """Guess whether a path refers to a package directory."""
200 if os.path.isdir(path):
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000201 for ext in ('.py', '.pyc', '.pyo'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000202 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000203 return True
204 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000205
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000206def source_synopsis(file):
207 line = file.readline()
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000208 while line[:1] == '#' or not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000209 line = file.readline()
210 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000211 line = line.strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000212 if line[:4] == 'r"""': line = line[1:]
213 if line[:3] == '"""':
214 line = line[3:]
215 if line[-1:] == '\\': line = line[:-1]
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000216 while not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000217 line = file.readline()
218 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000219 result = line.split('"""')[0].strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000220 else: result = None
221 return result
222
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000223def synopsis(filename, cache={}):
224 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000225 mtime = os.stat(filename).st_mtime
Charles-François Natali27c4e882011-07-27 19:40:02 +0200226 lastupdate, result = cache.get(filename, (None, None))
227 if lastupdate is None or lastupdate < mtime:
Georg Brandl26fd2e12006-03-08 09:34:53 +0000228 try:
Victor Stinnere6c910e2011-06-30 15:55:43 +0200229 file = tokenize.open(filename)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200230 except OSError:
Georg Brandl26fd2e12006-03-08 09:34:53 +0000231 # module can't be opened, so skip it
232 return None
Brett Cannoncb66eb02012-05-11 12:58:42 -0400233 binary_suffixes = importlib.machinery.BYTECODE_SUFFIXES[:]
234 binary_suffixes += importlib.machinery.EXTENSION_SUFFIXES[:]
235 if any(filename.endswith(x) for x in binary_suffixes):
236 # binary modules have to be imported
237 file.close()
238 if any(filename.endswith(x) for x in
239 importlib.machinery.BYTECODE_SUFFIXES):
240 loader = importlib.machinery.SourcelessFileLoader('__temp__',
241 filename)
242 else:
243 loader = importlib.machinery.ExtensionFileLoader('__temp__',
244 filename)
245 try:
246 module = loader.load_module('__temp__')
247 except:
248 return None
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000249 result = (module.__doc__ or '').splitlines()[0]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000250 del sys.modules['__temp__']
Brett Cannoncb66eb02012-05-11 12:58:42 -0400251 else:
252 # text modules can be directly examined
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000253 result = source_synopsis(file)
254 file.close()
Brett Cannoncb66eb02012-05-11 12:58:42 -0400255
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000256 cache[filename] = (mtime, result)
257 return result
258
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000259class ErrorDuringImport(Exception):
260 """Errors that occurred while trying to import something to document it."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000261 def __init__(self, filename, exc_info):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000262 self.filename = filename
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000263 self.exc, self.value, self.tb = exc_info
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000264
265 def __str__(self):
Guido van Rossuma01a8b62007-05-27 09:20:14 +0000266 exc = self.exc.__name__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000267 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000268
269def importfile(path):
270 """Import a Python source file or compiled file given its path."""
Brett Cannonf4ba4ec2013-06-15 14:25:04 -0400271 magic = importlib.util.MAGIC_NUMBER
Victor Stinnere975af62011-07-04 02:08:50 +0200272 with open(path, 'rb') as file:
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400273 is_bytecode = magic == file.read(len(magic))
274 filename = os.path.basename(path)
275 name, ext = os.path.splitext(filename)
276 if is_bytecode:
277 loader = importlib._bootstrap.SourcelessFileLoader(name, path)
278 else:
279 loader = importlib._bootstrap.SourceFileLoader(name, path)
280 try:
281 return loader.load_module(name)
282 except:
283 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000284
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000285def safeimport(path, forceload=0, cache={}):
286 """Import a module; handle errors; return None if the module isn't found.
287
288 If the module *is* found but an exception occurs, it's wrapped in an
289 ErrorDuringImport exception and reraised. Unlike __import__, if a
290 package path is specified, the module at the end of the path is returned,
291 not the package at the beginning. If the optional 'forceload' argument
292 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000293 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000294 # If forceload is 1 and the module has been previously loaded from
295 # disk, we always have to reload the module. Checking the file's
296 # mtime isn't good enough (e.g. the module could contain a class
297 # that inherits from another module that has changed).
298 if forceload and path in sys.modules:
299 if path not in sys.builtin_module_names:
Guido van Rossume7ba4952007-06-06 23:52:48 +0000300 # Remove the module from sys.modules and re-import to try
301 # and avoid problems with partially loaded modules.
302 # Also remove any submodules because they won't appear
303 # in the newly loaded module's namespace if they're already
304 # in sys.modules.
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000305 subs = [m for m in sys.modules if m.startswith(path + '.')]
306 for key in [path] + subs:
307 # Prevent garbage collection.
308 cache[key] = sys.modules[key]
309 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000310 module = __import__(path)
311 except:
312 # Did the error occur before or after the module was found?
313 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000314 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000315 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000316 raise ErrorDuringImport(sys.modules[path].__file__, info)
317 elif exc is SyntaxError:
318 # A SyntaxError occurred before we could execute the module.
319 raise ErrorDuringImport(value.filename, info)
Brett Cannon679ecb52013-07-04 17:51:50 -0400320 elif exc is ImportError and value.name == path:
Brett Cannonfd074152012-04-14 14:10:13 -0400321 # No such module in the path.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000322 return None
323 else:
324 # Some other error occurred during the importing process.
325 raise ErrorDuringImport(path, sys.exc_info())
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000326 for part in path.split('.')[1:]:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000327 try: module = getattr(module, part)
328 except AttributeError: return None
329 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000330
331# ---------------------------------------------------- formatter base class
332
333class Doc:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000334
335 PYTHONDOCS = os.environ.get("PYTHONDOCS",
336 "http://docs.python.org/%d.%d/library"
337 % sys.version_info[:2])
338
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000339 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000340 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000341 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000342 # 'try' clause is to attempt to handle the possibility that inspect
343 # identifies something in a way that pydoc itself has issues handling;
344 # think 'super' and how it is a descriptor (which raises the exception
345 # by lacking a __name__ attribute) and an instance.
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000346 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
347 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000348 try:
349 if inspect.ismodule(object): return self.docmodule(*args)
350 if inspect.isclass(object): return self.docclass(*args)
351 if inspect.isroutine(object): return self.docroutine(*args)
352 except AttributeError:
353 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000354 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000355 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000356
357 def fail(self, object, name=None, *args):
358 """Raise an exception for unimplemented types."""
359 message = "don't know how to document object%s of type %s" % (
360 name and ' ' + repr(name), type(object).__name__)
Collin Winterce36ad82007-08-30 01:19:48 +0000361 raise TypeError(message)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000362
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000363 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000364
Skip Montanaro4997a692003-09-10 16:47:51 +0000365 def getdocloc(self, object):
366 """Return the location of module docs or None"""
367
368 try:
369 file = inspect.getabsfile(object)
370 except TypeError:
371 file = '(built-in)'
372
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000373 docloc = os.environ.get("PYTHONDOCS", self.PYTHONDOCS)
374
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100375 basedir = os.path.join(sys.base_exec_prefix, "lib",
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000376 "python%d.%d" % sys.version_info[:2])
Skip Montanaro4997a692003-09-10 16:47:51 +0000377 if (isinstance(object, type(os)) and
378 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
379 'marshal', 'posix', 'signal', 'sys',
Georg Brandl2067bfd2008-05-25 13:05:15 +0000380 '_thread', 'zipimport') or
Skip Montanaro4997a692003-09-10 16:47:51 +0000381 (file.startswith(basedir) and
Brian Curtin49c284c2010-03-31 03:19:28 +0000382 not file.startswith(os.path.join(basedir, 'site-packages')))) and
Brian Curtinedef05b2010-04-01 04:05:25 +0000383 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
Skip Montanaro4997a692003-09-10 16:47:51 +0000384 if docloc.startswith("http://"):
Georg Brandl86def6c2008-01-21 20:36:10 +0000385 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
Skip Montanaro4997a692003-09-10 16:47:51 +0000386 else:
Georg Brandl86def6c2008-01-21 20:36:10 +0000387 docloc = os.path.join(docloc, object.__name__ + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000388 else:
389 docloc = None
390 return docloc
391
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000392# -------------------------------------------- HTML documentation generator
393
394class HTMLRepr(Repr):
395 """Class for safely making an HTML representation of a Python object."""
396 def __init__(self):
397 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000398 self.maxlist = self.maxtuple = 20
399 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000400 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000401
402 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000403 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000404
405 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000406 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000407
408 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000409 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000410 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000411 if hasattr(self, methodname):
412 return getattr(self, methodname)(x, level)
413 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000414
415 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000416 test = cram(x, self.maxstring)
417 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000418 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000419 # Backslashes are only literal in the string and are never
420 # needed to make any special characters, so show a raw string.
421 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000422 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000423 r'<font color="#c040c0">\1</font>',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000424 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000425
Skip Montanarodf708782002-03-07 22:58:02 +0000426 repr_str = repr_string
427
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000428 def repr_instance(self, x, level):
429 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000430 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000431 except:
432 return self.escape('<%s instance>' % x.__class__.__name__)
433
434 repr_unicode = repr_string
435
436class HTMLDoc(Doc):
437 """Formatter class for HTML documentation."""
438
439 # ------------------------------------------- HTML formatting utilities
440
441 _repr_instance = HTMLRepr()
442 repr = _repr_instance.repr
443 escape = _repr_instance.escape
444
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000445 def page(self, title, contents):
446 """Format an HTML page."""
Georg Brandl388faac2009-04-10 08:31:48 +0000447 return '''\
Georg Brandle6066942009-04-10 08:28:28 +0000448<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000449<html><head><title>Python: %s</title>
Georg Brandl388faac2009-04-10 08:31:48 +0000450<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000451</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000452%s
453</body></html>''' % (title, contents)
454
455 def heading(self, title, fgcol, bgcol, extras=''):
456 """Format a page heading."""
457 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000458<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000459<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000460<td valign=bottom>&nbsp;<br>
461<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000462><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000463><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000464 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
465
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000466 def section(self, title, fgcol, bgcol, contents, width=6,
467 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000468 """Format a section with a heading."""
469 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000470 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000471 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000472<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000473<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000474<td colspan=3 valign=bottom>&nbsp;<br>
475<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000476 ''' % (bgcol, fgcol, title)
477 if prelude:
478 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000479<tr bgcolor="%s"><td rowspan=2>%s</td>
480<td colspan=2>%s</td></tr>
481<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
482 else:
483 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000484<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000485
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000486 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000487
488 def bigsection(self, title, *args):
489 """Format a section with a big heading."""
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000490 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000491 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000492
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000493 def preformat(self, text):
494 """Format literal preformatted text."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000495 text = self.escape(text.expandtabs())
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000496 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
497 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000498
499 def multicolumn(self, list, format, cols=4):
500 """Format a list of items into a multi-column list."""
501 result = ''
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000502 rows = (len(list)+cols-1)//cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000503 for col in range(cols):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000504 result = result + '<td width="%d%%" valign=top>' % (100//cols)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000505 for i in range(rows*col, rows*col+rows):
506 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000507 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000508 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000509 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000510
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000511 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000512
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000513 def namelink(self, name, *dicts):
514 """Make a link for an identifier, given name-to-URL mappings."""
515 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000516 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000517 return '<a href="%s">%s</a>' % (dict[name], name)
518 return name
519
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000520 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000521 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000522 name, module = object.__name__, sys.modules.get(object.__module__)
523 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000524 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000525 module.__name__, name, classname(object, modname))
526 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000527
528 def modulelink(self, object):
529 """Make a link for a module."""
530 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
531
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000532 def modpkglink(self, modpkginfo):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000533 """Make a link for a module or package to display in an index."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000534 name, path, ispackage, shadowed = modpkginfo
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000535 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000536 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000537 if path:
538 url = '%s.%s.html' % (path, name)
539 else:
540 url = '%s.html' % name
541 if ispackage:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000542 text = '<strong>%s</strong>&nbsp;(package)' % name
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000543 else:
544 text = name
545 return '<a href="%s">%s</a>' % (url, text)
546
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000547 def filelink(self, url, path):
548 """Make a link to source file."""
549 return '<a href="file:%s">%s</a>' % (url, path)
550
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000551 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
552 """Mark up some plain text, given a context of symbols to look for.
553 Each context dictionary maps object names to anchor names."""
554 escape = escape or self.escape
555 results = []
556 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000557 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
558 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000559 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000560 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000561 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000562 match = pattern.search(text, here)
563 if not match: break
564 start, end = match.span()
565 results.append(escape(text[here:start]))
566
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000567 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000568 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000569 url = escape(all).replace('"', '&quot;')
570 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000571 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000572 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
573 results.append('<a href="%s">%s</a>' % (url, escape(all)))
574 elif pep:
Christian Heimes2202f872008-02-06 14:31:34 +0000575 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000576 results.append('<a href="%s">%s</a>' % (url, escape(all)))
577 elif text[end:end+1] == '(':
578 results.append(self.namelink(name, methods, funcs, classes))
579 elif selfdot:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000580 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000581 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000582 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000583 here = end
584 results.append(escape(text[here:]))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000585 return ''.join(results)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000586
587 # ---------------------------------------------- type-specific routines
588
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000589 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000590 """Produce HTML for a class tree as given by inspect.getclasstree()."""
591 result = ''
592 for entry in tree:
593 if type(entry) is type(()):
594 c, bases = entry
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000595 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000596 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000597 if bases and bases != (parent,):
598 parents = []
599 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000600 parents.append(self.classlink(base, modname))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000601 result = result + '(' + ', '.join(parents) + ')'
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000602 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000603 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000604 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000605 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000606 return '<dl>\n%s</dl>\n' % result
607
Tim Peters8dd7ade2001-10-18 19:56:17 +0000608 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000609 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000610 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000611 try:
612 all = object.__all__
613 except AttributeError:
614 all = None
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000615 parts = name.split('.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000616 links = []
617 for i in range(len(parts)-1):
618 links.append(
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000619 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000620 ('.'.join(parts[:i+1]), parts[i]))
621 linkedname = '.'.join(links + parts[-1:])
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000622 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000623 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000624 path = inspect.getabsfile(object)
Ka-Ping Yee6191a232001-04-13 15:00:27 +0000625 url = path
626 if sys.platform == 'win32':
627 import nturl2path
628 url = nturl2path.pathname2url(path)
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000629 filelink = self.filelink(url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000630 except TypeError:
631 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000632 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000633 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000634 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000635 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000636 version = version[11:-1].strip()
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000637 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000638 if hasattr(object, '__date__'):
639 info.append(self.escape(str(object.__date__)))
640 if info:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000641 head = head + ' (%s)' % ', '.join(info)
Skip Montanaro4997a692003-09-10 16:47:51 +0000642 docloc = self.getdocloc(object)
643 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000644 docloc = '<br><a href="%(docloc)s">Module Reference</a>' % locals()
Skip Montanaro4997a692003-09-10 16:47:51 +0000645 else:
646 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000647 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000648 head, '#ffffff', '#7799ee',
649 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000650
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000651 modules = inspect.getmembers(object, inspect.ismodule)
652
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000653 classes, cdict = [], {}
654 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000655 # if __all__ exists, believe it. Otherwise use old heuristic.
656 if (all is not None or
657 (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700658 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000659 classes.append((key, value))
660 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000661 for key, value in classes:
662 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000663 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000664 module = sys.modules.get(modname)
665 if modname != name and module and hasattr(module, key):
666 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000667 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000668 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000669 funcs, fdict = [], {}
670 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000671 # if __all__ exists, believe it. Otherwise use old heuristic.
672 if (all is not None or
673 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700674 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000675 funcs.append((key, value))
676 fdict[key] = '#-' + key
677 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000678 data = []
679 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700680 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000681 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000682
683 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
684 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000685 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000686
687 if hasattr(object, '__path__'):
688 modpkgs = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000689 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
690 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000691 modpkgs.sort()
692 contents = self.multicolumn(modpkgs, self.modpkglink)
693 result = result + self.bigsection(
694 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000695 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000696 contents = self.multicolumn(
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000697 modules, lambda t: self.modulelink(t[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000698 result = result + self.bigsection(
Christian Heimes7131fd92008-02-19 14:21:46 +0000699 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000700
701 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000702 classlist = [value for (key, value) in classes]
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000703 contents = [
704 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000705 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000706 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000707 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000708 'Classes', '#ffffff', '#ee77aa', ' '.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000709 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000710 contents = []
711 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000712 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000713 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000714 'Functions', '#ffffff', '#eeaa77', ' '.join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000715 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000716 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000717 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000718 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000719 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000720 'Data', '#ffffff', '#55aa55', '<br>\n'.join(contents))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000721 if hasattr(object, '__author__'):
722 contents = self.markup(str(object.__author__), self.preformat)
723 result = result + self.bigsection(
724 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000725 if hasattr(object, '__credits__'):
726 contents = self.markup(str(object.__credits__), self.preformat)
727 result = result + self.bigsection(
728 'Credits', '#ffffff', '#7799ee', contents)
729
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000730 return result
731
Tim Peters8dd7ade2001-10-18 19:56:17 +0000732 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
733 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000734 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000735 realname = object.__name__
736 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000737 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000738
Tim Petersb47879b2001-09-24 04:47:19 +0000739 contents = []
740 push = contents.append
741
Tim Petersfa26f7c2001-09-24 08:05:11 +0000742 # Cute little class to pump out a horizontal rule between sections.
743 class HorizontalRule:
744 def __init__(self):
745 self.needone = 0
746 def maybe(self):
747 if self.needone:
748 push('<hr>\n')
749 self.needone = 1
750 hr = HorizontalRule()
751
Tim Petersc86f6ca2001-09-26 21:31:51 +0000752 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000753 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000754 if len(mro) > 2:
755 hr.maybe()
756 push('<dl><dt>Method resolution order:</dt>\n')
757 for base in mro:
758 push('<dd>%s</dd>\n' % self.classlink(base,
759 object.__module__))
760 push('</dl>\n')
761
Tim Petersb47879b2001-09-24 04:47:19 +0000762 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000763 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000764 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000765 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000766 push(msg)
767 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100768 try:
769 value = getattr(object, name)
770 except Exception:
771 # Some descriptors may meet a failure in their __get__.
772 # (bug #1785)
773 push(self._docdescriptor(name, value, mod))
774 else:
775 push(self.document(value, name, mod,
776 funcs, classes, mdict, object))
Tim Petersb47879b2001-09-24 04:47:19 +0000777 push('\n')
778 return attrs
779
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000780 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000781 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000782 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000783 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000784 push(msg)
785 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000786 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000787 return attrs
788
Tim Petersfa26f7c2001-09-24 08:05:11 +0000789 def spilldata(msg, attrs, predicate):
790 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000791 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000792 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000793 push(msg)
794 for name, kind, homecls, value in ok:
795 base = self.docother(getattr(object, name), name, mod)
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200796 if callable(value) or inspect.isdatadescriptor(value):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000797 doc = getattr(value, "__doc__", None)
798 else:
799 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000800 if doc is None:
801 push('<dl><dt>%s</dl>\n' % base)
802 else:
803 doc = self.markup(getdoc(value), self.preformat,
804 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000805 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000806 push('<dl><dt>%s%s</dl>\n' % (base, doc))
807 push('\n')
808 return attrs
809
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000810 attrs = [(name, kind, cls, value)
811 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -0700812 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000813
Tim Petersb47879b2001-09-24 04:47:19 +0000814 mdict = {}
815 for key, kind, homecls, value in attrs:
816 mdict[key] = anchor = '#' + name + '-' + key
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100817 try:
818 value = getattr(object, name)
819 except Exception:
820 # Some descriptors may meet a failure in their __get__.
821 # (bug #1785)
822 pass
Tim Petersb47879b2001-09-24 04:47:19 +0000823 try:
824 # The value may not be hashable (e.g., a data attr with
825 # a dict or list value).
826 mdict[value] = anchor
827 except TypeError:
828 pass
829
Tim Petersfa26f7c2001-09-24 08:05:11 +0000830 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000831 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000832 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000833 else:
834 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000835 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
836
Georg Brandl1a3284e2007-12-02 09:40:06 +0000837 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000838 attrs = inherited
839 continue
840 elif thisclass is object:
841 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000842 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000843 tag = 'inherited from %s' % self.classlink(thisclass,
844 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000845 tag += ':<br>\n'
846
847 # Sort attrs by name.
Raymond Hettingerd4cb56d2008-01-30 02:55:10 +0000848 attrs.sort(key=lambda t: t[0])
Tim Petersb47879b2001-09-24 04:47:19 +0000849
850 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000851 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000852 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000853 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000854 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000855 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000856 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000857 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
858 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000859 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000860 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000861 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000862 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000863
864 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000865
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000866 if name == realname:
867 title = '<a name="%s">class <strong>%s</strong></a>' % (
868 name, realname)
869 else:
870 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
871 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000872 if bases:
873 parents = []
874 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000875 parents.append(self.classlink(base, object.__module__))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000876 title = title + '(%s)' % ', '.join(parents)
Tim Peters2306d242001-09-25 03:18:32 +0000877 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000878 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000879
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000880 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000881
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000882 def formatvalue(self, object):
883 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000884 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000885
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000886 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000887 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000888 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000889 realname = object.__name__
890 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000891 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000892 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000893 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000894 if inspect.ismethod(object):
Christian Heimesff737952007-11-27 10:40:20 +0000895 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000896 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000897 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000898 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000899 else:
Christian Heimesff737952007-11-27 10:40:20 +0000900 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000901 note = ' method of %s instance' % self.classlink(
Christian Heimesff737952007-11-27 10:40:20 +0000902 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000903 else:
904 note = ' unbound %s method' % self.classlink(imclass,mod)
Christian Heimesff737952007-11-27 10:40:20 +0000905 object = object.__func__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000906
907 if name == realname:
908 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
909 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000910 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000911 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000912 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000913 cl.__name__ + '-' + realname, realname)
914 skipdocs = 1
915 else:
916 reallink = realname
917 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
918 anchor, name, reallink)
Tim Peters4bcfa312001-09-20 06:08:24 +0000919 if inspect.isfunction(object):
Guido van Rossum2e65f892007-02-28 22:03:49 +0000920 args, varargs, kwonlyargs, kwdefaults, varkw, defaults, ann = \
921 inspect.getfullargspec(object)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000922 argspec = inspect.formatargspec(
Guido van Rossum2e65f892007-02-28 22:03:49 +0000923 args, varargs, kwonlyargs, kwdefaults, varkw, defaults, ann,
924 formatvalue=self.formatvalue,
925 formatannotation=inspect.formatannotationrelativeto(object))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000926 if realname == '<lambda>':
Tim Peters59ed4482001-10-31 04:20:26 +0000927 title = '<strong>%s</strong> <em>lambda</em> ' % name
Guido van Rossum2e65f892007-02-28 22:03:49 +0000928 # XXX lambda's won't usually have func_annotations['return']
929 # since the syntax doesn't support but it is possible.
930 # So removing parentheses isn't truly safe.
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000931 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +0000932 else:
933 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000934
Tim Peters2306d242001-09-25 03:18:32 +0000935 decl = title + argspec + (note and self.grey(
936 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000937
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000938 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000939 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000940 else:
941 doc = self.markup(
942 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000943 doc = doc and '<dd><tt>%s</tt></dd>' % doc
944 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000945
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000946 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000947 results = []
948 push = results.append
949
950 if name:
951 push('<dl><dt><strong>%s</strong></dt>\n' % name)
952 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000953 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000954 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000955 push('</dl>\n')
956
957 return ''.join(results)
958
959 def docproperty(self, object, name=None, mod=None, cl=None):
960 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000961 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000962
Tim Peters8dd7ade2001-10-18 19:56:17 +0000963 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000964 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000965 lhs = name and '<strong>%s</strong> = ' % name or ''
966 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000967
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000968 def docdata(self, object, name=None, mod=None, cl=None):
969 """Produce html documentation for a data descriptor."""
970 return self._docdescriptor(name, object, mod)
971
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000972 def index(self, dir, shadowed=None):
973 """Generate an HTML index for a directory of modules."""
974 modpkgs = []
975 if shadowed is None: shadowed = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000976 for importer, name, ispkg in pkgutil.iter_modules([dir]):
Victor Stinner4d652242011-04-12 23:41:50 +0200977 if any((0xD800 <= ord(ch) <= 0xDFFF) for ch in name):
978 # ignore a module if its name contains a surrogate character
979 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000980 modpkgs.append((name, '', ispkg, name in shadowed))
981 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000982
983 modpkgs.sort()
984 contents = self.multicolumn(modpkgs, self.modpkglink)
985 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
986
987# -------------------------------------------- text documentation generator
988
989class TextRepr(Repr):
990 """Class for safely making a text representation of a Python object."""
991 def __init__(self):
992 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000993 self.maxlist = self.maxtuple = 20
994 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000995 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000996
997 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000998 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000999 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001000 if hasattr(self, methodname):
1001 return getattr(self, methodname)(x, level)
1002 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001003
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001004 def repr_string(self, x, level):
1005 test = cram(x, self.maxstring)
1006 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001007 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001008 # Backslashes are only literal in the string and are never
1009 # needed to make any special characters, so show a raw string.
1010 return 'r' + testrepr[0] + test + testrepr[0]
1011 return testrepr
1012
Skip Montanarodf708782002-03-07 22:58:02 +00001013 repr_str = repr_string
1014
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001015 def repr_instance(self, x, level):
1016 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001017 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001018 except:
1019 return '<%s instance>' % x.__class__.__name__
1020
1021class TextDoc(Doc):
1022 """Formatter class for text documentation."""
1023
1024 # ------------------------------------------- text formatting utilities
1025
1026 _repr_instance = TextRepr()
1027 repr = _repr_instance.repr
1028
1029 def bold(self, text):
1030 """Format a string in bold by overstriking."""
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001031 return ''.join(ch + '\b' + ch for ch in text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001032
1033 def indent(self, text, prefix=' '):
1034 """Indent text by prepending a given prefix to each line."""
1035 if not text: return ''
Collin Winter72e110c2007-07-17 00:27:30 +00001036 lines = [prefix + line for line in text.split('\n')]
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001037 if lines: lines[-1] = lines[-1].rstrip()
1038 return '\n'.join(lines)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001039
1040 def section(self, title, contents):
1041 """Format a section with a given heading."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001042 clean_contents = self.indent(contents).rstrip()
1043 return self.bold(title) + '\n' + clean_contents + '\n\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001044
1045 # ---------------------------------------------- type-specific routines
1046
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001047 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001048 """Render in text a class tree as returned by inspect.getclasstree()."""
1049 result = ''
1050 for entry in tree:
1051 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001052 c, bases = entry
1053 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001054 if bases and bases != (parent,):
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001055 parents = (classname(c, modname) for c in bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001056 result = result + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001057 result = result + '\n'
1058 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001059 result = result + self.formattree(
1060 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001061 return result
1062
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001063 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001064 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001065 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001066 synop, desc = splitdoc(getdoc(object))
1067 result = self.section('NAME', name + (synop and ' - ' + synop))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001068 all = getattr(object, '__all__', None)
Skip Montanaro4997a692003-09-10 16:47:51 +00001069 docloc = self.getdocloc(object)
1070 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001071 result = result + self.section('MODULE REFERENCE', docloc + """
1072
Éric Araujo647ef8c2011-09-11 00:43:20 +02001073The following documentation is automatically generated from the Python
1074source files. It may be incomplete, incorrect or include features that
1075are considered implementation detail and may vary between Python
1076implementations. When in doubt, consult the module reference at the
1077location listed above.
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001078""")
Skip Montanaro4997a692003-09-10 16:47:51 +00001079
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001080 if desc:
1081 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001082
1083 classes = []
1084 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001085 # if __all__ exists, believe it. Otherwise use old heuristic.
1086 if (all is not None
1087 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001088 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001089 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001090 funcs = []
1091 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001092 # if __all__ exists, believe it. Otherwise use old heuristic.
1093 if (all is not None or
1094 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001095 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001096 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001097 data = []
1098 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001099 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001100 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001101
Christian Heimes1af737c2008-01-23 08:24:23 +00001102 modpkgs = []
1103 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001104 if hasattr(object, '__path__'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001105 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Christian Heimes1af737c2008-01-23 08:24:23 +00001106 modpkgs_names.add(modname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001107 if ispkg:
1108 modpkgs.append(modname + ' (package)')
1109 else:
1110 modpkgs.append(modname)
1111
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001112 modpkgs.sort()
1113 result = result + self.section(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001114 'PACKAGE CONTENTS', '\n'.join(modpkgs))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001115
Christian Heimes1af737c2008-01-23 08:24:23 +00001116 # Detect submodules as sometimes created by C extensions
1117 submodules = []
1118 for key, value in inspect.getmembers(object, inspect.ismodule):
1119 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1120 submodules.append(key)
1121 if submodules:
1122 submodules.sort()
1123 result = result + self.section(
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001124 'SUBMODULES', '\n'.join(submodules))
Christian Heimes1af737c2008-01-23 08:24:23 +00001125
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001126 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001127 classlist = [value for key, value in classes]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001128 contents = [self.formattree(
1129 inspect.getclasstree(classlist, 1), name)]
1130 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001131 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001132 result = result + self.section('CLASSES', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001133
1134 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001135 contents = []
1136 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001137 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001138 result = result + self.section('FUNCTIONS', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001139
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001140 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001141 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001142 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001143 contents.append(self.docother(value, key, name, maxlen=70))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001144 result = result + self.section('DATA', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001145
1146 if hasattr(object, '__version__'):
1147 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001148 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001149 version = version[11:-1].strip()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001150 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001151 if hasattr(object, '__date__'):
1152 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001153 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001154 result = result + self.section('AUTHOR', str(object.__author__))
1155 if hasattr(object, '__credits__'):
1156 result = result + self.section('CREDITS', str(object.__credits__))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001157 try:
1158 file = inspect.getabsfile(object)
1159 except TypeError:
1160 file = '(built-in)'
1161 result = result + self.section('FILE', file)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001162 return result
1163
Georg Brandl9bd45f992010-12-03 09:58:38 +00001164 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001165 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001166 realname = object.__name__
1167 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001168 bases = object.__bases__
1169
Tim Petersc86f6ca2001-09-26 21:31:51 +00001170 def makename(c, m=object.__module__):
1171 return classname(c, m)
1172
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001173 if name == realname:
1174 title = 'class ' + self.bold(realname)
1175 else:
1176 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001177 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001178 parents = map(makename, bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001179 title = title + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001180
1181 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001182 contents = doc and [doc + '\n'] or []
1183 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001184
Tim Petersc86f6ca2001-09-26 21:31:51 +00001185 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001186 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001187 if len(mro) > 2:
1188 push("Method resolution order:")
1189 for base in mro:
1190 push(' ' + makename(base))
1191 push('')
1192
Tim Petersf4aad8e2001-09-24 22:40:47 +00001193 # Cute little class to pump out a horizontal rule between sections.
1194 class HorizontalRule:
1195 def __init__(self):
1196 self.needone = 0
1197 def maybe(self):
1198 if self.needone:
1199 push('-' * 70)
1200 self.needone = 1
1201 hr = HorizontalRule()
1202
Tim Peters28355492001-09-23 21:29:55 +00001203 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001204 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001205 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001206 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001207 push(msg)
1208 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001209 try:
1210 value = getattr(object, name)
1211 except Exception:
1212 # Some descriptors may meet a failure in their __get__.
1213 # (bug #1785)
1214 push(self._docdescriptor(name, value, mod))
1215 else:
1216 push(self.document(value,
1217 name, mod, object))
Tim Peters28355492001-09-23 21:29:55 +00001218 return attrs
1219
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001220 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001221 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001222 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001223 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001224 push(msg)
1225 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001226 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001227 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001228
Tim Petersfa26f7c2001-09-24 08:05:11 +00001229 def spilldata(msg, attrs, predicate):
1230 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001231 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001232 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001233 push(msg)
1234 for name, kind, homecls, value in ok:
Florent Xicluna5d1155c2011-10-28 14:45:05 +02001235 if callable(value) or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001236 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001237 else:
1238 doc = None
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001239 push(self.docother(
1240 getattr(object, name, None) or homecls.__dict__[name],
1241 name, mod, maxlen=70, doc=doc) + '\n')
Tim Peters28355492001-09-23 21:29:55 +00001242 return attrs
1243
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001244 attrs = [(name, kind, cls, value)
1245 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -07001246 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001247
Tim Petersfa26f7c2001-09-24 08:05:11 +00001248 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001249 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001250 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001251 else:
1252 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001253 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1254
Georg Brandl1a3284e2007-12-02 09:40:06 +00001255 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001256 attrs = inherited
1257 continue
1258 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001259 tag = "defined here"
1260 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001261 tag = "inherited from %s" % classname(thisclass,
1262 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001263 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001264 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001265
1266 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001267 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001268 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001269 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001270 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001271 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001272 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001273 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1274 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001275 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1276 lambda t: t[1] == 'data')
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001277
Tim Peters28355492001-09-23 21:29:55 +00001278 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001279 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001280
1281 contents = '\n'.join(contents)
1282 if not contents:
1283 return title + '\n'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001284 return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001285
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001286 def formatvalue(self, object):
1287 """Format an argument default value as text."""
1288 return '=' + self.repr(object)
1289
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001290 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001291 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001292 realname = object.__name__
1293 name = name or realname
1294 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001295 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001296 if inspect.ismethod(object):
Christian Heimesff737952007-11-27 10:40:20 +00001297 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001298 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001299 if imclass is not cl:
1300 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001301 else:
Christian Heimesff737952007-11-27 10:40:20 +00001302 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001303 note = ' method of %s instance' % classname(
Christian Heimesff737952007-11-27 10:40:20 +00001304 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001305 else:
1306 note = ' unbound %s method' % classname(imclass,mod)
Christian Heimesff737952007-11-27 10:40:20 +00001307 object = object.__func__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001308
1309 if name == realname:
1310 title = self.bold(realname)
1311 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001312 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001313 cl.__dict__[realname] is object):
1314 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001315 title = self.bold(name) + ' = ' + realname
Tim Peters4bcfa312001-09-20 06:08:24 +00001316 if inspect.isfunction(object):
Guido van Rossum2e65f892007-02-28 22:03:49 +00001317 args, varargs, varkw, defaults, kwonlyargs, kwdefaults, ann = \
1318 inspect.getfullargspec(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001319 argspec = inspect.formatargspec(
Guido van Rossum2e65f892007-02-28 22:03:49 +00001320 args, varargs, varkw, defaults, kwonlyargs, kwdefaults, ann,
1321 formatvalue=self.formatvalue,
1322 formatannotation=inspect.formatannotationrelativeto(object))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001323 if realname == '<lambda>':
Georg Brandl501dd0d2006-02-17 09:45:40 +00001324 title = self.bold(name) + ' lambda '
Guido van Rossum2e65f892007-02-28 22:03:49 +00001325 # XXX lambda's won't usually have func_annotations['return']
1326 # since the syntax doesn't support but it is possible.
1327 # So removing parentheses isn't truly safe.
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001328 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +00001329 else:
1330 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001331 decl = title + argspec + note
1332
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001333 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001334 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001335 else:
1336 doc = getdoc(object) or ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001337 return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001338
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001339 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001340 results = []
1341 push = results.append
1342
1343 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001344 push(self.bold(name))
1345 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001346 doc = getdoc(value) or ''
1347 if doc:
1348 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001349 push('\n')
1350 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001351
1352 def docproperty(self, object, name=None, mod=None, cl=None):
1353 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001354 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001355
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001356 def docdata(self, object, name=None, mod=None, cl=None):
1357 """Produce text documentation for a data descriptor."""
1358 return self._docdescriptor(name, object, mod)
1359
Georg Brandl8b813db2005-10-01 16:32:31 +00001360 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001361 """Produce text documentation for a data object."""
1362 repr = self.repr(object)
1363 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001364 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001365 chop = maxlen - len(line)
1366 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001367 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001368 if doc is not None:
1369 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001370 return line
1371
Georg Brandld80d5f42010-12-03 07:47:22 +00001372class _PlainTextDoc(TextDoc):
1373 """Subclass of TextDoc which overrides string styling"""
1374 def bold(self, text):
1375 return text
1376
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001377# --------------------------------------------------------- user interfaces
1378
1379def pager(text):
1380 """The first time this is called, determine what kind of pager to use."""
1381 global pager
1382 pager = getpager()
1383 pager(text)
1384
1385def getpager():
1386 """Decide what method to use for paging through text."""
Guido van Rossuma01a8b62007-05-27 09:20:14 +00001387 if not hasattr(sys.stdout, "isatty"):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001388 return plainpager
1389 if not sys.stdin.isatty() or not sys.stdout.isatty():
1390 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001391 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001392 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001393 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001394 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001395 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001396 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001397 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001398 if os.environ.get('TERM') in ('dumb', 'emacs'):
1399 return plainpager
Jesus Cea4791a242012-10-05 03:15:39 +02001400 if sys.platform == 'win32':
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001401 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001402 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001403 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001404
1405 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001406 (fd, filename) = tempfile.mkstemp()
1407 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001408 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001409 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001410 return lambda text: pipepager(text, 'more')
1411 else:
1412 return ttypager
1413 finally:
1414 os.unlink(filename)
1415
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001416def plain(text):
1417 """Remove boldface formatting from text."""
1418 return re.sub('.\b', '', text)
1419
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001420def pipepager(text, cmd):
1421 """Page through text by feeding it to another program."""
1422 pipe = os.popen(cmd, 'w')
1423 try:
1424 pipe.write(text)
1425 pipe.close()
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001426 except OSError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001427 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001428
1429def tempfilepager(text, cmd):
1430 """Page through text by invoking a program on a temporary file."""
1431 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001432 filename = tempfile.mktemp()
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +01001433 with open(filename, 'w') as file:
1434 file.write(text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001435 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001436 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001437 finally:
1438 os.unlink(filename)
1439
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001440def ttypager(text):
1441 """Page through text on a text terminal."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001442 lines = plain(text).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001443 try:
1444 import tty
1445 fd = sys.stdin.fileno()
1446 old = tty.tcgetattr(fd)
1447 tty.setcbreak(fd)
1448 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001449 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001450 tty = None
1451 getchar = lambda: sys.stdin.readline()[:-1][:1]
1452
1453 try:
1454 r = inc = os.environ.get('LINES', 25) - 1
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001455 sys.stdout.write('\n'.join(lines[:inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001456 while lines[r:]:
1457 sys.stdout.write('-- more --')
1458 sys.stdout.flush()
1459 c = getchar()
1460
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001461 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001462 sys.stdout.write('\r \r')
1463 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001464 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001465 sys.stdout.write('\r \r' + lines[r] + '\n')
1466 r = r + 1
1467 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001468 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001469 r = r - inc - inc
1470 if r < 0: r = 0
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001471 sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001472 r = r + inc
1473
1474 finally:
1475 if tty:
1476 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1477
1478def plainpager(text):
1479 """Simply print unformatted text. This is the ultimate fallback."""
1480 sys.stdout.write(plain(text))
1481
1482def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001483 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001484 if inspect.ismodule(thing):
1485 if thing.__name__ in sys.builtin_module_names:
1486 return 'built-in module ' + thing.__name__
1487 if hasattr(thing, '__path__'):
1488 return 'package ' + thing.__name__
1489 else:
1490 return 'module ' + thing.__name__
1491 if inspect.isbuiltin(thing):
1492 return 'built-in function ' + thing.__name__
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001493 if inspect.isgetsetdescriptor(thing):
1494 return 'getset descriptor %s.%s.%s' % (
1495 thing.__objclass__.__module__, thing.__objclass__.__name__,
1496 thing.__name__)
1497 if inspect.ismemberdescriptor(thing):
1498 return 'member descriptor %s.%s.%s' % (
1499 thing.__objclass__.__module__, thing.__objclass__.__name__,
1500 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001501 if inspect.isclass(thing):
1502 return 'class ' + thing.__name__
1503 if inspect.isfunction(thing):
1504 return 'function ' + thing.__name__
1505 if inspect.ismethod(thing):
1506 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001507 return type(thing).__name__
1508
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001509def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001510 """Locate an object by name or dotted path, importing as necessary."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001511 parts = [part for part in path.split('.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001512 module, n = None, 0
1513 while n < len(parts):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001514 nextmodule = safeimport('.'.join(parts[:n+1]), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001515 if nextmodule: module, n = nextmodule, n + 1
1516 else: break
1517 if module:
1518 object = module
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001519 else:
Éric Araujoe64e51b2011-07-29 17:03:55 +02001520 object = builtins
1521 for part in parts[n:]:
1522 try:
1523 object = getattr(object, part)
1524 except AttributeError:
1525 return None
1526 return object
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001527
1528# --------------------------------------- interactive interpreter interface
1529
1530text = TextDoc()
Georg Brandld80d5f42010-12-03 07:47:22 +00001531plaintext = _PlainTextDoc()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001532html = HTMLDoc()
1533
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001534def resolve(thing, forceload=0):
1535 """Given an object or a path to an object, get the object and its name."""
1536 if isinstance(thing, str):
1537 object = locate(thing, forceload)
1538 if not object:
Collin Winterce36ad82007-08-30 01:19:48 +00001539 raise ImportError('no Python documentation found for %r' % thing)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001540 return object, thing
1541 else:
R David Murrayc43125a2012-04-23 13:23:57 -04001542 name = getattr(thing, '__name__', None)
1543 return thing, name if isinstance(name, str) else None
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001544
Georg Brandld80d5f42010-12-03 07:47:22 +00001545def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
1546 renderer=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001547 """Render text documentation, given an object or a path to an object."""
Georg Brandld80d5f42010-12-03 07:47:22 +00001548 if renderer is None:
1549 renderer = text
Guido van Rossumd8faa362007-04-27 19:54:29 +00001550 object, name = resolve(thing, forceload)
1551 desc = describe(object)
1552 module = inspect.getmodule(object)
1553 if name and '.' in name:
1554 desc += ' in ' + name[:name.rfind('.')]
1555 elif module and module is not object:
1556 desc += ' in module ' + module.__name__
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001557
1558 if not (inspect.ismodule(object) or
Guido van Rossumd8faa362007-04-27 19:54:29 +00001559 inspect.isclass(object) or
1560 inspect.isroutine(object) or
1561 inspect.isgetsetdescriptor(object) or
1562 inspect.ismemberdescriptor(object) or
1563 isinstance(object, property)):
1564 # If the passed object is a piece of data or an instance,
1565 # document its available methods instead of its value.
1566 object = type(object)
1567 desc += ' object'
Georg Brandld80d5f42010-12-03 07:47:22 +00001568 return title % desc + '\n\n' + renderer.document(object, name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001569
Georg Brandld80d5f42010-12-03 07:47:22 +00001570def doc(thing, title='Python Library Documentation: %s', forceload=0,
1571 output=None):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001572 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001573 try:
Georg Brandld80d5f42010-12-03 07:47:22 +00001574 if output is None:
1575 pager(render_doc(thing, title, forceload))
1576 else:
1577 output.write(render_doc(thing, title, forceload, plaintext))
Guido van Rossumb940e112007-01-10 16:19:56 +00001578 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001579 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001580
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001581def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001582 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001583 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001584 object, name = resolve(thing, forceload)
1585 page = html.page(describe(object), html.document(object, name))
Georg Brandl388faac2009-04-10 08:31:48 +00001586 file = open(name + '.html', 'w', encoding='utf-8')
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001587 file.write(page)
1588 file.close()
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001589 print('wrote', name + '.html')
Guido van Rossumb940e112007-01-10 16:19:56 +00001590 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001591 print(value)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001592
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001593def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001594 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001595 if done is None: done = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001596 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1597 writedoc(modname)
1598 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001599
1600class Helper:
Georg Brandl6b38daa2008-06-01 21:05:17 +00001601
1602 # These dictionaries map a topic name to either an alias, or a tuple
1603 # (label, seealso-items). The "label" is the label of the corresponding
1604 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl5617db82009-04-27 16:28:57 +00001605 # in pydoc_data/topics.py.
Georg Brandl6b38daa2008-06-01 21:05:17 +00001606 #
1607 # CAUTION: if you change one of these dictionaries, be sure to adapt the
1608 # list of needed labels in Doc/tools/sphinxext/pyspecific.py and
Georg Brandl5617db82009-04-27 16:28:57 +00001609 # regenerate the pydoc_data/topics.py file by running
Georg Brandl6b38daa2008-06-01 21:05:17 +00001610 # make pydoc-topics
1611 # in Doc/ and copying the output file into the Lib/ directory.
1612
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001613 keywords = {
Ezio Melottib185a042011-04-28 07:42:55 +03001614 'False': '',
1615 'None': '',
1616 'True': '',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001617 'and': 'BOOLEAN',
Guido van Rossumd8faa362007-04-27 19:54:29 +00001618 'as': 'with',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001619 'assert': ('assert', ''),
1620 'break': ('break', 'while for'),
1621 'class': ('class', 'CLASSES SPECIALMETHODS'),
1622 'continue': ('continue', 'while for'),
1623 'def': ('function', ''),
1624 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001625 'elif': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001626 'else': ('else', 'while for'),
Georg Brandl0d855392008-08-30 19:53:05 +00001627 'except': 'try',
1628 'finally': 'try',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001629 'for': ('for', 'break continue while'),
Georg Brandl0d855392008-08-30 19:53:05 +00001630 'from': 'import',
Georg Brandl74abf6f2010-11-20 19:54:36 +00001631 'global': ('global', 'nonlocal NAMESPACES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001632 'if': ('if', 'TRUTHVALUE'),
1633 'import': ('import', 'MODULES'),
Georg Brandl395ed242009-09-04 08:07:32 +00001634 'in': ('in', 'SEQUENCEMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001635 'is': 'COMPARISON',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001636 'lambda': ('lambda', 'FUNCTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001637 'nonlocal': ('nonlocal', 'global NAMESPACES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001638 'not': 'BOOLEAN',
1639 'or': 'BOOLEAN',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001640 'pass': ('pass', ''),
1641 'raise': ('raise', 'EXCEPTIONS'),
1642 'return': ('return', 'FUNCTIONS'),
1643 'try': ('try', 'EXCEPTIONS'),
1644 'while': ('while', 'break continue if TRUTHVALUE'),
1645 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1646 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001647 }
Georg Brandldb7b6b92009-01-01 15:53:14 +00001648 # Either add symbols to this dictionary or to the symbols dictionary
1649 # directly: Whichever is easier. They are merged later.
1650 _symbols_inverse = {
1651 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'),
1652 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1653 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1654 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1655 'UNARY' : ('-', '~'),
1656 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1657 '^=', '<<=', '>>=', '**=', '//='),
1658 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1659 'COMPLEX' : ('j', 'J')
1660 }
1661 symbols = {
1662 '%': 'OPERATORS FORMATTING',
1663 '**': 'POWER',
1664 ',': 'TUPLES LISTS FUNCTIONS',
1665 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1666 '...': 'ELLIPSIS',
1667 ':': 'SLICINGS DICTIONARYLITERALS',
1668 '@': 'def class',
1669 '\\': 'STRINGS',
1670 '_': 'PRIVATENAMES',
1671 '__': 'PRIVATENAMES SPECIALMETHODS',
1672 '`': 'BACKQUOTES',
1673 '(': 'TUPLES FUNCTIONS CALLS',
1674 ')': 'TUPLES FUNCTIONS CALLS',
1675 '[': 'LISTS SUBSCRIPTS SLICINGS',
1676 ']': 'LISTS SUBSCRIPTS SLICINGS'
1677 }
1678 for topic, symbols_ in _symbols_inverse.items():
1679 for symbol in symbols_:
1680 topics = symbols.get(symbol, topic)
1681 if topic not in topics:
1682 topics = topics + ' ' + topic
1683 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001684
1685 topics = {
Georg Brandl6b38daa2008-06-01 21:05:17 +00001686 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1687 'FUNCTIONS CLASSES MODULES FILES inspect'),
1688 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS '
1689 'FORMATTING TYPES'),
1690 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1691 'FORMATTING': ('formatstrings', 'OPERATORS'),
1692 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1693 'FORMATTING TYPES'),
1694 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1695 'INTEGER': ('integers', 'int range'),
1696 'FLOAT': ('floating', 'float math'),
1697 'COMPLEX': ('imaginary', 'complex cmath'),
1698 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING range LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001699 'MAPPINGS': 'DICTIONARIES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001700 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1701 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1702 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1703 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001704 'FRAMEOBJECTS': 'TYPES',
1705 'TRACEBACKS': 'TYPES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001706 'NONE': ('bltin-null-object', ''),
1707 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
1708 'FILES': ('bltin-file-objects', ''),
1709 'SPECIALATTRIBUTES': ('specialattrs', ''),
1710 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1711 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001712 'PACKAGES': 'import',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001713 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1714 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1715 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1716 'LISTS DICTIONARIES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001717 'OPERATORS': 'EXPRESSIONS',
1718 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001719 'OBJECTS': ('objects', 'TYPES'),
1720 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
Georg Brandl395ed242009-09-04 08:07:32 +00001721 'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS '
1722 'NUMBERMETHODS CLASSES'),
Mark Dickinsona56c4672009-01-27 18:17:45 +00001723 'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001724 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1725 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001726 'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS '
Georg Brandl6b38daa2008-06-01 21:05:17 +00001727 'SPECIALMETHODS'),
1728 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1729 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1730 'SPECIALMETHODS'),
1731 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001732 'NAMESPACES': ('naming', 'global nonlocal ASSIGNMENT DELETION DYNAMICFEATURES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001733 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001734 'SCOPING': 'NAMESPACES',
1735 'FRAMES': 'NAMESPACES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001736 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1737 'CONVERSIONS': ('conversions', ''),
1738 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1739 'SPECIALIDENTIFIERS': ('id-classes', ''),
1740 'PRIVATENAMES': ('atom-identifiers', ''),
1741 'LITERALS': ('atom-literals', 'STRINGS NUMBERS TUPLELITERALS '
1742 'LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001743 'TUPLES': 'SEQUENCES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001744 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1745 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1746 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1747 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1748 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1749 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001750 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'),
1751 'SLICINGS': ('slicings', 'SEQUENCEMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001752 'CALLS': ('calls', 'EXPRESSIONS'),
1753 'POWER': ('power', 'EXPRESSIONS'),
1754 'UNARY': ('unary', 'EXPRESSIONS'),
1755 'BINARY': ('binary', 'EXPRESSIONS'),
1756 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1757 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1758 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1759 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001760 'ASSERTION': 'assert',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001761 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1762 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001763 'DELETION': 'del',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001764 'RETURNING': 'return',
1765 'IMPORTING': 'import',
1766 'CONDITIONAL': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001767 'LOOPING': ('compound', 'for while break continue'),
1768 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1769 'DEBUGGING': ('debugger', 'pdb'),
1770 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001771 }
1772
Georg Brandl78aa3962010-07-31 21:51:48 +00001773 def __init__(self, input=None, output=None):
1774 self._input = input
1775 self._output = output
1776
Georg Brandl76ae3972010-08-01 06:32:55 +00001777 input = property(lambda self: self._input or sys.stdin)
1778 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001779
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001780 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001781 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001782 self()
1783 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001784 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001785
Alexander Belopolsky2e733c92010-07-04 17:00:20 +00001786 _GoInteractive = object()
1787 def __call__(self, request=_GoInteractive):
1788 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001789 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001790 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001791 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001792 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001793 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001794You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001795If you want to ask for help on a particular object directly from the
1796interpreter, you can type "help(object)". Executing "help('string')"
1797has the same effect as typing a particular string at the help> prompt.
1798''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001799
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001800 def interact(self):
1801 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001802 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001803 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001804 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001805 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001806 except (KeyboardInterrupt, EOFError):
1807 break
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001808 request = replace(request, '"', '', "'", '').strip()
1809 if request.lower() in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001810 self.help(request)
1811
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001812 def getline(self, prompt):
Guido van Rossum7c086c02008-01-02 03:52:38 +00001813 """Read one line, using input() when appropriate."""
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001814 if self.input is sys.stdin:
Guido van Rossum7c086c02008-01-02 03:52:38 +00001815 return input(prompt)
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001816 else:
1817 self.output.write(prompt)
1818 self.output.flush()
1819 return self.input.readline()
1820
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001821 def help(self, request):
1822 if type(request) is type(''):
R. David Murray1f1b9d32009-05-27 20:56:59 +00001823 request = request.strip()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001824 if request == 'help': self.intro()
1825 elif request == 'keywords': self.listkeywords()
Georg Brandldb7b6b92009-01-01 15:53:14 +00001826 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001827 elif request == 'topics': self.listtopics()
1828 elif request == 'modules': self.listmodules()
1829 elif request[:8] == 'modules ':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001830 self.listmodules(request.split()[1])
Georg Brandldb7b6b92009-01-01 15:53:14 +00001831 elif request in self.symbols: self.showsymbol(request)
Ezio Melottib185a042011-04-28 07:42:55 +03001832 elif request in ['True', 'False', 'None']:
1833 # special case these keywords since they are objects too
1834 doc(eval(request), 'Help on %s:')
Raymond Hettinger54f02222002-06-01 14:18:47 +00001835 elif request in self.keywords: self.showtopic(request)
1836 elif request in self.topics: self.showtopic(request)
Georg Brandld80d5f42010-12-03 07:47:22 +00001837 elif request: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001838 elif isinstance(request, Helper): self()
Georg Brandld80d5f42010-12-03 07:47:22 +00001839 else: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001840 self.output.write('\n')
1841
1842 def intro(self):
1843 self.output.write('''
Georg Brandlc645c6a2012-06-24 17:24:26 +02001844Welcome to Python %s! This is the interactive help utility.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001845
1846If this is your first time using Python, you should definitely check out
R David Murrayde0f6292012-03-31 12:06:35 -04001847the tutorial on the Internet at http://docs.python.org/%s/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001848
1849Enter the name of any module, keyword, or topic to get help on writing
1850Python programs and using Python modules. To quit this help utility and
1851return to the interpreter, just type "quit".
1852
Terry Jan Reedy34200572013-02-11 02:23:13 -05001853To get a list of available modules, keywords, symbols, or topics, type
1854"modules", "keywords", "symbols", or "topics". Each module also comes
1855with a one-line summary of what it does; to list the modules whose name
1856or summary contain a given string such as "spam", type "modules spam".
R David Murrayde0f6292012-03-31 12:06:35 -04001857''' % tuple([sys.version[:3]]*2))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001858
1859 def list(self, items, columns=4, width=80):
Guido van Rossum486364b2007-06-30 05:01:58 +00001860 items = list(sorted(items))
1861 colw = width // columns
1862 rows = (len(items) + columns - 1) // columns
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001863 for row in range(rows):
1864 for col in range(columns):
1865 i = col * rows + row
1866 if i < len(items):
1867 self.output.write(items[i])
1868 if col < columns - 1:
Guido van Rossum486364b2007-06-30 05:01:58 +00001869 self.output.write(' ' + ' ' * (colw - 1 - len(items[i])))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001870 self.output.write('\n')
1871
1872 def listkeywords(self):
1873 self.output.write('''
1874Here is a list of the Python keywords. Enter any keyword to get more help.
1875
1876''')
1877 self.list(self.keywords.keys())
1878
Georg Brandldb7b6b92009-01-01 15:53:14 +00001879 def listsymbols(self):
1880 self.output.write('''
1881Here is a list of the punctuation symbols which Python assigns special meaning
1882to. Enter any symbol to get more help.
1883
1884''')
1885 self.list(self.symbols.keys())
1886
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001887 def listtopics(self):
1888 self.output.write('''
1889Here is a list of available topics. Enter any topic name to get more help.
1890
1891''')
1892 self.list(self.topics.keys())
1893
Georg Brandldb7b6b92009-01-01 15:53:14 +00001894 def showtopic(self, topic, more_xrefs=''):
Georg Brandl6b38daa2008-06-01 21:05:17 +00001895 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001896 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04001897 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001898 self.output.write('''
Georg Brandl6b38daa2008-06-01 21:05:17 +00001899Sorry, topic and keyword documentation is not available because the
Georg Brandl5617db82009-04-27 16:28:57 +00001900module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001901''')
1902 return
1903 target = self.topics.get(topic, self.keywords.get(topic))
1904 if not target:
1905 self.output.write('no documentation found for %s\n' % repr(topic))
1906 return
1907 if type(target) is type(''):
Georg Brandldb7b6b92009-01-01 15:53:14 +00001908 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001909
Georg Brandl6b38daa2008-06-01 21:05:17 +00001910 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001911 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001912 doc = pydoc_data.topics.topics[label]
Georg Brandl6b38daa2008-06-01 21:05:17 +00001913 except KeyError:
1914 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001915 return
Georg Brandl6b38daa2008-06-01 21:05:17 +00001916 pager(doc.strip() + '\n')
Georg Brandldb7b6b92009-01-01 15:53:14 +00001917 if more_xrefs:
1918 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001919 if xrefs:
Brett Cannon1448ecf2013-10-04 11:38:59 -04001920 import textwrap
1921 text = 'Related help topics: ' + ', '.join(xrefs.split()) + '\n'
1922 wrapped_text = textwrap.wrap(text, 72)
1923 self.output.write('\n%s\n' % ''.join(wrapped_text))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001924
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001925 def _gettopic(self, topic, more_xrefs=''):
1926 """Return unbuffered tuple of (topic, xrefs).
1927
Georg Brandld2f38572011-01-30 08:37:19 +00001928 If an error occurs here, the exception is caught and displayed by
1929 the url handler.
1930
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001931 This function duplicates the showtopic method but returns its
1932 result directly so it can be formatted for display in an html page.
1933 """
1934 try:
1935 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04001936 except ImportError:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001937 return('''
1938Sorry, topic and keyword documentation is not available because the
1939module "pydoc_data.topics" could not be found.
1940''' , '')
1941 target = self.topics.get(topic, self.keywords.get(topic))
1942 if not target:
Georg Brandld2f38572011-01-30 08:37:19 +00001943 raise ValueError('could not find topic')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001944 if isinstance(target, str):
1945 return self._gettopic(target, more_xrefs)
1946 label, xrefs = target
Georg Brandld2f38572011-01-30 08:37:19 +00001947 doc = pydoc_data.topics.topics[label]
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001948 if more_xrefs:
1949 xrefs = (xrefs or '') + ' ' + more_xrefs
1950 return doc, xrefs
1951
Georg Brandldb7b6b92009-01-01 15:53:14 +00001952 def showsymbol(self, symbol):
1953 target = self.symbols[symbol]
1954 topic, _, xrefs = target.partition(' ')
1955 self.showtopic(topic, xrefs)
1956
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001957 def listmodules(self, key=''):
1958 if key:
1959 self.output.write('''
Terry Jan Reedy34200572013-02-11 02:23:13 -05001960Here is a list of modules whose name or summary contains '{}'.
1961If there are any, enter a module name to get more help.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001962
Terry Jan Reedy34200572013-02-11 02:23:13 -05001963'''.format(key))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001964 apropos(key)
1965 else:
1966 self.output.write('''
1967Please wait a moment while I gather a list of all available modules...
1968
1969''')
1970 modules = {}
1971 def callback(path, modname, desc, modules=modules):
1972 if modname and modname[-9:] == '.__init__':
1973 modname = modname[:-9] + ' (package)'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001974 if modname.find('.') < 0:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001975 modules[modname] = 1
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001976 def onerror(modname):
1977 callback(None, modname, None)
1978 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001979 self.list(modules.keys())
1980 self.output.write('''
1981Enter any module name to get more help. Or, type "modules spam" to search
Terry Jan Reedy34200572013-02-11 02:23:13 -05001982for modules whose name or summary contain the string "spam".
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001983''')
1984
Georg Brandl78aa3962010-07-31 21:51:48 +00001985help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001986
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001987class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001988 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001989
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001990 def run(self, callback, key=None, completer=None, onerror=None):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001991 if key: key = key.lower()
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001992 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001993 seen = {}
1994
1995 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001996 if modname != '__main__':
1997 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00001998 if key is None:
1999 callback(None, modname, '')
2000 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002001 name = __import__(modname).__doc__ or ''
2002 desc = name.split('\n')[0]
2003 name = modname + ' - ' + desc
2004 if name.lower().find(key) >= 0:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002005 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002006
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002007 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002008 if self.quit:
2009 break
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002010
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002011 if key is None:
2012 callback(None, modname, '')
2013 else:
Georg Brandl126c8792009-04-05 15:05:48 +00002014 try:
2015 loader = importer.find_module(modname)
2016 except SyntaxError:
2017 # raised by tests for bad coding cookies or BOM
2018 continue
2019 if hasattr(loader, 'get_source'):
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002020 try:
2021 source = loader.get_source(modname)
Nick Coghlan2824cb52012-07-15 22:12:14 +10002022 except Exception:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002023 if onerror:
2024 onerror(modname)
2025 continue
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002026 desc = source_synopsis(io.StringIO(source)) or ''
Georg Brandl126c8792009-04-05 15:05:48 +00002027 if hasattr(loader, 'get_filename'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002028 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002029 else:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002030 path = None
2031 else:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002032 try:
2033 module = loader.load_module(modname)
2034 except ImportError:
2035 if onerror:
2036 onerror(modname)
2037 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002038 desc = (module.__doc__ or '').splitlines()[0]
2039 path = getattr(module,'__file__',None)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002040 name = modname + ' - ' + desc
2041 if name.lower().find(key) >= 0:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002042 callback(path, modname, desc)
2043
2044 if completer:
2045 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002046
2047def apropos(key):
2048 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002049 def callback(path, modname, desc):
2050 if modname[-9:] == '.__init__':
2051 modname = modname[:-9] + ' (package)'
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002052 print(modname, desc and '- ' + desc)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002053 def onerror(modname):
2054 pass
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002055 with warnings.catch_warnings():
2056 warnings.filterwarnings('ignore') # ignore problems during import
2057 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002058
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002059# --------------------------------------- enhanced Web browser interface
2060
2061def _start_server(urlhandler, port):
2062 """Start an HTTP server thread on a specific port.
2063
2064 Start an HTML/text server thread, so HTML or text documents can be
2065 browsed dynamically and interactively with a Web browser. Example use:
2066
2067 >>> import time
2068 >>> import pydoc
2069
2070 Define a URL handler. To determine what the client is asking
2071 for, check the URL and content_type.
2072
2073 Then get or generate some text or HTML code and return it.
2074
2075 >>> def my_url_handler(url, content_type):
2076 ... text = 'the URL sent was: (%s, %s)' % (url, content_type)
2077 ... return text
2078
2079 Start server thread on port 0.
2080 If you use port 0, the server will pick a random port number.
2081 You can then use serverthread.port to get the port number.
2082
2083 >>> port = 0
2084 >>> serverthread = pydoc._start_server(my_url_handler, port)
2085
2086 Check that the server is really started. If it is, open browser
2087 and get first page. Use serverthread.url as the starting page.
2088
2089 >>> if serverthread.serving:
2090 ... import webbrowser
2091
2092 The next two lines are commented out so a browser doesn't open if
2093 doctest is run on this module.
2094
2095 #... webbrowser.open(serverthread.url)
2096 #True
2097
2098 Let the server do its thing. We just need to monitor its status.
2099 Use time.sleep so the loop doesn't hog the CPU.
2100
2101 >>> starttime = time.time()
2102 >>> timeout = 1 #seconds
2103
2104 This is a short timeout for testing purposes.
2105
2106 >>> while serverthread.serving:
2107 ... time.sleep(.01)
2108 ... if serverthread.serving and time.time() - starttime > timeout:
2109 ... serverthread.stop()
2110 ... break
2111
2112 Print any errors that may have occurred.
2113
2114 >>> print(serverthread.error)
2115 None
2116 """
2117 import http.server
2118 import email.message
2119 import select
2120 import threading
2121
2122 class DocHandler(http.server.BaseHTTPRequestHandler):
2123
2124 def do_GET(self):
2125 """Process a request from an HTML browser.
2126
2127 The URL received is in self.path.
2128 Get an HTML page from self.urlhandler and send it.
2129 """
2130 if self.path.endswith('.css'):
2131 content_type = 'text/css'
2132 else:
2133 content_type = 'text/html'
2134 self.send_response(200)
Georg Brandld2f38572011-01-30 08:37:19 +00002135 self.send_header('Content-Type', '%s; charset=UTF-8' % content_type)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002136 self.end_headers()
2137 self.wfile.write(self.urlhandler(
2138 self.path, content_type).encode('utf-8'))
2139
2140 def log_message(self, *args):
2141 # Don't log messages.
2142 pass
2143
2144 class DocServer(http.server.HTTPServer):
2145
2146 def __init__(self, port, callback):
2147 self.host = (sys.platform == 'mac') and '127.0.0.1' or 'localhost'
2148 self.address = ('', port)
2149 self.callback = callback
2150 self.base.__init__(self, self.address, self.handler)
2151 self.quit = False
2152
2153 def serve_until_quit(self):
2154 while not self.quit:
2155 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2156 if rd:
2157 self.handle_request()
Victor Stinnera3abd1d2011-01-03 16:12:39 +00002158 self.server_close()
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002159
2160 def server_activate(self):
2161 self.base.server_activate(self)
2162 if self.callback:
2163 self.callback(self)
2164
2165 class ServerThread(threading.Thread):
2166
2167 def __init__(self, urlhandler, port):
2168 self.urlhandler = urlhandler
2169 self.port = int(port)
2170 threading.Thread.__init__(self)
2171 self.serving = False
2172 self.error = None
2173
2174 def run(self):
2175 """Start the server."""
2176 try:
2177 DocServer.base = http.server.HTTPServer
2178 DocServer.handler = DocHandler
2179 DocHandler.MessageClass = email.message.Message
2180 DocHandler.urlhandler = staticmethod(self.urlhandler)
2181 docsvr = DocServer(self.port, self.ready)
2182 self.docserver = docsvr
2183 docsvr.serve_until_quit()
2184 except Exception as e:
2185 self.error = e
2186
2187 def ready(self, server):
2188 self.serving = True
2189 self.host = server.host
2190 self.port = server.server_port
2191 self.url = 'http://%s:%d/' % (self.host, self.port)
2192
2193 def stop(self):
2194 """Stop the server and this thread nicely"""
2195 self.docserver.quit = True
2196 self.serving = False
2197 self.url = None
2198
2199 thread = ServerThread(urlhandler, port)
2200 thread.start()
2201 # Wait until thread.serving is True to make sure we are
2202 # really up before returning.
2203 while not thread.error and not thread.serving:
2204 time.sleep(.01)
2205 return thread
2206
2207
2208def _url_handler(url, content_type="text/html"):
2209 """The pydoc url handler for use with the pydoc server.
2210
2211 If the content_type is 'text/css', the _pydoc.css style
2212 sheet is read and returned if it exits.
2213
2214 If the content_type is 'text/html', then the result of
2215 get_html_page(url) is returned.
2216 """
2217 class _HTMLDoc(HTMLDoc):
2218
2219 def page(self, title, contents):
2220 """Format an HTML page."""
2221 css_path = "pydoc_data/_pydoc.css"
2222 css_link = (
2223 '<link rel="stylesheet" type="text/css" href="%s">' %
2224 css_path)
2225 return '''\
2226<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Georg Brandld2f38572011-01-30 08:37:19 +00002227<html><head><title>Pydoc: %s</title>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002228<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Georg Brandld2f38572011-01-30 08:37:19 +00002229%s</head><body bgcolor="#f0f0f8">%s<div style="clear:both;padding-top:.5em;">%s</div>
2230</body></html>''' % (title, css_link, html_navbar(), contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002231
2232 def filelink(self, url, path):
2233 return '<a href="getfile?key=%s">%s</a>' % (url, path)
2234
2235
2236 html = _HTMLDoc()
2237
2238 def html_navbar():
Georg Brandld2f38572011-01-30 08:37:19 +00002239 version = html.escape("%s [%s, %s]" % (platform.python_version(),
2240 platform.python_build()[0],
2241 platform.python_compiler()))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002242 return """
2243 <div style='float:left'>
Georg Brandld2f38572011-01-30 08:37:19 +00002244 Python %s<br>%s
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002245 </div>
2246 <div style='float:right'>
2247 <div style='text-align:center'>
2248 <a href="index.html">Module Index</a>
2249 : <a href="topics.html">Topics</a>
2250 : <a href="keywords.html">Keywords</a>
2251 </div>
2252 <div>
Georg Brandld2f38572011-01-30 08:37:19 +00002253 <form action="get" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002254 <input type=text name=key size=15>
2255 <input type=submit value="Get">
Georg Brandld2f38572011-01-30 08:37:19 +00002256 </form>&nbsp;
2257 <form action="search" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002258 <input type=text name=key size=15>
2259 <input type=submit value="Search">
2260 </form>
2261 </div>
2262 </div>
Georg Brandld2f38572011-01-30 08:37:19 +00002263 """ % (version, html.escape(platform.platform(terse=True)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002264
2265 def html_index():
2266 """Module Index page."""
2267
2268 def bltinlink(name):
2269 return '<a href="%s.html">%s</a>' % (name, name)
2270
2271 heading = html.heading(
2272 '<big><big><strong>Index of Modules</strong></big></big>',
2273 '#ffffff', '#7799ee')
2274 names = [name for name in sys.builtin_module_names
2275 if name != '__main__']
2276 contents = html.multicolumn(names, bltinlink)
2277 contents = [heading, '<p>' + html.bigsection(
2278 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2279
2280 seen = {}
2281 for dir in sys.path:
2282 contents.append(html.index(dir, seen))
2283
2284 contents.append(
2285 '<p align=right><font color="#909090" face="helvetica,'
2286 'arial"><strong>pydoc</strong> by Ka-Ping Yee'
2287 '&lt;ping@lfw.org&gt;</font>')
Nick Coghlanecace282010-12-03 16:08:46 +00002288 return 'Index of Modules', ''.join(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002289
2290 def html_search(key):
2291 """Search results page."""
2292 # scan for modules
2293 search_result = []
2294
2295 def callback(path, modname, desc):
2296 if modname[-9:] == '.__init__':
2297 modname = modname[:-9] + ' (package)'
2298 search_result.append((modname, desc and '- ' + desc))
2299
2300 with warnings.catch_warnings():
2301 warnings.filterwarnings('ignore') # ignore problems during import
2302 ModuleScanner().run(callback, key)
2303
2304 # format page
2305 def bltinlink(name):
2306 return '<a href="%s.html">%s</a>' % (name, name)
2307
2308 results = []
2309 heading = html.heading(
2310 '<big><big><strong>Search Results</strong></big></big>',
2311 '#ffffff', '#7799ee')
2312 for name, desc in search_result:
2313 results.append(bltinlink(name) + desc)
2314 contents = heading + html.bigsection(
2315 'key = %s' % key, '#ffffff', '#ee77aa', '<br>'.join(results))
Nick Coghlanecace282010-12-03 16:08:46 +00002316 return 'Search Results', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002317
2318 def html_getfile(path):
2319 """Get and display a source file listing safely."""
Nick Coghlanecace282010-12-03 16:08:46 +00002320 path = path.replace('%20', ' ')
Victor Stinner91e08772011-07-05 14:30:41 +02002321 with tokenize.open(path) as fp:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002322 lines = html.escape(fp.read())
2323 body = '<pre>%s</pre>' % lines
2324 heading = html.heading(
2325 '<big><big><strong>File Listing</strong></big></big>',
2326 '#ffffff', '#7799ee')
2327 contents = heading + html.bigsection(
2328 'File: %s' % path, '#ffffff', '#ee77aa', body)
Nick Coghlanecace282010-12-03 16:08:46 +00002329 return 'getfile %s' % path, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002330
2331 def html_topics():
2332 """Index of topic texts available."""
2333
2334 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002335 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002336
2337 heading = html.heading(
2338 '<big><big><strong>INDEX</strong></big></big>',
2339 '#ffffff', '#7799ee')
2340 names = sorted(Helper.topics.keys())
2341
2342 contents = html.multicolumn(names, bltinlink)
2343 contents = heading + html.bigsection(
2344 'Topics', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002345 return 'Topics', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002346
2347 def html_keywords():
2348 """Index of keywords."""
2349 heading = html.heading(
2350 '<big><big><strong>INDEX</strong></big></big>',
2351 '#ffffff', '#7799ee')
2352 names = sorted(Helper.keywords.keys())
2353
2354 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002355 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002356
2357 contents = html.multicolumn(names, bltinlink)
2358 contents = heading + html.bigsection(
2359 'Keywords', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002360 return 'Keywords', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002361
2362 def html_topicpage(topic):
2363 """Topic or keyword help page."""
2364 buf = io.StringIO()
2365 htmlhelp = Helper(buf, buf)
2366 contents, xrefs = htmlhelp._gettopic(topic)
2367 if topic in htmlhelp.keywords:
2368 title = 'KEYWORD'
2369 else:
2370 title = 'TOPIC'
2371 heading = html.heading(
2372 '<big><big><strong>%s</strong></big></big>' % title,
2373 '#ffffff', '#7799ee')
Georg Brandld2f38572011-01-30 08:37:19 +00002374 contents = '<pre>%s</pre>' % html.markup(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002375 contents = html.bigsection(topic , '#ffffff','#ee77aa', contents)
Georg Brandld2f38572011-01-30 08:37:19 +00002376 if xrefs:
2377 xrefs = sorted(xrefs.split())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002378
Georg Brandld2f38572011-01-30 08:37:19 +00002379 def bltinlink(name):
2380 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002381
Georg Brandld2f38572011-01-30 08:37:19 +00002382 xrefs = html.multicolumn(xrefs, bltinlink)
2383 xrefs = html.section('Related help topics: ',
2384 '#ffffff', '#ee77aa', xrefs)
Nick Coghlanecace282010-12-03 16:08:46 +00002385 return ('%s %s' % (title, topic),
2386 ''.join((heading, contents, xrefs)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002387
Georg Brandld2f38572011-01-30 08:37:19 +00002388 def html_getobj(url):
2389 obj = locate(url, forceload=1)
2390 if obj is None and url != 'None':
2391 raise ValueError('could not find object')
2392 title = describe(obj)
2393 content = html.document(obj, url)
2394 return title, content
2395
2396 def html_error(url, exc):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002397 heading = html.heading(
2398 '<big><big><strong>Error</strong></big></big>',
Georg Brandld2f38572011-01-30 08:37:19 +00002399 '#ffffff', '#7799ee')
2400 contents = '<br>'.join(html.escape(line) for line in
2401 format_exception_only(type(exc), exc))
2402 contents = heading + html.bigsection(url, '#ffffff', '#bb0000',
2403 contents)
2404 return "Error - %s" % url, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002405
2406 def get_html_page(url):
2407 """Generate an HTML page for url."""
Georg Brandld2f38572011-01-30 08:37:19 +00002408 complete_url = url
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002409 if url.endswith('.html'):
2410 url = url[:-5]
Georg Brandld2f38572011-01-30 08:37:19 +00002411 try:
2412 if url in ("", "index"):
2413 title, content = html_index()
2414 elif url == "topics":
2415 title, content = html_topics()
2416 elif url == "keywords":
2417 title, content = html_keywords()
2418 elif '=' in url:
2419 op, _, url = url.partition('=')
2420 if op == "search?key":
2421 title, content = html_search(url)
2422 elif op == "getfile?key":
2423 title, content = html_getfile(url)
2424 elif op == "topic?key":
2425 # try topics first, then objects.
2426 try:
2427 title, content = html_topicpage(url)
2428 except ValueError:
2429 title, content = html_getobj(url)
2430 elif op == "get?key":
2431 # try objects first, then topics.
2432 if url in ("", "index"):
2433 title, content = html_index()
2434 else:
2435 try:
2436 title, content = html_getobj(url)
2437 except ValueError:
2438 title, content = html_topicpage(url)
2439 else:
2440 raise ValueError('bad pydoc url')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002441 else:
Georg Brandld2f38572011-01-30 08:37:19 +00002442 title, content = html_getobj(url)
2443 except Exception as exc:
2444 # Catch any errors and display them in an error page.
2445 title, content = html_error(complete_url, exc)
2446 return html.page(title, content)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002447
2448 if url.startswith('/'):
2449 url = url[1:]
2450 if content_type == 'text/css':
2451 path_here = os.path.dirname(os.path.realpath(__file__))
Georg Brandld2f38572011-01-30 08:37:19 +00002452 css_path = os.path.join(path_here, url)
2453 with open(css_path) as fp:
2454 return ''.join(fp.readlines())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002455 elif content_type == 'text/html':
2456 return get_html_page(url)
Georg Brandld2f38572011-01-30 08:37:19 +00002457 # Errors outside the url handler are caught by the server.
2458 raise TypeError('unknown content type %r for url %s' % (content_type, url))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002459
2460
2461def browse(port=0, *, open_browser=True):
2462 """Start the enhanced pydoc Web server and open a Web browser.
2463
2464 Use port '0' to start the server on an arbitrary port.
2465 Set open_browser to False to suppress opening a browser.
2466 """
2467 import webbrowser
2468 serverthread = _start_server(_url_handler, port)
2469 if serverthread.error:
2470 print(serverthread.error)
2471 return
2472 if serverthread.serving:
2473 server_help_msg = 'Server commands: [b]rowser, [q]uit'
2474 if open_browser:
2475 webbrowser.open(serverthread.url)
2476 try:
2477 print('Server ready at', serverthread.url)
2478 print(server_help_msg)
2479 while serverthread.serving:
2480 cmd = input('server> ')
2481 cmd = cmd.lower()
2482 if cmd == 'q':
2483 break
2484 elif cmd == 'b':
2485 webbrowser.open(serverthread.url)
2486 else:
2487 print(server_help_msg)
2488 except (KeyboardInterrupt, EOFError):
2489 print()
2490 finally:
2491 if serverthread.serving:
2492 serverthread.stop()
2493 print('Server stopped')
2494
2495
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002496# -------------------------------------------------- command-line interface
2497
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002498def ispath(x):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002499 return isinstance(x, str) and x.find(os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002500
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002501def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002502 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002503 import getopt
Guido van Rossum756aa932007-04-07 03:04:01 +00002504 class BadUsage(Exception): pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002505
Nick Coghlan106274b2009-11-15 23:04:33 +00002506 # Scripts don't get the current directory in their path by default
2507 # unless they are run with the '-m' switch
2508 if '' not in sys.path:
2509 scriptdir = os.path.dirname(sys.argv[0])
2510 if scriptdir in sys.path:
2511 sys.path.remove(scriptdir)
2512 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002513
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002514 try:
Victor Stinner383c3fc2011-05-25 01:35:05 +02002515 opts, args = getopt.getopt(sys.argv[1:], 'bk:p:w')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002516 writing = False
2517 start_server = False
2518 open_browser = False
2519 port = None
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002520 for opt, val in opts:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002521 if opt == '-b':
2522 start_server = True
2523 open_browser = True
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002524 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002525 apropos(val)
2526 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002527 if opt == '-p':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002528 start_server = True
2529 port = val
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002530 if opt == '-w':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002531 writing = True
2532
Benjamin Petersonb29614e2012-10-09 11:16:03 -04002533 if start_server:
2534 if port is None:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002535 port = 0
2536 browse(port, open_browser=open_browser)
2537 return
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002538
2539 if not args: raise BadUsage
2540 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002541 if ispath(arg) and not os.path.exists(arg):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002542 print('file %r does not exist' % arg)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002543 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002544 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002545 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002546 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002547 if writing:
2548 if ispath(arg) and os.path.isdir(arg):
2549 writedocs(arg)
2550 else:
2551 writedoc(arg)
2552 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002553 help.help(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +00002554 except ErrorDuringImport as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002555 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002556
2557 except (getopt.error, BadUsage):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002558 cmd = os.path.splitext(os.path.basename(sys.argv[0]))[0]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002559 print("""pydoc - the Python documentation tool
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002560
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002561{cmd} <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002562 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002563 Python keyword, topic, function, module, or package, or a dotted
2564 reference to a class or function within a module or module in a
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002565 package. If <name> contains a '{sep}', it is used as the path to a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002566 Python source file to document. If name is 'keywords', 'topics',
2567 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002568
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002569{cmd} -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002570 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002571
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002572{cmd} -p <port>
2573 Start an HTTP server on the given port on the local machine. Port
2574 number 0 can be used to get an arbitrary unused port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002575
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002576{cmd} -b
2577 Start an HTTP server on an arbitrary unused port and open a Web browser
2578 to interactively browse documentation. The -p option can be used with
2579 the -b option to explicitly specify the server port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002580
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002581{cmd} -w <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002582 Write out the HTML documentation for a module to a file in the current
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002583 directory. If <name> contains a '{sep}', it is treated as a filename; if
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002584 it names a directory, documentation is written for all the contents.
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002585""".format(cmd=cmd, sep=os.sep))
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002586
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002587if __name__ == '__main__':
2588 cli()