blob: cc22d7390a7b26869205ed794075f91d6816fcd4 [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
Ka-Ping Yeedd175342001-02-27 14:43:46 +00004In the Python interpreter, do "from pydoc import help" to provide online
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
Nick Coghlan7bb30b72010-12-03 09:29:11 +000056import inspect
Victor Stinnere6c910e2011-06-30 15:55:43 +020057import io
58import os
Nick Coghlan7bb30b72010-12-03 09:29:11 +000059import pkgutil
60import platform
61import re
Victor Stinnere6c910e2011-06-30 15:55:43 +020062import sys
Nick Coghlan7bb30b72010-12-03 09:29:11 +000063import time
Victor Stinnere6c910e2011-06-30 15:55:43 +020064import tokenize
Nick Coghlan7bb30b72010-12-03 09:29:11 +000065import warnings
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000066from collections import deque
Nick Coghlan7bb30b72010-12-03 09:29:11 +000067from reprlib import Repr
Georg Brandld2f38572011-01-30 08:37:19 +000068from traceback import extract_tb, format_exception_only
Nick Coghlan7bb30b72010-12-03 09:29:11 +000069
70
Ka-Ping Yeedd175342001-02-27 14:43:46 +000071# --------------------------------------------------------- common routines
72
Ka-Ping Yeedd175342001-02-27 14:43:46 +000073def pathdirs():
74 """Convert sys.path into a list of absolute, existing, unique paths."""
75 dirs = []
Ka-Ping Yee1d384632001-03-01 00:24:32 +000076 normdirs = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +000077 for dir in sys.path:
78 dir = os.path.abspath(dir or '.')
Ka-Ping Yee1d384632001-03-01 00:24:32 +000079 normdir = os.path.normcase(dir)
80 if normdir not in normdirs and os.path.isdir(dir):
Ka-Ping Yeedd175342001-02-27 14:43:46 +000081 dirs.append(dir)
Ka-Ping Yee1d384632001-03-01 00:24:32 +000082 normdirs.append(normdir)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000083 return dirs
84
85def getdoc(object):
86 """Get the doc string or comments for an object."""
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000087 result = inspect.getdoc(object) or inspect.getcomments(object)
Neal Norwitz9d72bb42007-04-17 08:48:32 +000088 return result and re.sub('^ *\n', '', result.rstrip()) or ''
Ka-Ping Yeedd175342001-02-27 14:43:46 +000089
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000090def splitdoc(doc):
91 """Split a doc string into a synopsis line (if any) and the rest."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +000092 lines = doc.strip().split('\n')
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000093 if len(lines) == 1:
94 return lines[0], ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +000095 elif len(lines) >= 2 and not lines[1].rstrip():
96 return lines[0], '\n'.join(lines[2:])
97 return '', '\n'.join(lines)
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000098
Ka-Ping Yeedd175342001-02-27 14:43:46 +000099def classname(object, modname):
100 """Get a class name and qualify it with a module name if necessary."""
101 name = object.__name__
102 if object.__module__ != modname:
103 name = object.__module__ + '.' + name
104 return name
105
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000106def isdata(object):
Georg Brandl94432422005-07-22 21:52:25 +0000107 """Check if an object is of a type that probably means it's data."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000108 return not (inspect.ismodule(object) or inspect.isclass(object) or
109 inspect.isroutine(object) or inspect.isframe(object) or
110 inspect.istraceback(object) or inspect.iscode(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000111
112def replace(text, *pairs):
113 """Do a series of global replacements on a string."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000114 while pairs:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000115 text = pairs[1].join(text.split(pairs[0]))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000116 pairs = pairs[2:]
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000117 return text
118
119def cram(text, maxlen):
120 """Omit part of a string if needed to make it fit in a maximum length."""
121 if len(text) > maxlen:
Raymond Hettingerfca3bb62002-10-21 04:44:11 +0000122 pre = max(0, (maxlen-3)//2)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000123 post = max(0, maxlen-3-pre)
124 return text[:pre] + '...' + text[len(text)-post:]
125 return text
126
Brett Cannon84601f12004-06-19 01:22:48 +0000127_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000128def stripid(text):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000129 """Remove the hexadecimal id from a Python object representation."""
Brett Cannonc6c1f472004-06-19 01:02:51 +0000130 # The behaviour of %p is implementation-dependent in terms of case.
Ezio Melotti412c95a2010-02-16 23:31:04 +0000131 return _re_stripid.sub(r'\1', text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000132
Brett Cannonc6c1f472004-06-19 01:02:51 +0000133def _is_some_method(obj):
134 return inspect.ismethod(obj) or inspect.ismethoddescriptor(obj)
Tim Peters536d2262001-09-20 05:13:38 +0000135
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000136def allmethods(cl):
137 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000138 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000139 methods[key] = 1
140 for base in cl.__bases__:
141 methods.update(allmethods(base)) # all your base are belong to us
142 for key in methods.keys():
143 methods[key] = getattr(cl, key)
144 return methods
145
Tim Petersfa26f7c2001-09-24 08:05:11 +0000146def _split_list(s, predicate):
147 """Split sequence s via predicate, and return pair ([true], [false]).
148
149 The return value is a 2-tuple of lists,
150 ([x for x in s if predicate(x)],
151 [x for x in s if not predicate(x)])
152 """
153
Tim Peters28355492001-09-23 21:29:55 +0000154 yes = []
155 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000156 for x in s:
157 if predicate(x):
158 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000159 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000160 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000161 return yes, no
162
Raymond Hettinger1103d052011-03-25 14:15:24 -0700163def visiblename(name, all=None, obj=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000164 """Decide whether to show documentation on a variable."""
165 # Certain special names are redundant.
Raymond Hettinger68272942011-03-18 02:22:15 -0700166 if name in {'__builtins__', '__doc__', '__file__', '__path__',
Barry Warsaw28a691b2010-04-17 00:19:56 +0000167 '__module__', '__name__', '__slots__', '__package__',
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000168 '__cached__', '__author__', '__credits__', '__date__',
Antoine Pitrou86a36b52011-11-25 18:56:07 +0100169 '__version__', '__qualname__'}:
Raymond Hettinger68272942011-03-18 02:22:15 -0700170 return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000171 # Private names are hidden, but special names are displayed.
172 if name.startswith('__') and name.endswith('__'): return 1
Raymond Hettinger1103d052011-03-25 14:15:24 -0700173 # Namedtuples have public fields and methods with a single leading underscore
174 if name.startswith('_') and hasattr(obj, '_fields'):
175 return True
Skip Montanaroa5616d22004-06-11 04:46:12 +0000176 if all is not None:
177 # only document that which the programmer exported in __all__
178 return name in all
179 else:
180 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000181
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000182def classify_class_attrs(object):
183 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000184 results = []
185 for (name, kind, cls, value) in inspect.classify_class_attrs(object):
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000186 if inspect.isdatadescriptor(value):
187 kind = 'data descriptor'
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000188 results.append((name, kind, cls, value))
189 return results
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000190
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000191# ----------------------------------------------------- module manipulation
192
193def ispackage(path):
194 """Guess whether a path refers to a package directory."""
195 if os.path.isdir(path):
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000196 for ext in ('.py', '.pyc', '.pyo'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000197 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000198 return True
199 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000200
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000201def source_synopsis(file):
202 line = file.readline()
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000203 while line[:1] == '#' or not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000204 line = file.readline()
205 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000206 line = line.strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000207 if line[:4] == 'r"""': line = line[1:]
208 if line[:3] == '"""':
209 line = line[3:]
210 if line[-1:] == '\\': line = line[:-1]
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000211 while not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000212 line = file.readline()
213 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000214 result = line.split('"""')[0].strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000215 else: result = None
216 return result
217
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000218def synopsis(filename, cache={}):
219 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000220 mtime = os.stat(filename).st_mtime
Charles-François Natali27c4e882011-07-27 19:40:02 +0200221 lastupdate, result = cache.get(filename, (None, None))
222 if lastupdate is None or lastupdate < mtime:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000223 info = inspect.getmoduleinfo(filename)
Georg Brandl26fd2e12006-03-08 09:34:53 +0000224 try:
Victor Stinnere6c910e2011-06-30 15:55:43 +0200225 file = tokenize.open(filename)
Georg Brandl26fd2e12006-03-08 09:34:53 +0000226 except IOError:
227 # module can't be opened, so skip it
228 return None
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000229 if info and 'b' in info[2]: # binary modules have to be imported
230 try: module = imp.load_module('__temp__', file, filename, info[1:])
231 except: return None
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000232 result = (module.__doc__ or '').splitlines()[0]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000233 del sys.modules['__temp__']
234 else: # text modules can be directly examined
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000235 result = source_synopsis(file)
236 file.close()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000237 cache[filename] = (mtime, result)
238 return result
239
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000240class ErrorDuringImport(Exception):
241 """Errors that occurred while trying to import something to document it."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000242 def __init__(self, filename, exc_info):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000243 self.filename = filename
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000244 self.exc, self.value, self.tb = exc_info
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000245
246 def __str__(self):
Guido van Rossuma01a8b62007-05-27 09:20:14 +0000247 exc = self.exc.__name__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000248 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000249
250def importfile(path):
251 """Import a Python source file or compiled file given its path."""
252 magic = imp.get_magic()
Victor Stinnere975af62011-07-04 02:08:50 +0200253 with open(path, 'rb') as file:
254 if file.read(len(magic)) == magic:
255 kind = imp.PY_COMPILED
256 else:
257 kind = imp.PY_SOURCE
258 file.seek(0)
259 filename = os.path.basename(path)
260 name, ext = os.path.splitext(filename)
261 try:
262 module = imp.load_module(name, file, path, (ext, 'r', kind))
263 except:
264 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000265 return module
266
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000267def safeimport(path, forceload=0, cache={}):
268 """Import a module; handle errors; return None if the module isn't found.
269
270 If the module *is* found but an exception occurs, it's wrapped in an
271 ErrorDuringImport exception and reraised. Unlike __import__, if a
272 package path is specified, the module at the end of the path is returned,
273 not the package at the beginning. If the optional 'forceload' argument
274 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000275 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000276 # If forceload is 1 and the module has been previously loaded from
277 # disk, we always have to reload the module. Checking the file's
278 # mtime isn't good enough (e.g. the module could contain a class
279 # that inherits from another module that has changed).
280 if forceload and path in sys.modules:
281 if path not in sys.builtin_module_names:
Guido van Rossume7ba4952007-06-06 23:52:48 +0000282 # Remove the module from sys.modules and re-import to try
283 # and avoid problems with partially loaded modules.
284 # Also remove any submodules because they won't appear
285 # in the newly loaded module's namespace if they're already
286 # in sys.modules.
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000287 subs = [m for m in sys.modules if m.startswith(path + '.')]
288 for key in [path] + subs:
289 # Prevent garbage collection.
290 cache[key] = sys.modules[key]
291 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000292 module = __import__(path)
293 except:
294 # Did the error occur before or after the module was found?
295 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000296 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000297 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000298 raise ErrorDuringImport(sys.modules[path].__file__, info)
299 elif exc is SyntaxError:
300 # A SyntaxError occurred before we could execute the module.
301 raise ErrorDuringImport(value.filename, info)
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000302 elif exc is ImportError and extract_tb(tb)[-1][2]=='safeimport':
Benjamin Peterson0289b152009-06-28 17:22:03 +0000303 # The import error occurred directly in this function,
304 # which means there is no such module in the path.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000305 return None
306 else:
307 # Some other error occurred during the importing process.
308 raise ErrorDuringImport(path, sys.exc_info())
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000309 for part in path.split('.')[1:]:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000310 try: module = getattr(module, part)
311 except AttributeError: return None
312 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000313
314# ---------------------------------------------------- formatter base class
315
316class Doc:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000317
318 PYTHONDOCS = os.environ.get("PYTHONDOCS",
319 "http://docs.python.org/%d.%d/library"
320 % sys.version_info[:2])
321
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000322 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000323 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000324 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000325 # 'try' clause is to attempt to handle the possibility that inspect
326 # identifies something in a way that pydoc itself has issues handling;
327 # think 'super' and how it is a descriptor (which raises the exception
328 # by lacking a __name__ attribute) and an instance.
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000329 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
330 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000331 try:
332 if inspect.ismodule(object): return self.docmodule(*args)
333 if inspect.isclass(object): return self.docclass(*args)
334 if inspect.isroutine(object): return self.docroutine(*args)
335 except AttributeError:
336 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000337 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000338 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000339
340 def fail(self, object, name=None, *args):
341 """Raise an exception for unimplemented types."""
342 message = "don't know how to document object%s of type %s" % (
343 name and ' ' + repr(name), type(object).__name__)
Collin Winterce36ad82007-08-30 01:19:48 +0000344 raise TypeError(message)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000345
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000346 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000347
Skip Montanaro4997a692003-09-10 16:47:51 +0000348 def getdocloc(self, object):
349 """Return the location of module docs or None"""
350
351 try:
352 file = inspect.getabsfile(object)
353 except TypeError:
354 file = '(built-in)'
355
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000356 docloc = os.environ.get("PYTHONDOCS", self.PYTHONDOCS)
357
Skip Montanaro4997a692003-09-10 16:47:51 +0000358 basedir = os.path.join(sys.exec_prefix, "lib",
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000359 "python%d.%d" % sys.version_info[:2])
Skip Montanaro4997a692003-09-10 16:47:51 +0000360 if (isinstance(object, type(os)) and
361 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
362 'marshal', 'posix', 'signal', 'sys',
Georg Brandl2067bfd2008-05-25 13:05:15 +0000363 '_thread', 'zipimport') or
Skip Montanaro4997a692003-09-10 16:47:51 +0000364 (file.startswith(basedir) and
Brian Curtin49c284c2010-03-31 03:19:28 +0000365 not file.startswith(os.path.join(basedir, 'site-packages')))) and
Brian Curtinedef05b2010-04-01 04:05:25 +0000366 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
Skip Montanaro4997a692003-09-10 16:47:51 +0000367 if docloc.startswith("http://"):
Georg Brandl86def6c2008-01-21 20:36:10 +0000368 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
Skip Montanaro4997a692003-09-10 16:47:51 +0000369 else:
Georg Brandl86def6c2008-01-21 20:36:10 +0000370 docloc = os.path.join(docloc, object.__name__ + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000371 else:
372 docloc = None
373 return docloc
374
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000375# -------------------------------------------- HTML documentation generator
376
377class HTMLRepr(Repr):
378 """Class for safely making an HTML representation of a Python object."""
379 def __init__(self):
380 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000381 self.maxlist = self.maxtuple = 20
382 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000383 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000384
385 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000386 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000387
388 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000389 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000390
391 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000392 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000393 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000394 if hasattr(self, methodname):
395 return getattr(self, methodname)(x, level)
396 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000397
398 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000399 test = cram(x, self.maxstring)
400 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000401 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000402 # Backslashes are only literal in the string and are never
403 # needed to make any special characters, so show a raw string.
404 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000405 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000406 r'<font color="#c040c0">\1</font>',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000407 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000408
Skip Montanarodf708782002-03-07 22:58:02 +0000409 repr_str = repr_string
410
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000411 def repr_instance(self, x, level):
412 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000413 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000414 except:
415 return self.escape('<%s instance>' % x.__class__.__name__)
416
417 repr_unicode = repr_string
418
419class HTMLDoc(Doc):
420 """Formatter class for HTML documentation."""
421
422 # ------------------------------------------- HTML formatting utilities
423
424 _repr_instance = HTMLRepr()
425 repr = _repr_instance.repr
426 escape = _repr_instance.escape
427
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000428 def page(self, title, contents):
429 """Format an HTML page."""
Georg Brandl388faac2009-04-10 08:31:48 +0000430 return '''\
Georg Brandle6066942009-04-10 08:28:28 +0000431<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000432<html><head><title>Python: %s</title>
Georg Brandl388faac2009-04-10 08:31:48 +0000433<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000434</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000435%s
436</body></html>''' % (title, contents)
437
438 def heading(self, title, fgcol, bgcol, extras=''):
439 """Format a page heading."""
440 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000441<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000442<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000443<td valign=bottom>&nbsp;<br>
444<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000445><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000446><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000447 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
448
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000449 def section(self, title, fgcol, bgcol, contents, width=6,
450 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000451 """Format a section with a heading."""
452 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000453 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000454 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000455<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000456<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000457<td colspan=3 valign=bottom>&nbsp;<br>
458<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000459 ''' % (bgcol, fgcol, title)
460 if prelude:
461 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000462<tr bgcolor="%s"><td rowspan=2>%s</td>
463<td colspan=2>%s</td></tr>
464<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
465 else:
466 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000467<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000468
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000469 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000470
471 def bigsection(self, title, *args):
472 """Format a section with a big heading."""
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000473 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000474 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000475
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000476 def preformat(self, text):
477 """Format literal preformatted text."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000478 text = self.escape(text.expandtabs())
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000479 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
480 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000481
482 def multicolumn(self, list, format, cols=4):
483 """Format a list of items into a multi-column list."""
484 result = ''
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000485 rows = (len(list)+cols-1)//cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000486 for col in range(cols):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000487 result = result + '<td width="%d%%" valign=top>' % (100//cols)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000488 for i in range(rows*col, rows*col+rows):
489 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000490 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000491 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000492 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000493
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000494 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000495
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000496 def namelink(self, name, *dicts):
497 """Make a link for an identifier, given name-to-URL mappings."""
498 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000499 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000500 return '<a href="%s">%s</a>' % (dict[name], name)
501 return name
502
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000503 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000504 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000505 name, module = object.__name__, sys.modules.get(object.__module__)
506 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000507 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000508 module.__name__, name, classname(object, modname))
509 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000510
511 def modulelink(self, object):
512 """Make a link for a module."""
513 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
514
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000515 def modpkglink(self, modpkginfo):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000516 """Make a link for a module or package to display in an index."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000517 name, path, ispackage, shadowed = modpkginfo
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000518 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000519 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000520 if path:
521 url = '%s.%s.html' % (path, name)
522 else:
523 url = '%s.html' % name
524 if ispackage:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000525 text = '<strong>%s</strong>&nbsp;(package)' % name
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000526 else:
527 text = name
528 return '<a href="%s">%s</a>' % (url, text)
529
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000530 def filelink(self, url, path):
531 """Make a link to source file."""
532 return '<a href="file:%s">%s</a>' % (url, path)
533
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000534 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
535 """Mark up some plain text, given a context of symbols to look for.
536 Each context dictionary maps object names to anchor names."""
537 escape = escape or self.escape
538 results = []
539 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000540 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
541 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000542 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000543 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000544 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000545 match = pattern.search(text, here)
546 if not match: break
547 start, end = match.span()
548 results.append(escape(text[here:start]))
549
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000550 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000551 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000552 url = escape(all).replace('"', '&quot;')
553 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000554 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000555 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
556 results.append('<a href="%s">%s</a>' % (url, escape(all)))
557 elif pep:
Christian Heimes2202f872008-02-06 14:31:34 +0000558 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000559 results.append('<a href="%s">%s</a>' % (url, escape(all)))
560 elif text[end:end+1] == '(':
561 results.append(self.namelink(name, methods, funcs, classes))
562 elif selfdot:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000563 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000564 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000565 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000566 here = end
567 results.append(escape(text[here:]))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000568 return ''.join(results)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000569
570 # ---------------------------------------------- type-specific routines
571
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000572 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000573 """Produce HTML for a class tree as given by inspect.getclasstree()."""
574 result = ''
575 for entry in tree:
576 if type(entry) is type(()):
577 c, bases = entry
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000578 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000579 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000580 if bases and bases != (parent,):
581 parents = []
582 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000583 parents.append(self.classlink(base, modname))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000584 result = result + '(' + ', '.join(parents) + ')'
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000585 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000586 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000587 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000588 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000589 return '<dl>\n%s</dl>\n' % result
590
Tim Peters8dd7ade2001-10-18 19:56:17 +0000591 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000592 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000593 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000594 try:
595 all = object.__all__
596 except AttributeError:
597 all = None
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000598 parts = name.split('.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000599 links = []
600 for i in range(len(parts)-1):
601 links.append(
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000602 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000603 ('.'.join(parts[:i+1]), parts[i]))
604 linkedname = '.'.join(links + parts[-1:])
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000605 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000606 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000607 path = inspect.getabsfile(object)
Ka-Ping Yee6191a232001-04-13 15:00:27 +0000608 url = path
609 if sys.platform == 'win32':
610 import nturl2path
611 url = nturl2path.pathname2url(path)
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000612 filelink = self.filelink(url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000613 except TypeError:
614 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000615 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000616 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000617 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000618 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000619 version = version[11:-1].strip()
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000620 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000621 if hasattr(object, '__date__'):
622 info.append(self.escape(str(object.__date__)))
623 if info:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000624 head = head + ' (%s)' % ', '.join(info)
Skip Montanaro4997a692003-09-10 16:47:51 +0000625 docloc = self.getdocloc(object)
626 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000627 docloc = '<br><a href="%(docloc)s">Module Reference</a>' % locals()
Skip Montanaro4997a692003-09-10 16:47:51 +0000628 else:
629 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000630 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000631 head, '#ffffff', '#7799ee',
632 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000633
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000634 modules = inspect.getmembers(object, inspect.ismodule)
635
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000636 classes, cdict = [], {}
637 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000638 # if __all__ exists, believe it. Otherwise use old heuristic.
639 if (all is not None or
640 (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700641 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000642 classes.append((key, value))
643 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000644 for key, value in classes:
645 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000646 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000647 module = sys.modules.get(modname)
648 if modname != name and module and hasattr(module, key):
649 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000650 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000651 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000652 funcs, fdict = [], {}
653 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000654 # if __all__ exists, believe it. Otherwise use old heuristic.
655 if (all is not None or
656 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700657 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000658 funcs.append((key, value))
659 fdict[key] = '#-' + key
660 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000661 data = []
662 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700663 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000664 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000665
666 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
667 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000668 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000669
670 if hasattr(object, '__path__'):
671 modpkgs = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000672 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
673 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000674 modpkgs.sort()
675 contents = self.multicolumn(modpkgs, self.modpkglink)
676 result = result + self.bigsection(
677 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000678 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000679 contents = self.multicolumn(
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000680 modules, lambda t: self.modulelink(t[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000681 result = result + self.bigsection(
Christian Heimes7131fd92008-02-19 14:21:46 +0000682 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000683
684 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000685 classlist = [value for (key, value) in classes]
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000686 contents = [
687 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000688 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000689 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000690 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000691 'Classes', '#ffffff', '#ee77aa', ' '.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000692 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000693 contents = []
694 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000695 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000696 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000697 'Functions', '#ffffff', '#eeaa77', ' '.join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000698 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000699 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000700 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000701 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000702 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000703 'Data', '#ffffff', '#55aa55', '<br>\n'.join(contents))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000704 if hasattr(object, '__author__'):
705 contents = self.markup(str(object.__author__), self.preformat)
706 result = result + self.bigsection(
707 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000708 if hasattr(object, '__credits__'):
709 contents = self.markup(str(object.__credits__), self.preformat)
710 result = result + self.bigsection(
711 'Credits', '#ffffff', '#7799ee', contents)
712
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000713 return result
714
Tim Peters8dd7ade2001-10-18 19:56:17 +0000715 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
716 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000717 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000718 realname = object.__name__
719 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000720 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000721
Tim Petersb47879b2001-09-24 04:47:19 +0000722 contents = []
723 push = contents.append
724
Tim Petersfa26f7c2001-09-24 08:05:11 +0000725 # Cute little class to pump out a horizontal rule between sections.
726 class HorizontalRule:
727 def __init__(self):
728 self.needone = 0
729 def maybe(self):
730 if self.needone:
731 push('<hr>\n')
732 self.needone = 1
733 hr = HorizontalRule()
734
Tim Petersc86f6ca2001-09-26 21:31:51 +0000735 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000736 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000737 if len(mro) > 2:
738 hr.maybe()
739 push('<dl><dt>Method resolution order:</dt>\n')
740 for base in mro:
741 push('<dd>%s</dd>\n' % self.classlink(base,
742 object.__module__))
743 push('</dl>\n')
744
Tim Petersb47879b2001-09-24 04:47:19 +0000745 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000746 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000747 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000748 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000749 push(msg)
750 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100751 try:
752 value = getattr(object, name)
753 except Exception:
754 # Some descriptors may meet a failure in their __get__.
755 # (bug #1785)
756 push(self._docdescriptor(name, value, mod))
757 else:
758 push(self.document(value, name, mod,
759 funcs, classes, mdict, object))
Tim Petersb47879b2001-09-24 04:47:19 +0000760 push('\n')
761 return attrs
762
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000763 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000764 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000765 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000766 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000767 push(msg)
768 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000769 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000770 return attrs
771
Tim Petersfa26f7c2001-09-24 08:05:11 +0000772 def spilldata(msg, attrs, predicate):
773 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000774 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000775 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000776 push(msg)
777 for name, kind, homecls, value in ok:
778 base = self.docother(getattr(object, name), name, mod)
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200779 if callable(value) or inspect.isdatadescriptor(value):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000780 doc = getattr(value, "__doc__", None)
781 else:
782 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000783 if doc is None:
784 push('<dl><dt>%s</dl>\n' % base)
785 else:
786 doc = self.markup(getdoc(value), self.preformat,
787 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000788 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000789 push('<dl><dt>%s%s</dl>\n' % (base, doc))
790 push('\n')
791 return attrs
792
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000793 attrs = [(name, kind, cls, value)
794 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -0700795 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000796
Tim Petersb47879b2001-09-24 04:47:19 +0000797 mdict = {}
798 for key, kind, homecls, value in attrs:
799 mdict[key] = anchor = '#' + name + '-' + key
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100800 try:
801 value = getattr(object, name)
802 except Exception:
803 # Some descriptors may meet a failure in their __get__.
804 # (bug #1785)
805 pass
Tim Petersb47879b2001-09-24 04:47:19 +0000806 try:
807 # The value may not be hashable (e.g., a data attr with
808 # a dict or list value).
809 mdict[value] = anchor
810 except TypeError:
811 pass
812
Tim Petersfa26f7c2001-09-24 08:05:11 +0000813 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000814 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000815 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000816 else:
817 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000818 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
819
Georg Brandl1a3284e2007-12-02 09:40:06 +0000820 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000821 attrs = inherited
822 continue
823 elif thisclass is object:
824 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000825 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000826 tag = 'inherited from %s' % self.classlink(thisclass,
827 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000828 tag += ':<br>\n'
829
830 # Sort attrs by name.
Raymond Hettingerd4cb56d2008-01-30 02:55:10 +0000831 attrs.sort(key=lambda t: t[0])
Tim Petersb47879b2001-09-24 04:47:19 +0000832
833 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000834 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000835 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000836 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000837 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000838 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000839 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000840 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
841 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000842 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000843 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000844 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000845 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000846
847 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000848
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000849 if name == realname:
850 title = '<a name="%s">class <strong>%s</strong></a>' % (
851 name, realname)
852 else:
853 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
854 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000855 if bases:
856 parents = []
857 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000858 parents.append(self.classlink(base, object.__module__))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000859 title = title + '(%s)' % ', '.join(parents)
Tim Peters2306d242001-09-25 03:18:32 +0000860 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000861 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000862
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000863 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000864
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000865 def formatvalue(self, object):
866 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000867 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000868
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000869 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000870 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000871 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000872 realname = object.__name__
873 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000874 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000875 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000876 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000877 if inspect.ismethod(object):
Christian Heimesff737952007-11-27 10:40:20 +0000878 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000879 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000880 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000881 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000882 else:
Christian Heimesff737952007-11-27 10:40:20 +0000883 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000884 note = ' method of %s instance' % self.classlink(
Christian Heimesff737952007-11-27 10:40:20 +0000885 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000886 else:
887 note = ' unbound %s method' % self.classlink(imclass,mod)
Christian Heimesff737952007-11-27 10:40:20 +0000888 object = object.__func__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000889
890 if name == realname:
891 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
892 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000893 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000894 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000895 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000896 cl.__name__ + '-' + realname, realname)
897 skipdocs = 1
898 else:
899 reallink = realname
900 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
901 anchor, name, reallink)
Tim Peters4bcfa312001-09-20 06:08:24 +0000902 if inspect.isfunction(object):
Guido van Rossum2e65f892007-02-28 22:03:49 +0000903 args, varargs, kwonlyargs, kwdefaults, varkw, defaults, ann = \
904 inspect.getfullargspec(object)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000905 argspec = inspect.formatargspec(
Guido van Rossum2e65f892007-02-28 22:03:49 +0000906 args, varargs, kwonlyargs, kwdefaults, varkw, defaults, ann,
907 formatvalue=self.formatvalue,
908 formatannotation=inspect.formatannotationrelativeto(object))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000909 if realname == '<lambda>':
Tim Peters59ed4482001-10-31 04:20:26 +0000910 title = '<strong>%s</strong> <em>lambda</em> ' % name
Guido van Rossum2e65f892007-02-28 22:03:49 +0000911 # XXX lambda's won't usually have func_annotations['return']
912 # since the syntax doesn't support but it is possible.
913 # So removing parentheses isn't truly safe.
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000914 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +0000915 else:
916 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000917
Tim Peters2306d242001-09-25 03:18:32 +0000918 decl = title + argspec + (note and self.grey(
919 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000920
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000921 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000922 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000923 else:
924 doc = self.markup(
925 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000926 doc = doc and '<dd><tt>%s</tt></dd>' % doc
927 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000928
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000929 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000930 results = []
931 push = results.append
932
933 if name:
934 push('<dl><dt><strong>%s</strong></dt>\n' % name)
935 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000936 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000937 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000938 push('</dl>\n')
939
940 return ''.join(results)
941
942 def docproperty(self, object, name=None, mod=None, cl=None):
943 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000944 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000945
Tim Peters8dd7ade2001-10-18 19:56:17 +0000946 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000947 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000948 lhs = name and '<strong>%s</strong> = ' % name or ''
949 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000950
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000951 def docdata(self, object, name=None, mod=None, cl=None):
952 """Produce html documentation for a data descriptor."""
953 return self._docdescriptor(name, object, mod)
954
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000955 def index(self, dir, shadowed=None):
956 """Generate an HTML index for a directory of modules."""
957 modpkgs = []
958 if shadowed is None: shadowed = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000959 for importer, name, ispkg in pkgutil.iter_modules([dir]):
Victor Stinner4d652242011-04-12 23:41:50 +0200960 if any((0xD800 <= ord(ch) <= 0xDFFF) for ch in name):
961 # ignore a module if its name contains a surrogate character
962 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000963 modpkgs.append((name, '', ispkg, name in shadowed))
964 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000965
966 modpkgs.sort()
967 contents = self.multicolumn(modpkgs, self.modpkglink)
968 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
969
970# -------------------------------------------- text documentation generator
971
972class TextRepr(Repr):
973 """Class for safely making a text representation of a Python object."""
974 def __init__(self):
975 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000976 self.maxlist = self.maxtuple = 20
977 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000978 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000979
980 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000981 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000982 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000983 if hasattr(self, methodname):
984 return getattr(self, methodname)(x, level)
985 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000986
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000987 def repr_string(self, x, level):
988 test = cram(x, self.maxstring)
989 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000990 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000991 # Backslashes are only literal in the string and are never
992 # needed to make any special characters, so show a raw string.
993 return 'r' + testrepr[0] + test + testrepr[0]
994 return testrepr
995
Skip Montanarodf708782002-03-07 22:58:02 +0000996 repr_str = repr_string
997
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000998 def repr_instance(self, x, level):
999 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001000 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001001 except:
1002 return '<%s instance>' % x.__class__.__name__
1003
1004class TextDoc(Doc):
1005 """Formatter class for text documentation."""
1006
1007 # ------------------------------------------- text formatting utilities
1008
1009 _repr_instance = TextRepr()
1010 repr = _repr_instance.repr
1011
1012 def bold(self, text):
1013 """Format a string in bold by overstriking."""
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001014 return ''.join(ch + '\b' + ch for ch in text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001015
1016 def indent(self, text, prefix=' '):
1017 """Indent text by prepending a given prefix to each line."""
1018 if not text: return ''
Collin Winter72e110c2007-07-17 00:27:30 +00001019 lines = [prefix + line for line in text.split('\n')]
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001020 if lines: lines[-1] = lines[-1].rstrip()
1021 return '\n'.join(lines)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001022
1023 def section(self, title, contents):
1024 """Format a section with a given heading."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001025 clean_contents = self.indent(contents).rstrip()
1026 return self.bold(title) + '\n' + clean_contents + '\n\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001027
1028 # ---------------------------------------------- type-specific routines
1029
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001030 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001031 """Render in text a class tree as returned by inspect.getclasstree()."""
1032 result = ''
1033 for entry in tree:
1034 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001035 c, bases = entry
1036 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001037 if bases and bases != (parent,):
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001038 parents = (classname(c, modname) for c in bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001039 result = result + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001040 result = result + '\n'
1041 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001042 result = result + self.formattree(
1043 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001044 return result
1045
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001046 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001047 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001048 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001049 synop, desc = splitdoc(getdoc(object))
1050 result = self.section('NAME', name + (synop and ' - ' + synop))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001051 all = getattr(object, '__all__', None)
Skip Montanaro4997a692003-09-10 16:47:51 +00001052 docloc = self.getdocloc(object)
1053 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001054 result = result + self.section('MODULE REFERENCE', docloc + """
1055
Éric Araujo647ef8c2011-09-11 00:43:20 +02001056The following documentation is automatically generated from the Python
1057source files. It may be incomplete, incorrect or include features that
1058are considered implementation detail and may vary between Python
1059implementations. When in doubt, consult the module reference at the
1060location listed above.
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001061""")
Skip Montanaro4997a692003-09-10 16:47:51 +00001062
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001063 if desc:
1064 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001065
1066 classes = []
1067 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001068 # if __all__ exists, believe it. Otherwise use old heuristic.
1069 if (all is not None
1070 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001071 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001072 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001073 funcs = []
1074 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001075 # if __all__ exists, believe it. Otherwise use old heuristic.
1076 if (all is not None or
1077 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001078 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001079 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001080 data = []
1081 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001082 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001083 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001084
Christian Heimes1af737c2008-01-23 08:24:23 +00001085 modpkgs = []
1086 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001087 if hasattr(object, '__path__'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001088 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Christian Heimes1af737c2008-01-23 08:24:23 +00001089 modpkgs_names.add(modname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001090 if ispkg:
1091 modpkgs.append(modname + ' (package)')
1092 else:
1093 modpkgs.append(modname)
1094
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001095 modpkgs.sort()
1096 result = result + self.section(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001097 'PACKAGE CONTENTS', '\n'.join(modpkgs))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001098
Christian Heimes1af737c2008-01-23 08:24:23 +00001099 # Detect submodules as sometimes created by C extensions
1100 submodules = []
1101 for key, value in inspect.getmembers(object, inspect.ismodule):
1102 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1103 submodules.append(key)
1104 if submodules:
1105 submodules.sort()
1106 result = result + self.section(
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001107 'SUBMODULES', '\n'.join(submodules))
Christian Heimes1af737c2008-01-23 08:24:23 +00001108
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001109 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001110 classlist = [value for key, value in classes]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001111 contents = [self.formattree(
1112 inspect.getclasstree(classlist, 1), name)]
1113 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001114 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001115 result = result + self.section('CLASSES', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001116
1117 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001118 contents = []
1119 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001120 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001121 result = result + self.section('FUNCTIONS', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001122
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001123 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001124 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001125 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001126 contents.append(self.docother(value, key, name, maxlen=70))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001127 result = result + self.section('DATA', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001128
1129 if hasattr(object, '__version__'):
1130 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001131 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001132 version = version[11:-1].strip()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001133 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001134 if hasattr(object, '__date__'):
1135 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001136 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001137 result = result + self.section('AUTHOR', str(object.__author__))
1138 if hasattr(object, '__credits__'):
1139 result = result + self.section('CREDITS', str(object.__credits__))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001140 try:
1141 file = inspect.getabsfile(object)
1142 except TypeError:
1143 file = '(built-in)'
1144 result = result + self.section('FILE', file)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001145 return result
1146
Georg Brandl9bd45f992010-12-03 09:58:38 +00001147 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001148 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001149 realname = object.__name__
1150 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001151 bases = object.__bases__
1152
Tim Petersc86f6ca2001-09-26 21:31:51 +00001153 def makename(c, m=object.__module__):
1154 return classname(c, m)
1155
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001156 if name == realname:
1157 title = 'class ' + self.bold(realname)
1158 else:
1159 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001160 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001161 parents = map(makename, bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001162 title = title + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001163
1164 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001165 contents = doc and [doc + '\n'] or []
1166 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001167
Tim Petersc86f6ca2001-09-26 21:31:51 +00001168 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001169 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001170 if len(mro) > 2:
1171 push("Method resolution order:")
1172 for base in mro:
1173 push(' ' + makename(base))
1174 push('')
1175
Tim Petersf4aad8e2001-09-24 22:40:47 +00001176 # Cute little class to pump out a horizontal rule between sections.
1177 class HorizontalRule:
1178 def __init__(self):
1179 self.needone = 0
1180 def maybe(self):
1181 if self.needone:
1182 push('-' * 70)
1183 self.needone = 1
1184 hr = HorizontalRule()
1185
Tim Peters28355492001-09-23 21:29:55 +00001186 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001187 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001188 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001189 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001190 push(msg)
1191 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001192 try:
1193 value = getattr(object, name)
1194 except Exception:
1195 # Some descriptors may meet a failure in their __get__.
1196 # (bug #1785)
1197 push(self._docdescriptor(name, value, mod))
1198 else:
1199 push(self.document(value,
1200 name, mod, object))
Tim Peters28355492001-09-23 21:29:55 +00001201 return attrs
1202
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001203 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001204 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001205 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001206 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001207 push(msg)
1208 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001209 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001210 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001211
Tim Petersfa26f7c2001-09-24 08:05:11 +00001212 def spilldata(msg, attrs, predicate):
1213 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001214 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001215 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001216 push(msg)
1217 for name, kind, homecls, value in ok:
Florent Xicluna5d1155c2011-10-28 14:45:05 +02001218 if callable(value) or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001219 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001220 else:
1221 doc = None
Tim Peters28355492001-09-23 21:29:55 +00001222 push(self.docother(getattr(object, name),
Georg Brandl8b813db2005-10-01 16:32:31 +00001223 name, mod, maxlen=70, doc=doc) + '\n')
Tim Peters28355492001-09-23 21:29:55 +00001224 return attrs
1225
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001226 attrs = [(name, kind, cls, value)
1227 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -07001228 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001229
Tim Petersfa26f7c2001-09-24 08:05:11 +00001230 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001231 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001232 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001233 else:
1234 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001235 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1236
Georg Brandl1a3284e2007-12-02 09:40:06 +00001237 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001238 attrs = inherited
1239 continue
1240 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001241 tag = "defined here"
1242 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001243 tag = "inherited from %s" % classname(thisclass,
1244 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001245
1246 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001247 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001248
1249 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001250 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001251 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001252 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001253 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001254 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001255 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001256 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1257 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001258 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1259 lambda t: t[1] == 'data')
Tim Peters28355492001-09-23 21:29:55 +00001260 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001261 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001262
1263 contents = '\n'.join(contents)
1264 if not contents:
1265 return title + '\n'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001266 return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001267
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001268 def formatvalue(self, object):
1269 """Format an argument default value as text."""
1270 return '=' + self.repr(object)
1271
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001272 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001273 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001274 realname = object.__name__
1275 name = name or realname
1276 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001277 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001278 if inspect.ismethod(object):
Christian Heimesff737952007-11-27 10:40:20 +00001279 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001280 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001281 if imclass is not cl:
1282 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001283 else:
Christian Heimesff737952007-11-27 10:40:20 +00001284 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001285 note = ' method of %s instance' % classname(
Christian Heimesff737952007-11-27 10:40:20 +00001286 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001287 else:
1288 note = ' unbound %s method' % classname(imclass,mod)
Christian Heimesff737952007-11-27 10:40:20 +00001289 object = object.__func__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001290
1291 if name == realname:
1292 title = self.bold(realname)
1293 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001294 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001295 cl.__dict__[realname] is object):
1296 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001297 title = self.bold(name) + ' = ' + realname
Tim Peters4bcfa312001-09-20 06:08:24 +00001298 if inspect.isfunction(object):
Guido van Rossum2e65f892007-02-28 22:03:49 +00001299 args, varargs, varkw, defaults, kwonlyargs, kwdefaults, ann = \
1300 inspect.getfullargspec(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001301 argspec = inspect.formatargspec(
Guido van Rossum2e65f892007-02-28 22:03:49 +00001302 args, varargs, varkw, defaults, kwonlyargs, kwdefaults, ann,
1303 formatvalue=self.formatvalue,
1304 formatannotation=inspect.formatannotationrelativeto(object))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001305 if realname == '<lambda>':
Georg Brandl501dd0d2006-02-17 09:45:40 +00001306 title = self.bold(name) + ' lambda '
Guido van Rossum2e65f892007-02-28 22:03:49 +00001307 # XXX lambda's won't usually have func_annotations['return']
1308 # since the syntax doesn't support but it is possible.
1309 # So removing parentheses isn't truly safe.
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001310 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +00001311 else:
1312 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001313 decl = title + argspec + note
1314
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001315 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001316 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001317 else:
1318 doc = getdoc(object) or ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001319 return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001320
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001321 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001322 results = []
1323 push = results.append
1324
1325 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001326 push(self.bold(name))
1327 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001328 doc = getdoc(value) or ''
1329 if doc:
1330 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001331 push('\n')
1332 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001333
1334 def docproperty(self, object, name=None, mod=None, cl=None):
1335 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001336 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001337
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001338 def docdata(self, object, name=None, mod=None, cl=None):
1339 """Produce text documentation for a data descriptor."""
1340 return self._docdescriptor(name, object, mod)
1341
Georg Brandl8b813db2005-10-01 16:32:31 +00001342 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001343 """Produce text documentation for a data object."""
1344 repr = self.repr(object)
1345 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001346 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001347 chop = maxlen - len(line)
1348 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001349 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001350 if doc is not None:
1351 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001352 return line
1353
Georg Brandld80d5f42010-12-03 07:47:22 +00001354class _PlainTextDoc(TextDoc):
1355 """Subclass of TextDoc which overrides string styling"""
1356 def bold(self, text):
1357 return text
1358
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001359# --------------------------------------------------------- user interfaces
1360
1361def pager(text):
1362 """The first time this is called, determine what kind of pager to use."""
1363 global pager
1364 pager = getpager()
1365 pager(text)
1366
1367def getpager():
1368 """Decide what method to use for paging through text."""
Guido van Rossuma01a8b62007-05-27 09:20:14 +00001369 if not hasattr(sys.stdout, "isatty"):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001370 return plainpager
1371 if not sys.stdin.isatty() or not sys.stdout.isatty():
1372 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001373 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001374 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001375 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001376 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001377 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001378 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001379 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001380 if os.environ.get('TERM') in ('dumb', 'emacs'):
1381 return plainpager
Andrew MacIntyre54e0eab2002-03-03 03:12:30 +00001382 if sys.platform == 'win32' or sys.platform.startswith('os2'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001383 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001384 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001385 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001386
1387 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001388 (fd, filename) = tempfile.mkstemp()
1389 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001390 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001391 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001392 return lambda text: pipepager(text, 'more')
1393 else:
1394 return ttypager
1395 finally:
1396 os.unlink(filename)
1397
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001398def plain(text):
1399 """Remove boldface formatting from text."""
1400 return re.sub('.\b', '', text)
1401
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001402def pipepager(text, cmd):
1403 """Page through text by feeding it to another program."""
1404 pipe = os.popen(cmd, 'w')
1405 try:
1406 pipe.write(text)
1407 pipe.close()
1408 except IOError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001409 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001410
1411def tempfilepager(text, cmd):
1412 """Page through text by invoking a program on a temporary file."""
1413 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001414 filename = tempfile.mktemp()
1415 file = open(filename, 'w')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001416 file.write(text)
1417 file.close()
1418 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001419 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001420 finally:
1421 os.unlink(filename)
1422
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001423def ttypager(text):
1424 """Page through text on a text terminal."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001425 lines = plain(text).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001426 try:
1427 import tty
1428 fd = sys.stdin.fileno()
1429 old = tty.tcgetattr(fd)
1430 tty.setcbreak(fd)
1431 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001432 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001433 tty = None
1434 getchar = lambda: sys.stdin.readline()[:-1][:1]
1435
1436 try:
1437 r = inc = os.environ.get('LINES', 25) - 1
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001438 sys.stdout.write('\n'.join(lines[:inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001439 while lines[r:]:
1440 sys.stdout.write('-- more --')
1441 sys.stdout.flush()
1442 c = getchar()
1443
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001444 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001445 sys.stdout.write('\r \r')
1446 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001447 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001448 sys.stdout.write('\r \r' + lines[r] + '\n')
1449 r = r + 1
1450 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001451 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001452 r = r - inc - inc
1453 if r < 0: r = 0
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001454 sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001455 r = r + inc
1456
1457 finally:
1458 if tty:
1459 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1460
1461def plainpager(text):
1462 """Simply print unformatted text. This is the ultimate fallback."""
1463 sys.stdout.write(plain(text))
1464
1465def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001466 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001467 if inspect.ismodule(thing):
1468 if thing.__name__ in sys.builtin_module_names:
1469 return 'built-in module ' + thing.__name__
1470 if hasattr(thing, '__path__'):
1471 return 'package ' + thing.__name__
1472 else:
1473 return 'module ' + thing.__name__
1474 if inspect.isbuiltin(thing):
1475 return 'built-in function ' + thing.__name__
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001476 if inspect.isgetsetdescriptor(thing):
1477 return 'getset descriptor %s.%s.%s' % (
1478 thing.__objclass__.__module__, thing.__objclass__.__name__,
1479 thing.__name__)
1480 if inspect.ismemberdescriptor(thing):
1481 return 'member descriptor %s.%s.%s' % (
1482 thing.__objclass__.__module__, thing.__objclass__.__name__,
1483 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001484 if inspect.isclass(thing):
1485 return 'class ' + thing.__name__
1486 if inspect.isfunction(thing):
1487 return 'function ' + thing.__name__
1488 if inspect.ismethod(thing):
1489 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001490 return type(thing).__name__
1491
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001492def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001493 """Locate an object by name or dotted path, importing as necessary."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001494 parts = [part for part in path.split('.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001495 module, n = None, 0
1496 while n < len(parts):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001497 nextmodule = safeimport('.'.join(parts[:n+1]), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001498 if nextmodule: module, n = nextmodule, n + 1
1499 else: break
1500 if module:
1501 object = module
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001502 else:
Éric Araujoe64e51b2011-07-29 17:03:55 +02001503 object = builtins
1504 for part in parts[n:]:
1505 try:
1506 object = getattr(object, part)
1507 except AttributeError:
1508 return None
1509 return object
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001510
1511# --------------------------------------- interactive interpreter interface
1512
1513text = TextDoc()
Georg Brandld80d5f42010-12-03 07:47:22 +00001514plaintext = _PlainTextDoc()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001515html = HTMLDoc()
1516
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001517def resolve(thing, forceload=0):
1518 """Given an object or a path to an object, get the object and its name."""
1519 if isinstance(thing, str):
1520 object = locate(thing, forceload)
1521 if not object:
Collin Winterce36ad82007-08-30 01:19:48 +00001522 raise ImportError('no Python documentation found for %r' % thing)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001523 return object, thing
1524 else:
1525 return thing, getattr(thing, '__name__', None)
1526
Georg Brandld80d5f42010-12-03 07:47:22 +00001527def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
1528 renderer=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001529 """Render text documentation, given an object or a path to an object."""
Georg Brandld80d5f42010-12-03 07:47:22 +00001530 if renderer is None:
1531 renderer = text
Guido van Rossumd8faa362007-04-27 19:54:29 +00001532 object, name = resolve(thing, forceload)
1533 desc = describe(object)
1534 module = inspect.getmodule(object)
1535 if name and '.' in name:
1536 desc += ' in ' + name[:name.rfind('.')]
1537 elif module and module is not object:
1538 desc += ' in module ' + module.__name__
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001539
1540 if not (inspect.ismodule(object) or
Guido van Rossumd8faa362007-04-27 19:54:29 +00001541 inspect.isclass(object) or
1542 inspect.isroutine(object) or
1543 inspect.isgetsetdescriptor(object) or
1544 inspect.ismemberdescriptor(object) or
1545 isinstance(object, property)):
1546 # If the passed object is a piece of data or an instance,
1547 # document its available methods instead of its value.
1548 object = type(object)
1549 desc += ' object'
Georg Brandld80d5f42010-12-03 07:47:22 +00001550 return title % desc + '\n\n' + renderer.document(object, name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001551
Georg Brandld80d5f42010-12-03 07:47:22 +00001552def doc(thing, title='Python Library Documentation: %s', forceload=0,
1553 output=None):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001554 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001555 try:
Georg Brandld80d5f42010-12-03 07:47:22 +00001556 if output is None:
1557 pager(render_doc(thing, title, forceload))
1558 else:
1559 output.write(render_doc(thing, title, forceload, plaintext))
Guido van Rossumb940e112007-01-10 16:19:56 +00001560 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001561 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001562
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001563def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001564 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001565 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001566 object, name = resolve(thing, forceload)
1567 page = html.page(describe(object), html.document(object, name))
Georg Brandl388faac2009-04-10 08:31:48 +00001568 file = open(name + '.html', 'w', encoding='utf-8')
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001569 file.write(page)
1570 file.close()
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001571 print('wrote', name + '.html')
Guido van Rossumb940e112007-01-10 16:19:56 +00001572 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001573 print(value)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001574
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001575def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001576 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001577 if done is None: done = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001578 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1579 writedoc(modname)
1580 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001581
1582class Helper:
Georg Brandl6b38daa2008-06-01 21:05:17 +00001583
1584 # These dictionaries map a topic name to either an alias, or a tuple
1585 # (label, seealso-items). The "label" is the label of the corresponding
1586 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl5617db82009-04-27 16:28:57 +00001587 # in pydoc_data/topics.py.
Georg Brandl6b38daa2008-06-01 21:05:17 +00001588 #
1589 # CAUTION: if you change one of these dictionaries, be sure to adapt the
1590 # list of needed labels in Doc/tools/sphinxext/pyspecific.py and
Georg Brandl5617db82009-04-27 16:28:57 +00001591 # regenerate the pydoc_data/topics.py file by running
Georg Brandl6b38daa2008-06-01 21:05:17 +00001592 # make pydoc-topics
1593 # in Doc/ and copying the output file into the Lib/ directory.
1594
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001595 keywords = {
Ezio Melottib185a042011-04-28 07:42:55 +03001596 'False': '',
1597 'None': '',
1598 'True': '',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001599 'and': 'BOOLEAN',
Guido van Rossumd8faa362007-04-27 19:54:29 +00001600 'as': 'with',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001601 'assert': ('assert', ''),
1602 'break': ('break', 'while for'),
1603 'class': ('class', 'CLASSES SPECIALMETHODS'),
1604 'continue': ('continue', 'while for'),
1605 'def': ('function', ''),
1606 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001607 'elif': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001608 'else': ('else', 'while for'),
Georg Brandl0d855392008-08-30 19:53:05 +00001609 'except': 'try',
1610 'finally': 'try',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001611 'for': ('for', 'break continue while'),
Georg Brandl0d855392008-08-30 19:53:05 +00001612 'from': 'import',
Georg Brandl74abf6f2010-11-20 19:54:36 +00001613 'global': ('global', 'nonlocal NAMESPACES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001614 'if': ('if', 'TRUTHVALUE'),
1615 'import': ('import', 'MODULES'),
Georg Brandl395ed242009-09-04 08:07:32 +00001616 'in': ('in', 'SEQUENCEMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001617 'is': 'COMPARISON',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001618 'lambda': ('lambda', 'FUNCTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001619 'nonlocal': ('nonlocal', 'global NAMESPACES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001620 'not': 'BOOLEAN',
1621 'or': 'BOOLEAN',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001622 'pass': ('pass', ''),
1623 'raise': ('raise', 'EXCEPTIONS'),
1624 'return': ('return', 'FUNCTIONS'),
1625 'try': ('try', 'EXCEPTIONS'),
1626 'while': ('while', 'break continue if TRUTHVALUE'),
1627 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1628 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001629 }
Georg Brandldb7b6b92009-01-01 15:53:14 +00001630 # Either add symbols to this dictionary or to the symbols dictionary
1631 # directly: Whichever is easier. They are merged later.
1632 _symbols_inverse = {
1633 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'),
1634 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1635 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1636 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1637 'UNARY' : ('-', '~'),
1638 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1639 '^=', '<<=', '>>=', '**=', '//='),
1640 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1641 'COMPLEX' : ('j', 'J')
1642 }
1643 symbols = {
1644 '%': 'OPERATORS FORMATTING',
1645 '**': 'POWER',
1646 ',': 'TUPLES LISTS FUNCTIONS',
1647 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1648 '...': 'ELLIPSIS',
1649 ':': 'SLICINGS DICTIONARYLITERALS',
1650 '@': 'def class',
1651 '\\': 'STRINGS',
1652 '_': 'PRIVATENAMES',
1653 '__': 'PRIVATENAMES SPECIALMETHODS',
1654 '`': 'BACKQUOTES',
1655 '(': 'TUPLES FUNCTIONS CALLS',
1656 ')': 'TUPLES FUNCTIONS CALLS',
1657 '[': 'LISTS SUBSCRIPTS SLICINGS',
1658 ']': 'LISTS SUBSCRIPTS SLICINGS'
1659 }
1660 for topic, symbols_ in _symbols_inverse.items():
1661 for symbol in symbols_:
1662 topics = symbols.get(symbol, topic)
1663 if topic not in topics:
1664 topics = topics + ' ' + topic
1665 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001666
1667 topics = {
Georg Brandl6b38daa2008-06-01 21:05:17 +00001668 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1669 'FUNCTIONS CLASSES MODULES FILES inspect'),
1670 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS '
1671 'FORMATTING TYPES'),
1672 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1673 'FORMATTING': ('formatstrings', 'OPERATORS'),
1674 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1675 'FORMATTING TYPES'),
1676 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1677 'INTEGER': ('integers', 'int range'),
1678 'FLOAT': ('floating', 'float math'),
1679 'COMPLEX': ('imaginary', 'complex cmath'),
1680 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING range LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001681 'MAPPINGS': 'DICTIONARIES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001682 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1683 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1684 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1685 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001686 'FRAMEOBJECTS': 'TYPES',
1687 'TRACEBACKS': 'TYPES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001688 'NONE': ('bltin-null-object', ''),
1689 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
1690 'FILES': ('bltin-file-objects', ''),
1691 'SPECIALATTRIBUTES': ('specialattrs', ''),
1692 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1693 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001694 'PACKAGES': 'import',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001695 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1696 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1697 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1698 'LISTS DICTIONARIES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001699 'OPERATORS': 'EXPRESSIONS',
1700 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001701 'OBJECTS': ('objects', 'TYPES'),
1702 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
Georg Brandl395ed242009-09-04 08:07:32 +00001703 'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS '
1704 'NUMBERMETHODS CLASSES'),
Mark Dickinsona56c4672009-01-27 18:17:45 +00001705 'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001706 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1707 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001708 'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS '
Georg Brandl6b38daa2008-06-01 21:05:17 +00001709 'SPECIALMETHODS'),
1710 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1711 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1712 'SPECIALMETHODS'),
1713 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001714 'NAMESPACES': ('naming', 'global nonlocal ASSIGNMENT DELETION DYNAMICFEATURES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001715 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001716 'SCOPING': 'NAMESPACES',
1717 'FRAMES': 'NAMESPACES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001718 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1719 'CONVERSIONS': ('conversions', ''),
1720 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1721 'SPECIALIDENTIFIERS': ('id-classes', ''),
1722 'PRIVATENAMES': ('atom-identifiers', ''),
1723 'LITERALS': ('atom-literals', 'STRINGS NUMBERS TUPLELITERALS '
1724 'LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001725 'TUPLES': 'SEQUENCES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001726 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1727 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1728 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1729 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1730 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1731 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001732 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'),
1733 'SLICINGS': ('slicings', 'SEQUENCEMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001734 'CALLS': ('calls', 'EXPRESSIONS'),
1735 'POWER': ('power', 'EXPRESSIONS'),
1736 'UNARY': ('unary', 'EXPRESSIONS'),
1737 'BINARY': ('binary', 'EXPRESSIONS'),
1738 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1739 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1740 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1741 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001742 'ASSERTION': 'assert',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001743 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1744 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001745 'DELETION': 'del',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001746 'RETURNING': 'return',
1747 'IMPORTING': 'import',
1748 'CONDITIONAL': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001749 'LOOPING': ('compound', 'for while break continue'),
1750 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1751 'DEBUGGING': ('debugger', 'pdb'),
1752 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001753 }
1754
Georg Brandl78aa3962010-07-31 21:51:48 +00001755 def __init__(self, input=None, output=None):
1756 self._input = input
1757 self._output = output
1758
Georg Brandl76ae3972010-08-01 06:32:55 +00001759 input = property(lambda self: self._input or sys.stdin)
1760 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001761
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001762 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001763 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001764 self()
1765 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001766 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001767
Alexander Belopolsky2e733c92010-07-04 17:00:20 +00001768 _GoInteractive = object()
1769 def __call__(self, request=_GoInteractive):
1770 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001771 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001772 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001773 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001774 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001775 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001776You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001777If you want to ask for help on a particular object directly from the
1778interpreter, you can type "help(object)". Executing "help('string')"
1779has the same effect as typing a particular string at the help> prompt.
1780''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001781
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001782 def interact(self):
1783 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001784 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001785 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001786 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001787 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001788 except (KeyboardInterrupt, EOFError):
1789 break
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001790 request = replace(request, '"', '', "'", '').strip()
1791 if request.lower() in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001792 self.help(request)
1793
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001794 def getline(self, prompt):
Guido van Rossum7c086c02008-01-02 03:52:38 +00001795 """Read one line, using input() when appropriate."""
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001796 if self.input is sys.stdin:
Guido van Rossum7c086c02008-01-02 03:52:38 +00001797 return input(prompt)
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001798 else:
1799 self.output.write(prompt)
1800 self.output.flush()
1801 return self.input.readline()
1802
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001803 def help(self, request):
1804 if type(request) is type(''):
R. David Murray1f1b9d32009-05-27 20:56:59 +00001805 request = request.strip()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001806 if request == 'help': self.intro()
1807 elif request == 'keywords': self.listkeywords()
Georg Brandldb7b6b92009-01-01 15:53:14 +00001808 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001809 elif request == 'topics': self.listtopics()
1810 elif request == 'modules': self.listmodules()
1811 elif request[:8] == 'modules ':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001812 self.listmodules(request.split()[1])
Georg Brandldb7b6b92009-01-01 15:53:14 +00001813 elif request in self.symbols: self.showsymbol(request)
Ezio Melottib185a042011-04-28 07:42:55 +03001814 elif request in ['True', 'False', 'None']:
1815 # special case these keywords since they are objects too
1816 doc(eval(request), 'Help on %s:')
Raymond Hettinger54f02222002-06-01 14:18:47 +00001817 elif request in self.keywords: self.showtopic(request)
1818 elif request in self.topics: self.showtopic(request)
Georg Brandld80d5f42010-12-03 07:47:22 +00001819 elif request: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001820 elif isinstance(request, Helper): self()
Georg Brandld80d5f42010-12-03 07:47:22 +00001821 else: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001822 self.output.write('\n')
1823
1824 def intro(self):
1825 self.output.write('''
1826Welcome to Python %s! This is the online help utility.
1827
1828If this is your first time using Python, you should definitely check out
R David Murrayde0f6292012-03-31 12:06:35 -04001829the tutorial on the Internet at http://docs.python.org/%s/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001830
1831Enter the name of any module, keyword, or topic to get help on writing
1832Python programs and using Python modules. To quit this help utility and
1833return to the interpreter, just type "quit".
1834
1835To get a list of available modules, keywords, or topics, type "modules",
1836"keywords", or "topics". Each module also comes with a one-line summary
1837of what it does; to list the modules whose summaries contain a given word
1838such as "spam", type "modules spam".
R David Murrayde0f6292012-03-31 12:06:35 -04001839''' % tuple([sys.version[:3]]*2))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001840
1841 def list(self, items, columns=4, width=80):
Guido van Rossum486364b2007-06-30 05:01:58 +00001842 items = list(sorted(items))
1843 colw = width // columns
1844 rows = (len(items) + columns - 1) // columns
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001845 for row in range(rows):
1846 for col in range(columns):
1847 i = col * rows + row
1848 if i < len(items):
1849 self.output.write(items[i])
1850 if col < columns - 1:
Guido van Rossum486364b2007-06-30 05:01:58 +00001851 self.output.write(' ' + ' ' * (colw - 1 - len(items[i])))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001852 self.output.write('\n')
1853
1854 def listkeywords(self):
1855 self.output.write('''
1856Here is a list of the Python keywords. Enter any keyword to get more help.
1857
1858''')
1859 self.list(self.keywords.keys())
1860
Georg Brandldb7b6b92009-01-01 15:53:14 +00001861 def listsymbols(self):
1862 self.output.write('''
1863Here is a list of the punctuation symbols which Python assigns special meaning
1864to. Enter any symbol to get more help.
1865
1866''')
1867 self.list(self.symbols.keys())
1868
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001869 def listtopics(self):
1870 self.output.write('''
1871Here is a list of available topics. Enter any topic name to get more help.
1872
1873''')
1874 self.list(self.topics.keys())
1875
Georg Brandldb7b6b92009-01-01 15:53:14 +00001876 def showtopic(self, topic, more_xrefs=''):
Georg Brandl6b38daa2008-06-01 21:05:17 +00001877 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001878 import pydoc_data.topics
Georg Brandl6b38daa2008-06-01 21:05:17 +00001879 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001880 self.output.write('''
Georg Brandl6b38daa2008-06-01 21:05:17 +00001881Sorry, topic and keyword documentation is not available because the
Georg Brandl5617db82009-04-27 16:28:57 +00001882module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001883''')
1884 return
1885 target = self.topics.get(topic, self.keywords.get(topic))
1886 if not target:
1887 self.output.write('no documentation found for %s\n' % repr(topic))
1888 return
1889 if type(target) is type(''):
Georg Brandldb7b6b92009-01-01 15:53:14 +00001890 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001891
Georg Brandl6b38daa2008-06-01 21:05:17 +00001892 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001893 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001894 doc = pydoc_data.topics.topics[label]
Georg Brandl6b38daa2008-06-01 21:05:17 +00001895 except KeyError:
1896 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001897 return
Georg Brandl6b38daa2008-06-01 21:05:17 +00001898 pager(doc.strip() + '\n')
Georg Brandldb7b6b92009-01-01 15:53:14 +00001899 if more_xrefs:
1900 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001901 if xrefs:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001902 import formatter
Guido van Rossum34d19282007-08-09 01:03:29 +00001903 buffer = io.StringIO()
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001904 formatter.DumbWriter(buffer).send_flowing_data(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001905 'Related help topics: ' + ', '.join(xrefs.split()) + '\n')
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001906 self.output.write('\n%s\n' % buffer.getvalue())
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001907
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001908 def _gettopic(self, topic, more_xrefs=''):
1909 """Return unbuffered tuple of (topic, xrefs).
1910
Georg Brandld2f38572011-01-30 08:37:19 +00001911 If an error occurs here, the exception is caught and displayed by
1912 the url handler.
1913
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001914 This function duplicates the showtopic method but returns its
1915 result directly so it can be formatted for display in an html page.
1916 """
1917 try:
1918 import pydoc_data.topics
1919 except ImportError:
1920 return('''
1921Sorry, topic and keyword documentation is not available because the
1922module "pydoc_data.topics" could not be found.
1923''' , '')
1924 target = self.topics.get(topic, self.keywords.get(topic))
1925 if not target:
Georg Brandld2f38572011-01-30 08:37:19 +00001926 raise ValueError('could not find topic')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001927 if isinstance(target, str):
1928 return self._gettopic(target, more_xrefs)
1929 label, xrefs = target
Georg Brandld2f38572011-01-30 08:37:19 +00001930 doc = pydoc_data.topics.topics[label]
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001931 if more_xrefs:
1932 xrefs = (xrefs or '') + ' ' + more_xrefs
1933 return doc, xrefs
1934
Georg Brandldb7b6b92009-01-01 15:53:14 +00001935 def showsymbol(self, symbol):
1936 target = self.symbols[symbol]
1937 topic, _, xrefs = target.partition(' ')
1938 self.showtopic(topic, xrefs)
1939
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001940 def listmodules(self, key=''):
1941 if key:
1942 self.output.write('''
1943Here is a list of matching modules. Enter any module name to get more help.
1944
1945''')
1946 apropos(key)
1947 else:
1948 self.output.write('''
1949Please wait a moment while I gather a list of all available modules...
1950
1951''')
1952 modules = {}
1953 def callback(path, modname, desc, modules=modules):
1954 if modname and modname[-9:] == '.__init__':
1955 modname = modname[:-9] + ' (package)'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001956 if modname.find('.') < 0:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001957 modules[modname] = 1
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001958 def onerror(modname):
1959 callback(None, modname, None)
1960 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001961 self.list(modules.keys())
1962 self.output.write('''
1963Enter any module name to get more help. Or, type "modules spam" to search
1964for modules whose descriptions contain the word "spam".
1965''')
1966
Georg Brandl78aa3962010-07-31 21:51:48 +00001967help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001968
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001969class Scanner:
1970 """A generic tree iterator."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001971 def __init__(self, roots, children, descendp):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001972 self.roots = roots[:]
1973 self.state = []
1974 self.children = children
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001975 self.descendp = descendp
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001976
1977 def next(self):
1978 if not self.state:
1979 if not self.roots:
1980 return None
1981 root = self.roots.pop(0)
1982 self.state = [(root, self.children(root))]
1983 node, children = self.state[-1]
1984 if not children:
1985 self.state.pop()
1986 return self.next()
1987 child = children.pop(0)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001988 if self.descendp(child):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001989 self.state.append((child, self.children(child)))
1990 return child
1991
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001992
1993class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001994 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001995
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001996 def run(self, callback, key=None, completer=None, onerror=None):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001997 if key: key = key.lower()
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001998 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001999 seen = {}
2000
2001 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002002 if modname != '__main__':
2003 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00002004 if key is None:
2005 callback(None, modname, '')
2006 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002007 name = __import__(modname).__doc__ or ''
2008 desc = name.split('\n')[0]
2009 name = modname + ' - ' + desc
2010 if name.lower().find(key) >= 0:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002011 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002012
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002013 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002014 if self.quit:
2015 break
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002016
2017 # XXX Skipping this file is a workaround for a bug
2018 # that causes python to crash with a segfault.
2019 # http://bugs.python.org/issue9319
2020 #
2021 # TODO Remove this once the bug is fixed.
2022 if modname in {'test.badsyntax_pep3120', 'badsyntax_pep3120'}:
2023 continue
2024
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002025 if key is None:
2026 callback(None, modname, '')
2027 else:
Georg Brandl126c8792009-04-05 15:05:48 +00002028 try:
2029 loader = importer.find_module(modname)
2030 except SyntaxError:
2031 # raised by tests for bad coding cookies or BOM
2032 continue
2033 if hasattr(loader, 'get_source'):
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002034 try:
2035 source = loader.get_source(modname)
2036 except UnicodeDecodeError:
2037 if onerror:
2038 onerror(modname)
2039 continue
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002040 desc = source_synopsis(io.StringIO(source)) or ''
Georg Brandl126c8792009-04-05 15:05:48 +00002041 if hasattr(loader, 'get_filename'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002042 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002043 else:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002044 path = None
2045 else:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002046 try:
2047 module = loader.load_module(modname)
2048 except ImportError:
2049 if onerror:
2050 onerror(modname)
2051 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002052 desc = (module.__doc__ or '').splitlines()[0]
2053 path = getattr(module,'__file__',None)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002054 name = modname + ' - ' + desc
2055 if name.lower().find(key) >= 0:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002056 callback(path, modname, desc)
2057
2058 if completer:
2059 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002060
2061def apropos(key):
2062 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002063 def callback(path, modname, desc):
2064 if modname[-9:] == '.__init__':
2065 modname = modname[:-9] + ' (package)'
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002066 print(modname, desc and '- ' + desc)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002067 def onerror(modname):
2068 pass
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002069 with warnings.catch_warnings():
2070 warnings.filterwarnings('ignore') # ignore problems during import
2071 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002072
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002073# --------------------------------------- enhanced Web browser interface
2074
2075def _start_server(urlhandler, port):
2076 """Start an HTTP server thread on a specific port.
2077
2078 Start an HTML/text server thread, so HTML or text documents can be
2079 browsed dynamically and interactively with a Web browser. Example use:
2080
2081 >>> import time
2082 >>> import pydoc
2083
2084 Define a URL handler. To determine what the client is asking
2085 for, check the URL and content_type.
2086
2087 Then get or generate some text or HTML code and return it.
2088
2089 >>> def my_url_handler(url, content_type):
2090 ... text = 'the URL sent was: (%s, %s)' % (url, content_type)
2091 ... return text
2092
2093 Start server thread on port 0.
2094 If you use port 0, the server will pick a random port number.
2095 You can then use serverthread.port to get the port number.
2096
2097 >>> port = 0
2098 >>> serverthread = pydoc._start_server(my_url_handler, port)
2099
2100 Check that the server is really started. If it is, open browser
2101 and get first page. Use serverthread.url as the starting page.
2102
2103 >>> if serverthread.serving:
2104 ... import webbrowser
2105
2106 The next two lines are commented out so a browser doesn't open if
2107 doctest is run on this module.
2108
2109 #... webbrowser.open(serverthread.url)
2110 #True
2111
2112 Let the server do its thing. We just need to monitor its status.
2113 Use time.sleep so the loop doesn't hog the CPU.
2114
2115 >>> starttime = time.time()
2116 >>> timeout = 1 #seconds
2117
2118 This is a short timeout for testing purposes.
2119
2120 >>> while serverthread.serving:
2121 ... time.sleep(.01)
2122 ... if serverthread.serving and time.time() - starttime > timeout:
2123 ... serverthread.stop()
2124 ... break
2125
2126 Print any errors that may have occurred.
2127
2128 >>> print(serverthread.error)
2129 None
2130 """
2131 import http.server
2132 import email.message
2133 import select
2134 import threading
2135
2136 class DocHandler(http.server.BaseHTTPRequestHandler):
2137
2138 def do_GET(self):
2139 """Process a request from an HTML browser.
2140
2141 The URL received is in self.path.
2142 Get an HTML page from self.urlhandler and send it.
2143 """
2144 if self.path.endswith('.css'):
2145 content_type = 'text/css'
2146 else:
2147 content_type = 'text/html'
2148 self.send_response(200)
Georg Brandld2f38572011-01-30 08:37:19 +00002149 self.send_header('Content-Type', '%s; charset=UTF-8' % content_type)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002150 self.end_headers()
2151 self.wfile.write(self.urlhandler(
2152 self.path, content_type).encode('utf-8'))
2153
2154 def log_message(self, *args):
2155 # Don't log messages.
2156 pass
2157
2158 class DocServer(http.server.HTTPServer):
2159
2160 def __init__(self, port, callback):
2161 self.host = (sys.platform == 'mac') and '127.0.0.1' or 'localhost'
2162 self.address = ('', port)
2163 self.callback = callback
2164 self.base.__init__(self, self.address, self.handler)
2165 self.quit = False
2166
2167 def serve_until_quit(self):
2168 while not self.quit:
2169 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2170 if rd:
2171 self.handle_request()
Victor Stinnera3abd1d2011-01-03 16:12:39 +00002172 self.server_close()
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002173
2174 def server_activate(self):
2175 self.base.server_activate(self)
2176 if self.callback:
2177 self.callback(self)
2178
2179 class ServerThread(threading.Thread):
2180
2181 def __init__(self, urlhandler, port):
2182 self.urlhandler = urlhandler
2183 self.port = int(port)
2184 threading.Thread.__init__(self)
2185 self.serving = False
2186 self.error = None
2187
2188 def run(self):
2189 """Start the server."""
2190 try:
2191 DocServer.base = http.server.HTTPServer
2192 DocServer.handler = DocHandler
2193 DocHandler.MessageClass = email.message.Message
2194 DocHandler.urlhandler = staticmethod(self.urlhandler)
2195 docsvr = DocServer(self.port, self.ready)
2196 self.docserver = docsvr
2197 docsvr.serve_until_quit()
2198 except Exception as e:
2199 self.error = e
2200
2201 def ready(self, server):
2202 self.serving = True
2203 self.host = server.host
2204 self.port = server.server_port
2205 self.url = 'http://%s:%d/' % (self.host, self.port)
2206
2207 def stop(self):
2208 """Stop the server and this thread nicely"""
2209 self.docserver.quit = True
2210 self.serving = False
2211 self.url = None
2212
2213 thread = ServerThread(urlhandler, port)
2214 thread.start()
2215 # Wait until thread.serving is True to make sure we are
2216 # really up before returning.
2217 while not thread.error and not thread.serving:
2218 time.sleep(.01)
2219 return thread
2220
2221
2222def _url_handler(url, content_type="text/html"):
2223 """The pydoc url handler for use with the pydoc server.
2224
2225 If the content_type is 'text/css', the _pydoc.css style
2226 sheet is read and returned if it exits.
2227
2228 If the content_type is 'text/html', then the result of
2229 get_html_page(url) is returned.
2230 """
2231 class _HTMLDoc(HTMLDoc):
2232
2233 def page(self, title, contents):
2234 """Format an HTML page."""
2235 css_path = "pydoc_data/_pydoc.css"
2236 css_link = (
2237 '<link rel="stylesheet" type="text/css" href="%s">' %
2238 css_path)
2239 return '''\
2240<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Georg Brandld2f38572011-01-30 08:37:19 +00002241<html><head><title>Pydoc: %s</title>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002242<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Georg Brandld2f38572011-01-30 08:37:19 +00002243%s</head><body bgcolor="#f0f0f8">%s<div style="clear:both;padding-top:.5em;">%s</div>
2244</body></html>''' % (title, css_link, html_navbar(), contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002245
2246 def filelink(self, url, path):
2247 return '<a href="getfile?key=%s">%s</a>' % (url, path)
2248
2249
2250 html = _HTMLDoc()
2251
2252 def html_navbar():
Georg Brandld2f38572011-01-30 08:37:19 +00002253 version = html.escape("%s [%s, %s]" % (platform.python_version(),
2254 platform.python_build()[0],
2255 platform.python_compiler()))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002256 return """
2257 <div style='float:left'>
Georg Brandld2f38572011-01-30 08:37:19 +00002258 Python %s<br>%s
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002259 </div>
2260 <div style='float:right'>
2261 <div style='text-align:center'>
2262 <a href="index.html">Module Index</a>
2263 : <a href="topics.html">Topics</a>
2264 : <a href="keywords.html">Keywords</a>
2265 </div>
2266 <div>
Georg Brandld2f38572011-01-30 08:37:19 +00002267 <form action="get" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002268 <input type=text name=key size=15>
2269 <input type=submit value="Get">
Georg Brandld2f38572011-01-30 08:37:19 +00002270 </form>&nbsp;
2271 <form action="search" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002272 <input type=text name=key size=15>
2273 <input type=submit value="Search">
2274 </form>
2275 </div>
2276 </div>
Georg Brandld2f38572011-01-30 08:37:19 +00002277 """ % (version, html.escape(platform.platform(terse=True)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002278
2279 def html_index():
2280 """Module Index page."""
2281
2282 def bltinlink(name):
2283 return '<a href="%s.html">%s</a>' % (name, name)
2284
2285 heading = html.heading(
2286 '<big><big><strong>Index of Modules</strong></big></big>',
2287 '#ffffff', '#7799ee')
2288 names = [name for name in sys.builtin_module_names
2289 if name != '__main__']
2290 contents = html.multicolumn(names, bltinlink)
2291 contents = [heading, '<p>' + html.bigsection(
2292 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2293
2294 seen = {}
2295 for dir in sys.path:
2296 contents.append(html.index(dir, seen))
2297
2298 contents.append(
2299 '<p align=right><font color="#909090" face="helvetica,'
2300 'arial"><strong>pydoc</strong> by Ka-Ping Yee'
2301 '&lt;ping@lfw.org&gt;</font>')
Nick Coghlanecace282010-12-03 16:08:46 +00002302 return 'Index of Modules', ''.join(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002303
2304 def html_search(key):
2305 """Search results page."""
2306 # scan for modules
2307 search_result = []
2308
2309 def callback(path, modname, desc):
2310 if modname[-9:] == '.__init__':
2311 modname = modname[:-9] + ' (package)'
2312 search_result.append((modname, desc and '- ' + desc))
2313
2314 with warnings.catch_warnings():
2315 warnings.filterwarnings('ignore') # ignore problems during import
2316 ModuleScanner().run(callback, key)
2317
2318 # format page
2319 def bltinlink(name):
2320 return '<a href="%s.html">%s</a>' % (name, name)
2321
2322 results = []
2323 heading = html.heading(
2324 '<big><big><strong>Search Results</strong></big></big>',
2325 '#ffffff', '#7799ee')
2326 for name, desc in search_result:
2327 results.append(bltinlink(name) + desc)
2328 contents = heading + html.bigsection(
2329 'key = %s' % key, '#ffffff', '#ee77aa', '<br>'.join(results))
Nick Coghlanecace282010-12-03 16:08:46 +00002330 return 'Search Results', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002331
2332 def html_getfile(path):
2333 """Get and display a source file listing safely."""
Nick Coghlanecace282010-12-03 16:08:46 +00002334 path = path.replace('%20', ' ')
Victor Stinner91e08772011-07-05 14:30:41 +02002335 with tokenize.open(path) as fp:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002336 lines = html.escape(fp.read())
2337 body = '<pre>%s</pre>' % lines
2338 heading = html.heading(
2339 '<big><big><strong>File Listing</strong></big></big>',
2340 '#ffffff', '#7799ee')
2341 contents = heading + html.bigsection(
2342 'File: %s' % path, '#ffffff', '#ee77aa', body)
Nick Coghlanecace282010-12-03 16:08:46 +00002343 return 'getfile %s' % path, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002344
2345 def html_topics():
2346 """Index of topic texts available."""
2347
2348 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002349 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002350
2351 heading = html.heading(
2352 '<big><big><strong>INDEX</strong></big></big>',
2353 '#ffffff', '#7799ee')
2354 names = sorted(Helper.topics.keys())
2355
2356 contents = html.multicolumn(names, bltinlink)
2357 contents = heading + html.bigsection(
2358 'Topics', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002359 return 'Topics', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002360
2361 def html_keywords():
2362 """Index of keywords."""
2363 heading = html.heading(
2364 '<big><big><strong>INDEX</strong></big></big>',
2365 '#ffffff', '#7799ee')
2366 names = sorted(Helper.keywords.keys())
2367
2368 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002369 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002370
2371 contents = html.multicolumn(names, bltinlink)
2372 contents = heading + html.bigsection(
2373 'Keywords', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002374 return 'Keywords', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002375
2376 def html_topicpage(topic):
2377 """Topic or keyword help page."""
2378 buf = io.StringIO()
2379 htmlhelp = Helper(buf, buf)
2380 contents, xrefs = htmlhelp._gettopic(topic)
2381 if topic in htmlhelp.keywords:
2382 title = 'KEYWORD'
2383 else:
2384 title = 'TOPIC'
2385 heading = html.heading(
2386 '<big><big><strong>%s</strong></big></big>' % title,
2387 '#ffffff', '#7799ee')
Georg Brandld2f38572011-01-30 08:37:19 +00002388 contents = '<pre>%s</pre>' % html.markup(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002389 contents = html.bigsection(topic , '#ffffff','#ee77aa', contents)
Georg Brandld2f38572011-01-30 08:37:19 +00002390 if xrefs:
2391 xrefs = sorted(xrefs.split())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002392
Georg Brandld2f38572011-01-30 08:37:19 +00002393 def bltinlink(name):
2394 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002395
Georg Brandld2f38572011-01-30 08:37:19 +00002396 xrefs = html.multicolumn(xrefs, bltinlink)
2397 xrefs = html.section('Related help topics: ',
2398 '#ffffff', '#ee77aa', xrefs)
Nick Coghlanecace282010-12-03 16:08:46 +00002399 return ('%s %s' % (title, topic),
2400 ''.join((heading, contents, xrefs)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002401
Georg Brandld2f38572011-01-30 08:37:19 +00002402 def html_getobj(url):
2403 obj = locate(url, forceload=1)
2404 if obj is None and url != 'None':
2405 raise ValueError('could not find object')
2406 title = describe(obj)
2407 content = html.document(obj, url)
2408 return title, content
2409
2410 def html_error(url, exc):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002411 heading = html.heading(
2412 '<big><big><strong>Error</strong></big></big>',
Georg Brandld2f38572011-01-30 08:37:19 +00002413 '#ffffff', '#7799ee')
2414 contents = '<br>'.join(html.escape(line) for line in
2415 format_exception_only(type(exc), exc))
2416 contents = heading + html.bigsection(url, '#ffffff', '#bb0000',
2417 contents)
2418 return "Error - %s" % url, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002419
2420 def get_html_page(url):
2421 """Generate an HTML page for url."""
Georg Brandld2f38572011-01-30 08:37:19 +00002422 complete_url = url
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002423 if url.endswith('.html'):
2424 url = url[:-5]
Georg Brandld2f38572011-01-30 08:37:19 +00002425 try:
2426 if url in ("", "index"):
2427 title, content = html_index()
2428 elif url == "topics":
2429 title, content = html_topics()
2430 elif url == "keywords":
2431 title, content = html_keywords()
2432 elif '=' in url:
2433 op, _, url = url.partition('=')
2434 if op == "search?key":
2435 title, content = html_search(url)
2436 elif op == "getfile?key":
2437 title, content = html_getfile(url)
2438 elif op == "topic?key":
2439 # try topics first, then objects.
2440 try:
2441 title, content = html_topicpage(url)
2442 except ValueError:
2443 title, content = html_getobj(url)
2444 elif op == "get?key":
2445 # try objects first, then topics.
2446 if url in ("", "index"):
2447 title, content = html_index()
2448 else:
2449 try:
2450 title, content = html_getobj(url)
2451 except ValueError:
2452 title, content = html_topicpage(url)
2453 else:
2454 raise ValueError('bad pydoc url')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002455 else:
Georg Brandld2f38572011-01-30 08:37:19 +00002456 title, content = html_getobj(url)
2457 except Exception as exc:
2458 # Catch any errors and display them in an error page.
2459 title, content = html_error(complete_url, exc)
2460 return html.page(title, content)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002461
2462 if url.startswith('/'):
2463 url = url[1:]
2464 if content_type == 'text/css':
2465 path_here = os.path.dirname(os.path.realpath(__file__))
Georg Brandld2f38572011-01-30 08:37:19 +00002466 css_path = os.path.join(path_here, url)
2467 with open(css_path) as fp:
2468 return ''.join(fp.readlines())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002469 elif content_type == 'text/html':
2470 return get_html_page(url)
Georg Brandld2f38572011-01-30 08:37:19 +00002471 # Errors outside the url handler are caught by the server.
2472 raise TypeError('unknown content type %r for url %s' % (content_type, url))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002473
2474
2475def browse(port=0, *, open_browser=True):
2476 """Start the enhanced pydoc Web server and open a Web browser.
2477
2478 Use port '0' to start the server on an arbitrary port.
2479 Set open_browser to False to suppress opening a browser.
2480 """
2481 import webbrowser
2482 serverthread = _start_server(_url_handler, port)
2483 if serverthread.error:
2484 print(serverthread.error)
2485 return
2486 if serverthread.serving:
2487 server_help_msg = 'Server commands: [b]rowser, [q]uit'
2488 if open_browser:
2489 webbrowser.open(serverthread.url)
2490 try:
2491 print('Server ready at', serverthread.url)
2492 print(server_help_msg)
2493 while serverthread.serving:
2494 cmd = input('server> ')
2495 cmd = cmd.lower()
2496 if cmd == 'q':
2497 break
2498 elif cmd == 'b':
2499 webbrowser.open(serverthread.url)
2500 else:
2501 print(server_help_msg)
2502 except (KeyboardInterrupt, EOFError):
2503 print()
2504 finally:
2505 if serverthread.serving:
2506 serverthread.stop()
2507 print('Server stopped')
2508
2509
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002510# -------------------------------------------------- command-line interface
2511
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002512def ispath(x):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002513 return isinstance(x, str) and x.find(os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002514
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002515def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002516 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002517 import getopt
Guido van Rossum756aa932007-04-07 03:04:01 +00002518 class BadUsage(Exception): pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002519
Nick Coghlan106274b2009-11-15 23:04:33 +00002520 # Scripts don't get the current directory in their path by default
2521 # unless they are run with the '-m' switch
2522 if '' not in sys.path:
2523 scriptdir = os.path.dirname(sys.argv[0])
2524 if scriptdir in sys.path:
2525 sys.path.remove(scriptdir)
2526 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002527
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002528 try:
Victor Stinner383c3fc2011-05-25 01:35:05 +02002529 opts, args = getopt.getopt(sys.argv[1:], 'bk:p:w')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002530 writing = False
2531 start_server = False
2532 open_browser = False
2533 port = None
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002534 for opt, val in opts:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002535 if opt == '-b':
2536 start_server = True
2537 open_browser = True
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002538 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002539 apropos(val)
2540 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002541 if opt == '-p':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002542 start_server = True
2543 port = val
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002544 if opt == '-w':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002545 writing = True
2546
2547 if start_server == True:
2548 if port == None:
2549 port = 0
2550 browse(port, open_browser=open_browser)
2551 return
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002552
2553 if not args: raise BadUsage
2554 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002555 if ispath(arg) and not os.path.exists(arg):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002556 print('file %r does not exist' % arg)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002557 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002558 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002559 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002560 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002561 if writing:
2562 if ispath(arg) and os.path.isdir(arg):
2563 writedocs(arg)
2564 else:
2565 writedoc(arg)
2566 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002567 help.help(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +00002568 except ErrorDuringImport as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002569 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002570
2571 except (getopt.error, BadUsage):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002572 cmd = os.path.splitext(os.path.basename(sys.argv[0]))[0]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002573 print("""pydoc - the Python documentation tool
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002574
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002575{cmd} <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002576 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002577 Python keyword, topic, function, module, or package, or a dotted
2578 reference to a class or function within a module or module in a
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002579 package. If <name> contains a '{sep}', it is used as the path to a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002580 Python source file to document. If name is 'keywords', 'topics',
2581 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002582
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002583{cmd} -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002584 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002585
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002586{cmd} -p <port>
2587 Start an HTTP server on the given port on the local machine. Port
2588 number 0 can be used to get an arbitrary unused port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002589
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002590{cmd} -b
2591 Start an HTTP server on an arbitrary unused port and open a Web browser
2592 to interactively browse documentation. The -p option can be used with
2593 the -b option to explicitly specify the server port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002594
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002595{cmd} -w <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002596 Write out the HTML documentation for a module to a file in the current
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002597 directory. If <name> contains a '{sep}', it is treated as a filename; if
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002598 it names a directory, documentation is written for all the contents.
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002599""".format(cmd=cmd, sep=os.sep))
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002600
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002601if __name__ == '__main__':
2602 cli()