blob: 1619446c2d66be090987d80617d0ac8445cfd7b7 [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 +000025For platforms without a command line, "pydoc -g" starts the HTTP server
Nick Coghlan7bb30b72010-12-03 09:29:11 +000026and also pops up a little window for controlling it. This option is
27deprecated, since the server can now be controlled directly from HTTP
28clients.
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000029
30Run "pydoc -w <name>" to write out the HTML documentation for a module
31to a file named "<name>.html".
Skip Montanaro4997a692003-09-10 16:47:51 +000032
33Module docs for core modules are assumed to be in
34
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000035 http://docs.python.org/X.Y/library/
Skip Montanaro4997a692003-09-10 16:47:51 +000036
37This can be overridden by setting the PYTHONDOCS environment variable
38to a different URL or to a local directory containing the Library
39Reference Manual pages.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000040"""
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000041__all__ = ['help']
Ka-Ping Yeedd175342001-02-27 14:43:46 +000042__author__ = "Ka-Ping Yee <ping@lfw.org>"
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000043__date__ = "26 February 2001"
Jeremy Hylton3e0055f2005-10-20 19:59:25 +000044
Ka-Ping Yee09d7d9a2001-02-27 22:43:48 +000045__version__ = "$Revision$"
Martin v. Löwis6fe8f192004-11-14 10:21:04 +000046__credits__ = """Guido van Rossum, for an excellent programming language.
Ka-Ping Yee5e2b1732001-02-27 23:35:09 +000047Tommy Burnette, the original creator of manpy.
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000048Paul Prescod, for all his work on onlinehelp.
49Richard Chamberlain, for the first implementation of textdoc.
Raymond Hettingered2dbe32005-01-01 07:51:01 +000050"""
Ka-Ping Yeedd175342001-02-27 14:43:46 +000051
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000052# Known bugs that can't be fixed here:
53# - imp.load_module() cannot be prevented from clobbering existing
54# loaded modules, so calling synopsis() on a binary module file
55# changes the contents of any existing module with the same name.
56# - If the __file__ attribute on a module is a relative path and
57# the current directory is changed with os.chdir(), an incorrect
58# path will be displayed.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000059
Nick Coghlan7bb30b72010-12-03 09:29:11 +000060import builtins
61import imp
Nick Coghlan7bb30b72010-12-03 09:29:11 +000062import inspect
Victor Stinnere6c910e2011-06-30 15:55:43 +020063import io
64import os
Nick Coghlan7bb30b72010-12-03 09:29:11 +000065import pkgutil
66import platform
67import re
Victor Stinnere6c910e2011-06-30 15:55:43 +020068import sys
Nick Coghlan7bb30b72010-12-03 09:29:11 +000069import time
Victor Stinnere6c910e2011-06-30 15:55:43 +020070import tokenize
Nick Coghlan7bb30b72010-12-03 09:29:11 +000071import warnings
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000072from collections import deque
Nick Coghlan7bb30b72010-12-03 09:29:11 +000073from reprlib import Repr
Georg Brandld2f38572011-01-30 08:37:19 +000074from traceback import extract_tb, format_exception_only
Nick Coghlan7bb30b72010-12-03 09:29:11 +000075
76
Ka-Ping Yeedd175342001-02-27 14:43:46 +000077# --------------------------------------------------------- common routines
78
Ka-Ping Yeedd175342001-02-27 14:43:46 +000079def pathdirs():
80 """Convert sys.path into a list of absolute, existing, unique paths."""
81 dirs = []
Ka-Ping Yee1d384632001-03-01 00:24:32 +000082 normdirs = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +000083 for dir in sys.path:
84 dir = os.path.abspath(dir or '.')
Ka-Ping Yee1d384632001-03-01 00:24:32 +000085 normdir = os.path.normcase(dir)
86 if normdir not in normdirs and os.path.isdir(dir):
Ka-Ping Yeedd175342001-02-27 14:43:46 +000087 dirs.append(dir)
Ka-Ping Yee1d384632001-03-01 00:24:32 +000088 normdirs.append(normdir)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000089 return dirs
90
91def getdoc(object):
92 """Get the doc string or comments for an object."""
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000093 result = inspect.getdoc(object) or inspect.getcomments(object)
Neal Norwitz9d72bb42007-04-17 08:48:32 +000094 return result and re.sub('^ *\n', '', result.rstrip()) or ''
Ka-Ping Yeedd175342001-02-27 14:43:46 +000095
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000096def splitdoc(doc):
97 """Split a doc string into a synopsis line (if any) and the rest."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +000098 lines = doc.strip().split('\n')
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000099 if len(lines) == 1:
100 return lines[0], ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000101 elif len(lines) >= 2 and not lines[1].rstrip():
102 return lines[0], '\n'.join(lines[2:])
103 return '', '\n'.join(lines)
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000104
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000105def classname(object, modname):
106 """Get a class name and qualify it with a module name if necessary."""
107 name = object.__name__
108 if object.__module__ != modname:
109 name = object.__module__ + '.' + name
110 return name
111
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000112def isdata(object):
Georg Brandl94432422005-07-22 21:52:25 +0000113 """Check if an object is of a type that probably means it's data."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000114 return not (inspect.ismodule(object) or inspect.isclass(object) or
115 inspect.isroutine(object) or inspect.isframe(object) or
116 inspect.istraceback(object) or inspect.iscode(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000117
118def replace(text, *pairs):
119 """Do a series of global replacements on a string."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000120 while pairs:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000121 text = pairs[1].join(text.split(pairs[0]))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000122 pairs = pairs[2:]
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000123 return text
124
125def cram(text, maxlen):
126 """Omit part of a string if needed to make it fit in a maximum length."""
127 if len(text) > maxlen:
Raymond Hettingerfca3bb62002-10-21 04:44:11 +0000128 pre = max(0, (maxlen-3)//2)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000129 post = max(0, maxlen-3-pre)
130 return text[:pre] + '...' + text[len(text)-post:]
131 return text
132
Brett Cannon84601f12004-06-19 01:22:48 +0000133_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000134def stripid(text):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000135 """Remove the hexadecimal id from a Python object representation."""
Brett Cannonc6c1f472004-06-19 01:02:51 +0000136 # The behaviour of %p is implementation-dependent in terms of case.
Ezio Melotti412c95a2010-02-16 23:31:04 +0000137 return _re_stripid.sub(r'\1', text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000138
Brett Cannonc6c1f472004-06-19 01:02:51 +0000139def _is_some_method(obj):
140 return inspect.ismethod(obj) or inspect.ismethoddescriptor(obj)
Tim Peters536d2262001-09-20 05:13:38 +0000141
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000142def allmethods(cl):
143 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000144 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000145 methods[key] = 1
146 for base in cl.__bases__:
147 methods.update(allmethods(base)) # all your base are belong to us
148 for key in methods.keys():
149 methods[key] = getattr(cl, key)
150 return methods
151
Tim Petersfa26f7c2001-09-24 08:05:11 +0000152def _split_list(s, predicate):
153 """Split sequence s via predicate, and return pair ([true], [false]).
154
155 The return value is a 2-tuple of lists,
156 ([x for x in s if predicate(x)],
157 [x for x in s if not predicate(x)])
158 """
159
Tim Peters28355492001-09-23 21:29:55 +0000160 yes = []
161 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000162 for x in s:
163 if predicate(x):
164 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000165 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000166 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000167 return yes, no
168
Raymond Hettinger1103d052011-03-25 14:15:24 -0700169def visiblename(name, all=None, obj=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000170 """Decide whether to show documentation on a variable."""
171 # Certain special names are redundant.
Benjamin Peterson41181742008-07-02 20:22:54 +0000172 _hidden_names = ('__builtins__', '__doc__', '__file__', '__path__',
Barry Warsaw28a691b2010-04-17 00:19:56 +0000173 '__module__', '__name__', '__slots__', '__package__',
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000174 '__cached__', '__author__', '__credits__', '__date__',
175 '__version__')
Benjamin Peterson41181742008-07-02 20:22:54 +0000176 if name in _hidden_names: return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000177 # Private names are hidden, but special names are displayed.
178 if name.startswith('__') and name.endswith('__'): return 1
Raymond Hettinger1103d052011-03-25 14:15:24 -0700179 # Namedtuples have public fields and methods with a single leading underscore
180 if name.startswith('_') and hasattr(obj, '_fields'):
181 return True
Skip Montanaroa5616d22004-06-11 04:46:12 +0000182 if all is not None:
183 # only document that which the programmer exported in __all__
184 return name in all
185 else:
186 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000187
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000188def classify_class_attrs(object):
189 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000190 results = []
191 for (name, kind, cls, value) in inspect.classify_class_attrs(object):
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000192 if inspect.isdatadescriptor(value):
193 kind = 'data descriptor'
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000194 results.append((name, kind, cls, value))
195 return results
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000196
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000197# ----------------------------------------------------- module manipulation
198
199def ispackage(path):
200 """Guess whether a path refers to a package directory."""
201 if os.path.isdir(path):
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000202 for ext in ('.py', '.pyc', '.pyo'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000203 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000204 return True
205 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000206
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000207def source_synopsis(file):
208 line = file.readline()
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000209 while line[:1] == '#' or not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000210 line = file.readline()
211 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000212 line = line.strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000213 if line[:4] == 'r"""': line = line[1:]
214 if line[:3] == '"""':
215 line = line[3:]
216 if line[-1:] == '\\': line = line[:-1]
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000217 while not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000218 line = file.readline()
219 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000220 result = line.split('"""')[0].strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000221 else: result = None
222 return result
223
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000224def synopsis(filename, cache={}):
225 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000226 mtime = os.stat(filename).st_mtime
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000227 lastupdate, result = cache.get(filename, (0, None))
228 if lastupdate < mtime:
229 info = inspect.getmoduleinfo(filename)
Georg Brandl26fd2e12006-03-08 09:34:53 +0000230 try:
Victor Stinnere6c910e2011-06-30 15:55:43 +0200231 file = tokenize.open(filename)
Georg Brandl26fd2e12006-03-08 09:34:53 +0000232 except IOError:
233 # module can't be opened, so skip it
234 return None
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000235 if info and 'b' in info[2]: # binary modules have to be imported
236 try: module = imp.load_module('__temp__', file, filename, info[1:])
237 except: return None
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000238 result = (module.__doc__ or '').splitlines()[0]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000239 del sys.modules['__temp__']
240 else: # text modules can be directly examined
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000241 result = source_synopsis(file)
242 file.close()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000243 cache[filename] = (mtime, result)
244 return result
245
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000246class ErrorDuringImport(Exception):
247 """Errors that occurred while trying to import something to document it."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000248 def __init__(self, filename, exc_info):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000249 self.filename = filename
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000250 self.exc, self.value, self.tb = exc_info
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000251
252 def __str__(self):
Guido van Rossuma01a8b62007-05-27 09:20:14 +0000253 exc = self.exc.__name__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000254 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000255
256def importfile(path):
257 """Import a Python source file or compiled file given its path."""
258 magic = imp.get_magic()
259 file = open(path, 'r')
260 if file.read(len(magic)) == magic:
261 kind = imp.PY_COMPILED
262 else:
263 kind = imp.PY_SOURCE
264 file.close()
265 filename = os.path.basename(path)
266 name, ext = os.path.splitext(filename)
267 file = open(path, 'r')
268 try:
269 module = imp.load_module(name, file, path, (ext, 'r', kind))
270 except:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000271 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000272 file.close()
273 return module
274
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000275def safeimport(path, forceload=0, cache={}):
276 """Import a module; handle errors; return None if the module isn't found.
277
278 If the module *is* found but an exception occurs, it's wrapped in an
279 ErrorDuringImport exception and reraised. Unlike __import__, if a
280 package path is specified, the module at the end of the path is returned,
281 not the package at the beginning. If the optional 'forceload' argument
282 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000283 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000284 # If forceload is 1 and the module has been previously loaded from
285 # disk, we always have to reload the module. Checking the file's
286 # mtime isn't good enough (e.g. the module could contain a class
287 # that inherits from another module that has changed).
288 if forceload and path in sys.modules:
289 if path not in sys.builtin_module_names:
Guido van Rossume7ba4952007-06-06 23:52:48 +0000290 # Remove the module from sys.modules and re-import to try
291 # and avoid problems with partially loaded modules.
292 # Also remove any submodules because they won't appear
293 # in the newly loaded module's namespace if they're already
294 # in sys.modules.
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000295 subs = [m for m in sys.modules if m.startswith(path + '.')]
296 for key in [path] + subs:
297 # Prevent garbage collection.
298 cache[key] = sys.modules[key]
299 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000300 module = __import__(path)
301 except:
302 # Did the error occur before or after the module was found?
303 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000304 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000305 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000306 raise ErrorDuringImport(sys.modules[path].__file__, info)
307 elif exc is SyntaxError:
308 # A SyntaxError occurred before we could execute the module.
309 raise ErrorDuringImport(value.filename, info)
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000310 elif exc is ImportError and extract_tb(tb)[-1][2]=='safeimport':
Benjamin Peterson0289b152009-06-28 17:22:03 +0000311 # The import error occurred directly in this function,
312 # which means there is no such module in the path.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000313 return None
314 else:
315 # Some other error occurred during the importing process.
316 raise ErrorDuringImport(path, sys.exc_info())
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000317 for part in path.split('.')[1:]:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000318 try: module = getattr(module, part)
319 except AttributeError: return None
320 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000321
322# ---------------------------------------------------- formatter base class
323
324class Doc:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000325
326 PYTHONDOCS = os.environ.get("PYTHONDOCS",
327 "http://docs.python.org/%d.%d/library"
328 % sys.version_info[:2])
329
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000330 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000331 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000332 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000333 # 'try' clause is to attempt to handle the possibility that inspect
334 # identifies something in a way that pydoc itself has issues handling;
335 # think 'super' and how it is a descriptor (which raises the exception
336 # by lacking a __name__ attribute) and an instance.
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000337 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
338 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000339 try:
340 if inspect.ismodule(object): return self.docmodule(*args)
341 if inspect.isclass(object): return self.docclass(*args)
342 if inspect.isroutine(object): return self.docroutine(*args)
343 except AttributeError:
344 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000345 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000346 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000347
348 def fail(self, object, name=None, *args):
349 """Raise an exception for unimplemented types."""
350 message = "don't know how to document object%s of type %s" % (
351 name and ' ' + repr(name), type(object).__name__)
Collin Winterce36ad82007-08-30 01:19:48 +0000352 raise TypeError(message)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000353
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000354 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000355
Skip Montanaro4997a692003-09-10 16:47:51 +0000356 def getdocloc(self, object):
357 """Return the location of module docs or None"""
358
359 try:
360 file = inspect.getabsfile(object)
361 except TypeError:
362 file = '(built-in)'
363
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000364 docloc = os.environ.get("PYTHONDOCS", self.PYTHONDOCS)
365
Skip Montanaro4997a692003-09-10 16:47:51 +0000366 basedir = os.path.join(sys.exec_prefix, "lib",
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000367 "python%d.%d" % sys.version_info[:2])
Skip Montanaro4997a692003-09-10 16:47:51 +0000368 if (isinstance(object, type(os)) and
369 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
370 'marshal', 'posix', 'signal', 'sys',
Georg Brandl2067bfd2008-05-25 13:05:15 +0000371 '_thread', 'zipimport') or
Skip Montanaro4997a692003-09-10 16:47:51 +0000372 (file.startswith(basedir) and
Brian Curtin49c284c2010-03-31 03:19:28 +0000373 not file.startswith(os.path.join(basedir, 'site-packages')))) and
Brian Curtinedef05b2010-04-01 04:05:25 +0000374 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
Skip Montanaro4997a692003-09-10 16:47:51 +0000375 if docloc.startswith("http://"):
Georg Brandl86def6c2008-01-21 20:36:10 +0000376 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
Skip Montanaro4997a692003-09-10 16:47:51 +0000377 else:
Georg Brandl86def6c2008-01-21 20:36:10 +0000378 docloc = os.path.join(docloc, object.__name__ + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000379 else:
380 docloc = None
381 return docloc
382
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000383# -------------------------------------------- HTML documentation generator
384
385class HTMLRepr(Repr):
386 """Class for safely making an HTML representation of a Python object."""
387 def __init__(self):
388 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000389 self.maxlist = self.maxtuple = 20
390 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000391 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000392
393 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000394 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000395
396 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000397 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000398
399 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000400 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000401 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000402 if hasattr(self, methodname):
403 return getattr(self, methodname)(x, level)
404 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000405
406 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000407 test = cram(x, self.maxstring)
408 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000409 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000410 # Backslashes are only literal in the string and are never
411 # needed to make any special characters, so show a raw string.
412 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000413 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000414 r'<font color="#c040c0">\1</font>',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000415 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000416
Skip Montanarodf708782002-03-07 22:58:02 +0000417 repr_str = repr_string
418
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000419 def repr_instance(self, x, level):
420 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000421 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000422 except:
423 return self.escape('<%s instance>' % x.__class__.__name__)
424
425 repr_unicode = repr_string
426
427class HTMLDoc(Doc):
428 """Formatter class for HTML documentation."""
429
430 # ------------------------------------------- HTML formatting utilities
431
432 _repr_instance = HTMLRepr()
433 repr = _repr_instance.repr
434 escape = _repr_instance.escape
435
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000436 def page(self, title, contents):
437 """Format an HTML page."""
Georg Brandl388faac2009-04-10 08:31:48 +0000438 return '''\
Georg Brandle6066942009-04-10 08:28:28 +0000439<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000440<html><head><title>Python: %s</title>
Georg Brandl388faac2009-04-10 08:31:48 +0000441<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000442</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000443%s
444</body></html>''' % (title, contents)
445
446 def heading(self, title, fgcol, bgcol, extras=''):
447 """Format a page heading."""
448 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000449<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000450<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000451<td valign=bottom>&nbsp;<br>
452<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000453><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000454><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000455 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
456
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000457 def section(self, title, fgcol, bgcol, contents, width=6,
458 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000459 """Format a section with a heading."""
460 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000461 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000462 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000463<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000464<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000465<td colspan=3 valign=bottom>&nbsp;<br>
466<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000467 ''' % (bgcol, fgcol, title)
468 if prelude:
469 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000470<tr bgcolor="%s"><td rowspan=2>%s</td>
471<td colspan=2>%s</td></tr>
472<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
473 else:
474 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000475<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000476
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000477 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000478
479 def bigsection(self, title, *args):
480 """Format a section with a big heading."""
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000481 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000482 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000483
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000484 def preformat(self, text):
485 """Format literal preformatted text."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000486 text = self.escape(text.expandtabs())
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000487 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
488 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000489
490 def multicolumn(self, list, format, cols=4):
491 """Format a list of items into a multi-column list."""
492 result = ''
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000493 rows = (len(list)+cols-1)//cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000494 for col in range(cols):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000495 result = result + '<td width="%d%%" valign=top>' % (100//cols)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000496 for i in range(rows*col, rows*col+rows):
497 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000498 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000499 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000500 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000501
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000502 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000503
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000504 def namelink(self, name, *dicts):
505 """Make a link for an identifier, given name-to-URL mappings."""
506 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000507 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000508 return '<a href="%s">%s</a>' % (dict[name], name)
509 return name
510
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000511 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000512 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000513 name, module = object.__name__, sys.modules.get(object.__module__)
514 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000515 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000516 module.__name__, name, classname(object, modname))
517 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000518
519 def modulelink(self, object):
520 """Make a link for a module."""
521 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
522
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000523 def modpkglink(self, modpkginfo):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000524 """Make a link for a module or package to display in an index."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000525 name, path, ispackage, shadowed = modpkginfo
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000526 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000527 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000528 if path:
529 url = '%s.%s.html' % (path, name)
530 else:
531 url = '%s.html' % name
532 if ispackage:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000533 text = '<strong>%s</strong>&nbsp;(package)' % name
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000534 else:
535 text = name
536 return '<a href="%s">%s</a>' % (url, text)
537
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000538 def filelink(self, url, path):
539 """Make a link to source file."""
540 return '<a href="file:%s">%s</a>' % (url, path)
541
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000542 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
543 """Mark up some plain text, given a context of symbols to look for.
544 Each context dictionary maps object names to anchor names."""
545 escape = escape or self.escape
546 results = []
547 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000548 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
549 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000550 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000551 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000552 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000553 match = pattern.search(text, here)
554 if not match: break
555 start, end = match.span()
556 results.append(escape(text[here:start]))
557
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000558 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000559 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000560 url = escape(all).replace('"', '&quot;')
561 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000562 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000563 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
564 results.append('<a href="%s">%s</a>' % (url, escape(all)))
565 elif pep:
Christian Heimes2202f872008-02-06 14:31:34 +0000566 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000567 results.append('<a href="%s">%s</a>' % (url, escape(all)))
568 elif text[end:end+1] == '(':
569 results.append(self.namelink(name, methods, funcs, classes))
570 elif selfdot:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000571 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000572 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000573 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000574 here = end
575 results.append(escape(text[here:]))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000576 return ''.join(results)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000577
578 # ---------------------------------------------- type-specific routines
579
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000580 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000581 """Produce HTML for a class tree as given by inspect.getclasstree()."""
582 result = ''
583 for entry in tree:
584 if type(entry) is type(()):
585 c, bases = entry
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000586 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000587 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000588 if bases and bases != (parent,):
589 parents = []
590 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000591 parents.append(self.classlink(base, modname))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000592 result = result + '(' + ', '.join(parents) + ')'
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000593 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000594 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000595 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000596 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000597 return '<dl>\n%s</dl>\n' % result
598
Tim Peters8dd7ade2001-10-18 19:56:17 +0000599 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000600 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000601 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000602 try:
603 all = object.__all__
604 except AttributeError:
605 all = None
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000606 parts = name.split('.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000607 links = []
608 for i in range(len(parts)-1):
609 links.append(
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000610 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000611 ('.'.join(parts[:i+1]), parts[i]))
612 linkedname = '.'.join(links + parts[-1:])
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000613 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000614 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000615 path = inspect.getabsfile(object)
Ka-Ping Yee6191a232001-04-13 15:00:27 +0000616 url = path
617 if sys.platform == 'win32':
618 import nturl2path
619 url = nturl2path.pathname2url(path)
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000620 filelink = self.filelink(url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000621 except TypeError:
622 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000623 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000624 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000625 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000626 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000627 version = version[11:-1].strip()
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000628 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000629 if hasattr(object, '__date__'):
630 info.append(self.escape(str(object.__date__)))
631 if info:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000632 head = head + ' (%s)' % ', '.join(info)
Skip Montanaro4997a692003-09-10 16:47:51 +0000633 docloc = self.getdocloc(object)
634 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000635 docloc = '<br><a href="%(docloc)s">Module Reference</a>' % locals()
Skip Montanaro4997a692003-09-10 16:47:51 +0000636 else:
637 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000638 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000639 head, '#ffffff', '#7799ee',
640 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000641
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000642 modules = inspect.getmembers(object, inspect.ismodule)
643
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000644 classes, cdict = [], {}
645 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000646 # if __all__ exists, believe it. Otherwise use old heuristic.
647 if (all is not None or
648 (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700649 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000650 classes.append((key, value))
651 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000652 for key, value in classes:
653 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000654 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000655 module = sys.modules.get(modname)
656 if modname != name and module and hasattr(module, key):
657 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000658 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000659 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000660 funcs, fdict = [], {}
661 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000662 # if __all__ exists, believe it. Otherwise use old heuristic.
663 if (all is not None or
664 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700665 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000666 funcs.append((key, value))
667 fdict[key] = '#-' + key
668 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000669 data = []
670 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700671 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000672 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000673
674 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
675 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000676 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000677
678 if hasattr(object, '__path__'):
679 modpkgs = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000680 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
681 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000682 modpkgs.sort()
683 contents = self.multicolumn(modpkgs, self.modpkglink)
684 result = result + self.bigsection(
685 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000686 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000687 contents = self.multicolumn(
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000688 modules, lambda t: self.modulelink(t[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000689 result = result + self.bigsection(
Christian Heimes7131fd92008-02-19 14:21:46 +0000690 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000691
692 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000693 classlist = [value for (key, value) in classes]
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000694 contents = [
695 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000696 for key, value in classes:
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 'Classes', '#ffffff', '#ee77aa', ' '.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000700 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000701 contents = []
702 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000703 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000704 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000705 'Functions', '#ffffff', '#eeaa77', ' '.join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000706 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000707 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000708 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000709 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000710 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000711 'Data', '#ffffff', '#55aa55', '<br>\n'.join(contents))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000712 if hasattr(object, '__author__'):
713 contents = self.markup(str(object.__author__), self.preformat)
714 result = result + self.bigsection(
715 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000716 if hasattr(object, '__credits__'):
717 contents = self.markup(str(object.__credits__), self.preformat)
718 result = result + self.bigsection(
719 'Credits', '#ffffff', '#7799ee', contents)
720
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000721 return result
722
Tim Peters8dd7ade2001-10-18 19:56:17 +0000723 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
724 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000725 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000726 realname = object.__name__
727 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000728 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000729
Tim Petersb47879b2001-09-24 04:47:19 +0000730 contents = []
731 push = contents.append
732
Tim Petersfa26f7c2001-09-24 08:05:11 +0000733 # Cute little class to pump out a horizontal rule between sections.
734 class HorizontalRule:
735 def __init__(self):
736 self.needone = 0
737 def maybe(self):
738 if self.needone:
739 push('<hr>\n')
740 self.needone = 1
741 hr = HorizontalRule()
742
Tim Petersc86f6ca2001-09-26 21:31:51 +0000743 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000744 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000745 if len(mro) > 2:
746 hr.maybe()
747 push('<dl><dt>Method resolution order:</dt>\n')
748 for base in mro:
749 push('<dd>%s</dd>\n' % self.classlink(base,
750 object.__module__))
751 push('</dl>\n')
752
Tim Petersb47879b2001-09-24 04:47:19 +0000753 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000754 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000755 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000756 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000757 push(msg)
758 for name, kind, homecls, value in ok:
759 push(self.document(getattr(object, name), name, mod,
760 funcs, classes, mdict, object))
761 push('\n')
762 return attrs
763
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000764 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000765 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000766 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000767 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000768 push(msg)
769 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000770 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000771 return attrs
772
Tim Petersfa26f7c2001-09-24 08:05:11 +0000773 def spilldata(msg, attrs, predicate):
774 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000775 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000776 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000777 push(msg)
778 for name, kind, homecls, value in ok:
779 base = self.docother(getattr(object, name), name, mod)
Guido van Rossumd59da4b2007-05-22 18:11:13 +0000780 if hasattr(value, '__call__') or inspect.isdatadescriptor(value):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000781 doc = getattr(value, "__doc__", None)
782 else:
783 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000784 if doc is None:
785 push('<dl><dt>%s</dl>\n' % base)
786 else:
787 doc = self.markup(getdoc(value), self.preformat,
788 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000789 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000790 push('<dl><dt>%s%s</dl>\n' % (base, doc))
791 push('\n')
792 return attrs
793
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000794 attrs = [(name, kind, cls, value)
795 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -0700796 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000797
Tim Petersb47879b2001-09-24 04:47:19 +0000798 mdict = {}
799 for key, kind, homecls, value in attrs:
800 mdict[key] = anchor = '#' + name + '-' + key
801 value = getattr(object, key)
802 try:
803 # The value may not be hashable (e.g., a data attr with
804 # a dict or list value).
805 mdict[value] = anchor
806 except TypeError:
807 pass
808
Tim Petersfa26f7c2001-09-24 08:05:11 +0000809 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000810 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000811 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000812 else:
813 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000814 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
815
Georg Brandl1a3284e2007-12-02 09:40:06 +0000816 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000817 attrs = inherited
818 continue
819 elif thisclass is object:
820 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000821 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000822 tag = 'inherited from %s' % self.classlink(thisclass,
823 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000824 tag += ':<br>\n'
825
826 # Sort attrs by name.
Raymond Hettingerd4cb56d2008-01-30 02:55:10 +0000827 attrs.sort(key=lambda t: t[0])
Tim Petersb47879b2001-09-24 04:47:19 +0000828
829 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000830 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000831 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000832 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000833 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000834 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000835 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000836 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
837 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000838 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000839 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000840 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000841 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000842
843 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000844
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000845 if name == realname:
846 title = '<a name="%s">class <strong>%s</strong></a>' % (
847 name, realname)
848 else:
849 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
850 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000851 if bases:
852 parents = []
853 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000854 parents.append(self.classlink(base, object.__module__))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000855 title = title + '(%s)' % ', '.join(parents)
Tim Peters2306d242001-09-25 03:18:32 +0000856 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000857 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000858
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000859 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000860
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000861 def formatvalue(self, object):
862 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000863 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000864
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000865 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000866 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000867 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000868 realname = object.__name__
869 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000870 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000871 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000872 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000873 if inspect.ismethod(object):
Christian Heimesff737952007-11-27 10:40:20 +0000874 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000875 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000876 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000877 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000878 else:
Christian Heimesff737952007-11-27 10:40:20 +0000879 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000880 note = ' method of %s instance' % self.classlink(
Christian Heimesff737952007-11-27 10:40:20 +0000881 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000882 else:
883 note = ' unbound %s method' % self.classlink(imclass,mod)
Christian Heimesff737952007-11-27 10:40:20 +0000884 object = object.__func__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000885
886 if name == realname:
887 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
888 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000889 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000890 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000891 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000892 cl.__name__ + '-' + realname, realname)
893 skipdocs = 1
894 else:
895 reallink = realname
896 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
897 anchor, name, reallink)
Tim Peters4bcfa312001-09-20 06:08:24 +0000898 if inspect.isfunction(object):
Guido van Rossum2e65f892007-02-28 22:03:49 +0000899 args, varargs, kwonlyargs, kwdefaults, varkw, defaults, ann = \
900 inspect.getfullargspec(object)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000901 argspec = inspect.formatargspec(
Guido van Rossum2e65f892007-02-28 22:03:49 +0000902 args, varargs, kwonlyargs, kwdefaults, varkw, defaults, ann,
903 formatvalue=self.formatvalue,
904 formatannotation=inspect.formatannotationrelativeto(object))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000905 if realname == '<lambda>':
Tim Peters59ed4482001-10-31 04:20:26 +0000906 title = '<strong>%s</strong> <em>lambda</em> ' % name
Guido van Rossum2e65f892007-02-28 22:03:49 +0000907 # XXX lambda's won't usually have func_annotations['return']
908 # since the syntax doesn't support but it is possible.
909 # So removing parentheses isn't truly safe.
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000910 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +0000911 else:
912 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000913
Tim Peters2306d242001-09-25 03:18:32 +0000914 decl = title + argspec + (note and self.grey(
915 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000916
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000917 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000918 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000919 else:
920 doc = self.markup(
921 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000922 doc = doc and '<dd><tt>%s</tt></dd>' % doc
923 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000924
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000925 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000926 results = []
927 push = results.append
928
929 if name:
930 push('<dl><dt><strong>%s</strong></dt>\n' % name)
931 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000932 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000933 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000934 push('</dl>\n')
935
936 return ''.join(results)
937
938 def docproperty(self, object, name=None, mod=None, cl=None):
939 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000940 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000941
Tim Peters8dd7ade2001-10-18 19:56:17 +0000942 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000943 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000944 lhs = name and '<strong>%s</strong> = ' % name or ''
945 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000946
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000947 def docdata(self, object, name=None, mod=None, cl=None):
948 """Produce html documentation for a data descriptor."""
949 return self._docdescriptor(name, object, mod)
950
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000951 def index(self, dir, shadowed=None):
952 """Generate an HTML index for a directory of modules."""
953 modpkgs = []
954 if shadowed is None: shadowed = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000955 for importer, name, ispkg in pkgutil.iter_modules([dir]):
956 modpkgs.append((name, '', ispkg, name in shadowed))
957 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000958
959 modpkgs.sort()
960 contents = self.multicolumn(modpkgs, self.modpkglink)
961 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
962
963# -------------------------------------------- text documentation generator
964
965class TextRepr(Repr):
966 """Class for safely making a text representation of a Python object."""
967 def __init__(self):
968 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000969 self.maxlist = self.maxtuple = 20
970 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000971 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000972
973 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000974 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000975 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000976 if hasattr(self, methodname):
977 return getattr(self, methodname)(x, level)
978 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000979
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000980 def repr_string(self, x, level):
981 test = cram(x, self.maxstring)
982 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000983 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000984 # Backslashes are only literal in the string and are never
985 # needed to make any special characters, so show a raw string.
986 return 'r' + testrepr[0] + test + testrepr[0]
987 return testrepr
988
Skip Montanarodf708782002-03-07 22:58:02 +0000989 repr_str = repr_string
990
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000991 def repr_instance(self, x, level):
992 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000993 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000994 except:
995 return '<%s instance>' % x.__class__.__name__
996
997class TextDoc(Doc):
998 """Formatter class for text documentation."""
999
1000 # ------------------------------------------- text formatting utilities
1001
1002 _repr_instance = TextRepr()
1003 repr = _repr_instance.repr
1004
1005 def bold(self, text):
1006 """Format a string in bold by overstriking."""
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001007 return ''.join(ch + '\b' + ch for ch in text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001008
1009 def indent(self, text, prefix=' '):
1010 """Indent text by prepending a given prefix to each line."""
1011 if not text: return ''
Collin Winter72e110c2007-07-17 00:27:30 +00001012 lines = [prefix + line for line in text.split('\n')]
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001013 if lines: lines[-1] = lines[-1].rstrip()
1014 return '\n'.join(lines)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001015
1016 def section(self, title, contents):
1017 """Format a section with a given heading."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001018 clean_contents = self.indent(contents).rstrip()
1019 return self.bold(title) + '\n' + clean_contents + '\n\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001020
1021 # ---------------------------------------------- type-specific routines
1022
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001023 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001024 """Render in text a class tree as returned by inspect.getclasstree()."""
1025 result = ''
1026 for entry in tree:
1027 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001028 c, bases = entry
1029 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001030 if bases and bases != (parent,):
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001031 parents = (classname(c, modname) for c in bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001032 result = result + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001033 result = result + '\n'
1034 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001035 result = result + self.formattree(
1036 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001037 return result
1038
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001039 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001040 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001041 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001042 synop, desc = splitdoc(getdoc(object))
1043 result = self.section('NAME', name + (synop and ' - ' + synop))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001044 all = getattr(object, '__all__', None)
Skip Montanaro4997a692003-09-10 16:47:51 +00001045 docloc = self.getdocloc(object)
1046 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001047 result = result + self.section('MODULE REFERENCE', docloc + """
1048
1049The following documentation is automatically generated from the Python source
1050files. It may be incomplete, incorrect or include features that are considered
1051implementation detail and may vary between Python implementations. When in
1052doubt, consult the module reference at the location listed above.
1053""")
Skip Montanaro4997a692003-09-10 16:47:51 +00001054
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001055 if desc:
1056 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001057
1058 classes = []
1059 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001060 # if __all__ exists, believe it. Otherwise use old heuristic.
1061 if (all is not None
1062 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001063 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001064 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001065 funcs = []
1066 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001067 # if __all__ exists, believe it. Otherwise use old heuristic.
1068 if (all is not None or
1069 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001070 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001071 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001072 data = []
1073 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001074 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001075 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001076
Christian Heimes1af737c2008-01-23 08:24:23 +00001077 modpkgs = []
1078 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001079 if hasattr(object, '__path__'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001080 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Christian Heimes1af737c2008-01-23 08:24:23 +00001081 modpkgs_names.add(modname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001082 if ispkg:
1083 modpkgs.append(modname + ' (package)')
1084 else:
1085 modpkgs.append(modname)
1086
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001087 modpkgs.sort()
1088 result = result + self.section(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001089 'PACKAGE CONTENTS', '\n'.join(modpkgs))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001090
Christian Heimes1af737c2008-01-23 08:24:23 +00001091 # Detect submodules as sometimes created by C extensions
1092 submodules = []
1093 for key, value in inspect.getmembers(object, inspect.ismodule):
1094 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1095 submodules.append(key)
1096 if submodules:
1097 submodules.sort()
1098 result = result + self.section(
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001099 'SUBMODULES', '\n'.join(submodules))
Christian Heimes1af737c2008-01-23 08:24:23 +00001100
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001101 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001102 classlist = [value for key, value in classes]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001103 contents = [self.formattree(
1104 inspect.getclasstree(classlist, 1), name)]
1105 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001106 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001107 result = result + self.section('CLASSES', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001108
1109 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001110 contents = []
1111 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001112 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001113 result = result + self.section('FUNCTIONS', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001114
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001115 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001116 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001117 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001118 contents.append(self.docother(value, key, name, maxlen=70))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001119 result = result + self.section('DATA', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001120
1121 if hasattr(object, '__version__'):
1122 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001123 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001124 version = version[11:-1].strip()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001125 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001126 if hasattr(object, '__date__'):
1127 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001128 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001129 result = result + self.section('AUTHOR', str(object.__author__))
1130 if hasattr(object, '__credits__'):
1131 result = result + self.section('CREDITS', str(object.__credits__))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001132 try:
1133 file = inspect.getabsfile(object)
1134 except TypeError:
1135 file = '(built-in)'
1136 result = result + self.section('FILE', file)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001137 return result
1138
Georg Brandl9bd45f992010-12-03 09:58:38 +00001139 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001140 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001141 realname = object.__name__
1142 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001143 bases = object.__bases__
1144
Tim Petersc86f6ca2001-09-26 21:31:51 +00001145 def makename(c, m=object.__module__):
1146 return classname(c, m)
1147
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001148 if name == realname:
1149 title = 'class ' + self.bold(realname)
1150 else:
1151 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001152 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001153 parents = map(makename, bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001154 title = title + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001155
1156 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001157 contents = doc and [doc + '\n'] or []
1158 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001159
Tim Petersc86f6ca2001-09-26 21:31:51 +00001160 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001161 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001162 if len(mro) > 2:
1163 push("Method resolution order:")
1164 for base in mro:
1165 push(' ' + makename(base))
1166 push('')
1167
Tim Petersf4aad8e2001-09-24 22:40:47 +00001168 # Cute little class to pump out a horizontal rule between sections.
1169 class HorizontalRule:
1170 def __init__(self):
1171 self.needone = 0
1172 def maybe(self):
1173 if self.needone:
1174 push('-' * 70)
1175 self.needone = 1
1176 hr = HorizontalRule()
1177
Tim Peters28355492001-09-23 21:29:55 +00001178 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001179 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001180 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001181 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001182 push(msg)
1183 for name, kind, homecls, value in ok:
1184 push(self.document(getattr(object, name),
1185 name, mod, object))
1186 return attrs
1187
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001188 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001189 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001190 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001191 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001192 push(msg)
1193 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001194 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001195 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001196
Tim Petersfa26f7c2001-09-24 08:05:11 +00001197 def spilldata(msg, attrs, predicate):
1198 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001199 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001200 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001201 push(msg)
1202 for name, kind, homecls, value in ok:
Guido van Rossumd59da4b2007-05-22 18:11:13 +00001203 if hasattr(value, '__call__') or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001204 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001205 else:
1206 doc = None
Tim Peters28355492001-09-23 21:29:55 +00001207 push(self.docother(getattr(object, name),
Georg Brandl8b813db2005-10-01 16:32:31 +00001208 name, mod, maxlen=70, doc=doc) + '\n')
Tim Peters28355492001-09-23 21:29:55 +00001209 return attrs
1210
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001211 attrs = [(name, kind, cls, value)
1212 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -07001213 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001214
Tim Petersfa26f7c2001-09-24 08:05:11 +00001215 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001216 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001217 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001218 else:
1219 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001220 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1221
Georg Brandl1a3284e2007-12-02 09:40:06 +00001222 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001223 attrs = inherited
1224 continue
1225 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001226 tag = "defined here"
1227 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001228 tag = "inherited from %s" % classname(thisclass,
1229 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001230
1231 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001232 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001233
1234 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001235 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001236 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001237 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001238 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001239 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001240 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001241 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1242 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001243 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1244 lambda t: t[1] == 'data')
Tim Peters28355492001-09-23 21:29:55 +00001245 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001246 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001247
1248 contents = '\n'.join(contents)
1249 if not contents:
1250 return title + '\n'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001251 return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001252
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001253 def formatvalue(self, object):
1254 """Format an argument default value as text."""
1255 return '=' + self.repr(object)
1256
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001257 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001258 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001259 realname = object.__name__
1260 name = name or realname
1261 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001262 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001263 if inspect.ismethod(object):
Christian Heimesff737952007-11-27 10:40:20 +00001264 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001265 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001266 if imclass is not cl:
1267 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001268 else:
Christian Heimesff737952007-11-27 10:40:20 +00001269 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001270 note = ' method of %s instance' % classname(
Christian Heimesff737952007-11-27 10:40:20 +00001271 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001272 else:
1273 note = ' unbound %s method' % classname(imclass,mod)
Christian Heimesff737952007-11-27 10:40:20 +00001274 object = object.__func__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001275
1276 if name == realname:
1277 title = self.bold(realname)
1278 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001279 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001280 cl.__dict__[realname] is object):
1281 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001282 title = self.bold(name) + ' = ' + realname
Tim Peters4bcfa312001-09-20 06:08:24 +00001283 if inspect.isfunction(object):
Guido van Rossum2e65f892007-02-28 22:03:49 +00001284 args, varargs, varkw, defaults, kwonlyargs, kwdefaults, ann = \
1285 inspect.getfullargspec(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001286 argspec = inspect.formatargspec(
Guido van Rossum2e65f892007-02-28 22:03:49 +00001287 args, varargs, varkw, defaults, kwonlyargs, kwdefaults, ann,
1288 formatvalue=self.formatvalue,
1289 formatannotation=inspect.formatannotationrelativeto(object))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001290 if realname == '<lambda>':
Georg Brandl501dd0d2006-02-17 09:45:40 +00001291 title = self.bold(name) + ' lambda '
Guido van Rossum2e65f892007-02-28 22:03:49 +00001292 # XXX lambda's won't usually have func_annotations['return']
1293 # since the syntax doesn't support but it is possible.
1294 # So removing parentheses isn't truly safe.
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001295 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +00001296 else:
1297 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001298 decl = title + argspec + note
1299
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001300 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001301 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001302 else:
1303 doc = getdoc(object) or ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001304 return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001305
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001306 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001307 results = []
1308 push = results.append
1309
1310 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001311 push(self.bold(name))
1312 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001313 doc = getdoc(value) or ''
1314 if doc:
1315 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001316 push('\n')
1317 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001318
1319 def docproperty(self, object, name=None, mod=None, cl=None):
1320 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001321 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001322
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001323 def docdata(self, object, name=None, mod=None, cl=None):
1324 """Produce text documentation for a data descriptor."""
1325 return self._docdescriptor(name, object, mod)
1326
Georg Brandl8b813db2005-10-01 16:32:31 +00001327 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001328 """Produce text documentation for a data object."""
1329 repr = self.repr(object)
1330 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001331 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001332 chop = maxlen - len(line)
1333 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001334 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001335 if doc is not None:
1336 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001337 return line
1338
Georg Brandld80d5f42010-12-03 07:47:22 +00001339class _PlainTextDoc(TextDoc):
1340 """Subclass of TextDoc which overrides string styling"""
1341 def bold(self, text):
1342 return text
1343
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001344# --------------------------------------------------------- user interfaces
1345
1346def pager(text):
1347 """The first time this is called, determine what kind of pager to use."""
1348 global pager
1349 pager = getpager()
1350 pager(text)
1351
1352def getpager():
1353 """Decide what method to use for paging through text."""
Guido van Rossuma01a8b62007-05-27 09:20:14 +00001354 if not hasattr(sys.stdout, "isatty"):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001355 return plainpager
1356 if not sys.stdin.isatty() or not sys.stdout.isatty():
1357 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001358 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001359 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001360 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001361 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001362 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001363 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001364 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001365 if os.environ.get('TERM') in ('dumb', 'emacs'):
1366 return plainpager
Andrew MacIntyre54e0eab2002-03-03 03:12:30 +00001367 if sys.platform == 'win32' or sys.platform.startswith('os2'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001368 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001369 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001370 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001371
1372 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001373 (fd, filename) = tempfile.mkstemp()
1374 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001375 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001376 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001377 return lambda text: pipepager(text, 'more')
1378 else:
1379 return ttypager
1380 finally:
1381 os.unlink(filename)
1382
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001383def plain(text):
1384 """Remove boldface formatting from text."""
1385 return re.sub('.\b', '', text)
1386
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001387def pipepager(text, cmd):
1388 """Page through text by feeding it to another program."""
1389 pipe = os.popen(cmd, 'w')
1390 try:
1391 pipe.write(text)
1392 pipe.close()
1393 except IOError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001394 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001395
1396def tempfilepager(text, cmd):
1397 """Page through text by invoking a program on a temporary file."""
1398 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001399 filename = tempfile.mktemp()
1400 file = open(filename, 'w')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001401 file.write(text)
1402 file.close()
1403 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001404 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001405 finally:
1406 os.unlink(filename)
1407
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001408def ttypager(text):
1409 """Page through text on a text terminal."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001410 lines = plain(text).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001411 try:
1412 import tty
1413 fd = sys.stdin.fileno()
1414 old = tty.tcgetattr(fd)
1415 tty.setcbreak(fd)
1416 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001417 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001418 tty = None
1419 getchar = lambda: sys.stdin.readline()[:-1][:1]
1420
1421 try:
1422 r = inc = os.environ.get('LINES', 25) - 1
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001423 sys.stdout.write('\n'.join(lines[:inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001424 while lines[r:]:
1425 sys.stdout.write('-- more --')
1426 sys.stdout.flush()
1427 c = getchar()
1428
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001429 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001430 sys.stdout.write('\r \r')
1431 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001432 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001433 sys.stdout.write('\r \r' + lines[r] + '\n')
1434 r = r + 1
1435 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001436 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001437 r = r - inc - inc
1438 if r < 0: r = 0
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001439 sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001440 r = r + inc
1441
1442 finally:
1443 if tty:
1444 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1445
1446def plainpager(text):
1447 """Simply print unformatted text. This is the ultimate fallback."""
1448 sys.stdout.write(plain(text))
1449
1450def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001451 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001452 if inspect.ismodule(thing):
1453 if thing.__name__ in sys.builtin_module_names:
1454 return 'built-in module ' + thing.__name__
1455 if hasattr(thing, '__path__'):
1456 return 'package ' + thing.__name__
1457 else:
1458 return 'module ' + thing.__name__
1459 if inspect.isbuiltin(thing):
1460 return 'built-in function ' + thing.__name__
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001461 if inspect.isgetsetdescriptor(thing):
1462 return 'getset descriptor %s.%s.%s' % (
1463 thing.__objclass__.__module__, thing.__objclass__.__name__,
1464 thing.__name__)
1465 if inspect.ismemberdescriptor(thing):
1466 return 'member descriptor %s.%s.%s' % (
1467 thing.__objclass__.__module__, thing.__objclass__.__name__,
1468 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001469 if inspect.isclass(thing):
1470 return 'class ' + thing.__name__
1471 if inspect.isfunction(thing):
1472 return 'function ' + thing.__name__
1473 if inspect.ismethod(thing):
1474 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001475 return type(thing).__name__
1476
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001477def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001478 """Locate an object by name or dotted path, importing as necessary."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001479 parts = [part for part in path.split('.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001480 module, n = None, 0
1481 while n < len(parts):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001482 nextmodule = safeimport('.'.join(parts[:n+1]), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001483 if nextmodule: module, n = nextmodule, n + 1
1484 else: break
1485 if module:
1486 object = module
1487 for part in parts[n:]:
1488 try: object = getattr(object, part)
1489 except AttributeError: return None
1490 return object
1491 else:
Georg Brandl1a3284e2007-12-02 09:40:06 +00001492 if hasattr(builtins, path):
1493 return getattr(builtins, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001494
1495# --------------------------------------- interactive interpreter interface
1496
1497text = TextDoc()
Georg Brandld80d5f42010-12-03 07:47:22 +00001498plaintext = _PlainTextDoc()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001499html = HTMLDoc()
1500
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001501def resolve(thing, forceload=0):
1502 """Given an object or a path to an object, get the object and its name."""
1503 if isinstance(thing, str):
1504 object = locate(thing, forceload)
1505 if not object:
Collin Winterce36ad82007-08-30 01:19:48 +00001506 raise ImportError('no Python documentation found for %r' % thing)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001507 return object, thing
1508 else:
1509 return thing, getattr(thing, '__name__', None)
1510
Georg Brandld80d5f42010-12-03 07:47:22 +00001511def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
1512 renderer=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001513 """Render text documentation, given an object or a path to an object."""
Georg Brandld80d5f42010-12-03 07:47:22 +00001514 if renderer is None:
1515 renderer = text
Guido van Rossumd8faa362007-04-27 19:54:29 +00001516 object, name = resolve(thing, forceload)
1517 desc = describe(object)
1518 module = inspect.getmodule(object)
1519 if name and '.' in name:
1520 desc += ' in ' + name[:name.rfind('.')]
1521 elif module and module is not object:
1522 desc += ' in module ' + module.__name__
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001523
1524 if not (inspect.ismodule(object) or
Guido van Rossumd8faa362007-04-27 19:54:29 +00001525 inspect.isclass(object) or
1526 inspect.isroutine(object) or
1527 inspect.isgetsetdescriptor(object) or
1528 inspect.ismemberdescriptor(object) or
1529 isinstance(object, property)):
1530 # If the passed object is a piece of data or an instance,
1531 # document its available methods instead of its value.
1532 object = type(object)
1533 desc += ' object'
Georg Brandld80d5f42010-12-03 07:47:22 +00001534 return title % desc + '\n\n' + renderer.document(object, name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001535
Georg Brandld80d5f42010-12-03 07:47:22 +00001536def doc(thing, title='Python Library Documentation: %s', forceload=0,
1537 output=None):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001538 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001539 try:
Georg Brandld80d5f42010-12-03 07:47:22 +00001540 if output is None:
1541 pager(render_doc(thing, title, forceload))
1542 else:
1543 output.write(render_doc(thing, title, forceload, plaintext))
Guido van Rossumb940e112007-01-10 16:19:56 +00001544 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001545 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001546
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001547def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001548 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001549 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001550 object, name = resolve(thing, forceload)
1551 page = html.page(describe(object), html.document(object, name))
Georg Brandl388faac2009-04-10 08:31:48 +00001552 file = open(name + '.html', 'w', encoding='utf-8')
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001553 file.write(page)
1554 file.close()
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001555 print('wrote', name + '.html')
Guido van Rossumb940e112007-01-10 16:19:56 +00001556 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001557 print(value)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001558
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001559def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001560 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001561 if done is None: done = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001562 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1563 writedoc(modname)
1564 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001565
1566class Helper:
Georg Brandl6b38daa2008-06-01 21:05:17 +00001567
1568 # These dictionaries map a topic name to either an alias, or a tuple
1569 # (label, seealso-items). The "label" is the label of the corresponding
1570 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl5617db82009-04-27 16:28:57 +00001571 # in pydoc_data/topics.py.
Georg Brandl6b38daa2008-06-01 21:05:17 +00001572 #
1573 # CAUTION: if you change one of these dictionaries, be sure to adapt the
1574 # list of needed labels in Doc/tools/sphinxext/pyspecific.py and
Georg Brandl5617db82009-04-27 16:28:57 +00001575 # regenerate the pydoc_data/topics.py file by running
Georg Brandl6b38daa2008-06-01 21:05:17 +00001576 # make pydoc-topics
1577 # in Doc/ and copying the output file into the Lib/ directory.
1578
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001579 keywords = {
Ezio Melottib185a042011-04-28 07:42:55 +03001580 'False': '',
1581 'None': '',
1582 'True': '',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001583 'and': 'BOOLEAN',
Guido van Rossumd8faa362007-04-27 19:54:29 +00001584 'as': 'with',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001585 'assert': ('assert', ''),
1586 'break': ('break', 'while for'),
1587 'class': ('class', 'CLASSES SPECIALMETHODS'),
1588 'continue': ('continue', 'while for'),
1589 'def': ('function', ''),
1590 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001591 'elif': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001592 'else': ('else', 'while for'),
Georg Brandl0d855392008-08-30 19:53:05 +00001593 'except': 'try',
1594 'finally': 'try',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001595 'for': ('for', 'break continue while'),
Georg Brandl0d855392008-08-30 19:53:05 +00001596 'from': 'import',
Georg Brandl74abf6f2010-11-20 19:54:36 +00001597 'global': ('global', 'nonlocal NAMESPACES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001598 'if': ('if', 'TRUTHVALUE'),
1599 'import': ('import', 'MODULES'),
Georg Brandl395ed242009-09-04 08:07:32 +00001600 'in': ('in', 'SEQUENCEMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001601 'is': 'COMPARISON',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001602 'lambda': ('lambda', 'FUNCTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001603 'nonlocal': ('nonlocal', 'global NAMESPACES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001604 'not': 'BOOLEAN',
1605 'or': 'BOOLEAN',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001606 'pass': ('pass', ''),
1607 'raise': ('raise', 'EXCEPTIONS'),
1608 'return': ('return', 'FUNCTIONS'),
1609 'try': ('try', 'EXCEPTIONS'),
1610 'while': ('while', 'break continue if TRUTHVALUE'),
1611 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1612 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001613 }
Georg Brandldb7b6b92009-01-01 15:53:14 +00001614 # Either add symbols to this dictionary or to the symbols dictionary
1615 # directly: Whichever is easier. They are merged later.
1616 _symbols_inverse = {
1617 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'),
1618 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1619 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1620 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1621 'UNARY' : ('-', '~'),
1622 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1623 '^=', '<<=', '>>=', '**=', '//='),
1624 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1625 'COMPLEX' : ('j', 'J')
1626 }
1627 symbols = {
1628 '%': 'OPERATORS FORMATTING',
1629 '**': 'POWER',
1630 ',': 'TUPLES LISTS FUNCTIONS',
1631 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1632 '...': 'ELLIPSIS',
1633 ':': 'SLICINGS DICTIONARYLITERALS',
1634 '@': 'def class',
1635 '\\': 'STRINGS',
1636 '_': 'PRIVATENAMES',
1637 '__': 'PRIVATENAMES SPECIALMETHODS',
1638 '`': 'BACKQUOTES',
1639 '(': 'TUPLES FUNCTIONS CALLS',
1640 ')': 'TUPLES FUNCTIONS CALLS',
1641 '[': 'LISTS SUBSCRIPTS SLICINGS',
1642 ']': 'LISTS SUBSCRIPTS SLICINGS'
1643 }
1644 for topic, symbols_ in _symbols_inverse.items():
1645 for symbol in symbols_:
1646 topics = symbols.get(symbol, topic)
1647 if topic not in topics:
1648 topics = topics + ' ' + topic
1649 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001650
1651 topics = {
Georg Brandl6b38daa2008-06-01 21:05:17 +00001652 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1653 'FUNCTIONS CLASSES MODULES FILES inspect'),
1654 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS '
1655 'FORMATTING TYPES'),
1656 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1657 'FORMATTING': ('formatstrings', 'OPERATORS'),
1658 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1659 'FORMATTING TYPES'),
1660 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1661 'INTEGER': ('integers', 'int range'),
1662 'FLOAT': ('floating', 'float math'),
1663 'COMPLEX': ('imaginary', 'complex cmath'),
1664 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING range LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001665 'MAPPINGS': 'DICTIONARIES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001666 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1667 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1668 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1669 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001670 'FRAMEOBJECTS': 'TYPES',
1671 'TRACEBACKS': 'TYPES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001672 'NONE': ('bltin-null-object', ''),
1673 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
1674 'FILES': ('bltin-file-objects', ''),
1675 'SPECIALATTRIBUTES': ('specialattrs', ''),
1676 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1677 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001678 'PACKAGES': 'import',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001679 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1680 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1681 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1682 'LISTS DICTIONARIES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001683 'OPERATORS': 'EXPRESSIONS',
1684 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001685 'OBJECTS': ('objects', 'TYPES'),
1686 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
Georg Brandl395ed242009-09-04 08:07:32 +00001687 'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS '
1688 'NUMBERMETHODS CLASSES'),
Mark Dickinsona56c4672009-01-27 18:17:45 +00001689 'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001690 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1691 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001692 'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS '
Georg Brandl6b38daa2008-06-01 21:05:17 +00001693 'SPECIALMETHODS'),
1694 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1695 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1696 'SPECIALMETHODS'),
1697 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001698 'NAMESPACES': ('naming', 'global nonlocal ASSIGNMENT DELETION DYNAMICFEATURES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001699 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001700 'SCOPING': 'NAMESPACES',
1701 'FRAMES': 'NAMESPACES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001702 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1703 'CONVERSIONS': ('conversions', ''),
1704 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1705 'SPECIALIDENTIFIERS': ('id-classes', ''),
1706 'PRIVATENAMES': ('atom-identifiers', ''),
1707 'LITERALS': ('atom-literals', 'STRINGS NUMBERS TUPLELITERALS '
1708 'LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001709 'TUPLES': 'SEQUENCES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001710 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1711 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1712 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1713 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1714 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1715 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001716 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'),
1717 'SLICINGS': ('slicings', 'SEQUENCEMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001718 'CALLS': ('calls', 'EXPRESSIONS'),
1719 'POWER': ('power', 'EXPRESSIONS'),
1720 'UNARY': ('unary', 'EXPRESSIONS'),
1721 'BINARY': ('binary', 'EXPRESSIONS'),
1722 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1723 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1724 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1725 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001726 'ASSERTION': 'assert',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001727 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1728 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001729 'DELETION': 'del',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001730 'RETURNING': 'return',
1731 'IMPORTING': 'import',
1732 'CONDITIONAL': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001733 'LOOPING': ('compound', 'for while break continue'),
1734 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1735 'DEBUGGING': ('debugger', 'pdb'),
1736 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001737 }
1738
Georg Brandl78aa3962010-07-31 21:51:48 +00001739 def __init__(self, input=None, output=None):
1740 self._input = input
1741 self._output = output
1742
Georg Brandl76ae3972010-08-01 06:32:55 +00001743 input = property(lambda self: self._input or sys.stdin)
1744 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001745
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001746 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001747 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001748 self()
1749 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001750 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001751
Alexander Belopolsky2e733c92010-07-04 17:00:20 +00001752 _GoInteractive = object()
1753 def __call__(self, request=_GoInteractive):
1754 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001755 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001756 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001757 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001758 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001759 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001760You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001761If you want to ask for help on a particular object directly from the
1762interpreter, you can type "help(object)". Executing "help('string')"
1763has the same effect as typing a particular string at the help> prompt.
1764''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001765
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001766 def interact(self):
1767 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001768 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001769 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001770 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001771 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001772 except (KeyboardInterrupt, EOFError):
1773 break
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001774 request = replace(request, '"', '', "'", '').strip()
1775 if request.lower() in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001776 self.help(request)
1777
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001778 def getline(self, prompt):
Guido van Rossum7c086c02008-01-02 03:52:38 +00001779 """Read one line, using input() when appropriate."""
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001780 if self.input is sys.stdin:
Guido van Rossum7c086c02008-01-02 03:52:38 +00001781 return input(prompt)
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001782 else:
1783 self.output.write(prompt)
1784 self.output.flush()
1785 return self.input.readline()
1786
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001787 def help(self, request):
1788 if type(request) is type(''):
R. David Murray1f1b9d32009-05-27 20:56:59 +00001789 request = request.strip()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001790 if request == 'help': self.intro()
1791 elif request == 'keywords': self.listkeywords()
Georg Brandldb7b6b92009-01-01 15:53:14 +00001792 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001793 elif request == 'topics': self.listtopics()
1794 elif request == 'modules': self.listmodules()
1795 elif request[:8] == 'modules ':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001796 self.listmodules(request.split()[1])
Georg Brandldb7b6b92009-01-01 15:53:14 +00001797 elif request in self.symbols: self.showsymbol(request)
Ezio Melottib185a042011-04-28 07:42:55 +03001798 elif request in ['True', 'False', 'None']:
1799 # special case these keywords since they are objects too
1800 doc(eval(request), 'Help on %s:')
Raymond Hettinger54f02222002-06-01 14:18:47 +00001801 elif request in self.keywords: self.showtopic(request)
1802 elif request in self.topics: self.showtopic(request)
Georg Brandld80d5f42010-12-03 07:47:22 +00001803 elif request: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001804 elif isinstance(request, Helper): self()
Georg Brandld80d5f42010-12-03 07:47:22 +00001805 else: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001806 self.output.write('\n')
1807
1808 def intro(self):
1809 self.output.write('''
1810Welcome to Python %s! This is the online help utility.
1811
1812If this is your first time using Python, you should definitely check out
Georg Brandl86def6c2008-01-21 20:36:10 +00001813the tutorial on the Internet at http://docs.python.org/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001814
1815Enter the name of any module, keyword, or topic to get help on writing
1816Python programs and using Python modules. To quit this help utility and
1817return to the interpreter, just type "quit".
1818
1819To get a list of available modules, keywords, or topics, type "modules",
1820"keywords", or "topics". Each module also comes with a one-line summary
1821of what it does; to list the modules whose summaries contain a given word
1822such as "spam", type "modules spam".
1823''' % sys.version[:3])
1824
1825 def list(self, items, columns=4, width=80):
Guido van Rossum486364b2007-06-30 05:01:58 +00001826 items = list(sorted(items))
1827 colw = width // columns
1828 rows = (len(items) + columns - 1) // columns
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001829 for row in range(rows):
1830 for col in range(columns):
1831 i = col * rows + row
1832 if i < len(items):
1833 self.output.write(items[i])
1834 if col < columns - 1:
Guido van Rossum486364b2007-06-30 05:01:58 +00001835 self.output.write(' ' + ' ' * (colw - 1 - len(items[i])))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001836 self.output.write('\n')
1837
1838 def listkeywords(self):
1839 self.output.write('''
1840Here is a list of the Python keywords. Enter any keyword to get more help.
1841
1842''')
1843 self.list(self.keywords.keys())
1844
Georg Brandldb7b6b92009-01-01 15:53:14 +00001845 def listsymbols(self):
1846 self.output.write('''
1847Here is a list of the punctuation symbols which Python assigns special meaning
1848to. Enter any symbol to get more help.
1849
1850''')
1851 self.list(self.symbols.keys())
1852
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001853 def listtopics(self):
1854 self.output.write('''
1855Here is a list of available topics. Enter any topic name to get more help.
1856
1857''')
1858 self.list(self.topics.keys())
1859
Georg Brandldb7b6b92009-01-01 15:53:14 +00001860 def showtopic(self, topic, more_xrefs=''):
Georg Brandl6b38daa2008-06-01 21:05:17 +00001861 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001862 import pydoc_data.topics
Georg Brandl6b38daa2008-06-01 21:05:17 +00001863 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001864 self.output.write('''
Georg Brandl6b38daa2008-06-01 21:05:17 +00001865Sorry, topic and keyword documentation is not available because the
Georg Brandl5617db82009-04-27 16:28:57 +00001866module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001867''')
1868 return
1869 target = self.topics.get(topic, self.keywords.get(topic))
1870 if not target:
1871 self.output.write('no documentation found for %s\n' % repr(topic))
1872 return
1873 if type(target) is type(''):
Georg Brandldb7b6b92009-01-01 15:53:14 +00001874 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001875
Georg Brandl6b38daa2008-06-01 21:05:17 +00001876 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001877 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001878 doc = pydoc_data.topics.topics[label]
Georg Brandl6b38daa2008-06-01 21:05:17 +00001879 except KeyError:
1880 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001881 return
Georg Brandl6b38daa2008-06-01 21:05:17 +00001882 pager(doc.strip() + '\n')
Georg Brandldb7b6b92009-01-01 15:53:14 +00001883 if more_xrefs:
1884 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001885 if xrefs:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001886 import formatter
Guido van Rossum34d19282007-08-09 01:03:29 +00001887 buffer = io.StringIO()
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001888 formatter.DumbWriter(buffer).send_flowing_data(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001889 'Related help topics: ' + ', '.join(xrefs.split()) + '\n')
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001890 self.output.write('\n%s\n' % buffer.getvalue())
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001891
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001892 def _gettopic(self, topic, more_xrefs=''):
1893 """Return unbuffered tuple of (topic, xrefs).
1894
Georg Brandld2f38572011-01-30 08:37:19 +00001895 If an error occurs here, the exception is caught and displayed by
1896 the url handler.
1897
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001898 This function duplicates the showtopic method but returns its
1899 result directly so it can be formatted for display in an html page.
1900 """
1901 try:
1902 import pydoc_data.topics
1903 except ImportError:
1904 return('''
1905Sorry, topic and keyword documentation is not available because the
1906module "pydoc_data.topics" could not be found.
1907''' , '')
1908 target = self.topics.get(topic, self.keywords.get(topic))
1909 if not target:
Georg Brandld2f38572011-01-30 08:37:19 +00001910 raise ValueError('could not find topic')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001911 if isinstance(target, str):
1912 return self._gettopic(target, more_xrefs)
1913 label, xrefs = target
Georg Brandld2f38572011-01-30 08:37:19 +00001914 doc = pydoc_data.topics.topics[label]
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001915 if more_xrefs:
1916 xrefs = (xrefs or '') + ' ' + more_xrefs
1917 return doc, xrefs
1918
Georg Brandldb7b6b92009-01-01 15:53:14 +00001919 def showsymbol(self, symbol):
1920 target = self.symbols[symbol]
1921 topic, _, xrefs = target.partition(' ')
1922 self.showtopic(topic, xrefs)
1923
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001924 def listmodules(self, key=''):
1925 if key:
1926 self.output.write('''
1927Here is a list of matching modules. Enter any module name to get more help.
1928
1929''')
1930 apropos(key)
1931 else:
1932 self.output.write('''
1933Please wait a moment while I gather a list of all available modules...
1934
1935''')
1936 modules = {}
1937 def callback(path, modname, desc, modules=modules):
1938 if modname and modname[-9:] == '.__init__':
1939 modname = modname[:-9] + ' (package)'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001940 if modname.find('.') < 0:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001941 modules[modname] = 1
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001942 def onerror(modname):
1943 callback(None, modname, None)
1944 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001945 self.list(modules.keys())
1946 self.output.write('''
1947Enter any module name to get more help. Or, type "modules spam" to search
1948for modules whose descriptions contain the word "spam".
1949''')
1950
Georg Brandl78aa3962010-07-31 21:51:48 +00001951help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001952
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001953class Scanner:
1954 """A generic tree iterator."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001955 def __init__(self, roots, children, descendp):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001956 self.roots = roots[:]
1957 self.state = []
1958 self.children = children
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001959 self.descendp = descendp
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001960
1961 def next(self):
1962 if not self.state:
1963 if not self.roots:
1964 return None
1965 root = self.roots.pop(0)
1966 self.state = [(root, self.children(root))]
1967 node, children = self.state[-1]
1968 if not children:
1969 self.state.pop()
1970 return self.next()
1971 child = children.pop(0)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001972 if self.descendp(child):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001973 self.state.append((child, self.children(child)))
1974 return child
1975
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001976
1977class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001978 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001979
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001980 def run(self, callback, key=None, completer=None, onerror=None):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001981 if key: key = key.lower()
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001982 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001983 seen = {}
1984
1985 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001986 if modname != '__main__':
1987 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00001988 if key is None:
1989 callback(None, modname, '')
1990 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001991 name = __import__(modname).__doc__ or ''
1992 desc = name.split('\n')[0]
1993 name = modname + ' - ' + desc
1994 if name.lower().find(key) >= 0:
Ka-Ping Yee66246962001-04-12 11:59:50 +00001995 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001996
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001997 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001998 if self.quit:
1999 break
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002000
2001 # XXX Skipping this file is a workaround for a bug
2002 # that causes python to crash with a segfault.
2003 # http://bugs.python.org/issue9319
2004 #
2005 # TODO Remove this once the bug is fixed.
2006 if modname in {'test.badsyntax_pep3120', 'badsyntax_pep3120'}:
2007 continue
2008
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002009 if key is None:
2010 callback(None, modname, '')
2011 else:
Georg Brandl126c8792009-04-05 15:05:48 +00002012 try:
2013 loader = importer.find_module(modname)
2014 except SyntaxError:
2015 # raised by tests for bad coding cookies or BOM
2016 continue
2017 if hasattr(loader, 'get_source'):
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002018 try:
2019 source = loader.get_source(modname)
2020 except UnicodeDecodeError:
2021 if onerror:
2022 onerror(modname)
2023 continue
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002024 desc = source_synopsis(io.StringIO(source)) or ''
Georg Brandl126c8792009-04-05 15:05:48 +00002025 if hasattr(loader, 'get_filename'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002026 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002027 else:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002028 path = None
2029 else:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002030 try:
2031 module = loader.load_module(modname)
2032 except ImportError:
2033 if onerror:
2034 onerror(modname)
2035 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002036 desc = (module.__doc__ or '').splitlines()[0]
2037 path = getattr(module,'__file__',None)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002038 name = modname + ' - ' + desc
2039 if name.lower().find(key) >= 0:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002040 callback(path, modname, desc)
2041
2042 if completer:
2043 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002044
2045def apropos(key):
2046 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002047 def callback(path, modname, desc):
2048 if modname[-9:] == '.__init__':
2049 modname = modname[:-9] + ' (package)'
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002050 print(modname, desc and '- ' + desc)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002051 def onerror(modname):
2052 pass
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002053 with warnings.catch_warnings():
2054 warnings.filterwarnings('ignore') # ignore problems during import
2055 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002056
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002057# --------------------------------------------------- Web browser interface
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002058
Ka-Ping Yee66246962001-04-12 11:59:50 +00002059def serve(port, callback=None, completer=None):
Georg Brandl83e9f4c2008-06-12 18:52:31 +00002060 import http.server, email.message, select
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002061
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002062 msg = 'the pydoc.serve() function is deprecated'
2063 warnings.warn(msg, DeprecationWarning, stacklevel=2)
2064
Georg Brandl24420152008-05-26 16:32:26 +00002065 class DocHandler(http.server.BaseHTTPRequestHandler):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002066 def send_document(self, title, contents):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002067 try:
2068 self.send_response(200)
Georg Brandl825fc8b2008-01-19 20:44:32 +00002069 self.send_header('Content-Type', 'text/html; charset=UTF-8')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002070 self.end_headers()
Georg Brandl825fc8b2008-01-19 20:44:32 +00002071 self.wfile.write(html.page(title, contents).encode('utf-8'))
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002072 except IOError: pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002073
2074 def do_GET(self):
2075 path = self.path
2076 if path[-5:] == '.html': path = path[:-5]
2077 if path[:1] == '/': path = path[1:]
2078 if path and path != '.':
2079 try:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00002080 obj = locate(path, forceload=1)
Guido van Rossumb940e112007-01-10 16:19:56 +00002081 except ErrorDuringImport as value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002082 self.send_document(path, html.escape(str(value)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002083 return
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002084 if obj:
2085 self.send_document(describe(obj), html.document(obj, path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002086 else:
2087 self.send_document(path,
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002088'no Python documentation found for %s' % repr(path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002089 else:
2090 heading = html.heading(
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002091'<big><big><strong>Python: Index of Modules</strong></big></big>',
2092'#ffffff', '#7799ee')
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002093 def bltinlink(name):
2094 return '<a href="%s.html">%s</a>' % (name, name)
Georg Brandl661b0a12008-01-27 18:16:00 +00002095 names = [x for x in sys.builtin_module_names if x != '__main__']
2096 contents = html.multicolumn(names, bltinlink)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002097 indices = ['<p>' + html.bigsection(
2098 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2099
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002100 seen = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002101 for dir in sys.path:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002102 indices.append(html.index(dir, seen))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002103 contents = heading + ' '.join(indices) + '''<p align=right>
Tim Peters2306d242001-09-25 03:18:32 +00002104<font color="#909090" face="helvetica, arial"><strong>
2105pydoc</strong> by Ka-Ping Yee &lt;ping@lfw.org&gt;</font>'''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002106 self.send_document('Index of Modules', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002107
2108 def log_message(self, *args): pass
2109
Georg Brandl24420152008-05-26 16:32:26 +00002110 class DocServer(http.server.HTTPServer):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002111 def __init__(self, port, callback):
Ronald Oussoren94f25282010-05-05 19:11:21 +00002112 host = 'localhost'
Senthil Kumaran7ff59132010-08-18 19:32:21 +00002113 self.address = (host, port)
Ka-Ping Yeedb8ed152001-03-02 05:58:17 +00002114 self.url = 'http://%s:%d/' % (host, port)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002115 self.callback = callback
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002116 self.base.__init__(self, self.address, self.handler)
2117
2118 def serve_until_quit(self):
2119 import select
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002120 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002121 while not self.quit:
2122 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2123 if rd: self.handle_request()
Victor Stinnera3abd1d2011-01-03 16:12:39 +00002124 self.server_close()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002125
2126 def server_activate(self):
2127 self.base.server_activate(self)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002128 if self.callback: self.callback(self)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002129
Georg Brandl24420152008-05-26 16:32:26 +00002130 DocServer.base = http.server.HTTPServer
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002131 DocServer.handler = DocHandler
Georg Brandl83e9f4c2008-06-12 18:52:31 +00002132 DocHandler.MessageClass = email.message.Message
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002133 try:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002134 try:
2135 DocServer(port, callback).serve_until_quit()
2136 except (KeyboardInterrupt, select.error):
2137 pass
2138 finally:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002139 if completer: completer()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002140
2141# ----------------------------------------------------- graphical interface
2142
2143def gui():
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002144 """Graphical interface (starts Web server and pops up a control window)."""
2145
2146 msg = ('the pydoc.gui() function and "pydoc -g" option are deprecated\n',
2147 'use "pydoc.browse() function and "pydoc -b" option instead.')
2148 warnings.warn(msg, DeprecationWarning, stacklevel=2)
2149
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002150 class GUI:
2151 def __init__(self, window, port=7464):
2152 self.window = window
2153 self.server = None
2154 self.scanner = None
2155
Georg Brandl14fc4272008-05-17 18:39:55 +00002156 import tkinter
2157 self.server_frm = tkinter.Frame(window)
2158 self.title_lbl = tkinter.Label(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002159 text='Starting server...\n ')
Georg Brandl14fc4272008-05-17 18:39:55 +00002160 self.open_btn = tkinter.Button(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002161 text='open browser', command=self.open, state='disabled')
Georg Brandl14fc4272008-05-17 18:39:55 +00002162 self.quit_btn = tkinter.Button(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002163 text='quit serving', command=self.quit, state='disabled')
2164
Georg Brandl14fc4272008-05-17 18:39:55 +00002165 self.search_frm = tkinter.Frame(window)
2166 self.search_lbl = tkinter.Label(self.search_frm, text='Search for')
2167 self.search_ent = tkinter.Entry(self.search_frm)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002168 self.search_ent.bind('<Return>', self.search)
Georg Brandl14fc4272008-05-17 18:39:55 +00002169 self.stop_btn = tkinter.Button(self.search_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002170 text='stop', pady=0, command=self.stop, state='disabled')
2171 if sys.platform == 'win32':
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002172 # Trying to hide and show this button crashes under Windows.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002173 self.stop_btn.pack(side='right')
2174
2175 self.window.title('pydoc')
2176 self.window.protocol('WM_DELETE_WINDOW', self.quit)
2177 self.title_lbl.pack(side='top', fill='x')
2178 self.open_btn.pack(side='left', fill='x', expand=1)
2179 self.quit_btn.pack(side='right', fill='x', expand=1)
2180 self.server_frm.pack(side='top', fill='x')
2181
2182 self.search_lbl.pack(side='left')
2183 self.search_ent.pack(side='right', fill='x', expand=1)
2184 self.search_frm.pack(side='top', fill='x')
2185 self.search_ent.focus_set()
2186
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002187 font = ('helvetica', sys.platform == 'win32' and 8 or 10)
Georg Brandl14fc4272008-05-17 18:39:55 +00002188 self.result_lst = tkinter.Listbox(window, font=font, height=6)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002189 self.result_lst.bind('<Button-1>', self.select)
2190 self.result_lst.bind('<Double-Button-1>', self.goto)
Georg Brandl14fc4272008-05-17 18:39:55 +00002191 self.result_scr = tkinter.Scrollbar(window,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002192 orient='vertical', command=self.result_lst.yview)
2193 self.result_lst.config(yscrollcommand=self.result_scr.set)
2194
Georg Brandl14fc4272008-05-17 18:39:55 +00002195 self.result_frm = tkinter.Frame(window)
2196 self.goto_btn = tkinter.Button(self.result_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002197 text='go to selected', command=self.goto)
Georg Brandl14fc4272008-05-17 18:39:55 +00002198 self.hide_btn = tkinter.Button(self.result_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002199 text='hide results', command=self.hide)
2200 self.goto_btn.pack(side='left', fill='x', expand=1)
2201 self.hide_btn.pack(side='right', fill='x', expand=1)
2202
2203 self.window.update()
2204 self.minwidth = self.window.winfo_width()
2205 self.minheight = self.window.winfo_height()
2206 self.bigminheight = (self.server_frm.winfo_reqheight() +
2207 self.search_frm.winfo_reqheight() +
2208 self.result_lst.winfo_reqheight() +
2209 self.result_frm.winfo_reqheight())
2210 self.bigwidth, self.bigheight = self.minwidth, self.bigminheight
2211 self.expanded = 0
2212 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2213 self.window.wm_minsize(self.minwidth, self.minheight)
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002214 self.window.tk.willdispatch()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002215
2216 import threading
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002217 threading.Thread(
2218 target=serve, args=(port, self.ready, self.quit)).start()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002219
2220 def ready(self, server):
2221 self.server = server
2222 self.title_lbl.config(
2223 text='Python documentation server at\n' + server.url)
2224 self.open_btn.config(state='normal')
2225 self.quit_btn.config(state='normal')
2226
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002227 def open(self, event=None, url=None):
2228 url = url or self.server.url
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002229 import webbrowser
2230 webbrowser.open(url)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002231
2232 def quit(self, event=None):
2233 if self.server:
2234 self.server.quit = 1
2235 self.window.quit()
2236
2237 def search(self, event=None):
2238 key = self.search_ent.get()
2239 self.stop_btn.pack(side='right')
2240 self.stop_btn.config(state='normal')
2241 self.search_lbl.config(text='Searching for "%s"...' % key)
2242 self.search_ent.forget()
2243 self.search_lbl.pack(side='left')
2244 self.result_lst.delete(0, 'end')
2245 self.goto_btn.config(state='disabled')
2246 self.expand()
2247
2248 import threading
2249 if self.scanner:
2250 self.scanner.quit = 1
2251 self.scanner = ModuleScanner()
2252 threading.Thread(target=self.scanner.run,
Ka-Ping Yee6dcfa382001-04-12 20:27:31 +00002253 args=(self.update, key, self.done)).start()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002254
2255 def update(self, path, modname, desc):
2256 if modname[-9:] == '.__init__':
2257 modname = modname[:-9] + ' (package)'
2258 self.result_lst.insert('end',
2259 modname + ' - ' + (desc or '(no description)'))
2260
2261 def stop(self, event=None):
2262 if self.scanner:
2263 self.scanner.quit = 1
2264 self.scanner = None
2265
2266 def done(self):
2267 self.scanner = None
2268 self.search_lbl.config(text='Search for')
2269 self.search_lbl.pack(side='left')
2270 self.search_ent.pack(side='right', fill='x', expand=1)
2271 if sys.platform != 'win32': self.stop_btn.forget()
2272 self.stop_btn.config(state='disabled')
2273
2274 def select(self, event=None):
2275 self.goto_btn.config(state='normal')
2276
2277 def goto(self, event=None):
2278 selection = self.result_lst.curselection()
2279 if selection:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002280 modname = self.result_lst.get(selection[0]).split()[0]
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002281 self.open(url=self.server.url + modname + '.html')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002282
2283 def collapse(self):
2284 if not self.expanded: return
2285 self.result_frm.forget()
2286 self.result_scr.forget()
2287 self.result_lst.forget()
2288 self.bigwidth = self.window.winfo_width()
2289 self.bigheight = self.window.winfo_height()
2290 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2291 self.window.wm_minsize(self.minwidth, self.minheight)
2292 self.expanded = 0
2293
2294 def expand(self):
2295 if self.expanded: return
2296 self.result_frm.pack(side='bottom', fill='x')
2297 self.result_scr.pack(side='right', fill='y')
2298 self.result_lst.pack(side='top', fill='both', expand=1)
2299 self.window.wm_geometry('%dx%d' % (self.bigwidth, self.bigheight))
2300 self.window.wm_minsize(self.minwidth, self.bigminheight)
2301 self.expanded = 1
2302
2303 def hide(self, event=None):
2304 self.stop()
2305 self.collapse()
2306
Georg Brandl14fc4272008-05-17 18:39:55 +00002307 import tkinter
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002308 try:
Georg Brandl14fc4272008-05-17 18:39:55 +00002309 root = tkinter.Tk()
Martin v. Löwise09bd932004-08-22 16:13:26 +00002310 # Tk will crash if pythonw.exe has an XP .manifest
2311 # file and the root has is not destroyed explicitly.
2312 # If the problem is ever fixed in Tk, the explicit
2313 # destroy can go.
2314 try:
2315 gui = GUI(root)
2316 root.mainloop()
2317 finally:
2318 root.destroy()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002319 except KeyboardInterrupt:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002320 pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002321
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002322
2323# --------------------------------------- enhanced Web browser interface
2324
2325def _start_server(urlhandler, port):
2326 """Start an HTTP server thread on a specific port.
2327
2328 Start an HTML/text server thread, so HTML or text documents can be
2329 browsed dynamically and interactively with a Web browser. Example use:
2330
2331 >>> import time
2332 >>> import pydoc
2333
2334 Define a URL handler. To determine what the client is asking
2335 for, check the URL and content_type.
2336
2337 Then get or generate some text or HTML code and return it.
2338
2339 >>> def my_url_handler(url, content_type):
2340 ... text = 'the URL sent was: (%s, %s)' % (url, content_type)
2341 ... return text
2342
2343 Start server thread on port 0.
2344 If you use port 0, the server will pick a random port number.
2345 You can then use serverthread.port to get the port number.
2346
2347 >>> port = 0
2348 >>> serverthread = pydoc._start_server(my_url_handler, port)
2349
2350 Check that the server is really started. If it is, open browser
2351 and get first page. Use serverthread.url as the starting page.
2352
2353 >>> if serverthread.serving:
2354 ... import webbrowser
2355
2356 The next two lines are commented out so a browser doesn't open if
2357 doctest is run on this module.
2358
2359 #... webbrowser.open(serverthread.url)
2360 #True
2361
2362 Let the server do its thing. We just need to monitor its status.
2363 Use time.sleep so the loop doesn't hog the CPU.
2364
2365 >>> starttime = time.time()
2366 >>> timeout = 1 #seconds
2367
2368 This is a short timeout for testing purposes.
2369
2370 >>> while serverthread.serving:
2371 ... time.sleep(.01)
2372 ... if serverthread.serving and time.time() - starttime > timeout:
2373 ... serverthread.stop()
2374 ... break
2375
2376 Print any errors that may have occurred.
2377
2378 >>> print(serverthread.error)
2379 None
2380 """
2381 import http.server
2382 import email.message
2383 import select
2384 import threading
2385
2386 class DocHandler(http.server.BaseHTTPRequestHandler):
2387
2388 def do_GET(self):
2389 """Process a request from an HTML browser.
2390
2391 The URL received is in self.path.
2392 Get an HTML page from self.urlhandler and send it.
2393 """
2394 if self.path.endswith('.css'):
2395 content_type = 'text/css'
2396 else:
2397 content_type = 'text/html'
2398 self.send_response(200)
Georg Brandld2f38572011-01-30 08:37:19 +00002399 self.send_header('Content-Type', '%s; charset=UTF-8' % content_type)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002400 self.end_headers()
2401 self.wfile.write(self.urlhandler(
2402 self.path, content_type).encode('utf-8'))
2403
2404 def log_message(self, *args):
2405 # Don't log messages.
2406 pass
2407
2408 class DocServer(http.server.HTTPServer):
2409
2410 def __init__(self, port, callback):
2411 self.host = (sys.platform == 'mac') and '127.0.0.1' or 'localhost'
2412 self.address = ('', port)
2413 self.callback = callback
2414 self.base.__init__(self, self.address, self.handler)
2415 self.quit = False
2416
2417 def serve_until_quit(self):
2418 while not self.quit:
2419 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2420 if rd:
2421 self.handle_request()
Victor Stinnera3abd1d2011-01-03 16:12:39 +00002422 self.server_close()
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002423
2424 def server_activate(self):
2425 self.base.server_activate(self)
2426 if self.callback:
2427 self.callback(self)
2428
2429 class ServerThread(threading.Thread):
2430
2431 def __init__(self, urlhandler, port):
2432 self.urlhandler = urlhandler
2433 self.port = int(port)
2434 threading.Thread.__init__(self)
2435 self.serving = False
2436 self.error = None
2437
2438 def run(self):
2439 """Start the server."""
2440 try:
2441 DocServer.base = http.server.HTTPServer
2442 DocServer.handler = DocHandler
2443 DocHandler.MessageClass = email.message.Message
2444 DocHandler.urlhandler = staticmethod(self.urlhandler)
2445 docsvr = DocServer(self.port, self.ready)
2446 self.docserver = docsvr
2447 docsvr.serve_until_quit()
2448 except Exception as e:
2449 self.error = e
2450
2451 def ready(self, server):
2452 self.serving = True
2453 self.host = server.host
2454 self.port = server.server_port
2455 self.url = 'http://%s:%d/' % (self.host, self.port)
2456
2457 def stop(self):
2458 """Stop the server and this thread nicely"""
2459 self.docserver.quit = True
2460 self.serving = False
2461 self.url = None
2462
2463 thread = ServerThread(urlhandler, port)
2464 thread.start()
2465 # Wait until thread.serving is True to make sure we are
2466 # really up before returning.
2467 while not thread.error and not thread.serving:
2468 time.sleep(.01)
2469 return thread
2470
2471
2472def _url_handler(url, content_type="text/html"):
2473 """The pydoc url handler for use with the pydoc server.
2474
2475 If the content_type is 'text/css', the _pydoc.css style
2476 sheet is read and returned if it exits.
2477
2478 If the content_type is 'text/html', then the result of
2479 get_html_page(url) is returned.
2480 """
2481 class _HTMLDoc(HTMLDoc):
2482
2483 def page(self, title, contents):
2484 """Format an HTML page."""
2485 css_path = "pydoc_data/_pydoc.css"
2486 css_link = (
2487 '<link rel="stylesheet" type="text/css" href="%s">' %
2488 css_path)
2489 return '''\
2490<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Georg Brandld2f38572011-01-30 08:37:19 +00002491<html><head><title>Pydoc: %s</title>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002492<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Georg Brandld2f38572011-01-30 08:37:19 +00002493%s</head><body bgcolor="#f0f0f8">%s<div style="clear:both;padding-top:.5em;">%s</div>
2494</body></html>''' % (title, css_link, html_navbar(), contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002495
2496 def filelink(self, url, path):
2497 return '<a href="getfile?key=%s">%s</a>' % (url, path)
2498
2499
2500 html = _HTMLDoc()
2501
2502 def html_navbar():
Georg Brandld2f38572011-01-30 08:37:19 +00002503 version = html.escape("%s [%s, %s]" % (platform.python_version(),
2504 platform.python_build()[0],
2505 platform.python_compiler()))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002506 return """
2507 <div style='float:left'>
Georg Brandld2f38572011-01-30 08:37:19 +00002508 Python %s<br>%s
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002509 </div>
2510 <div style='float:right'>
2511 <div style='text-align:center'>
2512 <a href="index.html">Module Index</a>
2513 : <a href="topics.html">Topics</a>
2514 : <a href="keywords.html">Keywords</a>
2515 </div>
2516 <div>
Georg Brandld2f38572011-01-30 08:37:19 +00002517 <form action="get" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002518 <input type=text name=key size=15>
2519 <input type=submit value="Get">
Georg Brandld2f38572011-01-30 08:37:19 +00002520 </form>&nbsp;
2521 <form action="search" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002522 <input type=text name=key size=15>
2523 <input type=submit value="Search">
2524 </form>
2525 </div>
2526 </div>
Georg Brandld2f38572011-01-30 08:37:19 +00002527 """ % (version, html.escape(platform.platform(terse=True)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002528
2529 def html_index():
2530 """Module Index page."""
2531
2532 def bltinlink(name):
2533 return '<a href="%s.html">%s</a>' % (name, name)
2534
2535 heading = html.heading(
2536 '<big><big><strong>Index of Modules</strong></big></big>',
2537 '#ffffff', '#7799ee')
2538 names = [name for name in sys.builtin_module_names
2539 if name != '__main__']
2540 contents = html.multicolumn(names, bltinlink)
2541 contents = [heading, '<p>' + html.bigsection(
2542 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2543
2544 seen = {}
2545 for dir in sys.path:
2546 contents.append(html.index(dir, seen))
2547
2548 contents.append(
2549 '<p align=right><font color="#909090" face="helvetica,'
2550 'arial"><strong>pydoc</strong> by Ka-Ping Yee'
2551 '&lt;ping@lfw.org&gt;</font>')
Nick Coghlanecace282010-12-03 16:08:46 +00002552 return 'Index of Modules', ''.join(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002553
2554 def html_search(key):
2555 """Search results page."""
2556 # scan for modules
2557 search_result = []
2558
2559 def callback(path, modname, desc):
2560 if modname[-9:] == '.__init__':
2561 modname = modname[:-9] + ' (package)'
2562 search_result.append((modname, desc and '- ' + desc))
2563
2564 with warnings.catch_warnings():
2565 warnings.filterwarnings('ignore') # ignore problems during import
2566 ModuleScanner().run(callback, key)
2567
2568 # format page
2569 def bltinlink(name):
2570 return '<a href="%s.html">%s</a>' % (name, name)
2571
2572 results = []
2573 heading = html.heading(
2574 '<big><big><strong>Search Results</strong></big></big>',
2575 '#ffffff', '#7799ee')
2576 for name, desc in search_result:
2577 results.append(bltinlink(name) + desc)
2578 contents = heading + html.bigsection(
2579 'key = %s' % key, '#ffffff', '#ee77aa', '<br>'.join(results))
Nick Coghlanecace282010-12-03 16:08:46 +00002580 return 'Search Results', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002581
2582 def html_getfile(path):
2583 """Get and display a source file listing safely."""
Nick Coghlanecace282010-12-03 16:08:46 +00002584 path = path.replace('%20', ' ')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002585 with open(path, 'r') as fp:
2586 lines = html.escape(fp.read())
2587 body = '<pre>%s</pre>' % lines
2588 heading = html.heading(
2589 '<big><big><strong>File Listing</strong></big></big>',
2590 '#ffffff', '#7799ee')
2591 contents = heading + html.bigsection(
2592 'File: %s' % path, '#ffffff', '#ee77aa', body)
Nick Coghlanecace282010-12-03 16:08:46 +00002593 return 'getfile %s' % path, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002594
2595 def html_topics():
2596 """Index of topic texts available."""
2597
2598 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002599 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002600
2601 heading = html.heading(
2602 '<big><big><strong>INDEX</strong></big></big>',
2603 '#ffffff', '#7799ee')
2604 names = sorted(Helper.topics.keys())
2605
2606 contents = html.multicolumn(names, bltinlink)
2607 contents = heading + html.bigsection(
2608 'Topics', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002609 return 'Topics', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002610
2611 def html_keywords():
2612 """Index of keywords."""
2613 heading = html.heading(
2614 '<big><big><strong>INDEX</strong></big></big>',
2615 '#ffffff', '#7799ee')
2616 names = sorted(Helper.keywords.keys())
2617
2618 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002619 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002620
2621 contents = html.multicolumn(names, bltinlink)
2622 contents = heading + html.bigsection(
2623 'Keywords', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002624 return 'Keywords', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002625
2626 def html_topicpage(topic):
2627 """Topic or keyword help page."""
2628 buf = io.StringIO()
2629 htmlhelp = Helper(buf, buf)
2630 contents, xrefs = htmlhelp._gettopic(topic)
2631 if topic in htmlhelp.keywords:
2632 title = 'KEYWORD'
2633 else:
2634 title = 'TOPIC'
2635 heading = html.heading(
2636 '<big><big><strong>%s</strong></big></big>' % title,
2637 '#ffffff', '#7799ee')
Georg Brandld2f38572011-01-30 08:37:19 +00002638 contents = '<pre>%s</pre>' % html.markup(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002639 contents = html.bigsection(topic , '#ffffff','#ee77aa', contents)
Georg Brandld2f38572011-01-30 08:37:19 +00002640 if xrefs:
2641 xrefs = sorted(xrefs.split())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002642
Georg Brandld2f38572011-01-30 08:37:19 +00002643 def bltinlink(name):
2644 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002645
Georg Brandld2f38572011-01-30 08:37:19 +00002646 xrefs = html.multicolumn(xrefs, bltinlink)
2647 xrefs = html.section('Related help topics: ',
2648 '#ffffff', '#ee77aa', xrefs)
Nick Coghlanecace282010-12-03 16:08:46 +00002649 return ('%s %s' % (title, topic),
2650 ''.join((heading, contents, xrefs)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002651
Georg Brandld2f38572011-01-30 08:37:19 +00002652 def html_getobj(url):
2653 obj = locate(url, forceload=1)
2654 if obj is None and url != 'None':
2655 raise ValueError('could not find object')
2656 title = describe(obj)
2657 content = html.document(obj, url)
2658 return title, content
2659
2660 def html_error(url, exc):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002661 heading = html.heading(
2662 '<big><big><strong>Error</strong></big></big>',
Georg Brandld2f38572011-01-30 08:37:19 +00002663 '#ffffff', '#7799ee')
2664 contents = '<br>'.join(html.escape(line) for line in
2665 format_exception_only(type(exc), exc))
2666 contents = heading + html.bigsection(url, '#ffffff', '#bb0000',
2667 contents)
2668 return "Error - %s" % url, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002669
2670 def get_html_page(url):
2671 """Generate an HTML page for url."""
Georg Brandld2f38572011-01-30 08:37:19 +00002672 complete_url = url
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002673 if url.endswith('.html'):
2674 url = url[:-5]
Georg Brandld2f38572011-01-30 08:37:19 +00002675 try:
2676 if url in ("", "index"):
2677 title, content = html_index()
2678 elif url == "topics":
2679 title, content = html_topics()
2680 elif url == "keywords":
2681 title, content = html_keywords()
2682 elif '=' in url:
2683 op, _, url = url.partition('=')
2684 if op == "search?key":
2685 title, content = html_search(url)
2686 elif op == "getfile?key":
2687 title, content = html_getfile(url)
2688 elif op == "topic?key":
2689 # try topics first, then objects.
2690 try:
2691 title, content = html_topicpage(url)
2692 except ValueError:
2693 title, content = html_getobj(url)
2694 elif op == "get?key":
2695 # try objects first, then topics.
2696 if url in ("", "index"):
2697 title, content = html_index()
2698 else:
2699 try:
2700 title, content = html_getobj(url)
2701 except ValueError:
2702 title, content = html_topicpage(url)
2703 else:
2704 raise ValueError('bad pydoc url')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002705 else:
Georg Brandld2f38572011-01-30 08:37:19 +00002706 title, content = html_getobj(url)
2707 except Exception as exc:
2708 # Catch any errors and display them in an error page.
2709 title, content = html_error(complete_url, exc)
2710 return html.page(title, content)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002711
2712 if url.startswith('/'):
2713 url = url[1:]
2714 if content_type == 'text/css':
2715 path_here = os.path.dirname(os.path.realpath(__file__))
Georg Brandld2f38572011-01-30 08:37:19 +00002716 css_path = os.path.join(path_here, url)
2717 with open(css_path) as fp:
2718 return ''.join(fp.readlines())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002719 elif content_type == 'text/html':
2720 return get_html_page(url)
Georg Brandld2f38572011-01-30 08:37:19 +00002721 # Errors outside the url handler are caught by the server.
2722 raise TypeError('unknown content type %r for url %s' % (content_type, url))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002723
2724
2725def browse(port=0, *, open_browser=True):
2726 """Start the enhanced pydoc Web server and open a Web browser.
2727
2728 Use port '0' to start the server on an arbitrary port.
2729 Set open_browser to False to suppress opening a browser.
2730 """
2731 import webbrowser
2732 serverthread = _start_server(_url_handler, port)
2733 if serverthread.error:
2734 print(serverthread.error)
2735 return
2736 if serverthread.serving:
2737 server_help_msg = 'Server commands: [b]rowser, [q]uit'
2738 if open_browser:
2739 webbrowser.open(serverthread.url)
2740 try:
2741 print('Server ready at', serverthread.url)
2742 print(server_help_msg)
2743 while serverthread.serving:
2744 cmd = input('server> ')
2745 cmd = cmd.lower()
2746 if cmd == 'q':
2747 break
2748 elif cmd == 'b':
2749 webbrowser.open(serverthread.url)
2750 else:
2751 print(server_help_msg)
2752 except (KeyboardInterrupt, EOFError):
2753 print()
2754 finally:
2755 if serverthread.serving:
2756 serverthread.stop()
2757 print('Server stopped')
2758
2759
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002760# -------------------------------------------------- command-line interface
2761
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002762def ispath(x):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002763 return isinstance(x, str) and x.find(os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002764
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002765def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002766 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002767 import getopt
Guido van Rossum756aa932007-04-07 03:04:01 +00002768 class BadUsage(Exception): pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002769
Nick Coghlan106274b2009-11-15 23:04:33 +00002770 # Scripts don't get the current directory in their path by default
2771 # unless they are run with the '-m' switch
2772 if '' not in sys.path:
2773 scriptdir = os.path.dirname(sys.argv[0])
2774 if scriptdir in sys.path:
2775 sys.path.remove(scriptdir)
2776 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002777
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002778 try:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002779 opts, args = getopt.getopt(sys.argv[1:], 'bgk:p:w')
2780 writing = False
2781 start_server = False
2782 open_browser = False
2783 port = None
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002784 for opt, val in opts:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002785 if opt == '-g':
2786 gui()
2787 return
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002788 if opt == '-b':
2789 start_server = True
2790 open_browser = True
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002791 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002792 apropos(val)
2793 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002794 if opt == '-p':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002795 start_server = True
2796 port = val
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002797 if opt == '-w':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002798 writing = True
2799
2800 if start_server == True:
2801 if port == None:
2802 port = 0
2803 browse(port, open_browser=open_browser)
2804 return
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002805
2806 if not args: raise BadUsage
2807 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002808 if ispath(arg) and not os.path.exists(arg):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002809 print('file %r does not exist' % arg)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002810 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002811 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002812 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002813 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002814 if writing:
2815 if ispath(arg) and os.path.isdir(arg):
2816 writedocs(arg)
2817 else:
2818 writedoc(arg)
2819 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002820 help.help(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +00002821 except ErrorDuringImport as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002822 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002823
2824 except (getopt.error, BadUsage):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002825 cmd = os.path.splitext(os.path.basename(sys.argv[0]))[0]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002826 print("""pydoc - the Python documentation tool
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002827
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002828{cmd} <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002829 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002830 Python keyword, topic, function, module, or package, or a dotted
2831 reference to a class or function within a module or module in a
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002832 package. If <name> contains a '{sep}', it is used as the path to a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002833 Python source file to document. If name is 'keywords', 'topics',
2834 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002835
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002836{cmd} -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002837 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002838
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002839{cmd} -p <port>
2840 Start an HTTP server on the given port on the local machine. Port
2841 number 0 can be used to get an arbitrary unused port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002842
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002843{cmd} -b
2844 Start an HTTP server on an arbitrary unused port and open a Web browser
2845 to interactively browse documentation. The -p option can be used with
2846 the -b option to explicitly specify the server port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002847
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002848{cmd} -g
2849 Deprecated.
2850
2851{cmd} -w <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002852 Write out the HTML documentation for a module to a file in the current
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002853 directory. If <name> contains a '{sep}', it is treated as a filename; if
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002854 it names a directory, documentation is written for all the contents.
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002855""".format(cmd=cmd, sep=os.sep))
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002856
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002857if __name__ == '__main__':
2858 cli()