blob: 292aa46015ecf5e7b6b86469a22d211ff751a4bf [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:
47# - imp.load_module() cannot be prevented from clobbering existing
48# loaded modules, so calling synopsis() on a binary module file
49# changes the contents of any existing module with the same name.
50# - If the __file__ attribute on a module is a relative path and
51# the current directory is changed with os.chdir(), an incorrect
52# path will be displayed.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000053
Nick Coghlan7bb30b72010-12-03 09:29:11 +000054import builtins
55import imp
Brett Cannoncb66eb02012-05-11 12:58:42 -040056import importlib.machinery
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):
135 return inspect.ismethod(obj) or inspect.ismethoddescriptor(obj)
Tim Peters536d2262001-09-20 05:13:38 +0000136
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000137def allmethods(cl):
138 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000139 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000140 methods[key] = 1
141 for base in cl.__bases__:
142 methods.update(allmethods(base)) # all your base are belong to us
143 for key in methods.keys():
144 methods[key] = getattr(cl, key)
145 return methods
146
Tim Petersfa26f7c2001-09-24 08:05:11 +0000147def _split_list(s, predicate):
148 """Split sequence s via predicate, and return pair ([true], [false]).
149
150 The return value is a 2-tuple of lists,
151 ([x for x in s if predicate(x)],
152 [x for x in s if not predicate(x)])
153 """
154
Tim Peters28355492001-09-23 21:29:55 +0000155 yes = []
156 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000157 for x in s:
158 if predicate(x):
159 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000160 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000161 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000162 return yes, no
163
Raymond Hettinger1103d052011-03-25 14:15:24 -0700164def visiblename(name, all=None, obj=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000165 """Decide whether to show documentation on a variable."""
Brett Cannond340b432012-08-06 17:19:22 -0400166 # Certain special names are redundant or internal.
167 if name in {'__author__', '__builtins__', '__cached__', '__credits__',
168 '__date__', '__doc__', '__file__', '__initializing__',
169 '__loader__', '__module__', '__name__', '__package__',
170 '__path__', '__qualname__', '__slots__', '__version__'}:
Raymond Hettinger68272942011-03-18 02:22:15 -0700171 return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000172 # Private names are hidden, but special names are displayed.
173 if name.startswith('__') and name.endswith('__'): return 1
Raymond Hettinger1103d052011-03-25 14:15:24 -0700174 # Namedtuples have public fields and methods with a single leading underscore
175 if name.startswith('_') and hasattr(obj, '_fields'):
176 return True
Skip Montanaroa5616d22004-06-11 04:46:12 +0000177 if all is not None:
178 # only document that which the programmer exported in __all__
179 return name in all
180 else:
181 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000182
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000183def classify_class_attrs(object):
184 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000185 results = []
186 for (name, kind, cls, value) in inspect.classify_class_attrs(object):
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000187 if inspect.isdatadescriptor(value):
188 kind = 'data descriptor'
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000189 results.append((name, kind, cls, value))
190 return results
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000191
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000192# ----------------------------------------------------- module manipulation
193
194def ispackage(path):
195 """Guess whether a path refers to a package directory."""
196 if os.path.isdir(path):
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000197 for ext in ('.py', '.pyc', '.pyo'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000198 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000199 return True
200 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000201
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000202def source_synopsis(file):
203 line = file.readline()
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000204 while line[:1] == '#' or not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000205 line = file.readline()
206 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000207 line = line.strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000208 if line[:4] == 'r"""': line = line[1:]
209 if line[:3] == '"""':
210 line = line[3:]
211 if line[-1:] == '\\': line = line[:-1]
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000212 while not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000213 line = file.readline()
214 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000215 result = line.split('"""')[0].strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000216 else: result = None
217 return result
218
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000219def synopsis(filename, cache={}):
220 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000221 mtime = os.stat(filename).st_mtime
Charles-François Natali27c4e882011-07-27 19:40:02 +0200222 lastupdate, result = cache.get(filename, (None, None))
223 if lastupdate is None or lastupdate < mtime:
Georg Brandl26fd2e12006-03-08 09:34:53 +0000224 try:
Victor Stinnere6c910e2011-06-30 15:55:43 +0200225 file = tokenize.open(filename)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200226 except OSError:
Georg Brandl26fd2e12006-03-08 09:34:53 +0000227 # module can't be opened, so skip it
228 return None
Brett Cannoncb66eb02012-05-11 12:58:42 -0400229 binary_suffixes = importlib.machinery.BYTECODE_SUFFIXES[:]
230 binary_suffixes += importlib.machinery.EXTENSION_SUFFIXES[:]
231 if any(filename.endswith(x) for x in binary_suffixes):
232 # binary modules have to be imported
233 file.close()
234 if any(filename.endswith(x) for x in
235 importlib.machinery.BYTECODE_SUFFIXES):
236 loader = importlib.machinery.SourcelessFileLoader('__temp__',
237 filename)
238 else:
239 loader = importlib.machinery.ExtensionFileLoader('__temp__',
240 filename)
241 try:
242 module = loader.load_module('__temp__')
243 except:
244 return None
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000245 result = (module.__doc__ or '').splitlines()[0]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000246 del sys.modules['__temp__']
Brett Cannoncb66eb02012-05-11 12:58:42 -0400247 else:
248 # text modules can be directly examined
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000249 result = source_synopsis(file)
250 file.close()
Brett Cannoncb66eb02012-05-11 12:58:42 -0400251
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000252 cache[filename] = (mtime, result)
253 return result
254
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000255class ErrorDuringImport(Exception):
256 """Errors that occurred while trying to import something to document it."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000257 def __init__(self, filename, exc_info):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000258 self.filename = filename
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000259 self.exc, self.value, self.tb = exc_info
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000260
261 def __str__(self):
Guido van Rossuma01a8b62007-05-27 09:20:14 +0000262 exc = self.exc.__name__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000263 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000264
265def importfile(path):
266 """Import a Python source file or compiled file given its path."""
267 magic = imp.get_magic()
Victor Stinnere975af62011-07-04 02:08:50 +0200268 with open(path, 'rb') as file:
269 if file.read(len(magic)) == magic:
270 kind = imp.PY_COMPILED
271 else:
272 kind = imp.PY_SOURCE
273 file.seek(0)
274 filename = os.path.basename(path)
275 name, ext = os.path.splitext(filename)
276 try:
277 module = imp.load_module(name, file, path, (ext, 'r', kind))
278 except:
279 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000280 return module
281
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000282def safeimport(path, forceload=0, cache={}):
283 """Import a module; handle errors; return None if the module isn't found.
284
285 If the module *is* found but an exception occurs, it's wrapped in an
286 ErrorDuringImport exception and reraised. Unlike __import__, if a
287 package path is specified, the module at the end of the path is returned,
288 not the package at the beginning. If the optional 'forceload' argument
289 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000290 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000291 # If forceload is 1 and the module has been previously loaded from
292 # disk, we always have to reload the module. Checking the file's
293 # mtime isn't good enough (e.g. the module could contain a class
294 # that inherits from another module that has changed).
295 if forceload and path in sys.modules:
296 if path not in sys.builtin_module_names:
Guido van Rossume7ba4952007-06-06 23:52:48 +0000297 # Remove the module from sys.modules and re-import to try
298 # and avoid problems with partially loaded modules.
299 # Also remove any submodules because they won't appear
300 # in the newly loaded module's namespace if they're already
301 # in sys.modules.
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000302 subs = [m for m in sys.modules if m.startswith(path + '.')]
303 for key in [path] + subs:
304 # Prevent garbage collection.
305 cache[key] = sys.modules[key]
306 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000307 module = __import__(path)
308 except:
309 # Did the error occur before or after the module was found?
310 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000311 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000312 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000313 raise ErrorDuringImport(sys.modules[path].__file__, info)
314 elif exc is SyntaxError:
315 # A SyntaxError occurred before we could execute the module.
316 raise ErrorDuringImport(value.filename, info)
Brett Cannonfd074152012-04-14 14:10:13 -0400317 elif exc is ImportError and value.name == path:
318 # No such module in the path.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000319 return None
320 else:
321 # Some other error occurred during the importing process.
322 raise ErrorDuringImport(path, sys.exc_info())
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000323 for part in path.split('.')[1:]:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000324 try: module = getattr(module, part)
325 except AttributeError: return None
326 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000327
328# ---------------------------------------------------- formatter base class
329
330class Doc:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000331
332 PYTHONDOCS = os.environ.get("PYTHONDOCS",
333 "http://docs.python.org/%d.%d/library"
334 % sys.version_info[:2])
335
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000336 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000337 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000338 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000339 # 'try' clause is to attempt to handle the possibility that inspect
340 # identifies something in a way that pydoc itself has issues handling;
341 # think 'super' and how it is a descriptor (which raises the exception
342 # by lacking a __name__ attribute) and an instance.
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000343 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
344 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000345 try:
346 if inspect.ismodule(object): return self.docmodule(*args)
347 if inspect.isclass(object): return self.docclass(*args)
348 if inspect.isroutine(object): return self.docroutine(*args)
349 except AttributeError:
350 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000351 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000352 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000353
354 def fail(self, object, name=None, *args):
355 """Raise an exception for unimplemented types."""
356 message = "don't know how to document object%s of type %s" % (
357 name and ' ' + repr(name), type(object).__name__)
Collin Winterce36ad82007-08-30 01:19:48 +0000358 raise TypeError(message)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000359
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000360 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000361
Skip Montanaro4997a692003-09-10 16:47:51 +0000362 def getdocloc(self, object):
363 """Return the location of module docs or None"""
364
365 try:
366 file = inspect.getabsfile(object)
367 except TypeError:
368 file = '(built-in)'
369
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000370 docloc = os.environ.get("PYTHONDOCS", self.PYTHONDOCS)
371
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100372 basedir = os.path.join(sys.base_exec_prefix, "lib",
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000373 "python%d.%d" % sys.version_info[:2])
Skip Montanaro4997a692003-09-10 16:47:51 +0000374 if (isinstance(object, type(os)) and
375 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
376 'marshal', 'posix', 'signal', 'sys',
Georg Brandl2067bfd2008-05-25 13:05:15 +0000377 '_thread', 'zipimport') or
Skip Montanaro4997a692003-09-10 16:47:51 +0000378 (file.startswith(basedir) and
Brian Curtin49c284c2010-03-31 03:19:28 +0000379 not file.startswith(os.path.join(basedir, 'site-packages')))) and
Brian Curtinedef05b2010-04-01 04:05:25 +0000380 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
Skip Montanaro4997a692003-09-10 16:47:51 +0000381 if docloc.startswith("http://"):
Georg Brandl86def6c2008-01-21 20:36:10 +0000382 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
Skip Montanaro4997a692003-09-10 16:47:51 +0000383 else:
Georg Brandl86def6c2008-01-21 20:36:10 +0000384 docloc = os.path.join(docloc, object.__name__ + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000385 else:
386 docloc = None
387 return docloc
388
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000389# -------------------------------------------- HTML documentation generator
390
391class HTMLRepr(Repr):
392 """Class for safely making an HTML representation of a Python object."""
393 def __init__(self):
394 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000395 self.maxlist = self.maxtuple = 20
396 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000397 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000398
399 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000400 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000401
402 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000403 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000404
405 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000406 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000407 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000408 if hasattr(self, methodname):
409 return getattr(self, methodname)(x, level)
410 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000411
412 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000413 test = cram(x, self.maxstring)
414 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000415 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000416 # Backslashes are only literal in the string and are never
417 # needed to make any special characters, so show a raw string.
418 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000419 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000420 r'<font color="#c040c0">\1</font>',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000421 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000422
Skip Montanarodf708782002-03-07 22:58:02 +0000423 repr_str = repr_string
424
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000425 def repr_instance(self, x, level):
426 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000427 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000428 except:
429 return self.escape('<%s instance>' % x.__class__.__name__)
430
431 repr_unicode = repr_string
432
433class HTMLDoc(Doc):
434 """Formatter class for HTML documentation."""
435
436 # ------------------------------------------- HTML formatting utilities
437
438 _repr_instance = HTMLRepr()
439 repr = _repr_instance.repr
440 escape = _repr_instance.escape
441
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000442 def page(self, title, contents):
443 """Format an HTML page."""
Georg Brandl388faac2009-04-10 08:31:48 +0000444 return '''\
Georg Brandle6066942009-04-10 08:28:28 +0000445<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000446<html><head><title>Python: %s</title>
Georg Brandl388faac2009-04-10 08:31:48 +0000447<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000448</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000449%s
450</body></html>''' % (title, contents)
451
452 def heading(self, title, fgcol, bgcol, extras=''):
453 """Format a page heading."""
454 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000455<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000456<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000457<td valign=bottom>&nbsp;<br>
458<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000459><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000460><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000461 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
462
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000463 def section(self, title, fgcol, bgcol, contents, width=6,
464 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000465 """Format a section with a heading."""
466 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000467 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000468 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000469<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000470<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000471<td colspan=3 valign=bottom>&nbsp;<br>
472<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000473 ''' % (bgcol, fgcol, title)
474 if prelude:
475 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000476<tr bgcolor="%s"><td rowspan=2>%s</td>
477<td colspan=2>%s</td></tr>
478<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
479 else:
480 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000481<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000482
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000483 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000484
485 def bigsection(self, title, *args):
486 """Format a section with a big heading."""
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000487 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000488 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000489
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000490 def preformat(self, text):
491 """Format literal preformatted text."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000492 text = self.escape(text.expandtabs())
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000493 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
494 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000495
496 def multicolumn(self, list, format, cols=4):
497 """Format a list of items into a multi-column list."""
498 result = ''
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000499 rows = (len(list)+cols-1)//cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000500 for col in range(cols):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000501 result = result + '<td width="%d%%" valign=top>' % (100//cols)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000502 for i in range(rows*col, rows*col+rows):
503 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000504 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000505 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000506 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000507
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000508 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000509
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000510 def namelink(self, name, *dicts):
511 """Make a link for an identifier, given name-to-URL mappings."""
512 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000513 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000514 return '<a href="%s">%s</a>' % (dict[name], name)
515 return name
516
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000517 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000518 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000519 name, module = object.__name__, sys.modules.get(object.__module__)
520 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000521 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000522 module.__name__, name, classname(object, modname))
523 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000524
525 def modulelink(self, object):
526 """Make a link for a module."""
527 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
528
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000529 def modpkglink(self, modpkginfo):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000530 """Make a link for a module or package to display in an index."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000531 name, path, ispackage, shadowed = modpkginfo
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000532 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000533 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000534 if path:
535 url = '%s.%s.html' % (path, name)
536 else:
537 url = '%s.html' % name
538 if ispackage:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000539 text = '<strong>%s</strong>&nbsp;(package)' % name
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000540 else:
541 text = name
542 return '<a href="%s">%s</a>' % (url, text)
543
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000544 def filelink(self, url, path):
545 """Make a link to source file."""
546 return '<a href="file:%s">%s</a>' % (url, path)
547
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000548 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
549 """Mark up some plain text, given a context of symbols to look for.
550 Each context dictionary maps object names to anchor names."""
551 escape = escape or self.escape
552 results = []
553 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000554 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
555 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000556 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000557 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000558 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000559 match = pattern.search(text, here)
560 if not match: break
561 start, end = match.span()
562 results.append(escape(text[here:start]))
563
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000564 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000565 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000566 url = escape(all).replace('"', '&quot;')
567 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000568 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000569 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
570 results.append('<a href="%s">%s</a>' % (url, escape(all)))
571 elif pep:
Christian Heimes2202f872008-02-06 14:31:34 +0000572 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000573 results.append('<a href="%s">%s</a>' % (url, escape(all)))
574 elif text[end:end+1] == '(':
575 results.append(self.namelink(name, methods, funcs, classes))
576 elif selfdot:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000577 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000578 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000579 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000580 here = end
581 results.append(escape(text[here:]))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000582 return ''.join(results)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000583
584 # ---------------------------------------------- type-specific routines
585
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000586 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000587 """Produce HTML for a class tree as given by inspect.getclasstree()."""
588 result = ''
589 for entry in tree:
590 if type(entry) is type(()):
591 c, bases = entry
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000592 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000593 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000594 if bases and bases != (parent,):
595 parents = []
596 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000597 parents.append(self.classlink(base, modname))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000598 result = result + '(' + ', '.join(parents) + ')'
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000599 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000600 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000601 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000602 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000603 return '<dl>\n%s</dl>\n' % result
604
Tim Peters8dd7ade2001-10-18 19:56:17 +0000605 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000606 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000607 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000608 try:
609 all = object.__all__
610 except AttributeError:
611 all = None
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000612 parts = name.split('.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000613 links = []
614 for i in range(len(parts)-1):
615 links.append(
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000616 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000617 ('.'.join(parts[:i+1]), parts[i]))
618 linkedname = '.'.join(links + parts[-1:])
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000619 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000620 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000621 path = inspect.getabsfile(object)
Ka-Ping Yee6191a232001-04-13 15:00:27 +0000622 url = path
623 if sys.platform == 'win32':
624 import nturl2path
625 url = nturl2path.pathname2url(path)
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000626 filelink = self.filelink(url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000627 except TypeError:
628 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000629 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000630 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000631 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000632 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000633 version = version[11:-1].strip()
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000634 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000635 if hasattr(object, '__date__'):
636 info.append(self.escape(str(object.__date__)))
637 if info:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000638 head = head + ' (%s)' % ', '.join(info)
Skip Montanaro4997a692003-09-10 16:47:51 +0000639 docloc = self.getdocloc(object)
640 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000641 docloc = '<br><a href="%(docloc)s">Module Reference</a>' % locals()
Skip Montanaro4997a692003-09-10 16:47:51 +0000642 else:
643 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000644 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000645 head, '#ffffff', '#7799ee',
646 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000647
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000648 modules = inspect.getmembers(object, inspect.ismodule)
649
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000650 classes, cdict = [], {}
651 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000652 # if __all__ exists, believe it. Otherwise use old heuristic.
653 if (all is not None or
654 (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700655 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000656 classes.append((key, value))
657 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000658 for key, value in classes:
659 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000660 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000661 module = sys.modules.get(modname)
662 if modname != name and module and hasattr(module, key):
663 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000664 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000665 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000666 funcs, fdict = [], {}
667 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000668 # if __all__ exists, believe it. Otherwise use old heuristic.
669 if (all is not None or
670 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700671 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000672 funcs.append((key, value))
673 fdict[key] = '#-' + key
674 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000675 data = []
676 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700677 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000678 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000679
680 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
681 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000682 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000683
684 if hasattr(object, '__path__'):
685 modpkgs = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000686 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
687 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000688 modpkgs.sort()
689 contents = self.multicolumn(modpkgs, self.modpkglink)
690 result = result + self.bigsection(
691 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000692 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000693 contents = self.multicolumn(
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000694 modules, lambda t: self.modulelink(t[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000695 result = result + self.bigsection(
Christian Heimes7131fd92008-02-19 14:21:46 +0000696 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000697
698 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000699 classlist = [value for (key, value) in classes]
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000700 contents = [
701 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000702 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000703 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000704 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000705 'Classes', '#ffffff', '#ee77aa', ' '.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000706 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000707 contents = []
708 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000709 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000710 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000711 'Functions', '#ffffff', '#eeaa77', ' '.join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000712 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000713 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000714 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000715 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000716 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000717 'Data', '#ffffff', '#55aa55', '<br>\n'.join(contents))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000718 if hasattr(object, '__author__'):
719 contents = self.markup(str(object.__author__), self.preformat)
720 result = result + self.bigsection(
721 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000722 if hasattr(object, '__credits__'):
723 contents = self.markup(str(object.__credits__), self.preformat)
724 result = result + self.bigsection(
725 'Credits', '#ffffff', '#7799ee', contents)
726
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000727 return result
728
Tim Peters8dd7ade2001-10-18 19:56:17 +0000729 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
730 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000731 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000732 realname = object.__name__
733 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000734 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000735
Tim Petersb47879b2001-09-24 04:47:19 +0000736 contents = []
737 push = contents.append
738
Tim Petersfa26f7c2001-09-24 08:05:11 +0000739 # Cute little class to pump out a horizontal rule between sections.
740 class HorizontalRule:
741 def __init__(self):
742 self.needone = 0
743 def maybe(self):
744 if self.needone:
745 push('<hr>\n')
746 self.needone = 1
747 hr = HorizontalRule()
748
Tim Petersc86f6ca2001-09-26 21:31:51 +0000749 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000750 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000751 if len(mro) > 2:
752 hr.maybe()
753 push('<dl><dt>Method resolution order:</dt>\n')
754 for base in mro:
755 push('<dd>%s</dd>\n' % self.classlink(base,
756 object.__module__))
757 push('</dl>\n')
758
Tim Petersb47879b2001-09-24 04:47:19 +0000759 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000760 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000761 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000762 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000763 push(msg)
764 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100765 try:
766 value = getattr(object, name)
767 except Exception:
768 # Some descriptors may meet a failure in their __get__.
769 # (bug #1785)
770 push(self._docdescriptor(name, value, mod))
771 else:
772 push(self.document(value, name, mod,
773 funcs, classes, mdict, object))
Tim Petersb47879b2001-09-24 04:47:19 +0000774 push('\n')
775 return attrs
776
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000777 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000778 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000779 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000780 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000781 push(msg)
782 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000783 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000784 return attrs
785
Tim Petersfa26f7c2001-09-24 08:05:11 +0000786 def spilldata(msg, attrs, predicate):
787 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000788 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000789 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000790 push(msg)
791 for name, kind, homecls, value in ok:
792 base = self.docother(getattr(object, name), name, mod)
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200793 if callable(value) or inspect.isdatadescriptor(value):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000794 doc = getattr(value, "__doc__", None)
795 else:
796 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000797 if doc is None:
798 push('<dl><dt>%s</dl>\n' % base)
799 else:
800 doc = self.markup(getdoc(value), self.preformat,
801 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000802 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000803 push('<dl><dt>%s%s</dl>\n' % (base, doc))
804 push('\n')
805 return attrs
806
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000807 attrs = [(name, kind, cls, value)
808 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -0700809 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000810
Tim Petersb47879b2001-09-24 04:47:19 +0000811 mdict = {}
812 for key, kind, homecls, value in attrs:
813 mdict[key] = anchor = '#' + name + '-' + key
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100814 try:
815 value = getattr(object, name)
816 except Exception:
817 # Some descriptors may meet a failure in their __get__.
818 # (bug #1785)
819 pass
Tim Petersb47879b2001-09-24 04:47:19 +0000820 try:
821 # The value may not be hashable (e.g., a data attr with
822 # a dict or list value).
823 mdict[value] = anchor
824 except TypeError:
825 pass
826
Tim Petersfa26f7c2001-09-24 08:05:11 +0000827 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000828 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000829 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000830 else:
831 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000832 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
833
Georg Brandl1a3284e2007-12-02 09:40:06 +0000834 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000835 attrs = inherited
836 continue
837 elif thisclass is object:
838 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000839 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000840 tag = 'inherited from %s' % self.classlink(thisclass,
841 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000842 tag += ':<br>\n'
843
844 # Sort attrs by name.
Raymond Hettingerd4cb56d2008-01-30 02:55:10 +0000845 attrs.sort(key=lambda t: t[0])
Tim Petersb47879b2001-09-24 04:47:19 +0000846
847 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000848 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000849 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000850 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000851 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000852 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000853 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000854 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
855 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000856 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000857 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000858 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000859 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000860
861 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000862
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000863 if name == realname:
864 title = '<a name="%s">class <strong>%s</strong></a>' % (
865 name, realname)
866 else:
867 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
868 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000869 if bases:
870 parents = []
871 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000872 parents.append(self.classlink(base, object.__module__))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000873 title = title + '(%s)' % ', '.join(parents)
Tim Peters2306d242001-09-25 03:18:32 +0000874 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000875 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000876
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000877 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000878
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000879 def formatvalue(self, object):
880 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000881 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000882
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000883 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000884 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000885 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000886 realname = object.__name__
887 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000888 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000889 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000890 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000891 if inspect.ismethod(object):
Christian Heimesff737952007-11-27 10:40:20 +0000892 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000893 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000894 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000895 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000896 else:
Christian Heimesff737952007-11-27 10:40:20 +0000897 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000898 note = ' method of %s instance' % self.classlink(
Christian Heimesff737952007-11-27 10:40:20 +0000899 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000900 else:
901 note = ' unbound %s method' % self.classlink(imclass,mod)
Christian Heimesff737952007-11-27 10:40:20 +0000902 object = object.__func__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000903
904 if name == realname:
905 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
906 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000907 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000908 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000909 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000910 cl.__name__ + '-' + realname, realname)
911 skipdocs = 1
912 else:
913 reallink = realname
914 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
915 anchor, name, reallink)
Tim Peters4bcfa312001-09-20 06:08:24 +0000916 if inspect.isfunction(object):
Guido van Rossum2e65f892007-02-28 22:03:49 +0000917 args, varargs, kwonlyargs, kwdefaults, varkw, defaults, ann = \
918 inspect.getfullargspec(object)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000919 argspec = inspect.formatargspec(
Guido van Rossum2e65f892007-02-28 22:03:49 +0000920 args, varargs, kwonlyargs, kwdefaults, varkw, defaults, ann,
921 formatvalue=self.formatvalue,
922 formatannotation=inspect.formatannotationrelativeto(object))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000923 if realname == '<lambda>':
Tim Peters59ed4482001-10-31 04:20:26 +0000924 title = '<strong>%s</strong> <em>lambda</em> ' % name
Guido van Rossum2e65f892007-02-28 22:03:49 +0000925 # XXX lambda's won't usually have func_annotations['return']
926 # since the syntax doesn't support but it is possible.
927 # So removing parentheses isn't truly safe.
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000928 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +0000929 else:
930 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000931
Tim Peters2306d242001-09-25 03:18:32 +0000932 decl = title + argspec + (note and self.grey(
933 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000934
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000935 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000936 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000937 else:
938 doc = self.markup(
939 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000940 doc = doc and '<dd><tt>%s</tt></dd>' % doc
941 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000942
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000943 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000944 results = []
945 push = results.append
946
947 if name:
948 push('<dl><dt><strong>%s</strong></dt>\n' % name)
949 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000950 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000951 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000952 push('</dl>\n')
953
954 return ''.join(results)
955
956 def docproperty(self, object, name=None, mod=None, cl=None):
957 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000958 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000959
Tim Peters8dd7ade2001-10-18 19:56:17 +0000960 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000961 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000962 lhs = name and '<strong>%s</strong> = ' % name or ''
963 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000964
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000965 def docdata(self, object, name=None, mod=None, cl=None):
966 """Produce html documentation for a data descriptor."""
967 return self._docdescriptor(name, object, mod)
968
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000969 def index(self, dir, shadowed=None):
970 """Generate an HTML index for a directory of modules."""
971 modpkgs = []
972 if shadowed is None: shadowed = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000973 for importer, name, ispkg in pkgutil.iter_modules([dir]):
Victor Stinner4d652242011-04-12 23:41:50 +0200974 if any((0xD800 <= ord(ch) <= 0xDFFF) for ch in name):
975 # ignore a module if its name contains a surrogate character
976 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000977 modpkgs.append((name, '', ispkg, name in shadowed))
978 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000979
980 modpkgs.sort()
981 contents = self.multicolumn(modpkgs, self.modpkglink)
982 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
983
984# -------------------------------------------- text documentation generator
985
986class TextRepr(Repr):
987 """Class for safely making a text representation of a Python object."""
988 def __init__(self):
989 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000990 self.maxlist = self.maxtuple = 20
991 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000992 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000993
994 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000995 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000996 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000997 if hasattr(self, methodname):
998 return getattr(self, methodname)(x, level)
999 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001000
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001001 def repr_string(self, x, level):
1002 test = cram(x, self.maxstring)
1003 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001004 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001005 # Backslashes are only literal in the string and are never
1006 # needed to make any special characters, so show a raw string.
1007 return 'r' + testrepr[0] + test + testrepr[0]
1008 return testrepr
1009
Skip Montanarodf708782002-03-07 22:58:02 +00001010 repr_str = repr_string
1011
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001012 def repr_instance(self, x, level):
1013 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001014 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001015 except:
1016 return '<%s instance>' % x.__class__.__name__
1017
1018class TextDoc(Doc):
1019 """Formatter class for text documentation."""
1020
1021 # ------------------------------------------- text formatting utilities
1022
1023 _repr_instance = TextRepr()
1024 repr = _repr_instance.repr
1025
1026 def bold(self, text):
1027 """Format a string in bold by overstriking."""
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001028 return ''.join(ch + '\b' + ch for ch in text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001029
1030 def indent(self, text, prefix=' '):
1031 """Indent text by prepending a given prefix to each line."""
1032 if not text: return ''
Collin Winter72e110c2007-07-17 00:27:30 +00001033 lines = [prefix + line for line in text.split('\n')]
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001034 if lines: lines[-1] = lines[-1].rstrip()
1035 return '\n'.join(lines)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001036
1037 def section(self, title, contents):
1038 """Format a section with a given heading."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001039 clean_contents = self.indent(contents).rstrip()
1040 return self.bold(title) + '\n' + clean_contents + '\n\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001041
1042 # ---------------------------------------------- type-specific routines
1043
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001044 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001045 """Render in text a class tree as returned by inspect.getclasstree()."""
1046 result = ''
1047 for entry in tree:
1048 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001049 c, bases = entry
1050 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001051 if bases and bases != (parent,):
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001052 parents = (classname(c, modname) for c in bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001053 result = result + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001054 result = result + '\n'
1055 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001056 result = result + self.formattree(
1057 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001058 return result
1059
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001060 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001061 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001062 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001063 synop, desc = splitdoc(getdoc(object))
1064 result = self.section('NAME', name + (synop and ' - ' + synop))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001065 all = getattr(object, '__all__', None)
Skip Montanaro4997a692003-09-10 16:47:51 +00001066 docloc = self.getdocloc(object)
1067 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001068 result = result + self.section('MODULE REFERENCE', docloc + """
1069
Éric Araujo647ef8c2011-09-11 00:43:20 +02001070The following documentation is automatically generated from the Python
1071source files. It may be incomplete, incorrect or include features that
1072are considered implementation detail and may vary between Python
1073implementations. When in doubt, consult the module reference at the
1074location listed above.
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001075""")
Skip Montanaro4997a692003-09-10 16:47:51 +00001076
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001077 if desc:
1078 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001079
1080 classes = []
1081 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001082 # if __all__ exists, believe it. Otherwise use old heuristic.
1083 if (all is not None
1084 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001085 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001086 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001087 funcs = []
1088 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001089 # if __all__ exists, believe it. Otherwise use old heuristic.
1090 if (all is not None or
1091 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001092 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001093 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001094 data = []
1095 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001096 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001097 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001098
Christian Heimes1af737c2008-01-23 08:24:23 +00001099 modpkgs = []
1100 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001101 if hasattr(object, '__path__'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001102 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Christian Heimes1af737c2008-01-23 08:24:23 +00001103 modpkgs_names.add(modname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001104 if ispkg:
1105 modpkgs.append(modname + ' (package)')
1106 else:
1107 modpkgs.append(modname)
1108
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001109 modpkgs.sort()
1110 result = result + self.section(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001111 'PACKAGE CONTENTS', '\n'.join(modpkgs))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001112
Christian Heimes1af737c2008-01-23 08:24:23 +00001113 # Detect submodules as sometimes created by C extensions
1114 submodules = []
1115 for key, value in inspect.getmembers(object, inspect.ismodule):
1116 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1117 submodules.append(key)
1118 if submodules:
1119 submodules.sort()
1120 result = result + self.section(
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001121 'SUBMODULES', '\n'.join(submodules))
Christian Heimes1af737c2008-01-23 08:24:23 +00001122
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001123 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001124 classlist = [value for key, value in classes]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001125 contents = [self.formattree(
1126 inspect.getclasstree(classlist, 1), name)]
1127 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001128 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001129 result = result + self.section('CLASSES', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001130
1131 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001132 contents = []
1133 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001134 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001135 result = result + self.section('FUNCTIONS', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001136
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001137 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001138 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001139 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001140 contents.append(self.docother(value, key, name, maxlen=70))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001141 result = result + self.section('DATA', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001142
1143 if hasattr(object, '__version__'):
1144 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001145 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001146 version = version[11:-1].strip()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001147 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001148 if hasattr(object, '__date__'):
1149 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001150 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001151 result = result + self.section('AUTHOR', str(object.__author__))
1152 if hasattr(object, '__credits__'):
1153 result = result + self.section('CREDITS', str(object.__credits__))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001154 try:
1155 file = inspect.getabsfile(object)
1156 except TypeError:
1157 file = '(built-in)'
1158 result = result + self.section('FILE', file)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001159 return result
1160
Georg Brandl9bd45f992010-12-03 09:58:38 +00001161 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001162 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001163 realname = object.__name__
1164 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001165 bases = object.__bases__
1166
Tim Petersc86f6ca2001-09-26 21:31:51 +00001167 def makename(c, m=object.__module__):
1168 return classname(c, m)
1169
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001170 if name == realname:
1171 title = 'class ' + self.bold(realname)
1172 else:
1173 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001174 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001175 parents = map(makename, bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001176 title = title + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001177
1178 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001179 contents = doc and [doc + '\n'] or []
1180 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001181
Tim Petersc86f6ca2001-09-26 21:31:51 +00001182 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001183 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001184 if len(mro) > 2:
1185 push("Method resolution order:")
1186 for base in mro:
1187 push(' ' + makename(base))
1188 push('')
1189
Tim Petersf4aad8e2001-09-24 22:40:47 +00001190 # Cute little class to pump out a horizontal rule between sections.
1191 class HorizontalRule:
1192 def __init__(self):
1193 self.needone = 0
1194 def maybe(self):
1195 if self.needone:
1196 push('-' * 70)
1197 self.needone = 1
1198 hr = HorizontalRule()
1199
Tim Peters28355492001-09-23 21:29:55 +00001200 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001201 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001202 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001203 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001204 push(msg)
1205 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001206 try:
1207 value = getattr(object, name)
1208 except Exception:
1209 # Some descriptors may meet a failure in their __get__.
1210 # (bug #1785)
1211 push(self._docdescriptor(name, value, mod))
1212 else:
1213 push(self.document(value,
1214 name, mod, object))
Tim Peters28355492001-09-23 21:29:55 +00001215 return attrs
1216
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001217 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001218 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001219 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001220 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001221 push(msg)
1222 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001223 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001224 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001225
Tim Petersfa26f7c2001-09-24 08:05:11 +00001226 def spilldata(msg, attrs, predicate):
1227 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001228 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001229 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001230 push(msg)
1231 for name, kind, homecls, value in ok:
Florent Xicluna5d1155c2011-10-28 14:45:05 +02001232 if callable(value) or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001233 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001234 else:
1235 doc = None
Tim Peters28355492001-09-23 21:29:55 +00001236 push(self.docother(getattr(object, name),
Georg Brandl8b813db2005-10-01 16:32:31 +00001237 name, mod, maxlen=70, doc=doc) + '\n')
Tim Peters28355492001-09-23 21:29:55 +00001238 return attrs
1239
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001240 attrs = [(name, kind, cls, value)
1241 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -07001242 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001243
Tim Petersfa26f7c2001-09-24 08:05:11 +00001244 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001245 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001246 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001247 else:
1248 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001249 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1250
Georg Brandl1a3284e2007-12-02 09:40:06 +00001251 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001252 attrs = inherited
1253 continue
1254 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001255 tag = "defined here"
1256 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001257 tag = "inherited from %s" % classname(thisclass,
1258 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001259
1260 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001261 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001262
1263 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001264 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001265 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001266 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001267 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001268 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001269 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001270 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1271 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001272 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1273 lambda t: t[1] == 'data')
Tim Peters28355492001-09-23 21:29:55 +00001274 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001275 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001276
1277 contents = '\n'.join(contents)
1278 if not contents:
1279 return title + '\n'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001280 return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001281
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001282 def formatvalue(self, object):
1283 """Format an argument default value as text."""
1284 return '=' + self.repr(object)
1285
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001286 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001287 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001288 realname = object.__name__
1289 name = name or realname
1290 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001291 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001292 if inspect.ismethod(object):
Christian Heimesff737952007-11-27 10:40:20 +00001293 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001294 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001295 if imclass is not cl:
1296 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001297 else:
Christian Heimesff737952007-11-27 10:40:20 +00001298 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001299 note = ' method of %s instance' % classname(
Christian Heimesff737952007-11-27 10:40:20 +00001300 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001301 else:
1302 note = ' unbound %s method' % classname(imclass,mod)
Christian Heimesff737952007-11-27 10:40:20 +00001303 object = object.__func__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001304
1305 if name == realname:
1306 title = self.bold(realname)
1307 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001308 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001309 cl.__dict__[realname] is object):
1310 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001311 title = self.bold(name) + ' = ' + realname
Tim Peters4bcfa312001-09-20 06:08:24 +00001312 if inspect.isfunction(object):
Guido van Rossum2e65f892007-02-28 22:03:49 +00001313 args, varargs, varkw, defaults, kwonlyargs, kwdefaults, ann = \
1314 inspect.getfullargspec(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001315 argspec = inspect.formatargspec(
Guido van Rossum2e65f892007-02-28 22:03:49 +00001316 args, varargs, varkw, defaults, kwonlyargs, kwdefaults, ann,
1317 formatvalue=self.formatvalue,
1318 formatannotation=inspect.formatannotationrelativeto(object))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001319 if realname == '<lambda>':
Georg Brandl501dd0d2006-02-17 09:45:40 +00001320 title = self.bold(name) + ' lambda '
Guido van Rossum2e65f892007-02-28 22:03:49 +00001321 # XXX lambda's won't usually have func_annotations['return']
1322 # since the syntax doesn't support but it is possible.
1323 # So removing parentheses isn't truly safe.
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001324 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +00001325 else:
1326 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001327 decl = title + argspec + note
1328
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001329 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001330 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001331 else:
1332 doc = getdoc(object) or ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001333 return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001334
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001335 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001336 results = []
1337 push = results.append
1338
1339 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001340 push(self.bold(name))
1341 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001342 doc = getdoc(value) or ''
1343 if doc:
1344 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001345 push('\n')
1346 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001347
1348 def docproperty(self, object, name=None, mod=None, cl=None):
1349 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001350 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001351
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001352 def docdata(self, object, name=None, mod=None, cl=None):
1353 """Produce text documentation for a data descriptor."""
1354 return self._docdescriptor(name, object, mod)
1355
Georg Brandl8b813db2005-10-01 16:32:31 +00001356 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001357 """Produce text documentation for a data object."""
1358 repr = self.repr(object)
1359 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001360 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001361 chop = maxlen - len(line)
1362 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001363 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001364 if doc is not None:
1365 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001366 return line
1367
Georg Brandld80d5f42010-12-03 07:47:22 +00001368class _PlainTextDoc(TextDoc):
1369 """Subclass of TextDoc which overrides string styling"""
1370 def bold(self, text):
1371 return text
1372
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001373# --------------------------------------------------------- user interfaces
1374
1375def pager(text):
1376 """The first time this is called, determine what kind of pager to use."""
1377 global pager
1378 pager = getpager()
1379 pager(text)
1380
1381def getpager():
1382 """Decide what method to use for paging through text."""
Guido van Rossuma01a8b62007-05-27 09:20:14 +00001383 if not hasattr(sys.stdout, "isatty"):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001384 return plainpager
1385 if not sys.stdin.isatty() or not sys.stdout.isatty():
1386 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001387 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001388 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001389 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001390 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001391 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001392 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001393 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001394 if os.environ.get('TERM') in ('dumb', 'emacs'):
1395 return plainpager
Jesus Cea4791a242012-10-05 03:15:39 +02001396 if sys.platform == 'win32':
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001397 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001398 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001399 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001400
1401 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001402 (fd, filename) = tempfile.mkstemp()
1403 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001404 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001405 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001406 return lambda text: pipepager(text, 'more')
1407 else:
1408 return ttypager
1409 finally:
1410 os.unlink(filename)
1411
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001412def plain(text):
1413 """Remove boldface formatting from text."""
1414 return re.sub('.\b', '', text)
1415
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001416def pipepager(text, cmd):
1417 """Page through text by feeding it to another program."""
1418 pipe = os.popen(cmd, 'w')
1419 try:
1420 pipe.write(text)
1421 pipe.close()
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001422 except OSError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001423 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001424
1425def tempfilepager(text, cmd):
1426 """Page through text by invoking a program on a temporary file."""
1427 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001428 filename = tempfile.mktemp()
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +01001429 with open(filename, 'w') as file:
1430 file.write(text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001431 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001432 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001433 finally:
1434 os.unlink(filename)
1435
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001436def ttypager(text):
1437 """Page through text on a text terminal."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001438 lines = plain(text).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001439 try:
1440 import tty
1441 fd = sys.stdin.fileno()
1442 old = tty.tcgetattr(fd)
1443 tty.setcbreak(fd)
1444 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001445 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001446 tty = None
1447 getchar = lambda: sys.stdin.readline()[:-1][:1]
1448
1449 try:
1450 r = inc = os.environ.get('LINES', 25) - 1
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001451 sys.stdout.write('\n'.join(lines[:inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001452 while lines[r:]:
1453 sys.stdout.write('-- more --')
1454 sys.stdout.flush()
1455 c = getchar()
1456
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001457 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001458 sys.stdout.write('\r \r')
1459 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001460 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001461 sys.stdout.write('\r \r' + lines[r] + '\n')
1462 r = r + 1
1463 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001464 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001465 r = r - inc - inc
1466 if r < 0: r = 0
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001467 sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001468 r = r + inc
1469
1470 finally:
1471 if tty:
1472 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1473
1474def plainpager(text):
1475 """Simply print unformatted text. This is the ultimate fallback."""
1476 sys.stdout.write(plain(text))
1477
1478def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001479 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001480 if inspect.ismodule(thing):
1481 if thing.__name__ in sys.builtin_module_names:
1482 return 'built-in module ' + thing.__name__
1483 if hasattr(thing, '__path__'):
1484 return 'package ' + thing.__name__
1485 else:
1486 return 'module ' + thing.__name__
1487 if inspect.isbuiltin(thing):
1488 return 'built-in function ' + thing.__name__
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001489 if inspect.isgetsetdescriptor(thing):
1490 return 'getset descriptor %s.%s.%s' % (
1491 thing.__objclass__.__module__, thing.__objclass__.__name__,
1492 thing.__name__)
1493 if inspect.ismemberdescriptor(thing):
1494 return 'member descriptor %s.%s.%s' % (
1495 thing.__objclass__.__module__, thing.__objclass__.__name__,
1496 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001497 if inspect.isclass(thing):
1498 return 'class ' + thing.__name__
1499 if inspect.isfunction(thing):
1500 return 'function ' + thing.__name__
1501 if inspect.ismethod(thing):
1502 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001503 return type(thing).__name__
1504
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001505def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001506 """Locate an object by name or dotted path, importing as necessary."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001507 parts = [part for part in path.split('.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001508 module, n = None, 0
1509 while n < len(parts):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001510 nextmodule = safeimport('.'.join(parts[:n+1]), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001511 if nextmodule: module, n = nextmodule, n + 1
1512 else: break
1513 if module:
1514 object = module
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001515 else:
Éric Araujoe64e51b2011-07-29 17:03:55 +02001516 object = builtins
1517 for part in parts[n:]:
1518 try:
1519 object = getattr(object, part)
1520 except AttributeError:
1521 return None
1522 return object
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001523
1524# --------------------------------------- interactive interpreter interface
1525
1526text = TextDoc()
Georg Brandld80d5f42010-12-03 07:47:22 +00001527plaintext = _PlainTextDoc()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001528html = HTMLDoc()
1529
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001530def resolve(thing, forceload=0):
1531 """Given an object or a path to an object, get the object and its name."""
1532 if isinstance(thing, str):
1533 object = locate(thing, forceload)
1534 if not object:
Collin Winterce36ad82007-08-30 01:19:48 +00001535 raise ImportError('no Python documentation found for %r' % thing)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001536 return object, thing
1537 else:
R David Murrayc43125a2012-04-23 13:23:57 -04001538 name = getattr(thing, '__name__', None)
1539 return thing, name if isinstance(name, str) else None
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001540
Georg Brandld80d5f42010-12-03 07:47:22 +00001541def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
1542 renderer=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001543 """Render text documentation, given an object or a path to an object."""
Georg Brandld80d5f42010-12-03 07:47:22 +00001544 if renderer is None:
1545 renderer = text
Guido van Rossumd8faa362007-04-27 19:54:29 +00001546 object, name = resolve(thing, forceload)
1547 desc = describe(object)
1548 module = inspect.getmodule(object)
1549 if name and '.' in name:
1550 desc += ' in ' + name[:name.rfind('.')]
1551 elif module and module is not object:
1552 desc += ' in module ' + module.__name__
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001553
1554 if not (inspect.ismodule(object) or
Guido van Rossumd8faa362007-04-27 19:54:29 +00001555 inspect.isclass(object) or
1556 inspect.isroutine(object) or
1557 inspect.isgetsetdescriptor(object) or
1558 inspect.ismemberdescriptor(object) or
1559 isinstance(object, property)):
1560 # If the passed object is a piece of data or an instance,
1561 # document its available methods instead of its value.
1562 object = type(object)
1563 desc += ' object'
Georg Brandld80d5f42010-12-03 07:47:22 +00001564 return title % desc + '\n\n' + renderer.document(object, name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001565
Georg Brandld80d5f42010-12-03 07:47:22 +00001566def doc(thing, title='Python Library Documentation: %s', forceload=0,
1567 output=None):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001568 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001569 try:
Georg Brandld80d5f42010-12-03 07:47:22 +00001570 if output is None:
1571 pager(render_doc(thing, title, forceload))
1572 else:
1573 output.write(render_doc(thing, title, forceload, plaintext))
Guido van Rossumb940e112007-01-10 16:19:56 +00001574 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001575 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001576
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001577def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001578 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001579 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001580 object, name = resolve(thing, forceload)
1581 page = html.page(describe(object), html.document(object, name))
Georg Brandl388faac2009-04-10 08:31:48 +00001582 file = open(name + '.html', 'w', encoding='utf-8')
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001583 file.write(page)
1584 file.close()
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001585 print('wrote', name + '.html')
Guido van Rossumb940e112007-01-10 16:19:56 +00001586 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001587 print(value)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001588
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001589def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001590 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001591 if done is None: done = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001592 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1593 writedoc(modname)
1594 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001595
1596class Helper:
Georg Brandl6b38daa2008-06-01 21:05:17 +00001597
1598 # These dictionaries map a topic name to either an alias, or a tuple
1599 # (label, seealso-items). The "label" is the label of the corresponding
1600 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl5617db82009-04-27 16:28:57 +00001601 # in pydoc_data/topics.py.
Georg Brandl6b38daa2008-06-01 21:05:17 +00001602 #
1603 # CAUTION: if you change one of these dictionaries, be sure to adapt the
1604 # list of needed labels in Doc/tools/sphinxext/pyspecific.py and
Georg Brandl5617db82009-04-27 16:28:57 +00001605 # regenerate the pydoc_data/topics.py file by running
Georg Brandl6b38daa2008-06-01 21:05:17 +00001606 # make pydoc-topics
1607 # in Doc/ and copying the output file into the Lib/ directory.
1608
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001609 keywords = {
Ezio Melottib185a042011-04-28 07:42:55 +03001610 'False': '',
1611 'None': '',
1612 'True': '',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001613 'and': 'BOOLEAN',
Guido van Rossumd8faa362007-04-27 19:54:29 +00001614 'as': 'with',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001615 'assert': ('assert', ''),
1616 'break': ('break', 'while for'),
1617 'class': ('class', 'CLASSES SPECIALMETHODS'),
1618 'continue': ('continue', 'while for'),
1619 'def': ('function', ''),
1620 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001621 'elif': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001622 'else': ('else', 'while for'),
Georg Brandl0d855392008-08-30 19:53:05 +00001623 'except': 'try',
1624 'finally': 'try',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001625 'for': ('for', 'break continue while'),
Georg Brandl0d855392008-08-30 19:53:05 +00001626 'from': 'import',
Georg Brandl74abf6f2010-11-20 19:54:36 +00001627 'global': ('global', 'nonlocal NAMESPACES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001628 'if': ('if', 'TRUTHVALUE'),
1629 'import': ('import', 'MODULES'),
Georg Brandl395ed242009-09-04 08:07:32 +00001630 'in': ('in', 'SEQUENCEMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001631 'is': 'COMPARISON',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001632 'lambda': ('lambda', 'FUNCTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001633 'nonlocal': ('nonlocal', 'global NAMESPACES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001634 'not': 'BOOLEAN',
1635 'or': 'BOOLEAN',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001636 'pass': ('pass', ''),
1637 'raise': ('raise', 'EXCEPTIONS'),
1638 'return': ('return', 'FUNCTIONS'),
1639 'try': ('try', 'EXCEPTIONS'),
1640 'while': ('while', 'break continue if TRUTHVALUE'),
1641 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1642 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001643 }
Georg Brandldb7b6b92009-01-01 15:53:14 +00001644 # Either add symbols to this dictionary or to the symbols dictionary
1645 # directly: Whichever is easier. They are merged later.
1646 _symbols_inverse = {
1647 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'),
1648 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1649 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1650 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1651 'UNARY' : ('-', '~'),
1652 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1653 '^=', '<<=', '>>=', '**=', '//='),
1654 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1655 'COMPLEX' : ('j', 'J')
1656 }
1657 symbols = {
1658 '%': 'OPERATORS FORMATTING',
1659 '**': 'POWER',
1660 ',': 'TUPLES LISTS FUNCTIONS',
1661 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1662 '...': 'ELLIPSIS',
1663 ':': 'SLICINGS DICTIONARYLITERALS',
1664 '@': 'def class',
1665 '\\': 'STRINGS',
1666 '_': 'PRIVATENAMES',
1667 '__': 'PRIVATENAMES SPECIALMETHODS',
1668 '`': 'BACKQUOTES',
1669 '(': 'TUPLES FUNCTIONS CALLS',
1670 ')': 'TUPLES FUNCTIONS CALLS',
1671 '[': 'LISTS SUBSCRIPTS SLICINGS',
1672 ']': 'LISTS SUBSCRIPTS SLICINGS'
1673 }
1674 for topic, symbols_ in _symbols_inverse.items():
1675 for symbol in symbols_:
1676 topics = symbols.get(symbol, topic)
1677 if topic not in topics:
1678 topics = topics + ' ' + topic
1679 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001680
1681 topics = {
Georg Brandl6b38daa2008-06-01 21:05:17 +00001682 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1683 'FUNCTIONS CLASSES MODULES FILES inspect'),
1684 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS '
1685 'FORMATTING TYPES'),
1686 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1687 'FORMATTING': ('formatstrings', 'OPERATORS'),
1688 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1689 'FORMATTING TYPES'),
1690 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1691 'INTEGER': ('integers', 'int range'),
1692 'FLOAT': ('floating', 'float math'),
1693 'COMPLEX': ('imaginary', 'complex cmath'),
1694 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING range LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001695 'MAPPINGS': 'DICTIONARIES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001696 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1697 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1698 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1699 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001700 'FRAMEOBJECTS': 'TYPES',
1701 'TRACEBACKS': 'TYPES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001702 'NONE': ('bltin-null-object', ''),
1703 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
1704 'FILES': ('bltin-file-objects', ''),
1705 'SPECIALATTRIBUTES': ('specialattrs', ''),
1706 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1707 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001708 'PACKAGES': 'import',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001709 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1710 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1711 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1712 'LISTS DICTIONARIES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001713 'OPERATORS': 'EXPRESSIONS',
1714 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001715 'OBJECTS': ('objects', 'TYPES'),
1716 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
Georg Brandl395ed242009-09-04 08:07:32 +00001717 'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS '
1718 'NUMBERMETHODS CLASSES'),
Mark Dickinsona56c4672009-01-27 18:17:45 +00001719 'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001720 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1721 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001722 'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS '
Georg Brandl6b38daa2008-06-01 21:05:17 +00001723 'SPECIALMETHODS'),
1724 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1725 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1726 'SPECIALMETHODS'),
1727 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001728 'NAMESPACES': ('naming', 'global nonlocal ASSIGNMENT DELETION DYNAMICFEATURES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001729 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001730 'SCOPING': 'NAMESPACES',
1731 'FRAMES': 'NAMESPACES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001732 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1733 'CONVERSIONS': ('conversions', ''),
1734 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1735 'SPECIALIDENTIFIERS': ('id-classes', ''),
1736 'PRIVATENAMES': ('atom-identifiers', ''),
1737 'LITERALS': ('atom-literals', 'STRINGS NUMBERS TUPLELITERALS '
1738 'LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001739 'TUPLES': 'SEQUENCES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001740 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1741 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1742 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1743 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1744 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1745 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001746 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'),
1747 'SLICINGS': ('slicings', 'SEQUENCEMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001748 'CALLS': ('calls', 'EXPRESSIONS'),
1749 'POWER': ('power', 'EXPRESSIONS'),
1750 'UNARY': ('unary', 'EXPRESSIONS'),
1751 'BINARY': ('binary', 'EXPRESSIONS'),
1752 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1753 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1754 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1755 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001756 'ASSERTION': 'assert',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001757 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1758 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001759 'DELETION': 'del',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001760 'RETURNING': 'return',
1761 'IMPORTING': 'import',
1762 'CONDITIONAL': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001763 'LOOPING': ('compound', 'for while break continue'),
1764 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1765 'DEBUGGING': ('debugger', 'pdb'),
1766 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001767 }
1768
Georg Brandl78aa3962010-07-31 21:51:48 +00001769 def __init__(self, input=None, output=None):
1770 self._input = input
1771 self._output = output
1772
Georg Brandl76ae3972010-08-01 06:32:55 +00001773 input = property(lambda self: self._input or sys.stdin)
1774 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001775
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001776 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001777 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001778 self()
1779 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001780 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001781
Alexander Belopolsky2e733c92010-07-04 17:00:20 +00001782 _GoInteractive = object()
1783 def __call__(self, request=_GoInteractive):
1784 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001785 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001786 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001787 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001788 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001789 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001790You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001791If you want to ask for help on a particular object directly from the
1792interpreter, you can type "help(object)". Executing "help('string')"
1793has the same effect as typing a particular string at the help> prompt.
1794''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001795
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001796 def interact(self):
1797 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001798 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001799 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001800 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001801 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001802 except (KeyboardInterrupt, EOFError):
1803 break
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001804 request = replace(request, '"', '', "'", '').strip()
1805 if request.lower() in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001806 self.help(request)
1807
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001808 def getline(self, prompt):
Guido van Rossum7c086c02008-01-02 03:52:38 +00001809 """Read one line, using input() when appropriate."""
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001810 if self.input is sys.stdin:
Guido van Rossum7c086c02008-01-02 03:52:38 +00001811 return input(prompt)
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001812 else:
1813 self.output.write(prompt)
1814 self.output.flush()
1815 return self.input.readline()
1816
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001817 def help(self, request):
1818 if type(request) is type(''):
R. David Murray1f1b9d32009-05-27 20:56:59 +00001819 request = request.strip()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001820 if request == 'help': self.intro()
1821 elif request == 'keywords': self.listkeywords()
Georg Brandldb7b6b92009-01-01 15:53:14 +00001822 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001823 elif request == 'topics': self.listtopics()
1824 elif request == 'modules': self.listmodules()
1825 elif request[:8] == 'modules ':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001826 self.listmodules(request.split()[1])
Georg Brandldb7b6b92009-01-01 15:53:14 +00001827 elif request in self.symbols: self.showsymbol(request)
Ezio Melottib185a042011-04-28 07:42:55 +03001828 elif request in ['True', 'False', 'None']:
1829 # special case these keywords since they are objects too
1830 doc(eval(request), 'Help on %s:')
Raymond Hettinger54f02222002-06-01 14:18:47 +00001831 elif request in self.keywords: self.showtopic(request)
1832 elif request in self.topics: self.showtopic(request)
Georg Brandld80d5f42010-12-03 07:47:22 +00001833 elif request: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001834 elif isinstance(request, Helper): self()
Georg Brandld80d5f42010-12-03 07:47:22 +00001835 else: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001836 self.output.write('\n')
1837
1838 def intro(self):
1839 self.output.write('''
Georg Brandlc645c6a2012-06-24 17:24:26 +02001840Welcome to Python %s! This is the interactive help utility.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001841
1842If this is your first time using Python, you should definitely check out
R David Murrayde0f6292012-03-31 12:06:35 -04001843the tutorial on the Internet at http://docs.python.org/%s/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001844
1845Enter the name of any module, keyword, or topic to get help on writing
1846Python programs and using Python modules. To quit this help utility and
1847return to the interpreter, just type "quit".
1848
Terry Jan Reedy34200572013-02-11 02:23:13 -05001849To get a list of available modules, keywords, symbols, or topics, type
1850"modules", "keywords", "symbols", or "topics". Each module also comes
1851with a one-line summary of what it does; to list the modules whose name
1852or summary contain a given string such as "spam", type "modules spam".
R David Murrayde0f6292012-03-31 12:06:35 -04001853''' % tuple([sys.version[:3]]*2))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001854
1855 def list(self, items, columns=4, width=80):
Guido van Rossum486364b2007-06-30 05:01:58 +00001856 items = list(sorted(items))
1857 colw = width // columns
1858 rows = (len(items) + columns - 1) // columns
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001859 for row in range(rows):
1860 for col in range(columns):
1861 i = col * rows + row
1862 if i < len(items):
1863 self.output.write(items[i])
1864 if col < columns - 1:
Guido van Rossum486364b2007-06-30 05:01:58 +00001865 self.output.write(' ' + ' ' * (colw - 1 - len(items[i])))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001866 self.output.write('\n')
1867
1868 def listkeywords(self):
1869 self.output.write('''
1870Here is a list of the Python keywords. Enter any keyword to get more help.
1871
1872''')
1873 self.list(self.keywords.keys())
1874
Georg Brandldb7b6b92009-01-01 15:53:14 +00001875 def listsymbols(self):
1876 self.output.write('''
1877Here is a list of the punctuation symbols which Python assigns special meaning
1878to. Enter any symbol to get more help.
1879
1880''')
1881 self.list(self.symbols.keys())
1882
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001883 def listtopics(self):
1884 self.output.write('''
1885Here is a list of available topics. Enter any topic name to get more help.
1886
1887''')
1888 self.list(self.topics.keys())
1889
Georg Brandldb7b6b92009-01-01 15:53:14 +00001890 def showtopic(self, topic, more_xrefs=''):
Georg Brandl6b38daa2008-06-01 21:05:17 +00001891 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001892 import pydoc_data.topics
Georg Brandl6b38daa2008-06-01 21:05:17 +00001893 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001894 self.output.write('''
Georg Brandl6b38daa2008-06-01 21:05:17 +00001895Sorry, topic and keyword documentation is not available because the
Georg Brandl5617db82009-04-27 16:28:57 +00001896module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001897''')
1898 return
1899 target = self.topics.get(topic, self.keywords.get(topic))
1900 if not target:
1901 self.output.write('no documentation found for %s\n' % repr(topic))
1902 return
1903 if type(target) is type(''):
Georg Brandldb7b6b92009-01-01 15:53:14 +00001904 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001905
Georg Brandl6b38daa2008-06-01 21:05:17 +00001906 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001907 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001908 doc = pydoc_data.topics.topics[label]
Georg Brandl6b38daa2008-06-01 21:05:17 +00001909 except KeyError:
1910 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001911 return
Georg Brandl6b38daa2008-06-01 21:05:17 +00001912 pager(doc.strip() + '\n')
Georg Brandldb7b6b92009-01-01 15:53:14 +00001913 if more_xrefs:
1914 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001915 if xrefs:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001916 import formatter
Guido van Rossum34d19282007-08-09 01:03:29 +00001917 buffer = io.StringIO()
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001918 formatter.DumbWriter(buffer).send_flowing_data(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001919 'Related help topics: ' + ', '.join(xrefs.split()) + '\n')
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001920 self.output.write('\n%s\n' % buffer.getvalue())
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001921
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001922 def _gettopic(self, topic, more_xrefs=''):
1923 """Return unbuffered tuple of (topic, xrefs).
1924
Georg Brandld2f38572011-01-30 08:37:19 +00001925 If an error occurs here, the exception is caught and displayed by
1926 the url handler.
1927
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001928 This function duplicates the showtopic method but returns its
1929 result directly so it can be formatted for display in an html page.
1930 """
1931 try:
1932 import pydoc_data.topics
1933 except ImportError:
1934 return('''
1935Sorry, topic and keyword documentation is not available because the
1936module "pydoc_data.topics" could not be found.
1937''' , '')
1938 target = self.topics.get(topic, self.keywords.get(topic))
1939 if not target:
Georg Brandld2f38572011-01-30 08:37:19 +00001940 raise ValueError('could not find topic')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001941 if isinstance(target, str):
1942 return self._gettopic(target, more_xrefs)
1943 label, xrefs = target
Georg Brandld2f38572011-01-30 08:37:19 +00001944 doc = pydoc_data.topics.topics[label]
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001945 if more_xrefs:
1946 xrefs = (xrefs or '') + ' ' + more_xrefs
1947 return doc, xrefs
1948
Georg Brandldb7b6b92009-01-01 15:53:14 +00001949 def showsymbol(self, symbol):
1950 target = self.symbols[symbol]
1951 topic, _, xrefs = target.partition(' ')
1952 self.showtopic(topic, xrefs)
1953
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001954 def listmodules(self, key=''):
1955 if key:
1956 self.output.write('''
Terry Jan Reedy34200572013-02-11 02:23:13 -05001957Here is a list of modules whose name or summary contains '{}'.
1958If there are any, enter a module name to get more help.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001959
Terry Jan Reedy34200572013-02-11 02:23:13 -05001960'''.format(key))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001961 apropos(key)
1962 else:
1963 self.output.write('''
1964Please wait a moment while I gather a list of all available modules...
1965
1966''')
1967 modules = {}
1968 def callback(path, modname, desc, modules=modules):
1969 if modname and modname[-9:] == '.__init__':
1970 modname = modname[:-9] + ' (package)'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001971 if modname.find('.') < 0:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001972 modules[modname] = 1
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001973 def onerror(modname):
1974 callback(None, modname, None)
1975 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001976 self.list(modules.keys())
1977 self.output.write('''
1978Enter any module name to get more help. Or, type "modules spam" to search
Terry Jan Reedy34200572013-02-11 02:23:13 -05001979for modules whose name or summary contain the string "spam".
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001980''')
1981
Georg Brandl78aa3962010-07-31 21:51:48 +00001982help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001983
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001984class Scanner:
1985 """A generic tree iterator."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001986 def __init__(self, roots, children, descendp):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001987 self.roots = roots[:]
1988 self.state = []
1989 self.children = children
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001990 self.descendp = descendp
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001991
1992 def next(self):
1993 if not self.state:
1994 if not self.roots:
1995 return None
1996 root = self.roots.pop(0)
1997 self.state = [(root, self.children(root))]
1998 node, children = self.state[-1]
1999 if not children:
2000 self.state.pop()
2001 return self.next()
2002 child = children.pop(0)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002003 if self.descendp(child):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002004 self.state.append((child, self.children(child)))
2005 return child
2006
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002007
2008class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002009 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002010
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002011 def run(self, callback, key=None, completer=None, onerror=None):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002012 if key: key = key.lower()
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002013 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002014 seen = {}
2015
2016 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002017 if modname != '__main__':
2018 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00002019 if key is None:
2020 callback(None, modname, '')
2021 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002022 name = __import__(modname).__doc__ or ''
2023 desc = name.split('\n')[0]
2024 name = modname + ' - ' + desc
2025 if name.lower().find(key) >= 0:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002026 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002027
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002028 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002029 if self.quit:
2030 break
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002031
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002032 if key is None:
2033 callback(None, modname, '')
2034 else:
Georg Brandl126c8792009-04-05 15:05:48 +00002035 try:
2036 loader = importer.find_module(modname)
2037 except SyntaxError:
2038 # raised by tests for bad coding cookies or BOM
2039 continue
2040 if hasattr(loader, 'get_source'):
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002041 try:
2042 source = loader.get_source(modname)
Nick Coghlan2824cb52012-07-15 22:12:14 +10002043 except Exception:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002044 if onerror:
2045 onerror(modname)
2046 continue
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002047 desc = source_synopsis(io.StringIO(source)) or ''
Georg Brandl126c8792009-04-05 15:05:48 +00002048 if hasattr(loader, 'get_filename'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002049 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002050 else:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002051 path = None
2052 else:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002053 try:
2054 module = loader.load_module(modname)
2055 except ImportError:
2056 if onerror:
2057 onerror(modname)
2058 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002059 desc = (module.__doc__ or '').splitlines()[0]
2060 path = getattr(module,'__file__',None)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002061 name = modname + ' - ' + desc
2062 if name.lower().find(key) >= 0:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002063 callback(path, modname, desc)
2064
2065 if completer:
2066 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002067
2068def apropos(key):
2069 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002070 def callback(path, modname, desc):
2071 if modname[-9:] == '.__init__':
2072 modname = modname[:-9] + ' (package)'
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002073 print(modname, desc and '- ' + desc)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002074 def onerror(modname):
2075 pass
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002076 with warnings.catch_warnings():
2077 warnings.filterwarnings('ignore') # ignore problems during import
2078 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002079
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002080# --------------------------------------- enhanced Web browser interface
2081
2082def _start_server(urlhandler, port):
2083 """Start an HTTP server thread on a specific port.
2084
2085 Start an HTML/text server thread, so HTML or text documents can be
2086 browsed dynamically and interactively with a Web browser. Example use:
2087
2088 >>> import time
2089 >>> import pydoc
2090
2091 Define a URL handler. To determine what the client is asking
2092 for, check the URL and content_type.
2093
2094 Then get or generate some text or HTML code and return it.
2095
2096 >>> def my_url_handler(url, content_type):
2097 ... text = 'the URL sent was: (%s, %s)' % (url, content_type)
2098 ... return text
2099
2100 Start server thread on port 0.
2101 If you use port 0, the server will pick a random port number.
2102 You can then use serverthread.port to get the port number.
2103
2104 >>> port = 0
2105 >>> serverthread = pydoc._start_server(my_url_handler, port)
2106
2107 Check that the server is really started. If it is, open browser
2108 and get first page. Use serverthread.url as the starting page.
2109
2110 >>> if serverthread.serving:
2111 ... import webbrowser
2112
2113 The next two lines are commented out so a browser doesn't open if
2114 doctest is run on this module.
2115
2116 #... webbrowser.open(serverthread.url)
2117 #True
2118
2119 Let the server do its thing. We just need to monitor its status.
2120 Use time.sleep so the loop doesn't hog the CPU.
2121
2122 >>> starttime = time.time()
2123 >>> timeout = 1 #seconds
2124
2125 This is a short timeout for testing purposes.
2126
2127 >>> while serverthread.serving:
2128 ... time.sleep(.01)
2129 ... if serverthread.serving and time.time() - starttime > timeout:
2130 ... serverthread.stop()
2131 ... break
2132
2133 Print any errors that may have occurred.
2134
2135 >>> print(serverthread.error)
2136 None
2137 """
2138 import http.server
2139 import email.message
2140 import select
2141 import threading
2142
2143 class DocHandler(http.server.BaseHTTPRequestHandler):
2144
2145 def do_GET(self):
2146 """Process a request from an HTML browser.
2147
2148 The URL received is in self.path.
2149 Get an HTML page from self.urlhandler and send it.
2150 """
2151 if self.path.endswith('.css'):
2152 content_type = 'text/css'
2153 else:
2154 content_type = 'text/html'
2155 self.send_response(200)
Georg Brandld2f38572011-01-30 08:37:19 +00002156 self.send_header('Content-Type', '%s; charset=UTF-8' % content_type)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002157 self.end_headers()
2158 self.wfile.write(self.urlhandler(
2159 self.path, content_type).encode('utf-8'))
2160
2161 def log_message(self, *args):
2162 # Don't log messages.
2163 pass
2164
2165 class DocServer(http.server.HTTPServer):
2166
2167 def __init__(self, port, callback):
2168 self.host = (sys.platform == 'mac') and '127.0.0.1' or 'localhost'
2169 self.address = ('', port)
2170 self.callback = callback
2171 self.base.__init__(self, self.address, self.handler)
2172 self.quit = False
2173
2174 def serve_until_quit(self):
2175 while not self.quit:
2176 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2177 if rd:
2178 self.handle_request()
Victor Stinnera3abd1d2011-01-03 16:12:39 +00002179 self.server_close()
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002180
2181 def server_activate(self):
2182 self.base.server_activate(self)
2183 if self.callback:
2184 self.callback(self)
2185
2186 class ServerThread(threading.Thread):
2187
2188 def __init__(self, urlhandler, port):
2189 self.urlhandler = urlhandler
2190 self.port = int(port)
2191 threading.Thread.__init__(self)
2192 self.serving = False
2193 self.error = None
2194
2195 def run(self):
2196 """Start the server."""
2197 try:
2198 DocServer.base = http.server.HTTPServer
2199 DocServer.handler = DocHandler
2200 DocHandler.MessageClass = email.message.Message
2201 DocHandler.urlhandler = staticmethod(self.urlhandler)
2202 docsvr = DocServer(self.port, self.ready)
2203 self.docserver = docsvr
2204 docsvr.serve_until_quit()
2205 except Exception as e:
2206 self.error = e
2207
2208 def ready(self, server):
2209 self.serving = True
2210 self.host = server.host
2211 self.port = server.server_port
2212 self.url = 'http://%s:%d/' % (self.host, self.port)
2213
2214 def stop(self):
2215 """Stop the server and this thread nicely"""
2216 self.docserver.quit = True
2217 self.serving = False
2218 self.url = None
2219
2220 thread = ServerThread(urlhandler, port)
2221 thread.start()
2222 # Wait until thread.serving is True to make sure we are
2223 # really up before returning.
2224 while not thread.error and not thread.serving:
2225 time.sleep(.01)
2226 return thread
2227
2228
2229def _url_handler(url, content_type="text/html"):
2230 """The pydoc url handler for use with the pydoc server.
2231
2232 If the content_type is 'text/css', the _pydoc.css style
2233 sheet is read and returned if it exits.
2234
2235 If the content_type is 'text/html', then the result of
2236 get_html_page(url) is returned.
2237 """
2238 class _HTMLDoc(HTMLDoc):
2239
2240 def page(self, title, contents):
2241 """Format an HTML page."""
2242 css_path = "pydoc_data/_pydoc.css"
2243 css_link = (
2244 '<link rel="stylesheet" type="text/css" href="%s">' %
2245 css_path)
2246 return '''\
2247<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Georg Brandld2f38572011-01-30 08:37:19 +00002248<html><head><title>Pydoc: %s</title>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002249<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Georg Brandld2f38572011-01-30 08:37:19 +00002250%s</head><body bgcolor="#f0f0f8">%s<div style="clear:both;padding-top:.5em;">%s</div>
2251</body></html>''' % (title, css_link, html_navbar(), contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002252
2253 def filelink(self, url, path):
2254 return '<a href="getfile?key=%s">%s</a>' % (url, path)
2255
2256
2257 html = _HTMLDoc()
2258
2259 def html_navbar():
Georg Brandld2f38572011-01-30 08:37:19 +00002260 version = html.escape("%s [%s, %s]" % (platform.python_version(),
2261 platform.python_build()[0],
2262 platform.python_compiler()))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002263 return """
2264 <div style='float:left'>
Georg Brandld2f38572011-01-30 08:37:19 +00002265 Python %s<br>%s
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002266 </div>
2267 <div style='float:right'>
2268 <div style='text-align:center'>
2269 <a href="index.html">Module Index</a>
2270 : <a href="topics.html">Topics</a>
2271 : <a href="keywords.html">Keywords</a>
2272 </div>
2273 <div>
Georg Brandld2f38572011-01-30 08:37:19 +00002274 <form action="get" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002275 <input type=text name=key size=15>
2276 <input type=submit value="Get">
Georg Brandld2f38572011-01-30 08:37:19 +00002277 </form>&nbsp;
2278 <form action="search" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002279 <input type=text name=key size=15>
2280 <input type=submit value="Search">
2281 </form>
2282 </div>
2283 </div>
Georg Brandld2f38572011-01-30 08:37:19 +00002284 """ % (version, html.escape(platform.platform(terse=True)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002285
2286 def html_index():
2287 """Module Index page."""
2288
2289 def bltinlink(name):
2290 return '<a href="%s.html">%s</a>' % (name, name)
2291
2292 heading = html.heading(
2293 '<big><big><strong>Index of Modules</strong></big></big>',
2294 '#ffffff', '#7799ee')
2295 names = [name for name in sys.builtin_module_names
2296 if name != '__main__']
2297 contents = html.multicolumn(names, bltinlink)
2298 contents = [heading, '<p>' + html.bigsection(
2299 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2300
2301 seen = {}
2302 for dir in sys.path:
2303 contents.append(html.index(dir, seen))
2304
2305 contents.append(
2306 '<p align=right><font color="#909090" face="helvetica,'
2307 'arial"><strong>pydoc</strong> by Ka-Ping Yee'
2308 '&lt;ping@lfw.org&gt;</font>')
Nick Coghlanecace282010-12-03 16:08:46 +00002309 return 'Index of Modules', ''.join(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002310
2311 def html_search(key):
2312 """Search results page."""
2313 # scan for modules
2314 search_result = []
2315
2316 def callback(path, modname, desc):
2317 if modname[-9:] == '.__init__':
2318 modname = modname[:-9] + ' (package)'
2319 search_result.append((modname, desc and '- ' + desc))
2320
2321 with warnings.catch_warnings():
2322 warnings.filterwarnings('ignore') # ignore problems during import
2323 ModuleScanner().run(callback, key)
2324
2325 # format page
2326 def bltinlink(name):
2327 return '<a href="%s.html">%s</a>' % (name, name)
2328
2329 results = []
2330 heading = html.heading(
2331 '<big><big><strong>Search Results</strong></big></big>',
2332 '#ffffff', '#7799ee')
2333 for name, desc in search_result:
2334 results.append(bltinlink(name) + desc)
2335 contents = heading + html.bigsection(
2336 'key = %s' % key, '#ffffff', '#ee77aa', '<br>'.join(results))
Nick Coghlanecace282010-12-03 16:08:46 +00002337 return 'Search Results', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002338
2339 def html_getfile(path):
2340 """Get and display a source file listing safely."""
Nick Coghlanecace282010-12-03 16:08:46 +00002341 path = path.replace('%20', ' ')
Victor Stinner91e08772011-07-05 14:30:41 +02002342 with tokenize.open(path) as fp:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002343 lines = html.escape(fp.read())
2344 body = '<pre>%s</pre>' % lines
2345 heading = html.heading(
2346 '<big><big><strong>File Listing</strong></big></big>',
2347 '#ffffff', '#7799ee')
2348 contents = heading + html.bigsection(
2349 'File: %s' % path, '#ffffff', '#ee77aa', body)
Nick Coghlanecace282010-12-03 16:08:46 +00002350 return 'getfile %s' % path, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002351
2352 def html_topics():
2353 """Index of topic texts available."""
2354
2355 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002356 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002357
2358 heading = html.heading(
2359 '<big><big><strong>INDEX</strong></big></big>',
2360 '#ffffff', '#7799ee')
2361 names = sorted(Helper.topics.keys())
2362
2363 contents = html.multicolumn(names, bltinlink)
2364 contents = heading + html.bigsection(
2365 'Topics', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002366 return 'Topics', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002367
2368 def html_keywords():
2369 """Index of keywords."""
2370 heading = html.heading(
2371 '<big><big><strong>INDEX</strong></big></big>',
2372 '#ffffff', '#7799ee')
2373 names = sorted(Helper.keywords.keys())
2374
2375 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002376 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002377
2378 contents = html.multicolumn(names, bltinlink)
2379 contents = heading + html.bigsection(
2380 'Keywords', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002381 return 'Keywords', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002382
2383 def html_topicpage(topic):
2384 """Topic or keyword help page."""
2385 buf = io.StringIO()
2386 htmlhelp = Helper(buf, buf)
2387 contents, xrefs = htmlhelp._gettopic(topic)
2388 if topic in htmlhelp.keywords:
2389 title = 'KEYWORD'
2390 else:
2391 title = 'TOPIC'
2392 heading = html.heading(
2393 '<big><big><strong>%s</strong></big></big>' % title,
2394 '#ffffff', '#7799ee')
Georg Brandld2f38572011-01-30 08:37:19 +00002395 contents = '<pre>%s</pre>' % html.markup(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002396 contents = html.bigsection(topic , '#ffffff','#ee77aa', contents)
Georg Brandld2f38572011-01-30 08:37:19 +00002397 if xrefs:
2398 xrefs = sorted(xrefs.split())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002399
Georg Brandld2f38572011-01-30 08:37:19 +00002400 def bltinlink(name):
2401 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002402
Georg Brandld2f38572011-01-30 08:37:19 +00002403 xrefs = html.multicolumn(xrefs, bltinlink)
2404 xrefs = html.section('Related help topics: ',
2405 '#ffffff', '#ee77aa', xrefs)
Nick Coghlanecace282010-12-03 16:08:46 +00002406 return ('%s %s' % (title, topic),
2407 ''.join((heading, contents, xrefs)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002408
Georg Brandld2f38572011-01-30 08:37:19 +00002409 def html_getobj(url):
2410 obj = locate(url, forceload=1)
2411 if obj is None and url != 'None':
2412 raise ValueError('could not find object')
2413 title = describe(obj)
2414 content = html.document(obj, url)
2415 return title, content
2416
2417 def html_error(url, exc):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002418 heading = html.heading(
2419 '<big><big><strong>Error</strong></big></big>',
Georg Brandld2f38572011-01-30 08:37:19 +00002420 '#ffffff', '#7799ee')
2421 contents = '<br>'.join(html.escape(line) for line in
2422 format_exception_only(type(exc), exc))
2423 contents = heading + html.bigsection(url, '#ffffff', '#bb0000',
2424 contents)
2425 return "Error - %s" % url, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002426
2427 def get_html_page(url):
2428 """Generate an HTML page for url."""
Georg Brandld2f38572011-01-30 08:37:19 +00002429 complete_url = url
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002430 if url.endswith('.html'):
2431 url = url[:-5]
Georg Brandld2f38572011-01-30 08:37:19 +00002432 try:
2433 if url in ("", "index"):
2434 title, content = html_index()
2435 elif url == "topics":
2436 title, content = html_topics()
2437 elif url == "keywords":
2438 title, content = html_keywords()
2439 elif '=' in url:
2440 op, _, url = url.partition('=')
2441 if op == "search?key":
2442 title, content = html_search(url)
2443 elif op == "getfile?key":
2444 title, content = html_getfile(url)
2445 elif op == "topic?key":
2446 # try topics first, then objects.
2447 try:
2448 title, content = html_topicpage(url)
2449 except ValueError:
2450 title, content = html_getobj(url)
2451 elif op == "get?key":
2452 # try objects first, then topics.
2453 if url in ("", "index"):
2454 title, content = html_index()
2455 else:
2456 try:
2457 title, content = html_getobj(url)
2458 except ValueError:
2459 title, content = html_topicpage(url)
2460 else:
2461 raise ValueError('bad pydoc url')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002462 else:
Georg Brandld2f38572011-01-30 08:37:19 +00002463 title, content = html_getobj(url)
2464 except Exception as exc:
2465 # Catch any errors and display them in an error page.
2466 title, content = html_error(complete_url, exc)
2467 return html.page(title, content)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002468
2469 if url.startswith('/'):
2470 url = url[1:]
2471 if content_type == 'text/css':
2472 path_here = os.path.dirname(os.path.realpath(__file__))
Georg Brandld2f38572011-01-30 08:37:19 +00002473 css_path = os.path.join(path_here, url)
2474 with open(css_path) as fp:
2475 return ''.join(fp.readlines())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002476 elif content_type == 'text/html':
2477 return get_html_page(url)
Georg Brandld2f38572011-01-30 08:37:19 +00002478 # Errors outside the url handler are caught by the server.
2479 raise TypeError('unknown content type %r for url %s' % (content_type, url))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002480
2481
2482def browse(port=0, *, open_browser=True):
2483 """Start the enhanced pydoc Web server and open a Web browser.
2484
2485 Use port '0' to start the server on an arbitrary port.
2486 Set open_browser to False to suppress opening a browser.
2487 """
2488 import webbrowser
2489 serverthread = _start_server(_url_handler, port)
2490 if serverthread.error:
2491 print(serverthread.error)
2492 return
2493 if serverthread.serving:
2494 server_help_msg = 'Server commands: [b]rowser, [q]uit'
2495 if open_browser:
2496 webbrowser.open(serverthread.url)
2497 try:
2498 print('Server ready at', serverthread.url)
2499 print(server_help_msg)
2500 while serverthread.serving:
2501 cmd = input('server> ')
2502 cmd = cmd.lower()
2503 if cmd == 'q':
2504 break
2505 elif cmd == 'b':
2506 webbrowser.open(serverthread.url)
2507 else:
2508 print(server_help_msg)
2509 except (KeyboardInterrupt, EOFError):
2510 print()
2511 finally:
2512 if serverthread.serving:
2513 serverthread.stop()
2514 print('Server stopped')
2515
2516
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002517# -------------------------------------------------- command-line interface
2518
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002519def ispath(x):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002520 return isinstance(x, str) and x.find(os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002521
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002522def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002523 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002524 import getopt
Guido van Rossum756aa932007-04-07 03:04:01 +00002525 class BadUsage(Exception): pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002526
Nick Coghlan106274b2009-11-15 23:04:33 +00002527 # Scripts don't get the current directory in their path by default
2528 # unless they are run with the '-m' switch
2529 if '' not in sys.path:
2530 scriptdir = os.path.dirname(sys.argv[0])
2531 if scriptdir in sys.path:
2532 sys.path.remove(scriptdir)
2533 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002534
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002535 try:
Victor Stinner383c3fc2011-05-25 01:35:05 +02002536 opts, args = getopt.getopt(sys.argv[1:], 'bk:p:w')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002537 writing = False
2538 start_server = False
2539 open_browser = False
2540 port = None
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002541 for opt, val in opts:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002542 if opt == '-b':
2543 start_server = True
2544 open_browser = True
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002545 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002546 apropos(val)
2547 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002548 if opt == '-p':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002549 start_server = True
2550 port = val
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002551 if opt == '-w':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002552 writing = True
2553
Benjamin Petersonb29614e2012-10-09 11:16:03 -04002554 if start_server:
2555 if port is None:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002556 port = 0
2557 browse(port, open_browser=open_browser)
2558 return
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002559
2560 if not args: raise BadUsage
2561 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002562 if ispath(arg) and not os.path.exists(arg):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002563 print('file %r does not exist' % arg)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002564 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002565 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002566 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002567 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002568 if writing:
2569 if ispath(arg) and os.path.isdir(arg):
2570 writedocs(arg)
2571 else:
2572 writedoc(arg)
2573 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002574 help.help(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +00002575 except ErrorDuringImport as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002576 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002577
2578 except (getopt.error, BadUsage):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002579 cmd = os.path.splitext(os.path.basename(sys.argv[0]))[0]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002580 print("""pydoc - the Python documentation tool
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002581
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002582{cmd} <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002583 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002584 Python keyword, topic, function, module, or package, or a dotted
2585 reference to a class or function within a module or module in a
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002586 package. If <name> contains a '{sep}', it is used as the path to a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002587 Python source file to document. If name is 'keywords', 'topics',
2588 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002589
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002590{cmd} -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002591 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002592
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002593{cmd} -p <port>
2594 Start an HTTP server on the given port on the local machine. Port
2595 number 0 can be used to get an arbitrary unused port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002596
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002597{cmd} -b
2598 Start an HTTP server on an arbitrary unused port and open a Web browser
2599 to interactively browse documentation. The -p option can be used with
2600 the -b option to explicitly specify the server port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002601
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002602{cmd} -w <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002603 Write out the HTML documentation for a module to a file in the current
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002604 directory. If <name> contains a '{sep}', it is treated as a filename; if
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002605 it names a directory, documentation is written for all the contents.
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002606""".format(cmd=cmd, sep=os.sep))
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002607
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002608if __name__ == '__main__':
2609 cli()