blob: ffb4f893c7cd65ee5e77728d0de4ae9e38ce05c8 [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__',
Raymond Hettinger68272942011-03-18 02:22:15 -0700169 '__version__'}:
170 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
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000221 lastupdate, result = cache.get(filename, (0, None))
222 if lastupdate < mtime:
223 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:
751 push(self.document(getattr(object, name), name, mod,
752 funcs, classes, mdict, object))
753 push('\n')
754 return attrs
755
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000756 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000757 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000758 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000759 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000760 push(msg)
761 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000762 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000763 return attrs
764
Tim Petersfa26f7c2001-09-24 08:05:11 +0000765 def spilldata(msg, attrs, predicate):
766 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000767 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000768 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000769 push(msg)
770 for name, kind, homecls, value in ok:
771 base = self.docother(getattr(object, name), name, mod)
Guido van Rossumd59da4b2007-05-22 18:11:13 +0000772 if hasattr(value, '__call__') or inspect.isdatadescriptor(value):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000773 doc = getattr(value, "__doc__", None)
774 else:
775 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000776 if doc is None:
777 push('<dl><dt>%s</dl>\n' % base)
778 else:
779 doc = self.markup(getdoc(value), self.preformat,
780 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000781 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000782 push('<dl><dt>%s%s</dl>\n' % (base, doc))
783 push('\n')
784 return attrs
785
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000786 attrs = [(name, kind, cls, value)
787 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -0700788 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000789
Tim Petersb47879b2001-09-24 04:47:19 +0000790 mdict = {}
791 for key, kind, homecls, value in attrs:
792 mdict[key] = anchor = '#' + name + '-' + key
793 value = getattr(object, key)
794 try:
795 # The value may not be hashable (e.g., a data attr with
796 # a dict or list value).
797 mdict[value] = anchor
798 except TypeError:
799 pass
800
Tim Petersfa26f7c2001-09-24 08:05:11 +0000801 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000802 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000803 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000804 else:
805 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000806 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
807
Georg Brandl1a3284e2007-12-02 09:40:06 +0000808 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000809 attrs = inherited
810 continue
811 elif thisclass is object:
812 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000813 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000814 tag = 'inherited from %s' % self.classlink(thisclass,
815 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000816 tag += ':<br>\n'
817
818 # Sort attrs by name.
Raymond Hettingerd4cb56d2008-01-30 02:55:10 +0000819 attrs.sort(key=lambda t: t[0])
Tim Petersb47879b2001-09-24 04:47:19 +0000820
821 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000822 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000823 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000824 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000825 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000826 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000827 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000828 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
829 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000830 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000831 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000832 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000833 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000834
835 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000836
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000837 if name == realname:
838 title = '<a name="%s">class <strong>%s</strong></a>' % (
839 name, realname)
840 else:
841 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
842 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000843 if bases:
844 parents = []
845 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000846 parents.append(self.classlink(base, object.__module__))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000847 title = title + '(%s)' % ', '.join(parents)
Tim Peters2306d242001-09-25 03:18:32 +0000848 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000849 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000850
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000851 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000852
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000853 def formatvalue(self, object):
854 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000855 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000856
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000857 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000858 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000859 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000860 realname = object.__name__
861 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000862 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000863 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000864 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000865 if inspect.ismethod(object):
Christian Heimesff737952007-11-27 10:40:20 +0000866 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000867 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000868 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000869 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000870 else:
Christian Heimesff737952007-11-27 10:40:20 +0000871 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000872 note = ' method of %s instance' % self.classlink(
Christian Heimesff737952007-11-27 10:40:20 +0000873 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000874 else:
875 note = ' unbound %s method' % self.classlink(imclass,mod)
Christian Heimesff737952007-11-27 10:40:20 +0000876 object = object.__func__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000877
878 if name == realname:
879 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
880 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000881 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000882 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000883 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000884 cl.__name__ + '-' + realname, realname)
885 skipdocs = 1
886 else:
887 reallink = realname
888 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
889 anchor, name, reallink)
Tim Peters4bcfa312001-09-20 06:08:24 +0000890 if inspect.isfunction(object):
Guido van Rossum2e65f892007-02-28 22:03:49 +0000891 args, varargs, kwonlyargs, kwdefaults, varkw, defaults, ann = \
892 inspect.getfullargspec(object)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000893 argspec = inspect.formatargspec(
Guido van Rossum2e65f892007-02-28 22:03:49 +0000894 args, varargs, kwonlyargs, kwdefaults, varkw, defaults, ann,
895 formatvalue=self.formatvalue,
896 formatannotation=inspect.formatannotationrelativeto(object))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000897 if realname == '<lambda>':
Tim Peters59ed4482001-10-31 04:20:26 +0000898 title = '<strong>%s</strong> <em>lambda</em> ' % name
Guido van Rossum2e65f892007-02-28 22:03:49 +0000899 # XXX lambda's won't usually have func_annotations['return']
900 # since the syntax doesn't support but it is possible.
901 # So removing parentheses isn't truly safe.
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000902 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +0000903 else:
904 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000905
Tim Peters2306d242001-09-25 03:18:32 +0000906 decl = title + argspec + (note and self.grey(
907 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000908
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000909 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000910 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000911 else:
912 doc = self.markup(
913 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000914 doc = doc and '<dd><tt>%s</tt></dd>' % doc
915 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000916
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000917 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000918 results = []
919 push = results.append
920
921 if name:
922 push('<dl><dt><strong>%s</strong></dt>\n' % name)
923 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000924 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000925 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000926 push('</dl>\n')
927
928 return ''.join(results)
929
930 def docproperty(self, object, name=None, mod=None, cl=None):
931 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000932 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000933
Tim Peters8dd7ade2001-10-18 19:56:17 +0000934 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000935 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000936 lhs = name and '<strong>%s</strong> = ' % name or ''
937 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000938
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000939 def docdata(self, object, name=None, mod=None, cl=None):
940 """Produce html documentation for a data descriptor."""
941 return self._docdescriptor(name, object, mod)
942
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000943 def index(self, dir, shadowed=None):
944 """Generate an HTML index for a directory of modules."""
945 modpkgs = []
946 if shadowed is None: shadowed = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000947 for importer, name, ispkg in pkgutil.iter_modules([dir]):
Victor Stinner4d652242011-04-12 23:41:50 +0200948 if any((0xD800 <= ord(ch) <= 0xDFFF) for ch in name):
949 # ignore a module if its name contains a surrogate character
950 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000951 modpkgs.append((name, '', ispkg, name in shadowed))
952 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000953
954 modpkgs.sort()
955 contents = self.multicolumn(modpkgs, self.modpkglink)
956 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
957
958# -------------------------------------------- text documentation generator
959
960class TextRepr(Repr):
961 """Class for safely making a text representation of a Python object."""
962 def __init__(self):
963 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000964 self.maxlist = self.maxtuple = 20
965 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000966 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000967
968 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000969 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000970 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000971 if hasattr(self, methodname):
972 return getattr(self, methodname)(x, level)
973 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000974
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000975 def repr_string(self, x, level):
976 test = cram(x, self.maxstring)
977 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000978 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000979 # Backslashes are only literal in the string and are never
980 # needed to make any special characters, so show a raw string.
981 return 'r' + testrepr[0] + test + testrepr[0]
982 return testrepr
983
Skip Montanarodf708782002-03-07 22:58:02 +0000984 repr_str = repr_string
985
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000986 def repr_instance(self, x, level):
987 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000988 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000989 except:
990 return '<%s instance>' % x.__class__.__name__
991
992class TextDoc(Doc):
993 """Formatter class for text documentation."""
994
995 # ------------------------------------------- text formatting utilities
996
997 _repr_instance = TextRepr()
998 repr = _repr_instance.repr
999
1000 def bold(self, text):
1001 """Format a string in bold by overstriking."""
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001002 return ''.join(ch + '\b' + ch for ch in text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001003
1004 def indent(self, text, prefix=' '):
1005 """Indent text by prepending a given prefix to each line."""
1006 if not text: return ''
Collin Winter72e110c2007-07-17 00:27:30 +00001007 lines = [prefix + line for line in text.split('\n')]
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001008 if lines: lines[-1] = lines[-1].rstrip()
1009 return '\n'.join(lines)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001010
1011 def section(self, title, contents):
1012 """Format a section with a given heading."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001013 clean_contents = self.indent(contents).rstrip()
1014 return self.bold(title) + '\n' + clean_contents + '\n\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001015
1016 # ---------------------------------------------- type-specific routines
1017
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001018 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001019 """Render in text a class tree as returned by inspect.getclasstree()."""
1020 result = ''
1021 for entry in tree:
1022 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001023 c, bases = entry
1024 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001025 if bases and bases != (parent,):
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001026 parents = (classname(c, modname) for c in bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001027 result = result + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001028 result = result + '\n'
1029 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001030 result = result + self.formattree(
1031 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001032 return result
1033
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001034 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001035 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001036 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001037 synop, desc = splitdoc(getdoc(object))
1038 result = self.section('NAME', name + (synop and ' - ' + synop))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001039 all = getattr(object, '__all__', None)
Skip Montanaro4997a692003-09-10 16:47:51 +00001040 docloc = self.getdocloc(object)
1041 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001042 result = result + self.section('MODULE REFERENCE', docloc + """
1043
1044The following documentation is automatically generated from the Python source
1045files. It may be incomplete, incorrect or include features that are considered
1046implementation detail and may vary between Python implementations. When in
1047doubt, consult the module reference at the location listed above.
1048""")
Skip Montanaro4997a692003-09-10 16:47:51 +00001049
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001050 if desc:
1051 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001052
1053 classes = []
1054 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001055 # if __all__ exists, believe it. Otherwise use old heuristic.
1056 if (all is not None
1057 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001058 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001059 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001060 funcs = []
1061 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001062 # if __all__ exists, believe it. Otherwise use old heuristic.
1063 if (all is not None or
1064 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001065 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001066 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001067 data = []
1068 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001069 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001070 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001071
Christian Heimes1af737c2008-01-23 08:24:23 +00001072 modpkgs = []
1073 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001074 if hasattr(object, '__path__'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001075 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Christian Heimes1af737c2008-01-23 08:24:23 +00001076 modpkgs_names.add(modname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001077 if ispkg:
1078 modpkgs.append(modname + ' (package)')
1079 else:
1080 modpkgs.append(modname)
1081
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001082 modpkgs.sort()
1083 result = result + self.section(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001084 'PACKAGE CONTENTS', '\n'.join(modpkgs))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001085
Christian Heimes1af737c2008-01-23 08:24:23 +00001086 # Detect submodules as sometimes created by C extensions
1087 submodules = []
1088 for key, value in inspect.getmembers(object, inspect.ismodule):
1089 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1090 submodules.append(key)
1091 if submodules:
1092 submodules.sort()
1093 result = result + self.section(
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001094 'SUBMODULES', '\n'.join(submodules))
Christian Heimes1af737c2008-01-23 08:24:23 +00001095
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001096 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001097 classlist = [value for key, value in classes]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001098 contents = [self.formattree(
1099 inspect.getclasstree(classlist, 1), name)]
1100 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001101 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001102 result = result + self.section('CLASSES', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001103
1104 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001105 contents = []
1106 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001107 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001108 result = result + self.section('FUNCTIONS', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001109
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001110 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001111 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001112 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001113 contents.append(self.docother(value, key, name, maxlen=70))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001114 result = result + self.section('DATA', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001115
1116 if hasattr(object, '__version__'):
1117 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001118 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001119 version = version[11:-1].strip()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001120 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001121 if hasattr(object, '__date__'):
1122 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001123 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001124 result = result + self.section('AUTHOR', str(object.__author__))
1125 if hasattr(object, '__credits__'):
1126 result = result + self.section('CREDITS', str(object.__credits__))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001127 try:
1128 file = inspect.getabsfile(object)
1129 except TypeError:
1130 file = '(built-in)'
1131 result = result + self.section('FILE', file)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001132 return result
1133
Georg Brandl9bd45f992010-12-03 09:58:38 +00001134 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001135 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001136 realname = object.__name__
1137 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001138 bases = object.__bases__
1139
Tim Petersc86f6ca2001-09-26 21:31:51 +00001140 def makename(c, m=object.__module__):
1141 return classname(c, m)
1142
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001143 if name == realname:
1144 title = 'class ' + self.bold(realname)
1145 else:
1146 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001147 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001148 parents = map(makename, bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001149 title = title + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001150
1151 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001152 contents = doc and [doc + '\n'] or []
1153 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001154
Tim Petersc86f6ca2001-09-26 21:31:51 +00001155 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001156 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001157 if len(mro) > 2:
1158 push("Method resolution order:")
1159 for base in mro:
1160 push(' ' + makename(base))
1161 push('')
1162
Tim Petersf4aad8e2001-09-24 22:40:47 +00001163 # Cute little class to pump out a horizontal rule between sections.
1164 class HorizontalRule:
1165 def __init__(self):
1166 self.needone = 0
1167 def maybe(self):
1168 if self.needone:
1169 push('-' * 70)
1170 self.needone = 1
1171 hr = HorizontalRule()
1172
Tim Peters28355492001-09-23 21:29:55 +00001173 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001174 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001175 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001176 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001177 push(msg)
1178 for name, kind, homecls, value in ok:
1179 push(self.document(getattr(object, name),
1180 name, mod, object))
1181 return attrs
1182
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001183 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001184 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001185 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001186 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001187 push(msg)
1188 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001189 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001190 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001191
Tim Petersfa26f7c2001-09-24 08:05:11 +00001192 def spilldata(msg, attrs, predicate):
1193 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001194 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001195 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001196 push(msg)
1197 for name, kind, homecls, value in ok:
Guido van Rossumd59da4b2007-05-22 18:11:13 +00001198 if hasattr(value, '__call__') or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001199 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001200 else:
1201 doc = None
Tim Peters28355492001-09-23 21:29:55 +00001202 push(self.docother(getattr(object, name),
Georg Brandl8b813db2005-10-01 16:32:31 +00001203 name, mod, maxlen=70, doc=doc) + '\n')
Tim Peters28355492001-09-23 21:29:55 +00001204 return attrs
1205
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001206 attrs = [(name, kind, cls, value)
1207 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -07001208 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001209
Tim Petersfa26f7c2001-09-24 08:05:11 +00001210 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001211 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001212 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001213 else:
1214 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001215 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1216
Georg Brandl1a3284e2007-12-02 09:40:06 +00001217 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001218 attrs = inherited
1219 continue
1220 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001221 tag = "defined here"
1222 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001223 tag = "inherited from %s" % classname(thisclass,
1224 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001225
1226 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001227 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001228
1229 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001230 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001231 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001232 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001233 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001234 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001235 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001236 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1237 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001238 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1239 lambda t: t[1] == 'data')
Tim Peters28355492001-09-23 21:29:55 +00001240 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001241 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001242
1243 contents = '\n'.join(contents)
1244 if not contents:
1245 return title + '\n'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001246 return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001247
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001248 def formatvalue(self, object):
1249 """Format an argument default value as text."""
1250 return '=' + self.repr(object)
1251
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001252 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001253 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001254 realname = object.__name__
1255 name = name or realname
1256 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001257 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001258 if inspect.ismethod(object):
Christian Heimesff737952007-11-27 10:40:20 +00001259 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001260 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001261 if imclass is not cl:
1262 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001263 else:
Christian Heimesff737952007-11-27 10:40:20 +00001264 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001265 note = ' method of %s instance' % classname(
Christian Heimesff737952007-11-27 10:40:20 +00001266 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001267 else:
1268 note = ' unbound %s method' % classname(imclass,mod)
Christian Heimesff737952007-11-27 10:40:20 +00001269 object = object.__func__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001270
1271 if name == realname:
1272 title = self.bold(realname)
1273 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001274 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001275 cl.__dict__[realname] is object):
1276 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001277 title = self.bold(name) + ' = ' + realname
Tim Peters4bcfa312001-09-20 06:08:24 +00001278 if inspect.isfunction(object):
Guido van Rossum2e65f892007-02-28 22:03:49 +00001279 args, varargs, varkw, defaults, kwonlyargs, kwdefaults, ann = \
1280 inspect.getfullargspec(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001281 argspec = inspect.formatargspec(
Guido van Rossum2e65f892007-02-28 22:03:49 +00001282 args, varargs, varkw, defaults, kwonlyargs, kwdefaults, ann,
1283 formatvalue=self.formatvalue,
1284 formatannotation=inspect.formatannotationrelativeto(object))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001285 if realname == '<lambda>':
Georg Brandl501dd0d2006-02-17 09:45:40 +00001286 title = self.bold(name) + ' lambda '
Guido van Rossum2e65f892007-02-28 22:03:49 +00001287 # XXX lambda's won't usually have func_annotations['return']
1288 # since the syntax doesn't support but it is possible.
1289 # So removing parentheses isn't truly safe.
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001290 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +00001291 else:
1292 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001293 decl = title + argspec + note
1294
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001295 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001296 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001297 else:
1298 doc = getdoc(object) or ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001299 return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001300
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001301 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001302 results = []
1303 push = results.append
1304
1305 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001306 push(self.bold(name))
1307 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001308 doc = getdoc(value) or ''
1309 if doc:
1310 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001311 push('\n')
1312 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001313
1314 def docproperty(self, object, name=None, mod=None, cl=None):
1315 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001316 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001317
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001318 def docdata(self, object, name=None, mod=None, cl=None):
1319 """Produce text documentation for a data descriptor."""
1320 return self._docdescriptor(name, object, mod)
1321
Georg Brandl8b813db2005-10-01 16:32:31 +00001322 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001323 """Produce text documentation for a data object."""
1324 repr = self.repr(object)
1325 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001326 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001327 chop = maxlen - len(line)
1328 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001329 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001330 if doc is not None:
1331 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001332 return line
1333
Georg Brandld80d5f42010-12-03 07:47:22 +00001334class _PlainTextDoc(TextDoc):
1335 """Subclass of TextDoc which overrides string styling"""
1336 def bold(self, text):
1337 return text
1338
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001339# --------------------------------------------------------- user interfaces
1340
1341def pager(text):
1342 """The first time this is called, determine what kind of pager to use."""
1343 global pager
1344 pager = getpager()
1345 pager(text)
1346
1347def getpager():
1348 """Decide what method to use for paging through text."""
Guido van Rossuma01a8b62007-05-27 09:20:14 +00001349 if not hasattr(sys.stdout, "isatty"):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001350 return plainpager
1351 if not sys.stdin.isatty() or not sys.stdout.isatty():
1352 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001353 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001354 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001355 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001356 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001357 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001358 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001359 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001360 if os.environ.get('TERM') in ('dumb', 'emacs'):
1361 return plainpager
Andrew MacIntyre54e0eab2002-03-03 03:12:30 +00001362 if sys.platform == 'win32' or sys.platform.startswith('os2'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001363 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001364 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001365 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001366
1367 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001368 (fd, filename) = tempfile.mkstemp()
1369 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001370 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001371 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001372 return lambda text: pipepager(text, 'more')
1373 else:
1374 return ttypager
1375 finally:
1376 os.unlink(filename)
1377
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001378def plain(text):
1379 """Remove boldface formatting from text."""
1380 return re.sub('.\b', '', text)
1381
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001382def pipepager(text, cmd):
1383 """Page through text by feeding it to another program."""
1384 pipe = os.popen(cmd, 'w')
1385 try:
1386 pipe.write(text)
1387 pipe.close()
1388 except IOError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001389 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001390
1391def tempfilepager(text, cmd):
1392 """Page through text by invoking a program on a temporary file."""
1393 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001394 filename = tempfile.mktemp()
1395 file = open(filename, 'w')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001396 file.write(text)
1397 file.close()
1398 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001399 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001400 finally:
1401 os.unlink(filename)
1402
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001403def ttypager(text):
1404 """Page through text on a text terminal."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001405 lines = plain(text).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001406 try:
1407 import tty
1408 fd = sys.stdin.fileno()
1409 old = tty.tcgetattr(fd)
1410 tty.setcbreak(fd)
1411 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001412 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001413 tty = None
1414 getchar = lambda: sys.stdin.readline()[:-1][:1]
1415
1416 try:
1417 r = inc = os.environ.get('LINES', 25) - 1
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001418 sys.stdout.write('\n'.join(lines[:inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001419 while lines[r:]:
1420 sys.stdout.write('-- more --')
1421 sys.stdout.flush()
1422 c = getchar()
1423
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001424 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001425 sys.stdout.write('\r \r')
1426 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001427 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001428 sys.stdout.write('\r \r' + lines[r] + '\n')
1429 r = r + 1
1430 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001431 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001432 r = r - inc - inc
1433 if r < 0: r = 0
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001434 sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001435 r = r + inc
1436
1437 finally:
1438 if tty:
1439 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1440
1441def plainpager(text):
1442 """Simply print unformatted text. This is the ultimate fallback."""
1443 sys.stdout.write(plain(text))
1444
1445def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001446 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001447 if inspect.ismodule(thing):
1448 if thing.__name__ in sys.builtin_module_names:
1449 return 'built-in module ' + thing.__name__
1450 if hasattr(thing, '__path__'):
1451 return 'package ' + thing.__name__
1452 else:
1453 return 'module ' + thing.__name__
1454 if inspect.isbuiltin(thing):
1455 return 'built-in function ' + thing.__name__
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001456 if inspect.isgetsetdescriptor(thing):
1457 return 'getset descriptor %s.%s.%s' % (
1458 thing.__objclass__.__module__, thing.__objclass__.__name__,
1459 thing.__name__)
1460 if inspect.ismemberdescriptor(thing):
1461 return 'member descriptor %s.%s.%s' % (
1462 thing.__objclass__.__module__, thing.__objclass__.__name__,
1463 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001464 if inspect.isclass(thing):
1465 return 'class ' + thing.__name__
1466 if inspect.isfunction(thing):
1467 return 'function ' + thing.__name__
1468 if inspect.ismethod(thing):
1469 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001470 return type(thing).__name__
1471
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001472def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001473 """Locate an object by name or dotted path, importing as necessary."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001474 parts = [part for part in path.split('.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001475 module, n = None, 0
1476 while n < len(parts):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001477 nextmodule = safeimport('.'.join(parts[:n+1]), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001478 if nextmodule: module, n = nextmodule, n + 1
1479 else: break
1480 if module:
1481 object = module
1482 for part in parts[n:]:
1483 try: object = getattr(object, part)
1484 except AttributeError: return None
1485 return object
1486 else:
Georg Brandl1a3284e2007-12-02 09:40:06 +00001487 if hasattr(builtins, path):
1488 return getattr(builtins, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001489
1490# --------------------------------------- interactive interpreter interface
1491
1492text = TextDoc()
Georg Brandld80d5f42010-12-03 07:47:22 +00001493plaintext = _PlainTextDoc()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001494html = HTMLDoc()
1495
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001496def resolve(thing, forceload=0):
1497 """Given an object or a path to an object, get the object and its name."""
1498 if isinstance(thing, str):
1499 object = locate(thing, forceload)
1500 if not object:
Collin Winterce36ad82007-08-30 01:19:48 +00001501 raise ImportError('no Python documentation found for %r' % thing)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001502 return object, thing
1503 else:
1504 return thing, getattr(thing, '__name__', None)
1505
Georg Brandld80d5f42010-12-03 07:47:22 +00001506def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
1507 renderer=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001508 """Render text documentation, given an object or a path to an object."""
Georg Brandld80d5f42010-12-03 07:47:22 +00001509 if renderer is None:
1510 renderer = text
Guido van Rossumd8faa362007-04-27 19:54:29 +00001511 object, name = resolve(thing, forceload)
1512 desc = describe(object)
1513 module = inspect.getmodule(object)
1514 if name and '.' in name:
1515 desc += ' in ' + name[:name.rfind('.')]
1516 elif module and module is not object:
1517 desc += ' in module ' + module.__name__
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001518
1519 if not (inspect.ismodule(object) or
Guido van Rossumd8faa362007-04-27 19:54:29 +00001520 inspect.isclass(object) or
1521 inspect.isroutine(object) or
1522 inspect.isgetsetdescriptor(object) or
1523 inspect.ismemberdescriptor(object) or
1524 isinstance(object, property)):
1525 # If the passed object is a piece of data or an instance,
1526 # document its available methods instead of its value.
1527 object = type(object)
1528 desc += ' object'
Georg Brandld80d5f42010-12-03 07:47:22 +00001529 return title % desc + '\n\n' + renderer.document(object, name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001530
Georg Brandld80d5f42010-12-03 07:47:22 +00001531def doc(thing, title='Python Library Documentation: %s', forceload=0,
1532 output=None):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001533 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001534 try:
Georg Brandld80d5f42010-12-03 07:47:22 +00001535 if output is None:
1536 pager(render_doc(thing, title, forceload))
1537 else:
1538 output.write(render_doc(thing, title, forceload, plaintext))
Guido van Rossumb940e112007-01-10 16:19:56 +00001539 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001540 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001541
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001542def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001543 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001544 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001545 object, name = resolve(thing, forceload)
1546 page = html.page(describe(object), html.document(object, name))
Georg Brandl388faac2009-04-10 08:31:48 +00001547 file = open(name + '.html', 'w', encoding='utf-8')
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001548 file.write(page)
1549 file.close()
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001550 print('wrote', name + '.html')
Guido van Rossumb940e112007-01-10 16:19:56 +00001551 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001552 print(value)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001553
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001554def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001555 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001556 if done is None: done = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001557 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1558 writedoc(modname)
1559 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001560
1561class Helper:
Georg Brandl6b38daa2008-06-01 21:05:17 +00001562
1563 # These dictionaries map a topic name to either an alias, or a tuple
1564 # (label, seealso-items). The "label" is the label of the corresponding
1565 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl5617db82009-04-27 16:28:57 +00001566 # in pydoc_data/topics.py.
Georg Brandl6b38daa2008-06-01 21:05:17 +00001567 #
1568 # CAUTION: if you change one of these dictionaries, be sure to adapt the
1569 # list of needed labels in Doc/tools/sphinxext/pyspecific.py and
Georg Brandl5617db82009-04-27 16:28:57 +00001570 # regenerate the pydoc_data/topics.py file by running
Georg Brandl6b38daa2008-06-01 21:05:17 +00001571 # make pydoc-topics
1572 # in Doc/ and copying the output file into the Lib/ directory.
1573
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001574 keywords = {
Ezio Melottib185a042011-04-28 07:42:55 +03001575 'False': '',
1576 'None': '',
1577 'True': '',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001578 'and': 'BOOLEAN',
Guido van Rossumd8faa362007-04-27 19:54:29 +00001579 'as': 'with',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001580 'assert': ('assert', ''),
1581 'break': ('break', 'while for'),
1582 'class': ('class', 'CLASSES SPECIALMETHODS'),
1583 'continue': ('continue', 'while for'),
1584 'def': ('function', ''),
1585 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001586 'elif': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001587 'else': ('else', 'while for'),
Georg Brandl0d855392008-08-30 19:53:05 +00001588 'except': 'try',
1589 'finally': 'try',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001590 'for': ('for', 'break continue while'),
Georg Brandl0d855392008-08-30 19:53:05 +00001591 'from': 'import',
Georg Brandl74abf6f2010-11-20 19:54:36 +00001592 'global': ('global', 'nonlocal NAMESPACES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001593 'if': ('if', 'TRUTHVALUE'),
1594 'import': ('import', 'MODULES'),
Georg Brandl395ed242009-09-04 08:07:32 +00001595 'in': ('in', 'SEQUENCEMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001596 'is': 'COMPARISON',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001597 'lambda': ('lambda', 'FUNCTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001598 'nonlocal': ('nonlocal', 'global NAMESPACES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001599 'not': 'BOOLEAN',
1600 'or': 'BOOLEAN',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001601 'pass': ('pass', ''),
1602 'raise': ('raise', 'EXCEPTIONS'),
1603 'return': ('return', 'FUNCTIONS'),
1604 'try': ('try', 'EXCEPTIONS'),
1605 'while': ('while', 'break continue if TRUTHVALUE'),
1606 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1607 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001608 }
Georg Brandldb7b6b92009-01-01 15:53:14 +00001609 # Either add symbols to this dictionary or to the symbols dictionary
1610 # directly: Whichever is easier. They are merged later.
1611 _symbols_inverse = {
1612 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'),
1613 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1614 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1615 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1616 'UNARY' : ('-', '~'),
1617 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1618 '^=', '<<=', '>>=', '**=', '//='),
1619 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1620 'COMPLEX' : ('j', 'J')
1621 }
1622 symbols = {
1623 '%': 'OPERATORS FORMATTING',
1624 '**': 'POWER',
1625 ',': 'TUPLES LISTS FUNCTIONS',
1626 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1627 '...': 'ELLIPSIS',
1628 ':': 'SLICINGS DICTIONARYLITERALS',
1629 '@': 'def class',
1630 '\\': 'STRINGS',
1631 '_': 'PRIVATENAMES',
1632 '__': 'PRIVATENAMES SPECIALMETHODS',
1633 '`': 'BACKQUOTES',
1634 '(': 'TUPLES FUNCTIONS CALLS',
1635 ')': 'TUPLES FUNCTIONS CALLS',
1636 '[': 'LISTS SUBSCRIPTS SLICINGS',
1637 ']': 'LISTS SUBSCRIPTS SLICINGS'
1638 }
1639 for topic, symbols_ in _symbols_inverse.items():
1640 for symbol in symbols_:
1641 topics = symbols.get(symbol, topic)
1642 if topic not in topics:
1643 topics = topics + ' ' + topic
1644 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001645
1646 topics = {
Georg Brandl6b38daa2008-06-01 21:05:17 +00001647 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1648 'FUNCTIONS CLASSES MODULES FILES inspect'),
1649 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS '
1650 'FORMATTING TYPES'),
1651 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1652 'FORMATTING': ('formatstrings', 'OPERATORS'),
1653 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1654 'FORMATTING TYPES'),
1655 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1656 'INTEGER': ('integers', 'int range'),
1657 'FLOAT': ('floating', 'float math'),
1658 'COMPLEX': ('imaginary', 'complex cmath'),
1659 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING range LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001660 'MAPPINGS': 'DICTIONARIES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001661 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1662 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1663 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1664 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001665 'FRAMEOBJECTS': 'TYPES',
1666 'TRACEBACKS': 'TYPES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001667 'NONE': ('bltin-null-object', ''),
1668 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
1669 'FILES': ('bltin-file-objects', ''),
1670 'SPECIALATTRIBUTES': ('specialattrs', ''),
1671 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1672 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001673 'PACKAGES': 'import',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001674 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1675 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1676 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1677 'LISTS DICTIONARIES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001678 'OPERATORS': 'EXPRESSIONS',
1679 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001680 'OBJECTS': ('objects', 'TYPES'),
1681 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
Georg Brandl395ed242009-09-04 08:07:32 +00001682 'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS '
1683 'NUMBERMETHODS CLASSES'),
Mark Dickinsona56c4672009-01-27 18:17:45 +00001684 'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001685 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1686 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001687 'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS '
Georg Brandl6b38daa2008-06-01 21:05:17 +00001688 'SPECIALMETHODS'),
1689 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1690 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1691 'SPECIALMETHODS'),
1692 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001693 'NAMESPACES': ('naming', 'global nonlocal ASSIGNMENT DELETION DYNAMICFEATURES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001694 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001695 'SCOPING': 'NAMESPACES',
1696 'FRAMES': 'NAMESPACES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001697 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1698 'CONVERSIONS': ('conversions', ''),
1699 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1700 'SPECIALIDENTIFIERS': ('id-classes', ''),
1701 'PRIVATENAMES': ('atom-identifiers', ''),
1702 'LITERALS': ('atom-literals', 'STRINGS NUMBERS TUPLELITERALS '
1703 'LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001704 'TUPLES': 'SEQUENCES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001705 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1706 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1707 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1708 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1709 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1710 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001711 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'),
1712 'SLICINGS': ('slicings', 'SEQUENCEMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001713 'CALLS': ('calls', 'EXPRESSIONS'),
1714 'POWER': ('power', 'EXPRESSIONS'),
1715 'UNARY': ('unary', 'EXPRESSIONS'),
1716 'BINARY': ('binary', 'EXPRESSIONS'),
1717 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1718 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1719 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1720 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001721 'ASSERTION': 'assert',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001722 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1723 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001724 'DELETION': 'del',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001725 'RETURNING': 'return',
1726 'IMPORTING': 'import',
1727 'CONDITIONAL': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001728 'LOOPING': ('compound', 'for while break continue'),
1729 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1730 'DEBUGGING': ('debugger', 'pdb'),
1731 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001732 }
1733
Georg Brandl78aa3962010-07-31 21:51:48 +00001734 def __init__(self, input=None, output=None):
1735 self._input = input
1736 self._output = output
1737
Georg Brandl76ae3972010-08-01 06:32:55 +00001738 input = property(lambda self: self._input or sys.stdin)
1739 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001740
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001741 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001742 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001743 self()
1744 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001745 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001746
Alexander Belopolsky2e733c92010-07-04 17:00:20 +00001747 _GoInteractive = object()
1748 def __call__(self, request=_GoInteractive):
1749 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001750 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001751 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001752 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001753 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001754 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001755You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001756If you want to ask for help on a particular object directly from the
1757interpreter, you can type "help(object)". Executing "help('string')"
1758has the same effect as typing a particular string at the help> prompt.
1759''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001760
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001761 def interact(self):
1762 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001763 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001764 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001765 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001766 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001767 except (KeyboardInterrupt, EOFError):
1768 break
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001769 request = replace(request, '"', '', "'", '').strip()
1770 if request.lower() in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001771 self.help(request)
1772
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001773 def getline(self, prompt):
Guido van Rossum7c086c02008-01-02 03:52:38 +00001774 """Read one line, using input() when appropriate."""
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001775 if self.input is sys.stdin:
Guido van Rossum7c086c02008-01-02 03:52:38 +00001776 return input(prompt)
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001777 else:
1778 self.output.write(prompt)
1779 self.output.flush()
1780 return self.input.readline()
1781
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001782 def help(self, request):
1783 if type(request) is type(''):
R. David Murray1f1b9d32009-05-27 20:56:59 +00001784 request = request.strip()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001785 if request == 'help': self.intro()
1786 elif request == 'keywords': self.listkeywords()
Georg Brandldb7b6b92009-01-01 15:53:14 +00001787 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001788 elif request == 'topics': self.listtopics()
1789 elif request == 'modules': self.listmodules()
1790 elif request[:8] == 'modules ':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001791 self.listmodules(request.split()[1])
Georg Brandldb7b6b92009-01-01 15:53:14 +00001792 elif request in self.symbols: self.showsymbol(request)
Ezio Melottib185a042011-04-28 07:42:55 +03001793 elif request in ['True', 'False', 'None']:
1794 # special case these keywords since they are objects too
1795 doc(eval(request), 'Help on %s:')
Raymond Hettinger54f02222002-06-01 14:18:47 +00001796 elif request in self.keywords: self.showtopic(request)
1797 elif request in self.topics: self.showtopic(request)
Georg Brandld80d5f42010-12-03 07:47:22 +00001798 elif request: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001799 elif isinstance(request, Helper): self()
Georg Brandld80d5f42010-12-03 07:47:22 +00001800 else: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001801 self.output.write('\n')
1802
1803 def intro(self):
1804 self.output.write('''
1805Welcome to Python %s! This is the online help utility.
1806
1807If this is your first time using Python, you should definitely check out
Georg Brandl86def6c2008-01-21 20:36:10 +00001808the tutorial on the Internet at http://docs.python.org/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001809
1810Enter the name of any module, keyword, or topic to get help on writing
1811Python programs and using Python modules. To quit this help utility and
1812return to the interpreter, just type "quit".
1813
1814To get a list of available modules, keywords, or topics, type "modules",
1815"keywords", or "topics". Each module also comes with a one-line summary
1816of what it does; to list the modules whose summaries contain a given word
1817such as "spam", type "modules spam".
1818''' % sys.version[:3])
1819
1820 def list(self, items, columns=4, width=80):
Guido van Rossum486364b2007-06-30 05:01:58 +00001821 items = list(sorted(items))
1822 colw = width // columns
1823 rows = (len(items) + columns - 1) // columns
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001824 for row in range(rows):
1825 for col in range(columns):
1826 i = col * rows + row
1827 if i < len(items):
1828 self.output.write(items[i])
1829 if col < columns - 1:
Guido van Rossum486364b2007-06-30 05:01:58 +00001830 self.output.write(' ' + ' ' * (colw - 1 - len(items[i])))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001831 self.output.write('\n')
1832
1833 def listkeywords(self):
1834 self.output.write('''
1835Here is a list of the Python keywords. Enter any keyword to get more help.
1836
1837''')
1838 self.list(self.keywords.keys())
1839
Georg Brandldb7b6b92009-01-01 15:53:14 +00001840 def listsymbols(self):
1841 self.output.write('''
1842Here is a list of the punctuation symbols which Python assigns special meaning
1843to. Enter any symbol to get more help.
1844
1845''')
1846 self.list(self.symbols.keys())
1847
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001848 def listtopics(self):
1849 self.output.write('''
1850Here is a list of available topics. Enter any topic name to get more help.
1851
1852''')
1853 self.list(self.topics.keys())
1854
Georg Brandldb7b6b92009-01-01 15:53:14 +00001855 def showtopic(self, topic, more_xrefs=''):
Georg Brandl6b38daa2008-06-01 21:05:17 +00001856 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001857 import pydoc_data.topics
Georg Brandl6b38daa2008-06-01 21:05:17 +00001858 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001859 self.output.write('''
Georg Brandl6b38daa2008-06-01 21:05:17 +00001860Sorry, topic and keyword documentation is not available because the
Georg Brandl5617db82009-04-27 16:28:57 +00001861module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001862''')
1863 return
1864 target = self.topics.get(topic, self.keywords.get(topic))
1865 if not target:
1866 self.output.write('no documentation found for %s\n' % repr(topic))
1867 return
1868 if type(target) is type(''):
Georg Brandldb7b6b92009-01-01 15:53:14 +00001869 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001870
Georg Brandl6b38daa2008-06-01 21:05:17 +00001871 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001872 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001873 doc = pydoc_data.topics.topics[label]
Georg Brandl6b38daa2008-06-01 21:05:17 +00001874 except KeyError:
1875 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001876 return
Georg Brandl6b38daa2008-06-01 21:05:17 +00001877 pager(doc.strip() + '\n')
Georg Brandldb7b6b92009-01-01 15:53:14 +00001878 if more_xrefs:
1879 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001880 if xrefs:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001881 import formatter
Guido van Rossum34d19282007-08-09 01:03:29 +00001882 buffer = io.StringIO()
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001883 formatter.DumbWriter(buffer).send_flowing_data(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001884 'Related help topics: ' + ', '.join(xrefs.split()) + '\n')
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001885 self.output.write('\n%s\n' % buffer.getvalue())
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001886
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001887 def _gettopic(self, topic, more_xrefs=''):
1888 """Return unbuffered tuple of (topic, xrefs).
1889
Georg Brandld2f38572011-01-30 08:37:19 +00001890 If an error occurs here, the exception is caught and displayed by
1891 the url handler.
1892
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001893 This function duplicates the showtopic method but returns its
1894 result directly so it can be formatted for display in an html page.
1895 """
1896 try:
1897 import pydoc_data.topics
1898 except ImportError:
1899 return('''
1900Sorry, topic and keyword documentation is not available because the
1901module "pydoc_data.topics" could not be found.
1902''' , '')
1903 target = self.topics.get(topic, self.keywords.get(topic))
1904 if not target:
Georg Brandld2f38572011-01-30 08:37:19 +00001905 raise ValueError('could not find topic')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001906 if isinstance(target, str):
1907 return self._gettopic(target, more_xrefs)
1908 label, xrefs = target
Georg Brandld2f38572011-01-30 08:37:19 +00001909 doc = pydoc_data.topics.topics[label]
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001910 if more_xrefs:
1911 xrefs = (xrefs or '') + ' ' + more_xrefs
1912 return doc, xrefs
1913
Georg Brandldb7b6b92009-01-01 15:53:14 +00001914 def showsymbol(self, symbol):
1915 target = self.symbols[symbol]
1916 topic, _, xrefs = target.partition(' ')
1917 self.showtopic(topic, xrefs)
1918
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001919 def listmodules(self, key=''):
1920 if key:
1921 self.output.write('''
1922Here is a list of matching modules. Enter any module name to get more help.
1923
1924''')
1925 apropos(key)
1926 else:
1927 self.output.write('''
1928Please wait a moment while I gather a list of all available modules...
1929
1930''')
1931 modules = {}
1932 def callback(path, modname, desc, modules=modules):
1933 if modname and modname[-9:] == '.__init__':
1934 modname = modname[:-9] + ' (package)'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001935 if modname.find('.') < 0:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001936 modules[modname] = 1
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001937 def onerror(modname):
1938 callback(None, modname, None)
1939 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001940 self.list(modules.keys())
1941 self.output.write('''
1942Enter any module name to get more help. Or, type "modules spam" to search
1943for modules whose descriptions contain the word "spam".
1944''')
1945
Georg Brandl78aa3962010-07-31 21:51:48 +00001946help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001947
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001948class Scanner:
1949 """A generic tree iterator."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001950 def __init__(self, roots, children, descendp):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001951 self.roots = roots[:]
1952 self.state = []
1953 self.children = children
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001954 self.descendp = descendp
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001955
1956 def next(self):
1957 if not self.state:
1958 if not self.roots:
1959 return None
1960 root = self.roots.pop(0)
1961 self.state = [(root, self.children(root))]
1962 node, children = self.state[-1]
1963 if not children:
1964 self.state.pop()
1965 return self.next()
1966 child = children.pop(0)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001967 if self.descendp(child):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001968 self.state.append((child, self.children(child)))
1969 return child
1970
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001971
1972class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001973 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001974
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001975 def run(self, callback, key=None, completer=None, onerror=None):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001976 if key: key = key.lower()
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001977 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001978 seen = {}
1979
1980 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001981 if modname != '__main__':
1982 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00001983 if key is None:
1984 callback(None, modname, '')
1985 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001986 name = __import__(modname).__doc__ or ''
1987 desc = name.split('\n')[0]
1988 name = modname + ' - ' + desc
1989 if name.lower().find(key) >= 0:
Ka-Ping Yee66246962001-04-12 11:59:50 +00001990 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001991
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001992 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001993 if self.quit:
1994 break
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001995
1996 # XXX Skipping this file is a workaround for a bug
1997 # that causes python to crash with a segfault.
1998 # http://bugs.python.org/issue9319
1999 #
2000 # TODO Remove this once the bug is fixed.
2001 if modname in {'test.badsyntax_pep3120', 'badsyntax_pep3120'}:
2002 continue
2003
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002004 if key is None:
2005 callback(None, modname, '')
2006 else:
Georg Brandl126c8792009-04-05 15:05:48 +00002007 try:
2008 loader = importer.find_module(modname)
2009 except SyntaxError:
2010 # raised by tests for bad coding cookies or BOM
2011 continue
2012 if hasattr(loader, 'get_source'):
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002013 try:
2014 source = loader.get_source(modname)
2015 except UnicodeDecodeError:
2016 if onerror:
2017 onerror(modname)
2018 continue
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002019 desc = source_synopsis(io.StringIO(source)) or ''
Georg Brandl126c8792009-04-05 15:05:48 +00002020 if hasattr(loader, 'get_filename'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002021 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002022 else:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002023 path = None
2024 else:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002025 try:
2026 module = loader.load_module(modname)
2027 except ImportError:
2028 if onerror:
2029 onerror(modname)
2030 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002031 desc = (module.__doc__ or '').splitlines()[0]
2032 path = getattr(module,'__file__',None)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002033 name = modname + ' - ' + desc
2034 if name.lower().find(key) >= 0:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002035 callback(path, modname, desc)
2036
2037 if completer:
2038 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002039
2040def apropos(key):
2041 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002042 def callback(path, modname, desc):
2043 if modname[-9:] == '.__init__':
2044 modname = modname[:-9] + ' (package)'
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002045 print(modname, desc and '- ' + desc)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002046 def onerror(modname):
2047 pass
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002048 with warnings.catch_warnings():
2049 warnings.filterwarnings('ignore') # ignore problems during import
2050 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002051
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002052# --------------------------------------- enhanced Web browser interface
2053
2054def _start_server(urlhandler, port):
2055 """Start an HTTP server thread on a specific port.
2056
2057 Start an HTML/text server thread, so HTML or text documents can be
2058 browsed dynamically and interactively with a Web browser. Example use:
2059
2060 >>> import time
2061 >>> import pydoc
2062
2063 Define a URL handler. To determine what the client is asking
2064 for, check the URL and content_type.
2065
2066 Then get or generate some text or HTML code and return it.
2067
2068 >>> def my_url_handler(url, content_type):
2069 ... text = 'the URL sent was: (%s, %s)' % (url, content_type)
2070 ... return text
2071
2072 Start server thread on port 0.
2073 If you use port 0, the server will pick a random port number.
2074 You can then use serverthread.port to get the port number.
2075
2076 >>> port = 0
2077 >>> serverthread = pydoc._start_server(my_url_handler, port)
2078
2079 Check that the server is really started. If it is, open browser
2080 and get first page. Use serverthread.url as the starting page.
2081
2082 >>> if serverthread.serving:
2083 ... import webbrowser
2084
2085 The next two lines are commented out so a browser doesn't open if
2086 doctest is run on this module.
2087
2088 #... webbrowser.open(serverthread.url)
2089 #True
2090
2091 Let the server do its thing. We just need to monitor its status.
2092 Use time.sleep so the loop doesn't hog the CPU.
2093
2094 >>> starttime = time.time()
2095 >>> timeout = 1 #seconds
2096
2097 This is a short timeout for testing purposes.
2098
2099 >>> while serverthread.serving:
2100 ... time.sleep(.01)
2101 ... if serverthread.serving and time.time() - starttime > timeout:
2102 ... serverthread.stop()
2103 ... break
2104
2105 Print any errors that may have occurred.
2106
2107 >>> print(serverthread.error)
2108 None
2109 """
2110 import http.server
2111 import email.message
2112 import select
2113 import threading
2114
2115 class DocHandler(http.server.BaseHTTPRequestHandler):
2116
2117 def do_GET(self):
2118 """Process a request from an HTML browser.
2119
2120 The URL received is in self.path.
2121 Get an HTML page from self.urlhandler and send it.
2122 """
2123 if self.path.endswith('.css'):
2124 content_type = 'text/css'
2125 else:
2126 content_type = 'text/html'
2127 self.send_response(200)
Georg Brandld2f38572011-01-30 08:37:19 +00002128 self.send_header('Content-Type', '%s; charset=UTF-8' % content_type)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002129 self.end_headers()
2130 self.wfile.write(self.urlhandler(
2131 self.path, content_type).encode('utf-8'))
2132
2133 def log_message(self, *args):
2134 # Don't log messages.
2135 pass
2136
2137 class DocServer(http.server.HTTPServer):
2138
2139 def __init__(self, port, callback):
2140 self.host = (sys.platform == 'mac') and '127.0.0.1' or 'localhost'
2141 self.address = ('', port)
2142 self.callback = callback
2143 self.base.__init__(self, self.address, self.handler)
2144 self.quit = False
2145
2146 def serve_until_quit(self):
2147 while not self.quit:
2148 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2149 if rd:
2150 self.handle_request()
Victor Stinnera3abd1d2011-01-03 16:12:39 +00002151 self.server_close()
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002152
2153 def server_activate(self):
2154 self.base.server_activate(self)
2155 if self.callback:
2156 self.callback(self)
2157
2158 class ServerThread(threading.Thread):
2159
2160 def __init__(self, urlhandler, port):
2161 self.urlhandler = urlhandler
2162 self.port = int(port)
2163 threading.Thread.__init__(self)
2164 self.serving = False
2165 self.error = None
2166
2167 def run(self):
2168 """Start the server."""
2169 try:
2170 DocServer.base = http.server.HTTPServer
2171 DocServer.handler = DocHandler
2172 DocHandler.MessageClass = email.message.Message
2173 DocHandler.urlhandler = staticmethod(self.urlhandler)
2174 docsvr = DocServer(self.port, self.ready)
2175 self.docserver = docsvr
2176 docsvr.serve_until_quit()
2177 except Exception as e:
2178 self.error = e
2179
2180 def ready(self, server):
2181 self.serving = True
2182 self.host = server.host
2183 self.port = server.server_port
2184 self.url = 'http://%s:%d/' % (self.host, self.port)
2185
2186 def stop(self):
2187 """Stop the server and this thread nicely"""
2188 self.docserver.quit = True
2189 self.serving = False
2190 self.url = None
2191
2192 thread = ServerThread(urlhandler, port)
2193 thread.start()
2194 # Wait until thread.serving is True to make sure we are
2195 # really up before returning.
2196 while not thread.error and not thread.serving:
2197 time.sleep(.01)
2198 return thread
2199
2200
2201def _url_handler(url, content_type="text/html"):
2202 """The pydoc url handler for use with the pydoc server.
2203
2204 If the content_type is 'text/css', the _pydoc.css style
2205 sheet is read and returned if it exits.
2206
2207 If the content_type is 'text/html', then the result of
2208 get_html_page(url) is returned.
2209 """
2210 class _HTMLDoc(HTMLDoc):
2211
2212 def page(self, title, contents):
2213 """Format an HTML page."""
2214 css_path = "pydoc_data/_pydoc.css"
2215 css_link = (
2216 '<link rel="stylesheet" type="text/css" href="%s">' %
2217 css_path)
2218 return '''\
2219<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Georg Brandld2f38572011-01-30 08:37:19 +00002220<html><head><title>Pydoc: %s</title>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002221<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Georg Brandld2f38572011-01-30 08:37:19 +00002222%s</head><body bgcolor="#f0f0f8">%s<div style="clear:both;padding-top:.5em;">%s</div>
2223</body></html>''' % (title, css_link, html_navbar(), contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002224
2225 def filelink(self, url, path):
2226 return '<a href="getfile?key=%s">%s</a>' % (url, path)
2227
2228
2229 html = _HTMLDoc()
2230
2231 def html_navbar():
Georg Brandld2f38572011-01-30 08:37:19 +00002232 version = html.escape("%s [%s, %s]" % (platform.python_version(),
2233 platform.python_build()[0],
2234 platform.python_compiler()))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002235 return """
2236 <div style='float:left'>
Georg Brandld2f38572011-01-30 08:37:19 +00002237 Python %s<br>%s
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002238 </div>
2239 <div style='float:right'>
2240 <div style='text-align:center'>
2241 <a href="index.html">Module Index</a>
2242 : <a href="topics.html">Topics</a>
2243 : <a href="keywords.html">Keywords</a>
2244 </div>
2245 <div>
Georg Brandld2f38572011-01-30 08:37:19 +00002246 <form action="get" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002247 <input type=text name=key size=15>
2248 <input type=submit value="Get">
Georg Brandld2f38572011-01-30 08:37:19 +00002249 </form>&nbsp;
2250 <form action="search" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002251 <input type=text name=key size=15>
2252 <input type=submit value="Search">
2253 </form>
2254 </div>
2255 </div>
Georg Brandld2f38572011-01-30 08:37:19 +00002256 """ % (version, html.escape(platform.platform(terse=True)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002257
2258 def html_index():
2259 """Module Index page."""
2260
2261 def bltinlink(name):
2262 return '<a href="%s.html">%s</a>' % (name, name)
2263
2264 heading = html.heading(
2265 '<big><big><strong>Index of Modules</strong></big></big>',
2266 '#ffffff', '#7799ee')
2267 names = [name for name in sys.builtin_module_names
2268 if name != '__main__']
2269 contents = html.multicolumn(names, bltinlink)
2270 contents = [heading, '<p>' + html.bigsection(
2271 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2272
2273 seen = {}
2274 for dir in sys.path:
2275 contents.append(html.index(dir, seen))
2276
2277 contents.append(
2278 '<p align=right><font color="#909090" face="helvetica,'
2279 'arial"><strong>pydoc</strong> by Ka-Ping Yee'
2280 '&lt;ping@lfw.org&gt;</font>')
Nick Coghlanecace282010-12-03 16:08:46 +00002281 return 'Index of Modules', ''.join(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002282
2283 def html_search(key):
2284 """Search results page."""
2285 # scan for modules
2286 search_result = []
2287
2288 def callback(path, modname, desc):
2289 if modname[-9:] == '.__init__':
2290 modname = modname[:-9] + ' (package)'
2291 search_result.append((modname, desc and '- ' + desc))
2292
2293 with warnings.catch_warnings():
2294 warnings.filterwarnings('ignore') # ignore problems during import
2295 ModuleScanner().run(callback, key)
2296
2297 # format page
2298 def bltinlink(name):
2299 return '<a href="%s.html">%s</a>' % (name, name)
2300
2301 results = []
2302 heading = html.heading(
2303 '<big><big><strong>Search Results</strong></big></big>',
2304 '#ffffff', '#7799ee')
2305 for name, desc in search_result:
2306 results.append(bltinlink(name) + desc)
2307 contents = heading + html.bigsection(
2308 'key = %s' % key, '#ffffff', '#ee77aa', '<br>'.join(results))
Nick Coghlanecace282010-12-03 16:08:46 +00002309 return 'Search Results', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002310
2311 def html_getfile(path):
2312 """Get and display a source file listing safely."""
Nick Coghlanecace282010-12-03 16:08:46 +00002313 path = path.replace('%20', ' ')
Victor Stinner91e08772011-07-05 14:30:41 +02002314 with tokenize.open(path) as fp:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002315 lines = html.escape(fp.read())
2316 body = '<pre>%s</pre>' % lines
2317 heading = html.heading(
2318 '<big><big><strong>File Listing</strong></big></big>',
2319 '#ffffff', '#7799ee')
2320 contents = heading + html.bigsection(
2321 'File: %s' % path, '#ffffff', '#ee77aa', body)
Nick Coghlanecace282010-12-03 16:08:46 +00002322 return 'getfile %s' % path, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002323
2324 def html_topics():
2325 """Index of topic texts available."""
2326
2327 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002328 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002329
2330 heading = html.heading(
2331 '<big><big><strong>INDEX</strong></big></big>',
2332 '#ffffff', '#7799ee')
2333 names = sorted(Helper.topics.keys())
2334
2335 contents = html.multicolumn(names, bltinlink)
2336 contents = heading + html.bigsection(
2337 'Topics', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002338 return 'Topics', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002339
2340 def html_keywords():
2341 """Index of keywords."""
2342 heading = html.heading(
2343 '<big><big><strong>INDEX</strong></big></big>',
2344 '#ffffff', '#7799ee')
2345 names = sorted(Helper.keywords.keys())
2346
2347 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002348 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002349
2350 contents = html.multicolumn(names, bltinlink)
2351 contents = heading + html.bigsection(
2352 'Keywords', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002353 return 'Keywords', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002354
2355 def html_topicpage(topic):
2356 """Topic or keyword help page."""
2357 buf = io.StringIO()
2358 htmlhelp = Helper(buf, buf)
2359 contents, xrefs = htmlhelp._gettopic(topic)
2360 if topic in htmlhelp.keywords:
2361 title = 'KEYWORD'
2362 else:
2363 title = 'TOPIC'
2364 heading = html.heading(
2365 '<big><big><strong>%s</strong></big></big>' % title,
2366 '#ffffff', '#7799ee')
Georg Brandld2f38572011-01-30 08:37:19 +00002367 contents = '<pre>%s</pre>' % html.markup(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002368 contents = html.bigsection(topic , '#ffffff','#ee77aa', contents)
Georg Brandld2f38572011-01-30 08:37:19 +00002369 if xrefs:
2370 xrefs = sorted(xrefs.split())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002371
Georg Brandld2f38572011-01-30 08:37:19 +00002372 def bltinlink(name):
2373 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002374
Georg Brandld2f38572011-01-30 08:37:19 +00002375 xrefs = html.multicolumn(xrefs, bltinlink)
2376 xrefs = html.section('Related help topics: ',
2377 '#ffffff', '#ee77aa', xrefs)
Nick Coghlanecace282010-12-03 16:08:46 +00002378 return ('%s %s' % (title, topic),
2379 ''.join((heading, contents, xrefs)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002380
Georg Brandld2f38572011-01-30 08:37:19 +00002381 def html_getobj(url):
2382 obj = locate(url, forceload=1)
2383 if obj is None and url != 'None':
2384 raise ValueError('could not find object')
2385 title = describe(obj)
2386 content = html.document(obj, url)
2387 return title, content
2388
2389 def html_error(url, exc):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002390 heading = html.heading(
2391 '<big><big><strong>Error</strong></big></big>',
Georg Brandld2f38572011-01-30 08:37:19 +00002392 '#ffffff', '#7799ee')
2393 contents = '<br>'.join(html.escape(line) for line in
2394 format_exception_only(type(exc), exc))
2395 contents = heading + html.bigsection(url, '#ffffff', '#bb0000',
2396 contents)
2397 return "Error - %s" % url, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002398
2399 def get_html_page(url):
2400 """Generate an HTML page for url."""
Georg Brandld2f38572011-01-30 08:37:19 +00002401 complete_url = url
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002402 if url.endswith('.html'):
2403 url = url[:-5]
Georg Brandld2f38572011-01-30 08:37:19 +00002404 try:
2405 if url in ("", "index"):
2406 title, content = html_index()
2407 elif url == "topics":
2408 title, content = html_topics()
2409 elif url == "keywords":
2410 title, content = html_keywords()
2411 elif '=' in url:
2412 op, _, url = url.partition('=')
2413 if op == "search?key":
2414 title, content = html_search(url)
2415 elif op == "getfile?key":
2416 title, content = html_getfile(url)
2417 elif op == "topic?key":
2418 # try topics first, then objects.
2419 try:
2420 title, content = html_topicpage(url)
2421 except ValueError:
2422 title, content = html_getobj(url)
2423 elif op == "get?key":
2424 # try objects first, then topics.
2425 if url in ("", "index"):
2426 title, content = html_index()
2427 else:
2428 try:
2429 title, content = html_getobj(url)
2430 except ValueError:
2431 title, content = html_topicpage(url)
2432 else:
2433 raise ValueError('bad pydoc url')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002434 else:
Georg Brandld2f38572011-01-30 08:37:19 +00002435 title, content = html_getobj(url)
2436 except Exception as exc:
2437 # Catch any errors and display them in an error page.
2438 title, content = html_error(complete_url, exc)
2439 return html.page(title, content)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002440
2441 if url.startswith('/'):
2442 url = url[1:]
2443 if content_type == 'text/css':
2444 path_here = os.path.dirname(os.path.realpath(__file__))
Georg Brandld2f38572011-01-30 08:37:19 +00002445 css_path = os.path.join(path_here, url)
2446 with open(css_path) as fp:
2447 return ''.join(fp.readlines())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002448 elif content_type == 'text/html':
2449 return get_html_page(url)
Georg Brandld2f38572011-01-30 08:37:19 +00002450 # Errors outside the url handler are caught by the server.
2451 raise TypeError('unknown content type %r for url %s' % (content_type, url))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002452
2453
2454def browse(port=0, *, open_browser=True):
2455 """Start the enhanced pydoc Web server and open a Web browser.
2456
2457 Use port '0' to start the server on an arbitrary port.
2458 Set open_browser to False to suppress opening a browser.
2459 """
2460 import webbrowser
2461 serverthread = _start_server(_url_handler, port)
2462 if serverthread.error:
2463 print(serverthread.error)
2464 return
2465 if serverthread.serving:
2466 server_help_msg = 'Server commands: [b]rowser, [q]uit'
2467 if open_browser:
2468 webbrowser.open(serverthread.url)
2469 try:
2470 print('Server ready at', serverthread.url)
2471 print(server_help_msg)
2472 while serverthread.serving:
2473 cmd = input('server> ')
2474 cmd = cmd.lower()
2475 if cmd == 'q':
2476 break
2477 elif cmd == 'b':
2478 webbrowser.open(serverthread.url)
2479 else:
2480 print(server_help_msg)
2481 except (KeyboardInterrupt, EOFError):
2482 print()
2483 finally:
2484 if serverthread.serving:
2485 serverthread.stop()
2486 print('Server stopped')
2487
2488
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002489# -------------------------------------------------- command-line interface
2490
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002491def ispath(x):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002492 return isinstance(x, str) and x.find(os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002493
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002494def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002495 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002496 import getopt
Guido van Rossum756aa932007-04-07 03:04:01 +00002497 class BadUsage(Exception): pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002498
Nick Coghlan106274b2009-11-15 23:04:33 +00002499 # Scripts don't get the current directory in their path by default
2500 # unless they are run with the '-m' switch
2501 if '' not in sys.path:
2502 scriptdir = os.path.dirname(sys.argv[0])
2503 if scriptdir in sys.path:
2504 sys.path.remove(scriptdir)
2505 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002506
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002507 try:
Victor Stinner383c3fc2011-05-25 01:35:05 +02002508 opts, args = getopt.getopt(sys.argv[1:], 'bk:p:w')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002509 writing = False
2510 start_server = False
2511 open_browser = False
2512 port = None
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002513 for opt, val in opts:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002514 if opt == '-b':
2515 start_server = True
2516 open_browser = True
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002517 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002518 apropos(val)
2519 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002520 if opt == '-p':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002521 start_server = True
2522 port = val
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002523 if opt == '-w':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002524 writing = True
2525
2526 if start_server == True:
2527 if port == None:
2528 port = 0
2529 browse(port, open_browser=open_browser)
2530 return
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002531
2532 if not args: raise BadUsage
2533 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002534 if ispath(arg) and not os.path.exists(arg):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002535 print('file %r does not exist' % arg)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002536 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002537 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002538 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002539 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002540 if writing:
2541 if ispath(arg) and os.path.isdir(arg):
2542 writedocs(arg)
2543 else:
2544 writedoc(arg)
2545 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002546 help.help(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +00002547 except ErrorDuringImport as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002548 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002549
2550 except (getopt.error, BadUsage):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002551 cmd = os.path.splitext(os.path.basename(sys.argv[0]))[0]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002552 print("""pydoc - the Python documentation tool
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002553
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002554{cmd} <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002555 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002556 Python keyword, topic, function, module, or package, or a dotted
2557 reference to a class or function within a module or module in a
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002558 package. If <name> contains a '{sep}', it is used as the path to a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002559 Python source file to document. If name is 'keywords', 'topics',
2560 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002561
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002562{cmd} -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002563 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002564
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002565{cmd} -p <port>
2566 Start an HTTP server on the given port on the local machine. Port
2567 number 0 can be used to get an arbitrary unused port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002568
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002569{cmd} -b
2570 Start an HTTP server on an arbitrary unused port and open a Web browser
2571 to interactively browse documentation. The -p option can be used with
2572 the -b option to explicitly specify the server port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002573
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002574{cmd} -w <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002575 Write out the HTML documentation for a module to a file in the current
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002576 directory. If <name> contains a '{sep}', it is treated as a filename; if
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002577 it names a directory, documentation is written for all the contents.
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002578""".format(cmd=cmd, sep=os.sep))
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002579
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002580if __name__ == '__main__':
2581 cli()