blob: 0716a3ab6caaffd856e3d550379a02703649648e [file] [log] [blame]
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001#!/usr/bin/env python
Guido van Rossumfce538c2002-08-06 17:29:38 +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
30 http://www.python.org/doc/current/lib/
31
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
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000055import sys, imp, os, re, types, inspect, __builtin__, pkgutil
Ka-Ping Yeedd175342001-02-27 14:43:46 +000056from repr import Repr
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000057try:
58 from collections import deque
59except ImportError:
60 # Python 2.3 compatibility
61 class deque(list):
62 def popleft(self):
63 return self.pop(0)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000064
65# --------------------------------------------------------- common routines
66
Ka-Ping Yeedd175342001-02-27 14:43:46 +000067def pathdirs():
68 """Convert sys.path into a list of absolute, existing, unique paths."""
69 dirs = []
Ka-Ping Yee1d384632001-03-01 00:24:32 +000070 normdirs = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +000071 for dir in sys.path:
72 dir = os.path.abspath(dir or '.')
Ka-Ping Yee1d384632001-03-01 00:24:32 +000073 normdir = os.path.normcase(dir)
74 if normdir not in normdirs and os.path.isdir(dir):
Ka-Ping Yeedd175342001-02-27 14:43:46 +000075 dirs.append(dir)
Ka-Ping Yee1d384632001-03-01 00:24:32 +000076 normdirs.append(normdir)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000077 return dirs
78
79def getdoc(object):
80 """Get the doc string or comments for an object."""
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000081 result = inspect.getdoc(object) or inspect.getcomments(object)
Neal Norwitz9d72bb42007-04-17 08:48:32 +000082 return result and re.sub('^ *\n', '', result.rstrip()) or ''
Ka-Ping Yeedd175342001-02-27 14:43:46 +000083
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000084def splitdoc(doc):
85 """Split a doc string into a synopsis line (if any) and the rest."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +000086 lines = doc.strip().split('\n')
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000087 if len(lines) == 1:
88 return lines[0], ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +000089 elif len(lines) >= 2 and not lines[1].rstrip():
90 return lines[0], '\n'.join(lines[2:])
91 return '', '\n'.join(lines)
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000092
Ka-Ping Yeedd175342001-02-27 14:43:46 +000093def classname(object, modname):
94 """Get a class name and qualify it with a module name if necessary."""
95 name = object.__name__
96 if object.__module__ != modname:
97 name = object.__module__ + '.' + name
98 return name
99
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000100def isdata(object):
Georg Brandl94432422005-07-22 21:52:25 +0000101 """Check if an object is of a type that probably means it's data."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000102 return not (inspect.ismodule(object) or inspect.isclass(object) or
103 inspect.isroutine(object) or inspect.isframe(object) or
104 inspect.istraceback(object) or inspect.iscode(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000105
106def replace(text, *pairs):
107 """Do a series of global replacements on a string."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000108 while pairs:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000109 text = pairs[1].join(text.split(pairs[0]))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000110 pairs = pairs[2:]
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000111 return text
112
113def cram(text, maxlen):
114 """Omit part of a string if needed to make it fit in a maximum length."""
115 if len(text) > maxlen:
Raymond Hettingerfca3bb62002-10-21 04:44:11 +0000116 pre = max(0, (maxlen-3)//2)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000117 post = max(0, maxlen-3-pre)
118 return text[:pre] + '...' + text[len(text)-post:]
119 return text
120
Brett Cannon84601f12004-06-19 01:22:48 +0000121_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000122def stripid(text):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000123 """Remove the hexadecimal id from a Python object representation."""
Brett Cannonc6c1f472004-06-19 01:02:51 +0000124 # The behaviour of %p is implementation-dependent in terms of case.
125 if _re_stripid.search(repr(Exception)):
126 return _re_stripid.sub(r'\1', text)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000127 return text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000128
Brett Cannonc6c1f472004-06-19 01:02:51 +0000129def _is_some_method(obj):
130 return inspect.ismethod(obj) or inspect.ismethoddescriptor(obj)
Tim Peters536d2262001-09-20 05:13:38 +0000131
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000132def allmethods(cl):
133 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000134 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000135 methods[key] = 1
136 for base in cl.__bases__:
137 methods.update(allmethods(base)) # all your base are belong to us
138 for key in methods.keys():
139 methods[key] = getattr(cl, key)
140 return methods
141
Tim Petersfa26f7c2001-09-24 08:05:11 +0000142def _split_list(s, predicate):
143 """Split sequence s via predicate, and return pair ([true], [false]).
144
145 The return value is a 2-tuple of lists,
146 ([x for x in s if predicate(x)],
147 [x for x in s if not predicate(x)])
148 """
149
Tim Peters28355492001-09-23 21:29:55 +0000150 yes = []
151 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000152 for x in s:
153 if predicate(x):
154 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000155 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000156 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000157 return yes, no
158
Skip Montanaroa5616d22004-06-11 04:46:12 +0000159def visiblename(name, all=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000160 """Decide whether to show documentation on a variable."""
161 # Certain special names are redundant.
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000162 if name in ('__builtins__', '__doc__', '__file__', '__path__',
163 '__module__', '__name__', '__slots__'): return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000164 # Private names are hidden, but special names are displayed.
165 if name.startswith('__') and name.endswith('__'): return 1
Skip Montanaroa5616d22004-06-11 04:46:12 +0000166 if all is not None:
167 # only document that which the programmer exported in __all__
168 return name in all
169 else:
170 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000171
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000172def classify_class_attrs(object):
173 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000174 results = []
175 for (name, kind, cls, value) in inspect.classify_class_attrs(object):
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000176 if inspect.isdatadescriptor(value):
177 kind = 'data descriptor'
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000178 results.append((name, kind, cls, value))
179 return results
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000180
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000181# ----------------------------------------------------- module manipulation
182
183def ispackage(path):
184 """Guess whether a path refers to a package directory."""
185 if os.path.isdir(path):
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000186 for ext in ('.py', '.pyc', '.pyo'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000187 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000188 return True
189 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000190
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000191def source_synopsis(file):
192 line = file.readline()
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000193 while line[:1] == '#' or not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000194 line = file.readline()
195 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000196 line = line.strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000197 if line[:4] == 'r"""': line = line[1:]
198 if line[:3] == '"""':
199 line = line[3:]
200 if line[-1:] == '\\': line = line[:-1]
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000201 while not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000202 line = file.readline()
203 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000204 result = line.split('"""')[0].strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000205 else: result = None
206 return result
207
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000208def synopsis(filename, cache={}):
209 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000210 mtime = os.stat(filename).st_mtime
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000211 lastupdate, result = cache.get(filename, (0, None))
212 if lastupdate < mtime:
213 info = inspect.getmoduleinfo(filename)
Georg Brandl26fd2e12006-03-08 09:34:53 +0000214 try:
215 file = open(filename)
216 except IOError:
217 # module can't be opened, so skip it
218 return None
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000219 if info and 'b' in info[2]: # binary modules have to be imported
220 try: module = imp.load_module('__temp__', file, filename, info[1:])
221 except: return None
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000222 result = (module.__doc__ or '').splitlines()[0]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000223 del sys.modules['__temp__']
224 else: # text modules can be directly examined
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000225 result = source_synopsis(file)
226 file.close()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000227 cache[filename] = (mtime, result)
228 return result
229
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000230class ErrorDuringImport(Exception):
231 """Errors that occurred while trying to import something to document it."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000232 def __init__(self, filename, exc_info):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000233 self.filename = filename
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000234 self.exc, self.value, self.tb = exc_info
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000235
236 def __str__(self):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000237 exc = self.exc
238 if type(exc) is types.ClassType:
239 exc = exc.__name__
240 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000241
242def importfile(path):
243 """Import a Python source file or compiled file given its path."""
244 magic = imp.get_magic()
245 file = open(path, 'r')
246 if file.read(len(magic)) == magic:
247 kind = imp.PY_COMPILED
248 else:
249 kind = imp.PY_SOURCE
250 file.close()
251 filename = os.path.basename(path)
252 name, ext = os.path.splitext(filename)
253 file = open(path, 'r')
254 try:
255 module = imp.load_module(name, file, path, (ext, 'r', kind))
256 except:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000257 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000258 file.close()
259 return module
260
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000261def safeimport(path, forceload=0, cache={}):
262 """Import a module; handle errors; return None if the module isn't found.
263
264 If the module *is* found but an exception occurs, it's wrapped in an
265 ErrorDuringImport exception and reraised. Unlike __import__, if a
266 package path is specified, the module at the end of the path is returned,
267 not the package at the beginning. If the optional 'forceload' argument
268 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000269 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000270 # If forceload is 1 and the module has been previously loaded from
271 # disk, we always have to reload the module. Checking the file's
272 # mtime isn't good enough (e.g. the module could contain a class
273 # that inherits from another module that has changed).
274 if forceload and path in sys.modules:
275 if path not in sys.builtin_module_names:
276 # Avoid simply calling reload() because it leaves names in
277 # the currently loaded module lying around if they're not
278 # defined in the new source file. Instead, remove the
279 # module from sys.modules and re-import. Also remove any
280 # submodules because they won't appear in the newly loaded
281 # module's namespace if they're already in sys.modules.
282 subs = [m for m in sys.modules if m.startswith(path + '.')]
283 for key in [path] + subs:
284 # Prevent garbage collection.
285 cache[key] = sys.modules[key]
286 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000287 module = __import__(path)
288 except:
289 # Did the error occur before or after the module was found?
290 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000291 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000292 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000293 raise ErrorDuringImport(sys.modules[path].__file__, info)
294 elif exc is SyntaxError:
295 # A SyntaxError occurred before we could execute the module.
296 raise ErrorDuringImport(value.filename, info)
297 elif exc is ImportError and \
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000298 str(value).lower().split()[:2] == ['no', 'module']:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000299 # The module was not found.
300 return None
301 else:
302 # Some other error occurred during the importing process.
303 raise ErrorDuringImport(path, sys.exc_info())
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000304 for part in path.split('.')[1:]:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000305 try: module = getattr(module, part)
306 except AttributeError: return None
307 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000308
309# ---------------------------------------------------- formatter base class
310
311class Doc:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000312 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000313 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000314 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000315 # 'try' clause is to attempt to handle the possibility that inspect
316 # identifies something in a way that pydoc itself has issues handling;
317 # think 'super' and how it is a descriptor (which raises the exception
318 # by lacking a __name__ attribute) and an instance.
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000319 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
320 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000321 try:
322 if inspect.ismodule(object): return self.docmodule(*args)
323 if inspect.isclass(object): return self.docclass(*args)
324 if inspect.isroutine(object): return self.docroutine(*args)
325 except AttributeError:
326 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000327 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000328 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000329
330 def fail(self, object, name=None, *args):
331 """Raise an exception for unimplemented types."""
332 message = "don't know how to document object%s of type %s" % (
333 name and ' ' + repr(name), type(object).__name__)
334 raise TypeError, message
335
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000336 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000337
Skip Montanaro4997a692003-09-10 16:47:51 +0000338 def getdocloc(self, object):
339 """Return the location of module docs or None"""
340
341 try:
342 file = inspect.getabsfile(object)
343 except TypeError:
344 file = '(built-in)'
345
346 docloc = os.environ.get("PYTHONDOCS",
347 "http://www.python.org/doc/current/lib")
348 basedir = os.path.join(sys.exec_prefix, "lib",
349 "python"+sys.version[0:3])
350 if (isinstance(object, type(os)) and
351 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
352 'marshal', 'posix', 'signal', 'sys',
353 'thread', 'zipimport') or
354 (file.startswith(basedir) and
355 not file.startswith(os.path.join(basedir, 'site-packages'))))):
Skip Montanarof2134842004-06-07 02:40:05 +0000356 htmlfile = "module-%s.html" % object.__name__
Skip Montanaro4997a692003-09-10 16:47:51 +0000357 if docloc.startswith("http://"):
Skip Montanarof2134842004-06-07 02:40:05 +0000358 docloc = "%s/%s" % (docloc.rstrip("/"), htmlfile)
Skip Montanaro4997a692003-09-10 16:47:51 +0000359 else:
Skip Montanarof2134842004-06-07 02:40:05 +0000360 docloc = os.path.join(docloc, htmlfile)
Skip Montanaro4997a692003-09-10 16:47:51 +0000361 else:
362 docloc = None
363 return docloc
364
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000365# -------------------------------------------- HTML documentation generator
366
367class HTMLRepr(Repr):
368 """Class for safely making an HTML representation of a Python object."""
369 def __init__(self):
370 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000371 self.maxlist = self.maxtuple = 20
372 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000373 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000374
375 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000376 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000377
378 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000379 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000380
381 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000382 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000383 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000384 if hasattr(self, methodname):
385 return getattr(self, methodname)(x, level)
386 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000387
388 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000389 test = cram(x, self.maxstring)
390 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000391 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000392 # Backslashes are only literal in the string and are never
393 # needed to make any special characters, so show a raw string.
394 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000395 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000396 r'<font color="#c040c0">\1</font>',
397 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000398
Skip Montanarodf708782002-03-07 22:58:02 +0000399 repr_str = repr_string
400
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000401 def repr_instance(self, x, level):
402 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000403 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000404 except:
405 return self.escape('<%s instance>' % x.__class__.__name__)
406
407 repr_unicode = repr_string
408
409class HTMLDoc(Doc):
410 """Formatter class for HTML documentation."""
411
412 # ------------------------------------------- HTML formatting utilities
413
414 _repr_instance = HTMLRepr()
415 repr = _repr_instance.repr
416 escape = _repr_instance.escape
417
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000418 def page(self, title, contents):
419 """Format an HTML page."""
420 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000421<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000422<html><head><title>Python: %s</title>
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000423</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000424%s
425</body></html>''' % (title, contents)
426
427 def heading(self, title, fgcol, bgcol, extras=''):
428 """Format a page heading."""
429 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000430<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000431<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000432<td valign=bottom>&nbsp;<br>
433<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000434><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000435><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000436 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
437
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000438 def section(self, title, fgcol, bgcol, contents, width=6,
439 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000440 """Format a section with a heading."""
441 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000442 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000443 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000444<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000445<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000446<td colspan=3 valign=bottom>&nbsp;<br>
447<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000448 ''' % (bgcol, fgcol, title)
449 if prelude:
450 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000451<tr bgcolor="%s"><td rowspan=2>%s</td>
452<td colspan=2>%s</td></tr>
453<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
454 else:
455 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000456<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000457
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000458 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000459
460 def bigsection(self, title, *args):
461 """Format a section with a big heading."""
462 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000463 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000464
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000465 def preformat(self, text):
466 """Format literal preformatted text."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000467 text = self.escape(text.expandtabs())
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000468 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
469 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000470
471 def multicolumn(self, list, format, cols=4):
472 """Format a list of items into a multi-column list."""
473 result = ''
474 rows = (len(list)+cols-1)/cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000475 for col in range(cols):
476 result = result + '<td width="%d%%" valign=top>' % (100/cols)
477 for i in range(rows*col, rows*col+rows):
478 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000479 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000480 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000481 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000482
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000483 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000484
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000485 def namelink(self, name, *dicts):
486 """Make a link for an identifier, given name-to-URL mappings."""
487 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000488 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000489 return '<a href="%s">%s</a>' % (dict[name], name)
490 return name
491
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000492 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000493 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000494 name, module = object.__name__, sys.modules.get(object.__module__)
495 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000496 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000497 module.__name__, name, classname(object, modname))
498 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000499
500 def modulelink(self, object):
501 """Make a link for a module."""
502 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
503
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000504 def modpkglink(self, modpkginfo):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000505 """Make a link for a module or package to display in an index."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000506 name, path, ispackage, shadowed = modpkginfo
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000507 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000508 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000509 if path:
510 url = '%s.%s.html' % (path, name)
511 else:
512 url = '%s.html' % name
513 if ispackage:
514 text = '<strong>%s</strong>&nbsp;(package)' % name
515 else:
516 text = name
517 return '<a href="%s">%s</a>' % (url, text)
518
519 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
520 """Mark up some plain text, given a context of symbols to look for.
521 Each context dictionary maps object names to anchor names."""
522 escape = escape or self.escape
523 results = []
524 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000525 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
526 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000527 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000528 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000529 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000530 match = pattern.search(text, here)
531 if not match: break
532 start, end = match.span()
533 results.append(escape(text[here:start]))
534
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000535 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000536 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000537 url = escape(all).replace('"', '&quot;')
538 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000539 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000540 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
541 results.append('<a href="%s">%s</a>' % (url, escape(all)))
542 elif pep:
543 url = 'http://www.python.org/peps/pep-%04d.html' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000544 results.append('<a href="%s">%s</a>' % (url, escape(all)))
545 elif text[end:end+1] == '(':
546 results.append(self.namelink(name, methods, funcs, classes))
547 elif selfdot:
548 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000549 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000550 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000551 here = end
552 results.append(escape(text[here:]))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000553 return ''.join(results)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000554
555 # ---------------------------------------------- type-specific routines
556
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000557 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000558 """Produce HTML for a class tree as given by inspect.getclasstree()."""
559 result = ''
560 for entry in tree:
561 if type(entry) is type(()):
562 c, bases = entry
Tim Peters2306d242001-09-25 03:18:32 +0000563 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000564 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000565 if bases and bases != (parent,):
566 parents = []
567 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000568 parents.append(self.classlink(base, modname))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000569 result = result + '(' + ', '.join(parents) + ')'
Tim Peters2306d242001-09-25 03:18:32 +0000570 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000571 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000572 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000573 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000574 return '<dl>\n%s</dl>\n' % result
575
Tim Peters8dd7ade2001-10-18 19:56:17 +0000576 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000577 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000578 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000579 try:
580 all = object.__all__
581 except AttributeError:
582 all = None
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000583 parts = name.split('.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000584 links = []
585 for i in range(len(parts)-1):
586 links.append(
587 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000588 ('.'.join(parts[:i+1]), parts[i]))
589 linkedname = '.'.join(links + parts[-1:])
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000590 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000591 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000592 path = inspect.getabsfile(object)
Ka-Ping Yee6191a232001-04-13 15:00:27 +0000593 url = path
594 if sys.platform == 'win32':
595 import nturl2path
596 url = nturl2path.pathname2url(path)
597 filelink = '<a href="file:%s">%s</a>' % (url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000598 except TypeError:
599 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000600 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000601 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000602 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000603 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000604 version = version[11:-1].strip()
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000605 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000606 if hasattr(object, '__date__'):
607 info.append(self.escape(str(object.__date__)))
608 if info:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000609 head = head + ' (%s)' % ', '.join(info)
Skip Montanaro4997a692003-09-10 16:47:51 +0000610 docloc = self.getdocloc(object)
611 if docloc is not None:
612 docloc = '<br><a href="%(docloc)s">Module Docs</a>' % locals()
613 else:
614 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000615 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000616 head, '#ffffff', '#7799ee',
617 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000618
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000619 modules = inspect.getmembers(object, inspect.ismodule)
620
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000621 classes, cdict = [], {}
622 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000623 # if __all__ exists, believe it. Otherwise use old heuristic.
624 if (all is not None or
625 (inspect.getmodule(value) or object) is object):
Skip Montanaroa5616d22004-06-11 04:46:12 +0000626 if visiblename(key, all):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000627 classes.append((key, value))
628 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000629 for key, value in classes:
630 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000631 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000632 module = sys.modules.get(modname)
633 if modname != name and module and hasattr(module, key):
634 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000635 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000636 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000637 funcs, fdict = [], {}
638 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000639 # if __all__ exists, believe it. Otherwise use old heuristic.
640 if (all is not None or
641 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Skip Montanaroa5616d22004-06-11 04:46:12 +0000642 if visiblename(key, all):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000643 funcs.append((key, value))
644 fdict[key] = '#-' + key
645 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000646 data = []
647 for key, value in inspect.getmembers(object, isdata):
Skip Montanaroa5616d22004-06-11 04:46:12 +0000648 if visiblename(key, all):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000649 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000650
651 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
652 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000653 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000654
655 if hasattr(object, '__path__'):
656 modpkgs = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000657 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
658 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000659 modpkgs.sort()
660 contents = self.multicolumn(modpkgs, self.modpkglink)
661 result = result + self.bigsection(
662 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000663 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000664 contents = self.multicolumn(
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000665 modules, lambda t: self.modulelink(t[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000666 result = result + self.bigsection(
667 'Modules', '#fffff', '#aa55cc', contents)
668
669 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000670 classlist = [value for (key, value) in classes]
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000671 contents = [
672 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000673 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000674 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000675 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000676 'Classes', '#ffffff', '#ee77aa', ' '.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000677 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000678 contents = []
679 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000680 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000681 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000682 'Functions', '#ffffff', '#eeaa77', ' '.join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000683 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000684 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000685 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000686 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000687 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000688 'Data', '#ffffff', '#55aa55', '<br>\n'.join(contents))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000689 if hasattr(object, '__author__'):
690 contents = self.markup(str(object.__author__), self.preformat)
691 result = result + self.bigsection(
692 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000693 if hasattr(object, '__credits__'):
694 contents = self.markup(str(object.__credits__), self.preformat)
695 result = result + self.bigsection(
696 'Credits', '#ffffff', '#7799ee', contents)
697
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000698 return result
699
Tim Peters8dd7ade2001-10-18 19:56:17 +0000700 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
701 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000702 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000703 realname = object.__name__
704 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000705 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000706
Tim Petersb47879b2001-09-24 04:47:19 +0000707 contents = []
708 push = contents.append
709
Tim Petersfa26f7c2001-09-24 08:05:11 +0000710 # Cute little class to pump out a horizontal rule between sections.
711 class HorizontalRule:
712 def __init__(self):
713 self.needone = 0
714 def maybe(self):
715 if self.needone:
716 push('<hr>\n')
717 self.needone = 1
718 hr = HorizontalRule()
719
Tim Petersc86f6ca2001-09-26 21:31:51 +0000720 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000721 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000722 if len(mro) > 2:
723 hr.maybe()
724 push('<dl><dt>Method resolution order:</dt>\n')
725 for base in mro:
726 push('<dd>%s</dd>\n' % self.classlink(base,
727 object.__module__))
728 push('</dl>\n')
729
Tim Petersb47879b2001-09-24 04:47:19 +0000730 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000731 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000732 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000733 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000734 push(msg)
735 for name, kind, homecls, value in ok:
736 push(self.document(getattr(object, name), name, mod,
737 funcs, classes, mdict, object))
738 push('\n')
739 return attrs
740
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000741 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000742 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000743 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000744 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000745 push(msg)
746 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000747 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000748 return attrs
749
Tim Petersfa26f7c2001-09-24 08:05:11 +0000750 def spilldata(msg, attrs, predicate):
751 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000752 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000753 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000754 push(msg)
755 for name, kind, homecls, value in ok:
756 base = self.docother(getattr(object, name), name, mod)
Martin v. Löwise59e2ba2003-05-03 09:09:02 +0000757 if callable(value) or inspect.isdatadescriptor(value):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000758 doc = getattr(value, "__doc__", None)
759 else:
760 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000761 if doc is None:
762 push('<dl><dt>%s</dl>\n' % base)
763 else:
764 doc = self.markup(getdoc(value), self.preformat,
765 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000766 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000767 push('<dl><dt>%s%s</dl>\n' % (base, doc))
768 push('\n')
769 return attrs
770
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000771 attrs = [(name, kind, cls, value)
772 for name, kind, cls, value in classify_class_attrs(object)
773 if visiblename(name)]
774
Tim Petersb47879b2001-09-24 04:47:19 +0000775 mdict = {}
776 for key, kind, homecls, value in attrs:
777 mdict[key] = anchor = '#' + name + '-' + key
778 value = getattr(object, key)
779 try:
780 # The value may not be hashable (e.g., a data attr with
781 # a dict or list value).
782 mdict[value] = anchor
783 except TypeError:
784 pass
785
Tim Petersfa26f7c2001-09-24 08:05:11 +0000786 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000787 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000788 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000789 else:
790 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000791 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
792
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000793 if thisclass is __builtin__.object:
794 attrs = inherited
795 continue
796 elif thisclass is object:
797 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000798 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000799 tag = 'inherited from %s' % self.classlink(thisclass,
800 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000801 tag += ':<br>\n'
802
803 # Sort attrs by name.
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000804 try:
805 attrs.sort(key=lambda t: t[0])
806 except TypeError:
807 attrs.sort(lambda t1, t2: cmp(t1[0], t2[0])) # 2.3 compat
Tim Petersb47879b2001-09-24 04:47:19 +0000808
809 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000810 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000811 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000812 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000813 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000814 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000815 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000816 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
817 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000818 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000819 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000820 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000821 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000822
823 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000824
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000825 if name == realname:
826 title = '<a name="%s">class <strong>%s</strong></a>' % (
827 name, realname)
828 else:
829 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
830 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000831 if bases:
832 parents = []
833 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000834 parents.append(self.classlink(base, object.__module__))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000835 title = title + '(%s)' % ', '.join(parents)
Tim Peters2306d242001-09-25 03:18:32 +0000836 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000837 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000838
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000839 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000840
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000841 def formatvalue(self, object):
842 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000843 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000844
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000845 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000846 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000847 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000848 realname = object.__name__
849 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000850 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000851 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000852 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000853 if inspect.ismethod(object):
Ka-Ping Yee6dcfa382001-04-12 20:27:31 +0000854 imclass = object.im_class
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000855 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000856 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000857 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000858 else:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000859 if object.im_self is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000860 note = ' method of %s instance' % self.classlink(
861 object.im_self.__class__, mod)
862 else:
863 note = ' unbound %s method' % self.classlink(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000864 object = object.im_func
865
866 if name == realname:
867 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
868 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000869 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000870 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000871 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000872 cl.__name__ + '-' + realname, realname)
873 skipdocs = 1
874 else:
875 reallink = realname
876 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
877 anchor, name, reallink)
Tim Peters4bcfa312001-09-20 06:08:24 +0000878 if inspect.isfunction(object):
Guido van Rossum2e65f892007-02-28 22:03:49 +0000879 args, varargs, kwonlyargs, kwdefaults, varkw, defaults, ann = \
880 inspect.getfullargspec(object)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000881 argspec = inspect.formatargspec(
Guido van Rossum2e65f892007-02-28 22:03:49 +0000882 args, varargs, kwonlyargs, kwdefaults, varkw, defaults, ann,
883 formatvalue=self.formatvalue,
884 formatannotation=inspect.formatannotationrelativeto(object))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000885 if realname == '<lambda>':
Tim Peters59ed4482001-10-31 04:20:26 +0000886 title = '<strong>%s</strong> <em>lambda</em> ' % name
Guido van Rossum2e65f892007-02-28 22:03:49 +0000887 # XXX lambda's won't usually have func_annotations['return']
888 # since the syntax doesn't support but it is possible.
889 # So removing parentheses isn't truly safe.
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000890 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +0000891 else:
892 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000893
Tim Peters2306d242001-09-25 03:18:32 +0000894 decl = title + argspec + (note and self.grey(
895 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000896
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000897 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000898 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000899 else:
900 doc = self.markup(
901 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000902 doc = doc and '<dd><tt>%s</tt></dd>' % doc
903 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000904
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000905 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000906 results = []
907 push = results.append
908
909 if name:
910 push('<dl><dt><strong>%s</strong></dt>\n' % name)
911 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000912 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000913 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000914 push('</dl>\n')
915
916 return ''.join(results)
917
918 def docproperty(self, object, name=None, mod=None, cl=None):
919 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000920 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000921
Tim Peters8dd7ade2001-10-18 19:56:17 +0000922 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000923 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000924 lhs = name and '<strong>%s</strong> = ' % name or ''
925 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000926
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000927 def docdata(self, object, name=None, mod=None, cl=None):
928 """Produce html documentation for a data descriptor."""
929 return self._docdescriptor(name, object, mod)
930
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000931 def index(self, dir, shadowed=None):
932 """Generate an HTML index for a directory of modules."""
933 modpkgs = []
934 if shadowed is None: shadowed = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000935 for importer, name, ispkg in pkgutil.iter_modules([dir]):
936 modpkgs.append((name, '', ispkg, name in shadowed))
937 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000938
939 modpkgs.sort()
940 contents = self.multicolumn(modpkgs, self.modpkglink)
941 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
942
943# -------------------------------------------- text documentation generator
944
945class TextRepr(Repr):
946 """Class for safely making a text representation of a Python object."""
947 def __init__(self):
948 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000949 self.maxlist = self.maxtuple = 20
950 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000951 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000952
953 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000954 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000955 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000956 if hasattr(self, methodname):
957 return getattr(self, methodname)(x, level)
958 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000959
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000960 def repr_string(self, x, level):
961 test = cram(x, self.maxstring)
962 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000963 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000964 # Backslashes are only literal in the string and are never
965 # needed to make any special characters, so show a raw string.
966 return 'r' + testrepr[0] + test + testrepr[0]
967 return testrepr
968
Skip Montanarodf708782002-03-07 22:58:02 +0000969 repr_str = repr_string
970
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000971 def repr_instance(self, x, level):
972 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000973 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000974 except:
975 return '<%s instance>' % x.__class__.__name__
976
977class TextDoc(Doc):
978 """Formatter class for text documentation."""
979
980 # ------------------------------------------- text formatting utilities
981
982 _repr_instance = TextRepr()
983 repr = _repr_instance.repr
984
985 def bold(self, text):
986 """Format a string in bold by overstriking."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000987 return ''.join(map(lambda ch: ch + '\b' + ch, text))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000988
989 def indent(self, text, prefix=' '):
990 """Indent text by prepending a given prefix to each line."""
991 if not text: return ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000992 lines = text.split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000993 lines = map(lambda line, prefix=prefix: prefix + line, lines)
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000994 if lines: lines[-1] = lines[-1].rstrip()
995 return '\n'.join(lines)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000996
997 def section(self, title, contents):
998 """Format a section with a given heading."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000999 clean_contents = self.indent(contents).rstrip()
1000 return self.bold(title) + '\n' + clean_contents + '\n\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001001
1002 # ---------------------------------------------- type-specific routines
1003
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001004 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001005 """Render in text a class tree as returned by inspect.getclasstree()."""
1006 result = ''
1007 for entry in tree:
1008 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001009 c, bases = entry
1010 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001011 if bases and bases != (parent,):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001012 parents = map(lambda c, m=modname: classname(c, m), bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001013 result = result + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001014 result = result + '\n'
1015 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001016 result = result + self.formattree(
1017 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001018 return result
1019
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001020 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001021 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001022 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001023 synop, desc = splitdoc(getdoc(object))
1024 result = self.section('NAME', name + (synop and ' - ' + synop))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001025
1026 try:
Skip Montanaroa5616d22004-06-11 04:46:12 +00001027 all = object.__all__
1028 except AttributeError:
1029 all = None
1030
1031 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001032 file = inspect.getabsfile(object)
1033 except TypeError:
1034 file = '(built-in)'
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001035 result = result + self.section('FILE', file)
Skip Montanaro4997a692003-09-10 16:47:51 +00001036
1037 docloc = self.getdocloc(object)
1038 if docloc is not None:
1039 result = result + self.section('MODULE DOCS', docloc)
1040
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001041 if desc:
1042 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001043
1044 classes = []
1045 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001046 # if __all__ exists, believe it. Otherwise use old heuristic.
1047 if (all is not None
1048 or (inspect.getmodule(value) or object) is object):
Skip Montanaroa5616d22004-06-11 04:46:12 +00001049 if visiblename(key, all):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001050 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001051 funcs = []
1052 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001053 # if __all__ exists, believe it. Otherwise use old heuristic.
1054 if (all is not None or
1055 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Skip Montanaroa5616d22004-06-11 04:46:12 +00001056 if visiblename(key, all):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001057 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001058 data = []
1059 for key, value in inspect.getmembers(object, isdata):
Skip Montanaroa5616d22004-06-11 04:46:12 +00001060 if visiblename(key, all):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001061 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001062
1063 if hasattr(object, '__path__'):
1064 modpkgs = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001065 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
1066 if ispkg:
1067 modpkgs.append(modname + ' (package)')
1068 else:
1069 modpkgs.append(modname)
1070
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001071 modpkgs.sort()
1072 result = result + self.section(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001073 'PACKAGE CONTENTS', '\n'.join(modpkgs))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001074
1075 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001076 classlist = [value for key, value in classes]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001077 contents = [self.formattree(
1078 inspect.getclasstree(classlist, 1), name)]
1079 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001080 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001081 result = result + self.section('CLASSES', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001082
1083 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001084 contents = []
1085 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001086 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001087 result = result + self.section('FUNCTIONS', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001088
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001089 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001090 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001091 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001092 contents.append(self.docother(value, key, name, maxlen=70))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001093 result = result + self.section('DATA', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001094
1095 if hasattr(object, '__version__'):
1096 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001097 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001098 version = version[11:-1].strip()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001099 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001100 if hasattr(object, '__date__'):
1101 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001102 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001103 result = result + self.section('AUTHOR', str(object.__author__))
1104 if hasattr(object, '__credits__'):
1105 result = result + self.section('CREDITS', str(object.__credits__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001106 return result
1107
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001108 def docclass(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001109 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001110 realname = object.__name__
1111 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001112 bases = object.__bases__
1113
Tim Petersc86f6ca2001-09-26 21:31:51 +00001114 def makename(c, m=object.__module__):
1115 return classname(c, m)
1116
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001117 if name == realname:
1118 title = 'class ' + self.bold(realname)
1119 else:
1120 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001121 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001122 parents = map(makename, bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001123 title = title + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001124
1125 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001126 contents = doc and [doc + '\n'] or []
1127 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001128
Tim Petersc86f6ca2001-09-26 21:31:51 +00001129 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001130 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001131 if len(mro) > 2:
1132 push("Method resolution order:")
1133 for base in mro:
1134 push(' ' + makename(base))
1135 push('')
1136
Tim Petersf4aad8e2001-09-24 22:40:47 +00001137 # Cute little class to pump out a horizontal rule between sections.
1138 class HorizontalRule:
1139 def __init__(self):
1140 self.needone = 0
1141 def maybe(self):
1142 if self.needone:
1143 push('-' * 70)
1144 self.needone = 1
1145 hr = HorizontalRule()
1146
Tim Peters28355492001-09-23 21:29:55 +00001147 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001148 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001149 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001150 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001151 push(msg)
1152 for name, kind, homecls, value in ok:
1153 push(self.document(getattr(object, name),
1154 name, mod, object))
1155 return attrs
1156
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001157 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001158 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001159 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001160 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001161 push(msg)
1162 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001163 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001164 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001165
Tim Petersfa26f7c2001-09-24 08:05:11 +00001166 def spilldata(msg, attrs, predicate):
1167 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001168 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001169 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001170 push(msg)
1171 for name, kind, homecls, value in ok:
Martin v. Löwise59e2ba2003-05-03 09:09:02 +00001172 if callable(value) or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001173 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001174 else:
1175 doc = None
Tim Peters28355492001-09-23 21:29:55 +00001176 push(self.docother(getattr(object, name),
Georg Brandl8b813db2005-10-01 16:32:31 +00001177 name, mod, maxlen=70, doc=doc) + '\n')
Tim Peters28355492001-09-23 21:29:55 +00001178 return attrs
1179
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001180 attrs = [(name, kind, cls, value)
1181 for name, kind, cls, value in classify_class_attrs(object)
1182 if visiblename(name)]
1183
Tim Petersfa26f7c2001-09-24 08:05:11 +00001184 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001185 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001186 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001187 else:
1188 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001189 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1190
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001191 if thisclass is __builtin__.object:
1192 attrs = inherited
1193 continue
1194 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001195 tag = "defined here"
1196 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001197 tag = "inherited from %s" % classname(thisclass,
1198 object.__module__)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001199 filter(lambda t: not t[0].startswith('_'), attrs)
Tim Peters28355492001-09-23 21:29:55 +00001200
1201 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001202 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001203
1204 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001205 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001206 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001207 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001208 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001209 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001210 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001211 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1212 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001213 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1214 lambda t: t[1] == 'data')
Tim Peters28355492001-09-23 21:29:55 +00001215 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001216 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001217
1218 contents = '\n'.join(contents)
1219 if not contents:
1220 return title + '\n'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001221 return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001222
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001223 def formatvalue(self, object):
1224 """Format an argument default value as text."""
1225 return '=' + self.repr(object)
1226
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001227 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001228 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001229 realname = object.__name__
1230 name = name or realname
1231 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001232 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001233 if inspect.ismethod(object):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001234 imclass = object.im_class
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001235 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001236 if imclass is not cl:
1237 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001238 else:
Guido van Rossumd8faa362007-04-27 19:54:29 +00001239 if object.im_self is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001240 note = ' method of %s instance' % classname(
1241 object.im_self.__class__, mod)
1242 else:
1243 note = ' unbound %s method' % classname(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001244 object = object.im_func
1245
1246 if name == realname:
1247 title = self.bold(realname)
1248 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001249 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001250 cl.__dict__[realname] is object):
1251 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001252 title = self.bold(name) + ' = ' + realname
Tim Peters4bcfa312001-09-20 06:08:24 +00001253 if inspect.isfunction(object):
Guido van Rossum2e65f892007-02-28 22:03:49 +00001254 args, varargs, varkw, defaults, kwonlyargs, kwdefaults, ann = \
1255 inspect.getfullargspec(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001256 argspec = inspect.formatargspec(
Guido van Rossum2e65f892007-02-28 22:03:49 +00001257 args, varargs, varkw, defaults, kwonlyargs, kwdefaults, ann,
1258 formatvalue=self.formatvalue,
1259 formatannotation=inspect.formatannotationrelativeto(object))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001260 if realname == '<lambda>':
Georg Brandl501dd0d2006-02-17 09:45:40 +00001261 title = self.bold(name) + ' lambda '
Guido van Rossum2e65f892007-02-28 22:03:49 +00001262 # XXX lambda's won't usually have func_annotations['return']
1263 # since the syntax doesn't support but it is possible.
1264 # So removing parentheses isn't truly safe.
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001265 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +00001266 else:
1267 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001268 decl = title + argspec + note
1269
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001270 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001271 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001272 else:
1273 doc = getdoc(object) or ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001274 return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001275
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001276 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001277 results = []
1278 push = results.append
1279
1280 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001281 push(self.bold(name))
1282 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001283 doc = getdoc(value) or ''
1284 if doc:
1285 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001286 push('\n')
1287 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001288
1289 def docproperty(self, object, name=None, mod=None, cl=None):
1290 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001291 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001292
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001293 def docdata(self, object, name=None, mod=None, cl=None):
1294 """Produce text documentation for a data descriptor."""
1295 return self._docdescriptor(name, object, mod)
1296
Georg Brandl8b813db2005-10-01 16:32:31 +00001297 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001298 """Produce text documentation for a data object."""
1299 repr = self.repr(object)
1300 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001301 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001302 chop = maxlen - len(line)
1303 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001304 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001305 if doc is not None:
1306 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001307 return line
1308
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001309# --------------------------------------------------------- user interfaces
1310
1311def pager(text):
1312 """The first time this is called, determine what kind of pager to use."""
1313 global pager
1314 pager = getpager()
1315 pager(text)
1316
1317def getpager():
1318 """Decide what method to use for paging through text."""
1319 if type(sys.stdout) is not types.FileType:
1320 return plainpager
1321 if not sys.stdin.isatty() or not sys.stdout.isatty():
1322 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001323 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001324 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001325 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001326 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001327 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001328 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001329 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001330 if os.environ.get('TERM') in ('dumb', 'emacs'):
1331 return plainpager
Andrew MacIntyre54e0eab2002-03-03 03:12:30 +00001332 if sys.platform == 'win32' or sys.platform.startswith('os2'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001333 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001334 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001335 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001336
1337 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001338 (fd, filename) = tempfile.mkstemp()
1339 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001340 try:
1341 if hasattr(os, 'system') and os.system('more %s' % filename) == 0:
1342 return lambda text: pipepager(text, 'more')
1343 else:
1344 return ttypager
1345 finally:
1346 os.unlink(filename)
1347
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001348def plain(text):
1349 """Remove boldface formatting from text."""
1350 return re.sub('.\b', '', text)
1351
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001352def pipepager(text, cmd):
1353 """Page through text by feeding it to another program."""
1354 pipe = os.popen(cmd, 'w')
1355 try:
1356 pipe.write(text)
1357 pipe.close()
1358 except IOError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001359 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001360
1361def tempfilepager(text, cmd):
1362 """Page through text by invoking a program on a temporary file."""
1363 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001364 filename = tempfile.mktemp()
1365 file = open(filename, 'w')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001366 file.write(text)
1367 file.close()
1368 try:
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00001369 os.system(cmd + ' ' + filename)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001370 finally:
1371 os.unlink(filename)
1372
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001373def ttypager(text):
1374 """Page through text on a text terminal."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001375 lines = plain(text).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001376 try:
1377 import tty
1378 fd = sys.stdin.fileno()
1379 old = tty.tcgetattr(fd)
1380 tty.setcbreak(fd)
1381 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001382 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001383 tty = None
1384 getchar = lambda: sys.stdin.readline()[:-1][:1]
1385
1386 try:
1387 r = inc = os.environ.get('LINES', 25) - 1
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001388 sys.stdout.write('\n'.join(lines[:inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001389 while lines[r:]:
1390 sys.stdout.write('-- more --')
1391 sys.stdout.flush()
1392 c = getchar()
1393
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001394 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001395 sys.stdout.write('\r \r')
1396 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001397 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001398 sys.stdout.write('\r \r' + lines[r] + '\n')
1399 r = r + 1
1400 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001401 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001402 r = r - inc - inc
1403 if r < 0: r = 0
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001404 sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001405 r = r + inc
1406
1407 finally:
1408 if tty:
1409 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1410
1411def plainpager(text):
1412 """Simply print unformatted text. This is the ultimate fallback."""
1413 sys.stdout.write(plain(text))
1414
1415def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001416 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001417 if inspect.ismodule(thing):
1418 if thing.__name__ in sys.builtin_module_names:
1419 return 'built-in module ' + thing.__name__
1420 if hasattr(thing, '__path__'):
1421 return 'package ' + thing.__name__
1422 else:
1423 return 'module ' + thing.__name__
1424 if inspect.isbuiltin(thing):
1425 return 'built-in function ' + thing.__name__
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001426 if inspect.isgetsetdescriptor(thing):
1427 return 'getset descriptor %s.%s.%s' % (
1428 thing.__objclass__.__module__, thing.__objclass__.__name__,
1429 thing.__name__)
1430 if inspect.ismemberdescriptor(thing):
1431 return 'member descriptor %s.%s.%s' % (
1432 thing.__objclass__.__module__, thing.__objclass__.__name__,
1433 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001434 if inspect.isclass(thing):
1435 return 'class ' + thing.__name__
1436 if inspect.isfunction(thing):
1437 return 'function ' + thing.__name__
1438 if inspect.ismethod(thing):
1439 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001440 return type(thing).__name__
1441
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001442def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001443 """Locate an object by name or dotted path, importing as necessary."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001444 parts = [part for part in path.split('.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001445 module, n = None, 0
1446 while n < len(parts):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001447 nextmodule = safeimport('.'.join(parts[:n+1]), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001448 if nextmodule: module, n = nextmodule, n + 1
1449 else: break
1450 if module:
1451 object = module
1452 for part in parts[n:]:
1453 try: object = getattr(object, part)
1454 except AttributeError: return None
1455 return object
1456 else:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001457 if hasattr(__builtin__, path):
1458 return getattr(__builtin__, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001459
1460# --------------------------------------- interactive interpreter interface
1461
1462text = TextDoc()
1463html = HTMLDoc()
1464
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001465def resolve(thing, forceload=0):
1466 """Given an object or a path to an object, get the object and its name."""
1467 if isinstance(thing, str):
1468 object = locate(thing, forceload)
1469 if not object:
1470 raise ImportError, 'no Python documentation found for %r' % thing
1471 return object, thing
1472 else:
1473 return thing, getattr(thing, '__name__', None)
1474
Guido van Rossumd8faa362007-04-27 19:54:29 +00001475def render_doc(thing, title='Python Library Documentation: %s', forceload=0):
1476 """Render text documentation, given an object or a path to an object."""
1477 object, name = resolve(thing, forceload)
1478 desc = describe(object)
1479 module = inspect.getmodule(object)
1480 if name and '.' in name:
1481 desc += ' in ' + name[:name.rfind('.')]
1482 elif module and module is not object:
1483 desc += ' in module ' + module.__name__
1484 elif not (inspect.ismodule(object) or
1485 inspect.isclass(object) or
1486 inspect.isroutine(object) or
1487 inspect.isgetsetdescriptor(object) or
1488 inspect.ismemberdescriptor(object) or
1489 isinstance(object, property)):
1490 # If the passed object is a piece of data or an instance,
1491 # document its available methods instead of its value.
1492 object = type(object)
1493 desc += ' object'
1494 return title % desc + '\n\n' + text.document(object, name)
1495
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001496def doc(thing, title='Python Library Documentation: %s', forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001497 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001498 try:
1499 object, name = resolve(thing, forceload)
1500 desc = describe(object)
1501 module = inspect.getmodule(object)
1502 if name and '.' in name:
1503 desc += ' in ' + name[:name.rfind('.')]
1504 elif module and module is not object:
1505 desc += ' in module ' + module.__name__
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +00001506 elif not (inspect.ismodule(object) or
1507 inspect.isclass(object) or
1508 inspect.isroutine(object) or
1509 inspect.isgetsetdescriptor(object) or
1510 inspect.ismemberdescriptor(object) or
1511 isinstance(object, property)):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001512 # If the passed object is a piece of data or an instance,
1513 # document its available methods instead of its value.
1514 object = type(object)
1515 desc += ' object'
Guido van Rossumd8faa362007-04-27 19:54:29 +00001516 pager(render_doc(thing, title, forceload))
Guido van Rossumb940e112007-01-10 16:19:56 +00001517 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001518 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001519
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001520def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001521 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001522 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001523 object, name = resolve(thing, forceload)
1524 page = html.page(describe(object), html.document(object, name))
1525 file = open(name + '.html', 'w')
1526 file.write(page)
1527 file.close()
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001528 print('wrote', name + '.html')
Guido van Rossumb940e112007-01-10 16:19:56 +00001529 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001530 print(value)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001531
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001532def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001533 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001534 if done is None: done = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001535 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1536 writedoc(modname)
1537 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001538
Neal Norwitzce96f692006-03-17 06:49:51 +00001539def raw_input(prompt):
1540 sys.stdout.write(prompt)
1541 sys.stdout.flush()
1542 return sys.stdin.readline()
1543
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001544class Helper:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001545 keywords = {
1546 'and': 'BOOLEAN',
Guido van Rossumd8faa362007-04-27 19:54:29 +00001547 'as': 'with',
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001548 'assert': ('ref/assert', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001549 'break': ('ref/break', 'while for'),
1550 'class': ('ref/class', 'CLASSES SPECIALMETHODS'),
1551 'continue': ('ref/continue', 'while for'),
1552 'def': ('ref/function', ''),
1553 'del': ('ref/del', 'BASICMETHODS'),
1554 'elif': 'if',
1555 'else': ('ref/if', 'while for'),
1556 'except': 'try',
1557 'exec': ('ref/exec', ''),
1558 'finally': 'try',
1559 'for': ('ref/for', 'break continue while'),
1560 'from': 'import',
1561 'global': ('ref/global', 'NAMESPACES'),
1562 'if': ('ref/if', 'TRUTHVALUE'),
1563 'import': ('ref/import', 'MODULES'),
1564 'in': ('ref/comparisons', 'SEQUENCEMETHODS2'),
1565 'is': 'COMPARISON',
Neal Norwitz742dde42003-03-30 20:31:34 +00001566 'lambda': ('ref/lambdas', 'FUNCTIONS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001567 'not': 'BOOLEAN',
1568 'or': 'BOOLEAN',
Neal Norwitz742dde42003-03-30 20:31:34 +00001569 'pass': ('ref/pass', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001570 'print': ('ref/print', ''),
1571 'raise': ('ref/raise', 'EXCEPTIONS'),
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001572 'return': ('ref/return', 'FUNCTIONS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001573 'try': ('ref/try', 'EXCEPTIONS'),
1574 'while': ('ref/while', 'break continue if TRUTHVALUE'),
Guido van Rossumd8faa362007-04-27 19:54:29 +00001575 'with': ('ref/with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
Tim Petersfb05c4e2002-10-30 05:21:00 +00001576 'yield': ('ref/yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001577 }
1578
1579 topics = {
1580 'TYPES': ('ref/types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS FUNCTIONS CLASSES MODULES FILES inspect'),
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001581 'STRINGS': ('ref/strings', 'str UNICODE SEQUENCES STRINGMETHODS FORMATTING TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001582 'STRINGMETHODS': ('lib/string-methods', 'STRINGS FORMATTING'),
1583 'FORMATTING': ('lib/typesseq-strings', 'OPERATORS'),
Neal Norwitz54f871e2003-05-26 13:49:54 +00001584 'UNICODE': ('ref/strings', 'encodings unicode SEQUENCES STRINGMETHODS FORMATTING TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001585 'NUMBERS': ('ref/numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1586 'INTEGER': ('ref/integers', 'int range'),
1587 'FLOAT': ('ref/floating', 'float math'),
1588 'COMPLEX': ('ref/imaginary', 'complex cmath'),
Guido van Rossum805365e2007-05-07 22:24:25 +00001589 'SEQUENCES': ('lib/typesseq', 'STRINGMETHODS FORMATTING range LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001590 'MAPPINGS': 'DICTIONARIES',
1591 'FUNCTIONS': ('lib/typesfunctions', 'def TYPES'),
1592 'METHODS': ('lib/typesmethods', 'class def CLASSES TYPES'),
1593 'CODEOBJECTS': ('lib/bltin-code-objects', 'compile FUNCTIONS TYPES'),
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001594 'TYPEOBJECTS': ('lib/bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001595 'FRAMEOBJECTS': 'TYPES',
1596 'TRACEBACKS': 'TYPES',
1597 'NONE': ('lib/bltin-null-object', ''),
1598 'ELLIPSIS': ('lib/bltin-ellipsis-object', 'SLICINGS'),
1599 'FILES': ('lib/bltin-file-objects', ''),
1600 'SPECIALATTRIBUTES': ('lib/specialattrs', ''),
1601 'CLASSES': ('ref/types', 'class SPECIALMETHODS PRIVATENAMES'),
1602 'MODULES': ('lib/typesmodules', 'import'),
1603 'PACKAGES': 'import',
Neal Norwitz2eca4402006-08-29 04:40:24 +00001604 'EXPRESSIONS': ('ref/summary', 'lambda or and not in is BOOLEAN COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES LISTS DICTIONARIES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001605 'OPERATORS': 'EXPRESSIONS',
1606 'PRECEDENCE': 'EXPRESSIONS',
1607 'OBJECTS': ('ref/objects', 'TYPES'),
1608 'SPECIALMETHODS': ('ref/specialnames', 'BASICMETHODS ATTRIBUTEMETHODS CALLABLEMETHODS SEQUENCEMETHODS1 MAPPINGMETHODS SEQUENCEMETHODS2 NUMBERMETHODS CLASSES'),
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001609 'BASICMETHODS': ('ref/customization', 'cmp hash repr str SPECIALMETHODS'),
1610 'ATTRIBUTEMETHODS': ('ref/attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1611 'CALLABLEMETHODS': ('ref/callable-types', 'CALLS SPECIALMETHODS'),
1612 'SEQUENCEMETHODS1': ('ref/sequence-types', 'SEQUENCES SEQUENCEMETHODS2 SPECIALMETHODS'),
1613 'SEQUENCEMETHODS2': ('ref/sequence-methods', 'SEQUENCES SEQUENCEMETHODS1 SPECIALMETHODS'),
1614 'MAPPINGMETHODS': ('ref/sequence-types', 'MAPPINGS SPECIALMETHODS'),
1615 'NUMBERMETHODS': ('ref/numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT SPECIALMETHODS'),
Neal Norwitz54f871e2003-05-26 13:49:54 +00001616 'EXECUTION': ('ref/execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
1617 'NAMESPACES': ('ref/naming', 'global ASSIGNMENT DELETION DYNAMICFEATURES'),
1618 'DYNAMICFEATURES': ('ref/dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001619 'SCOPING': 'NAMESPACES',
1620 'FRAMES': 'NAMESPACES',
1621 'EXCEPTIONS': ('ref/exceptions', 'try except finally raise'),
Neal Norwitz54f871e2003-05-26 13:49:54 +00001622 'COERCIONS': ('ref/coercion-rules','CONVERSIONS'),
1623 'CONVERSIONS': ('ref/conversions', 'COERCIONS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001624 'IDENTIFIERS': ('ref/identifiers', 'keywords SPECIALIDENTIFIERS'),
1625 'SPECIALIDENTIFIERS': ('ref/id-classes', ''),
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001626 'PRIVATENAMES': ('ref/atom-identifiers', ''),
Neal Norwitz2eca4402006-08-29 04:40:24 +00001627 'LITERALS': ('ref/atom-literals', 'STRINGS NUMBERS TUPLELITERALS LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001628 'TUPLES': 'SEQUENCES',
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001629 'TUPLELITERALS': ('ref/exprlists', 'TUPLES LITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001630 'LISTS': ('lib/typesseq-mutable', 'LISTLITERALS'),
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001631 'LISTLITERALS': ('ref/lists', 'LISTS LITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001632 'DICTIONARIES': ('lib/typesmapping', 'DICTIONARYLITERALS'),
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001633 'DICTIONARYLITERALS': ('ref/dict', 'DICTIONARIES LITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001634 'ATTRIBUTES': ('ref/attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
1635 'SUBSCRIPTS': ('ref/subscriptions', 'SEQUENCEMETHODS1'),
1636 'SLICINGS': ('ref/slicings', 'SEQUENCEMETHODS2'),
1637 'CALLS': ('ref/calls', 'EXPRESSIONS'),
1638 'POWER': ('ref/power', 'EXPRESSIONS'),
1639 'UNARY': ('ref/unary', 'EXPRESSIONS'),
1640 'BINARY': ('ref/binary', 'EXPRESSIONS'),
1641 'SHIFTING': ('ref/shifting', 'EXPRESSIONS'),
1642 'BITWISE': ('ref/bitwise', 'EXPRESSIONS'),
1643 'COMPARISON': ('ref/comparisons', 'EXPRESSIONS BASICMETHODS'),
Neal Norwitzf98159c2003-02-07 20:49:40 +00001644 'BOOLEAN': ('ref/Booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001645 'ASSERTION': 'assert',
1646 'ASSIGNMENT': ('ref/assignment', 'AUGMENTEDASSIGNMENT'),
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001647 'AUGMENTEDASSIGNMENT': ('ref/augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001648 'DELETION': 'del',
1649 'PRINTING': 'print',
1650 'RETURNING': 'return',
1651 'IMPORTING': 'import',
1652 'CONDITIONAL': 'if',
1653 'LOOPING': ('ref/compound', 'for while break continue'),
1654 'TRUTHVALUE': ('lib/truth', 'if while and or not BASICMETHODS'),
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001655 'DEBUGGING': ('lib/module-pdb', 'pdb'),
Guido van Rossumd8faa362007-04-27 19:54:29 +00001656 'CONTEXTMANAGERS': ('ref/context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001657 }
1658
1659 def __init__(self, input, output):
1660 self.input = input
1661 self.output = output
1662 self.docdir = None
1663 execdir = os.path.dirname(sys.executable)
1664 homedir = os.environ.get('PYTHONHOME')
Guido van Rossumd8faa362007-04-27 19:54:29 +00001665 join = os.path.join
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001666 for dir in [os.environ.get('PYTHONDOCS'),
1667 homedir and os.path.join(homedir, 'doc'),
Guido van Rossumd8faa362007-04-27 19:54:29 +00001668 join(execdir, 'doc'), # for Windows
1669 join(sys.prefix, 'doc/python-docs-' + sys.version.split()[0]),
1670 join(sys.prefix, 'doc/python-' + sys.version.split()[0]),
1671 join(sys.prefix, 'doc/python-docs-' + sys.version[:3]),
1672 join(sys.prefix, 'doc/python-' + sys.version[:3]),
1673 join(sys.prefix, 'Resources/English.lproj/Documentation')]:
1674 if dir and os.path.isdir(join(dir, 'lib')):
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001675 self.docdir = dir
Guido van Rossumd8faa362007-04-27 19:54:29 +00001676 break
1677 if dir and os.path.isdir(join(dir, 'html', 'lib')):
1678 self.docdir = join(dir, 'html')
1679 break
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001680
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001681 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001682 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001683 self()
1684 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001685 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001686
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001687 def __call__(self, request=None):
1688 if request is not None:
1689 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001690 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001691 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001692 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001693 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001694You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001695If you want to ask for help on a particular object directly from the
1696interpreter, you can type "help(object)". Executing "help('string')"
1697has the same effect as typing a particular string at the help> prompt.
1698''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001699
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001700 def interact(self):
1701 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001702 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001703 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001704 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001705 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001706 except (KeyboardInterrupt, EOFError):
1707 break
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001708 request = replace(request, '"', '', "'", '').strip()
1709 if request.lower() in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001710 self.help(request)
1711
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001712 def getline(self, prompt):
1713 """Read one line, using raw_input when available."""
1714 if self.input is sys.stdin:
1715 return raw_input(prompt)
1716 else:
1717 self.output.write(prompt)
1718 self.output.flush()
1719 return self.input.readline()
1720
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001721 def help(self, request):
1722 if type(request) is type(''):
1723 if request == 'help': self.intro()
1724 elif request == 'keywords': self.listkeywords()
1725 elif request == 'topics': self.listtopics()
1726 elif request == 'modules': self.listmodules()
1727 elif request[:8] == 'modules ':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001728 self.listmodules(request.split()[1])
Raymond Hettinger54f02222002-06-01 14:18:47 +00001729 elif request in self.keywords: self.showtopic(request)
1730 elif request in self.topics: self.showtopic(request)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001731 elif request: doc(request, 'Help on %s:')
1732 elif isinstance(request, Helper): self()
1733 else: doc(request, 'Help on %s:')
1734 self.output.write('\n')
1735
1736 def intro(self):
1737 self.output.write('''
1738Welcome to Python %s! This is the online help utility.
1739
1740If this is your first time using Python, you should definitely check out
1741the tutorial on the Internet at http://www.python.org/doc/tut/.
1742
1743Enter the name of any module, keyword, or topic to get help on writing
1744Python programs and using Python modules. To quit this help utility and
1745return to the interpreter, just type "quit".
1746
1747To get a list of available modules, keywords, or topics, type "modules",
1748"keywords", or "topics". Each module also comes with a one-line summary
1749of what it does; to list the modules whose summaries contain a given word
1750such as "spam", type "modules spam".
1751''' % sys.version[:3])
1752
1753 def list(self, items, columns=4, width=80):
1754 items = items[:]
1755 items.sort()
1756 colw = width / columns
1757 rows = (len(items) + columns - 1) / columns
1758 for row in range(rows):
1759 for col in range(columns):
1760 i = col * rows + row
1761 if i < len(items):
1762 self.output.write(items[i])
1763 if col < columns - 1:
1764 self.output.write(' ' + ' ' * (colw-1 - len(items[i])))
1765 self.output.write('\n')
1766
1767 def listkeywords(self):
1768 self.output.write('''
1769Here is a list of the Python keywords. Enter any keyword to get more help.
1770
1771''')
1772 self.list(self.keywords.keys())
1773
1774 def listtopics(self):
1775 self.output.write('''
1776Here is a list of available topics. Enter any topic name to get more help.
1777
1778''')
1779 self.list(self.topics.keys())
1780
1781 def showtopic(self, topic):
1782 if not self.docdir:
1783 self.output.write('''
1784Sorry, topic and keyword documentation is not available because the Python
1785HTML documentation files could not be found. If you have installed them,
1786please set the environment variable PYTHONDOCS to indicate their location.
Thomas Wouters902d6eb2007-01-09 23:18:33 +00001787
1788On the Microsoft Windows operating system, the files can be built by
1789running "hh -decompile . PythonNN.chm" in the C:\PythonNN\Doc> directory.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001790''')
1791 return
1792 target = self.topics.get(topic, self.keywords.get(topic))
1793 if not target:
1794 self.output.write('no documentation found for %s\n' % repr(topic))
1795 return
1796 if type(target) is type(''):
1797 return self.showtopic(target)
1798
1799 filename, xrefs = target
1800 filename = self.docdir + '/' + filename + '.html'
1801 try:
1802 file = open(filename)
1803 except:
1804 self.output.write('could not read docs from %s\n' % filename)
1805 return
1806
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001807 divpat = re.compile('<div[^>]*navigat.*?</div.*?>', re.I | re.S)
1808 addrpat = re.compile('<address.*?>.*?</address.*?>', re.I | re.S)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001809 document = re.sub(addrpat, '', re.sub(divpat, '', file.read()))
1810 file.close()
1811
1812 import htmllib, formatter, StringIO
1813 buffer = StringIO.StringIO()
1814 parser = htmllib.HTMLParser(
1815 formatter.AbstractFormatter(formatter.DumbWriter(buffer)))
1816 parser.start_table = parser.do_p
1817 parser.end_table = lambda parser=parser: parser.do_p({})
1818 parser.start_tr = parser.do_br
1819 parser.start_td = parser.start_th = lambda a, b=buffer: b.write('\t')
1820 parser.feed(document)
1821 buffer = replace(buffer.getvalue(), '\xa0', ' ', '\n', '\n ')
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001822 pager(' ' + buffer.strip() + '\n')
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001823 if xrefs:
1824 buffer = StringIO.StringIO()
1825 formatter.DumbWriter(buffer).send_flowing_data(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001826 'Related help topics: ' + ', '.join(xrefs.split()) + '\n')
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001827 self.output.write('\n%s\n' % buffer.getvalue())
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001828
1829 def listmodules(self, key=''):
1830 if key:
1831 self.output.write('''
1832Here is a list of matching modules. Enter any module name to get more help.
1833
1834''')
1835 apropos(key)
1836 else:
1837 self.output.write('''
1838Please wait a moment while I gather a list of all available modules...
1839
1840''')
1841 modules = {}
1842 def callback(path, modname, desc, modules=modules):
1843 if modname and modname[-9:] == '.__init__':
1844 modname = modname[:-9] + ' (package)'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001845 if modname.find('.') < 0:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001846 modules[modname] = 1
1847 ModuleScanner().run(callback)
1848 self.list(modules.keys())
1849 self.output.write('''
1850Enter any module name to get more help. Or, type "modules spam" to search
1851for modules whose descriptions contain the word "spam".
1852''')
1853
1854help = Helper(sys.stdin, sys.stdout)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001855
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001856class Scanner:
1857 """A generic tree iterator."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001858 def __init__(self, roots, children, descendp):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001859 self.roots = roots[:]
1860 self.state = []
1861 self.children = children
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001862 self.descendp = descendp
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001863
1864 def next(self):
1865 if not self.state:
1866 if not self.roots:
1867 return None
1868 root = self.roots.pop(0)
1869 self.state = [(root, self.children(root))]
1870 node, children = self.state[-1]
1871 if not children:
1872 self.state.pop()
1873 return self.next()
1874 child = children.pop(0)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001875 if self.descendp(child):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001876 self.state.append((child, self.children(child)))
1877 return child
1878
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001879
1880class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001881 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001882
Ka-Ping Yee66246962001-04-12 11:59:50 +00001883 def run(self, callback, key=None, completer=None):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001884 if key: key = key.lower()
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001885 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001886 seen = {}
1887
1888 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001889 if modname != '__main__':
1890 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00001891 if key is None:
1892 callback(None, modname, '')
1893 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001894 name = __import__(modname).__doc__ or ''
1895 desc = name.split('\n')[0]
1896 name = modname + ' - ' + desc
1897 if name.lower().find(key) >= 0:
Ka-Ping Yee66246962001-04-12 11:59:50 +00001898 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001899
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001900 for importer, modname, ispkg in pkgutil.walk_packages():
1901 if self.quit:
1902 break
1903 if key is None:
1904 callback(None, modname, '')
1905 else:
1906 loader = importer.find_module(modname)
1907 if hasattr(loader,'get_source'):
1908 import StringIO
1909 desc = source_synopsis(
1910 StringIO.StringIO(loader.get_source(modname))
1911 ) or ''
1912 if hasattr(loader,'get_filename'):
1913 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00001914 else:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001915 path = None
1916 else:
1917 module = loader.load_module(modname)
1918 desc = (module.__doc__ or '').splitlines()[0]
1919 path = getattr(module,'__file__',None)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001920 name = modname + ' - ' + desc
1921 if name.lower().find(key) >= 0:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001922 callback(path, modname, desc)
1923
1924 if completer:
1925 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001926
1927def apropos(key):
1928 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001929 def callback(path, modname, desc):
1930 if modname[-9:] == '.__init__':
1931 modname = modname[:-9] + ' (package)'
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001932 print(modname, desc and '- ' + desc)
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001933 try: import warnings
1934 except ImportError: pass
1935 else: warnings.filterwarnings('ignore') # ignore problems during import
Ka-Ping Yee66246962001-04-12 11:59:50 +00001936 ModuleScanner().run(callback, key)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001937
1938# --------------------------------------------------- web browser interface
1939
Ka-Ping Yee66246962001-04-12 11:59:50 +00001940def serve(port, callback=None, completer=None):
Ka-Ping Yeefd540692001-04-12 12:54:36 +00001941 import BaseHTTPServer, mimetools, select
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001942
1943 # Patch up mimetools.Message so it doesn't break if rfc822 is reloaded.
1944 class Message(mimetools.Message):
1945 def __init__(self, fp, seekable=1):
1946 Message = self.__class__
1947 Message.__bases__[0].__bases__[0].__init__(self, fp, seekable)
1948 self.encodingheader = self.getheader('content-transfer-encoding')
1949 self.typeheader = self.getheader('content-type')
1950 self.parsetype()
1951 self.parseplist()
1952
1953 class DocHandler(BaseHTTPServer.BaseHTTPRequestHandler):
1954 def send_document(self, title, contents):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001955 try:
1956 self.send_response(200)
1957 self.send_header('Content-Type', 'text/html')
1958 self.end_headers()
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001959 self.wfile.write(html.page(title, contents))
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001960 except IOError: pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001961
1962 def do_GET(self):
1963 path = self.path
1964 if path[-5:] == '.html': path = path[:-5]
1965 if path[:1] == '/': path = path[1:]
1966 if path and path != '.':
1967 try:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001968 obj = locate(path, forceload=1)
Guido van Rossumb940e112007-01-10 16:19:56 +00001969 except ErrorDuringImport as value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001970 self.send_document(path, html.escape(str(value)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001971 return
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001972 if obj:
1973 self.send_document(describe(obj), html.document(obj, path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001974 else:
1975 self.send_document(path,
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001976'no Python documentation found for %s' % repr(path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001977 else:
1978 heading = html.heading(
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001979'<big><big><strong>Python: Index of Modules</strong></big></big>',
1980'#ffffff', '#7799ee')
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001981 def bltinlink(name):
1982 return '<a href="%s.html">%s</a>' % (name, name)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001983 names = filter(lambda x: x != '__main__',
1984 sys.builtin_module_names)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001985 contents = html.multicolumn(names, bltinlink)
1986 indices = ['<p>' + html.bigsection(
1987 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
1988
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001989 seen = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001990 for dir in sys.path:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001991 indices.append(html.index(dir, seen))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001992 contents = heading + ' '.join(indices) + '''<p align=right>
Tim Peters2306d242001-09-25 03:18:32 +00001993<font color="#909090" face="helvetica, arial"><strong>
1994pydoc</strong> by Ka-Ping Yee &lt;ping@lfw.org&gt;</font>'''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001995 self.send_document('Index of Modules', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001996
1997 def log_message(self, *args): pass
1998
Ka-Ping Yeefd540692001-04-12 12:54:36 +00001999 class DocServer(BaseHTTPServer.HTTPServer):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002000 def __init__(self, port, callback):
Ka-Ping Yeedb8ed152001-03-02 05:58:17 +00002001 host = (sys.platform == 'mac') and '127.0.0.1' or 'localhost'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002002 self.address = ('', port)
Ka-Ping Yeedb8ed152001-03-02 05:58:17 +00002003 self.url = 'http://%s:%d/' % (host, port)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002004 self.callback = callback
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002005 self.base.__init__(self, self.address, self.handler)
2006
2007 def serve_until_quit(self):
2008 import select
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002009 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002010 while not self.quit:
2011 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2012 if rd: self.handle_request()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002013
2014 def server_activate(self):
2015 self.base.server_activate(self)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002016 if self.callback: self.callback(self)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002017
2018 DocServer.base = BaseHTTPServer.HTTPServer
2019 DocServer.handler = DocHandler
2020 DocHandler.MessageClass = Message
2021 try:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002022 try:
2023 DocServer(port, callback).serve_until_quit()
2024 except (KeyboardInterrupt, select.error):
2025 pass
2026 finally:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002027 if completer: completer()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002028
2029# ----------------------------------------------------- graphical interface
2030
2031def gui():
2032 """Graphical interface (starts web server and pops up a control window)."""
2033 class GUI:
2034 def __init__(self, window, port=7464):
2035 self.window = window
2036 self.server = None
2037 self.scanner = None
2038
2039 import Tkinter
2040 self.server_frm = Tkinter.Frame(window)
2041 self.title_lbl = Tkinter.Label(self.server_frm,
2042 text='Starting server...\n ')
2043 self.open_btn = Tkinter.Button(self.server_frm,
2044 text='open browser', command=self.open, state='disabled')
2045 self.quit_btn = Tkinter.Button(self.server_frm,
2046 text='quit serving', command=self.quit, state='disabled')
2047
2048 self.search_frm = Tkinter.Frame(window)
2049 self.search_lbl = Tkinter.Label(self.search_frm, text='Search for')
2050 self.search_ent = Tkinter.Entry(self.search_frm)
2051 self.search_ent.bind('<Return>', self.search)
2052 self.stop_btn = Tkinter.Button(self.search_frm,
2053 text='stop', pady=0, command=self.stop, state='disabled')
2054 if sys.platform == 'win32':
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002055 # Trying to hide and show this button crashes under Windows.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002056 self.stop_btn.pack(side='right')
2057
2058 self.window.title('pydoc')
2059 self.window.protocol('WM_DELETE_WINDOW', self.quit)
2060 self.title_lbl.pack(side='top', fill='x')
2061 self.open_btn.pack(side='left', fill='x', expand=1)
2062 self.quit_btn.pack(side='right', fill='x', expand=1)
2063 self.server_frm.pack(side='top', fill='x')
2064
2065 self.search_lbl.pack(side='left')
2066 self.search_ent.pack(side='right', fill='x', expand=1)
2067 self.search_frm.pack(side='top', fill='x')
2068 self.search_ent.focus_set()
2069
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002070 font = ('helvetica', sys.platform == 'win32' and 8 or 10)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002071 self.result_lst = Tkinter.Listbox(window, font=font, height=6)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002072 self.result_lst.bind('<Button-1>', self.select)
2073 self.result_lst.bind('<Double-Button-1>', self.goto)
2074 self.result_scr = Tkinter.Scrollbar(window,
2075 orient='vertical', command=self.result_lst.yview)
2076 self.result_lst.config(yscrollcommand=self.result_scr.set)
2077
2078 self.result_frm = Tkinter.Frame(window)
2079 self.goto_btn = Tkinter.Button(self.result_frm,
2080 text='go to selected', command=self.goto)
2081 self.hide_btn = Tkinter.Button(self.result_frm,
2082 text='hide results', command=self.hide)
2083 self.goto_btn.pack(side='left', fill='x', expand=1)
2084 self.hide_btn.pack(side='right', fill='x', expand=1)
2085
2086 self.window.update()
2087 self.minwidth = self.window.winfo_width()
2088 self.minheight = self.window.winfo_height()
2089 self.bigminheight = (self.server_frm.winfo_reqheight() +
2090 self.search_frm.winfo_reqheight() +
2091 self.result_lst.winfo_reqheight() +
2092 self.result_frm.winfo_reqheight())
2093 self.bigwidth, self.bigheight = self.minwidth, self.bigminheight
2094 self.expanded = 0
2095 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2096 self.window.wm_minsize(self.minwidth, self.minheight)
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002097 self.window.tk.willdispatch()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002098
2099 import threading
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002100 threading.Thread(
2101 target=serve, args=(port, self.ready, self.quit)).start()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002102
2103 def ready(self, server):
2104 self.server = server
2105 self.title_lbl.config(
2106 text='Python documentation server at\n' + server.url)
2107 self.open_btn.config(state='normal')
2108 self.quit_btn.config(state='normal')
2109
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002110 def open(self, event=None, url=None):
2111 url = url or self.server.url
2112 try:
2113 import webbrowser
2114 webbrowser.open(url)
2115 except ImportError: # pre-webbrowser.py compatibility
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002116 if sys.platform == 'win32':
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002117 os.system('start "%s"' % url)
2118 elif sys.platform == 'mac':
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002119 try: import ic
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002120 except ImportError: pass
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002121 else: ic.launchurl(url)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002122 else:
2123 rc = os.system('netscape -remote "openURL(%s)" &' % url)
2124 if rc: os.system('netscape "%s" &' % url)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002125
2126 def quit(self, event=None):
2127 if self.server:
2128 self.server.quit = 1
2129 self.window.quit()
2130
2131 def search(self, event=None):
2132 key = self.search_ent.get()
2133 self.stop_btn.pack(side='right')
2134 self.stop_btn.config(state='normal')
2135 self.search_lbl.config(text='Searching for "%s"...' % key)
2136 self.search_ent.forget()
2137 self.search_lbl.pack(side='left')
2138 self.result_lst.delete(0, 'end')
2139 self.goto_btn.config(state='disabled')
2140 self.expand()
2141
2142 import threading
2143 if self.scanner:
2144 self.scanner.quit = 1
2145 self.scanner = ModuleScanner()
2146 threading.Thread(target=self.scanner.run,
Ka-Ping Yee6dcfa382001-04-12 20:27:31 +00002147 args=(self.update, key, self.done)).start()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002148
2149 def update(self, path, modname, desc):
2150 if modname[-9:] == '.__init__':
2151 modname = modname[:-9] + ' (package)'
2152 self.result_lst.insert('end',
2153 modname + ' - ' + (desc or '(no description)'))
2154
2155 def stop(self, event=None):
2156 if self.scanner:
2157 self.scanner.quit = 1
2158 self.scanner = None
2159
2160 def done(self):
2161 self.scanner = None
2162 self.search_lbl.config(text='Search for')
2163 self.search_lbl.pack(side='left')
2164 self.search_ent.pack(side='right', fill='x', expand=1)
2165 if sys.platform != 'win32': self.stop_btn.forget()
2166 self.stop_btn.config(state='disabled')
2167
2168 def select(self, event=None):
2169 self.goto_btn.config(state='normal')
2170
2171 def goto(self, event=None):
2172 selection = self.result_lst.curselection()
2173 if selection:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002174 modname = self.result_lst.get(selection[0]).split()[0]
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002175 self.open(url=self.server.url + modname + '.html')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002176
2177 def collapse(self):
2178 if not self.expanded: return
2179 self.result_frm.forget()
2180 self.result_scr.forget()
2181 self.result_lst.forget()
2182 self.bigwidth = self.window.winfo_width()
2183 self.bigheight = self.window.winfo_height()
2184 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2185 self.window.wm_minsize(self.minwidth, self.minheight)
2186 self.expanded = 0
2187
2188 def expand(self):
2189 if self.expanded: return
2190 self.result_frm.pack(side='bottom', fill='x')
2191 self.result_scr.pack(side='right', fill='y')
2192 self.result_lst.pack(side='top', fill='both', expand=1)
2193 self.window.wm_geometry('%dx%d' % (self.bigwidth, self.bigheight))
2194 self.window.wm_minsize(self.minwidth, self.bigminheight)
2195 self.expanded = 1
2196
2197 def hide(self, event=None):
2198 self.stop()
2199 self.collapse()
2200
2201 import Tkinter
2202 try:
Martin v. Löwise09bd932004-08-22 16:13:26 +00002203 root = Tkinter.Tk()
2204 # Tk will crash if pythonw.exe has an XP .manifest
2205 # file and the root has is not destroyed explicitly.
2206 # If the problem is ever fixed in Tk, the explicit
2207 # destroy can go.
2208 try:
2209 gui = GUI(root)
2210 root.mainloop()
2211 finally:
2212 root.destroy()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002213 except KeyboardInterrupt:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002214 pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002215
2216# -------------------------------------------------- command-line interface
2217
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002218def ispath(x):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002219 return isinstance(x, str) and x.find(os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002220
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002221def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002222 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002223 import getopt
Guido van Rossum756aa932007-04-07 03:04:01 +00002224 class BadUsage(Exception): pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002225
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002226 # Scripts don't get the current directory in their path by default.
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +00002227 scriptdir = os.path.dirname(sys.argv[0])
2228 if scriptdir in sys.path:
2229 sys.path.remove(scriptdir)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002230 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002231
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002232 try:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002233 opts, args = getopt.getopt(sys.argv[1:], 'gk:p:w')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002234 writing = 0
2235
2236 for opt, val in opts:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002237 if opt == '-g':
2238 gui()
2239 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002240 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002241 apropos(val)
2242 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002243 if opt == '-p':
2244 try:
2245 port = int(val)
2246 except ValueError:
2247 raise BadUsage
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002248 def ready(server):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002249 print('pydoc server ready at %s' % server.url)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002250 def stopped():
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002251 print('pydoc server stopped')
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002252 serve(port, ready, stopped)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002253 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002254 if opt == '-w':
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002255 writing = 1
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002256
2257 if not args: raise BadUsage
2258 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002259 if ispath(arg) and not os.path.exists(arg):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002260 print('file %r does not exist' % arg)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002261 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002262 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002263 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002264 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002265 if writing:
2266 if ispath(arg) and os.path.isdir(arg):
2267 writedocs(arg)
2268 else:
2269 writedoc(arg)
2270 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002271 help.help(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +00002272 except ErrorDuringImport as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002273 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002274
2275 except (getopt.error, BadUsage):
Martin v. Löwisf9b08b82003-10-31 13:05:21 +00002276 cmd = os.path.basename(sys.argv[0])
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002277 print("""pydoc - the Python documentation tool
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002278
2279%s <name> ...
2280 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002281 Python keyword, topic, function, module, or package, or a dotted
2282 reference to a class or function within a module or module in a
2283 package. If <name> contains a '%s', it is used as the path to a
2284 Python source file to document. If name is 'keywords', 'topics',
2285 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002286
2287%s -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002288 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002289
2290%s -p <port>
2291 Start an HTTP server on the given port on the local machine.
2292
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002293%s -g
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002294 Pop up a graphical interface for finding and serving documentation.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002295
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002296%s -w <name> ...
2297 Write out the HTML documentation for a module to a file in the current
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002298 directory. If <name> contains a '%s', it is treated as a filename; if
2299 it names a directory, documentation is written for all the contents.
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002300""" % (cmd, os.sep, cmd, cmd, cmd, cmd, os.sep))
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002301
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002302if __name__ == '__main__': cli()