blob: 17ae29ff47e83a3452b0649383d88f5b7ea8e59d [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
Ka-Ping Yee09d7d9a2001-02-27 22:43:48 +000040__version__ = "$Revision$"
Martin v. Löwis6fe8f192004-11-14 10:21:04 +000041__credits__ = """Guido van Rossum, for an excellent programming language.
Ka-Ping Yee5e2b1732001-02-27 23:35:09 +000042Tommy Burnette, the original creator of manpy.
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000043Paul Prescod, for all his work on onlinehelp.
44Richard Chamberlain, for the first implementation of textdoc.
Raymond Hettingered2dbe32005-01-01 07:51:01 +000045"""
Ka-Ping Yeedd175342001-02-27 14:43:46 +000046
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000047# Known bugs that can't be fixed here:
48# - imp.load_module() cannot be prevented from clobbering existing
49# loaded modules, so calling synopsis() on a binary module file
50# changes the contents of any existing module with the same name.
51# - If the __file__ attribute on a module is a relative path and
52# the current directory is changed with os.chdir(), an incorrect
53# path will be displayed.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000054
Nick Coghlan7bb30b72010-12-03 09:29:11 +000055import os
56import sys
57import builtins
58import imp
59import io
60import inspect
61import pkgutil
62import platform
63import re
64import time
65import warnings
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000066from collections import deque
Nick Coghlan7bb30b72010-12-03 09:29:11 +000067from reprlib import Repr
Georg Brandld2f38572011-01-30 08:37:19 +000068from traceback import extract_tb, format_exception_only
Nick Coghlan7bb30b72010-12-03 09:29:11 +000069
70
Ka-Ping Yeedd175342001-02-27 14:43:46 +000071# --------------------------------------------------------- common routines
72
Ka-Ping Yeedd175342001-02-27 14:43:46 +000073def pathdirs():
74 """Convert sys.path into a list of absolute, existing, unique paths."""
75 dirs = []
Ka-Ping Yee1d384632001-03-01 00:24:32 +000076 normdirs = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +000077 for dir in sys.path:
78 dir = os.path.abspath(dir or '.')
Ka-Ping Yee1d384632001-03-01 00:24:32 +000079 normdir = os.path.normcase(dir)
80 if normdir not in normdirs and os.path.isdir(dir):
Ka-Ping Yeedd175342001-02-27 14:43:46 +000081 dirs.append(dir)
Ka-Ping Yee1d384632001-03-01 00:24:32 +000082 normdirs.append(normdir)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000083 return dirs
84
85def getdoc(object):
86 """Get the doc string or comments for an object."""
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000087 result = inspect.getdoc(object) or inspect.getcomments(object)
Neal Norwitz9d72bb42007-04-17 08:48:32 +000088 return result and re.sub('^ *\n', '', result.rstrip()) or ''
Ka-Ping Yeedd175342001-02-27 14:43:46 +000089
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000090def splitdoc(doc):
91 """Split a doc string into a synopsis line (if any) and the rest."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +000092 lines = doc.strip().split('\n')
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000093 if len(lines) == 1:
94 return lines[0], ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +000095 elif len(lines) >= 2 and not lines[1].rstrip():
96 return lines[0], '\n'.join(lines[2:])
97 return '', '\n'.join(lines)
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000098
Ka-Ping Yeedd175342001-02-27 14:43:46 +000099def classname(object, modname):
100 """Get a class name and qualify it with a module name if necessary."""
101 name = object.__name__
102 if object.__module__ != modname:
103 name = object.__module__ + '.' + name
104 return name
105
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000106def isdata(object):
Georg Brandl94432422005-07-22 21:52:25 +0000107 """Check if an object is of a type that probably means it's data."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000108 return not (inspect.ismodule(object) or inspect.isclass(object) or
109 inspect.isroutine(object) or inspect.isframe(object) or
110 inspect.istraceback(object) or inspect.iscode(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000111
112def replace(text, *pairs):
113 """Do a series of global replacements on a string."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000114 while pairs:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000115 text = pairs[1].join(text.split(pairs[0]))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000116 pairs = pairs[2:]
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000117 return text
118
119def cram(text, maxlen):
120 """Omit part of a string if needed to make it fit in a maximum length."""
121 if len(text) > maxlen:
Raymond Hettingerfca3bb62002-10-21 04:44:11 +0000122 pre = max(0, (maxlen-3)//2)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000123 post = max(0, maxlen-3-pre)
124 return text[:pre] + '...' + text[len(text)-post:]
125 return text
126
Brett Cannon84601f12004-06-19 01:22:48 +0000127_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000128def stripid(text):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000129 """Remove the hexadecimal id from a Python object representation."""
Brett Cannonc6c1f472004-06-19 01:02:51 +0000130 # The behaviour of %p is implementation-dependent in terms of case.
Ezio Melotti412c95a2010-02-16 23:31:04 +0000131 return _re_stripid.sub(r'\1', text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000132
Brett Cannonc6c1f472004-06-19 01:02:51 +0000133def _is_some_method(obj):
134 return inspect.ismethod(obj) or inspect.ismethoddescriptor(obj)
Tim Peters536d2262001-09-20 05:13:38 +0000135
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000136def allmethods(cl):
137 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000138 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000139 methods[key] = 1
140 for base in cl.__bases__:
141 methods.update(allmethods(base)) # all your base are belong to us
142 for key in methods.keys():
143 methods[key] = getattr(cl, key)
144 return methods
145
Tim Petersfa26f7c2001-09-24 08:05:11 +0000146def _split_list(s, predicate):
147 """Split sequence s via predicate, and return pair ([true], [false]).
148
149 The return value is a 2-tuple of lists,
150 ([x for x in s if predicate(x)],
151 [x for x in s if not predicate(x)])
152 """
153
Tim Peters28355492001-09-23 21:29:55 +0000154 yes = []
155 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000156 for x in s:
157 if predicate(x):
158 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000159 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000160 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000161 return yes, no
162
Raymond Hettinger1103d052011-03-25 14:15:24 -0700163def visiblename(name, all=None, obj=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000164 """Decide whether to show documentation on a variable."""
165 # Certain special names are redundant.
Raymond Hettinger68272942011-03-18 02:22:15 -0700166 if name in {'__builtins__', '__doc__', '__file__', '__path__',
Barry Warsaw28a691b2010-04-17 00:19:56 +0000167 '__module__', '__name__', '__slots__', '__package__',
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000168 '__cached__', '__author__', '__credits__', '__date__',
Raymond Hettinger68272942011-03-18 02:22:15 -0700169 '__version__'}:
170 return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000171 # Private names are hidden, but special names are displayed.
172 if name.startswith('__') and name.endswith('__'): return 1
Raymond Hettinger1103d052011-03-25 14:15:24 -0700173 # Namedtuples have public fields and methods with a single leading underscore
174 if name.startswith('_') and hasattr(obj, '_fields'):
175 return True
Skip Montanaroa5616d22004-06-11 04:46:12 +0000176 if all is not None:
177 # only document that which the programmer exported in __all__
178 return name in all
179 else:
180 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000181
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000182def classify_class_attrs(object):
183 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000184 results = []
185 for (name, kind, cls, value) in inspect.classify_class_attrs(object):
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000186 if inspect.isdatadescriptor(value):
187 kind = 'data descriptor'
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000188 results.append((name, kind, cls, value))
189 return results
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000190
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000191# ----------------------------------------------------- module manipulation
192
193def ispackage(path):
194 """Guess whether a path refers to a package directory."""
195 if os.path.isdir(path):
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000196 for ext in ('.py', '.pyc', '.pyo'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000197 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000198 return True
199 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000200
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000201def source_synopsis(file):
202 line = file.readline()
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000203 while line[:1] == '#' or not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000204 line = file.readline()
205 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000206 line = line.strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000207 if line[:4] == 'r"""': line = line[1:]
208 if line[:3] == '"""':
209 line = line[3:]
210 if line[-1:] == '\\': line = line[:-1]
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000211 while not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000212 line = file.readline()
213 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000214 result = line.split('"""')[0].strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000215 else: result = None
216 return result
217
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000218def synopsis(filename, cache={}):
219 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000220 mtime = os.stat(filename).st_mtime
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000221 lastupdate, result = cache.get(filename, (0, None))
222 if lastupdate < mtime:
223 info = inspect.getmoduleinfo(filename)
Georg Brandl26fd2e12006-03-08 09:34:53 +0000224 try:
225 file = open(filename)
226 except IOError:
227 # module can't be opened, so skip it
228 return None
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000229 if info and 'b' in info[2]: # binary modules have to be imported
230 try: module = imp.load_module('__temp__', file, filename, info[1:])
231 except: return None
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000232 result = (module.__doc__ or '').splitlines()[0]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000233 del sys.modules['__temp__']
234 else: # text modules can be directly examined
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000235 result = source_synopsis(file)
236 file.close()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000237 cache[filename] = (mtime, result)
238 return result
239
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000240class ErrorDuringImport(Exception):
241 """Errors that occurred while trying to import something to document it."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000242 def __init__(self, filename, exc_info):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000243 self.filename = filename
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000244 self.exc, self.value, self.tb = exc_info
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000245
246 def __str__(self):
Guido van Rossuma01a8b62007-05-27 09:20:14 +0000247 exc = self.exc.__name__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000248 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000249
250def importfile(path):
251 """Import a Python source file or compiled file given its path."""
252 magic = imp.get_magic()
253 file = open(path, 'r')
254 if file.read(len(magic)) == magic:
255 kind = imp.PY_COMPILED
256 else:
257 kind = imp.PY_SOURCE
258 file.close()
259 filename = os.path.basename(path)
260 name, ext = os.path.splitext(filename)
261 file = open(path, 'r')
262 try:
263 module = imp.load_module(name, file, path, (ext, 'r', kind))
264 except:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000265 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000266 file.close()
267 return module
268
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000269def safeimport(path, forceload=0, cache={}):
270 """Import a module; handle errors; return None if the module isn't found.
271
272 If the module *is* found but an exception occurs, it's wrapped in an
273 ErrorDuringImport exception and reraised. Unlike __import__, if a
274 package path is specified, the module at the end of the path is returned,
275 not the package at the beginning. If the optional 'forceload' argument
276 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000277 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000278 # If forceload is 1 and the module has been previously loaded from
279 # disk, we always have to reload the module. Checking the file's
280 # mtime isn't good enough (e.g. the module could contain a class
281 # that inherits from another module that has changed).
282 if forceload and path in sys.modules:
283 if path not in sys.builtin_module_names:
Guido van Rossume7ba4952007-06-06 23:52:48 +0000284 # Remove the module from sys.modules and re-import to try
285 # and avoid problems with partially loaded modules.
286 # Also remove any submodules because they won't appear
287 # in the newly loaded module's namespace if they're already
288 # in sys.modules.
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000289 subs = [m for m in sys.modules if m.startswith(path + '.')]
290 for key in [path] + subs:
291 # Prevent garbage collection.
292 cache[key] = sys.modules[key]
293 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000294 module = __import__(path)
295 except:
296 # Did the error occur before or after the module was found?
297 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000298 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000299 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000300 raise ErrorDuringImport(sys.modules[path].__file__, info)
301 elif exc is SyntaxError:
302 # A SyntaxError occurred before we could execute the module.
303 raise ErrorDuringImport(value.filename, info)
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000304 elif exc is ImportError and extract_tb(tb)[-1][2]=='safeimport':
Benjamin Peterson0289b152009-06-28 17:22:03 +0000305 # The import error occurred directly in this function,
306 # which means there is no such module in the path.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000307 return None
308 else:
309 # Some other error occurred during the importing process.
310 raise ErrorDuringImport(path, sys.exc_info())
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000311 for part in path.split('.')[1:]:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000312 try: module = getattr(module, part)
313 except AttributeError: return None
314 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000315
316# ---------------------------------------------------- formatter base class
317
318class Doc:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000319
320 PYTHONDOCS = os.environ.get("PYTHONDOCS",
321 "http://docs.python.org/%d.%d/library"
322 % sys.version_info[:2])
323
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000324 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000325 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000326 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000327 # 'try' clause is to attempt to handle the possibility that inspect
328 # identifies something in a way that pydoc itself has issues handling;
329 # think 'super' and how it is a descriptor (which raises the exception
330 # by lacking a __name__ attribute) and an instance.
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000331 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
332 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000333 try:
334 if inspect.ismodule(object): return self.docmodule(*args)
335 if inspect.isclass(object): return self.docclass(*args)
336 if inspect.isroutine(object): return self.docroutine(*args)
337 except AttributeError:
338 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000339 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000340 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000341
342 def fail(self, object, name=None, *args):
343 """Raise an exception for unimplemented types."""
344 message = "don't know how to document object%s of type %s" % (
345 name and ' ' + repr(name), type(object).__name__)
Collin Winterce36ad82007-08-30 01:19:48 +0000346 raise TypeError(message)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000347
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000348 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000349
Skip Montanaro4997a692003-09-10 16:47:51 +0000350 def getdocloc(self, object):
351 """Return the location of module docs or None"""
352
353 try:
354 file = inspect.getabsfile(object)
355 except TypeError:
356 file = '(built-in)'
357
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000358 docloc = os.environ.get("PYTHONDOCS", self.PYTHONDOCS)
359
Skip Montanaro4997a692003-09-10 16:47:51 +0000360 basedir = os.path.join(sys.exec_prefix, "lib",
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000361 "python%d.%d" % sys.version_info[:2])
Skip Montanaro4997a692003-09-10 16:47:51 +0000362 if (isinstance(object, type(os)) and
363 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
364 'marshal', 'posix', 'signal', 'sys',
Georg Brandl2067bfd2008-05-25 13:05:15 +0000365 '_thread', 'zipimport') or
Skip Montanaro4997a692003-09-10 16:47:51 +0000366 (file.startswith(basedir) and
Brian Curtin49c284c2010-03-31 03:19:28 +0000367 not file.startswith(os.path.join(basedir, 'site-packages')))) and
Brian Curtinedef05b2010-04-01 04:05:25 +0000368 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
Skip Montanaro4997a692003-09-10 16:47:51 +0000369 if docloc.startswith("http://"):
Georg Brandl86def6c2008-01-21 20:36:10 +0000370 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
Skip Montanaro4997a692003-09-10 16:47:51 +0000371 else:
Georg Brandl86def6c2008-01-21 20:36:10 +0000372 docloc = os.path.join(docloc, object.__name__ + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000373 else:
374 docloc = None
375 return docloc
376
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000377# -------------------------------------------- HTML documentation generator
378
379class HTMLRepr(Repr):
380 """Class for safely making an HTML representation of a Python object."""
381 def __init__(self):
382 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000383 self.maxlist = self.maxtuple = 20
384 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000385 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000386
387 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000388 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000389
390 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000391 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000392
393 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000394 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000395 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000396 if hasattr(self, methodname):
397 return getattr(self, methodname)(x, level)
398 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000399
400 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000401 test = cram(x, self.maxstring)
402 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000403 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000404 # Backslashes are only literal in the string and are never
405 # needed to make any special characters, so show a raw string.
406 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000407 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000408 r'<font color="#c040c0">\1</font>',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000409 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000410
Skip Montanarodf708782002-03-07 22:58:02 +0000411 repr_str = repr_string
412
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000413 def repr_instance(self, x, level):
414 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000415 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000416 except:
417 return self.escape('<%s instance>' % x.__class__.__name__)
418
419 repr_unicode = repr_string
420
421class HTMLDoc(Doc):
422 """Formatter class for HTML documentation."""
423
424 # ------------------------------------------- HTML formatting utilities
425
426 _repr_instance = HTMLRepr()
427 repr = _repr_instance.repr
428 escape = _repr_instance.escape
429
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000430 def page(self, title, contents):
431 """Format an HTML page."""
Georg Brandl388faac2009-04-10 08:31:48 +0000432 return '''\
Georg Brandle6066942009-04-10 08:28:28 +0000433<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000434<html><head><title>Python: %s</title>
Georg Brandl388faac2009-04-10 08:31:48 +0000435<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000436</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000437%s
438</body></html>''' % (title, contents)
439
440 def heading(self, title, fgcol, bgcol, extras=''):
441 """Format a page heading."""
442 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000443<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000444<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000445<td valign=bottom>&nbsp;<br>
446<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000447><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000448><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000449 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
450
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000451 def section(self, title, fgcol, bgcol, contents, width=6,
452 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000453 """Format a section with a heading."""
454 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000455 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000456 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000457<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000458<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000459<td colspan=3 valign=bottom>&nbsp;<br>
460<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000461 ''' % (bgcol, fgcol, title)
462 if prelude:
463 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000464<tr bgcolor="%s"><td rowspan=2>%s</td>
465<td colspan=2>%s</td></tr>
466<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
467 else:
468 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000469<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000470
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000471 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000472
473 def bigsection(self, title, *args):
474 """Format a section with a big heading."""
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000475 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000476 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000477
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000478 def preformat(self, text):
479 """Format literal preformatted text."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000480 text = self.escape(text.expandtabs())
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000481 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
482 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000483
484 def multicolumn(self, list, format, cols=4):
485 """Format a list of items into a multi-column list."""
486 result = ''
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000487 rows = (len(list)+cols-1)//cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000488 for col in range(cols):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000489 result = result + '<td width="%d%%" valign=top>' % (100//cols)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000490 for i in range(rows*col, rows*col+rows):
491 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000492 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000493 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000494 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000495
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000496 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000497
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000498 def namelink(self, name, *dicts):
499 """Make a link for an identifier, given name-to-URL mappings."""
500 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000501 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000502 return '<a href="%s">%s</a>' % (dict[name], name)
503 return name
504
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000505 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000506 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000507 name, module = object.__name__, sys.modules.get(object.__module__)
508 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000509 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000510 module.__name__, name, classname(object, modname))
511 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000512
513 def modulelink(self, object):
514 """Make a link for a module."""
515 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
516
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000517 def modpkglink(self, modpkginfo):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000518 """Make a link for a module or package to display in an index."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000519 name, path, ispackage, shadowed = modpkginfo
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000520 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000521 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000522 if path:
523 url = '%s.%s.html' % (path, name)
524 else:
525 url = '%s.html' % name
526 if ispackage:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000527 text = '<strong>%s</strong>&nbsp;(package)' % name
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000528 else:
529 text = name
530 return '<a href="%s">%s</a>' % (url, text)
531
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000532 def filelink(self, url, path):
533 """Make a link to source file."""
534 return '<a href="file:%s">%s</a>' % (url, path)
535
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000536 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
537 """Mark up some plain text, given a context of symbols to look for.
538 Each context dictionary maps object names to anchor names."""
539 escape = escape or self.escape
540 results = []
541 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000542 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
543 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000544 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000545 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000546 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000547 match = pattern.search(text, here)
548 if not match: break
549 start, end = match.span()
550 results.append(escape(text[here:start]))
551
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000552 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000553 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000554 url = escape(all).replace('"', '&quot;')
555 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000556 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000557 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
558 results.append('<a href="%s">%s</a>' % (url, escape(all)))
559 elif pep:
Christian Heimes2202f872008-02-06 14:31:34 +0000560 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000561 results.append('<a href="%s">%s</a>' % (url, escape(all)))
562 elif text[end:end+1] == '(':
563 results.append(self.namelink(name, methods, funcs, classes))
564 elif selfdot:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000565 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000566 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000567 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000568 here = end
569 results.append(escape(text[here:]))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000570 return ''.join(results)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000571
572 # ---------------------------------------------- type-specific routines
573
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000574 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000575 """Produce HTML for a class tree as given by inspect.getclasstree()."""
576 result = ''
577 for entry in tree:
578 if type(entry) is type(()):
579 c, bases = entry
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000580 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000581 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000582 if bases and bases != (parent,):
583 parents = []
584 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000585 parents.append(self.classlink(base, modname))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000586 result = result + '(' + ', '.join(parents) + ')'
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000587 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000588 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000589 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000590 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000591 return '<dl>\n%s</dl>\n' % result
592
Tim Peters8dd7ade2001-10-18 19:56:17 +0000593 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000594 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000595 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000596 try:
597 all = object.__all__
598 except AttributeError:
599 all = None
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000600 parts = name.split('.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000601 links = []
602 for i in range(len(parts)-1):
603 links.append(
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000604 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000605 ('.'.join(parts[:i+1]), parts[i]))
606 linkedname = '.'.join(links + parts[-1:])
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000607 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000608 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000609 path = inspect.getabsfile(object)
Ka-Ping Yee6191a232001-04-13 15:00:27 +0000610 url = path
611 if sys.platform == 'win32':
612 import nturl2path
613 url = nturl2path.pathname2url(path)
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000614 filelink = self.filelink(url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000615 except TypeError:
616 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000617 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000618 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000619 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000620 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000621 version = version[11:-1].strip()
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000622 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000623 if hasattr(object, '__date__'):
624 info.append(self.escape(str(object.__date__)))
625 if info:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000626 head = head + ' (%s)' % ', '.join(info)
Skip Montanaro4997a692003-09-10 16:47:51 +0000627 docloc = self.getdocloc(object)
628 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000629 docloc = '<br><a href="%(docloc)s">Module Reference</a>' % locals()
Skip Montanaro4997a692003-09-10 16:47:51 +0000630 else:
631 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000632 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000633 head, '#ffffff', '#7799ee',
634 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000635
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000636 modules = inspect.getmembers(object, inspect.ismodule)
637
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000638 classes, cdict = [], {}
639 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000640 # if __all__ exists, believe it. Otherwise use old heuristic.
641 if (all is not None or
642 (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700643 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000644 classes.append((key, value))
645 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000646 for key, value in classes:
647 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000648 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000649 module = sys.modules.get(modname)
650 if modname != name and module and hasattr(module, key):
651 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000652 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000653 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000654 funcs, fdict = [], {}
655 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000656 # if __all__ exists, believe it. Otherwise use old heuristic.
657 if (all is not None or
658 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700659 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000660 funcs.append((key, value))
661 fdict[key] = '#-' + key
662 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000663 data = []
664 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700665 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000666 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000667
668 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
669 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000670 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000671
672 if hasattr(object, '__path__'):
673 modpkgs = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000674 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
675 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000676 modpkgs.sort()
677 contents = self.multicolumn(modpkgs, self.modpkglink)
678 result = result + self.bigsection(
679 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000680 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000681 contents = self.multicolumn(
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000682 modules, lambda t: self.modulelink(t[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000683 result = result + self.bigsection(
Christian Heimes7131fd92008-02-19 14:21:46 +0000684 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000685
686 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000687 classlist = [value for (key, value) in classes]
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000688 contents = [
689 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000690 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000691 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000692 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000693 'Classes', '#ffffff', '#ee77aa', ' '.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000694 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000695 contents = []
696 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000697 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000698 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000699 'Functions', '#ffffff', '#eeaa77', ' '.join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000700 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000701 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000702 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000703 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000704 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000705 'Data', '#ffffff', '#55aa55', '<br>\n'.join(contents))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000706 if hasattr(object, '__author__'):
707 contents = self.markup(str(object.__author__), self.preformat)
708 result = result + self.bigsection(
709 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000710 if hasattr(object, '__credits__'):
711 contents = self.markup(str(object.__credits__), self.preformat)
712 result = result + self.bigsection(
713 'Credits', '#ffffff', '#7799ee', contents)
714
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000715 return result
716
Tim Peters8dd7ade2001-10-18 19:56:17 +0000717 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
718 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000719 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000720 realname = object.__name__
721 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000722 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000723
Tim Petersb47879b2001-09-24 04:47:19 +0000724 contents = []
725 push = contents.append
726
Tim Petersfa26f7c2001-09-24 08:05:11 +0000727 # Cute little class to pump out a horizontal rule between sections.
728 class HorizontalRule:
729 def __init__(self):
730 self.needone = 0
731 def maybe(self):
732 if self.needone:
733 push('<hr>\n')
734 self.needone = 1
735 hr = HorizontalRule()
736
Tim Petersc86f6ca2001-09-26 21:31:51 +0000737 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000738 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000739 if len(mro) > 2:
740 hr.maybe()
741 push('<dl><dt>Method resolution order:</dt>\n')
742 for base in mro:
743 push('<dd>%s</dd>\n' % self.classlink(base,
744 object.__module__))
745 push('</dl>\n')
746
Tim Petersb47879b2001-09-24 04:47:19 +0000747 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000748 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000749 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000750 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000751 push(msg)
752 for name, kind, homecls, value in ok:
753 push(self.document(getattr(object, name), name, mod,
754 funcs, classes, mdict, object))
755 push('\n')
756 return attrs
757
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000758 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000759 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000760 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000761 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000762 push(msg)
763 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000764 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000765 return attrs
766
Tim Petersfa26f7c2001-09-24 08:05:11 +0000767 def spilldata(msg, attrs, predicate):
768 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000769 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000770 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000771 push(msg)
772 for name, kind, homecls, value in ok:
773 base = self.docother(getattr(object, name), name, mod)
Guido van Rossumd59da4b2007-05-22 18:11:13 +0000774 if hasattr(value, '__call__') or inspect.isdatadescriptor(value):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000775 doc = getattr(value, "__doc__", None)
776 else:
777 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000778 if doc is None:
779 push('<dl><dt>%s</dl>\n' % base)
780 else:
781 doc = self.markup(getdoc(value), self.preformat,
782 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000783 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000784 push('<dl><dt>%s%s</dl>\n' % (base, doc))
785 push('\n')
786 return attrs
787
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000788 attrs = [(name, kind, cls, value)
789 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -0700790 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000791
Tim Petersb47879b2001-09-24 04:47:19 +0000792 mdict = {}
793 for key, kind, homecls, value in attrs:
794 mdict[key] = anchor = '#' + name + '-' + key
795 value = getattr(object, key)
796 try:
797 # The value may not be hashable (e.g., a data attr with
798 # a dict or list value).
799 mdict[value] = anchor
800 except TypeError:
801 pass
802
Tim Petersfa26f7c2001-09-24 08:05:11 +0000803 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000804 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000805 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000806 else:
807 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000808 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
809
Georg Brandl1a3284e2007-12-02 09:40:06 +0000810 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000811 attrs = inherited
812 continue
813 elif thisclass is object:
814 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000815 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000816 tag = 'inherited from %s' % self.classlink(thisclass,
817 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000818 tag += ':<br>\n'
819
820 # Sort attrs by name.
Raymond Hettingerd4cb56d2008-01-30 02:55:10 +0000821 attrs.sort(key=lambda t: t[0])
Tim Petersb47879b2001-09-24 04:47:19 +0000822
823 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000824 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000825 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000826 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000827 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000828 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000829 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000830 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
831 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000832 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000833 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000834 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000835 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000836
837 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000838
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000839 if name == realname:
840 title = '<a name="%s">class <strong>%s</strong></a>' % (
841 name, realname)
842 else:
843 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
844 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000845 if bases:
846 parents = []
847 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000848 parents.append(self.classlink(base, object.__module__))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000849 title = title + '(%s)' % ', '.join(parents)
Tim Peters2306d242001-09-25 03:18:32 +0000850 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000851 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000852
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000853 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000854
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000855 def formatvalue(self, object):
856 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000857 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000858
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000859 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000860 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000861 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000862 realname = object.__name__
863 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000864 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000865 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000866 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000867 if inspect.ismethod(object):
Christian Heimesff737952007-11-27 10:40:20 +0000868 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000869 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000870 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000871 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000872 else:
Christian Heimesff737952007-11-27 10:40:20 +0000873 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000874 note = ' method of %s instance' % self.classlink(
Christian Heimesff737952007-11-27 10:40:20 +0000875 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000876 else:
877 note = ' unbound %s method' % self.classlink(imclass,mod)
Christian Heimesff737952007-11-27 10:40:20 +0000878 object = object.__func__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000879
880 if name == realname:
881 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
882 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000883 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000884 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000885 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000886 cl.__name__ + '-' + realname, realname)
887 skipdocs = 1
888 else:
889 reallink = realname
890 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
891 anchor, name, reallink)
Tim Peters4bcfa312001-09-20 06:08:24 +0000892 if inspect.isfunction(object):
Guido van Rossum2e65f892007-02-28 22:03:49 +0000893 args, varargs, kwonlyargs, kwdefaults, varkw, defaults, ann = \
894 inspect.getfullargspec(object)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000895 argspec = inspect.formatargspec(
Guido van Rossum2e65f892007-02-28 22:03:49 +0000896 args, varargs, kwonlyargs, kwdefaults, varkw, defaults, ann,
897 formatvalue=self.formatvalue,
898 formatannotation=inspect.formatannotationrelativeto(object))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000899 if realname == '<lambda>':
Tim Peters59ed4482001-10-31 04:20:26 +0000900 title = '<strong>%s</strong> <em>lambda</em> ' % name
Guido van Rossum2e65f892007-02-28 22:03:49 +0000901 # XXX lambda's won't usually have func_annotations['return']
902 # since the syntax doesn't support but it is possible.
903 # So removing parentheses isn't truly safe.
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000904 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +0000905 else:
906 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000907
Tim Peters2306d242001-09-25 03:18:32 +0000908 decl = title + argspec + (note and self.grey(
909 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000910
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000911 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000912 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000913 else:
914 doc = self.markup(
915 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000916 doc = doc and '<dd><tt>%s</tt></dd>' % doc
917 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000918
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000919 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000920 results = []
921 push = results.append
922
923 if name:
924 push('<dl><dt><strong>%s</strong></dt>\n' % name)
925 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000926 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000927 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000928 push('</dl>\n')
929
930 return ''.join(results)
931
932 def docproperty(self, object, name=None, mod=None, cl=None):
933 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000934 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000935
Tim Peters8dd7ade2001-10-18 19:56:17 +0000936 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000937 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000938 lhs = name and '<strong>%s</strong> = ' % name or ''
939 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000940
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000941 def docdata(self, object, name=None, mod=None, cl=None):
942 """Produce html documentation for a data descriptor."""
943 return self._docdescriptor(name, object, mod)
944
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000945 def index(self, dir, shadowed=None):
946 """Generate an HTML index for a directory of modules."""
947 modpkgs = []
948 if shadowed is None: shadowed = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000949 for importer, name, ispkg in pkgutil.iter_modules([dir]):
Victor Stinner4d652242011-04-12 23:41:50 +0200950 if any((0xD800 <= ord(ch) <= 0xDFFF) for ch in name):
951 # ignore a module if its name contains a surrogate character
952 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000953 modpkgs.append((name, '', ispkg, name in shadowed))
954 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000955
956 modpkgs.sort()
957 contents = self.multicolumn(modpkgs, self.modpkglink)
958 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
959
960# -------------------------------------------- text documentation generator
961
962class TextRepr(Repr):
963 """Class for safely making a text representation of a Python object."""
964 def __init__(self):
965 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000966 self.maxlist = self.maxtuple = 20
967 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000968 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000969
970 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000971 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000972 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000973 if hasattr(self, methodname):
974 return getattr(self, methodname)(x, level)
975 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000976
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000977 def repr_string(self, x, level):
978 test = cram(x, self.maxstring)
979 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000980 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000981 # Backslashes are only literal in the string and are never
982 # needed to make any special characters, so show a raw string.
983 return 'r' + testrepr[0] + test + testrepr[0]
984 return testrepr
985
Skip Montanarodf708782002-03-07 22:58:02 +0000986 repr_str = repr_string
987
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000988 def repr_instance(self, x, level):
989 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000990 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000991 except:
992 return '<%s instance>' % x.__class__.__name__
993
994class TextDoc(Doc):
995 """Formatter class for text documentation."""
996
997 # ------------------------------------------- text formatting utilities
998
999 _repr_instance = TextRepr()
1000 repr = _repr_instance.repr
1001
1002 def bold(self, text):
1003 """Format a string in bold by overstriking."""
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001004 return ''.join(ch + '\b' + ch for ch in text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001005
1006 def indent(self, text, prefix=' '):
1007 """Indent text by prepending a given prefix to each line."""
1008 if not text: return ''
Collin Winter72e110c2007-07-17 00:27:30 +00001009 lines = [prefix + line for line in text.split('\n')]
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001010 if lines: lines[-1] = lines[-1].rstrip()
1011 return '\n'.join(lines)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001012
1013 def section(self, title, contents):
1014 """Format a section with a given heading."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001015 clean_contents = self.indent(contents).rstrip()
1016 return self.bold(title) + '\n' + clean_contents + '\n\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001017
1018 # ---------------------------------------------- type-specific routines
1019
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001020 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001021 """Render in text a class tree as returned by inspect.getclasstree()."""
1022 result = ''
1023 for entry in tree:
1024 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001025 c, bases = entry
1026 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001027 if bases and bases != (parent,):
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001028 parents = (classname(c, modname) for c in bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001029 result = result + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001030 result = result + '\n'
1031 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001032 result = result + self.formattree(
1033 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001034 return result
1035
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001036 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001037 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001038 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001039 synop, desc = splitdoc(getdoc(object))
1040 result = self.section('NAME', name + (synop and ' - ' + synop))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001041 all = getattr(object, '__all__', None)
Skip Montanaro4997a692003-09-10 16:47:51 +00001042 docloc = self.getdocloc(object)
1043 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001044 result = result + self.section('MODULE REFERENCE', docloc + """
1045
1046The following documentation is automatically generated from the Python source
1047files. It may be incomplete, incorrect or include features that are considered
1048implementation detail and may vary between Python implementations. When in
1049doubt, consult the module reference at the location listed above.
1050""")
Skip Montanaro4997a692003-09-10 16:47:51 +00001051
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001052 if desc:
1053 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001054
1055 classes = []
1056 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001057 # if __all__ exists, believe it. Otherwise use old heuristic.
1058 if (all is not None
1059 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001060 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001061 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001062 funcs = []
1063 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001064 # if __all__ exists, believe it. Otherwise use old heuristic.
1065 if (all is not None or
1066 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001067 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001068 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001069 data = []
1070 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001071 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001072 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001073
Christian Heimes1af737c2008-01-23 08:24:23 +00001074 modpkgs = []
1075 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001076 if hasattr(object, '__path__'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001077 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Christian Heimes1af737c2008-01-23 08:24:23 +00001078 modpkgs_names.add(modname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001079 if ispkg:
1080 modpkgs.append(modname + ' (package)')
1081 else:
1082 modpkgs.append(modname)
1083
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001084 modpkgs.sort()
1085 result = result + self.section(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001086 'PACKAGE CONTENTS', '\n'.join(modpkgs))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001087
Christian Heimes1af737c2008-01-23 08:24:23 +00001088 # Detect submodules as sometimes created by C extensions
1089 submodules = []
1090 for key, value in inspect.getmembers(object, inspect.ismodule):
1091 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1092 submodules.append(key)
1093 if submodules:
1094 submodules.sort()
1095 result = result + self.section(
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001096 'SUBMODULES', '\n'.join(submodules))
Christian Heimes1af737c2008-01-23 08:24:23 +00001097
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001098 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001099 classlist = [value for key, value in classes]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001100 contents = [self.formattree(
1101 inspect.getclasstree(classlist, 1), name)]
1102 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001103 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001104 result = result + self.section('CLASSES', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001105
1106 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001107 contents = []
1108 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001109 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001110 result = result + self.section('FUNCTIONS', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001111
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001112 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001113 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001114 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001115 contents.append(self.docother(value, key, name, maxlen=70))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001116 result = result + self.section('DATA', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001117
1118 if hasattr(object, '__version__'):
1119 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001120 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001121 version = version[11:-1].strip()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001122 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001123 if hasattr(object, '__date__'):
1124 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001125 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001126 result = result + self.section('AUTHOR', str(object.__author__))
1127 if hasattr(object, '__credits__'):
1128 result = result + self.section('CREDITS', str(object.__credits__))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001129 try:
1130 file = inspect.getabsfile(object)
1131 except TypeError:
1132 file = '(built-in)'
1133 result = result + self.section('FILE', file)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001134 return result
1135
Georg Brandl9bd45f992010-12-03 09:58:38 +00001136 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001137 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001138 realname = object.__name__
1139 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001140 bases = object.__bases__
1141
Tim Petersc86f6ca2001-09-26 21:31:51 +00001142 def makename(c, m=object.__module__):
1143 return classname(c, m)
1144
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001145 if name == realname:
1146 title = 'class ' + self.bold(realname)
1147 else:
1148 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001149 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001150 parents = map(makename, bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001151 title = title + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001152
1153 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001154 contents = doc and [doc + '\n'] or []
1155 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001156
Tim Petersc86f6ca2001-09-26 21:31:51 +00001157 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001158 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001159 if len(mro) > 2:
1160 push("Method resolution order:")
1161 for base in mro:
1162 push(' ' + makename(base))
1163 push('')
1164
Tim Petersf4aad8e2001-09-24 22:40:47 +00001165 # Cute little class to pump out a horizontal rule between sections.
1166 class HorizontalRule:
1167 def __init__(self):
1168 self.needone = 0
1169 def maybe(self):
1170 if self.needone:
1171 push('-' * 70)
1172 self.needone = 1
1173 hr = HorizontalRule()
1174
Tim Peters28355492001-09-23 21:29:55 +00001175 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001176 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001177 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001178 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001179 push(msg)
1180 for name, kind, homecls, value in ok:
1181 push(self.document(getattr(object, name),
1182 name, mod, object))
1183 return attrs
1184
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001185 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001186 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001187 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001188 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001189 push(msg)
1190 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001191 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001192 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001193
Tim Petersfa26f7c2001-09-24 08:05:11 +00001194 def spilldata(msg, attrs, predicate):
1195 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001196 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001197 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001198 push(msg)
1199 for name, kind, homecls, value in ok:
Guido van Rossumd59da4b2007-05-22 18:11:13 +00001200 if hasattr(value, '__call__') or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001201 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001202 else:
1203 doc = None
Tim Peters28355492001-09-23 21:29:55 +00001204 push(self.docother(getattr(object, name),
Georg Brandl8b813db2005-10-01 16:32:31 +00001205 name, mod, maxlen=70, doc=doc) + '\n')
Tim Peters28355492001-09-23 21:29:55 +00001206 return attrs
1207
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001208 attrs = [(name, kind, cls, value)
1209 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -07001210 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001211
Tim Petersfa26f7c2001-09-24 08:05:11 +00001212 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001213 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001214 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001215 else:
1216 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001217 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1218
Georg Brandl1a3284e2007-12-02 09:40:06 +00001219 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001220 attrs = inherited
1221 continue
1222 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001223 tag = "defined here"
1224 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001225 tag = "inherited from %s" % classname(thisclass,
1226 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001227
1228 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001229 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001230
1231 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001232 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001233 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001234 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001235 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001236 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001237 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001238 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1239 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001240 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1241 lambda t: t[1] == 'data')
Tim Peters28355492001-09-23 21:29:55 +00001242 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001243 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001244
1245 contents = '\n'.join(contents)
1246 if not contents:
1247 return title + '\n'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001248 return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001249
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001250 def formatvalue(self, object):
1251 """Format an argument default value as text."""
1252 return '=' + self.repr(object)
1253
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001254 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001255 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001256 realname = object.__name__
1257 name = name or realname
1258 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001259 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001260 if inspect.ismethod(object):
Christian Heimesff737952007-11-27 10:40:20 +00001261 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001262 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001263 if imclass is not cl:
1264 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001265 else:
Christian Heimesff737952007-11-27 10:40:20 +00001266 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001267 note = ' method of %s instance' % classname(
Christian Heimesff737952007-11-27 10:40:20 +00001268 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001269 else:
1270 note = ' unbound %s method' % classname(imclass,mod)
Christian Heimesff737952007-11-27 10:40:20 +00001271 object = object.__func__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001272
1273 if name == realname:
1274 title = self.bold(realname)
1275 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001276 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001277 cl.__dict__[realname] is object):
1278 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001279 title = self.bold(name) + ' = ' + realname
Tim Peters4bcfa312001-09-20 06:08:24 +00001280 if inspect.isfunction(object):
Guido van Rossum2e65f892007-02-28 22:03:49 +00001281 args, varargs, varkw, defaults, kwonlyargs, kwdefaults, ann = \
1282 inspect.getfullargspec(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001283 argspec = inspect.formatargspec(
Guido van Rossum2e65f892007-02-28 22:03:49 +00001284 args, varargs, varkw, defaults, kwonlyargs, kwdefaults, ann,
1285 formatvalue=self.formatvalue,
1286 formatannotation=inspect.formatannotationrelativeto(object))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001287 if realname == '<lambda>':
Georg Brandl501dd0d2006-02-17 09:45:40 +00001288 title = self.bold(name) + ' lambda '
Guido van Rossum2e65f892007-02-28 22:03:49 +00001289 # XXX lambda's won't usually have func_annotations['return']
1290 # since the syntax doesn't support but it is possible.
1291 # So removing parentheses isn't truly safe.
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001292 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +00001293 else:
1294 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001295 decl = title + argspec + note
1296
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001297 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001298 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001299 else:
1300 doc = getdoc(object) or ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001301 return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001302
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001303 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001304 results = []
1305 push = results.append
1306
1307 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001308 push(self.bold(name))
1309 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001310 doc = getdoc(value) or ''
1311 if doc:
1312 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001313 push('\n')
1314 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001315
1316 def docproperty(self, object, name=None, mod=None, cl=None):
1317 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001318 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001319
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001320 def docdata(self, object, name=None, mod=None, cl=None):
1321 """Produce text documentation for a data descriptor."""
1322 return self._docdescriptor(name, object, mod)
1323
Georg Brandl8b813db2005-10-01 16:32:31 +00001324 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001325 """Produce text documentation for a data object."""
1326 repr = self.repr(object)
1327 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001328 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001329 chop = maxlen - len(line)
1330 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001331 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001332 if doc is not None:
1333 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001334 return line
1335
Georg Brandld80d5f42010-12-03 07:47:22 +00001336class _PlainTextDoc(TextDoc):
1337 """Subclass of TextDoc which overrides string styling"""
1338 def bold(self, text):
1339 return text
1340
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001341# --------------------------------------------------------- user interfaces
1342
1343def pager(text):
1344 """The first time this is called, determine what kind of pager to use."""
1345 global pager
1346 pager = getpager()
1347 pager(text)
1348
1349def getpager():
1350 """Decide what method to use for paging through text."""
Guido van Rossuma01a8b62007-05-27 09:20:14 +00001351 if not hasattr(sys.stdout, "isatty"):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001352 return plainpager
1353 if not sys.stdin.isatty() or not sys.stdout.isatty():
1354 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001355 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001356 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001357 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001358 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001359 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001360 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001361 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001362 if os.environ.get('TERM') in ('dumb', 'emacs'):
1363 return plainpager
Andrew MacIntyre54e0eab2002-03-03 03:12:30 +00001364 if sys.platform == 'win32' or sys.platform.startswith('os2'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001365 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001366 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001367 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001368
1369 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001370 (fd, filename) = tempfile.mkstemp()
1371 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001372 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001373 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001374 return lambda text: pipepager(text, 'more')
1375 else:
1376 return ttypager
1377 finally:
1378 os.unlink(filename)
1379
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001380def plain(text):
1381 """Remove boldface formatting from text."""
1382 return re.sub('.\b', '', text)
1383
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001384def pipepager(text, cmd):
1385 """Page through text by feeding it to another program."""
1386 pipe = os.popen(cmd, 'w')
1387 try:
1388 pipe.write(text)
1389 pipe.close()
1390 except IOError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001391 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001392
1393def tempfilepager(text, cmd):
1394 """Page through text by invoking a program on a temporary file."""
1395 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001396 filename = tempfile.mktemp()
1397 file = open(filename, 'w')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001398 file.write(text)
1399 file.close()
1400 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001401 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001402 finally:
1403 os.unlink(filename)
1404
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001405def ttypager(text):
1406 """Page through text on a text terminal."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001407 lines = plain(text).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001408 try:
1409 import tty
1410 fd = sys.stdin.fileno()
1411 old = tty.tcgetattr(fd)
1412 tty.setcbreak(fd)
1413 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001414 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001415 tty = None
1416 getchar = lambda: sys.stdin.readline()[:-1][:1]
1417
1418 try:
1419 r = inc = os.environ.get('LINES', 25) - 1
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001420 sys.stdout.write('\n'.join(lines[:inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001421 while lines[r:]:
1422 sys.stdout.write('-- more --')
1423 sys.stdout.flush()
1424 c = getchar()
1425
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001426 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001427 sys.stdout.write('\r \r')
1428 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001429 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001430 sys.stdout.write('\r \r' + lines[r] + '\n')
1431 r = r + 1
1432 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001433 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001434 r = r - inc - inc
1435 if r < 0: r = 0
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001436 sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001437 r = r + inc
1438
1439 finally:
1440 if tty:
1441 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1442
1443def plainpager(text):
1444 """Simply print unformatted text. This is the ultimate fallback."""
1445 sys.stdout.write(plain(text))
1446
1447def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001448 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001449 if inspect.ismodule(thing):
1450 if thing.__name__ in sys.builtin_module_names:
1451 return 'built-in module ' + thing.__name__
1452 if hasattr(thing, '__path__'):
1453 return 'package ' + thing.__name__
1454 else:
1455 return 'module ' + thing.__name__
1456 if inspect.isbuiltin(thing):
1457 return 'built-in function ' + thing.__name__
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001458 if inspect.isgetsetdescriptor(thing):
1459 return 'getset descriptor %s.%s.%s' % (
1460 thing.__objclass__.__module__, thing.__objclass__.__name__,
1461 thing.__name__)
1462 if inspect.ismemberdescriptor(thing):
1463 return 'member descriptor %s.%s.%s' % (
1464 thing.__objclass__.__module__, thing.__objclass__.__name__,
1465 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001466 if inspect.isclass(thing):
1467 return 'class ' + thing.__name__
1468 if inspect.isfunction(thing):
1469 return 'function ' + thing.__name__
1470 if inspect.ismethod(thing):
1471 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001472 return type(thing).__name__
1473
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001474def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001475 """Locate an object by name or dotted path, importing as necessary."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001476 parts = [part for part in path.split('.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001477 module, n = None, 0
1478 while n < len(parts):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001479 nextmodule = safeimport('.'.join(parts[:n+1]), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001480 if nextmodule: module, n = nextmodule, n + 1
1481 else: break
1482 if module:
1483 object = module
1484 for part in parts[n:]:
1485 try: object = getattr(object, part)
1486 except AttributeError: return None
1487 return object
1488 else:
Georg Brandl1a3284e2007-12-02 09:40:06 +00001489 if hasattr(builtins, path):
1490 return getattr(builtins, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001491
1492# --------------------------------------- interactive interpreter interface
1493
1494text = TextDoc()
Georg Brandld80d5f42010-12-03 07:47:22 +00001495plaintext = _PlainTextDoc()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001496html = HTMLDoc()
1497
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001498def resolve(thing, forceload=0):
1499 """Given an object or a path to an object, get the object and its name."""
1500 if isinstance(thing, str):
1501 object = locate(thing, forceload)
1502 if not object:
Collin Winterce36ad82007-08-30 01:19:48 +00001503 raise ImportError('no Python documentation found for %r' % thing)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001504 return object, thing
1505 else:
1506 return thing, getattr(thing, '__name__', None)
1507
Georg Brandld80d5f42010-12-03 07:47:22 +00001508def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
1509 renderer=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001510 """Render text documentation, given an object or a path to an object."""
Georg Brandld80d5f42010-12-03 07:47:22 +00001511 if renderer is None:
1512 renderer = text
Guido van Rossumd8faa362007-04-27 19:54:29 +00001513 object, name = resolve(thing, forceload)
1514 desc = describe(object)
1515 module = inspect.getmodule(object)
1516 if name and '.' in name:
1517 desc += ' in ' + name[:name.rfind('.')]
1518 elif module and module is not object:
1519 desc += ' in module ' + module.__name__
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001520
1521 if not (inspect.ismodule(object) or
Guido van Rossumd8faa362007-04-27 19:54:29 +00001522 inspect.isclass(object) or
1523 inspect.isroutine(object) or
1524 inspect.isgetsetdescriptor(object) or
1525 inspect.ismemberdescriptor(object) or
1526 isinstance(object, property)):
1527 # If the passed object is a piece of data or an instance,
1528 # document its available methods instead of its value.
1529 object = type(object)
1530 desc += ' object'
Georg Brandld80d5f42010-12-03 07:47:22 +00001531 return title % desc + '\n\n' + renderer.document(object, name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001532
Georg Brandld80d5f42010-12-03 07:47:22 +00001533def doc(thing, title='Python Library Documentation: %s', forceload=0,
1534 output=None):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001535 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001536 try:
Georg Brandld80d5f42010-12-03 07:47:22 +00001537 if output is None:
1538 pager(render_doc(thing, title, forceload))
1539 else:
1540 output.write(render_doc(thing, title, forceload, plaintext))
Guido van Rossumb940e112007-01-10 16:19:56 +00001541 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001542 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001543
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001544def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001545 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001546 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001547 object, name = resolve(thing, forceload)
1548 page = html.page(describe(object), html.document(object, name))
Georg Brandl388faac2009-04-10 08:31:48 +00001549 file = open(name + '.html', 'w', encoding='utf-8')
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001550 file.write(page)
1551 file.close()
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001552 print('wrote', name + '.html')
Guido van Rossumb940e112007-01-10 16:19:56 +00001553 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001554 print(value)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001555
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001556def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001557 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001558 if done is None: done = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001559 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1560 writedoc(modname)
1561 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001562
1563class Helper:
Georg Brandl6b38daa2008-06-01 21:05:17 +00001564
1565 # These dictionaries map a topic name to either an alias, or a tuple
1566 # (label, seealso-items). The "label" is the label of the corresponding
1567 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl5617db82009-04-27 16:28:57 +00001568 # in pydoc_data/topics.py.
Georg Brandl6b38daa2008-06-01 21:05:17 +00001569 #
1570 # CAUTION: if you change one of these dictionaries, be sure to adapt the
1571 # list of needed labels in Doc/tools/sphinxext/pyspecific.py and
Georg Brandl5617db82009-04-27 16:28:57 +00001572 # regenerate the pydoc_data/topics.py file by running
Georg Brandl6b38daa2008-06-01 21:05:17 +00001573 # make pydoc-topics
1574 # in Doc/ and copying the output file into the Lib/ directory.
1575
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001576 keywords = {
Ezio Melottib185a042011-04-28 07:42:55 +03001577 'False': '',
1578 'None': '',
1579 'True': '',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001580 'and': 'BOOLEAN',
Guido van Rossumd8faa362007-04-27 19:54:29 +00001581 'as': 'with',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001582 'assert': ('assert', ''),
1583 'break': ('break', 'while for'),
1584 'class': ('class', 'CLASSES SPECIALMETHODS'),
1585 'continue': ('continue', 'while for'),
1586 'def': ('function', ''),
1587 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001588 'elif': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001589 'else': ('else', 'while for'),
Georg Brandl0d855392008-08-30 19:53:05 +00001590 'except': 'try',
1591 'finally': 'try',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001592 'for': ('for', 'break continue while'),
Georg Brandl0d855392008-08-30 19:53:05 +00001593 'from': 'import',
Georg Brandl74abf6f2010-11-20 19:54:36 +00001594 'global': ('global', 'nonlocal NAMESPACES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001595 'if': ('if', 'TRUTHVALUE'),
1596 'import': ('import', 'MODULES'),
Georg Brandl395ed242009-09-04 08:07:32 +00001597 'in': ('in', 'SEQUENCEMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001598 'is': 'COMPARISON',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001599 'lambda': ('lambda', 'FUNCTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001600 'nonlocal': ('nonlocal', 'global NAMESPACES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001601 'not': 'BOOLEAN',
1602 'or': 'BOOLEAN',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001603 'pass': ('pass', ''),
1604 'raise': ('raise', 'EXCEPTIONS'),
1605 'return': ('return', 'FUNCTIONS'),
1606 'try': ('try', 'EXCEPTIONS'),
1607 'while': ('while', 'break continue if TRUTHVALUE'),
1608 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1609 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001610 }
Georg Brandldb7b6b92009-01-01 15:53:14 +00001611 # Either add symbols to this dictionary or to the symbols dictionary
1612 # directly: Whichever is easier. They are merged later.
1613 _symbols_inverse = {
1614 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'),
1615 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1616 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1617 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1618 'UNARY' : ('-', '~'),
1619 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1620 '^=', '<<=', '>>=', '**=', '//='),
1621 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1622 'COMPLEX' : ('j', 'J')
1623 }
1624 symbols = {
1625 '%': 'OPERATORS FORMATTING',
1626 '**': 'POWER',
1627 ',': 'TUPLES LISTS FUNCTIONS',
1628 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1629 '...': 'ELLIPSIS',
1630 ':': 'SLICINGS DICTIONARYLITERALS',
1631 '@': 'def class',
1632 '\\': 'STRINGS',
1633 '_': 'PRIVATENAMES',
1634 '__': 'PRIVATENAMES SPECIALMETHODS',
1635 '`': 'BACKQUOTES',
1636 '(': 'TUPLES FUNCTIONS CALLS',
1637 ')': 'TUPLES FUNCTIONS CALLS',
1638 '[': 'LISTS SUBSCRIPTS SLICINGS',
1639 ']': 'LISTS SUBSCRIPTS SLICINGS'
1640 }
1641 for topic, symbols_ in _symbols_inverse.items():
1642 for symbol in symbols_:
1643 topics = symbols.get(symbol, topic)
1644 if topic not in topics:
1645 topics = topics + ' ' + topic
1646 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001647
1648 topics = {
Georg Brandl6b38daa2008-06-01 21:05:17 +00001649 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1650 'FUNCTIONS CLASSES MODULES FILES inspect'),
1651 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS '
1652 'FORMATTING TYPES'),
1653 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1654 'FORMATTING': ('formatstrings', 'OPERATORS'),
1655 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1656 'FORMATTING TYPES'),
1657 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1658 'INTEGER': ('integers', 'int range'),
1659 'FLOAT': ('floating', 'float math'),
1660 'COMPLEX': ('imaginary', 'complex cmath'),
1661 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING range LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001662 'MAPPINGS': 'DICTIONARIES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001663 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1664 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1665 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1666 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001667 'FRAMEOBJECTS': 'TYPES',
1668 'TRACEBACKS': 'TYPES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001669 'NONE': ('bltin-null-object', ''),
1670 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
1671 'FILES': ('bltin-file-objects', ''),
1672 'SPECIALATTRIBUTES': ('specialattrs', ''),
1673 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1674 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001675 'PACKAGES': 'import',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001676 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1677 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1678 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1679 'LISTS DICTIONARIES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001680 'OPERATORS': 'EXPRESSIONS',
1681 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001682 'OBJECTS': ('objects', 'TYPES'),
1683 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
Georg Brandl395ed242009-09-04 08:07:32 +00001684 'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS '
1685 'NUMBERMETHODS CLASSES'),
Mark Dickinsona56c4672009-01-27 18:17:45 +00001686 'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001687 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1688 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001689 'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS '
Georg Brandl6b38daa2008-06-01 21:05:17 +00001690 'SPECIALMETHODS'),
1691 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1692 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1693 'SPECIALMETHODS'),
1694 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001695 'NAMESPACES': ('naming', 'global nonlocal ASSIGNMENT DELETION DYNAMICFEATURES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001696 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001697 'SCOPING': 'NAMESPACES',
1698 'FRAMES': 'NAMESPACES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001699 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1700 'CONVERSIONS': ('conversions', ''),
1701 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1702 'SPECIALIDENTIFIERS': ('id-classes', ''),
1703 'PRIVATENAMES': ('atom-identifiers', ''),
1704 'LITERALS': ('atom-literals', 'STRINGS NUMBERS TUPLELITERALS '
1705 'LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001706 'TUPLES': 'SEQUENCES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001707 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1708 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1709 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1710 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1711 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1712 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001713 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'),
1714 'SLICINGS': ('slicings', 'SEQUENCEMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001715 'CALLS': ('calls', 'EXPRESSIONS'),
1716 'POWER': ('power', 'EXPRESSIONS'),
1717 'UNARY': ('unary', 'EXPRESSIONS'),
1718 'BINARY': ('binary', 'EXPRESSIONS'),
1719 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1720 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1721 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1722 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001723 'ASSERTION': 'assert',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001724 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1725 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001726 'DELETION': 'del',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001727 'RETURNING': 'return',
1728 'IMPORTING': 'import',
1729 'CONDITIONAL': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001730 'LOOPING': ('compound', 'for while break continue'),
1731 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1732 'DEBUGGING': ('debugger', 'pdb'),
1733 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001734 }
1735
Georg Brandl78aa3962010-07-31 21:51:48 +00001736 def __init__(self, input=None, output=None):
1737 self._input = input
1738 self._output = output
1739
Georg Brandl76ae3972010-08-01 06:32:55 +00001740 input = property(lambda self: self._input or sys.stdin)
1741 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001742
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001743 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001744 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001745 self()
1746 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001747 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001748
Alexander Belopolsky2e733c92010-07-04 17:00:20 +00001749 _GoInteractive = object()
1750 def __call__(self, request=_GoInteractive):
1751 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001752 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001753 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001754 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001755 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001756 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001757You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001758If you want to ask for help on a particular object directly from the
1759interpreter, you can type "help(object)". Executing "help('string')"
1760has the same effect as typing a particular string at the help> prompt.
1761''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001762
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001763 def interact(self):
1764 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001765 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001766 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001767 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001768 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001769 except (KeyboardInterrupt, EOFError):
1770 break
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001771 request = replace(request, '"', '', "'", '').strip()
1772 if request.lower() in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001773 self.help(request)
1774
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001775 def getline(self, prompt):
Guido van Rossum7c086c02008-01-02 03:52:38 +00001776 """Read one line, using input() when appropriate."""
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001777 if self.input is sys.stdin:
Guido van Rossum7c086c02008-01-02 03:52:38 +00001778 return input(prompt)
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001779 else:
1780 self.output.write(prompt)
1781 self.output.flush()
1782 return self.input.readline()
1783
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001784 def help(self, request):
1785 if type(request) is type(''):
R. David Murray1f1b9d32009-05-27 20:56:59 +00001786 request = request.strip()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001787 if request == 'help': self.intro()
1788 elif request == 'keywords': self.listkeywords()
Georg Brandldb7b6b92009-01-01 15:53:14 +00001789 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001790 elif request == 'topics': self.listtopics()
1791 elif request == 'modules': self.listmodules()
1792 elif request[:8] == 'modules ':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001793 self.listmodules(request.split()[1])
Georg Brandldb7b6b92009-01-01 15:53:14 +00001794 elif request in self.symbols: self.showsymbol(request)
Ezio Melottib185a042011-04-28 07:42:55 +03001795 elif request in ['True', 'False', 'None']:
1796 # special case these keywords since they are objects too
1797 doc(eval(request), 'Help on %s:')
Raymond Hettinger54f02222002-06-01 14:18:47 +00001798 elif request in self.keywords: self.showtopic(request)
1799 elif request in self.topics: self.showtopic(request)
Georg Brandld80d5f42010-12-03 07:47:22 +00001800 elif request: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001801 elif isinstance(request, Helper): self()
Georg Brandld80d5f42010-12-03 07:47:22 +00001802 else: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001803 self.output.write('\n')
1804
1805 def intro(self):
1806 self.output.write('''
1807Welcome to Python %s! This is the online help utility.
1808
1809If this is your first time using Python, you should definitely check out
Georg Brandl86def6c2008-01-21 20:36:10 +00001810the tutorial on the Internet at http://docs.python.org/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001811
1812Enter the name of any module, keyword, or topic to get help on writing
1813Python programs and using Python modules. To quit this help utility and
1814return to the interpreter, just type "quit".
1815
1816To get a list of available modules, keywords, or topics, type "modules",
1817"keywords", or "topics". Each module also comes with a one-line summary
1818of what it does; to list the modules whose summaries contain a given word
1819such as "spam", type "modules spam".
1820''' % sys.version[:3])
1821
1822 def list(self, items, columns=4, width=80):
Guido van Rossum486364b2007-06-30 05:01:58 +00001823 items = list(sorted(items))
1824 colw = width // columns
1825 rows = (len(items) + columns - 1) // columns
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001826 for row in range(rows):
1827 for col in range(columns):
1828 i = col * rows + row
1829 if i < len(items):
1830 self.output.write(items[i])
1831 if col < columns - 1:
Guido van Rossum486364b2007-06-30 05:01:58 +00001832 self.output.write(' ' + ' ' * (colw - 1 - len(items[i])))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001833 self.output.write('\n')
1834
1835 def listkeywords(self):
1836 self.output.write('''
1837Here is a list of the Python keywords. Enter any keyword to get more help.
1838
1839''')
1840 self.list(self.keywords.keys())
1841
Georg Brandldb7b6b92009-01-01 15:53:14 +00001842 def listsymbols(self):
1843 self.output.write('''
1844Here is a list of the punctuation symbols which Python assigns special meaning
1845to. Enter any symbol to get more help.
1846
1847''')
1848 self.list(self.symbols.keys())
1849
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001850 def listtopics(self):
1851 self.output.write('''
1852Here is a list of available topics. Enter any topic name to get more help.
1853
1854''')
1855 self.list(self.topics.keys())
1856
Georg Brandldb7b6b92009-01-01 15:53:14 +00001857 def showtopic(self, topic, more_xrefs=''):
Georg Brandl6b38daa2008-06-01 21:05:17 +00001858 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001859 import pydoc_data.topics
Georg Brandl6b38daa2008-06-01 21:05:17 +00001860 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001861 self.output.write('''
Georg Brandl6b38daa2008-06-01 21:05:17 +00001862Sorry, topic and keyword documentation is not available because the
Georg Brandl5617db82009-04-27 16:28:57 +00001863module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001864''')
1865 return
1866 target = self.topics.get(topic, self.keywords.get(topic))
1867 if not target:
1868 self.output.write('no documentation found for %s\n' % repr(topic))
1869 return
1870 if type(target) is type(''):
Georg Brandldb7b6b92009-01-01 15:53:14 +00001871 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001872
Georg Brandl6b38daa2008-06-01 21:05:17 +00001873 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001874 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001875 doc = pydoc_data.topics.topics[label]
Georg Brandl6b38daa2008-06-01 21:05:17 +00001876 except KeyError:
1877 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001878 return
Georg Brandl6b38daa2008-06-01 21:05:17 +00001879 pager(doc.strip() + '\n')
Georg Brandldb7b6b92009-01-01 15:53:14 +00001880 if more_xrefs:
1881 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001882 if xrefs:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001883 import formatter
Guido van Rossum34d19282007-08-09 01:03:29 +00001884 buffer = io.StringIO()
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001885 formatter.DumbWriter(buffer).send_flowing_data(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001886 'Related help topics: ' + ', '.join(xrefs.split()) + '\n')
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001887 self.output.write('\n%s\n' % buffer.getvalue())
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001888
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001889 def _gettopic(self, topic, more_xrefs=''):
1890 """Return unbuffered tuple of (topic, xrefs).
1891
Georg Brandld2f38572011-01-30 08:37:19 +00001892 If an error occurs here, the exception is caught and displayed by
1893 the url handler.
1894
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001895 This function duplicates the showtopic method but returns its
1896 result directly so it can be formatted for display in an html page.
1897 """
1898 try:
1899 import pydoc_data.topics
1900 except ImportError:
1901 return('''
1902Sorry, topic and keyword documentation is not available because the
1903module "pydoc_data.topics" could not be found.
1904''' , '')
1905 target = self.topics.get(topic, self.keywords.get(topic))
1906 if not target:
Georg Brandld2f38572011-01-30 08:37:19 +00001907 raise ValueError('could not find topic')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001908 if isinstance(target, str):
1909 return self._gettopic(target, more_xrefs)
1910 label, xrefs = target
Georg Brandld2f38572011-01-30 08:37:19 +00001911 doc = pydoc_data.topics.topics[label]
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001912 if more_xrefs:
1913 xrefs = (xrefs or '') + ' ' + more_xrefs
1914 return doc, xrefs
1915
Georg Brandldb7b6b92009-01-01 15:53:14 +00001916 def showsymbol(self, symbol):
1917 target = self.symbols[symbol]
1918 topic, _, xrefs = target.partition(' ')
1919 self.showtopic(topic, xrefs)
1920
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001921 def listmodules(self, key=''):
1922 if key:
1923 self.output.write('''
1924Here is a list of matching modules. Enter any module name to get more help.
1925
1926''')
1927 apropos(key)
1928 else:
1929 self.output.write('''
1930Please wait a moment while I gather a list of all available modules...
1931
1932''')
1933 modules = {}
1934 def callback(path, modname, desc, modules=modules):
1935 if modname and modname[-9:] == '.__init__':
1936 modname = modname[:-9] + ' (package)'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001937 if modname.find('.') < 0:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001938 modules[modname] = 1
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001939 def onerror(modname):
1940 callback(None, modname, None)
1941 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001942 self.list(modules.keys())
1943 self.output.write('''
1944Enter any module name to get more help. Or, type "modules spam" to search
1945for modules whose descriptions contain the word "spam".
1946''')
1947
Georg Brandl78aa3962010-07-31 21:51:48 +00001948help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001949
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001950class Scanner:
1951 """A generic tree iterator."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001952 def __init__(self, roots, children, descendp):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001953 self.roots = roots[:]
1954 self.state = []
1955 self.children = children
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001956 self.descendp = descendp
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001957
1958 def next(self):
1959 if not self.state:
1960 if not self.roots:
1961 return None
1962 root = self.roots.pop(0)
1963 self.state = [(root, self.children(root))]
1964 node, children = self.state[-1]
1965 if not children:
1966 self.state.pop()
1967 return self.next()
1968 child = children.pop(0)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001969 if self.descendp(child):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001970 self.state.append((child, self.children(child)))
1971 return child
1972
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001973
1974class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001975 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001976
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001977 def run(self, callback, key=None, completer=None, onerror=None):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001978 if key: key = key.lower()
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001979 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001980 seen = {}
1981
1982 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001983 if modname != '__main__':
1984 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00001985 if key is None:
1986 callback(None, modname, '')
1987 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001988 name = __import__(modname).__doc__ or ''
1989 desc = name.split('\n')[0]
1990 name = modname + ' - ' + desc
1991 if name.lower().find(key) >= 0:
Ka-Ping Yee66246962001-04-12 11:59:50 +00001992 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001993
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001994 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001995 if self.quit:
1996 break
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001997
1998 # XXX Skipping this file is a workaround for a bug
1999 # that causes python to crash with a segfault.
2000 # http://bugs.python.org/issue9319
2001 #
2002 # TODO Remove this once the bug is fixed.
2003 if modname in {'test.badsyntax_pep3120', 'badsyntax_pep3120'}:
2004 continue
2005
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002006 if key is None:
2007 callback(None, modname, '')
2008 else:
Georg Brandl126c8792009-04-05 15:05:48 +00002009 try:
2010 loader = importer.find_module(modname)
2011 except SyntaxError:
2012 # raised by tests for bad coding cookies or BOM
2013 continue
2014 if hasattr(loader, 'get_source'):
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002015 try:
2016 source = loader.get_source(modname)
2017 except UnicodeDecodeError:
2018 if onerror:
2019 onerror(modname)
2020 continue
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002021 desc = source_synopsis(io.StringIO(source)) or ''
Georg Brandl126c8792009-04-05 15:05:48 +00002022 if hasattr(loader, 'get_filename'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002023 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002024 else:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002025 path = None
2026 else:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002027 try:
2028 module = loader.load_module(modname)
2029 except ImportError:
2030 if onerror:
2031 onerror(modname)
2032 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002033 desc = (module.__doc__ or '').splitlines()[0]
2034 path = getattr(module,'__file__',None)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002035 name = modname + ' - ' + desc
2036 if name.lower().find(key) >= 0:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002037 callback(path, modname, desc)
2038
2039 if completer:
2040 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002041
2042def apropos(key):
2043 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002044 def callback(path, modname, desc):
2045 if modname[-9:] == '.__init__':
2046 modname = modname[:-9] + ' (package)'
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002047 print(modname, desc and '- ' + desc)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002048 def onerror(modname):
2049 pass
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002050 with warnings.catch_warnings():
2051 warnings.filterwarnings('ignore') # ignore problems during import
2052 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002053
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002054# --------------------------------------------------- Web browser interface
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002055
Ka-Ping Yee66246962001-04-12 11:59:50 +00002056def serve(port, callback=None, completer=None):
Georg Brandl83e9f4c2008-06-12 18:52:31 +00002057 import http.server, email.message, select
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002058
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002059 msg = 'the pydoc.serve() function is deprecated'
2060 warnings.warn(msg, DeprecationWarning, stacklevel=2)
2061
Georg Brandl24420152008-05-26 16:32:26 +00002062 class DocHandler(http.server.BaseHTTPRequestHandler):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002063 def send_document(self, title, contents):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002064 try:
2065 self.send_response(200)
Georg Brandl825fc8b2008-01-19 20:44:32 +00002066 self.send_header('Content-Type', 'text/html; charset=UTF-8')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002067 self.end_headers()
Georg Brandl825fc8b2008-01-19 20:44:32 +00002068 self.wfile.write(html.page(title, contents).encode('utf-8'))
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002069 except IOError: pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002070
2071 def do_GET(self):
2072 path = self.path
2073 if path[-5:] == '.html': path = path[:-5]
2074 if path[:1] == '/': path = path[1:]
2075 if path and path != '.':
2076 try:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00002077 obj = locate(path, forceload=1)
Guido van Rossumb940e112007-01-10 16:19:56 +00002078 except ErrorDuringImport as value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002079 self.send_document(path, html.escape(str(value)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002080 return
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002081 if obj:
2082 self.send_document(describe(obj), html.document(obj, path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002083 else:
2084 self.send_document(path,
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002085'no Python documentation found for %s' % repr(path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002086 else:
2087 heading = html.heading(
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002088'<big><big><strong>Python: Index of Modules</strong></big></big>',
2089'#ffffff', '#7799ee')
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002090 def bltinlink(name):
2091 return '<a href="%s.html">%s</a>' % (name, name)
Georg Brandl661b0a12008-01-27 18:16:00 +00002092 names = [x for x in sys.builtin_module_names if x != '__main__']
2093 contents = html.multicolumn(names, bltinlink)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002094 indices = ['<p>' + html.bigsection(
2095 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2096
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002097 seen = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002098 for dir in sys.path:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002099 indices.append(html.index(dir, seen))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002100 contents = heading + ' '.join(indices) + '''<p align=right>
Tim Peters2306d242001-09-25 03:18:32 +00002101<font color="#909090" face="helvetica, arial"><strong>
2102pydoc</strong> by Ka-Ping Yee &lt;ping@lfw.org&gt;</font>'''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002103 self.send_document('Index of Modules', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002104
2105 def log_message(self, *args): pass
2106
Georg Brandl24420152008-05-26 16:32:26 +00002107 class DocServer(http.server.HTTPServer):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002108 def __init__(self, port, callback):
Ronald Oussoren94f25282010-05-05 19:11:21 +00002109 host = 'localhost'
Senthil Kumaran7ff59132010-08-18 19:32:21 +00002110 self.address = (host, port)
Ka-Ping Yeedb8ed152001-03-02 05:58:17 +00002111 self.url = 'http://%s:%d/' % (host, port)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002112 self.callback = callback
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002113 self.base.__init__(self, self.address, self.handler)
2114
2115 def serve_until_quit(self):
2116 import select
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002117 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002118 while not self.quit:
2119 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2120 if rd: self.handle_request()
Victor Stinnera3abd1d2011-01-03 16:12:39 +00002121 self.server_close()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002122
2123 def server_activate(self):
2124 self.base.server_activate(self)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002125 if self.callback: self.callback(self)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002126
Georg Brandl24420152008-05-26 16:32:26 +00002127 DocServer.base = http.server.HTTPServer
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002128 DocServer.handler = DocHandler
Georg Brandl83e9f4c2008-06-12 18:52:31 +00002129 DocHandler.MessageClass = email.message.Message
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002130 try:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002131 try:
2132 DocServer(port, callback).serve_until_quit()
2133 except (KeyboardInterrupt, select.error):
2134 pass
2135 finally:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002136 if completer: completer()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002137
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002138
2139# --------------------------------------- enhanced Web browser interface
2140
2141def _start_server(urlhandler, port):
2142 """Start an HTTP server thread on a specific port.
2143
2144 Start an HTML/text server thread, so HTML or text documents can be
2145 browsed dynamically and interactively with a Web browser. Example use:
2146
2147 >>> import time
2148 >>> import pydoc
2149
2150 Define a URL handler. To determine what the client is asking
2151 for, check the URL and content_type.
2152
2153 Then get or generate some text or HTML code and return it.
2154
2155 >>> def my_url_handler(url, content_type):
2156 ... text = 'the URL sent was: (%s, %s)' % (url, content_type)
2157 ... return text
2158
2159 Start server thread on port 0.
2160 If you use port 0, the server will pick a random port number.
2161 You can then use serverthread.port to get the port number.
2162
2163 >>> port = 0
2164 >>> serverthread = pydoc._start_server(my_url_handler, port)
2165
2166 Check that the server is really started. If it is, open browser
2167 and get first page. Use serverthread.url as the starting page.
2168
2169 >>> if serverthread.serving:
2170 ... import webbrowser
2171
2172 The next two lines are commented out so a browser doesn't open if
2173 doctest is run on this module.
2174
2175 #... webbrowser.open(serverthread.url)
2176 #True
2177
2178 Let the server do its thing. We just need to monitor its status.
2179 Use time.sleep so the loop doesn't hog the CPU.
2180
2181 >>> starttime = time.time()
2182 >>> timeout = 1 #seconds
2183
2184 This is a short timeout for testing purposes.
2185
2186 >>> while serverthread.serving:
2187 ... time.sleep(.01)
2188 ... if serverthread.serving and time.time() - starttime > timeout:
2189 ... serverthread.stop()
2190 ... break
2191
2192 Print any errors that may have occurred.
2193
2194 >>> print(serverthread.error)
2195 None
2196 """
2197 import http.server
2198 import email.message
2199 import select
2200 import threading
2201
2202 class DocHandler(http.server.BaseHTTPRequestHandler):
2203
2204 def do_GET(self):
2205 """Process a request from an HTML browser.
2206
2207 The URL received is in self.path.
2208 Get an HTML page from self.urlhandler and send it.
2209 """
2210 if self.path.endswith('.css'):
2211 content_type = 'text/css'
2212 else:
2213 content_type = 'text/html'
2214 self.send_response(200)
Georg Brandld2f38572011-01-30 08:37:19 +00002215 self.send_header('Content-Type', '%s; charset=UTF-8' % content_type)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002216 self.end_headers()
2217 self.wfile.write(self.urlhandler(
2218 self.path, content_type).encode('utf-8'))
2219
2220 def log_message(self, *args):
2221 # Don't log messages.
2222 pass
2223
2224 class DocServer(http.server.HTTPServer):
2225
2226 def __init__(self, port, callback):
2227 self.host = (sys.platform == 'mac') and '127.0.0.1' or 'localhost'
2228 self.address = ('', port)
2229 self.callback = callback
2230 self.base.__init__(self, self.address, self.handler)
2231 self.quit = False
2232
2233 def serve_until_quit(self):
2234 while not self.quit:
2235 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2236 if rd:
2237 self.handle_request()
Victor Stinnera3abd1d2011-01-03 16:12:39 +00002238 self.server_close()
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002239
2240 def server_activate(self):
2241 self.base.server_activate(self)
2242 if self.callback:
2243 self.callback(self)
2244
2245 class ServerThread(threading.Thread):
2246
2247 def __init__(self, urlhandler, port):
2248 self.urlhandler = urlhandler
2249 self.port = int(port)
2250 threading.Thread.__init__(self)
2251 self.serving = False
2252 self.error = None
2253
2254 def run(self):
2255 """Start the server."""
2256 try:
2257 DocServer.base = http.server.HTTPServer
2258 DocServer.handler = DocHandler
2259 DocHandler.MessageClass = email.message.Message
2260 DocHandler.urlhandler = staticmethod(self.urlhandler)
2261 docsvr = DocServer(self.port, self.ready)
2262 self.docserver = docsvr
2263 docsvr.serve_until_quit()
2264 except Exception as e:
2265 self.error = e
2266
2267 def ready(self, server):
2268 self.serving = True
2269 self.host = server.host
2270 self.port = server.server_port
2271 self.url = 'http://%s:%d/' % (self.host, self.port)
2272
2273 def stop(self):
2274 """Stop the server and this thread nicely"""
2275 self.docserver.quit = True
2276 self.serving = False
2277 self.url = None
2278
2279 thread = ServerThread(urlhandler, port)
2280 thread.start()
2281 # Wait until thread.serving is True to make sure we are
2282 # really up before returning.
2283 while not thread.error and not thread.serving:
2284 time.sleep(.01)
2285 return thread
2286
2287
2288def _url_handler(url, content_type="text/html"):
2289 """The pydoc url handler for use with the pydoc server.
2290
2291 If the content_type is 'text/css', the _pydoc.css style
2292 sheet is read and returned if it exits.
2293
2294 If the content_type is 'text/html', then the result of
2295 get_html_page(url) is returned.
2296 """
2297 class _HTMLDoc(HTMLDoc):
2298
2299 def page(self, title, contents):
2300 """Format an HTML page."""
2301 css_path = "pydoc_data/_pydoc.css"
2302 css_link = (
2303 '<link rel="stylesheet" type="text/css" href="%s">' %
2304 css_path)
2305 return '''\
2306<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Georg Brandld2f38572011-01-30 08:37:19 +00002307<html><head><title>Pydoc: %s</title>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002308<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Georg Brandld2f38572011-01-30 08:37:19 +00002309%s</head><body bgcolor="#f0f0f8">%s<div style="clear:both;padding-top:.5em;">%s</div>
2310</body></html>''' % (title, css_link, html_navbar(), contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002311
2312 def filelink(self, url, path):
2313 return '<a href="getfile?key=%s">%s</a>' % (url, path)
2314
2315
2316 html = _HTMLDoc()
2317
2318 def html_navbar():
Georg Brandld2f38572011-01-30 08:37:19 +00002319 version = html.escape("%s [%s, %s]" % (platform.python_version(),
2320 platform.python_build()[0],
2321 platform.python_compiler()))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002322 return """
2323 <div style='float:left'>
Georg Brandld2f38572011-01-30 08:37:19 +00002324 Python %s<br>%s
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002325 </div>
2326 <div style='float:right'>
2327 <div style='text-align:center'>
2328 <a href="index.html">Module Index</a>
2329 : <a href="topics.html">Topics</a>
2330 : <a href="keywords.html">Keywords</a>
2331 </div>
2332 <div>
Georg Brandld2f38572011-01-30 08:37:19 +00002333 <form action="get" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002334 <input type=text name=key size=15>
2335 <input type=submit value="Get">
Georg Brandld2f38572011-01-30 08:37:19 +00002336 </form>&nbsp;
2337 <form action="search" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002338 <input type=text name=key size=15>
2339 <input type=submit value="Search">
2340 </form>
2341 </div>
2342 </div>
Georg Brandld2f38572011-01-30 08:37:19 +00002343 """ % (version, html.escape(platform.platform(terse=True)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002344
2345 def html_index():
2346 """Module Index page."""
2347
2348 def bltinlink(name):
2349 return '<a href="%s.html">%s</a>' % (name, name)
2350
2351 heading = html.heading(
2352 '<big><big><strong>Index of Modules</strong></big></big>',
2353 '#ffffff', '#7799ee')
2354 names = [name for name in sys.builtin_module_names
2355 if name != '__main__']
2356 contents = html.multicolumn(names, bltinlink)
2357 contents = [heading, '<p>' + html.bigsection(
2358 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2359
2360 seen = {}
2361 for dir in sys.path:
2362 contents.append(html.index(dir, seen))
2363
2364 contents.append(
2365 '<p align=right><font color="#909090" face="helvetica,'
2366 'arial"><strong>pydoc</strong> by Ka-Ping Yee'
2367 '&lt;ping@lfw.org&gt;</font>')
Nick Coghlanecace282010-12-03 16:08:46 +00002368 return 'Index of Modules', ''.join(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002369
2370 def html_search(key):
2371 """Search results page."""
2372 # scan for modules
2373 search_result = []
2374
2375 def callback(path, modname, desc):
2376 if modname[-9:] == '.__init__':
2377 modname = modname[:-9] + ' (package)'
2378 search_result.append((modname, desc and '- ' + desc))
2379
2380 with warnings.catch_warnings():
2381 warnings.filterwarnings('ignore') # ignore problems during import
2382 ModuleScanner().run(callback, key)
2383
2384 # format page
2385 def bltinlink(name):
2386 return '<a href="%s.html">%s</a>' % (name, name)
2387
2388 results = []
2389 heading = html.heading(
2390 '<big><big><strong>Search Results</strong></big></big>',
2391 '#ffffff', '#7799ee')
2392 for name, desc in search_result:
2393 results.append(bltinlink(name) + desc)
2394 contents = heading + html.bigsection(
2395 'key = %s' % key, '#ffffff', '#ee77aa', '<br>'.join(results))
Nick Coghlanecace282010-12-03 16:08:46 +00002396 return 'Search Results', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002397
2398 def html_getfile(path):
2399 """Get and display a source file listing safely."""
Nick Coghlanecace282010-12-03 16:08:46 +00002400 path = path.replace('%20', ' ')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002401 with open(path, 'r') as fp:
2402 lines = html.escape(fp.read())
2403 body = '<pre>%s</pre>' % lines
2404 heading = html.heading(
2405 '<big><big><strong>File Listing</strong></big></big>',
2406 '#ffffff', '#7799ee')
2407 contents = heading + html.bigsection(
2408 'File: %s' % path, '#ffffff', '#ee77aa', body)
Nick Coghlanecace282010-12-03 16:08:46 +00002409 return 'getfile %s' % path, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002410
2411 def html_topics():
2412 """Index of topic texts available."""
2413
2414 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002415 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002416
2417 heading = html.heading(
2418 '<big><big><strong>INDEX</strong></big></big>',
2419 '#ffffff', '#7799ee')
2420 names = sorted(Helper.topics.keys())
2421
2422 contents = html.multicolumn(names, bltinlink)
2423 contents = heading + html.bigsection(
2424 'Topics', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002425 return 'Topics', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002426
2427 def html_keywords():
2428 """Index of keywords."""
2429 heading = html.heading(
2430 '<big><big><strong>INDEX</strong></big></big>',
2431 '#ffffff', '#7799ee')
2432 names = sorted(Helper.keywords.keys())
2433
2434 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002435 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002436
2437 contents = html.multicolumn(names, bltinlink)
2438 contents = heading + html.bigsection(
2439 'Keywords', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002440 return 'Keywords', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002441
2442 def html_topicpage(topic):
2443 """Topic or keyword help page."""
2444 buf = io.StringIO()
2445 htmlhelp = Helper(buf, buf)
2446 contents, xrefs = htmlhelp._gettopic(topic)
2447 if topic in htmlhelp.keywords:
2448 title = 'KEYWORD'
2449 else:
2450 title = 'TOPIC'
2451 heading = html.heading(
2452 '<big><big><strong>%s</strong></big></big>' % title,
2453 '#ffffff', '#7799ee')
Georg Brandld2f38572011-01-30 08:37:19 +00002454 contents = '<pre>%s</pre>' % html.markup(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002455 contents = html.bigsection(topic , '#ffffff','#ee77aa', contents)
Georg Brandld2f38572011-01-30 08:37:19 +00002456 if xrefs:
2457 xrefs = sorted(xrefs.split())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002458
Georg Brandld2f38572011-01-30 08:37:19 +00002459 def bltinlink(name):
2460 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002461
Georg Brandld2f38572011-01-30 08:37:19 +00002462 xrefs = html.multicolumn(xrefs, bltinlink)
2463 xrefs = html.section('Related help topics: ',
2464 '#ffffff', '#ee77aa', xrefs)
Nick Coghlanecace282010-12-03 16:08:46 +00002465 return ('%s %s' % (title, topic),
2466 ''.join((heading, contents, xrefs)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002467
Georg Brandld2f38572011-01-30 08:37:19 +00002468 def html_getobj(url):
2469 obj = locate(url, forceload=1)
2470 if obj is None and url != 'None':
2471 raise ValueError('could not find object')
2472 title = describe(obj)
2473 content = html.document(obj, url)
2474 return title, content
2475
2476 def html_error(url, exc):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002477 heading = html.heading(
2478 '<big><big><strong>Error</strong></big></big>',
Georg Brandld2f38572011-01-30 08:37:19 +00002479 '#ffffff', '#7799ee')
2480 contents = '<br>'.join(html.escape(line) for line in
2481 format_exception_only(type(exc), exc))
2482 contents = heading + html.bigsection(url, '#ffffff', '#bb0000',
2483 contents)
2484 return "Error - %s" % url, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002485
2486 def get_html_page(url):
2487 """Generate an HTML page for url."""
Georg Brandld2f38572011-01-30 08:37:19 +00002488 complete_url = url
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002489 if url.endswith('.html'):
2490 url = url[:-5]
Georg Brandld2f38572011-01-30 08:37:19 +00002491 try:
2492 if url in ("", "index"):
2493 title, content = html_index()
2494 elif url == "topics":
2495 title, content = html_topics()
2496 elif url == "keywords":
2497 title, content = html_keywords()
2498 elif '=' in url:
2499 op, _, url = url.partition('=')
2500 if op == "search?key":
2501 title, content = html_search(url)
2502 elif op == "getfile?key":
2503 title, content = html_getfile(url)
2504 elif op == "topic?key":
2505 # try topics first, then objects.
2506 try:
2507 title, content = html_topicpage(url)
2508 except ValueError:
2509 title, content = html_getobj(url)
2510 elif op == "get?key":
2511 # try objects first, then topics.
2512 if url in ("", "index"):
2513 title, content = html_index()
2514 else:
2515 try:
2516 title, content = html_getobj(url)
2517 except ValueError:
2518 title, content = html_topicpage(url)
2519 else:
2520 raise ValueError('bad pydoc url')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002521 else:
Georg Brandld2f38572011-01-30 08:37:19 +00002522 title, content = html_getobj(url)
2523 except Exception as exc:
2524 # Catch any errors and display them in an error page.
2525 title, content = html_error(complete_url, exc)
2526 return html.page(title, content)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002527
2528 if url.startswith('/'):
2529 url = url[1:]
2530 if content_type == 'text/css':
2531 path_here = os.path.dirname(os.path.realpath(__file__))
Georg Brandld2f38572011-01-30 08:37:19 +00002532 css_path = os.path.join(path_here, url)
2533 with open(css_path) as fp:
2534 return ''.join(fp.readlines())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002535 elif content_type == 'text/html':
2536 return get_html_page(url)
Georg Brandld2f38572011-01-30 08:37:19 +00002537 # Errors outside the url handler are caught by the server.
2538 raise TypeError('unknown content type %r for url %s' % (content_type, url))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002539
2540
2541def browse(port=0, *, open_browser=True):
2542 """Start the enhanced pydoc Web server and open a Web browser.
2543
2544 Use port '0' to start the server on an arbitrary port.
2545 Set open_browser to False to suppress opening a browser.
2546 """
2547 import webbrowser
2548 serverthread = _start_server(_url_handler, port)
2549 if serverthread.error:
2550 print(serverthread.error)
2551 return
2552 if serverthread.serving:
2553 server_help_msg = 'Server commands: [b]rowser, [q]uit'
2554 if open_browser:
2555 webbrowser.open(serverthread.url)
2556 try:
2557 print('Server ready at', serverthread.url)
2558 print(server_help_msg)
2559 while serverthread.serving:
2560 cmd = input('server> ')
2561 cmd = cmd.lower()
2562 if cmd == 'q':
2563 break
2564 elif cmd == 'b':
2565 webbrowser.open(serverthread.url)
2566 else:
2567 print(server_help_msg)
2568 except (KeyboardInterrupt, EOFError):
2569 print()
2570 finally:
2571 if serverthread.serving:
2572 serverthread.stop()
2573 print('Server stopped')
2574
2575
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002576# -------------------------------------------------- command-line interface
2577
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002578def ispath(x):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002579 return isinstance(x, str) and x.find(os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002580
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002581def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002582 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002583 import getopt
Guido van Rossum756aa932007-04-07 03:04:01 +00002584 class BadUsage(Exception): pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002585
Nick Coghlan106274b2009-11-15 23:04:33 +00002586 # Scripts don't get the current directory in their path by default
2587 # unless they are run with the '-m' switch
2588 if '' not in sys.path:
2589 scriptdir = os.path.dirname(sys.argv[0])
2590 if scriptdir in sys.path:
2591 sys.path.remove(scriptdir)
2592 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002593
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002594 try:
Victor Stinner383c3fc2011-05-25 01:35:05 +02002595 opts, args = getopt.getopt(sys.argv[1:], 'bk:p:w')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002596 writing = False
2597 start_server = False
2598 open_browser = False
2599 port = None
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002600 for opt, val in opts:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002601 if opt == '-b':
2602 start_server = True
2603 open_browser = True
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002604 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002605 apropos(val)
2606 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002607 if opt == '-p':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002608 start_server = True
2609 port = val
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002610 if opt == '-w':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002611 writing = True
2612
2613 if start_server == True:
2614 if port == None:
2615 port = 0
2616 browse(port, open_browser=open_browser)
2617 return
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002618
2619 if not args: raise BadUsage
2620 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002621 if ispath(arg) and not os.path.exists(arg):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002622 print('file %r does not exist' % arg)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002623 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002624 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002625 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002626 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002627 if writing:
2628 if ispath(arg) and os.path.isdir(arg):
2629 writedocs(arg)
2630 else:
2631 writedoc(arg)
2632 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002633 help.help(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +00002634 except ErrorDuringImport as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002635 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002636
2637 except (getopt.error, BadUsage):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002638 cmd = os.path.splitext(os.path.basename(sys.argv[0]))[0]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002639 print("""pydoc - the Python documentation tool
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002640
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002641{cmd} <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002642 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002643 Python keyword, topic, function, module, or package, or a dotted
2644 reference to a class or function within a module or module in a
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002645 package. If <name> contains a '{sep}', it is used as the path to a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002646 Python source file to document. If name is 'keywords', 'topics',
2647 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002648
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002649{cmd} -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002650 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002651
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002652{cmd} -p <port>
2653 Start an HTTP server on the given port on the local machine. Port
2654 number 0 can be used to get an arbitrary unused port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002655
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002656{cmd} -b
2657 Start an HTTP server on an arbitrary unused port and open a Web browser
2658 to interactively browse documentation. The -p option can be used with
2659 the -b option to explicitly specify the server port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002660
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002661{cmd} -w <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002662 Write out the HTML documentation for a module to a file in the current
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002663 directory. If <name> contains a '{sep}', it is treated as a filename; if
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002664 it names a directory, documentation is written for all the contents.
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002665""".format(cmd=cmd, sep=os.sep))
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002666
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002667if __name__ == '__main__':
2668 cli()