blob: 89d00a3302492ac4174782c0c655453f19b17706 [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 os
55import sys
56import builtins
57import imp
58import io
59import inspect
60import pkgutil
61import platform
62import re
63import time
64import warnings
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000065from collections import deque
Nick Coghlan7bb30b72010-12-03 09:29:11 +000066from reprlib import Repr
Georg Brandld2f38572011-01-30 08:37:19 +000067from traceback import extract_tb, format_exception_only
Nick Coghlan7bb30b72010-12-03 09:29:11 +000068
69
Ka-Ping Yeedd175342001-02-27 14:43:46 +000070# --------------------------------------------------------- common routines
71
Ka-Ping Yeedd175342001-02-27 14:43:46 +000072def pathdirs():
73 """Convert sys.path into a list of absolute, existing, unique paths."""
74 dirs = []
Ka-Ping Yee1d384632001-03-01 00:24:32 +000075 normdirs = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +000076 for dir in sys.path:
77 dir = os.path.abspath(dir or '.')
Ka-Ping Yee1d384632001-03-01 00:24:32 +000078 normdir = os.path.normcase(dir)
79 if normdir not in normdirs and os.path.isdir(dir):
Ka-Ping Yeedd175342001-02-27 14:43:46 +000080 dirs.append(dir)
Ka-Ping Yee1d384632001-03-01 00:24:32 +000081 normdirs.append(normdir)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000082 return dirs
83
84def getdoc(object):
85 """Get the doc string or comments for an object."""
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000086 result = inspect.getdoc(object) or inspect.getcomments(object)
Neal Norwitz9d72bb42007-04-17 08:48:32 +000087 return result and re.sub('^ *\n', '', result.rstrip()) or ''
Ka-Ping Yeedd175342001-02-27 14:43:46 +000088
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000089def splitdoc(doc):
90 """Split a doc string into a synopsis line (if any) and the rest."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +000091 lines = doc.strip().split('\n')
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000092 if len(lines) == 1:
93 return lines[0], ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +000094 elif len(lines) >= 2 and not lines[1].rstrip():
95 return lines[0], '\n'.join(lines[2:])
96 return '', '\n'.join(lines)
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000097
Ka-Ping Yeedd175342001-02-27 14:43:46 +000098def classname(object, modname):
99 """Get a class name and qualify it with a module name if necessary."""
100 name = object.__name__
101 if object.__module__ != modname:
102 name = object.__module__ + '.' + name
103 return name
104
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000105def isdata(object):
Georg Brandl94432422005-07-22 21:52:25 +0000106 """Check if an object is of a type that probably means it's data."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000107 return not (inspect.ismodule(object) or inspect.isclass(object) or
108 inspect.isroutine(object) or inspect.isframe(object) or
109 inspect.istraceback(object) or inspect.iscode(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000110
111def replace(text, *pairs):
112 """Do a series of global replacements on a string."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000113 while pairs:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000114 text = pairs[1].join(text.split(pairs[0]))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000115 pairs = pairs[2:]
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000116 return text
117
118def cram(text, maxlen):
119 """Omit part of a string if needed to make it fit in a maximum length."""
120 if len(text) > maxlen:
Raymond Hettingerfca3bb62002-10-21 04:44:11 +0000121 pre = max(0, (maxlen-3)//2)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000122 post = max(0, maxlen-3-pre)
123 return text[:pre] + '...' + text[len(text)-post:]
124 return text
125
Brett Cannon84601f12004-06-19 01:22:48 +0000126_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000127def stripid(text):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000128 """Remove the hexadecimal id from a Python object representation."""
Brett Cannonc6c1f472004-06-19 01:02:51 +0000129 # The behaviour of %p is implementation-dependent in terms of case.
Ezio Melotti412c95a2010-02-16 23:31:04 +0000130 return _re_stripid.sub(r'\1', text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000131
Brett Cannonc6c1f472004-06-19 01:02:51 +0000132def _is_some_method(obj):
133 return inspect.ismethod(obj) or inspect.ismethoddescriptor(obj)
Tim Peters536d2262001-09-20 05:13:38 +0000134
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000135def allmethods(cl):
136 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000137 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000138 methods[key] = 1
139 for base in cl.__bases__:
140 methods.update(allmethods(base)) # all your base are belong to us
141 for key in methods.keys():
142 methods[key] = getattr(cl, key)
143 return methods
144
Tim Petersfa26f7c2001-09-24 08:05:11 +0000145def _split_list(s, predicate):
146 """Split sequence s via predicate, and return pair ([true], [false]).
147
148 The return value is a 2-tuple of lists,
149 ([x for x in s if predicate(x)],
150 [x for x in s if not predicate(x)])
151 """
152
Tim Peters28355492001-09-23 21:29:55 +0000153 yes = []
154 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000155 for x in s:
156 if predicate(x):
157 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000158 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000159 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000160 return yes, no
161
Raymond Hettinger1103d052011-03-25 14:15:24 -0700162def visiblename(name, all=None, obj=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000163 """Decide whether to show documentation on a variable."""
164 # Certain special names are redundant.
Raymond Hettinger68272942011-03-18 02:22:15 -0700165 if name in {'__builtins__', '__doc__', '__file__', '__path__',
Barry Warsaw28a691b2010-04-17 00:19:56 +0000166 '__module__', '__name__', '__slots__', '__package__',
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000167 '__cached__', '__author__', '__credits__', '__date__',
Raymond Hettinger68272942011-03-18 02:22:15 -0700168 '__version__'}:
169 return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000170 # Private names are hidden, but special names are displayed.
171 if name.startswith('__') and name.endswith('__'): return 1
Raymond Hettinger1103d052011-03-25 14:15:24 -0700172 # Namedtuples have public fields and methods with a single leading underscore
173 if name.startswith('_') and hasattr(obj, '_fields'):
174 return True
Skip Montanaroa5616d22004-06-11 04:46:12 +0000175 if all is not None:
176 # only document that which the programmer exported in __all__
177 return name in all
178 else:
179 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000180
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000181def classify_class_attrs(object):
182 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000183 results = []
184 for (name, kind, cls, value) in inspect.classify_class_attrs(object):
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000185 if inspect.isdatadescriptor(value):
186 kind = 'data descriptor'
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000187 results.append((name, kind, cls, value))
188 return results
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000189
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000190# ----------------------------------------------------- module manipulation
191
192def ispackage(path):
193 """Guess whether a path refers to a package directory."""
194 if os.path.isdir(path):
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000195 for ext in ('.py', '.pyc', '.pyo'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000196 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000197 return True
198 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000199
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000200def source_synopsis(file):
201 line = file.readline()
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000202 while line[:1] == '#' or not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000203 line = file.readline()
204 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000205 line = line.strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000206 if line[:4] == 'r"""': line = line[1:]
207 if line[:3] == '"""':
208 line = line[3:]
209 if line[-1:] == '\\': line = line[:-1]
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000210 while not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000211 line = file.readline()
212 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000213 result = line.split('"""')[0].strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000214 else: result = None
215 return result
216
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000217def synopsis(filename, cache={}):
218 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000219 mtime = os.stat(filename).st_mtime
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000220 lastupdate, result = cache.get(filename, (0, None))
221 if lastupdate < mtime:
222 info = inspect.getmoduleinfo(filename)
Georg Brandl26fd2e12006-03-08 09:34:53 +0000223 try:
224 file = open(filename)
225 except IOError:
226 # module can't be opened, so skip it
227 return None
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000228 if info and 'b' in info[2]: # binary modules have to be imported
229 try: module = imp.load_module('__temp__', file, filename, info[1:])
230 except: return None
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000231 result = (module.__doc__ or '').splitlines()[0]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000232 del sys.modules['__temp__']
233 else: # text modules can be directly examined
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000234 result = source_synopsis(file)
235 file.close()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000236 cache[filename] = (mtime, result)
237 return result
238
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000239class ErrorDuringImport(Exception):
240 """Errors that occurred while trying to import something to document it."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000241 def __init__(self, filename, exc_info):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000242 self.filename = filename
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000243 self.exc, self.value, self.tb = exc_info
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000244
245 def __str__(self):
Guido van Rossuma01a8b62007-05-27 09:20:14 +0000246 exc = self.exc.__name__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000247 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000248
249def importfile(path):
250 """Import a Python source file or compiled file given its path."""
251 magic = imp.get_magic()
252 file = open(path, 'r')
253 if file.read(len(magic)) == magic:
254 kind = imp.PY_COMPILED
255 else:
256 kind = imp.PY_SOURCE
257 file.close()
258 filename = os.path.basename(path)
259 name, ext = os.path.splitext(filename)
260 file = open(path, 'r')
261 try:
262 module = imp.load_module(name, file, path, (ext, 'r', kind))
263 except:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000264 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000265 file.close()
266 return module
267
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000268def safeimport(path, forceload=0, cache={}):
269 """Import a module; handle errors; return None if the module isn't found.
270
271 If the module *is* found but an exception occurs, it's wrapped in an
272 ErrorDuringImport exception and reraised. Unlike __import__, if a
273 package path is specified, the module at the end of the path is returned,
274 not the package at the beginning. If the optional 'forceload' argument
275 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000276 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000277 # If forceload is 1 and the module has been previously loaded from
278 # disk, we always have to reload the module. Checking the file's
279 # mtime isn't good enough (e.g. the module could contain a class
280 # that inherits from another module that has changed).
281 if forceload and path in sys.modules:
282 if path not in sys.builtin_module_names:
Guido van Rossume7ba4952007-06-06 23:52:48 +0000283 # Remove the module from sys.modules and re-import to try
284 # and avoid problems with partially loaded modules.
285 # Also remove any submodules because they won't appear
286 # in the newly loaded module's namespace if they're already
287 # in sys.modules.
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000288 subs = [m for m in sys.modules if m.startswith(path + '.')]
289 for key in [path] + subs:
290 # Prevent garbage collection.
291 cache[key] = sys.modules[key]
292 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000293 module = __import__(path)
294 except:
295 # Did the error occur before or after the module was found?
296 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000297 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000298 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000299 raise ErrorDuringImport(sys.modules[path].__file__, info)
300 elif exc is SyntaxError:
301 # A SyntaxError occurred before we could execute the module.
302 raise ErrorDuringImport(value.filename, info)
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000303 elif exc is ImportError and extract_tb(tb)[-1][2]=='safeimport':
Benjamin Peterson0289b152009-06-28 17:22:03 +0000304 # The import error occurred directly in this function,
305 # which means there is no such module in the path.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000306 return None
307 else:
308 # Some other error occurred during the importing process.
309 raise ErrorDuringImport(path, sys.exc_info())
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000310 for part in path.split('.')[1:]:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000311 try: module = getattr(module, part)
312 except AttributeError: return None
313 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000314
315# ---------------------------------------------------- formatter base class
316
317class Doc:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000318
319 PYTHONDOCS = os.environ.get("PYTHONDOCS",
320 "http://docs.python.org/%d.%d/library"
321 % sys.version_info[:2])
322
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000323 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000324 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000325 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000326 # 'try' clause is to attempt to handle the possibility that inspect
327 # identifies something in a way that pydoc itself has issues handling;
328 # think 'super' and how it is a descriptor (which raises the exception
329 # by lacking a __name__ attribute) and an instance.
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000330 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
331 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000332 try:
333 if inspect.ismodule(object): return self.docmodule(*args)
334 if inspect.isclass(object): return self.docclass(*args)
335 if inspect.isroutine(object): return self.docroutine(*args)
336 except AttributeError:
337 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000338 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000339 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000340
341 def fail(self, object, name=None, *args):
342 """Raise an exception for unimplemented types."""
343 message = "don't know how to document object%s of type %s" % (
344 name and ' ' + repr(name), type(object).__name__)
Collin Winterce36ad82007-08-30 01:19:48 +0000345 raise TypeError(message)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000346
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000347 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000348
Skip Montanaro4997a692003-09-10 16:47:51 +0000349 def getdocloc(self, object):
350 """Return the location of module docs or None"""
351
352 try:
353 file = inspect.getabsfile(object)
354 except TypeError:
355 file = '(built-in)'
356
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000357 docloc = os.environ.get("PYTHONDOCS", self.PYTHONDOCS)
358
Skip Montanaro4997a692003-09-10 16:47:51 +0000359 basedir = os.path.join(sys.exec_prefix, "lib",
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000360 "python%d.%d" % sys.version_info[:2])
Skip Montanaro4997a692003-09-10 16:47:51 +0000361 if (isinstance(object, type(os)) and
362 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
363 'marshal', 'posix', 'signal', 'sys',
Georg Brandl2067bfd2008-05-25 13:05:15 +0000364 '_thread', 'zipimport') or
Skip Montanaro4997a692003-09-10 16:47:51 +0000365 (file.startswith(basedir) and
Brian Curtin49c284c2010-03-31 03:19:28 +0000366 not file.startswith(os.path.join(basedir, 'site-packages')))) and
Brian Curtinedef05b2010-04-01 04:05:25 +0000367 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
Skip Montanaro4997a692003-09-10 16:47:51 +0000368 if docloc.startswith("http://"):
Georg Brandl86def6c2008-01-21 20:36:10 +0000369 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
Skip Montanaro4997a692003-09-10 16:47:51 +0000370 else:
Georg Brandl86def6c2008-01-21 20:36:10 +0000371 docloc = os.path.join(docloc, object.__name__ + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000372 else:
373 docloc = None
374 return docloc
375
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000376# -------------------------------------------- HTML documentation generator
377
378class HTMLRepr(Repr):
379 """Class for safely making an HTML representation of a Python object."""
380 def __init__(self):
381 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000382 self.maxlist = self.maxtuple = 20
383 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000384 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000385
386 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000387 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000388
389 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000390 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000391
392 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000393 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000394 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000395 if hasattr(self, methodname):
396 return getattr(self, methodname)(x, level)
397 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000398
399 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000400 test = cram(x, self.maxstring)
401 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000402 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000403 # Backslashes are only literal in the string and are never
404 # needed to make any special characters, so show a raw string.
405 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000406 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000407 r'<font color="#c040c0">\1</font>',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000408 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000409
Skip Montanarodf708782002-03-07 22:58:02 +0000410 repr_str = repr_string
411
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000412 def repr_instance(self, x, level):
413 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000414 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000415 except:
416 return self.escape('<%s instance>' % x.__class__.__name__)
417
418 repr_unicode = repr_string
419
420class HTMLDoc(Doc):
421 """Formatter class for HTML documentation."""
422
423 # ------------------------------------------- HTML formatting utilities
424
425 _repr_instance = HTMLRepr()
426 repr = _repr_instance.repr
427 escape = _repr_instance.escape
428
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000429 def page(self, title, contents):
430 """Format an HTML page."""
Georg Brandl388faac2009-04-10 08:31:48 +0000431 return '''\
Georg Brandle6066942009-04-10 08:28:28 +0000432<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000433<html><head><title>Python: %s</title>
Georg Brandl388faac2009-04-10 08:31:48 +0000434<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000435</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000436%s
437</body></html>''' % (title, contents)
438
439 def heading(self, title, fgcol, bgcol, extras=''):
440 """Format a page heading."""
441 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000442<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000443<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000444<td valign=bottom>&nbsp;<br>
445<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000446><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000447><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000448 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
449
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000450 def section(self, title, fgcol, bgcol, contents, width=6,
451 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000452 """Format a section with a heading."""
453 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000454 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000455 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000456<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000457<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000458<td colspan=3 valign=bottom>&nbsp;<br>
459<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000460 ''' % (bgcol, fgcol, title)
461 if prelude:
462 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000463<tr bgcolor="%s"><td rowspan=2>%s</td>
464<td colspan=2>%s</td></tr>
465<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
466 else:
467 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000468<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000469
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000470 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000471
472 def bigsection(self, title, *args):
473 """Format a section with a big heading."""
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000474 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000475 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000476
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000477 def preformat(self, text):
478 """Format literal preformatted text."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000479 text = self.escape(text.expandtabs())
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000480 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
481 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000482
483 def multicolumn(self, list, format, cols=4):
484 """Format a list of items into a multi-column list."""
485 result = ''
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000486 rows = (len(list)+cols-1)//cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000487 for col in range(cols):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000488 result = result + '<td width="%d%%" valign=top>' % (100//cols)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000489 for i in range(rows*col, rows*col+rows):
490 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000491 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000492 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000493 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000494
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000495 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000496
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000497 def namelink(self, name, *dicts):
498 """Make a link for an identifier, given name-to-URL mappings."""
499 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000500 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000501 return '<a href="%s">%s</a>' % (dict[name], name)
502 return name
503
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000504 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000505 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000506 name, module = object.__name__, sys.modules.get(object.__module__)
507 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000508 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000509 module.__name__, name, classname(object, modname))
510 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000511
512 def modulelink(self, object):
513 """Make a link for a module."""
514 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
515
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000516 def modpkglink(self, modpkginfo):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000517 """Make a link for a module or package to display in an index."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000518 name, path, ispackage, shadowed = modpkginfo
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000519 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000520 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000521 if path:
522 url = '%s.%s.html' % (path, name)
523 else:
524 url = '%s.html' % name
525 if ispackage:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000526 text = '<strong>%s</strong>&nbsp;(package)' % name
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000527 else:
528 text = name
529 return '<a href="%s">%s</a>' % (url, text)
530
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000531 def filelink(self, url, path):
532 """Make a link to source file."""
533 return '<a href="file:%s">%s</a>' % (url, path)
534
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000535 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
536 """Mark up some plain text, given a context of symbols to look for.
537 Each context dictionary maps object names to anchor names."""
538 escape = escape or self.escape
539 results = []
540 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000541 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
542 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000543 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000544 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000545 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000546 match = pattern.search(text, here)
547 if not match: break
548 start, end = match.span()
549 results.append(escape(text[here:start]))
550
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000551 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000552 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000553 url = escape(all).replace('"', '&quot;')
554 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000555 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000556 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
557 results.append('<a href="%s">%s</a>' % (url, escape(all)))
558 elif pep:
Christian Heimes2202f872008-02-06 14:31:34 +0000559 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000560 results.append('<a href="%s">%s</a>' % (url, escape(all)))
561 elif text[end:end+1] == '(':
562 results.append(self.namelink(name, methods, funcs, classes))
563 elif selfdot:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000564 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000565 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000566 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000567 here = end
568 results.append(escape(text[here:]))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000569 return ''.join(results)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000570
571 # ---------------------------------------------- type-specific routines
572
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000573 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000574 """Produce HTML for a class tree as given by inspect.getclasstree()."""
575 result = ''
576 for entry in tree:
577 if type(entry) is type(()):
578 c, bases = entry
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000579 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000580 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000581 if bases and bases != (parent,):
582 parents = []
583 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000584 parents.append(self.classlink(base, modname))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000585 result = result + '(' + ', '.join(parents) + ')'
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000586 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000587 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000588 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000589 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000590 return '<dl>\n%s</dl>\n' % result
591
Tim Peters8dd7ade2001-10-18 19:56:17 +0000592 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000593 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000594 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000595 try:
596 all = object.__all__
597 except AttributeError:
598 all = None
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000599 parts = name.split('.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000600 links = []
601 for i in range(len(parts)-1):
602 links.append(
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000603 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000604 ('.'.join(parts[:i+1]), parts[i]))
605 linkedname = '.'.join(links + parts[-1:])
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000606 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000607 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000608 path = inspect.getabsfile(object)
Ka-Ping Yee6191a232001-04-13 15:00:27 +0000609 url = path
610 if sys.platform == 'win32':
611 import nturl2path
612 url = nturl2path.pathname2url(path)
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000613 filelink = self.filelink(url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000614 except TypeError:
615 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000616 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000617 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000618 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000619 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000620 version = version[11:-1].strip()
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000621 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000622 if hasattr(object, '__date__'):
623 info.append(self.escape(str(object.__date__)))
624 if info:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000625 head = head + ' (%s)' % ', '.join(info)
Skip Montanaro4997a692003-09-10 16:47:51 +0000626 docloc = self.getdocloc(object)
627 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000628 docloc = '<br><a href="%(docloc)s">Module Reference</a>' % locals()
Skip Montanaro4997a692003-09-10 16:47:51 +0000629 else:
630 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000631 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000632 head, '#ffffff', '#7799ee',
633 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000634
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000635 modules = inspect.getmembers(object, inspect.ismodule)
636
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000637 classes, cdict = [], {}
638 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000639 # if __all__ exists, believe it. Otherwise use old heuristic.
640 if (all is not None or
641 (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700642 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000643 classes.append((key, value))
644 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000645 for key, value in classes:
646 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000647 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000648 module = sys.modules.get(modname)
649 if modname != name and module and hasattr(module, key):
650 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000651 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000652 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000653 funcs, fdict = [], {}
654 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000655 # if __all__ exists, believe it. Otherwise use old heuristic.
656 if (all is not None or
657 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700658 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000659 funcs.append((key, value))
660 fdict[key] = '#-' + key
661 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000662 data = []
663 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700664 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000665 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000666
667 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
668 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000669 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000670
671 if hasattr(object, '__path__'):
672 modpkgs = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000673 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
674 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000675 modpkgs.sort()
676 contents = self.multicolumn(modpkgs, self.modpkglink)
677 result = result + self.bigsection(
678 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000679 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000680 contents = self.multicolumn(
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000681 modules, lambda t: self.modulelink(t[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000682 result = result + self.bigsection(
Christian Heimes7131fd92008-02-19 14:21:46 +0000683 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000684
685 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000686 classlist = [value for (key, value) in classes]
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000687 contents = [
688 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000689 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000690 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000691 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000692 'Classes', '#ffffff', '#ee77aa', ' '.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000693 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000694 contents = []
695 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000696 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000697 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000698 'Functions', '#ffffff', '#eeaa77', ' '.join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000699 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000700 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000701 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000702 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000703 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000704 'Data', '#ffffff', '#55aa55', '<br>\n'.join(contents))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000705 if hasattr(object, '__author__'):
706 contents = self.markup(str(object.__author__), self.preformat)
707 result = result + self.bigsection(
708 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000709 if hasattr(object, '__credits__'):
710 contents = self.markup(str(object.__credits__), self.preformat)
711 result = result + self.bigsection(
712 'Credits', '#ffffff', '#7799ee', contents)
713
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000714 return result
715
Tim Peters8dd7ade2001-10-18 19:56:17 +0000716 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
717 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000718 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000719 realname = object.__name__
720 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000721 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000722
Tim Petersb47879b2001-09-24 04:47:19 +0000723 contents = []
724 push = contents.append
725
Tim Petersfa26f7c2001-09-24 08:05:11 +0000726 # Cute little class to pump out a horizontal rule between sections.
727 class HorizontalRule:
728 def __init__(self):
729 self.needone = 0
730 def maybe(self):
731 if self.needone:
732 push('<hr>\n')
733 self.needone = 1
734 hr = HorizontalRule()
735
Tim Petersc86f6ca2001-09-26 21:31:51 +0000736 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000737 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000738 if len(mro) > 2:
739 hr.maybe()
740 push('<dl><dt>Method resolution order:</dt>\n')
741 for base in mro:
742 push('<dd>%s</dd>\n' % self.classlink(base,
743 object.__module__))
744 push('</dl>\n')
745
Tim Petersb47879b2001-09-24 04:47:19 +0000746 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000747 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000748 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000749 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000750 push(msg)
751 for name, kind, homecls, value in ok:
752 push(self.document(getattr(object, name), name, mod,
753 funcs, classes, mdict, object))
754 push('\n')
755 return attrs
756
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000757 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000758 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000759 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000760 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000761 push(msg)
762 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000763 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000764 return attrs
765
Tim Petersfa26f7c2001-09-24 08:05:11 +0000766 def spilldata(msg, attrs, predicate):
767 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000768 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000769 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000770 push(msg)
771 for name, kind, homecls, value in ok:
772 base = self.docother(getattr(object, name), name, mod)
Guido van Rossumd59da4b2007-05-22 18:11:13 +0000773 if hasattr(value, '__call__') or inspect.isdatadescriptor(value):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000774 doc = getattr(value, "__doc__", None)
775 else:
776 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000777 if doc is None:
778 push('<dl><dt>%s</dl>\n' % base)
779 else:
780 doc = self.markup(getdoc(value), self.preformat,
781 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000782 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000783 push('<dl><dt>%s%s</dl>\n' % (base, doc))
784 push('\n')
785 return attrs
786
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000787 attrs = [(name, kind, cls, value)
788 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -0700789 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000790
Tim Petersb47879b2001-09-24 04:47:19 +0000791 mdict = {}
792 for key, kind, homecls, value in attrs:
793 mdict[key] = anchor = '#' + name + '-' + key
794 value = getattr(object, key)
795 try:
796 # The value may not be hashable (e.g., a data attr with
797 # a dict or list value).
798 mdict[value] = anchor
799 except TypeError:
800 pass
801
Tim Petersfa26f7c2001-09-24 08:05:11 +0000802 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000803 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000804 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000805 else:
806 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000807 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
808
Georg Brandl1a3284e2007-12-02 09:40:06 +0000809 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000810 attrs = inherited
811 continue
812 elif thisclass is object:
813 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000814 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000815 tag = 'inherited from %s' % self.classlink(thisclass,
816 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000817 tag += ':<br>\n'
818
819 # Sort attrs by name.
Raymond Hettingerd4cb56d2008-01-30 02:55:10 +0000820 attrs.sort(key=lambda t: t[0])
Tim Petersb47879b2001-09-24 04:47:19 +0000821
822 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000823 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000824 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000825 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000826 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000827 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000828 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000829 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
830 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000831 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000832 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000833 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000834 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000835
836 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000837
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000838 if name == realname:
839 title = '<a name="%s">class <strong>%s</strong></a>' % (
840 name, realname)
841 else:
842 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
843 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000844 if bases:
845 parents = []
846 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000847 parents.append(self.classlink(base, object.__module__))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000848 title = title + '(%s)' % ', '.join(parents)
Tim Peters2306d242001-09-25 03:18:32 +0000849 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000850 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000851
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000852 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000853
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000854 def formatvalue(self, object):
855 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000856 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000857
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000858 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000859 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000860 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000861 realname = object.__name__
862 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000863 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000864 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000865 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000866 if inspect.ismethod(object):
Christian Heimesff737952007-11-27 10:40:20 +0000867 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000868 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000869 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000870 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000871 else:
Christian Heimesff737952007-11-27 10:40:20 +0000872 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000873 note = ' method of %s instance' % self.classlink(
Christian Heimesff737952007-11-27 10:40:20 +0000874 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000875 else:
876 note = ' unbound %s method' % self.classlink(imclass,mod)
Christian Heimesff737952007-11-27 10:40:20 +0000877 object = object.__func__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000878
879 if name == realname:
880 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
881 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000882 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000883 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000884 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000885 cl.__name__ + '-' + realname, realname)
886 skipdocs = 1
887 else:
888 reallink = realname
889 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
890 anchor, name, reallink)
Tim Peters4bcfa312001-09-20 06:08:24 +0000891 if inspect.isfunction(object):
Guido van Rossum2e65f892007-02-28 22:03:49 +0000892 args, varargs, kwonlyargs, kwdefaults, varkw, defaults, ann = \
893 inspect.getfullargspec(object)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000894 argspec = inspect.formatargspec(
Guido van Rossum2e65f892007-02-28 22:03:49 +0000895 args, varargs, kwonlyargs, kwdefaults, varkw, defaults, ann,
896 formatvalue=self.formatvalue,
897 formatannotation=inspect.formatannotationrelativeto(object))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000898 if realname == '<lambda>':
Tim Peters59ed4482001-10-31 04:20:26 +0000899 title = '<strong>%s</strong> <em>lambda</em> ' % name
Guido van Rossum2e65f892007-02-28 22:03:49 +0000900 # XXX lambda's won't usually have func_annotations['return']
901 # since the syntax doesn't support but it is possible.
902 # So removing parentheses isn't truly safe.
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000903 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +0000904 else:
905 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000906
Tim Peters2306d242001-09-25 03:18:32 +0000907 decl = title + argspec + (note and self.grey(
908 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000909
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000910 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000911 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000912 else:
913 doc = self.markup(
914 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000915 doc = doc and '<dd><tt>%s</tt></dd>' % doc
916 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000917
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000918 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000919 results = []
920 push = results.append
921
922 if name:
923 push('<dl><dt><strong>%s</strong></dt>\n' % name)
924 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000925 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000926 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000927 push('</dl>\n')
928
929 return ''.join(results)
930
931 def docproperty(self, object, name=None, mod=None, cl=None):
932 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000933 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000934
Tim Peters8dd7ade2001-10-18 19:56:17 +0000935 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000936 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000937 lhs = name and '<strong>%s</strong> = ' % name or ''
938 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000939
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000940 def docdata(self, object, name=None, mod=None, cl=None):
941 """Produce html documentation for a data descriptor."""
942 return self._docdescriptor(name, object, mod)
943
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000944 def index(self, dir, shadowed=None):
945 """Generate an HTML index for a directory of modules."""
946 modpkgs = []
947 if shadowed is None: shadowed = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000948 for importer, name, ispkg in pkgutil.iter_modules([dir]):
Victor Stinner4d652242011-04-12 23:41:50 +0200949 if any((0xD800 <= ord(ch) <= 0xDFFF) for ch in name):
950 # ignore a module if its name contains a surrogate character
951 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000952 modpkgs.append((name, '', ispkg, name in shadowed))
953 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000954
955 modpkgs.sort()
956 contents = self.multicolumn(modpkgs, self.modpkglink)
957 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
958
959# -------------------------------------------- text documentation generator
960
961class TextRepr(Repr):
962 """Class for safely making a text representation of a Python object."""
963 def __init__(self):
964 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000965 self.maxlist = self.maxtuple = 20
966 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000967 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000968
969 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000970 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000971 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000972 if hasattr(self, methodname):
973 return getattr(self, methodname)(x, level)
974 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000975
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000976 def repr_string(self, x, level):
977 test = cram(x, self.maxstring)
978 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000979 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000980 # Backslashes are only literal in the string and are never
981 # needed to make any special characters, so show a raw string.
982 return 'r' + testrepr[0] + test + testrepr[0]
983 return testrepr
984
Skip Montanarodf708782002-03-07 22:58:02 +0000985 repr_str = repr_string
986
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000987 def repr_instance(self, x, level):
988 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000989 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000990 except:
991 return '<%s instance>' % x.__class__.__name__
992
993class TextDoc(Doc):
994 """Formatter class for text documentation."""
995
996 # ------------------------------------------- text formatting utilities
997
998 _repr_instance = TextRepr()
999 repr = _repr_instance.repr
1000
1001 def bold(self, text):
1002 """Format a string in bold by overstriking."""
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001003 return ''.join(ch + '\b' + ch for ch in text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001004
1005 def indent(self, text, prefix=' '):
1006 """Indent text by prepending a given prefix to each line."""
1007 if not text: return ''
Collin Winter72e110c2007-07-17 00:27:30 +00001008 lines = [prefix + line for line in text.split('\n')]
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001009 if lines: lines[-1] = lines[-1].rstrip()
1010 return '\n'.join(lines)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001011
1012 def section(self, title, contents):
1013 """Format a section with a given heading."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001014 clean_contents = self.indent(contents).rstrip()
1015 return self.bold(title) + '\n' + clean_contents + '\n\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001016
1017 # ---------------------------------------------- type-specific routines
1018
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001019 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001020 """Render in text a class tree as returned by inspect.getclasstree()."""
1021 result = ''
1022 for entry in tree:
1023 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001024 c, bases = entry
1025 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001026 if bases and bases != (parent,):
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001027 parents = (classname(c, modname) for c in bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001028 result = result + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001029 result = result + '\n'
1030 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001031 result = result + self.formattree(
1032 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001033 return result
1034
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001035 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001036 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001037 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001038 synop, desc = splitdoc(getdoc(object))
1039 result = self.section('NAME', name + (synop and ' - ' + synop))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001040 all = getattr(object, '__all__', None)
Skip Montanaro4997a692003-09-10 16:47:51 +00001041 docloc = self.getdocloc(object)
1042 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001043 result = result + self.section('MODULE REFERENCE', docloc + """
1044
1045The following documentation is automatically generated from the Python source
1046files. It may be incomplete, incorrect or include features that are considered
1047implementation detail and may vary between Python implementations. When in
1048doubt, consult the module reference at the location listed above.
1049""")
Skip Montanaro4997a692003-09-10 16:47:51 +00001050
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001051 if desc:
1052 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001053
1054 classes = []
1055 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001056 # if __all__ exists, believe it. Otherwise use old heuristic.
1057 if (all is not None
1058 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001059 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001060 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001061 funcs = []
1062 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001063 # if __all__ exists, believe it. Otherwise use old heuristic.
1064 if (all is not None or
1065 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001066 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001067 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001068 data = []
1069 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001070 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001071 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001072
Christian Heimes1af737c2008-01-23 08:24:23 +00001073 modpkgs = []
1074 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001075 if hasattr(object, '__path__'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001076 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Christian Heimes1af737c2008-01-23 08:24:23 +00001077 modpkgs_names.add(modname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001078 if ispkg:
1079 modpkgs.append(modname + ' (package)')
1080 else:
1081 modpkgs.append(modname)
1082
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001083 modpkgs.sort()
1084 result = result + self.section(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001085 'PACKAGE CONTENTS', '\n'.join(modpkgs))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001086
Christian Heimes1af737c2008-01-23 08:24:23 +00001087 # Detect submodules as sometimes created by C extensions
1088 submodules = []
1089 for key, value in inspect.getmembers(object, inspect.ismodule):
1090 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1091 submodules.append(key)
1092 if submodules:
1093 submodules.sort()
1094 result = result + self.section(
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001095 'SUBMODULES', '\n'.join(submodules))
Christian Heimes1af737c2008-01-23 08:24:23 +00001096
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001097 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001098 classlist = [value for key, value in classes]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001099 contents = [self.formattree(
1100 inspect.getclasstree(classlist, 1), name)]
1101 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001102 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001103 result = result + self.section('CLASSES', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001104
1105 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001106 contents = []
1107 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001108 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001109 result = result + self.section('FUNCTIONS', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001110
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001111 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001112 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001113 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001114 contents.append(self.docother(value, key, name, maxlen=70))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001115 result = result + self.section('DATA', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001116
1117 if hasattr(object, '__version__'):
1118 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001119 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001120 version = version[11:-1].strip()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001121 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001122 if hasattr(object, '__date__'):
1123 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001124 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001125 result = result + self.section('AUTHOR', str(object.__author__))
1126 if hasattr(object, '__credits__'):
1127 result = result + self.section('CREDITS', str(object.__credits__))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001128 try:
1129 file = inspect.getabsfile(object)
1130 except TypeError:
1131 file = '(built-in)'
1132 result = result + self.section('FILE', file)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001133 return result
1134
Georg Brandl9bd45f992010-12-03 09:58:38 +00001135 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001136 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001137 realname = object.__name__
1138 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001139 bases = object.__bases__
1140
Tim Petersc86f6ca2001-09-26 21:31:51 +00001141 def makename(c, m=object.__module__):
1142 return classname(c, m)
1143
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001144 if name == realname:
1145 title = 'class ' + self.bold(realname)
1146 else:
1147 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001148 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001149 parents = map(makename, bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001150 title = title + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001151
1152 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001153 contents = doc and [doc + '\n'] or []
1154 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001155
Tim Petersc86f6ca2001-09-26 21:31:51 +00001156 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001157 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001158 if len(mro) > 2:
1159 push("Method resolution order:")
1160 for base in mro:
1161 push(' ' + makename(base))
1162 push('')
1163
Tim Petersf4aad8e2001-09-24 22:40:47 +00001164 # Cute little class to pump out a horizontal rule between sections.
1165 class HorizontalRule:
1166 def __init__(self):
1167 self.needone = 0
1168 def maybe(self):
1169 if self.needone:
1170 push('-' * 70)
1171 self.needone = 1
1172 hr = HorizontalRule()
1173
Tim Peters28355492001-09-23 21:29:55 +00001174 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001175 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001176 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001177 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001178 push(msg)
1179 for name, kind, homecls, value in ok:
1180 push(self.document(getattr(object, name),
1181 name, mod, object))
1182 return attrs
1183
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001184 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001185 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001186 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001187 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001188 push(msg)
1189 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001190 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001191 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001192
Tim Petersfa26f7c2001-09-24 08:05:11 +00001193 def spilldata(msg, attrs, predicate):
1194 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001195 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001196 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001197 push(msg)
1198 for name, kind, homecls, value in ok:
Guido van Rossumd59da4b2007-05-22 18:11:13 +00001199 if hasattr(value, '__call__') or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001200 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001201 else:
1202 doc = None
Tim Peters28355492001-09-23 21:29:55 +00001203 push(self.docother(getattr(object, name),
Georg Brandl8b813db2005-10-01 16:32:31 +00001204 name, mod, maxlen=70, doc=doc) + '\n')
Tim Peters28355492001-09-23 21:29:55 +00001205 return attrs
1206
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001207 attrs = [(name, kind, cls, value)
1208 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -07001209 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001210
Tim Petersfa26f7c2001-09-24 08:05:11 +00001211 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001212 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001213 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001214 else:
1215 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001216 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1217
Georg Brandl1a3284e2007-12-02 09:40:06 +00001218 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001219 attrs = inherited
1220 continue
1221 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001222 tag = "defined here"
1223 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001224 tag = "inherited from %s" % classname(thisclass,
1225 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001226
1227 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001228 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001229
1230 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001231 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001232 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001233 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001234 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001235 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001236 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001237 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1238 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001239 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1240 lambda t: t[1] == 'data')
Tim Peters28355492001-09-23 21:29:55 +00001241 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001242 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001243
1244 contents = '\n'.join(contents)
1245 if not contents:
1246 return title + '\n'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001247 return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001248
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001249 def formatvalue(self, object):
1250 """Format an argument default value as text."""
1251 return '=' + self.repr(object)
1252
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001253 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001254 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001255 realname = object.__name__
1256 name = name or realname
1257 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001258 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001259 if inspect.ismethod(object):
Christian Heimesff737952007-11-27 10:40:20 +00001260 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001261 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001262 if imclass is not cl:
1263 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001264 else:
Christian Heimesff737952007-11-27 10:40:20 +00001265 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001266 note = ' method of %s instance' % classname(
Christian Heimesff737952007-11-27 10:40:20 +00001267 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001268 else:
1269 note = ' unbound %s method' % classname(imclass,mod)
Christian Heimesff737952007-11-27 10:40:20 +00001270 object = object.__func__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001271
1272 if name == realname:
1273 title = self.bold(realname)
1274 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001275 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001276 cl.__dict__[realname] is object):
1277 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001278 title = self.bold(name) + ' = ' + realname
Tim Peters4bcfa312001-09-20 06:08:24 +00001279 if inspect.isfunction(object):
Guido van Rossum2e65f892007-02-28 22:03:49 +00001280 args, varargs, varkw, defaults, kwonlyargs, kwdefaults, ann = \
1281 inspect.getfullargspec(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001282 argspec = inspect.formatargspec(
Guido van Rossum2e65f892007-02-28 22:03:49 +00001283 args, varargs, varkw, defaults, kwonlyargs, kwdefaults, ann,
1284 formatvalue=self.formatvalue,
1285 formatannotation=inspect.formatannotationrelativeto(object))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001286 if realname == '<lambda>':
Georg Brandl501dd0d2006-02-17 09:45:40 +00001287 title = self.bold(name) + ' lambda '
Guido van Rossum2e65f892007-02-28 22:03:49 +00001288 # XXX lambda's won't usually have func_annotations['return']
1289 # since the syntax doesn't support but it is possible.
1290 # So removing parentheses isn't truly safe.
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001291 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +00001292 else:
1293 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001294 decl = title + argspec + note
1295
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001296 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001297 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001298 else:
1299 doc = getdoc(object) or ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001300 return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001301
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001302 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001303 results = []
1304 push = results.append
1305
1306 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001307 push(self.bold(name))
1308 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001309 doc = getdoc(value) or ''
1310 if doc:
1311 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001312 push('\n')
1313 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001314
1315 def docproperty(self, object, name=None, mod=None, cl=None):
1316 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001317 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001318
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001319 def docdata(self, object, name=None, mod=None, cl=None):
1320 """Produce text documentation for a data descriptor."""
1321 return self._docdescriptor(name, object, mod)
1322
Georg Brandl8b813db2005-10-01 16:32:31 +00001323 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001324 """Produce text documentation for a data object."""
1325 repr = self.repr(object)
1326 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001327 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001328 chop = maxlen - len(line)
1329 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001330 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001331 if doc is not None:
1332 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001333 return line
1334
Georg Brandld80d5f42010-12-03 07:47:22 +00001335class _PlainTextDoc(TextDoc):
1336 """Subclass of TextDoc which overrides string styling"""
1337 def bold(self, text):
1338 return text
1339
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001340# --------------------------------------------------------- user interfaces
1341
1342def pager(text):
1343 """The first time this is called, determine what kind of pager to use."""
1344 global pager
1345 pager = getpager()
1346 pager(text)
1347
1348def getpager():
1349 """Decide what method to use for paging through text."""
Guido van Rossuma01a8b62007-05-27 09:20:14 +00001350 if not hasattr(sys.stdout, "isatty"):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001351 return plainpager
1352 if not sys.stdin.isatty() or not sys.stdout.isatty():
1353 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001354 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001355 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001356 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001357 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001358 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001359 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001360 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001361 if os.environ.get('TERM') in ('dumb', 'emacs'):
1362 return plainpager
Andrew MacIntyre54e0eab2002-03-03 03:12:30 +00001363 if sys.platform == 'win32' or sys.platform.startswith('os2'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001364 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001365 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001366 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001367
1368 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001369 (fd, filename) = tempfile.mkstemp()
1370 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001371 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001372 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001373 return lambda text: pipepager(text, 'more')
1374 else:
1375 return ttypager
1376 finally:
1377 os.unlink(filename)
1378
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001379def plain(text):
1380 """Remove boldface formatting from text."""
1381 return re.sub('.\b', '', text)
1382
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001383def pipepager(text, cmd):
1384 """Page through text by feeding it to another program."""
1385 pipe = os.popen(cmd, 'w')
1386 try:
1387 pipe.write(text)
1388 pipe.close()
1389 except IOError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001390 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001391
1392def tempfilepager(text, cmd):
1393 """Page through text by invoking a program on a temporary file."""
1394 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001395 filename = tempfile.mktemp()
1396 file = open(filename, 'w')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001397 file.write(text)
1398 file.close()
1399 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001400 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001401 finally:
1402 os.unlink(filename)
1403
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001404def ttypager(text):
1405 """Page through text on a text terminal."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001406 lines = plain(text).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001407 try:
1408 import tty
1409 fd = sys.stdin.fileno()
1410 old = tty.tcgetattr(fd)
1411 tty.setcbreak(fd)
1412 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001413 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001414 tty = None
1415 getchar = lambda: sys.stdin.readline()[:-1][:1]
1416
1417 try:
1418 r = inc = os.environ.get('LINES', 25) - 1
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001419 sys.stdout.write('\n'.join(lines[:inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001420 while lines[r:]:
1421 sys.stdout.write('-- more --')
1422 sys.stdout.flush()
1423 c = getchar()
1424
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001425 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001426 sys.stdout.write('\r \r')
1427 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001428 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001429 sys.stdout.write('\r \r' + lines[r] + '\n')
1430 r = r + 1
1431 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001432 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001433 r = r - inc - inc
1434 if r < 0: r = 0
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001435 sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001436 r = r + inc
1437
1438 finally:
1439 if tty:
1440 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1441
1442def plainpager(text):
1443 """Simply print unformatted text. This is the ultimate fallback."""
1444 sys.stdout.write(plain(text))
1445
1446def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001447 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001448 if inspect.ismodule(thing):
1449 if thing.__name__ in sys.builtin_module_names:
1450 return 'built-in module ' + thing.__name__
1451 if hasattr(thing, '__path__'):
1452 return 'package ' + thing.__name__
1453 else:
1454 return 'module ' + thing.__name__
1455 if inspect.isbuiltin(thing):
1456 return 'built-in function ' + thing.__name__
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001457 if inspect.isgetsetdescriptor(thing):
1458 return 'getset descriptor %s.%s.%s' % (
1459 thing.__objclass__.__module__, thing.__objclass__.__name__,
1460 thing.__name__)
1461 if inspect.ismemberdescriptor(thing):
1462 return 'member descriptor %s.%s.%s' % (
1463 thing.__objclass__.__module__, thing.__objclass__.__name__,
1464 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001465 if inspect.isclass(thing):
1466 return 'class ' + thing.__name__
1467 if inspect.isfunction(thing):
1468 return 'function ' + thing.__name__
1469 if inspect.ismethod(thing):
1470 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001471 return type(thing).__name__
1472
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001473def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001474 """Locate an object by name or dotted path, importing as necessary."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001475 parts = [part for part in path.split('.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001476 module, n = None, 0
1477 while n < len(parts):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001478 nextmodule = safeimport('.'.join(parts[:n+1]), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001479 if nextmodule: module, n = nextmodule, n + 1
1480 else: break
1481 if module:
1482 object = module
1483 for part in parts[n:]:
1484 try: object = getattr(object, part)
1485 except AttributeError: return None
1486 return object
1487 else:
Georg Brandl1a3284e2007-12-02 09:40:06 +00001488 if hasattr(builtins, path):
1489 return getattr(builtins, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001490
1491# --------------------------------------- interactive interpreter interface
1492
1493text = TextDoc()
Georg Brandld80d5f42010-12-03 07:47:22 +00001494plaintext = _PlainTextDoc()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001495html = HTMLDoc()
1496
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001497def resolve(thing, forceload=0):
1498 """Given an object or a path to an object, get the object and its name."""
1499 if isinstance(thing, str):
1500 object = locate(thing, forceload)
1501 if not object:
Collin Winterce36ad82007-08-30 01:19:48 +00001502 raise ImportError('no Python documentation found for %r' % thing)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001503 return object, thing
1504 else:
1505 return thing, getattr(thing, '__name__', None)
1506
Georg Brandld80d5f42010-12-03 07:47:22 +00001507def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
1508 renderer=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001509 """Render text documentation, given an object or a path to an object."""
Georg Brandld80d5f42010-12-03 07:47:22 +00001510 if renderer is None:
1511 renderer = text
Guido van Rossumd8faa362007-04-27 19:54:29 +00001512 object, name = resolve(thing, forceload)
1513 desc = describe(object)
1514 module = inspect.getmodule(object)
1515 if name and '.' in name:
1516 desc += ' in ' + name[:name.rfind('.')]
1517 elif module and module is not object:
1518 desc += ' in module ' + module.__name__
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001519
1520 if not (inspect.ismodule(object) or
Guido van Rossumd8faa362007-04-27 19:54:29 +00001521 inspect.isclass(object) or
1522 inspect.isroutine(object) or
1523 inspect.isgetsetdescriptor(object) or
1524 inspect.ismemberdescriptor(object) or
1525 isinstance(object, property)):
1526 # If the passed object is a piece of data or an instance,
1527 # document its available methods instead of its value.
1528 object = type(object)
1529 desc += ' object'
Georg Brandld80d5f42010-12-03 07:47:22 +00001530 return title % desc + '\n\n' + renderer.document(object, name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001531
Georg Brandld80d5f42010-12-03 07:47:22 +00001532def doc(thing, title='Python Library Documentation: %s', forceload=0,
1533 output=None):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001534 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001535 try:
Georg Brandld80d5f42010-12-03 07:47:22 +00001536 if output is None:
1537 pager(render_doc(thing, title, forceload))
1538 else:
1539 output.write(render_doc(thing, title, forceload, plaintext))
Guido van Rossumb940e112007-01-10 16:19:56 +00001540 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001541 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001542
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001543def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001544 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001545 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001546 object, name = resolve(thing, forceload)
1547 page = html.page(describe(object), html.document(object, name))
Georg Brandl388faac2009-04-10 08:31:48 +00001548 file = open(name + '.html', 'w', encoding='utf-8')
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001549 file.write(page)
1550 file.close()
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001551 print('wrote', name + '.html')
Guido van Rossumb940e112007-01-10 16:19:56 +00001552 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001553 print(value)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001554
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001555def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001556 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001557 if done is None: done = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001558 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1559 writedoc(modname)
1560 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001561
1562class Helper:
Georg Brandl6b38daa2008-06-01 21:05:17 +00001563
1564 # These dictionaries map a topic name to either an alias, or a tuple
1565 # (label, seealso-items). The "label" is the label of the corresponding
1566 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl5617db82009-04-27 16:28:57 +00001567 # in pydoc_data/topics.py.
Georg Brandl6b38daa2008-06-01 21:05:17 +00001568 #
1569 # CAUTION: if you change one of these dictionaries, be sure to adapt the
1570 # list of needed labels in Doc/tools/sphinxext/pyspecific.py and
Georg Brandl5617db82009-04-27 16:28:57 +00001571 # regenerate the pydoc_data/topics.py file by running
Georg Brandl6b38daa2008-06-01 21:05:17 +00001572 # make pydoc-topics
1573 # in Doc/ and copying the output file into the Lib/ directory.
1574
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001575 keywords = {
Ezio Melottib185a042011-04-28 07:42:55 +03001576 'False': '',
1577 'None': '',
1578 'True': '',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001579 'and': 'BOOLEAN',
Guido van Rossumd8faa362007-04-27 19:54:29 +00001580 'as': 'with',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001581 'assert': ('assert', ''),
1582 'break': ('break', 'while for'),
1583 'class': ('class', 'CLASSES SPECIALMETHODS'),
1584 'continue': ('continue', 'while for'),
1585 'def': ('function', ''),
1586 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001587 'elif': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001588 'else': ('else', 'while for'),
Georg Brandl0d855392008-08-30 19:53:05 +00001589 'except': 'try',
1590 'finally': 'try',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001591 'for': ('for', 'break continue while'),
Georg Brandl0d855392008-08-30 19:53:05 +00001592 'from': 'import',
Georg Brandl74abf6f2010-11-20 19:54:36 +00001593 'global': ('global', 'nonlocal NAMESPACES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001594 'if': ('if', 'TRUTHVALUE'),
1595 'import': ('import', 'MODULES'),
Georg Brandl395ed242009-09-04 08:07:32 +00001596 'in': ('in', 'SEQUENCEMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001597 'is': 'COMPARISON',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001598 'lambda': ('lambda', 'FUNCTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001599 'nonlocal': ('nonlocal', 'global NAMESPACES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001600 'not': 'BOOLEAN',
1601 'or': 'BOOLEAN',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001602 'pass': ('pass', ''),
1603 'raise': ('raise', 'EXCEPTIONS'),
1604 'return': ('return', 'FUNCTIONS'),
1605 'try': ('try', 'EXCEPTIONS'),
1606 'while': ('while', 'break continue if TRUTHVALUE'),
1607 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1608 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001609 }
Georg Brandldb7b6b92009-01-01 15:53:14 +00001610 # Either add symbols to this dictionary or to the symbols dictionary
1611 # directly: Whichever is easier. They are merged later.
1612 _symbols_inverse = {
1613 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'),
1614 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1615 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1616 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1617 'UNARY' : ('-', '~'),
1618 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1619 '^=', '<<=', '>>=', '**=', '//='),
1620 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1621 'COMPLEX' : ('j', 'J')
1622 }
1623 symbols = {
1624 '%': 'OPERATORS FORMATTING',
1625 '**': 'POWER',
1626 ',': 'TUPLES LISTS FUNCTIONS',
1627 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1628 '...': 'ELLIPSIS',
1629 ':': 'SLICINGS DICTIONARYLITERALS',
1630 '@': 'def class',
1631 '\\': 'STRINGS',
1632 '_': 'PRIVATENAMES',
1633 '__': 'PRIVATENAMES SPECIALMETHODS',
1634 '`': 'BACKQUOTES',
1635 '(': 'TUPLES FUNCTIONS CALLS',
1636 ')': 'TUPLES FUNCTIONS CALLS',
1637 '[': 'LISTS SUBSCRIPTS SLICINGS',
1638 ']': 'LISTS SUBSCRIPTS SLICINGS'
1639 }
1640 for topic, symbols_ in _symbols_inverse.items():
1641 for symbol in symbols_:
1642 topics = symbols.get(symbol, topic)
1643 if topic not in topics:
1644 topics = topics + ' ' + topic
1645 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001646
1647 topics = {
Georg Brandl6b38daa2008-06-01 21:05:17 +00001648 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1649 'FUNCTIONS CLASSES MODULES FILES inspect'),
1650 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS '
1651 'FORMATTING TYPES'),
1652 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1653 'FORMATTING': ('formatstrings', 'OPERATORS'),
1654 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1655 'FORMATTING TYPES'),
1656 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1657 'INTEGER': ('integers', 'int range'),
1658 'FLOAT': ('floating', 'float math'),
1659 'COMPLEX': ('imaginary', 'complex cmath'),
1660 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING range LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001661 'MAPPINGS': 'DICTIONARIES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001662 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1663 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1664 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1665 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001666 'FRAMEOBJECTS': 'TYPES',
1667 'TRACEBACKS': 'TYPES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001668 'NONE': ('bltin-null-object', ''),
1669 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
1670 'FILES': ('bltin-file-objects', ''),
1671 'SPECIALATTRIBUTES': ('specialattrs', ''),
1672 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1673 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001674 'PACKAGES': 'import',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001675 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1676 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1677 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1678 'LISTS DICTIONARIES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001679 'OPERATORS': 'EXPRESSIONS',
1680 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001681 'OBJECTS': ('objects', 'TYPES'),
1682 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
Georg Brandl395ed242009-09-04 08:07:32 +00001683 'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS '
1684 'NUMBERMETHODS CLASSES'),
Mark Dickinsona56c4672009-01-27 18:17:45 +00001685 'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001686 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1687 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001688 'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS '
Georg Brandl6b38daa2008-06-01 21:05:17 +00001689 'SPECIALMETHODS'),
1690 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1691 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1692 'SPECIALMETHODS'),
1693 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001694 'NAMESPACES': ('naming', 'global nonlocal ASSIGNMENT DELETION DYNAMICFEATURES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001695 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001696 'SCOPING': 'NAMESPACES',
1697 'FRAMES': 'NAMESPACES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001698 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1699 'CONVERSIONS': ('conversions', ''),
1700 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1701 'SPECIALIDENTIFIERS': ('id-classes', ''),
1702 'PRIVATENAMES': ('atom-identifiers', ''),
1703 'LITERALS': ('atom-literals', 'STRINGS NUMBERS TUPLELITERALS '
1704 'LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001705 'TUPLES': 'SEQUENCES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001706 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1707 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1708 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1709 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1710 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1711 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001712 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'),
1713 'SLICINGS': ('slicings', 'SEQUENCEMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001714 'CALLS': ('calls', 'EXPRESSIONS'),
1715 'POWER': ('power', 'EXPRESSIONS'),
1716 'UNARY': ('unary', 'EXPRESSIONS'),
1717 'BINARY': ('binary', 'EXPRESSIONS'),
1718 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1719 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1720 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1721 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001722 'ASSERTION': 'assert',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001723 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1724 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001725 'DELETION': 'del',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001726 'RETURNING': 'return',
1727 'IMPORTING': 'import',
1728 'CONDITIONAL': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001729 'LOOPING': ('compound', 'for while break continue'),
1730 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1731 'DEBUGGING': ('debugger', 'pdb'),
1732 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001733 }
1734
Georg Brandl78aa3962010-07-31 21:51:48 +00001735 def __init__(self, input=None, output=None):
1736 self._input = input
1737 self._output = output
1738
Georg Brandl76ae3972010-08-01 06:32:55 +00001739 input = property(lambda self: self._input or sys.stdin)
1740 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001741
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001742 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001743 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001744 self()
1745 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001746 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001747
Alexander Belopolsky2e733c92010-07-04 17:00:20 +00001748 _GoInteractive = object()
1749 def __call__(self, request=_GoInteractive):
1750 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001751 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001752 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001753 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001754 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001755 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001756You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001757If you want to ask for help on a particular object directly from the
1758interpreter, you can type "help(object)". Executing "help('string')"
1759has the same effect as typing a particular string at the help> prompt.
1760''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001761
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001762 def interact(self):
1763 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001764 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001765 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001766 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001767 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001768 except (KeyboardInterrupt, EOFError):
1769 break
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001770 request = replace(request, '"', '', "'", '').strip()
1771 if request.lower() in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001772 self.help(request)
1773
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001774 def getline(self, prompt):
Guido van Rossum7c086c02008-01-02 03:52:38 +00001775 """Read one line, using input() when appropriate."""
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001776 if self.input is sys.stdin:
Guido van Rossum7c086c02008-01-02 03:52:38 +00001777 return input(prompt)
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001778 else:
1779 self.output.write(prompt)
1780 self.output.flush()
1781 return self.input.readline()
1782
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001783 def help(self, request):
1784 if type(request) is type(''):
R. David Murray1f1b9d32009-05-27 20:56:59 +00001785 request = request.strip()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001786 if request == 'help': self.intro()
1787 elif request == 'keywords': self.listkeywords()
Georg Brandldb7b6b92009-01-01 15:53:14 +00001788 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001789 elif request == 'topics': self.listtopics()
1790 elif request == 'modules': self.listmodules()
1791 elif request[:8] == 'modules ':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001792 self.listmodules(request.split()[1])
Georg Brandldb7b6b92009-01-01 15:53:14 +00001793 elif request in self.symbols: self.showsymbol(request)
Ezio Melottib185a042011-04-28 07:42:55 +03001794 elif request in ['True', 'False', 'None']:
1795 # special case these keywords since they are objects too
1796 doc(eval(request), 'Help on %s:')
Raymond Hettinger54f02222002-06-01 14:18:47 +00001797 elif request in self.keywords: self.showtopic(request)
1798 elif request in self.topics: self.showtopic(request)
Georg Brandld80d5f42010-12-03 07:47:22 +00001799 elif request: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001800 elif isinstance(request, Helper): self()
Georg Brandld80d5f42010-12-03 07:47:22 +00001801 else: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001802 self.output.write('\n')
1803
1804 def intro(self):
1805 self.output.write('''
1806Welcome to Python %s! This is the online help utility.
1807
1808If this is your first time using Python, you should definitely check out
Georg Brandl86def6c2008-01-21 20:36:10 +00001809the tutorial on the Internet at http://docs.python.org/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001810
1811Enter the name of any module, keyword, or topic to get help on writing
1812Python programs and using Python modules. To quit this help utility and
1813return to the interpreter, just type "quit".
1814
1815To get a list of available modules, keywords, or topics, type "modules",
1816"keywords", or "topics". Each module also comes with a one-line summary
1817of what it does; to list the modules whose summaries contain a given word
1818such as "spam", type "modules spam".
1819''' % sys.version[:3])
1820
1821 def list(self, items, columns=4, width=80):
Guido van Rossum486364b2007-06-30 05:01:58 +00001822 items = list(sorted(items))
1823 colw = width // columns
1824 rows = (len(items) + columns - 1) // columns
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001825 for row in range(rows):
1826 for col in range(columns):
1827 i = col * rows + row
1828 if i < len(items):
1829 self.output.write(items[i])
1830 if col < columns - 1:
Guido van Rossum486364b2007-06-30 05:01:58 +00001831 self.output.write(' ' + ' ' * (colw - 1 - len(items[i])))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001832 self.output.write('\n')
1833
1834 def listkeywords(self):
1835 self.output.write('''
1836Here is a list of the Python keywords. Enter any keyword to get more help.
1837
1838''')
1839 self.list(self.keywords.keys())
1840
Georg Brandldb7b6b92009-01-01 15:53:14 +00001841 def listsymbols(self):
1842 self.output.write('''
1843Here is a list of the punctuation symbols which Python assigns special meaning
1844to. Enter any symbol to get more help.
1845
1846''')
1847 self.list(self.symbols.keys())
1848
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001849 def listtopics(self):
1850 self.output.write('''
1851Here is a list of available topics. Enter any topic name to get more help.
1852
1853''')
1854 self.list(self.topics.keys())
1855
Georg Brandldb7b6b92009-01-01 15:53:14 +00001856 def showtopic(self, topic, more_xrefs=''):
Georg Brandl6b38daa2008-06-01 21:05:17 +00001857 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001858 import pydoc_data.topics
Georg Brandl6b38daa2008-06-01 21:05:17 +00001859 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001860 self.output.write('''
Georg Brandl6b38daa2008-06-01 21:05:17 +00001861Sorry, topic and keyword documentation is not available because the
Georg Brandl5617db82009-04-27 16:28:57 +00001862module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001863''')
1864 return
1865 target = self.topics.get(topic, self.keywords.get(topic))
1866 if not target:
1867 self.output.write('no documentation found for %s\n' % repr(topic))
1868 return
1869 if type(target) is type(''):
Georg Brandldb7b6b92009-01-01 15:53:14 +00001870 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001871
Georg Brandl6b38daa2008-06-01 21:05:17 +00001872 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001873 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001874 doc = pydoc_data.topics.topics[label]
Georg Brandl6b38daa2008-06-01 21:05:17 +00001875 except KeyError:
1876 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001877 return
Georg Brandl6b38daa2008-06-01 21:05:17 +00001878 pager(doc.strip() + '\n')
Georg Brandldb7b6b92009-01-01 15:53:14 +00001879 if more_xrefs:
1880 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001881 if xrefs:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001882 import formatter
Guido van Rossum34d19282007-08-09 01:03:29 +00001883 buffer = io.StringIO()
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001884 formatter.DumbWriter(buffer).send_flowing_data(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001885 'Related help topics: ' + ', '.join(xrefs.split()) + '\n')
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001886 self.output.write('\n%s\n' % buffer.getvalue())
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001887
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001888 def _gettopic(self, topic, more_xrefs=''):
1889 """Return unbuffered tuple of (topic, xrefs).
1890
Georg Brandld2f38572011-01-30 08:37:19 +00001891 If an error occurs here, the exception is caught and displayed by
1892 the url handler.
1893
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001894 This function duplicates the showtopic method but returns its
1895 result directly so it can be formatted for display in an html page.
1896 """
1897 try:
1898 import pydoc_data.topics
1899 except ImportError:
1900 return('''
1901Sorry, topic and keyword documentation is not available because the
1902module "pydoc_data.topics" could not be found.
1903''' , '')
1904 target = self.topics.get(topic, self.keywords.get(topic))
1905 if not target:
Georg Brandld2f38572011-01-30 08:37:19 +00001906 raise ValueError('could not find topic')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001907 if isinstance(target, str):
1908 return self._gettopic(target, more_xrefs)
1909 label, xrefs = target
Georg Brandld2f38572011-01-30 08:37:19 +00001910 doc = pydoc_data.topics.topics[label]
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001911 if more_xrefs:
1912 xrefs = (xrefs or '') + ' ' + more_xrefs
1913 return doc, xrefs
1914
Georg Brandldb7b6b92009-01-01 15:53:14 +00001915 def showsymbol(self, symbol):
1916 target = self.symbols[symbol]
1917 topic, _, xrefs = target.partition(' ')
1918 self.showtopic(topic, xrefs)
1919
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001920 def listmodules(self, key=''):
1921 if key:
1922 self.output.write('''
1923Here is a list of matching modules. Enter any module name to get more help.
1924
1925''')
1926 apropos(key)
1927 else:
1928 self.output.write('''
1929Please wait a moment while I gather a list of all available modules...
1930
1931''')
1932 modules = {}
1933 def callback(path, modname, desc, modules=modules):
1934 if modname and modname[-9:] == '.__init__':
1935 modname = modname[:-9] + ' (package)'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001936 if modname.find('.') < 0:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001937 modules[modname] = 1
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001938 def onerror(modname):
1939 callback(None, modname, None)
1940 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001941 self.list(modules.keys())
1942 self.output.write('''
1943Enter any module name to get more help. Or, type "modules spam" to search
1944for modules whose descriptions contain the word "spam".
1945''')
1946
Georg Brandl78aa3962010-07-31 21:51:48 +00001947help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001948
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001949class Scanner:
1950 """A generic tree iterator."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001951 def __init__(self, roots, children, descendp):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001952 self.roots = roots[:]
1953 self.state = []
1954 self.children = children
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001955 self.descendp = descendp
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001956
1957 def next(self):
1958 if not self.state:
1959 if not self.roots:
1960 return None
1961 root = self.roots.pop(0)
1962 self.state = [(root, self.children(root))]
1963 node, children = self.state[-1]
1964 if not children:
1965 self.state.pop()
1966 return self.next()
1967 child = children.pop(0)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001968 if self.descendp(child):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001969 self.state.append((child, self.children(child)))
1970 return child
1971
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001972
1973class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001974 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001975
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001976 def run(self, callback, key=None, completer=None, onerror=None):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001977 if key: key = key.lower()
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001978 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001979 seen = {}
1980
1981 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001982 if modname != '__main__':
1983 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00001984 if key is None:
1985 callback(None, modname, '')
1986 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001987 name = __import__(modname).__doc__ or ''
1988 desc = name.split('\n')[0]
1989 name = modname + ' - ' + desc
1990 if name.lower().find(key) >= 0:
Ka-Ping Yee66246962001-04-12 11:59:50 +00001991 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001992
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001993 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001994 if self.quit:
1995 break
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001996
1997 # XXX Skipping this file is a workaround for a bug
1998 # that causes python to crash with a segfault.
1999 # http://bugs.python.org/issue9319
2000 #
2001 # TODO Remove this once the bug is fixed.
2002 if modname in {'test.badsyntax_pep3120', 'badsyntax_pep3120'}:
2003 continue
2004
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002005 if key is None:
2006 callback(None, modname, '')
2007 else:
Georg Brandl126c8792009-04-05 15:05:48 +00002008 try:
2009 loader = importer.find_module(modname)
2010 except SyntaxError:
2011 # raised by tests for bad coding cookies or BOM
2012 continue
2013 if hasattr(loader, 'get_source'):
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002014 try:
2015 source = loader.get_source(modname)
2016 except UnicodeDecodeError:
2017 if onerror:
2018 onerror(modname)
2019 continue
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002020 desc = source_synopsis(io.StringIO(source)) or ''
Georg Brandl126c8792009-04-05 15:05:48 +00002021 if hasattr(loader, 'get_filename'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002022 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002023 else:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002024 path = None
2025 else:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002026 try:
2027 module = loader.load_module(modname)
2028 except ImportError:
2029 if onerror:
2030 onerror(modname)
2031 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002032 desc = (module.__doc__ or '').splitlines()[0]
2033 path = getattr(module,'__file__',None)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002034 name = modname + ' - ' + desc
2035 if name.lower().find(key) >= 0:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002036 callback(path, modname, desc)
2037
2038 if completer:
2039 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002040
2041def apropos(key):
2042 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002043 def callback(path, modname, desc):
2044 if modname[-9:] == '.__init__':
2045 modname = modname[:-9] + ' (package)'
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002046 print(modname, desc and '- ' + desc)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002047 def onerror(modname):
2048 pass
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002049 with warnings.catch_warnings():
2050 warnings.filterwarnings('ignore') # ignore problems during import
2051 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002052
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002053# --------------------------------------- enhanced Web browser interface
2054
2055def _start_server(urlhandler, port):
2056 """Start an HTTP server thread on a specific port.
2057
2058 Start an HTML/text server thread, so HTML or text documents can be
2059 browsed dynamically and interactively with a Web browser. Example use:
2060
2061 >>> import time
2062 >>> import pydoc
2063
2064 Define a URL handler. To determine what the client is asking
2065 for, check the URL and content_type.
2066
2067 Then get or generate some text or HTML code and return it.
2068
2069 >>> def my_url_handler(url, content_type):
2070 ... text = 'the URL sent was: (%s, %s)' % (url, content_type)
2071 ... return text
2072
2073 Start server thread on port 0.
2074 If you use port 0, the server will pick a random port number.
2075 You can then use serverthread.port to get the port number.
2076
2077 >>> port = 0
2078 >>> serverthread = pydoc._start_server(my_url_handler, port)
2079
2080 Check that the server is really started. If it is, open browser
2081 and get first page. Use serverthread.url as the starting page.
2082
2083 >>> if serverthread.serving:
2084 ... import webbrowser
2085
2086 The next two lines are commented out so a browser doesn't open if
2087 doctest is run on this module.
2088
2089 #... webbrowser.open(serverthread.url)
2090 #True
2091
2092 Let the server do its thing. We just need to monitor its status.
2093 Use time.sleep so the loop doesn't hog the CPU.
2094
2095 >>> starttime = time.time()
2096 >>> timeout = 1 #seconds
2097
2098 This is a short timeout for testing purposes.
2099
2100 >>> while serverthread.serving:
2101 ... time.sleep(.01)
2102 ... if serverthread.serving and time.time() - starttime > timeout:
2103 ... serverthread.stop()
2104 ... break
2105
2106 Print any errors that may have occurred.
2107
2108 >>> print(serverthread.error)
2109 None
2110 """
2111 import http.server
2112 import email.message
2113 import select
2114 import threading
2115
2116 class DocHandler(http.server.BaseHTTPRequestHandler):
2117
2118 def do_GET(self):
2119 """Process a request from an HTML browser.
2120
2121 The URL received is in self.path.
2122 Get an HTML page from self.urlhandler and send it.
2123 """
2124 if self.path.endswith('.css'):
2125 content_type = 'text/css'
2126 else:
2127 content_type = 'text/html'
2128 self.send_response(200)
Georg Brandld2f38572011-01-30 08:37:19 +00002129 self.send_header('Content-Type', '%s; charset=UTF-8' % content_type)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002130 self.end_headers()
2131 self.wfile.write(self.urlhandler(
2132 self.path, content_type).encode('utf-8'))
2133
2134 def log_message(self, *args):
2135 # Don't log messages.
2136 pass
2137
2138 class DocServer(http.server.HTTPServer):
2139
2140 def __init__(self, port, callback):
2141 self.host = (sys.platform == 'mac') and '127.0.0.1' or 'localhost'
2142 self.address = ('', port)
2143 self.callback = callback
2144 self.base.__init__(self, self.address, self.handler)
2145 self.quit = False
2146
2147 def serve_until_quit(self):
2148 while not self.quit:
2149 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2150 if rd:
2151 self.handle_request()
Victor Stinnera3abd1d2011-01-03 16:12:39 +00002152 self.server_close()
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002153
2154 def server_activate(self):
2155 self.base.server_activate(self)
2156 if self.callback:
2157 self.callback(self)
2158
2159 class ServerThread(threading.Thread):
2160
2161 def __init__(self, urlhandler, port):
2162 self.urlhandler = urlhandler
2163 self.port = int(port)
2164 threading.Thread.__init__(self)
2165 self.serving = False
2166 self.error = None
2167
2168 def run(self):
2169 """Start the server."""
2170 try:
2171 DocServer.base = http.server.HTTPServer
2172 DocServer.handler = DocHandler
2173 DocHandler.MessageClass = email.message.Message
2174 DocHandler.urlhandler = staticmethod(self.urlhandler)
2175 docsvr = DocServer(self.port, self.ready)
2176 self.docserver = docsvr
2177 docsvr.serve_until_quit()
2178 except Exception as e:
2179 self.error = e
2180
2181 def ready(self, server):
2182 self.serving = True
2183 self.host = server.host
2184 self.port = server.server_port
2185 self.url = 'http://%s:%d/' % (self.host, self.port)
2186
2187 def stop(self):
2188 """Stop the server and this thread nicely"""
2189 self.docserver.quit = True
2190 self.serving = False
2191 self.url = None
2192
2193 thread = ServerThread(urlhandler, port)
2194 thread.start()
2195 # Wait until thread.serving is True to make sure we are
2196 # really up before returning.
2197 while not thread.error and not thread.serving:
2198 time.sleep(.01)
2199 return thread
2200
2201
2202def _url_handler(url, content_type="text/html"):
2203 """The pydoc url handler for use with the pydoc server.
2204
2205 If the content_type is 'text/css', the _pydoc.css style
2206 sheet is read and returned if it exits.
2207
2208 If the content_type is 'text/html', then the result of
2209 get_html_page(url) is returned.
2210 """
2211 class _HTMLDoc(HTMLDoc):
2212
2213 def page(self, title, contents):
2214 """Format an HTML page."""
2215 css_path = "pydoc_data/_pydoc.css"
2216 css_link = (
2217 '<link rel="stylesheet" type="text/css" href="%s">' %
2218 css_path)
2219 return '''\
2220<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Georg Brandld2f38572011-01-30 08:37:19 +00002221<html><head><title>Pydoc: %s</title>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002222<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Georg Brandld2f38572011-01-30 08:37:19 +00002223%s</head><body bgcolor="#f0f0f8">%s<div style="clear:both;padding-top:.5em;">%s</div>
2224</body></html>''' % (title, css_link, html_navbar(), contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002225
2226 def filelink(self, url, path):
2227 return '<a href="getfile?key=%s">%s</a>' % (url, path)
2228
2229
2230 html = _HTMLDoc()
2231
2232 def html_navbar():
Georg Brandld2f38572011-01-30 08:37:19 +00002233 version = html.escape("%s [%s, %s]" % (platform.python_version(),
2234 platform.python_build()[0],
2235 platform.python_compiler()))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002236 return """
2237 <div style='float:left'>
Georg Brandld2f38572011-01-30 08:37:19 +00002238 Python %s<br>%s
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002239 </div>
2240 <div style='float:right'>
2241 <div style='text-align:center'>
2242 <a href="index.html">Module Index</a>
2243 : <a href="topics.html">Topics</a>
2244 : <a href="keywords.html">Keywords</a>
2245 </div>
2246 <div>
Georg Brandld2f38572011-01-30 08:37:19 +00002247 <form action="get" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002248 <input type=text name=key size=15>
2249 <input type=submit value="Get">
Georg Brandld2f38572011-01-30 08:37:19 +00002250 </form>&nbsp;
2251 <form action="search" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002252 <input type=text name=key size=15>
2253 <input type=submit value="Search">
2254 </form>
2255 </div>
2256 </div>
Georg Brandld2f38572011-01-30 08:37:19 +00002257 """ % (version, html.escape(platform.platform(terse=True)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002258
2259 def html_index():
2260 """Module Index page."""
2261
2262 def bltinlink(name):
2263 return '<a href="%s.html">%s</a>' % (name, name)
2264
2265 heading = html.heading(
2266 '<big><big><strong>Index of Modules</strong></big></big>',
2267 '#ffffff', '#7799ee')
2268 names = [name for name in sys.builtin_module_names
2269 if name != '__main__']
2270 contents = html.multicolumn(names, bltinlink)
2271 contents = [heading, '<p>' + html.bigsection(
2272 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2273
2274 seen = {}
2275 for dir in sys.path:
2276 contents.append(html.index(dir, seen))
2277
2278 contents.append(
2279 '<p align=right><font color="#909090" face="helvetica,'
2280 'arial"><strong>pydoc</strong> by Ka-Ping Yee'
2281 '&lt;ping@lfw.org&gt;</font>')
Nick Coghlanecace282010-12-03 16:08:46 +00002282 return 'Index of Modules', ''.join(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002283
2284 def html_search(key):
2285 """Search results page."""
2286 # scan for modules
2287 search_result = []
2288
2289 def callback(path, modname, desc):
2290 if modname[-9:] == '.__init__':
2291 modname = modname[:-9] + ' (package)'
2292 search_result.append((modname, desc and '- ' + desc))
2293
2294 with warnings.catch_warnings():
2295 warnings.filterwarnings('ignore') # ignore problems during import
2296 ModuleScanner().run(callback, key)
2297
2298 # format page
2299 def bltinlink(name):
2300 return '<a href="%s.html">%s</a>' % (name, name)
2301
2302 results = []
2303 heading = html.heading(
2304 '<big><big><strong>Search Results</strong></big></big>',
2305 '#ffffff', '#7799ee')
2306 for name, desc in search_result:
2307 results.append(bltinlink(name) + desc)
2308 contents = heading + html.bigsection(
2309 'key = %s' % key, '#ffffff', '#ee77aa', '<br>'.join(results))
Nick Coghlanecace282010-12-03 16:08:46 +00002310 return 'Search Results', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002311
2312 def html_getfile(path):
2313 """Get and display a source file listing safely."""
Nick Coghlanecace282010-12-03 16:08:46 +00002314 path = path.replace('%20', ' ')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002315 with open(path, 'r') as fp:
2316 lines = html.escape(fp.read())
2317 body = '<pre>%s</pre>' % lines
2318 heading = html.heading(
2319 '<big><big><strong>File Listing</strong></big></big>',
2320 '#ffffff', '#7799ee')
2321 contents = heading + html.bigsection(
2322 'File: %s' % path, '#ffffff', '#ee77aa', body)
Nick Coghlanecace282010-12-03 16:08:46 +00002323 return 'getfile %s' % path, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002324
2325 def html_topics():
2326 """Index of topic texts available."""
2327
2328 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002329 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002330
2331 heading = html.heading(
2332 '<big><big><strong>INDEX</strong></big></big>',
2333 '#ffffff', '#7799ee')
2334 names = sorted(Helper.topics.keys())
2335
2336 contents = html.multicolumn(names, bltinlink)
2337 contents = heading + html.bigsection(
2338 'Topics', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002339 return 'Topics', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002340
2341 def html_keywords():
2342 """Index of keywords."""
2343 heading = html.heading(
2344 '<big><big><strong>INDEX</strong></big></big>',
2345 '#ffffff', '#7799ee')
2346 names = sorted(Helper.keywords.keys())
2347
2348 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002349 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002350
2351 contents = html.multicolumn(names, bltinlink)
2352 contents = heading + html.bigsection(
2353 'Keywords', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002354 return 'Keywords', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002355
2356 def html_topicpage(topic):
2357 """Topic or keyword help page."""
2358 buf = io.StringIO()
2359 htmlhelp = Helper(buf, buf)
2360 contents, xrefs = htmlhelp._gettopic(topic)
2361 if topic in htmlhelp.keywords:
2362 title = 'KEYWORD'
2363 else:
2364 title = 'TOPIC'
2365 heading = html.heading(
2366 '<big><big><strong>%s</strong></big></big>' % title,
2367 '#ffffff', '#7799ee')
Georg Brandld2f38572011-01-30 08:37:19 +00002368 contents = '<pre>%s</pre>' % html.markup(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002369 contents = html.bigsection(topic , '#ffffff','#ee77aa', contents)
Georg Brandld2f38572011-01-30 08:37:19 +00002370 if xrefs:
2371 xrefs = sorted(xrefs.split())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002372
Georg Brandld2f38572011-01-30 08:37:19 +00002373 def bltinlink(name):
2374 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002375
Georg Brandld2f38572011-01-30 08:37:19 +00002376 xrefs = html.multicolumn(xrefs, bltinlink)
2377 xrefs = html.section('Related help topics: ',
2378 '#ffffff', '#ee77aa', xrefs)
Nick Coghlanecace282010-12-03 16:08:46 +00002379 return ('%s %s' % (title, topic),
2380 ''.join((heading, contents, xrefs)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002381
Georg Brandld2f38572011-01-30 08:37:19 +00002382 def html_getobj(url):
2383 obj = locate(url, forceload=1)
2384 if obj is None and url != 'None':
2385 raise ValueError('could not find object')
2386 title = describe(obj)
2387 content = html.document(obj, url)
2388 return title, content
2389
2390 def html_error(url, exc):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002391 heading = html.heading(
2392 '<big><big><strong>Error</strong></big></big>',
Georg Brandld2f38572011-01-30 08:37:19 +00002393 '#ffffff', '#7799ee')
2394 contents = '<br>'.join(html.escape(line) for line in
2395 format_exception_only(type(exc), exc))
2396 contents = heading + html.bigsection(url, '#ffffff', '#bb0000',
2397 contents)
2398 return "Error - %s" % url, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002399
2400 def get_html_page(url):
2401 """Generate an HTML page for url."""
Georg Brandld2f38572011-01-30 08:37:19 +00002402 complete_url = url
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002403 if url.endswith('.html'):
2404 url = url[:-5]
Georg Brandld2f38572011-01-30 08:37:19 +00002405 try:
2406 if url in ("", "index"):
2407 title, content = html_index()
2408 elif url == "topics":
2409 title, content = html_topics()
2410 elif url == "keywords":
2411 title, content = html_keywords()
2412 elif '=' in url:
2413 op, _, url = url.partition('=')
2414 if op == "search?key":
2415 title, content = html_search(url)
2416 elif op == "getfile?key":
2417 title, content = html_getfile(url)
2418 elif op == "topic?key":
2419 # try topics first, then objects.
2420 try:
2421 title, content = html_topicpage(url)
2422 except ValueError:
2423 title, content = html_getobj(url)
2424 elif op == "get?key":
2425 # try objects first, then topics.
2426 if url in ("", "index"):
2427 title, content = html_index()
2428 else:
2429 try:
2430 title, content = html_getobj(url)
2431 except ValueError:
2432 title, content = html_topicpage(url)
2433 else:
2434 raise ValueError('bad pydoc url')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002435 else:
Georg Brandld2f38572011-01-30 08:37:19 +00002436 title, content = html_getobj(url)
2437 except Exception as exc:
2438 # Catch any errors and display them in an error page.
2439 title, content = html_error(complete_url, exc)
2440 return html.page(title, content)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002441
2442 if url.startswith('/'):
2443 url = url[1:]
2444 if content_type == 'text/css':
2445 path_here = os.path.dirname(os.path.realpath(__file__))
Georg Brandld2f38572011-01-30 08:37:19 +00002446 css_path = os.path.join(path_here, url)
2447 with open(css_path) as fp:
2448 return ''.join(fp.readlines())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002449 elif content_type == 'text/html':
2450 return get_html_page(url)
Georg Brandld2f38572011-01-30 08:37:19 +00002451 # Errors outside the url handler are caught by the server.
2452 raise TypeError('unknown content type %r for url %s' % (content_type, url))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002453
2454
2455def browse(port=0, *, open_browser=True):
2456 """Start the enhanced pydoc Web server and open a Web browser.
2457
2458 Use port '0' to start the server on an arbitrary port.
2459 Set open_browser to False to suppress opening a browser.
2460 """
2461 import webbrowser
2462 serverthread = _start_server(_url_handler, port)
2463 if serverthread.error:
2464 print(serverthread.error)
2465 return
2466 if serverthread.serving:
2467 server_help_msg = 'Server commands: [b]rowser, [q]uit'
2468 if open_browser:
2469 webbrowser.open(serverthread.url)
2470 try:
2471 print('Server ready at', serverthread.url)
2472 print(server_help_msg)
2473 while serverthread.serving:
2474 cmd = input('server> ')
2475 cmd = cmd.lower()
2476 if cmd == 'q':
2477 break
2478 elif cmd == 'b':
2479 webbrowser.open(serverthread.url)
2480 else:
2481 print(server_help_msg)
2482 except (KeyboardInterrupt, EOFError):
2483 print()
2484 finally:
2485 if serverthread.serving:
2486 serverthread.stop()
2487 print('Server stopped')
2488
2489
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002490# -------------------------------------------------- command-line interface
2491
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002492def ispath(x):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002493 return isinstance(x, str) and x.find(os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002494
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002495def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002496 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002497 import getopt
Guido van Rossum756aa932007-04-07 03:04:01 +00002498 class BadUsage(Exception): pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002499
Nick Coghlan106274b2009-11-15 23:04:33 +00002500 # Scripts don't get the current directory in their path by default
2501 # unless they are run with the '-m' switch
2502 if '' not in sys.path:
2503 scriptdir = os.path.dirname(sys.argv[0])
2504 if scriptdir in sys.path:
2505 sys.path.remove(scriptdir)
2506 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002507
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002508 try:
Victor Stinner383c3fc2011-05-25 01:35:05 +02002509 opts, args = getopt.getopt(sys.argv[1:], 'bk:p:w')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002510 writing = False
2511 start_server = False
2512 open_browser = False
2513 port = None
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002514 for opt, val in opts:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002515 if opt == '-b':
2516 start_server = True
2517 open_browser = True
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002518 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002519 apropos(val)
2520 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002521 if opt == '-p':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002522 start_server = True
2523 port = val
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002524 if opt == '-w':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002525 writing = True
2526
2527 if start_server == True:
2528 if port == None:
2529 port = 0
2530 browse(port, open_browser=open_browser)
2531 return
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002532
2533 if not args: raise BadUsage
2534 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002535 if ispath(arg) and not os.path.exists(arg):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002536 print('file %r does not exist' % arg)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002537 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002538 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002539 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002540 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002541 if writing:
2542 if ispath(arg) and os.path.isdir(arg):
2543 writedocs(arg)
2544 else:
2545 writedoc(arg)
2546 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002547 help.help(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +00002548 except ErrorDuringImport as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002549 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002550
2551 except (getopt.error, BadUsage):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002552 cmd = os.path.splitext(os.path.basename(sys.argv[0]))[0]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002553 print("""pydoc - the Python documentation tool
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002554
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002555{cmd} <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002556 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002557 Python keyword, topic, function, module, or package, or a dotted
2558 reference to a class or function within a module or module in a
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002559 package. If <name> contains a '{sep}', it is used as the path to a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002560 Python source file to document. If name is 'keywords', 'topics',
2561 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002562
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002563{cmd} -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002564 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002565
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002566{cmd} -p <port>
2567 Start an HTTP server on the given port on the local machine. Port
2568 number 0 can be used to get an arbitrary unused port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002569
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002570{cmd} -b
2571 Start an HTTP server on an arbitrary unused port and open a Web browser
2572 to interactively browse documentation. The -p option can be used with
2573 the -b option to explicitly specify the server port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002574
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002575{cmd} -w <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002576 Write out the HTML documentation for a module to a file in the current
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002577 directory. If <name> contains a '{sep}', it is treated as a filename; if
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002578 it names a directory, documentation is written for all the contents.
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002579""".format(cmd=cmd, sep=os.sep))
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002580
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002581if __name__ == '__main__':
2582 cli()