blob: 95eb3183b7859e18c31d98771a03006507bc2d9f [file] [log] [blame]
Benjamin Peterson90f5ba52010-03-11 22:53:45 +00001#!/usr/bin/env python3
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00002# -*- coding: latin-1 -*-
Ka-Ping Yee1d384632001-03-01 00:24:32 +00003"""Generate Python documentation in HTML or text for interactive use.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00004
Ka-Ping Yeedd175342001-02-27 14:43:46 +00005In the Python interpreter, do "from pydoc import help" to provide online
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00006help. Calling help(thing) on a Python object documents the object.
7
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00008Or, at the shell command line outside of Python:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00009
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000010Run "pydoc <name>" to show documentation on something. <name> may be
11the name of a function, module, package, or a dotted reference to a
12class or function within a module or module in a package. If the
13argument contains a path segment delimiter (e.g. slash on Unix,
14backslash on Windows) it is treated as the path to a Python source file.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000015
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000016Run "pydoc -k <keyword>" to search for a keyword in the synopsis lines
17of all available modules.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000018
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000019Run "pydoc -p <port>" to start an HTTP server on a given port on the
20local machine to generate documentation web pages.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000021
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000022For platforms without a command line, "pydoc -g" starts the HTTP server
23and also pops up a little window for controlling it.
24
25Run "pydoc -w <name>" to write out the HTML documentation for a module
26to a file named "<name>.html".
Skip Montanaro4997a692003-09-10 16:47:51 +000027
28Module docs for core modules are assumed to be in
29
Georg Brandl86def6c2008-01-21 20:36:10 +000030 http://docs.python.org/library/
Skip Montanaro4997a692003-09-10 16:47:51 +000031
32This can be overridden by setting the PYTHONDOCS environment variable
33to a different URL or to a local directory containing the Library
34Reference Manual pages.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000035"""
Ka-Ping Yeedd175342001-02-27 14:43:46 +000036
37__author__ = "Ka-Ping Yee <ping@lfw.org>"
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000038__date__ = "26 February 2001"
Jeremy Hylton3e0055f2005-10-20 19:59:25 +000039
Ka-Ping Yee09d7d9a2001-02-27 22:43:48 +000040__version__ = "$Revision$"
Martin v. Löwis6fe8f192004-11-14 10:21:04 +000041__credits__ = """Guido van Rossum, for an excellent programming language.
Ka-Ping Yee5e2b1732001-02-27 23:35:09 +000042Tommy Burnette, the original creator of manpy.
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000043Paul Prescod, for all his work on onlinehelp.
44Richard Chamberlain, for the first implementation of textdoc.
Raymond Hettingered2dbe32005-01-01 07:51:01 +000045"""
Ka-Ping Yeedd175342001-02-27 14:43:46 +000046
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000047# Known bugs that can't be fixed here:
48# - imp.load_module() cannot be prevented from clobbering existing
49# loaded modules, so calling synopsis() on a binary module file
50# changes the contents of any existing module with the same name.
51# - If the __file__ attribute on a module is a relative path and
52# the current directory is changed with os.chdir(), an incorrect
53# path will be displayed.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000054
Georg Brandl1a3284e2007-12-02 09:40:06 +000055import sys, imp, os, re, inspect, builtins, pkgutil
Alexandre Vassalotti1f2ba4b2008-05-16 07:12:44 +000056from reprlib import Repr
Benjamin Peterson0289b152009-06-28 17:22:03 +000057from traceback import extract_tb as _extract_tb
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000058try:
59 from collections import deque
60except ImportError:
61 # Python 2.3 compatibility
62 class deque(list):
63 def popleft(self):
64 return self.pop(0)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000065
66# --------------------------------------------------------- common routines
67
Ka-Ping Yeedd175342001-02-27 14:43:46 +000068def pathdirs():
69 """Convert sys.path into a list of absolute, existing, unique paths."""
70 dirs = []
Ka-Ping Yee1d384632001-03-01 00:24:32 +000071 normdirs = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +000072 for dir in sys.path:
73 dir = os.path.abspath(dir or '.')
Ka-Ping Yee1d384632001-03-01 00:24:32 +000074 normdir = os.path.normcase(dir)
75 if normdir not in normdirs and os.path.isdir(dir):
Ka-Ping Yeedd175342001-02-27 14:43:46 +000076 dirs.append(dir)
Ka-Ping Yee1d384632001-03-01 00:24:32 +000077 normdirs.append(normdir)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000078 return dirs
79
80def getdoc(object):
81 """Get the doc string or comments for an object."""
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000082 result = inspect.getdoc(object) or inspect.getcomments(object)
Neal Norwitz9d72bb42007-04-17 08:48:32 +000083 return result and re.sub('^ *\n', '', result.rstrip()) or ''
Ka-Ping Yeedd175342001-02-27 14:43:46 +000084
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000085def splitdoc(doc):
86 """Split a doc string into a synopsis line (if any) and the rest."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +000087 lines = doc.strip().split('\n')
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000088 if len(lines) == 1:
89 return lines[0], ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +000090 elif len(lines) >= 2 and not lines[1].rstrip():
91 return lines[0], '\n'.join(lines[2:])
92 return '', '\n'.join(lines)
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000093
Ka-Ping Yeedd175342001-02-27 14:43:46 +000094def classname(object, modname):
95 """Get a class name and qualify it with a module name if necessary."""
96 name = object.__name__
97 if object.__module__ != modname:
98 name = object.__module__ + '.' + name
99 return name
100
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000101def isdata(object):
Georg Brandl94432422005-07-22 21:52:25 +0000102 """Check if an object is of a type that probably means it's data."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000103 return not (inspect.ismodule(object) or inspect.isclass(object) or
104 inspect.isroutine(object) or inspect.isframe(object) or
105 inspect.istraceback(object) or inspect.iscode(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000106
107def replace(text, *pairs):
108 """Do a series of global replacements on a string."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000109 while pairs:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000110 text = pairs[1].join(text.split(pairs[0]))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000111 pairs = pairs[2:]
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000112 return text
113
114def cram(text, maxlen):
115 """Omit part of a string if needed to make it fit in a maximum length."""
116 if len(text) > maxlen:
Raymond Hettingerfca3bb62002-10-21 04:44:11 +0000117 pre = max(0, (maxlen-3)//2)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000118 post = max(0, maxlen-3-pre)
119 return text[:pre] + '...' + text[len(text)-post:]
120 return text
121
Brett Cannon84601f12004-06-19 01:22:48 +0000122_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000123def stripid(text):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000124 """Remove the hexadecimal id from a Python object representation."""
Brett Cannonc6c1f472004-06-19 01:02:51 +0000125 # The behaviour of %p is implementation-dependent in terms of case.
Ezio Melotti412c95a2010-02-16 23:31:04 +0000126 return _re_stripid.sub(r'\1', text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000127
Brett Cannonc6c1f472004-06-19 01:02:51 +0000128def _is_some_method(obj):
129 return inspect.ismethod(obj) or inspect.ismethoddescriptor(obj)
Tim Peters536d2262001-09-20 05:13:38 +0000130
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000131def allmethods(cl):
132 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000133 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000134 methods[key] = 1
135 for base in cl.__bases__:
136 methods.update(allmethods(base)) # all your base are belong to us
137 for key in methods.keys():
138 methods[key] = getattr(cl, key)
139 return methods
140
Tim Petersfa26f7c2001-09-24 08:05:11 +0000141def _split_list(s, predicate):
142 """Split sequence s via predicate, and return pair ([true], [false]).
143
144 The return value is a 2-tuple of lists,
145 ([x for x in s if predicate(x)],
146 [x for x in s if not predicate(x)])
147 """
148
Tim Peters28355492001-09-23 21:29:55 +0000149 yes = []
150 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000151 for x in s:
152 if predicate(x):
153 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000154 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000155 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000156 return yes, no
157
Skip Montanaroa5616d22004-06-11 04:46:12 +0000158def visiblename(name, all=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000159 """Decide whether to show documentation on a variable."""
160 # Certain special names are redundant.
Benjamin Peterson41181742008-07-02 20:22:54 +0000161 _hidden_names = ('__builtins__', '__doc__', '__file__', '__path__',
Barry Warsaw28a691b2010-04-17 00:19:56 +0000162 '__module__', '__name__', '__slots__', '__package__',
163 '__cached__')
Benjamin Peterson41181742008-07-02 20:22:54 +0000164 if name in _hidden_names: return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000165 # Private names are hidden, but special names are displayed.
166 if name.startswith('__') and name.endswith('__'): return 1
Skip Montanaroa5616d22004-06-11 04:46:12 +0000167 if all is not None:
168 # only document that which the programmer exported in __all__
169 return name in all
170 else:
171 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000172
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000173def classify_class_attrs(object):
174 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000175 results = []
176 for (name, kind, cls, value) in inspect.classify_class_attrs(object):
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000177 if inspect.isdatadescriptor(value):
178 kind = 'data descriptor'
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000179 results.append((name, kind, cls, value))
180 return results
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000181
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000182# ----------------------------------------------------- module manipulation
183
184def ispackage(path):
185 """Guess whether a path refers to a package directory."""
186 if os.path.isdir(path):
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000187 for ext in ('.py', '.pyc', '.pyo'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000188 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000189 return True
190 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000191
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000192def source_synopsis(file):
193 line = file.readline()
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000194 while line[:1] == '#' or not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000195 line = file.readline()
196 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000197 line = line.strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000198 if line[:4] == 'r"""': line = line[1:]
199 if line[:3] == '"""':
200 line = line[3:]
201 if line[-1:] == '\\': line = line[:-1]
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000202 while not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000203 line = file.readline()
204 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000205 result = line.split('"""')[0].strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000206 else: result = None
207 return result
208
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000209def synopsis(filename, cache={}):
210 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000211 mtime = os.stat(filename).st_mtime
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000212 lastupdate, result = cache.get(filename, (0, None))
213 if lastupdate < mtime:
214 info = inspect.getmoduleinfo(filename)
Georg Brandl26fd2e12006-03-08 09:34:53 +0000215 try:
216 file = open(filename)
217 except IOError:
218 # module can't be opened, so skip it
219 return None
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000220 if info and 'b' in info[2]: # binary modules have to be imported
221 try: module = imp.load_module('__temp__', file, filename, info[1:])
222 except: return None
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000223 result = (module.__doc__ or '').splitlines()[0]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000224 del sys.modules['__temp__']
225 else: # text modules can be directly examined
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000226 result = source_synopsis(file)
227 file.close()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000228 cache[filename] = (mtime, result)
229 return result
230
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000231class ErrorDuringImport(Exception):
232 """Errors that occurred while trying to import something to document it."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000233 def __init__(self, filename, exc_info):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000234 self.filename = filename
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000235 self.exc, self.value, self.tb = exc_info
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000236
237 def __str__(self):
Guido van Rossuma01a8b62007-05-27 09:20:14 +0000238 exc = self.exc.__name__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000239 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000240
241def importfile(path):
242 """Import a Python source file or compiled file given its path."""
243 magic = imp.get_magic()
244 file = open(path, 'r')
245 if file.read(len(magic)) == magic:
246 kind = imp.PY_COMPILED
247 else:
248 kind = imp.PY_SOURCE
249 file.close()
250 filename = os.path.basename(path)
251 name, ext = os.path.splitext(filename)
252 file = open(path, 'r')
253 try:
254 module = imp.load_module(name, file, path, (ext, 'r', kind))
255 except:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000256 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000257 file.close()
258 return module
259
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000260def safeimport(path, forceload=0, cache={}):
261 """Import a module; handle errors; return None if the module isn't found.
262
263 If the module *is* found but an exception occurs, it's wrapped in an
264 ErrorDuringImport exception and reraised. Unlike __import__, if a
265 package path is specified, the module at the end of the path is returned,
266 not the package at the beginning. If the optional 'forceload' argument
267 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000268 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000269 # If forceload is 1 and the module has been previously loaded from
270 # disk, we always have to reload the module. Checking the file's
271 # mtime isn't good enough (e.g. the module could contain a class
272 # that inherits from another module that has changed).
273 if forceload and path in sys.modules:
274 if path not in sys.builtin_module_names:
Guido van Rossume7ba4952007-06-06 23:52:48 +0000275 # Remove the module from sys.modules and re-import to try
276 # and avoid problems with partially loaded modules.
277 # Also remove any submodules because they won't appear
278 # in the newly loaded module's namespace if they're already
279 # in sys.modules.
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000280 subs = [m for m in sys.modules if m.startswith(path + '.')]
281 for key in [path] + subs:
282 # Prevent garbage collection.
283 cache[key] = sys.modules[key]
284 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000285 module = __import__(path)
286 except:
287 # Did the error occur before or after the module was found?
288 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000289 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000290 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000291 raise ErrorDuringImport(sys.modules[path].__file__, info)
292 elif exc is SyntaxError:
293 # A SyntaxError occurred before we could execute the module.
294 raise ErrorDuringImport(value.filename, info)
Benjamin Peterson0289b152009-06-28 17:22:03 +0000295 elif exc is ImportError and _extract_tb(tb)[-1][2]=='safeimport':
296 # The import error occurred directly in this function,
297 # which means there is no such module in the path.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000298 return None
299 else:
300 # Some other error occurred during the importing process.
301 raise ErrorDuringImport(path, sys.exc_info())
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000302 for part in path.split('.')[1:]:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000303 try: module = getattr(module, part)
304 except AttributeError: return None
305 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000306
307# ---------------------------------------------------- formatter base class
308
309class Doc:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000310 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000311 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000312 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000313 # 'try' clause is to attempt to handle the possibility that inspect
314 # identifies something in a way that pydoc itself has issues handling;
315 # think 'super' and how it is a descriptor (which raises the exception
316 # by lacking a __name__ attribute) and an instance.
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000317 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
318 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000319 try:
320 if inspect.ismodule(object): return self.docmodule(*args)
321 if inspect.isclass(object): return self.docclass(*args)
322 if inspect.isroutine(object): return self.docroutine(*args)
323 except AttributeError:
324 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000325 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000326 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000327
328 def fail(self, object, name=None, *args):
329 """Raise an exception for unimplemented types."""
330 message = "don't know how to document object%s of type %s" % (
331 name and ' ' + repr(name), type(object).__name__)
Collin Winterce36ad82007-08-30 01:19:48 +0000332 raise TypeError(message)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000333
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000334 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000335
Skip Montanaro4997a692003-09-10 16:47:51 +0000336 def getdocloc(self, object):
337 """Return the location of module docs or None"""
338
339 try:
340 file = inspect.getabsfile(object)
341 except TypeError:
342 file = '(built-in)'
343
344 docloc = os.environ.get("PYTHONDOCS",
Georg Brandl86def6c2008-01-21 20:36:10 +0000345 "http://docs.python.org/library")
Skip Montanaro4997a692003-09-10 16:47:51 +0000346 basedir = os.path.join(sys.exec_prefix, "lib",
347 "python"+sys.version[0:3])
348 if (isinstance(object, type(os)) and
349 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
350 'marshal', 'posix', 'signal', 'sys',
Georg Brandl2067bfd2008-05-25 13:05:15 +0000351 '_thread', 'zipimport') or
Skip Montanaro4997a692003-09-10 16:47:51 +0000352 (file.startswith(basedir) and
Brian Curtin49c284c2010-03-31 03:19:28 +0000353 not file.startswith(os.path.join(basedir, 'site-packages')))) and
Brian Curtinedef05b2010-04-01 04:05:25 +0000354 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
Skip Montanaro4997a692003-09-10 16:47:51 +0000355 if docloc.startswith("http://"):
Georg Brandl86def6c2008-01-21 20:36:10 +0000356 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
Skip Montanaro4997a692003-09-10 16:47:51 +0000357 else:
Georg Brandl86def6c2008-01-21 20:36:10 +0000358 docloc = os.path.join(docloc, object.__name__ + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000359 else:
360 docloc = None
361 return docloc
362
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000363# -------------------------------------------- HTML documentation generator
364
365class HTMLRepr(Repr):
366 """Class for safely making an HTML representation of a Python object."""
367 def __init__(self):
368 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000369 self.maxlist = self.maxtuple = 20
370 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000371 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000372
373 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000374 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000375
376 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000377 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000378
379 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000380 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000381 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000382 if hasattr(self, methodname):
383 return getattr(self, methodname)(x, level)
384 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000385
386 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000387 test = cram(x, self.maxstring)
388 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000389 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000390 # Backslashes are only literal in the string and are never
391 # needed to make any special characters, so show a raw string.
392 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000393 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000394 r'<font color="#c040c0">\1</font>',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000395 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000396
Skip Montanarodf708782002-03-07 22:58:02 +0000397 repr_str = repr_string
398
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000399 def repr_instance(self, x, level):
400 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000401 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000402 except:
403 return self.escape('<%s instance>' % x.__class__.__name__)
404
405 repr_unicode = repr_string
406
407class HTMLDoc(Doc):
408 """Formatter class for HTML documentation."""
409
410 # ------------------------------------------- HTML formatting utilities
411
412 _repr_instance = HTMLRepr()
413 repr = _repr_instance.repr
414 escape = _repr_instance.escape
415
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000416 def page(self, title, contents):
417 """Format an HTML page."""
Georg Brandl388faac2009-04-10 08:31:48 +0000418 return '''\
Georg Brandle6066942009-04-10 08:28:28 +0000419<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000420<html><head><title>Python: %s</title>
Georg Brandl388faac2009-04-10 08:31:48 +0000421<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000422</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000423%s
424</body></html>''' % (title, contents)
425
426 def heading(self, title, fgcol, bgcol, extras=''):
427 """Format a page heading."""
428 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000429<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000430<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000431<td valign=bottom>&nbsp;<br>
432<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000433><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000434><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000435 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
436
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000437 def section(self, title, fgcol, bgcol, contents, width=6,
438 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000439 """Format a section with a heading."""
440 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000441 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000442 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000443<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000444<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000445<td colspan=3 valign=bottom>&nbsp;<br>
446<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000447 ''' % (bgcol, fgcol, title)
448 if prelude:
449 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000450<tr bgcolor="%s"><td rowspan=2>%s</td>
451<td colspan=2>%s</td></tr>
452<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
453 else:
454 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000455<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000456
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000457 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000458
459 def bigsection(self, title, *args):
460 """Format a section with a big heading."""
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000461 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000462 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000463
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000464 def preformat(self, text):
465 """Format literal preformatted text."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000466 text = self.escape(text.expandtabs())
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000467 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
468 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000469
470 def multicolumn(self, list, format, cols=4):
471 """Format a list of items into a multi-column list."""
472 result = ''
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000473 rows = (len(list)+cols-1)//cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000474 for col in range(cols):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000475 result = result + '<td width="%d%%" valign=top>' % (100//cols)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000476 for i in range(rows*col, rows*col+rows):
477 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000478 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000479 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000480 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000481
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000482 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000483
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000484 def namelink(self, name, *dicts):
485 """Make a link for an identifier, given name-to-URL mappings."""
486 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000487 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000488 return '<a href="%s">%s</a>' % (dict[name], name)
489 return name
490
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000491 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000492 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000493 name, module = object.__name__, sys.modules.get(object.__module__)
494 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000495 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000496 module.__name__, name, classname(object, modname))
497 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000498
499 def modulelink(self, object):
500 """Make a link for a module."""
501 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
502
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000503 def modpkglink(self, modpkginfo):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000504 """Make a link for a module or package to display in an index."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000505 name, path, ispackage, shadowed = modpkginfo
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000506 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000507 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000508 if path:
509 url = '%s.%s.html' % (path, name)
510 else:
511 url = '%s.html' % name
512 if ispackage:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000513 text = '<strong>%s</strong>&nbsp;(package)' % name
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000514 else:
515 text = name
516 return '<a href="%s">%s</a>' % (url, text)
517
518 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
519 """Mark up some plain text, given a context of symbols to look for.
520 Each context dictionary maps object names to anchor names."""
521 escape = escape or self.escape
522 results = []
523 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000524 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
525 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000526 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000527 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000528 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000529 match = pattern.search(text, here)
530 if not match: break
531 start, end = match.span()
532 results.append(escape(text[here:start]))
533
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000534 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000535 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000536 url = escape(all).replace('"', '&quot;')
537 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000538 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000539 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
540 results.append('<a href="%s">%s</a>' % (url, escape(all)))
541 elif pep:
Christian Heimes2202f872008-02-06 14:31:34 +0000542 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000543 results.append('<a href="%s">%s</a>' % (url, escape(all)))
544 elif text[end:end+1] == '(':
545 results.append(self.namelink(name, methods, funcs, classes))
546 elif selfdot:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000547 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000548 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000549 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000550 here = end
551 results.append(escape(text[here:]))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000552 return ''.join(results)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000553
554 # ---------------------------------------------- type-specific routines
555
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000556 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000557 """Produce HTML for a class tree as given by inspect.getclasstree()."""
558 result = ''
559 for entry in tree:
560 if type(entry) is type(()):
561 c, bases = entry
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000562 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000563 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000564 if bases and bases != (parent,):
565 parents = []
566 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000567 parents.append(self.classlink(base, modname))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000568 result = result + '(' + ', '.join(parents) + ')'
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000569 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000570 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000571 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000572 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000573 return '<dl>\n%s</dl>\n' % result
574
Tim Peters8dd7ade2001-10-18 19:56:17 +0000575 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000576 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000577 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000578 try:
579 all = object.__all__
580 except AttributeError:
581 all = None
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000582 parts = name.split('.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000583 links = []
584 for i in range(len(parts)-1):
585 links.append(
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000586 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000587 ('.'.join(parts[:i+1]), parts[i]))
588 linkedname = '.'.join(links + parts[-1:])
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000589 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000590 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000591 path = inspect.getabsfile(object)
Ka-Ping Yee6191a232001-04-13 15:00:27 +0000592 url = path
593 if sys.platform == 'win32':
594 import nturl2path
595 url = nturl2path.pathname2url(path)
596 filelink = '<a href="file:%s">%s</a>' % (url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000597 except TypeError:
598 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000599 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000600 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000601 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000602 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000603 version = version[11:-1].strip()
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000604 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000605 if hasattr(object, '__date__'):
606 info.append(self.escape(str(object.__date__)))
607 if info:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000608 head = head + ' (%s)' % ', '.join(info)
Skip Montanaro4997a692003-09-10 16:47:51 +0000609 docloc = self.getdocloc(object)
610 if docloc is not None:
611 docloc = '<br><a href="%(docloc)s">Module Docs</a>' % locals()
612 else:
613 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000614 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000615 head, '#ffffff', '#7799ee',
616 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000617
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000618 modules = inspect.getmembers(object, inspect.ismodule)
619
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000620 classes, cdict = [], {}
621 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000622 # if __all__ exists, believe it. Otherwise use old heuristic.
623 if (all is not None or
624 (inspect.getmodule(value) or object) is object):
Skip Montanaroa5616d22004-06-11 04:46:12 +0000625 if visiblename(key, all):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000626 classes.append((key, value))
627 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000628 for key, value in classes:
629 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000630 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000631 module = sys.modules.get(modname)
632 if modname != name and module and hasattr(module, key):
633 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000634 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000635 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000636 funcs, fdict = [], {}
637 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000638 # if __all__ exists, believe it. Otherwise use old heuristic.
639 if (all is not None or
640 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Skip Montanaroa5616d22004-06-11 04:46:12 +0000641 if visiblename(key, all):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000642 funcs.append((key, value))
643 fdict[key] = '#-' + key
644 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000645 data = []
646 for key, value in inspect.getmembers(object, isdata):
Skip Montanaroa5616d22004-06-11 04:46:12 +0000647 if visiblename(key, all):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000648 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000649
650 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
651 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000652 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000653
654 if hasattr(object, '__path__'):
655 modpkgs = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000656 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
657 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000658 modpkgs.sort()
659 contents = self.multicolumn(modpkgs, self.modpkglink)
660 result = result + self.bigsection(
661 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000662 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000663 contents = self.multicolumn(
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000664 modules, lambda t: self.modulelink(t[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000665 result = result + self.bigsection(
Christian Heimes7131fd92008-02-19 14:21:46 +0000666 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000667
668 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000669 classlist = [value for (key, value) in classes]
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000670 contents = [
671 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000672 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000673 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000674 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000675 'Classes', '#ffffff', '#ee77aa', ' '.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000676 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000677 contents = []
678 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000679 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000680 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000681 'Functions', '#ffffff', '#eeaa77', ' '.join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000682 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000683 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000684 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000685 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000686 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000687 'Data', '#ffffff', '#55aa55', '<br>\n'.join(contents))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000688 if hasattr(object, '__author__'):
689 contents = self.markup(str(object.__author__), self.preformat)
690 result = result + self.bigsection(
691 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000692 if hasattr(object, '__credits__'):
693 contents = self.markup(str(object.__credits__), self.preformat)
694 result = result + self.bigsection(
695 'Credits', '#ffffff', '#7799ee', contents)
696
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000697 return result
698
Tim Peters8dd7ade2001-10-18 19:56:17 +0000699 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
700 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000701 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000702 realname = object.__name__
703 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000704 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000705
Tim Petersb47879b2001-09-24 04:47:19 +0000706 contents = []
707 push = contents.append
708
Tim Petersfa26f7c2001-09-24 08:05:11 +0000709 # Cute little class to pump out a horizontal rule between sections.
710 class HorizontalRule:
711 def __init__(self):
712 self.needone = 0
713 def maybe(self):
714 if self.needone:
715 push('<hr>\n')
716 self.needone = 1
717 hr = HorizontalRule()
718
Tim Petersc86f6ca2001-09-26 21:31:51 +0000719 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000720 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000721 if len(mro) > 2:
722 hr.maybe()
723 push('<dl><dt>Method resolution order:</dt>\n')
724 for base in mro:
725 push('<dd>%s</dd>\n' % self.classlink(base,
726 object.__module__))
727 push('</dl>\n')
728
Tim Petersb47879b2001-09-24 04:47:19 +0000729 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000730 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000731 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000732 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000733 push(msg)
734 for name, kind, homecls, value in ok:
735 push(self.document(getattr(object, name), name, mod,
736 funcs, classes, mdict, object))
737 push('\n')
738 return attrs
739
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000740 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000741 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000742 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000743 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000744 push(msg)
745 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000746 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000747 return attrs
748
Tim Petersfa26f7c2001-09-24 08:05:11 +0000749 def spilldata(msg, attrs, predicate):
750 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000751 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000752 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000753 push(msg)
754 for name, kind, homecls, value in ok:
755 base = self.docother(getattr(object, name), name, mod)
Guido van Rossumd59da4b2007-05-22 18:11:13 +0000756 if hasattr(value, '__call__') or inspect.isdatadescriptor(value):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000757 doc = getattr(value, "__doc__", None)
758 else:
759 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000760 if doc is None:
761 push('<dl><dt>%s</dl>\n' % base)
762 else:
763 doc = self.markup(getdoc(value), self.preformat,
764 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000765 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000766 push('<dl><dt>%s%s</dl>\n' % (base, doc))
767 push('\n')
768 return attrs
769
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000770 attrs = [(name, kind, cls, value)
771 for name, kind, cls, value in classify_class_attrs(object)
772 if visiblename(name)]
773
Tim Petersb47879b2001-09-24 04:47:19 +0000774 mdict = {}
775 for key, kind, homecls, value in attrs:
776 mdict[key] = anchor = '#' + name + '-' + key
777 value = getattr(object, key)
778 try:
779 # The value may not be hashable (e.g., a data attr with
780 # a dict or list value).
781 mdict[value] = anchor
782 except TypeError:
783 pass
784
Tim Petersfa26f7c2001-09-24 08:05:11 +0000785 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000786 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000787 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000788 else:
789 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000790 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
791
Georg Brandl1a3284e2007-12-02 09:40:06 +0000792 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000793 attrs = inherited
794 continue
795 elif thisclass is object:
796 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000797 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000798 tag = 'inherited from %s' % self.classlink(thisclass,
799 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000800 tag += ':<br>\n'
801
802 # Sort attrs by name.
Raymond Hettingerd4cb56d2008-01-30 02:55:10 +0000803 attrs.sort(key=lambda t: t[0])
Tim Petersb47879b2001-09-24 04:47:19 +0000804
805 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000806 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000807 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000808 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000809 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000810 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000811 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000812 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
813 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000814 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000815 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000816 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000817 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000818
819 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000820
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000821 if name == realname:
822 title = '<a name="%s">class <strong>%s</strong></a>' % (
823 name, realname)
824 else:
825 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
826 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000827 if bases:
828 parents = []
829 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000830 parents.append(self.classlink(base, object.__module__))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000831 title = title + '(%s)' % ', '.join(parents)
Tim Peters2306d242001-09-25 03:18:32 +0000832 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000833 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000834
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000835 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000836
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000837 def formatvalue(self, object):
838 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000839 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000840
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000841 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000842 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000843 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000844 realname = object.__name__
845 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000846 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000847 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000848 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000849 if inspect.ismethod(object):
Christian Heimesff737952007-11-27 10:40:20 +0000850 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000851 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000852 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000853 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000854 else:
Christian Heimesff737952007-11-27 10:40:20 +0000855 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000856 note = ' method of %s instance' % self.classlink(
Christian Heimesff737952007-11-27 10:40:20 +0000857 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000858 else:
859 note = ' unbound %s method' % self.classlink(imclass,mod)
Christian Heimesff737952007-11-27 10:40:20 +0000860 object = object.__func__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000861
862 if name == realname:
863 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
864 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000865 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000866 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000867 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000868 cl.__name__ + '-' + realname, realname)
869 skipdocs = 1
870 else:
871 reallink = realname
872 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
873 anchor, name, reallink)
Tim Peters4bcfa312001-09-20 06:08:24 +0000874 if inspect.isfunction(object):
Guido van Rossum2e65f892007-02-28 22:03:49 +0000875 args, varargs, kwonlyargs, kwdefaults, varkw, defaults, ann = \
876 inspect.getfullargspec(object)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000877 argspec = inspect.formatargspec(
Guido van Rossum2e65f892007-02-28 22:03:49 +0000878 args, varargs, kwonlyargs, kwdefaults, varkw, defaults, ann,
879 formatvalue=self.formatvalue,
880 formatannotation=inspect.formatannotationrelativeto(object))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000881 if realname == '<lambda>':
Tim Peters59ed4482001-10-31 04:20:26 +0000882 title = '<strong>%s</strong> <em>lambda</em> ' % name
Guido van Rossum2e65f892007-02-28 22:03:49 +0000883 # XXX lambda's won't usually have func_annotations['return']
884 # since the syntax doesn't support but it is possible.
885 # So removing parentheses isn't truly safe.
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000886 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +0000887 else:
888 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000889
Tim Peters2306d242001-09-25 03:18:32 +0000890 decl = title + argspec + (note and self.grey(
891 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000892
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000893 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000894 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000895 else:
896 doc = self.markup(
897 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000898 doc = doc and '<dd><tt>%s</tt></dd>' % doc
899 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000900
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000901 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000902 results = []
903 push = results.append
904
905 if name:
906 push('<dl><dt><strong>%s</strong></dt>\n' % name)
907 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000908 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000909 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000910 push('</dl>\n')
911
912 return ''.join(results)
913
914 def docproperty(self, object, name=None, mod=None, cl=None):
915 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000916 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000917
Tim Peters8dd7ade2001-10-18 19:56:17 +0000918 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000919 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000920 lhs = name and '<strong>%s</strong> = ' % name or ''
921 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000922
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000923 def docdata(self, object, name=None, mod=None, cl=None):
924 """Produce html documentation for a data descriptor."""
925 return self._docdescriptor(name, object, mod)
926
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000927 def index(self, dir, shadowed=None):
928 """Generate an HTML index for a directory of modules."""
929 modpkgs = []
930 if shadowed is None: shadowed = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000931 for importer, name, ispkg in pkgutil.iter_modules([dir]):
932 modpkgs.append((name, '', ispkg, name in shadowed))
933 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000934
935 modpkgs.sort()
936 contents = self.multicolumn(modpkgs, self.modpkglink)
937 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
938
939# -------------------------------------------- text documentation generator
940
941class TextRepr(Repr):
942 """Class for safely making a text representation of a Python object."""
943 def __init__(self):
944 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000945 self.maxlist = self.maxtuple = 20
946 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000947 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000948
949 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000950 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000951 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000952 if hasattr(self, methodname):
953 return getattr(self, methodname)(x, level)
954 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000955
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000956 def repr_string(self, x, level):
957 test = cram(x, self.maxstring)
958 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000959 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000960 # Backslashes are only literal in the string and are never
961 # needed to make any special characters, so show a raw string.
962 return 'r' + testrepr[0] + test + testrepr[0]
963 return testrepr
964
Skip Montanarodf708782002-03-07 22:58:02 +0000965 repr_str = repr_string
966
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000967 def repr_instance(self, x, level):
968 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000969 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000970 except:
971 return '<%s instance>' % x.__class__.__name__
972
973class TextDoc(Doc):
974 """Formatter class for text documentation."""
975
976 # ------------------------------------------- text formatting utilities
977
978 _repr_instance = TextRepr()
979 repr = _repr_instance.repr
980
981 def bold(self, text):
982 """Format a string in bold by overstriking."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000983 return ''.join(map(lambda ch: ch + '\b' + ch, text))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000984
985 def indent(self, text, prefix=' '):
986 """Indent text by prepending a given prefix to each line."""
987 if not text: return ''
Collin Winter72e110c2007-07-17 00:27:30 +0000988 lines = [prefix + line for line in text.split('\n')]
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000989 if lines: lines[-1] = lines[-1].rstrip()
990 return '\n'.join(lines)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000991
992 def section(self, title, contents):
993 """Format a section with a given heading."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000994 clean_contents = self.indent(contents).rstrip()
995 return self.bold(title) + '\n' + clean_contents + '\n\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000996
997 # ---------------------------------------------- type-specific routines
998
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000999 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001000 """Render in text a class tree as returned by inspect.getclasstree()."""
1001 result = ''
1002 for entry in tree:
1003 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001004 c, bases = entry
1005 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001006 if bases and bases != (parent,):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001007 parents = map(lambda c, m=modname: classname(c, m), bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001008 result = result + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001009 result = result + '\n'
1010 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001011 result = result + self.formattree(
1012 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001013 return result
1014
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001015 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001016 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001017 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001018 synop, desc = splitdoc(getdoc(object))
1019 result = self.section('NAME', name + (synop and ' - ' + synop))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001020
1021 try:
Skip Montanaroa5616d22004-06-11 04:46:12 +00001022 all = object.__all__
1023 except AttributeError:
1024 all = None
1025
1026 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001027 file = inspect.getabsfile(object)
1028 except TypeError:
1029 file = '(built-in)'
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001030 result = result + self.section('FILE', file)
Skip Montanaro4997a692003-09-10 16:47:51 +00001031
1032 docloc = self.getdocloc(object)
1033 if docloc is not None:
1034 result = result + self.section('MODULE DOCS', docloc)
1035
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001036 if desc:
1037 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001038
1039 classes = []
1040 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001041 # if __all__ exists, believe it. Otherwise use old heuristic.
1042 if (all is not None
1043 or (inspect.getmodule(value) or object) is object):
Skip Montanaroa5616d22004-06-11 04:46:12 +00001044 if visiblename(key, all):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001045 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001046 funcs = []
1047 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001048 # if __all__ exists, believe it. Otherwise use old heuristic.
1049 if (all is not None or
1050 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Skip Montanaroa5616d22004-06-11 04:46:12 +00001051 if visiblename(key, all):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001052 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001053 data = []
1054 for key, value in inspect.getmembers(object, isdata):
Skip Montanaroa5616d22004-06-11 04:46:12 +00001055 if visiblename(key, all):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001056 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001057
Christian Heimes1af737c2008-01-23 08:24:23 +00001058 modpkgs = []
1059 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001060 if hasattr(object, '__path__'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001061 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Christian Heimes1af737c2008-01-23 08:24:23 +00001062 modpkgs_names.add(modname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001063 if ispkg:
1064 modpkgs.append(modname + ' (package)')
1065 else:
1066 modpkgs.append(modname)
1067
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001068 modpkgs.sort()
1069 result = result + self.section(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001070 'PACKAGE CONTENTS', '\n'.join(modpkgs))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001071
Christian Heimes1af737c2008-01-23 08:24:23 +00001072 # Detect submodules as sometimes created by C extensions
1073 submodules = []
1074 for key, value in inspect.getmembers(object, inspect.ismodule):
1075 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1076 submodules.append(key)
1077 if submodules:
1078 submodules.sort()
1079 result = result + self.section(
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001080 'SUBMODULES', '\n'.join(submodules))
Christian Heimes1af737c2008-01-23 08:24:23 +00001081
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001082 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001083 classlist = [value for key, value in classes]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001084 contents = [self.formattree(
1085 inspect.getclasstree(classlist, 1), name)]
1086 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001087 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001088 result = result + self.section('CLASSES', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001089
1090 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001091 contents = []
1092 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001093 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001094 result = result + self.section('FUNCTIONS', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001095
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001096 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001097 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001098 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001099 contents.append(self.docother(value, key, name, maxlen=70))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001100 result = result + self.section('DATA', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001101
1102 if hasattr(object, '__version__'):
1103 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001104 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001105 version = version[11:-1].strip()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001106 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001107 if hasattr(object, '__date__'):
1108 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001109 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001110 result = result + self.section('AUTHOR', str(object.__author__))
1111 if hasattr(object, '__credits__'):
1112 result = result + self.section('CREDITS', str(object.__credits__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001113 return result
1114
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001115 def docclass(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001116 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001117 realname = object.__name__
1118 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001119 bases = object.__bases__
1120
Tim Petersc86f6ca2001-09-26 21:31:51 +00001121 def makename(c, m=object.__module__):
1122 return classname(c, m)
1123
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001124 if name == realname:
1125 title = 'class ' + self.bold(realname)
1126 else:
1127 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001128 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001129 parents = map(makename, bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001130 title = title + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001131
1132 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001133 contents = doc and [doc + '\n'] or []
1134 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001135
Tim Petersc86f6ca2001-09-26 21:31:51 +00001136 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001137 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001138 if len(mro) > 2:
1139 push("Method resolution order:")
1140 for base in mro:
1141 push(' ' + makename(base))
1142 push('')
1143
Tim Petersf4aad8e2001-09-24 22:40:47 +00001144 # Cute little class to pump out a horizontal rule between sections.
1145 class HorizontalRule:
1146 def __init__(self):
1147 self.needone = 0
1148 def maybe(self):
1149 if self.needone:
1150 push('-' * 70)
1151 self.needone = 1
1152 hr = HorizontalRule()
1153
Tim Peters28355492001-09-23 21:29:55 +00001154 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001155 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001156 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001157 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001158 push(msg)
1159 for name, kind, homecls, value in ok:
1160 push(self.document(getattr(object, name),
1161 name, mod, object))
1162 return attrs
1163
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001164 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001165 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001166 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001167 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001168 push(msg)
1169 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001170 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001171 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001172
Tim Petersfa26f7c2001-09-24 08:05:11 +00001173 def spilldata(msg, attrs, predicate):
1174 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001175 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001176 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001177 push(msg)
1178 for name, kind, homecls, value in ok:
Guido van Rossumd59da4b2007-05-22 18:11:13 +00001179 if hasattr(value, '__call__') or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001180 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001181 else:
1182 doc = None
Tim Peters28355492001-09-23 21:29:55 +00001183 push(self.docother(getattr(object, name),
Georg Brandl8b813db2005-10-01 16:32:31 +00001184 name, mod, maxlen=70, doc=doc) + '\n')
Tim Peters28355492001-09-23 21:29:55 +00001185 return attrs
1186
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001187 attrs = [(name, kind, cls, value)
1188 for name, kind, cls, value in classify_class_attrs(object)
1189 if visiblename(name)]
1190
Tim Petersfa26f7c2001-09-24 08:05:11 +00001191 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001192 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001193 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001194 else:
1195 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001196 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1197
Georg Brandl1a3284e2007-12-02 09:40:06 +00001198 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001199 attrs = inherited
1200 continue
1201 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001202 tag = "defined here"
1203 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001204 tag = "inherited from %s" % classname(thisclass,
1205 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001206
1207 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001208 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001209
1210 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001211 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001212 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001213 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001214 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001215 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001216 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001217 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1218 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001219 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1220 lambda t: t[1] == 'data')
Tim Peters28355492001-09-23 21:29:55 +00001221 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001222 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001223
1224 contents = '\n'.join(contents)
1225 if not contents:
1226 return title + '\n'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001227 return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001228
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001229 def formatvalue(self, object):
1230 """Format an argument default value as text."""
1231 return '=' + self.repr(object)
1232
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001233 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001234 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001235 realname = object.__name__
1236 name = name or realname
1237 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001238 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001239 if inspect.ismethod(object):
Christian Heimesff737952007-11-27 10:40:20 +00001240 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001241 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001242 if imclass is not cl:
1243 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001244 else:
Christian Heimesff737952007-11-27 10:40:20 +00001245 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001246 note = ' method of %s instance' % classname(
Christian Heimesff737952007-11-27 10:40:20 +00001247 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001248 else:
1249 note = ' unbound %s method' % classname(imclass,mod)
Christian Heimesff737952007-11-27 10:40:20 +00001250 object = object.__func__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001251
1252 if name == realname:
1253 title = self.bold(realname)
1254 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001255 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001256 cl.__dict__[realname] is object):
1257 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001258 title = self.bold(name) + ' = ' + realname
Tim Peters4bcfa312001-09-20 06:08:24 +00001259 if inspect.isfunction(object):
Guido van Rossum2e65f892007-02-28 22:03:49 +00001260 args, varargs, varkw, defaults, kwonlyargs, kwdefaults, ann = \
1261 inspect.getfullargspec(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001262 argspec = inspect.formatargspec(
Guido van Rossum2e65f892007-02-28 22:03:49 +00001263 args, varargs, varkw, defaults, kwonlyargs, kwdefaults, ann,
1264 formatvalue=self.formatvalue,
1265 formatannotation=inspect.formatannotationrelativeto(object))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001266 if realname == '<lambda>':
Georg Brandl501dd0d2006-02-17 09:45:40 +00001267 title = self.bold(name) + ' lambda '
Guido van Rossum2e65f892007-02-28 22:03:49 +00001268 # XXX lambda's won't usually have func_annotations['return']
1269 # since the syntax doesn't support but it is possible.
1270 # So removing parentheses isn't truly safe.
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001271 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +00001272 else:
1273 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001274 decl = title + argspec + note
1275
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001276 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001277 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001278 else:
1279 doc = getdoc(object) or ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001280 return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001281
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001282 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001283 results = []
1284 push = results.append
1285
1286 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001287 push(self.bold(name))
1288 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001289 doc = getdoc(value) or ''
1290 if doc:
1291 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001292 push('\n')
1293 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001294
1295 def docproperty(self, object, name=None, mod=None, cl=None):
1296 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001297 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001298
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001299 def docdata(self, object, name=None, mod=None, cl=None):
1300 """Produce text documentation for a data descriptor."""
1301 return self._docdescriptor(name, object, mod)
1302
Georg Brandl8b813db2005-10-01 16:32:31 +00001303 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001304 """Produce text documentation for a data object."""
1305 repr = self.repr(object)
1306 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001307 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001308 chop = maxlen - len(line)
1309 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001310 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001311 if doc is not None:
1312 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001313 return line
1314
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001315# --------------------------------------------------------- user interfaces
1316
1317def pager(text):
1318 """The first time this is called, determine what kind of pager to use."""
1319 global pager
1320 pager = getpager()
1321 pager(text)
1322
1323def getpager():
1324 """Decide what method to use for paging through text."""
Guido van Rossuma01a8b62007-05-27 09:20:14 +00001325 if not hasattr(sys.stdout, "isatty"):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001326 return plainpager
1327 if not sys.stdin.isatty() or not sys.stdout.isatty():
1328 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001329 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001330 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001331 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001332 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001333 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001334 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001335 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001336 if os.environ.get('TERM') in ('dumb', 'emacs'):
1337 return plainpager
Andrew MacIntyre54e0eab2002-03-03 03:12:30 +00001338 if sys.platform == 'win32' or sys.platform.startswith('os2'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001339 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001340 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001341 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001342
1343 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001344 (fd, filename) = tempfile.mkstemp()
1345 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001346 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001347 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001348 return lambda text: pipepager(text, 'more')
1349 else:
1350 return ttypager
1351 finally:
1352 os.unlink(filename)
1353
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001354def plain(text):
1355 """Remove boldface formatting from text."""
1356 return re.sub('.\b', '', text)
1357
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001358def pipepager(text, cmd):
1359 """Page through text by feeding it to another program."""
1360 pipe = os.popen(cmd, 'w')
1361 try:
1362 pipe.write(text)
1363 pipe.close()
1364 except IOError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001365 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001366
1367def tempfilepager(text, cmd):
1368 """Page through text by invoking a program on a temporary file."""
1369 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001370 filename = tempfile.mktemp()
1371 file = open(filename, 'w')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001372 file.write(text)
1373 file.close()
1374 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001375 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001376 finally:
1377 os.unlink(filename)
1378
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001379def ttypager(text):
1380 """Page through text on a text terminal."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001381 lines = plain(text).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001382 try:
1383 import tty
1384 fd = sys.stdin.fileno()
1385 old = tty.tcgetattr(fd)
1386 tty.setcbreak(fd)
1387 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001388 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001389 tty = None
1390 getchar = lambda: sys.stdin.readline()[:-1][:1]
1391
1392 try:
1393 r = inc = os.environ.get('LINES', 25) - 1
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001394 sys.stdout.write('\n'.join(lines[:inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001395 while lines[r:]:
1396 sys.stdout.write('-- more --')
1397 sys.stdout.flush()
1398 c = getchar()
1399
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001400 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001401 sys.stdout.write('\r \r')
1402 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001403 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001404 sys.stdout.write('\r \r' + lines[r] + '\n')
1405 r = r + 1
1406 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001407 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001408 r = r - inc - inc
1409 if r < 0: r = 0
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001410 sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001411 r = r + inc
1412
1413 finally:
1414 if tty:
1415 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1416
1417def plainpager(text):
1418 """Simply print unformatted text. This is the ultimate fallback."""
1419 sys.stdout.write(plain(text))
1420
1421def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001422 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001423 if inspect.ismodule(thing):
1424 if thing.__name__ in sys.builtin_module_names:
1425 return 'built-in module ' + thing.__name__
1426 if hasattr(thing, '__path__'):
1427 return 'package ' + thing.__name__
1428 else:
1429 return 'module ' + thing.__name__
1430 if inspect.isbuiltin(thing):
1431 return 'built-in function ' + thing.__name__
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001432 if inspect.isgetsetdescriptor(thing):
1433 return 'getset descriptor %s.%s.%s' % (
1434 thing.__objclass__.__module__, thing.__objclass__.__name__,
1435 thing.__name__)
1436 if inspect.ismemberdescriptor(thing):
1437 return 'member descriptor %s.%s.%s' % (
1438 thing.__objclass__.__module__, thing.__objclass__.__name__,
1439 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001440 if inspect.isclass(thing):
1441 return 'class ' + thing.__name__
1442 if inspect.isfunction(thing):
1443 return 'function ' + thing.__name__
1444 if inspect.ismethod(thing):
1445 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001446 return type(thing).__name__
1447
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001448def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001449 """Locate an object by name or dotted path, importing as necessary."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001450 parts = [part for part in path.split('.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001451 module, n = None, 0
1452 while n < len(parts):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001453 nextmodule = safeimport('.'.join(parts[:n+1]), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001454 if nextmodule: module, n = nextmodule, n + 1
1455 else: break
1456 if module:
1457 object = module
1458 for part in parts[n:]:
1459 try: object = getattr(object, part)
1460 except AttributeError: return None
1461 return object
1462 else:
Georg Brandl1a3284e2007-12-02 09:40:06 +00001463 if hasattr(builtins, path):
1464 return getattr(builtins, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001465
1466# --------------------------------------- interactive interpreter interface
1467
1468text = TextDoc()
1469html = HTMLDoc()
1470
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001471def resolve(thing, forceload=0):
1472 """Given an object or a path to an object, get the object and its name."""
1473 if isinstance(thing, str):
1474 object = locate(thing, forceload)
1475 if not object:
Collin Winterce36ad82007-08-30 01:19:48 +00001476 raise ImportError('no Python documentation found for %r' % thing)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001477 return object, thing
1478 else:
1479 return thing, getattr(thing, '__name__', None)
1480
Guido van Rossumd8faa362007-04-27 19:54:29 +00001481def render_doc(thing, title='Python Library Documentation: %s', forceload=0):
1482 """Render text documentation, given an object or a path to an object."""
1483 object, name = resolve(thing, forceload)
1484 desc = describe(object)
1485 module = inspect.getmodule(object)
1486 if name and '.' in name:
1487 desc += ' in ' + name[:name.rfind('.')]
1488 elif module and module is not object:
1489 desc += ' in module ' + module.__name__
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001490
1491 if not (inspect.ismodule(object) or
Guido van Rossumd8faa362007-04-27 19:54:29 +00001492 inspect.isclass(object) or
1493 inspect.isroutine(object) or
1494 inspect.isgetsetdescriptor(object) or
1495 inspect.ismemberdescriptor(object) or
1496 isinstance(object, property)):
1497 # If the passed object is a piece of data or an instance,
1498 # document its available methods instead of its value.
1499 object = type(object)
1500 desc += ' object'
1501 return title % desc + '\n\n' + text.document(object, name)
1502
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001503def doc(thing, title='Python Library Documentation: %s', forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001504 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001505 try:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001506 pager(render_doc(thing, title, forceload))
Guido van Rossumb940e112007-01-10 16:19:56 +00001507 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001508 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001509
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001510def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001511 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001512 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001513 object, name = resolve(thing, forceload)
1514 page = html.page(describe(object), html.document(object, name))
Georg Brandl388faac2009-04-10 08:31:48 +00001515 file = open(name + '.html', 'w', encoding='utf-8')
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001516 file.write(page)
1517 file.close()
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001518 print('wrote', name + '.html')
Guido van Rossumb940e112007-01-10 16:19:56 +00001519 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001520 print(value)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001521
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001522def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001523 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001524 if done is None: done = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001525 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1526 writedoc(modname)
1527 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001528
1529class Helper:
Georg Brandl6b38daa2008-06-01 21:05:17 +00001530
1531 # These dictionaries map a topic name to either an alias, or a tuple
1532 # (label, seealso-items). The "label" is the label of the corresponding
1533 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl5617db82009-04-27 16:28:57 +00001534 # in pydoc_data/topics.py.
Georg Brandl6b38daa2008-06-01 21:05:17 +00001535 #
1536 # CAUTION: if you change one of these dictionaries, be sure to adapt the
1537 # list of needed labels in Doc/tools/sphinxext/pyspecific.py and
Georg Brandl5617db82009-04-27 16:28:57 +00001538 # regenerate the pydoc_data/topics.py file by running
Georg Brandl6b38daa2008-06-01 21:05:17 +00001539 # make pydoc-topics
1540 # in Doc/ and copying the output file into the Lib/ directory.
1541
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001542 keywords = {
1543 'and': 'BOOLEAN',
Guido van Rossumd8faa362007-04-27 19:54:29 +00001544 'as': 'with',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001545 'assert': ('assert', ''),
1546 'break': ('break', 'while for'),
1547 'class': ('class', 'CLASSES SPECIALMETHODS'),
1548 'continue': ('continue', 'while for'),
1549 'def': ('function', ''),
1550 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001551 'elif': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001552 'else': ('else', 'while for'),
Georg Brandl0d855392008-08-30 19:53:05 +00001553 'except': 'try',
1554 'finally': 'try',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001555 'for': ('for', 'break continue while'),
Georg Brandl0d855392008-08-30 19:53:05 +00001556 'from': 'import',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001557 'global': ('global', 'NAMESPACES'),
1558 'if': ('if', 'TRUTHVALUE'),
1559 'import': ('import', 'MODULES'),
Georg Brandl395ed242009-09-04 08:07:32 +00001560 'in': ('in', 'SEQUENCEMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001561 'is': 'COMPARISON',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001562 'lambda': ('lambda', 'FUNCTIONS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001563 'not': 'BOOLEAN',
1564 'or': 'BOOLEAN',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001565 'pass': ('pass', ''),
1566 'raise': ('raise', 'EXCEPTIONS'),
1567 'return': ('return', 'FUNCTIONS'),
1568 'try': ('try', 'EXCEPTIONS'),
1569 'while': ('while', 'break continue if TRUTHVALUE'),
1570 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1571 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001572 }
Georg Brandldb7b6b92009-01-01 15:53:14 +00001573 # Either add symbols to this dictionary or to the symbols dictionary
1574 # directly: Whichever is easier. They are merged later.
1575 _symbols_inverse = {
1576 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'),
1577 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1578 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1579 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1580 'UNARY' : ('-', '~'),
1581 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1582 '^=', '<<=', '>>=', '**=', '//='),
1583 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1584 'COMPLEX' : ('j', 'J')
1585 }
1586 symbols = {
1587 '%': 'OPERATORS FORMATTING',
1588 '**': 'POWER',
1589 ',': 'TUPLES LISTS FUNCTIONS',
1590 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1591 '...': 'ELLIPSIS',
1592 ':': 'SLICINGS DICTIONARYLITERALS',
1593 '@': 'def class',
1594 '\\': 'STRINGS',
1595 '_': 'PRIVATENAMES',
1596 '__': 'PRIVATENAMES SPECIALMETHODS',
1597 '`': 'BACKQUOTES',
1598 '(': 'TUPLES FUNCTIONS CALLS',
1599 ')': 'TUPLES FUNCTIONS CALLS',
1600 '[': 'LISTS SUBSCRIPTS SLICINGS',
1601 ']': 'LISTS SUBSCRIPTS SLICINGS'
1602 }
1603 for topic, symbols_ in _symbols_inverse.items():
1604 for symbol in symbols_:
1605 topics = symbols.get(symbol, topic)
1606 if topic not in topics:
1607 topics = topics + ' ' + topic
1608 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001609
1610 topics = {
Georg Brandl6b38daa2008-06-01 21:05:17 +00001611 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1612 'FUNCTIONS CLASSES MODULES FILES inspect'),
1613 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS '
1614 'FORMATTING TYPES'),
1615 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1616 'FORMATTING': ('formatstrings', 'OPERATORS'),
1617 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1618 'FORMATTING TYPES'),
1619 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1620 'INTEGER': ('integers', 'int range'),
1621 'FLOAT': ('floating', 'float math'),
1622 'COMPLEX': ('imaginary', 'complex cmath'),
1623 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING range LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001624 'MAPPINGS': 'DICTIONARIES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001625 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1626 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1627 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1628 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001629 'FRAMEOBJECTS': 'TYPES',
1630 'TRACEBACKS': 'TYPES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001631 'NONE': ('bltin-null-object', ''),
1632 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
1633 'FILES': ('bltin-file-objects', ''),
1634 'SPECIALATTRIBUTES': ('specialattrs', ''),
1635 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1636 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001637 'PACKAGES': 'import',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001638 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1639 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1640 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1641 'LISTS DICTIONARIES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001642 'OPERATORS': 'EXPRESSIONS',
1643 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001644 'OBJECTS': ('objects', 'TYPES'),
1645 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
Georg Brandl395ed242009-09-04 08:07:32 +00001646 'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS '
1647 'NUMBERMETHODS CLASSES'),
Mark Dickinsona56c4672009-01-27 18:17:45 +00001648 'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001649 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1650 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001651 'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS '
Georg Brandl6b38daa2008-06-01 21:05:17 +00001652 'SPECIALMETHODS'),
1653 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1654 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1655 'SPECIALMETHODS'),
1656 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
1657 'NAMESPACES': ('naming', 'global ASSIGNMENT DELETION DYNAMICFEATURES'),
1658 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001659 'SCOPING': 'NAMESPACES',
1660 'FRAMES': 'NAMESPACES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001661 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1662 'CONVERSIONS': ('conversions', ''),
1663 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1664 'SPECIALIDENTIFIERS': ('id-classes', ''),
1665 'PRIVATENAMES': ('atom-identifiers', ''),
1666 'LITERALS': ('atom-literals', 'STRINGS NUMBERS TUPLELITERALS '
1667 'LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001668 'TUPLES': 'SEQUENCES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001669 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1670 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1671 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1672 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1673 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1674 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001675 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'),
1676 'SLICINGS': ('slicings', 'SEQUENCEMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001677 'CALLS': ('calls', 'EXPRESSIONS'),
1678 'POWER': ('power', 'EXPRESSIONS'),
1679 'UNARY': ('unary', 'EXPRESSIONS'),
1680 'BINARY': ('binary', 'EXPRESSIONS'),
1681 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1682 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1683 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1684 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001685 'ASSERTION': 'assert',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001686 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1687 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001688 'DELETION': 'del',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001689 'RETURNING': 'return',
1690 'IMPORTING': 'import',
1691 'CONDITIONAL': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001692 'LOOPING': ('compound', 'for while break continue'),
1693 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1694 'DEBUGGING': ('debugger', 'pdb'),
1695 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001696 }
1697
1698 def __init__(self, input, output):
1699 self.input = input
1700 self.output = output
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001701
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001702 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001703 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001704 self()
1705 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001706 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001707
Alexander Belopolsky2e733c92010-07-04 17:00:20 +00001708 _GoInteractive = object()
1709 def __call__(self, request=_GoInteractive):
1710 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001711 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001712 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001713 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001714 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001715 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001716You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001717If you want to ask for help on a particular object directly from the
1718interpreter, you can type "help(object)". Executing "help('string')"
1719has the same effect as typing a particular string at the help> prompt.
1720''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001721
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001722 def interact(self):
1723 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001724 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001725 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001726 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001727 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001728 except (KeyboardInterrupt, EOFError):
1729 break
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001730 request = replace(request, '"', '', "'", '').strip()
1731 if request.lower() in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001732 self.help(request)
1733
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001734 def getline(self, prompt):
Guido van Rossum7c086c02008-01-02 03:52:38 +00001735 """Read one line, using input() when appropriate."""
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001736 if self.input is sys.stdin:
Guido van Rossum7c086c02008-01-02 03:52:38 +00001737 return input(prompt)
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001738 else:
1739 self.output.write(prompt)
1740 self.output.flush()
1741 return self.input.readline()
1742
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001743 def help(self, request):
1744 if type(request) is type(''):
R. David Murray1f1b9d32009-05-27 20:56:59 +00001745 request = request.strip()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001746 if request == 'help': self.intro()
1747 elif request == 'keywords': self.listkeywords()
Georg Brandldb7b6b92009-01-01 15:53:14 +00001748 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001749 elif request == 'topics': self.listtopics()
1750 elif request == 'modules': self.listmodules()
1751 elif request[:8] == 'modules ':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001752 self.listmodules(request.split()[1])
Georg Brandldb7b6b92009-01-01 15:53:14 +00001753 elif request in self.symbols: self.showsymbol(request)
Raymond Hettinger54f02222002-06-01 14:18:47 +00001754 elif request in self.keywords: self.showtopic(request)
1755 elif request in self.topics: self.showtopic(request)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001756 elif request: doc(request, 'Help on %s:')
1757 elif isinstance(request, Helper): self()
1758 else: doc(request, 'Help on %s:')
1759 self.output.write('\n')
1760
1761 def intro(self):
1762 self.output.write('''
1763Welcome to Python %s! This is the online help utility.
1764
1765If this is your first time using Python, you should definitely check out
Georg Brandl86def6c2008-01-21 20:36:10 +00001766the tutorial on the Internet at http://docs.python.org/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001767
1768Enter the name of any module, keyword, or topic to get help on writing
1769Python programs and using Python modules. To quit this help utility and
1770return to the interpreter, just type "quit".
1771
1772To get a list of available modules, keywords, or topics, type "modules",
1773"keywords", or "topics". Each module also comes with a one-line summary
1774of what it does; to list the modules whose summaries contain a given word
1775such as "spam", type "modules spam".
1776''' % sys.version[:3])
1777
1778 def list(self, items, columns=4, width=80):
Guido van Rossum486364b2007-06-30 05:01:58 +00001779 items = list(sorted(items))
1780 colw = width // columns
1781 rows = (len(items) + columns - 1) // columns
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001782 for row in range(rows):
1783 for col in range(columns):
1784 i = col * rows + row
1785 if i < len(items):
1786 self.output.write(items[i])
1787 if col < columns - 1:
Guido van Rossum486364b2007-06-30 05:01:58 +00001788 self.output.write(' ' + ' ' * (colw - 1 - len(items[i])))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001789 self.output.write('\n')
1790
1791 def listkeywords(self):
1792 self.output.write('''
1793Here is a list of the Python keywords. Enter any keyword to get more help.
1794
1795''')
1796 self.list(self.keywords.keys())
1797
Georg Brandldb7b6b92009-01-01 15:53:14 +00001798 def listsymbols(self):
1799 self.output.write('''
1800Here is a list of the punctuation symbols which Python assigns special meaning
1801to. Enter any symbol to get more help.
1802
1803''')
1804 self.list(self.symbols.keys())
1805
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001806 def listtopics(self):
1807 self.output.write('''
1808Here is a list of available topics. Enter any topic name to get more help.
1809
1810''')
1811 self.list(self.topics.keys())
1812
Georg Brandldb7b6b92009-01-01 15:53:14 +00001813 def showtopic(self, topic, more_xrefs=''):
Georg Brandl6b38daa2008-06-01 21:05:17 +00001814 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001815 import pydoc_data.topics
Georg Brandl6b38daa2008-06-01 21:05:17 +00001816 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001817 self.output.write('''
Georg Brandl6b38daa2008-06-01 21:05:17 +00001818Sorry, topic and keyword documentation is not available because the
Georg Brandl5617db82009-04-27 16:28:57 +00001819module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001820''')
1821 return
1822 target = self.topics.get(topic, self.keywords.get(topic))
1823 if not target:
1824 self.output.write('no documentation found for %s\n' % repr(topic))
1825 return
1826 if type(target) is type(''):
Georg Brandldb7b6b92009-01-01 15:53:14 +00001827 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001828
Georg Brandl6b38daa2008-06-01 21:05:17 +00001829 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001830 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001831 doc = pydoc_data.topics.topics[label]
Georg Brandl6b38daa2008-06-01 21:05:17 +00001832 except KeyError:
1833 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001834 return
Georg Brandl6b38daa2008-06-01 21:05:17 +00001835 pager(doc.strip() + '\n')
Georg Brandldb7b6b92009-01-01 15:53:14 +00001836 if more_xrefs:
1837 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001838 if xrefs:
Georg Brandl6b38daa2008-06-01 21:05:17 +00001839 import io, formatter
Guido van Rossum34d19282007-08-09 01:03:29 +00001840 buffer = io.StringIO()
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001841 formatter.DumbWriter(buffer).send_flowing_data(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001842 'Related help topics: ' + ', '.join(xrefs.split()) + '\n')
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001843 self.output.write('\n%s\n' % buffer.getvalue())
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001844
Georg Brandldb7b6b92009-01-01 15:53:14 +00001845 def showsymbol(self, symbol):
1846 target = self.symbols[symbol]
1847 topic, _, xrefs = target.partition(' ')
1848 self.showtopic(topic, xrefs)
1849
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001850 def listmodules(self, key=''):
1851 if key:
1852 self.output.write('''
1853Here is a list of matching modules. Enter any module name to get more help.
1854
1855''')
1856 apropos(key)
1857 else:
1858 self.output.write('''
1859Please wait a moment while I gather a list of all available modules...
1860
1861''')
1862 modules = {}
1863 def callback(path, modname, desc, modules=modules):
1864 if modname and modname[-9:] == '.__init__':
1865 modname = modname[:-9] + ' (package)'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001866 if modname.find('.') < 0:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001867 modules[modname] = 1
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001868 def onerror(modname):
1869 callback(None, modname, None)
1870 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001871 self.list(modules.keys())
1872 self.output.write('''
1873Enter any module name to get more help. Or, type "modules spam" to search
1874for modules whose descriptions contain the word "spam".
1875''')
1876
1877help = Helper(sys.stdin, sys.stdout)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001878
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001879class Scanner:
1880 """A generic tree iterator."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001881 def __init__(self, roots, children, descendp):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001882 self.roots = roots[:]
1883 self.state = []
1884 self.children = children
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001885 self.descendp = descendp
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001886
1887 def next(self):
1888 if not self.state:
1889 if not self.roots:
1890 return None
1891 root = self.roots.pop(0)
1892 self.state = [(root, self.children(root))]
1893 node, children = self.state[-1]
1894 if not children:
1895 self.state.pop()
1896 return self.next()
1897 child = children.pop(0)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001898 if self.descendp(child):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001899 self.state.append((child, self.children(child)))
1900 return child
1901
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001902
1903class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001904 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001905
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001906 def run(self, callback, key=None, completer=None, onerror=None):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001907 if key: key = key.lower()
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001908 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001909 seen = {}
1910
1911 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001912 if modname != '__main__':
1913 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00001914 if key is None:
1915 callback(None, modname, '')
1916 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001917 name = __import__(modname).__doc__ or ''
1918 desc = name.split('\n')[0]
1919 name = modname + ' - ' + desc
1920 if name.lower().find(key) >= 0:
Ka-Ping Yee66246962001-04-12 11:59:50 +00001921 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001922
Christian Heimesd32ed6f2008-01-14 18:49:24 +00001923 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001924 if self.quit:
1925 break
1926 if key is None:
1927 callback(None, modname, '')
1928 else:
Georg Brandl126c8792009-04-05 15:05:48 +00001929 try:
1930 loader = importer.find_module(modname)
1931 except SyntaxError:
1932 # raised by tests for bad coding cookies or BOM
1933 continue
1934 if hasattr(loader, 'get_source'):
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00001935 try:
1936 source = loader.get_source(modname)
1937 except UnicodeDecodeError:
1938 if onerror:
1939 onerror(modname)
1940 continue
Guido van Rossum34d19282007-08-09 01:03:29 +00001941 import io
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00001942 desc = source_synopsis(io.StringIO(source)) or ''
Georg Brandl126c8792009-04-05 15:05:48 +00001943 if hasattr(loader, 'get_filename'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001944 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00001945 else:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001946 path = None
1947 else:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00001948 try:
1949 module = loader.load_module(modname)
1950 except ImportError:
1951 if onerror:
1952 onerror(modname)
1953 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001954 desc = (module.__doc__ or '').splitlines()[0]
1955 path = getattr(module,'__file__',None)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001956 name = modname + ' - ' + desc
1957 if name.lower().find(key) >= 0:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001958 callback(path, modname, desc)
1959
1960 if completer:
1961 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001962
1963def apropos(key):
1964 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001965 def callback(path, modname, desc):
1966 if modname[-9:] == '.__init__':
1967 modname = modname[:-9] + ' (package)'
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001968 print(modname, desc and '- ' + desc)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00001969 def onerror(modname):
1970 pass
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001971 try: import warnings
1972 except ImportError: pass
1973 else: warnings.filterwarnings('ignore') # ignore problems during import
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00001974 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001975
1976# --------------------------------------------------- web browser interface
1977
Ka-Ping Yee66246962001-04-12 11:59:50 +00001978def serve(port, callback=None, completer=None):
Georg Brandl83e9f4c2008-06-12 18:52:31 +00001979 import http.server, email.message, select
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001980
Georg Brandl24420152008-05-26 16:32:26 +00001981 class DocHandler(http.server.BaseHTTPRequestHandler):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001982 def send_document(self, title, contents):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001983 try:
1984 self.send_response(200)
Georg Brandl825fc8b2008-01-19 20:44:32 +00001985 self.send_header('Content-Type', 'text/html; charset=UTF-8')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001986 self.end_headers()
Georg Brandl825fc8b2008-01-19 20:44:32 +00001987 self.wfile.write(html.page(title, contents).encode('utf-8'))
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001988 except IOError: pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001989
1990 def do_GET(self):
1991 path = self.path
1992 if path[-5:] == '.html': path = path[:-5]
1993 if path[:1] == '/': path = path[1:]
1994 if path and path != '.':
1995 try:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001996 obj = locate(path, forceload=1)
Guido van Rossumb940e112007-01-10 16:19:56 +00001997 except ErrorDuringImport as value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001998 self.send_document(path, html.escape(str(value)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001999 return
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002000 if obj:
2001 self.send_document(describe(obj), html.document(obj, path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002002 else:
2003 self.send_document(path,
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002004'no Python documentation found for %s' % repr(path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002005 else:
2006 heading = html.heading(
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002007'<big><big><strong>Python: Index of Modules</strong></big></big>',
2008'#ffffff', '#7799ee')
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002009 def bltinlink(name):
2010 return '<a href="%s.html">%s</a>' % (name, name)
Georg Brandl661b0a12008-01-27 18:16:00 +00002011 names = [x for x in sys.builtin_module_names if x != '__main__']
2012 contents = html.multicolumn(names, bltinlink)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002013 indices = ['<p>' + html.bigsection(
2014 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2015
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002016 seen = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002017 for dir in sys.path:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002018 indices.append(html.index(dir, seen))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002019 contents = heading + ' '.join(indices) + '''<p align=right>
Tim Peters2306d242001-09-25 03:18:32 +00002020<font color="#909090" face="helvetica, arial"><strong>
2021pydoc</strong> by Ka-Ping Yee &lt;ping@lfw.org&gt;</font>'''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002022 self.send_document('Index of Modules', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002023
2024 def log_message(self, *args): pass
2025
Georg Brandl24420152008-05-26 16:32:26 +00002026 class DocServer(http.server.HTTPServer):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002027 def __init__(self, port, callback):
Ronald Oussoren94f25282010-05-05 19:11:21 +00002028 host = 'localhost'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002029 self.address = ('', port)
Ka-Ping Yeedb8ed152001-03-02 05:58:17 +00002030 self.url = 'http://%s:%d/' % (host, port)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002031 self.callback = callback
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002032 self.base.__init__(self, self.address, self.handler)
2033
2034 def serve_until_quit(self):
2035 import select
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002036 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002037 while not self.quit:
2038 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2039 if rd: self.handle_request()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002040
2041 def server_activate(self):
2042 self.base.server_activate(self)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002043 if self.callback: self.callback(self)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002044
Georg Brandl24420152008-05-26 16:32:26 +00002045 DocServer.base = http.server.HTTPServer
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002046 DocServer.handler = DocHandler
Georg Brandl83e9f4c2008-06-12 18:52:31 +00002047 DocHandler.MessageClass = email.message.Message
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002048 try:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002049 try:
2050 DocServer(port, callback).serve_until_quit()
2051 except (KeyboardInterrupt, select.error):
2052 pass
2053 finally:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002054 if completer: completer()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002055
2056# ----------------------------------------------------- graphical interface
2057
2058def gui():
2059 """Graphical interface (starts web server and pops up a control window)."""
2060 class GUI:
2061 def __init__(self, window, port=7464):
2062 self.window = window
2063 self.server = None
2064 self.scanner = None
2065
Georg Brandl14fc4272008-05-17 18:39:55 +00002066 import tkinter
2067 self.server_frm = tkinter.Frame(window)
2068 self.title_lbl = tkinter.Label(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002069 text='Starting server...\n ')
Georg Brandl14fc4272008-05-17 18:39:55 +00002070 self.open_btn = tkinter.Button(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002071 text='open browser', command=self.open, state='disabled')
Georg Brandl14fc4272008-05-17 18:39:55 +00002072 self.quit_btn = tkinter.Button(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002073 text='quit serving', command=self.quit, state='disabled')
2074
Georg Brandl14fc4272008-05-17 18:39:55 +00002075 self.search_frm = tkinter.Frame(window)
2076 self.search_lbl = tkinter.Label(self.search_frm, text='Search for')
2077 self.search_ent = tkinter.Entry(self.search_frm)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002078 self.search_ent.bind('<Return>', self.search)
Georg Brandl14fc4272008-05-17 18:39:55 +00002079 self.stop_btn = tkinter.Button(self.search_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002080 text='stop', pady=0, command=self.stop, state='disabled')
2081 if sys.platform == 'win32':
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002082 # Trying to hide and show this button crashes under Windows.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002083 self.stop_btn.pack(side='right')
2084
2085 self.window.title('pydoc')
2086 self.window.protocol('WM_DELETE_WINDOW', self.quit)
2087 self.title_lbl.pack(side='top', fill='x')
2088 self.open_btn.pack(side='left', fill='x', expand=1)
2089 self.quit_btn.pack(side='right', fill='x', expand=1)
2090 self.server_frm.pack(side='top', fill='x')
2091
2092 self.search_lbl.pack(side='left')
2093 self.search_ent.pack(side='right', fill='x', expand=1)
2094 self.search_frm.pack(side='top', fill='x')
2095 self.search_ent.focus_set()
2096
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002097 font = ('helvetica', sys.platform == 'win32' and 8 or 10)
Georg Brandl14fc4272008-05-17 18:39:55 +00002098 self.result_lst = tkinter.Listbox(window, font=font, height=6)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002099 self.result_lst.bind('<Button-1>', self.select)
2100 self.result_lst.bind('<Double-Button-1>', self.goto)
Georg Brandl14fc4272008-05-17 18:39:55 +00002101 self.result_scr = tkinter.Scrollbar(window,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002102 orient='vertical', command=self.result_lst.yview)
2103 self.result_lst.config(yscrollcommand=self.result_scr.set)
2104
Georg Brandl14fc4272008-05-17 18:39:55 +00002105 self.result_frm = tkinter.Frame(window)
2106 self.goto_btn = tkinter.Button(self.result_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002107 text='go to selected', command=self.goto)
Georg Brandl14fc4272008-05-17 18:39:55 +00002108 self.hide_btn = tkinter.Button(self.result_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002109 text='hide results', command=self.hide)
2110 self.goto_btn.pack(side='left', fill='x', expand=1)
2111 self.hide_btn.pack(side='right', fill='x', expand=1)
2112
2113 self.window.update()
2114 self.minwidth = self.window.winfo_width()
2115 self.minheight = self.window.winfo_height()
2116 self.bigminheight = (self.server_frm.winfo_reqheight() +
2117 self.search_frm.winfo_reqheight() +
2118 self.result_lst.winfo_reqheight() +
2119 self.result_frm.winfo_reqheight())
2120 self.bigwidth, self.bigheight = self.minwidth, self.bigminheight
2121 self.expanded = 0
2122 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2123 self.window.wm_minsize(self.minwidth, self.minheight)
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002124 self.window.tk.willdispatch()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002125
2126 import threading
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002127 threading.Thread(
2128 target=serve, args=(port, self.ready, self.quit)).start()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002129
2130 def ready(self, server):
2131 self.server = server
2132 self.title_lbl.config(
2133 text='Python documentation server at\n' + server.url)
2134 self.open_btn.config(state='normal')
2135 self.quit_btn.config(state='normal')
2136
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002137 def open(self, event=None, url=None):
2138 url = url or self.server.url
2139 try:
2140 import webbrowser
2141 webbrowser.open(url)
2142 except ImportError: # pre-webbrowser.py compatibility
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002143 if sys.platform == 'win32':
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002144 os.system('start "%s"' % url)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002145 else:
2146 rc = os.system('netscape -remote "openURL(%s)" &' % url)
2147 if rc: os.system('netscape "%s" &' % url)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002148
2149 def quit(self, event=None):
2150 if self.server:
2151 self.server.quit = 1
2152 self.window.quit()
2153
2154 def search(self, event=None):
2155 key = self.search_ent.get()
2156 self.stop_btn.pack(side='right')
2157 self.stop_btn.config(state='normal')
2158 self.search_lbl.config(text='Searching for "%s"...' % key)
2159 self.search_ent.forget()
2160 self.search_lbl.pack(side='left')
2161 self.result_lst.delete(0, 'end')
2162 self.goto_btn.config(state='disabled')
2163 self.expand()
2164
2165 import threading
2166 if self.scanner:
2167 self.scanner.quit = 1
2168 self.scanner = ModuleScanner()
2169 threading.Thread(target=self.scanner.run,
Ka-Ping Yee6dcfa382001-04-12 20:27:31 +00002170 args=(self.update, key, self.done)).start()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002171
2172 def update(self, path, modname, desc):
2173 if modname[-9:] == '.__init__':
2174 modname = modname[:-9] + ' (package)'
2175 self.result_lst.insert('end',
2176 modname + ' - ' + (desc or '(no description)'))
2177
2178 def stop(self, event=None):
2179 if self.scanner:
2180 self.scanner.quit = 1
2181 self.scanner = None
2182
2183 def done(self):
2184 self.scanner = None
2185 self.search_lbl.config(text='Search for')
2186 self.search_lbl.pack(side='left')
2187 self.search_ent.pack(side='right', fill='x', expand=1)
2188 if sys.platform != 'win32': self.stop_btn.forget()
2189 self.stop_btn.config(state='disabled')
2190
2191 def select(self, event=None):
2192 self.goto_btn.config(state='normal')
2193
2194 def goto(self, event=None):
2195 selection = self.result_lst.curselection()
2196 if selection:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002197 modname = self.result_lst.get(selection[0]).split()[0]
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002198 self.open(url=self.server.url + modname + '.html')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002199
2200 def collapse(self):
2201 if not self.expanded: return
2202 self.result_frm.forget()
2203 self.result_scr.forget()
2204 self.result_lst.forget()
2205 self.bigwidth = self.window.winfo_width()
2206 self.bigheight = self.window.winfo_height()
2207 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2208 self.window.wm_minsize(self.minwidth, self.minheight)
2209 self.expanded = 0
2210
2211 def expand(self):
2212 if self.expanded: return
2213 self.result_frm.pack(side='bottom', fill='x')
2214 self.result_scr.pack(side='right', fill='y')
2215 self.result_lst.pack(side='top', fill='both', expand=1)
2216 self.window.wm_geometry('%dx%d' % (self.bigwidth, self.bigheight))
2217 self.window.wm_minsize(self.minwidth, self.bigminheight)
2218 self.expanded = 1
2219
2220 def hide(self, event=None):
2221 self.stop()
2222 self.collapse()
2223
Georg Brandl14fc4272008-05-17 18:39:55 +00002224 import tkinter
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002225 try:
Georg Brandl14fc4272008-05-17 18:39:55 +00002226 root = tkinter.Tk()
Martin v. Löwise09bd932004-08-22 16:13:26 +00002227 # Tk will crash if pythonw.exe has an XP .manifest
2228 # file and the root has is not destroyed explicitly.
2229 # If the problem is ever fixed in Tk, the explicit
2230 # destroy can go.
2231 try:
2232 gui = GUI(root)
2233 root.mainloop()
2234 finally:
2235 root.destroy()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002236 except KeyboardInterrupt:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002237 pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002238
2239# -------------------------------------------------- command-line interface
2240
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002241def ispath(x):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002242 return isinstance(x, str) and x.find(os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002243
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002244def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002245 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002246 import getopt
Guido van Rossum756aa932007-04-07 03:04:01 +00002247 class BadUsage(Exception): pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002248
Nick Coghlan106274b2009-11-15 23:04:33 +00002249 # Scripts don't get the current directory in their path by default
2250 # unless they are run with the '-m' switch
2251 if '' not in sys.path:
2252 scriptdir = os.path.dirname(sys.argv[0])
2253 if scriptdir in sys.path:
2254 sys.path.remove(scriptdir)
2255 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002256
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002257 try:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002258 opts, args = getopt.getopt(sys.argv[1:], 'gk:p:w')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002259 writing = 0
2260
2261 for opt, val in opts:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002262 if opt == '-g':
2263 gui()
2264 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002265 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002266 apropos(val)
2267 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002268 if opt == '-p':
2269 try:
2270 port = int(val)
2271 except ValueError:
2272 raise BadUsage
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002273 def ready(server):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002274 print('pydoc server ready at %s' % server.url)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002275 def stopped():
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002276 print('pydoc server stopped')
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002277 serve(port, ready, stopped)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002278 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002279 if opt == '-w':
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002280 writing = 1
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002281
2282 if not args: raise BadUsage
2283 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002284 if ispath(arg) and not os.path.exists(arg):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002285 print('file %r does not exist' % arg)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002286 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002287 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002288 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002289 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002290 if writing:
2291 if ispath(arg) and os.path.isdir(arg):
2292 writedocs(arg)
2293 else:
2294 writedoc(arg)
2295 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002296 help.help(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +00002297 except ErrorDuringImport as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002298 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002299
2300 except (getopt.error, BadUsage):
Martin v. Löwisf9b08b82003-10-31 13:05:21 +00002301 cmd = os.path.basename(sys.argv[0])
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002302 print("""pydoc - the Python documentation tool
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002303
2304%s <name> ...
2305 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002306 Python keyword, topic, function, module, or package, or a dotted
2307 reference to a class or function within a module or module in a
2308 package. If <name> contains a '%s', it is used as the path to a
2309 Python source file to document. If name is 'keywords', 'topics',
2310 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002311
2312%s -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002313 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002314
2315%s -p <port>
2316 Start an HTTP server on the given port on the local machine.
2317
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002318%s -g
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002319 Pop up a graphical interface for finding and serving documentation.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002320
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002321%s -w <name> ...
2322 Write out the HTML documentation for a module to a file in the current
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002323 directory. If <name> contains a '%s', it is treated as a filename; if
2324 it names a directory, documentation is written for all the contents.
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002325""" % (cmd, os.sep, cmd, cmd, cmd, cmd, os.sep))
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002326
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002327if __name__ == '__main__': cli()