blob: 33b9f384854247f5cc07d291e6978c70242f3faa [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
Andrew M. Kuchling2443efb2008-12-11 02:09:36 +000030 http://www.python.org/doc/<version>/lib/
Skip Montanaro4997a692003-09-10 16:47:51 +000031
32This can be overridden by setting the PYTHONDOCS environment variable
33to a different URL or to a local directory containing the Library
34Reference Manual pages.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000035"""
Ka-Ping Yeedd175342001-02-27 14:43:46 +000036
37__author__ = "Ka-Ping Yee <ping@lfw.org>"
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000038__date__ = "26 February 2001"
Jeremy Hylton3e0055f2005-10-20 19:59:25 +000039
Ka-Ping Yee09d7d9a2001-02-27 22:43:48 +000040__version__ = "$Revision$"
Martin v. Löwis6fe8f192004-11-14 10:21:04 +000041__credits__ = """Guido van Rossum, for an excellent programming language.
Ka-Ping Yee5e2b1732001-02-27 23:35:09 +000042Tommy Burnette, the original creator of manpy.
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000043Paul Prescod, for all his work on onlinehelp.
44Richard Chamberlain, for the first implementation of textdoc.
Raymond Hettingered2dbe32005-01-01 07:51:01 +000045"""
Ka-Ping Yeedd175342001-02-27 14:43:46 +000046
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000047# Known bugs that can't be fixed here:
48# - imp.load_module() cannot be prevented from clobbering existing
49# loaded modules, so calling synopsis() on a binary module file
50# changes the contents of any existing module with the same name.
51# - If the __file__ attribute on a module is a relative path and
52# the current directory is changed with os.chdir(), an incorrect
53# path will be displayed.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000054
Phillip J. Ebyceb30872006-04-18 00:59:55 +000055import sys, imp, os, re, types, inspect, __builtin__, pkgutil
Ka-Ping Yeedd175342001-02-27 14:43:46 +000056from repr import Repr
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000057from string import expandtabs, find, join, lower, split, strip, rfind, rstrip
Phillip J. Ebyceb30872006-04-18 00:59:55 +000058try:
59 from collections import deque
60except ImportError:
61 # Python 2.3 compatibility
62 class deque(list):
63 def popleft(self):
64 return self.pop(0)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000065
66# --------------------------------------------------------- common routines
67
Ka-Ping Yeedd175342001-02-27 14:43:46 +000068def pathdirs():
69 """Convert sys.path into a list of absolute, existing, unique paths."""
70 dirs = []
Ka-Ping Yee1d384632001-03-01 00:24:32 +000071 normdirs = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +000072 for dir in sys.path:
73 dir = os.path.abspath(dir or '.')
Ka-Ping Yee1d384632001-03-01 00:24:32 +000074 normdir = os.path.normcase(dir)
75 if normdir not in normdirs and os.path.isdir(dir):
Ka-Ping Yeedd175342001-02-27 14:43:46 +000076 dirs.append(dir)
Ka-Ping Yee1d384632001-03-01 00:24:32 +000077 normdirs.append(normdir)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000078 return dirs
79
80def getdoc(object):
81 """Get the doc string or comments for an object."""
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000082 result = inspect.getdoc(object) or inspect.getcomments(object)
Ka-Ping Yee239432a2001-03-02 02:45:08 +000083 return result and re.sub('^ *\n', '', rstrip(result)) or ''
Ka-Ping Yeedd175342001-02-27 14:43:46 +000084
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000085def splitdoc(doc):
86 """Split a doc string into a synopsis line (if any) and the rest."""
87 lines = split(strip(doc), '\n')
88 if len(lines) == 1:
89 return lines[0], ''
90 elif len(lines) >= 2 and not rstrip(lines[1]):
91 return lines[0], join(lines[2:], '\n')
92 return '', join(lines, '\n')
93
Ka-Ping Yeedd175342001-02-27 14:43:46 +000094def classname(object, modname):
95 """Get a class name and qualify it with a module name if necessary."""
96 name = object.__name__
97 if object.__module__ != modname:
98 name = object.__module__ + '.' + name
99 return name
100
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000101def isdata(object):
Georg Brandl94432422005-07-22 21:52:25 +0000102 """Check if an object is of a type that probably means it's data."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000103 return not (inspect.ismodule(object) or inspect.isclass(object) or
104 inspect.isroutine(object) or inspect.isframe(object) or
105 inspect.istraceback(object) or inspect.iscode(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000106
107def replace(text, *pairs):
108 """Do a series of global replacements on a string."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000109 while pairs:
110 text = join(split(text, pairs[0]), pairs[1])
111 pairs = pairs[2:]
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000112 return text
113
114def cram(text, maxlen):
115 """Omit part of a string if needed to make it fit in a maximum length."""
116 if len(text) > maxlen:
Raymond Hettingerfca3bb62002-10-21 04:44:11 +0000117 pre = max(0, (maxlen-3)//2)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000118 post = max(0, maxlen-3-pre)
119 return text[:pre] + '...' + text[len(text)-post:]
120 return text
121
Brett Cannon84601f12004-06-19 01:22:48 +0000122_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000123def stripid(text):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000124 """Remove the hexadecimal id from a Python object representation."""
Brett Cannonc6c1f472004-06-19 01:02:51 +0000125 # The behaviour of %p is implementation-dependent in terms of case.
126 if _re_stripid.search(repr(Exception)):
127 return _re_stripid.sub(r'\1', text)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000128 return text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000129
Brett Cannonc6c1f472004-06-19 01:02:51 +0000130def _is_some_method(obj):
131 return inspect.ismethod(obj) or inspect.ismethoddescriptor(obj)
Tim Peters536d2262001-09-20 05:13:38 +0000132
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000133def allmethods(cl):
134 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000135 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000136 methods[key] = 1
137 for base in cl.__bases__:
138 methods.update(allmethods(base)) # all your base are belong to us
139 for key in methods.keys():
140 methods[key] = getattr(cl, key)
141 return methods
142
Tim Petersfa26f7c2001-09-24 08:05:11 +0000143def _split_list(s, predicate):
144 """Split sequence s via predicate, and return pair ([true], [false]).
145
146 The return value is a 2-tuple of lists,
147 ([x for x in s if predicate(x)],
148 [x for x in s if not predicate(x)])
149 """
150
Tim Peters28355492001-09-23 21:29:55 +0000151 yes = []
152 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000153 for x in s:
154 if predicate(x):
155 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000156 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000157 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000158 return yes, no
159
Skip Montanaroa5616d22004-06-11 04:46:12 +0000160def visiblename(name, all=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000161 """Decide whether to show documentation on a variable."""
162 # Certain special names are redundant.
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000163 if name in ('__builtins__', '__doc__', '__file__', '__path__',
164 '__module__', '__name__', '__slots__'): return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000165 # Private names are hidden, but special names are displayed.
166 if name.startswith('__') and name.endswith('__'): return 1
Skip Montanaroa5616d22004-06-11 04:46:12 +0000167 if all is not None:
168 # only document that which the programmer exported in __all__
169 return name in all
170 else:
171 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000172
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000173def classify_class_attrs(object):
174 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
175 def fixup((name, kind, cls, value)):
176 if inspect.isdatadescriptor(value):
177 kind = 'data descriptor'
178 return name, kind, cls, value
179 return map(fixup, inspect.classify_class_attrs(object))
180
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
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000191def source_synopsis(file):
192 line = file.readline()
193 while line[:1] == '#' or not strip(line):
194 line = file.readline()
195 if not line: break
196 line = strip(line)
197 if line[:4] == 'r"""': line = line[1:]
198 if line[:3] == '"""':
199 line = line[3:]
200 if line[-1:] == '\\': line = line[:-1]
201 while not strip(line):
202 line = file.readline()
203 if not line: break
204 result = strip(split(line, '"""')[0])
205 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
Phillip J. Ebyceb30872006-04-18 00:59:55 +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
Phillip J. Ebyceb30872006-04-18 00:59:55 +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."""
232 def __init__(self, filename, (exc, value, tb)):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000233 self.filename = filename
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000234 self.exc = exc
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000235 self.value = value
236 self.tb = tb
237
238 def __str__(self):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000239 exc = self.exc
240 if type(exc) is types.ClassType:
241 exc = exc.__name__
242 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000243
244def importfile(path):
245 """Import a Python source file or compiled file given its path."""
246 magic = imp.get_magic()
247 file = open(path, 'r')
248 if file.read(len(magic)) == magic:
249 kind = imp.PY_COMPILED
250 else:
251 kind = imp.PY_SOURCE
252 file.close()
253 filename = os.path.basename(path)
254 name, ext = os.path.splitext(filename)
255 file = open(path, 'r')
256 try:
257 module = imp.load_module(name, file, path, (ext, 'r', kind))
258 except:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000259 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000260 file.close()
261 return module
262
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000263def safeimport(path, forceload=0, cache={}):
264 """Import a module; handle errors; return None if the module isn't found.
265
266 If the module *is* found but an exception occurs, it's wrapped in an
267 ErrorDuringImport exception and reraised. Unlike __import__, if a
268 package path is specified, the module at the end of the path is returned,
269 not the package at the beginning. If the optional 'forceload' argument
270 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000271 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000272 # If forceload is 1 and the module has been previously loaded from
273 # disk, we always have to reload the module. Checking the file's
274 # mtime isn't good enough (e.g. the module could contain a class
275 # that inherits from another module that has changed).
276 if forceload and path in sys.modules:
277 if path not in sys.builtin_module_names:
278 # Avoid simply calling reload() because it leaves names in
279 # the currently loaded module lying around if they're not
280 # defined in the new source file. Instead, remove the
281 # module from sys.modules and re-import. Also remove any
282 # submodules because they won't appear in the newly loaded
283 # module's namespace if they're already in sys.modules.
284 subs = [m for m in sys.modules if m.startswith(path + '.')]
285 for key in [path] + subs:
286 # Prevent garbage collection.
287 cache[key] = sys.modules[key]
288 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000289 module = __import__(path)
290 except:
291 # Did the error occur before or after the module was found?
292 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000293 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000294 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000295 raise ErrorDuringImport(sys.modules[path].__file__, info)
296 elif exc is SyntaxError:
297 # A SyntaxError occurred before we could execute the module.
298 raise ErrorDuringImport(value.filename, info)
299 elif exc is ImportError and \
300 split(lower(str(value)))[:2] == ['no', 'module']:
301 # The module was not found.
302 return None
303 else:
304 # Some other error occurred during the importing process.
305 raise ErrorDuringImport(path, sys.exc_info())
306 for part in split(path, '.')[1:]:
307 try: module = getattr(module, part)
308 except AttributeError: return None
309 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000310
311# ---------------------------------------------------- formatter base class
312
313class Doc:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000314 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000315 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000316 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000317 # 'try' clause is to attempt to handle the possibility that inspect
318 # identifies something in a way that pydoc itself has issues handling;
319 # think 'super' and how it is a descriptor (which raises the exception
320 # by lacking a __name__ attribute) and an instance.
Barry Warsaw00decd72006-07-27 23:43:15 +0000321 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
322 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000323 try:
324 if inspect.ismodule(object): return self.docmodule(*args)
325 if inspect.isclass(object): return self.docclass(*args)
326 if inspect.isroutine(object): return self.docroutine(*args)
327 except AttributeError:
328 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000329 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000330 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000331
332 def fail(self, object, name=None, *args):
333 """Raise an exception for unimplemented types."""
334 message = "don't know how to document object%s of type %s" % (
335 name and ' ' + repr(name), type(object).__name__)
336 raise TypeError, message
337
Barry Warsaw00decd72006-07-27 23:43:15 +0000338 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000339
Skip Montanaro4997a692003-09-10 16:47:51 +0000340 def getdocloc(self, object):
341 """Return the location of module docs or None"""
342
343 try:
344 file = inspect.getabsfile(object)
345 except TypeError:
346 file = '(built-in)'
347
Andrew M. Kuchling2443efb2008-12-11 02:09:36 +0000348 version = '.'.join(str(v) for v in sys.version_info[:3])
Skip Montanaro4997a692003-09-10 16:47:51 +0000349 docloc = os.environ.get("PYTHONDOCS",
Andrew M. Kuchling2443efb2008-12-11 02:09:36 +0000350 "http://www.python.org/doc/%s/lib" % version)
Skip Montanaro4997a692003-09-10 16:47:51 +0000351 basedir = os.path.join(sys.exec_prefix, "lib",
352 "python"+sys.version[0:3])
353 if (isinstance(object, type(os)) and
354 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
355 'marshal', 'posix', 'signal', 'sys',
356 'thread', 'zipimport') or
357 (file.startswith(basedir) and
358 not file.startswith(os.path.join(basedir, 'site-packages'))))):
Skip Montanarof2134842004-06-07 02:40:05 +0000359 htmlfile = "module-%s.html" % object.__name__
Skip Montanaro4997a692003-09-10 16:47:51 +0000360 if docloc.startswith("http://"):
Skip Montanarof2134842004-06-07 02:40:05 +0000361 docloc = "%s/%s" % (docloc.rstrip("/"), htmlfile)
Skip Montanaro4997a692003-09-10 16:47:51 +0000362 else:
Skip Montanarof2134842004-06-07 02:40:05 +0000363 docloc = os.path.join(docloc, htmlfile)
Skip Montanaro4997a692003-09-10 16:47:51 +0000364 else:
365 docloc = None
366 return docloc
367
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000368# -------------------------------------------- HTML documentation generator
369
370class HTMLRepr(Repr):
371 """Class for safely making an HTML representation of a Python object."""
372 def __init__(self):
373 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000374 self.maxlist = self.maxtuple = 20
375 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000376 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000377
378 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000379 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000380
381 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000382 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000383
384 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000385 if hasattr(type(x), '__name__'):
386 methodname = 'repr_' + join(split(type(x).__name__), '_')
387 if hasattr(self, methodname):
388 return getattr(self, methodname)(x, level)
389 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000390
391 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000392 test = cram(x, self.maxstring)
393 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000394 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000395 # Backslashes are only literal in the string and are never
396 # needed to make any special characters, so show a raw string.
397 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000398 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000399 r'<font color="#c040c0">\1</font>',
400 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000401
Skip Montanarodf708782002-03-07 22:58:02 +0000402 repr_str = repr_string
403
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000404 def repr_instance(self, x, level):
405 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000406 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000407 except:
408 return self.escape('<%s instance>' % x.__class__.__name__)
409
410 repr_unicode = repr_string
411
412class HTMLDoc(Doc):
413 """Formatter class for HTML documentation."""
414
415 # ------------------------------------------- HTML formatting utilities
416
417 _repr_instance = HTMLRepr()
418 repr = _repr_instance.repr
419 escape = _repr_instance.escape
420
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000421 def page(self, title, contents):
422 """Format an HTML page."""
423 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000424<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000425<html><head><title>Python: %s</title>
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000426</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000427%s
428</body></html>''' % (title, contents)
429
430 def heading(self, title, fgcol, bgcol, extras=''):
431 """Format a page heading."""
432 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000433<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000434<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000435<td valign=bottom>&nbsp;<br>
436<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000437><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000438><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000439 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
440
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000441 def section(self, title, fgcol, bgcol, contents, width=6,
442 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000443 """Format a section with a heading."""
444 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000445 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000446 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000447<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000448<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000449<td colspan=3 valign=bottom>&nbsp;<br>
450<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000451 ''' % (bgcol, fgcol, title)
452 if prelude:
453 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000454<tr bgcolor="%s"><td rowspan=2>%s</td>
455<td colspan=2>%s</td></tr>
456<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
457 else:
458 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000459<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000460
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000461 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000462
463 def bigsection(self, title, *args):
464 """Format a section with a big heading."""
465 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000466 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000467
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000468 def preformat(self, text):
469 """Format literal preformatted text."""
470 text = self.escape(expandtabs(text))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000471 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
472 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000473
474 def multicolumn(self, list, format, cols=4):
475 """Format a list of items into a multi-column list."""
476 result = ''
477 rows = (len(list)+cols-1)/cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000478 for col in range(cols):
479 result = result + '<td width="%d%%" valign=top>' % (100/cols)
480 for i in range(rows*col, rows*col+rows):
481 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000482 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000483 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000484 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000485
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000486 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000487
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000488 def namelink(self, name, *dicts):
489 """Make a link for an identifier, given name-to-URL mappings."""
490 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000491 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000492 return '<a href="%s">%s</a>' % (dict[name], name)
493 return name
494
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000495 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000496 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000497 name, module = object.__name__, sys.modules.get(object.__module__)
498 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000499 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000500 module.__name__, name, classname(object, modname))
501 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000502
503 def modulelink(self, object):
504 """Make a link for a module."""
505 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
506
507 def modpkglink(self, (name, path, ispackage, shadowed)):
508 """Make a link for a module or package to display in an index."""
509 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000510 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000511 if path:
512 url = '%s.%s.html' % (path, name)
513 else:
514 url = '%s.html' % name
515 if ispackage:
516 text = '<strong>%s</strong>&nbsp;(package)' % name
517 else:
518 text = name
519 return '<a href="%s">%s</a>' % (url, text)
520
521 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
522 """Mark up some plain text, given a context of symbols to look for.
523 Each context dictionary maps object names to anchor names."""
524 escape = escape or self.escape
525 results = []
526 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000527 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
528 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000529 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000530 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000531 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000532 match = pattern.search(text, here)
533 if not match: break
534 start, end = match.span()
535 results.append(escape(text[here:start]))
536
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000537 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000538 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000539 url = escape(all).replace('"', '&quot;')
540 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000541 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000542 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
543 results.append('<a href="%s">%s</a>' % (url, escape(all)))
544 elif pep:
545 url = 'http://www.python.org/peps/pep-%04d.html' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000546 results.append('<a href="%s">%s</a>' % (url, escape(all)))
547 elif text[end:end+1] == '(':
548 results.append(self.namelink(name, methods, funcs, classes))
549 elif selfdot:
550 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000551 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000552 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000553 here = end
554 results.append(escape(text[here:]))
555 return join(results, '')
556
557 # ---------------------------------------------- type-specific routines
558
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000559 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000560 """Produce HTML for a class tree as given by inspect.getclasstree()."""
561 result = ''
562 for entry in tree:
563 if type(entry) is type(()):
564 c, bases = entry
Tim Peters2306d242001-09-25 03:18:32 +0000565 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000566 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000567 if bases and bases != (parent,):
568 parents = []
569 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000570 parents.append(self.classlink(base, modname))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000571 result = result + '(' + join(parents, ', ') + ')'
Tim Peters2306d242001-09-25 03:18:32 +0000572 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000573 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000574 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000575 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000576 return '<dl>\n%s</dl>\n' % result
577
Tim Peters8dd7ade2001-10-18 19:56:17 +0000578 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000579 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000580 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000581 try:
582 all = object.__all__
583 except AttributeError:
584 all = None
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000585 parts = split(name, '.')
586 links = []
587 for i in range(len(parts)-1):
588 links.append(
589 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
590 (join(parts[:i+1], '.'), parts[i]))
591 linkedname = join(links + parts[-1:], '.')
592 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000593 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000594 path = inspect.getabsfile(object)
Ka-Ping Yee6191a232001-04-13 15:00:27 +0000595 url = path
596 if sys.platform == 'win32':
597 import nturl2path
598 url = nturl2path.pathname2url(path)
599 filelink = '<a href="file:%s">%s</a>' % (url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000600 except TypeError:
601 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000602 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000603 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000604 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000605 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
606 version = strip(version[11:-1])
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000607 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000608 if hasattr(object, '__date__'):
609 info.append(self.escape(str(object.__date__)))
610 if info:
611 head = head + ' (%s)' % join(info, ', ')
Skip Montanaro4997a692003-09-10 16:47:51 +0000612 docloc = self.getdocloc(object)
613 if docloc is not None:
614 docloc = '<br><a href="%(docloc)s">Module Docs</a>' % locals()
615 else:
616 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000617 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000618 head, '#ffffff', '#7799ee',
619 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000620
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000621 modules = inspect.getmembers(object, inspect.ismodule)
622
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000623 classes, cdict = [], {}
624 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000625 # if __all__ exists, believe it. Otherwise use old heuristic.
626 if (all is not None or
627 (inspect.getmodule(value) or object) is object):
Skip Montanaroa5616d22004-06-11 04:46:12 +0000628 if visiblename(key, all):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000629 classes.append((key, value))
630 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000631 for key, value in classes:
632 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000633 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000634 module = sys.modules.get(modname)
635 if modname != name and module and hasattr(module, key):
636 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000637 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000638 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000639 funcs, fdict = [], {}
640 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000641 # if __all__ exists, believe it. Otherwise use old heuristic.
642 if (all is not None or
643 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Skip Montanaroa5616d22004-06-11 04:46:12 +0000644 if visiblename(key, all):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000645 funcs.append((key, value))
646 fdict[key] = '#-' + key
647 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000648 data = []
649 for key, value in inspect.getmembers(object, isdata):
Skip Montanaroa5616d22004-06-11 04:46:12 +0000650 if visiblename(key, all):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000651 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000652
653 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
654 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000655 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000656
657 if hasattr(object, '__path__'):
658 modpkgs = []
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000659 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
660 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000661 modpkgs.sort()
662 contents = self.multicolumn(modpkgs, self.modpkglink)
663 result = result + self.bigsection(
664 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000665 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000666 contents = self.multicolumn(
667 modules, lambda (key, value), s=self: s.modulelink(value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000668 result = result + self.bigsection(
669 'Modules', '#fffff', '#aa55cc', contents)
670
671 if classes:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000672 classlist = map(lambda (key, value): value, classes)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000673 contents = [
674 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000675 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000676 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000677 result = result + self.bigsection(
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000678 'Classes', '#ffffff', '#ee77aa', join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000679 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000680 contents = []
681 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000682 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000683 result = result + self.bigsection(
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000684 'Functions', '#ffffff', '#eeaa77', join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000685 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000686 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000687 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000688 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000689 result = result + self.bigsection(
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000690 'Data', '#ffffff', '#55aa55', join(contents, '<br>\n'))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000691 if hasattr(object, '__author__'):
692 contents = self.markup(str(object.__author__), self.preformat)
693 result = result + self.bigsection(
694 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000695 if hasattr(object, '__credits__'):
696 contents = self.markup(str(object.__credits__), self.preformat)
697 result = result + self.bigsection(
698 'Credits', '#ffffff', '#7799ee', contents)
699
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000700 return result
701
Tim Peters8dd7ade2001-10-18 19:56:17 +0000702 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
703 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000704 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000705 realname = object.__name__
706 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000707 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000708
Tim Petersb47879b2001-09-24 04:47:19 +0000709 contents = []
710 push = contents.append
711
Tim Petersfa26f7c2001-09-24 08:05:11 +0000712 # Cute little class to pump out a horizontal rule between sections.
713 class HorizontalRule:
714 def __init__(self):
715 self.needone = 0
716 def maybe(self):
717 if self.needone:
718 push('<hr>\n')
719 self.needone = 1
720 hr = HorizontalRule()
721
Tim Petersc86f6ca2001-09-26 21:31:51 +0000722 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000723 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000724 if len(mro) > 2:
725 hr.maybe()
726 push('<dl><dt>Method resolution order:</dt>\n')
727 for base in mro:
728 push('<dd>%s</dd>\n' % self.classlink(base,
729 object.__module__))
730 push('</dl>\n')
731
Tim Petersb47879b2001-09-24 04:47:19 +0000732 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000733 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000734 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000735 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000736 push(msg)
737 for name, kind, homecls, value in ok:
738 push(self.document(getattr(object, name), name, mod,
739 funcs, classes, mdict, object))
740 push('\n')
741 return attrs
742
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000743 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000744 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000745 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000746 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000747 push(msg)
748 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000749 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000750 return attrs
751
Tim Petersfa26f7c2001-09-24 08:05:11 +0000752 def spilldata(msg, attrs, predicate):
753 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000754 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000755 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000756 push(msg)
757 for name, kind, homecls, value in ok:
758 base = self.docother(getattr(object, name), name, mod)
Martin v. Löwise59e2ba2003-05-03 09:09:02 +0000759 if callable(value) or inspect.isdatadescriptor(value):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000760 doc = getattr(value, "__doc__", None)
761 else:
762 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000763 if doc is None:
764 push('<dl><dt>%s</dl>\n' % base)
765 else:
766 doc = self.markup(getdoc(value), self.preformat,
767 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000768 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000769 push('<dl><dt>%s%s</dl>\n' % (base, doc))
770 push('\n')
771 return attrs
772
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000773 attrs = filter(lambda (name, kind, cls, value): visiblename(name),
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000774 classify_class_attrs(object))
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.
Phillip J. Ebyceb30872006-04-18 00:59:55 +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__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +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:
Georg Brandlafa4f482007-03-13 22:16:43 +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):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000879 args, varargs, varkw, defaults = inspect.getargspec(object)
880 argspec = inspect.formatargspec(
881 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000882 if realname == '<lambda>':
Tim Peters59ed4482001-10-31 04:20:26 +0000883 title = '<strong>%s</strong> <em>lambda</em> ' % name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000884 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +0000885 else:
886 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000887
Tim Peters2306d242001-09-25 03:18:32 +0000888 decl = title + argspec + (note and self.grey(
889 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000890
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000891 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000892 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000893 else:
894 doc = self.markup(
895 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000896 doc = doc and '<dd><tt>%s</tt></dd>' % doc
897 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000898
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000899 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000900 results = []
901 push = results.append
902
903 if name:
904 push('<dl><dt><strong>%s</strong></dt>\n' % name)
905 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000906 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000907 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000908 push('</dl>\n')
909
910 return ''.join(results)
911
912 def docproperty(self, object, name=None, mod=None, cl=None):
913 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000914 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000915
Tim Peters8dd7ade2001-10-18 19:56:17 +0000916 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000917 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000918 lhs = name and '<strong>%s</strong> = ' % name or ''
919 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000920
Barry Warsaw00decd72006-07-27 23:43:15 +0000921 def docdata(self, object, name=None, mod=None, cl=None):
922 """Produce html documentation for a data descriptor."""
923 return self._docdescriptor(name, object, mod)
924
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000925 def index(self, dir, shadowed=None):
926 """Generate an HTML index for a directory of modules."""
927 modpkgs = []
928 if shadowed is None: shadowed = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000929 for importer, name, ispkg in pkgutil.iter_modules([dir]):
930 modpkgs.append((name, '', ispkg, name in shadowed))
931 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000932
933 modpkgs.sort()
934 contents = self.multicolumn(modpkgs, self.modpkglink)
935 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
936
937# -------------------------------------------- text documentation generator
938
939class TextRepr(Repr):
940 """Class for safely making a text representation of a Python object."""
941 def __init__(self):
942 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000943 self.maxlist = self.maxtuple = 20
944 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000945 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000946
947 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000948 if hasattr(type(x), '__name__'):
949 methodname = 'repr_' + join(split(type(x).__name__), '_')
950 if hasattr(self, methodname):
951 return getattr(self, methodname)(x, level)
952 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000953
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000954 def repr_string(self, x, level):
955 test = cram(x, self.maxstring)
956 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000957 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000958 # Backslashes are only literal in the string and are never
959 # needed to make any special characters, so show a raw string.
960 return 'r' + testrepr[0] + test + testrepr[0]
961 return testrepr
962
Skip Montanarodf708782002-03-07 22:58:02 +0000963 repr_str = repr_string
964
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000965 def repr_instance(self, x, level):
966 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000967 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000968 except:
969 return '<%s instance>' % x.__class__.__name__
970
971class TextDoc(Doc):
972 """Formatter class for text documentation."""
973
974 # ------------------------------------------- text formatting utilities
975
976 _repr_instance = TextRepr()
977 repr = _repr_instance.repr
978
979 def bold(self, text):
980 """Format a string in bold by overstriking."""
981 return join(map(lambda ch: ch + '\b' + ch, text), '')
982
983 def indent(self, text, prefix=' '):
984 """Indent text by prepending a given prefix to each line."""
985 if not text: return ''
986 lines = split(text, '\n')
987 lines = map(lambda line, prefix=prefix: prefix + line, lines)
988 if lines: lines[-1] = rstrip(lines[-1])
989 return join(lines, '\n')
990
991 def section(self, title, contents):
992 """Format a section with a given heading."""
993 return self.bold(title) + '\n' + rstrip(self.indent(contents)) + '\n\n'
994
995 # ---------------------------------------------- type-specific routines
996
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000997 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000998 """Render in text a class tree as returned by inspect.getclasstree()."""
999 result = ''
1000 for entry in tree:
1001 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001002 c, bases = entry
1003 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001004 if bases and bases != (parent,):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001005 parents = map(lambda c, m=modname: classname(c, m), bases)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001006 result = result + '(%s)' % join(parents, ', ')
1007 result = result + '\n'
1008 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001009 result = result + self.formattree(
1010 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001011 return result
1012
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001013 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001014 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001015 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001016 synop, desc = splitdoc(getdoc(object))
1017 result = self.section('NAME', name + (synop and ' - ' + synop))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001018
1019 try:
Skip Montanaroa5616d22004-06-11 04:46:12 +00001020 all = object.__all__
1021 except AttributeError:
1022 all = None
1023
1024 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001025 file = inspect.getabsfile(object)
1026 except TypeError:
1027 file = '(built-in)'
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001028 result = result + self.section('FILE', file)
Skip Montanaro4997a692003-09-10 16:47:51 +00001029
1030 docloc = self.getdocloc(object)
1031 if docloc is not None:
1032 result = result + self.section('MODULE DOCS', docloc)
1033
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001034 if desc:
1035 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001036
1037 classes = []
1038 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001039 # if __all__ exists, believe it. Otherwise use old heuristic.
1040 if (all is not None
1041 or (inspect.getmodule(value) or object) is object):
Skip Montanaroa5616d22004-06-11 04:46:12 +00001042 if visiblename(key, all):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001043 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001044 funcs = []
1045 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001046 # if __all__ exists, believe it. Otherwise use old heuristic.
1047 if (all is not None or
1048 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Skip Montanaroa5616d22004-06-11 04:46:12 +00001049 if visiblename(key, all):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001050 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001051 data = []
1052 for key, value in inspect.getmembers(object, isdata):
Skip Montanaroa5616d22004-06-11 04:46:12 +00001053 if visiblename(key, all):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001054 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001055
1056 if hasattr(object, '__path__'):
1057 modpkgs = []
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001058 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
1059 if ispkg:
1060 modpkgs.append(modname + ' (package)')
1061 else:
1062 modpkgs.append(modname)
1063
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001064 modpkgs.sort()
1065 result = result + self.section(
1066 'PACKAGE CONTENTS', join(modpkgs, '\n'))
1067
1068 if classes:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001069 classlist = map(lambda (key, value): value, classes)
1070 contents = [self.formattree(
1071 inspect.getclasstree(classlist, 1), name)]
1072 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001073 contents.append(self.document(value, key, name))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001074 result = result + self.section('CLASSES', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001075
1076 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001077 contents = []
1078 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001079 contents.append(self.document(value, key, name))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001080 result = result + self.section('FUNCTIONS', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001081
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001082 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001083 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001084 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001085 contents.append(self.docother(value, key, name, maxlen=70))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001086 result = result + self.section('DATA', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001087
1088 if hasattr(object, '__version__'):
1089 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001090 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
1091 version = strip(version[11:-1])
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001092 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001093 if hasattr(object, '__date__'):
1094 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001095 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001096 result = result + self.section('AUTHOR', str(object.__author__))
1097 if hasattr(object, '__credits__'):
1098 result = result + self.section('CREDITS', str(object.__credits__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001099 return result
1100
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001101 def docclass(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001102 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001103 realname = object.__name__
1104 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001105 bases = object.__bases__
1106
Tim Petersc86f6ca2001-09-26 21:31:51 +00001107 def makename(c, m=object.__module__):
1108 return classname(c, m)
1109
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001110 if name == realname:
1111 title = 'class ' + self.bold(realname)
1112 else:
1113 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001114 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001115 parents = map(makename, bases)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001116 title = title + '(%s)' % join(parents, ', ')
1117
1118 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001119 contents = doc and [doc + '\n'] or []
1120 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001121
Tim Petersc86f6ca2001-09-26 21:31:51 +00001122 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001123 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001124 if len(mro) > 2:
1125 push("Method resolution order:")
1126 for base in mro:
1127 push(' ' + makename(base))
1128 push('')
1129
Tim Petersf4aad8e2001-09-24 22:40:47 +00001130 # Cute little class to pump out a horizontal rule between sections.
1131 class HorizontalRule:
1132 def __init__(self):
1133 self.needone = 0
1134 def maybe(self):
1135 if self.needone:
1136 push('-' * 70)
1137 self.needone = 1
1138 hr = HorizontalRule()
1139
Tim Peters28355492001-09-23 21:29:55 +00001140 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001141 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001142 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001143 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001144 push(msg)
1145 for name, kind, homecls, value in ok:
1146 push(self.document(getattr(object, name),
1147 name, mod, object))
1148 return attrs
1149
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001150 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001151 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001152 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001153 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001154 push(msg)
1155 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001156 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001157 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001158
Tim Petersfa26f7c2001-09-24 08:05:11 +00001159 def spilldata(msg, attrs, predicate):
1160 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001161 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001162 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001163 push(msg)
1164 for name, kind, homecls, value in ok:
Martin v. Löwise59e2ba2003-05-03 09:09:02 +00001165 if callable(value) or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001166 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001167 else:
1168 doc = None
Tim Peters28355492001-09-23 21:29:55 +00001169 push(self.docother(getattr(object, name),
Georg Brandl8b813db2005-10-01 16:32:31 +00001170 name, mod, maxlen=70, doc=doc) + '\n')
Tim Peters28355492001-09-23 21:29:55 +00001171 return attrs
1172
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001173 attrs = filter(lambda (name, kind, cls, value): visiblename(name),
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001174 classify_class_attrs(object))
Tim Petersfa26f7c2001-09-24 08:05:11 +00001175 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001176 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001177 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001178 else:
1179 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001180 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1181
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001182 if thisclass is __builtin__.object:
1183 attrs = inherited
1184 continue
1185 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001186 tag = "defined here"
1187 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001188 tag = "inherited from %s" % classname(thisclass,
1189 object.__module__)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001190 filter(lambda t: not t[0].startswith('_'), attrs)
Tim Peters28355492001-09-23 21:29:55 +00001191
1192 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001193 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001194
1195 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001196 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001197 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001198 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001199 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001200 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001201 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001202 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1203 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001204 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1205 lambda t: t[1] == 'data')
Tim Peters28355492001-09-23 21:29:55 +00001206 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001207 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001208
1209 contents = '\n'.join(contents)
1210 if not contents:
1211 return title + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001212 return title + '\n' + self.indent(rstrip(contents), ' | ') + '\n'
1213
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001214 def formatvalue(self, object):
1215 """Format an argument default value as text."""
1216 return '=' + self.repr(object)
1217
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001218 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001219 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001220 realname = object.__name__
1221 name = name or realname
1222 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001223 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001224 if inspect.ismethod(object):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001225 imclass = object.im_class
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001226 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001227 if imclass is not cl:
1228 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001229 else:
Georg Brandlafa4f482007-03-13 22:16:43 +00001230 if object.im_self is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001231 note = ' method of %s instance' % classname(
1232 object.im_self.__class__, mod)
1233 else:
1234 note = ' unbound %s method' % classname(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001235 object = object.im_func
1236
1237 if name == realname:
1238 title = self.bold(realname)
1239 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001240 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001241 cl.__dict__[realname] is object):
1242 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001243 title = self.bold(name) + ' = ' + realname
Tim Peters4bcfa312001-09-20 06:08:24 +00001244 if inspect.isfunction(object):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001245 args, varargs, varkw, defaults = inspect.getargspec(object)
1246 argspec = inspect.formatargspec(
1247 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001248 if realname == '<lambda>':
Georg Brandl501dd0d2006-02-17 09:45:40 +00001249 title = self.bold(name) + ' lambda '
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001250 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +00001251 else:
1252 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001253 decl = title + argspec + note
1254
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001255 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001256 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001257 else:
1258 doc = getdoc(object) or ''
1259 return decl + '\n' + (doc and rstrip(self.indent(doc)) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001260
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001261 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001262 results = []
1263 push = results.append
1264
1265 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001266 push(self.bold(name))
1267 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001268 doc = getdoc(value) or ''
1269 if doc:
1270 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001271 push('\n')
1272 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001273
1274 def docproperty(self, object, name=None, mod=None, cl=None):
1275 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001276 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001277
Barry Warsaw00decd72006-07-27 23:43:15 +00001278 def docdata(self, object, name=None, mod=None, cl=None):
1279 """Produce text documentation for a data descriptor."""
1280 return self._docdescriptor(name, object, mod)
1281
Georg Brandl8b813db2005-10-01 16:32:31 +00001282 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001283 """Produce text documentation for a data object."""
1284 repr = self.repr(object)
1285 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001286 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001287 chop = maxlen - len(line)
1288 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001289 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001290 if doc is not None:
1291 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001292 return line
1293
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001294# --------------------------------------------------------- user interfaces
1295
1296def pager(text):
1297 """The first time this is called, determine what kind of pager to use."""
1298 global pager
1299 pager = getpager()
1300 pager(text)
1301
1302def getpager():
1303 """Decide what method to use for paging through text."""
1304 if type(sys.stdout) is not types.FileType:
1305 return plainpager
1306 if not sys.stdin.isatty() or not sys.stdout.isatty():
1307 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001308 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001309 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001310 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001311 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001312 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001313 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001314 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001315 if os.environ.get('TERM') in ('dumb', 'emacs'):
1316 return plainpager
Andrew MacIntyre54e0eab2002-03-03 03:12:30 +00001317 if sys.platform == 'win32' or sys.platform.startswith('os2'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001318 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001319 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001320 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001321
1322 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001323 (fd, filename) = tempfile.mkstemp()
1324 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001325 try:
1326 if hasattr(os, 'system') and os.system('more %s' % filename) == 0:
1327 return lambda text: pipepager(text, 'more')
1328 else:
1329 return ttypager
1330 finally:
1331 os.unlink(filename)
1332
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001333def plain(text):
1334 """Remove boldface formatting from text."""
1335 return re.sub('.\b', '', text)
1336
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001337def pipepager(text, cmd):
1338 """Page through text by feeding it to another program."""
1339 pipe = os.popen(cmd, 'w')
1340 try:
1341 pipe.write(text)
1342 pipe.close()
1343 except IOError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001344 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001345
1346def tempfilepager(text, cmd):
1347 """Page through text by invoking a program on a temporary file."""
1348 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001349 filename = tempfile.mktemp()
1350 file = open(filename, 'w')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001351 file.write(text)
1352 file.close()
1353 try:
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00001354 os.system(cmd + ' ' + filename)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001355 finally:
1356 os.unlink(filename)
1357
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001358def ttypager(text):
1359 """Page through text on a text terminal."""
1360 lines = split(plain(text), '\n')
1361 try:
1362 import tty
1363 fd = sys.stdin.fileno()
1364 old = tty.tcgetattr(fd)
1365 tty.setcbreak(fd)
1366 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001367 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001368 tty = None
1369 getchar = lambda: sys.stdin.readline()[:-1][:1]
1370
1371 try:
1372 r = inc = os.environ.get('LINES', 25) - 1
1373 sys.stdout.write(join(lines[:inc], '\n') + '\n')
1374 while lines[r:]:
1375 sys.stdout.write('-- more --')
1376 sys.stdout.flush()
1377 c = getchar()
1378
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001379 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001380 sys.stdout.write('\r \r')
1381 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001382 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001383 sys.stdout.write('\r \r' + lines[r] + '\n')
1384 r = r + 1
1385 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001386 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001387 r = r - inc - inc
1388 if r < 0: r = 0
1389 sys.stdout.write('\n' + join(lines[r:r+inc], '\n') + '\n')
1390 r = r + inc
1391
1392 finally:
1393 if tty:
1394 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1395
1396def plainpager(text):
1397 """Simply print unformatted text. This is the ultimate fallback."""
1398 sys.stdout.write(plain(text))
1399
1400def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001401 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001402 if inspect.ismodule(thing):
1403 if thing.__name__ in sys.builtin_module_names:
1404 return 'built-in module ' + thing.__name__
1405 if hasattr(thing, '__path__'):
1406 return 'package ' + thing.__name__
1407 else:
1408 return 'module ' + thing.__name__
1409 if inspect.isbuiltin(thing):
1410 return 'built-in function ' + thing.__name__
Barry Warsaw00decd72006-07-27 23:43:15 +00001411 if inspect.isgetsetdescriptor(thing):
1412 return 'getset descriptor %s.%s.%s' % (
1413 thing.__objclass__.__module__, thing.__objclass__.__name__,
1414 thing.__name__)
1415 if inspect.ismemberdescriptor(thing):
1416 return 'member descriptor %s.%s.%s' % (
1417 thing.__objclass__.__module__, thing.__objclass__.__name__,
1418 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001419 if inspect.isclass(thing):
1420 return 'class ' + thing.__name__
1421 if inspect.isfunction(thing):
1422 return 'function ' + thing.__name__
1423 if inspect.ismethod(thing):
1424 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001425 if type(thing) is types.InstanceType:
1426 return 'instance of ' + thing.__class__.__name__
1427 return type(thing).__name__
1428
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001429def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001430 """Locate an object by name or dotted path, importing as necessary."""
Guido van Rossum97dede02003-02-16 01:12:32 +00001431 parts = [part for part in split(path, '.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001432 module, n = None, 0
1433 while n < len(parts):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001434 nextmodule = safeimport(join(parts[:n+1], '.'), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001435 if nextmodule: module, n = nextmodule, n + 1
1436 else: break
1437 if module:
1438 object = module
1439 for part in parts[n:]:
1440 try: object = getattr(object, part)
1441 except AttributeError: return None
1442 return object
1443 else:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001444 if hasattr(__builtin__, path):
1445 return getattr(__builtin__, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001446
1447# --------------------------------------- interactive interpreter interface
1448
1449text = TextDoc()
1450html = HTMLDoc()
1451
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001452def resolve(thing, forceload=0):
1453 """Given an object or a path to an object, get the object and its name."""
1454 if isinstance(thing, str):
1455 object = locate(thing, forceload)
1456 if not object:
1457 raise ImportError, 'no Python documentation found for %r' % thing
1458 return object, thing
1459 else:
1460 return thing, getattr(thing, '__name__', None)
1461
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001462def doc(thing, title='Python Library Documentation: %s', forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001463 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001464 try:
1465 object, name = resolve(thing, forceload)
1466 desc = describe(object)
1467 module = inspect.getmodule(object)
1468 if name and '.' in name:
1469 desc += ' in ' + name[:name.rfind('.')]
1470 elif module and module is not object:
1471 desc += ' in module ' + module.__name__
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001472 if not (inspect.ismodule(object) or
1473 inspect.isclass(object) or
1474 inspect.isroutine(object) or
Barry Warsaw00decd72006-07-27 23:43:15 +00001475 inspect.isgetsetdescriptor(object) or
1476 inspect.ismemberdescriptor(object) or
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001477 isinstance(object, property)):
1478 # If the passed object is a piece of data or an instance,
1479 # document its available methods instead of its value.
1480 object = type(object)
1481 desc += ' object'
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001482 pager(title % desc + '\n\n' + text.document(object, name))
1483 except (ImportError, ErrorDuringImport), value:
1484 print value
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001485
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001486def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001487 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001488 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001489 object, name = resolve(thing, forceload)
1490 page = html.page(describe(object), html.document(object, name))
1491 file = open(name + '.html', 'w')
1492 file.write(page)
1493 file.close()
1494 print 'wrote', name + '.html'
1495 except (ImportError, ErrorDuringImport), value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001496 print value
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001497
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001498def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001499 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001500 if done is None: done = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001501 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1502 writedoc(modname)
1503 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001504
1505class Helper:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001506 keywords = {
1507 'and': 'BOOLEAN',
Georg Brandl6cdcdbc2007-03-13 10:07:01 +00001508 'as': 'with',
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001509 'assert': ('ref/assert', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001510 'break': ('ref/break', 'while for'),
1511 'class': ('ref/class', 'CLASSES SPECIALMETHODS'),
1512 'continue': ('ref/continue', 'while for'),
1513 'def': ('ref/function', ''),
1514 'del': ('ref/del', 'BASICMETHODS'),
1515 'elif': 'if',
1516 'else': ('ref/if', 'while for'),
1517 'except': 'try',
1518 'exec': ('ref/exec', ''),
1519 'finally': 'try',
1520 'for': ('ref/for', 'break continue while'),
1521 'from': 'import',
1522 'global': ('ref/global', 'NAMESPACES'),
1523 'if': ('ref/if', 'TRUTHVALUE'),
1524 'import': ('ref/import', 'MODULES'),
1525 'in': ('ref/comparisons', 'SEQUENCEMETHODS2'),
1526 'is': 'COMPARISON',
Neal Norwitz742dde42003-03-30 20:31:34 +00001527 'lambda': ('ref/lambdas', 'FUNCTIONS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001528 'not': 'BOOLEAN',
1529 'or': 'BOOLEAN',
Neal Norwitz742dde42003-03-30 20:31:34 +00001530 'pass': ('ref/pass', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001531 'print': ('ref/print', ''),
1532 'raise': ('ref/raise', 'EXCEPTIONS'),
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001533 'return': ('ref/return', 'FUNCTIONS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001534 'try': ('ref/try', 'EXCEPTIONS'),
1535 'while': ('ref/while', 'break continue if TRUTHVALUE'),
Georg Brandl6cdcdbc2007-03-13 10:07:01 +00001536 'with': ('ref/with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
Tim Petersfb05c4e2002-10-30 05:21:00 +00001537 'yield': ('ref/yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001538 }
1539
1540 topics = {
1541 'TYPES': ('ref/types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS FUNCTIONS CLASSES MODULES FILES inspect'),
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001542 'STRINGS': ('ref/strings', 'str UNICODE SEQUENCES STRINGMETHODS FORMATTING TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001543 'STRINGMETHODS': ('lib/string-methods', 'STRINGS FORMATTING'),
1544 'FORMATTING': ('lib/typesseq-strings', 'OPERATORS'),
Neal Norwitz54f871e2003-05-26 13:49:54 +00001545 'UNICODE': ('ref/strings', 'encodings unicode SEQUENCES STRINGMETHODS FORMATTING TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001546 'NUMBERS': ('ref/numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1547 'INTEGER': ('ref/integers', 'int range'),
1548 'FLOAT': ('ref/floating', 'float math'),
1549 'COMPLEX': ('ref/imaginary', 'complex cmath'),
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001550 'SEQUENCES': ('lib/typesseq', 'STRINGMETHODS FORMATTING xrange LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001551 'MAPPINGS': 'DICTIONARIES',
1552 'FUNCTIONS': ('lib/typesfunctions', 'def TYPES'),
1553 'METHODS': ('lib/typesmethods', 'class def CLASSES TYPES'),
1554 'CODEOBJECTS': ('lib/bltin-code-objects', 'compile FUNCTIONS TYPES'),
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001555 'TYPEOBJECTS': ('lib/bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001556 'FRAMEOBJECTS': 'TYPES',
1557 'TRACEBACKS': 'TYPES',
1558 'NONE': ('lib/bltin-null-object', ''),
1559 'ELLIPSIS': ('lib/bltin-ellipsis-object', 'SLICINGS'),
1560 'FILES': ('lib/bltin-file-objects', ''),
1561 'SPECIALATTRIBUTES': ('lib/specialattrs', ''),
1562 'CLASSES': ('ref/types', 'class SPECIALMETHODS PRIVATENAMES'),
1563 'MODULES': ('lib/typesmodules', 'import'),
1564 'PACKAGES': 'import',
1565 'EXPRESSIONS': ('ref/summary', 'lambda or and not in is BOOLEAN COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES LISTS DICTIONARIES BACKQUOTES'),
1566 'OPERATORS': 'EXPRESSIONS',
1567 'PRECEDENCE': 'EXPRESSIONS',
1568 'OBJECTS': ('ref/objects', 'TYPES'),
1569 'SPECIALMETHODS': ('ref/specialnames', 'BASICMETHODS ATTRIBUTEMETHODS CALLABLEMETHODS SEQUENCEMETHODS1 MAPPINGMETHODS SEQUENCEMETHODS2 NUMBERMETHODS CLASSES'),
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001570 'BASICMETHODS': ('ref/customization', 'cmp hash repr str SPECIALMETHODS'),
1571 'ATTRIBUTEMETHODS': ('ref/attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1572 'CALLABLEMETHODS': ('ref/callable-types', 'CALLS SPECIALMETHODS'),
1573 'SEQUENCEMETHODS1': ('ref/sequence-types', 'SEQUENCES SEQUENCEMETHODS2 SPECIALMETHODS'),
1574 'SEQUENCEMETHODS2': ('ref/sequence-methods', 'SEQUENCES SEQUENCEMETHODS1 SPECIALMETHODS'),
1575 'MAPPINGMETHODS': ('ref/sequence-types', 'MAPPINGS SPECIALMETHODS'),
1576 'NUMBERMETHODS': ('ref/numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT SPECIALMETHODS'),
Neal Norwitz54f871e2003-05-26 13:49:54 +00001577 'EXECUTION': ('ref/execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
1578 'NAMESPACES': ('ref/naming', 'global ASSIGNMENT DELETION DYNAMICFEATURES'),
1579 'DYNAMICFEATURES': ('ref/dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001580 'SCOPING': 'NAMESPACES',
1581 'FRAMES': 'NAMESPACES',
1582 'EXCEPTIONS': ('ref/exceptions', 'try except finally raise'),
Neal Norwitz54f871e2003-05-26 13:49:54 +00001583 'COERCIONS': ('ref/coercion-rules','CONVERSIONS'),
1584 'CONVERSIONS': ('ref/conversions', 'COERCIONS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001585 'IDENTIFIERS': ('ref/identifiers', 'keywords SPECIALIDENTIFIERS'),
1586 'SPECIALIDENTIFIERS': ('ref/id-classes', ''),
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001587 'PRIVATENAMES': ('ref/atom-identifiers', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001588 'LITERALS': ('ref/atom-literals', 'STRINGS BACKQUOTES NUMBERS TUPLELITERALS LISTLITERALS DICTIONARYLITERALS'),
1589 'TUPLES': 'SEQUENCES',
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001590 'TUPLELITERALS': ('ref/exprlists', 'TUPLES LITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001591 'LISTS': ('lib/typesseq-mutable', 'LISTLITERALS'),
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001592 'LISTLITERALS': ('ref/lists', 'LISTS LITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001593 'DICTIONARIES': ('lib/typesmapping', 'DICTIONARYLITERALS'),
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001594 'DICTIONARYLITERALS': ('ref/dict', 'DICTIONARIES LITERALS'),
1595 'BACKQUOTES': ('ref/string-conversions', 'repr str STRINGS LITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001596 'ATTRIBUTES': ('ref/attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
1597 'SUBSCRIPTS': ('ref/subscriptions', 'SEQUENCEMETHODS1'),
1598 'SLICINGS': ('ref/slicings', 'SEQUENCEMETHODS2'),
1599 'CALLS': ('ref/calls', 'EXPRESSIONS'),
1600 'POWER': ('ref/power', 'EXPRESSIONS'),
1601 'UNARY': ('ref/unary', 'EXPRESSIONS'),
1602 'BINARY': ('ref/binary', 'EXPRESSIONS'),
1603 'SHIFTING': ('ref/shifting', 'EXPRESSIONS'),
1604 'BITWISE': ('ref/bitwise', 'EXPRESSIONS'),
1605 'COMPARISON': ('ref/comparisons', 'EXPRESSIONS BASICMETHODS'),
Neal Norwitzf98159c2003-02-07 20:49:40 +00001606 'BOOLEAN': ('ref/Booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001607 'ASSERTION': 'assert',
1608 'ASSIGNMENT': ('ref/assignment', 'AUGMENTEDASSIGNMENT'),
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001609 'AUGMENTEDASSIGNMENT': ('ref/augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001610 'DELETION': 'del',
1611 'PRINTING': 'print',
1612 'RETURNING': 'return',
1613 'IMPORTING': 'import',
1614 'CONDITIONAL': 'if',
1615 'LOOPING': ('ref/compound', 'for while break continue'),
1616 'TRUTHVALUE': ('lib/truth', 'if while and or not BASICMETHODS'),
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001617 'DEBUGGING': ('lib/module-pdb', 'pdb'),
Georg Brandl6cdcdbc2007-03-13 10:07:01 +00001618 'CONTEXTMANAGERS': ('ref/context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001619 }
1620
1621 def __init__(self, input, output):
1622 self.input = input
1623 self.output = output
1624 self.docdir = None
1625 execdir = os.path.dirname(sys.executable)
1626 homedir = os.environ.get('PYTHONHOME')
1627 for dir in [os.environ.get('PYTHONDOCS'),
1628 homedir and os.path.join(homedir, 'doc'),
1629 os.path.join(execdir, 'doc'),
1630 '/usr/doc/python-docs-' + split(sys.version)[0],
1631 '/usr/doc/python-' + split(sys.version)[0],
1632 '/usr/doc/python-docs-' + sys.version[:3],
Jack Jansenb2628b02002-08-23 08:40:42 +00001633 '/usr/doc/python-' + sys.version[:3],
1634 os.path.join(sys.prefix, 'Resources/English.lproj/Documentation')]:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001635 if dir and os.path.isdir(os.path.join(dir, 'lib')):
1636 self.docdir = dir
1637
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001638 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001639 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001640 self()
1641 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001642 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001643
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001644 def __call__(self, request=None):
1645 if request is not None:
1646 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001647 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001648 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001649 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001650 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001651You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001652If you want to ask for help on a particular object directly from the
1653interpreter, you can type "help(object)". Executing "help('string')"
1654has the same effect as typing a particular string at the help> prompt.
1655''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001656
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001657 def interact(self):
1658 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001659 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001660 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001661 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001662 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001663 except (KeyboardInterrupt, EOFError):
1664 break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001665 request = strip(replace(request, '"', '', "'", ''))
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001666 if lower(request) in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001667 self.help(request)
1668
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001669 def getline(self, prompt):
1670 """Read one line, using raw_input when available."""
1671 if self.input is sys.stdin:
1672 return raw_input(prompt)
1673 else:
1674 self.output.write(prompt)
1675 self.output.flush()
1676 return self.input.readline()
1677
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001678 def help(self, request):
1679 if type(request) is type(''):
1680 if request == 'help': self.intro()
1681 elif request == 'keywords': self.listkeywords()
1682 elif request == 'topics': self.listtopics()
1683 elif request == 'modules': self.listmodules()
1684 elif request[:8] == 'modules ':
1685 self.listmodules(split(request)[1])
Raymond Hettinger54f02222002-06-01 14:18:47 +00001686 elif request in self.keywords: self.showtopic(request)
1687 elif request in self.topics: self.showtopic(request)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001688 elif request: doc(request, 'Help on %s:')
1689 elif isinstance(request, Helper): self()
1690 else: doc(request, 'Help on %s:')
1691 self.output.write('\n')
1692
1693 def intro(self):
1694 self.output.write('''
1695Welcome to Python %s! This is the online help utility.
1696
1697If this is your first time using Python, you should definitely check out
1698the tutorial on the Internet at http://www.python.org/doc/tut/.
1699
1700Enter the name of any module, keyword, or topic to get help on writing
1701Python programs and using Python modules. To quit this help utility and
1702return to the interpreter, just type "quit".
1703
1704To get a list of available modules, keywords, or topics, type "modules",
1705"keywords", or "topics". Each module also comes with a one-line summary
1706of what it does; to list the modules whose summaries contain a given word
1707such as "spam", type "modules spam".
1708''' % sys.version[:3])
1709
1710 def list(self, items, columns=4, width=80):
1711 items = items[:]
1712 items.sort()
1713 colw = width / columns
1714 rows = (len(items) + columns - 1) / columns
1715 for row in range(rows):
1716 for col in range(columns):
1717 i = col * rows + row
1718 if i < len(items):
1719 self.output.write(items[i])
1720 if col < columns - 1:
1721 self.output.write(' ' + ' ' * (colw-1 - len(items[i])))
1722 self.output.write('\n')
1723
1724 def listkeywords(self):
1725 self.output.write('''
1726Here is a list of the Python keywords. Enter any keyword to get more help.
1727
1728''')
1729 self.list(self.keywords.keys())
1730
1731 def listtopics(self):
1732 self.output.write('''
1733Here is a list of available topics. Enter any topic name to get more help.
1734
1735''')
1736 self.list(self.topics.keys())
1737
1738 def showtopic(self, topic):
1739 if not self.docdir:
1740 self.output.write('''
1741Sorry, topic and keyword documentation is not available because the Python
1742HTML documentation files could not be found. If you have installed them,
1743please set the environment variable PYTHONDOCS to indicate their location.
Andrew M. Kuchlingdf6994d2006-12-19 15:19:14 +00001744
1745On the Microsoft Windows operating system, the files can be built by
1746running "hh -decompile . PythonNN.chm" in the C:\PythonNN\Doc> directory.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001747''')
1748 return
1749 target = self.topics.get(topic, self.keywords.get(topic))
1750 if not target:
1751 self.output.write('no documentation found for %s\n' % repr(topic))
1752 return
1753 if type(target) is type(''):
1754 return self.showtopic(target)
1755
1756 filename, xrefs = target
1757 filename = self.docdir + '/' + filename + '.html'
1758 try:
1759 file = open(filename)
1760 except:
1761 self.output.write('could not read docs from %s\n' % filename)
1762 return
1763
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001764 divpat = re.compile('<div[^>]*navigat.*?</div.*?>', re.I | re.S)
1765 addrpat = re.compile('<address.*?>.*?</address.*?>', re.I | re.S)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001766 document = re.sub(addrpat, '', re.sub(divpat, '', file.read()))
1767 file.close()
1768
1769 import htmllib, formatter, StringIO
1770 buffer = StringIO.StringIO()
1771 parser = htmllib.HTMLParser(
1772 formatter.AbstractFormatter(formatter.DumbWriter(buffer)))
1773 parser.start_table = parser.do_p
1774 parser.end_table = lambda parser=parser: parser.do_p({})
1775 parser.start_tr = parser.do_br
1776 parser.start_td = parser.start_th = lambda a, b=buffer: b.write('\t')
1777 parser.feed(document)
1778 buffer = replace(buffer.getvalue(), '\xa0', ' ', '\n', '\n ')
1779 pager(' ' + strip(buffer) + '\n')
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001780 if xrefs:
1781 buffer = StringIO.StringIO()
1782 formatter.DumbWriter(buffer).send_flowing_data(
1783 'Related help topics: ' + join(split(xrefs), ', ') + '\n')
1784 self.output.write('\n%s\n' % buffer.getvalue())
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001785
1786 def listmodules(self, key=''):
1787 if key:
1788 self.output.write('''
1789Here is a list of matching modules. Enter any module name to get more help.
1790
1791''')
1792 apropos(key)
1793 else:
1794 self.output.write('''
1795Please wait a moment while I gather a list of all available modules...
1796
1797''')
1798 modules = {}
1799 def callback(path, modname, desc, modules=modules):
1800 if modname and modname[-9:] == '.__init__':
1801 modname = modname[:-9] + ' (package)'
1802 if find(modname, '.') < 0:
1803 modules[modname] = 1
1804 ModuleScanner().run(callback)
1805 self.list(modules.keys())
1806 self.output.write('''
1807Enter any module name to get more help. Or, type "modules spam" to search
1808for modules whose descriptions contain the word "spam".
1809''')
1810
1811help = Helper(sys.stdin, sys.stdout)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001812
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001813class Scanner:
1814 """A generic tree iterator."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001815 def __init__(self, roots, children, descendp):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001816 self.roots = roots[:]
1817 self.state = []
1818 self.children = children
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001819 self.descendp = descendp
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001820
1821 def next(self):
1822 if not self.state:
1823 if not self.roots:
1824 return None
1825 root = self.roots.pop(0)
1826 self.state = [(root, self.children(root))]
1827 node, children = self.state[-1]
1828 if not children:
1829 self.state.pop()
1830 return self.next()
1831 child = children.pop(0)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001832 if self.descendp(child):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001833 self.state.append((child, self.children(child)))
1834 return child
1835
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001836
1837class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001838 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001839
Ka-Ping Yee66246962001-04-12 11:59:50 +00001840 def run(self, callback, key=None, completer=None):
1841 if key: key = lower(key)
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001842 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001843 seen = {}
1844
1845 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001846 if modname != '__main__':
1847 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00001848 if key is None:
1849 callback(None, modname, '')
1850 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001851 desc = split(__import__(modname).__doc__ or '', '\n')[0]
Ka-Ping Yee66246962001-04-12 11:59:50 +00001852 if find(lower(modname + ' - ' + desc), key) >= 0:
1853 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001854
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001855 for importer, modname, ispkg in pkgutil.walk_packages():
1856 if self.quit:
1857 break
1858 if key is None:
1859 callback(None, modname, '')
1860 else:
1861 loader = importer.find_module(modname)
1862 if hasattr(loader,'get_source'):
1863 import StringIO
1864 desc = source_synopsis(
1865 StringIO.StringIO(loader.get_source(modname))
1866 ) or ''
1867 if hasattr(loader,'get_filename'):
1868 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00001869 else:
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001870 path = None
1871 else:
1872 module = loader.load_module(modname)
1873 desc = (module.__doc__ or '').splitlines()[0]
1874 path = getattr(module,'__file__',None)
1875 if find(lower(modname + ' - ' + desc), key) >= 0:
1876 callback(path, modname, desc)
1877
1878 if completer:
1879 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001880
1881def apropos(key):
1882 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001883 def callback(path, modname, desc):
1884 if modname[-9:] == '.__init__':
1885 modname = modname[:-9] + ' (package)'
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001886 print modname, desc and '- ' + desc
1887 try: import warnings
1888 except ImportError: pass
1889 else: warnings.filterwarnings('ignore') # ignore problems during import
Ka-Ping Yee66246962001-04-12 11:59:50 +00001890 ModuleScanner().run(callback, key)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001891
1892# --------------------------------------------------- web browser interface
1893
Ka-Ping Yee66246962001-04-12 11:59:50 +00001894def serve(port, callback=None, completer=None):
Ka-Ping Yeefd540692001-04-12 12:54:36 +00001895 import BaseHTTPServer, mimetools, select
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001896
1897 # Patch up mimetools.Message so it doesn't break if rfc822 is reloaded.
1898 class Message(mimetools.Message):
1899 def __init__(self, fp, seekable=1):
1900 Message = self.__class__
1901 Message.__bases__[0].__bases__[0].__init__(self, fp, seekable)
1902 self.encodingheader = self.getheader('content-transfer-encoding')
1903 self.typeheader = self.getheader('content-type')
1904 self.parsetype()
1905 self.parseplist()
1906
1907 class DocHandler(BaseHTTPServer.BaseHTTPRequestHandler):
1908 def send_document(self, title, contents):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001909 try:
1910 self.send_response(200)
1911 self.send_header('Content-Type', 'text/html')
1912 self.end_headers()
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001913 self.wfile.write(html.page(title, contents))
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001914 except IOError: pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001915
1916 def do_GET(self):
1917 path = self.path
1918 if path[-5:] == '.html': path = path[:-5]
1919 if path[:1] == '/': path = path[1:]
1920 if path and path != '.':
1921 try:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001922 obj = locate(path, forceload=1)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001923 except ErrorDuringImport, value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001924 self.send_document(path, html.escape(str(value)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001925 return
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001926 if obj:
1927 self.send_document(describe(obj), html.document(obj, path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001928 else:
1929 self.send_document(path,
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001930'no Python documentation found for %s' % repr(path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001931 else:
1932 heading = html.heading(
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001933'<big><big><strong>Python: Index of Modules</strong></big></big>',
1934'#ffffff', '#7799ee')
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001935 def bltinlink(name):
1936 return '<a href="%s.html">%s</a>' % (name, name)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001937 names = filter(lambda x: x != '__main__',
1938 sys.builtin_module_names)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001939 contents = html.multicolumn(names, bltinlink)
1940 indices = ['<p>' + html.bigsection(
1941 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
1942
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001943 seen = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001944 for dir in sys.path:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001945 indices.append(html.index(dir, seen))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001946 contents = heading + join(indices) + '''<p align=right>
Tim Peters2306d242001-09-25 03:18:32 +00001947<font color="#909090" face="helvetica, arial"><strong>
1948pydoc</strong> by Ka-Ping Yee &lt;ping@lfw.org&gt;</font>'''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001949 self.send_document('Index of Modules', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001950
1951 def log_message(self, *args): pass
1952
Ka-Ping Yeefd540692001-04-12 12:54:36 +00001953 class DocServer(BaseHTTPServer.HTTPServer):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001954 def __init__(self, port, callback):
Ka-Ping Yeedb8ed152001-03-02 05:58:17 +00001955 host = (sys.platform == 'mac') and '127.0.0.1' or 'localhost'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001956 self.address = ('', port)
Ka-Ping Yeedb8ed152001-03-02 05:58:17 +00001957 self.url = 'http://%s:%d/' % (host, port)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001958 self.callback = callback
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001959 self.base.__init__(self, self.address, self.handler)
1960
1961 def serve_until_quit(self):
1962 import select
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001963 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001964 while not self.quit:
1965 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
1966 if rd: self.handle_request()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001967
1968 def server_activate(self):
1969 self.base.server_activate(self)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001970 if self.callback: self.callback(self)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001971
1972 DocServer.base = BaseHTTPServer.HTTPServer
1973 DocServer.handler = DocHandler
1974 DocHandler.MessageClass = Message
1975 try:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001976 try:
1977 DocServer(port, callback).serve_until_quit()
1978 except (KeyboardInterrupt, select.error):
1979 pass
1980 finally:
Ka-Ping Yee66246962001-04-12 11:59:50 +00001981 if completer: completer()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001982
1983# ----------------------------------------------------- graphical interface
1984
1985def gui():
1986 """Graphical interface (starts web server and pops up a control window)."""
1987 class GUI:
1988 def __init__(self, window, port=7464):
1989 self.window = window
1990 self.server = None
1991 self.scanner = None
1992
1993 import Tkinter
1994 self.server_frm = Tkinter.Frame(window)
1995 self.title_lbl = Tkinter.Label(self.server_frm,
1996 text='Starting server...\n ')
1997 self.open_btn = Tkinter.Button(self.server_frm,
1998 text='open browser', command=self.open, state='disabled')
1999 self.quit_btn = Tkinter.Button(self.server_frm,
2000 text='quit serving', command=self.quit, state='disabled')
2001
2002 self.search_frm = Tkinter.Frame(window)
2003 self.search_lbl = Tkinter.Label(self.search_frm, text='Search for')
2004 self.search_ent = Tkinter.Entry(self.search_frm)
2005 self.search_ent.bind('<Return>', self.search)
2006 self.stop_btn = Tkinter.Button(self.search_frm,
2007 text='stop', pady=0, command=self.stop, state='disabled')
2008 if sys.platform == 'win32':
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002009 # Trying to hide and show this button crashes under Windows.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002010 self.stop_btn.pack(side='right')
2011
2012 self.window.title('pydoc')
2013 self.window.protocol('WM_DELETE_WINDOW', self.quit)
2014 self.title_lbl.pack(side='top', fill='x')
2015 self.open_btn.pack(side='left', fill='x', expand=1)
2016 self.quit_btn.pack(side='right', fill='x', expand=1)
2017 self.server_frm.pack(side='top', fill='x')
2018
2019 self.search_lbl.pack(side='left')
2020 self.search_ent.pack(side='right', fill='x', expand=1)
2021 self.search_frm.pack(side='top', fill='x')
2022 self.search_ent.focus_set()
2023
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002024 font = ('helvetica', sys.platform == 'win32' and 8 or 10)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002025 self.result_lst = Tkinter.Listbox(window, font=font, height=6)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002026 self.result_lst.bind('<Button-1>', self.select)
2027 self.result_lst.bind('<Double-Button-1>', self.goto)
2028 self.result_scr = Tkinter.Scrollbar(window,
2029 orient='vertical', command=self.result_lst.yview)
2030 self.result_lst.config(yscrollcommand=self.result_scr.set)
2031
2032 self.result_frm = Tkinter.Frame(window)
2033 self.goto_btn = Tkinter.Button(self.result_frm,
2034 text='go to selected', command=self.goto)
2035 self.hide_btn = Tkinter.Button(self.result_frm,
2036 text='hide results', command=self.hide)
2037 self.goto_btn.pack(side='left', fill='x', expand=1)
2038 self.hide_btn.pack(side='right', fill='x', expand=1)
2039
2040 self.window.update()
2041 self.minwidth = self.window.winfo_width()
2042 self.minheight = self.window.winfo_height()
2043 self.bigminheight = (self.server_frm.winfo_reqheight() +
2044 self.search_frm.winfo_reqheight() +
2045 self.result_lst.winfo_reqheight() +
2046 self.result_frm.winfo_reqheight())
2047 self.bigwidth, self.bigheight = self.minwidth, self.bigminheight
2048 self.expanded = 0
2049 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2050 self.window.wm_minsize(self.minwidth, self.minheight)
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002051 self.window.tk.willdispatch()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002052
2053 import threading
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002054 threading.Thread(
2055 target=serve, args=(port, self.ready, self.quit)).start()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002056
2057 def ready(self, server):
2058 self.server = server
2059 self.title_lbl.config(
2060 text='Python documentation server at\n' + server.url)
2061 self.open_btn.config(state='normal')
2062 self.quit_btn.config(state='normal')
2063
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002064 def open(self, event=None, url=None):
2065 url = url or self.server.url
2066 try:
2067 import webbrowser
2068 webbrowser.open(url)
2069 except ImportError: # pre-webbrowser.py compatibility
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002070 if sys.platform == 'win32':
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002071 os.system('start "%s"' % url)
2072 elif sys.platform == 'mac':
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002073 try: import ic
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002074 except ImportError: pass
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002075 else: ic.launchurl(url)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002076 else:
2077 rc = os.system('netscape -remote "openURL(%s)" &' % url)
2078 if rc: os.system('netscape "%s" &' % url)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002079
2080 def quit(self, event=None):
2081 if self.server:
2082 self.server.quit = 1
2083 self.window.quit()
2084
2085 def search(self, event=None):
2086 key = self.search_ent.get()
2087 self.stop_btn.pack(side='right')
2088 self.stop_btn.config(state='normal')
2089 self.search_lbl.config(text='Searching for "%s"...' % key)
2090 self.search_ent.forget()
2091 self.search_lbl.pack(side='left')
2092 self.result_lst.delete(0, 'end')
2093 self.goto_btn.config(state='disabled')
2094 self.expand()
2095
2096 import threading
2097 if self.scanner:
2098 self.scanner.quit = 1
2099 self.scanner = ModuleScanner()
2100 threading.Thread(target=self.scanner.run,
Ka-Ping Yee6dcfa382001-04-12 20:27:31 +00002101 args=(self.update, key, self.done)).start()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002102
2103 def update(self, path, modname, desc):
2104 if modname[-9:] == '.__init__':
2105 modname = modname[:-9] + ' (package)'
2106 self.result_lst.insert('end',
2107 modname + ' - ' + (desc or '(no description)'))
2108
2109 def stop(self, event=None):
2110 if self.scanner:
2111 self.scanner.quit = 1
2112 self.scanner = None
2113
2114 def done(self):
2115 self.scanner = None
2116 self.search_lbl.config(text='Search for')
2117 self.search_lbl.pack(side='left')
2118 self.search_ent.pack(side='right', fill='x', expand=1)
2119 if sys.platform != 'win32': self.stop_btn.forget()
2120 self.stop_btn.config(state='disabled')
2121
2122 def select(self, event=None):
2123 self.goto_btn.config(state='normal')
2124
2125 def goto(self, event=None):
2126 selection = self.result_lst.curselection()
2127 if selection:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002128 modname = split(self.result_lst.get(selection[0]))[0]
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002129 self.open(url=self.server.url + modname + '.html')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002130
2131 def collapse(self):
2132 if not self.expanded: return
2133 self.result_frm.forget()
2134 self.result_scr.forget()
2135 self.result_lst.forget()
2136 self.bigwidth = self.window.winfo_width()
2137 self.bigheight = self.window.winfo_height()
2138 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2139 self.window.wm_minsize(self.minwidth, self.minheight)
2140 self.expanded = 0
2141
2142 def expand(self):
2143 if self.expanded: return
2144 self.result_frm.pack(side='bottom', fill='x')
2145 self.result_scr.pack(side='right', fill='y')
2146 self.result_lst.pack(side='top', fill='both', expand=1)
2147 self.window.wm_geometry('%dx%d' % (self.bigwidth, self.bigheight))
2148 self.window.wm_minsize(self.minwidth, self.bigminheight)
2149 self.expanded = 1
2150
2151 def hide(self, event=None):
2152 self.stop()
2153 self.collapse()
2154
2155 import Tkinter
2156 try:
Martin v. Löwise09bd932004-08-22 16:13:26 +00002157 root = Tkinter.Tk()
2158 # Tk will crash if pythonw.exe has an XP .manifest
2159 # file and the root has is not destroyed explicitly.
2160 # If the problem is ever fixed in Tk, the explicit
2161 # destroy can go.
2162 try:
2163 gui = GUI(root)
2164 root.mainloop()
2165 finally:
2166 root.destroy()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002167 except KeyboardInterrupt:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002168 pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002169
2170# -------------------------------------------------- command-line interface
2171
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002172def ispath(x):
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002173 return isinstance(x, str) and find(x, os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002174
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002175def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002176 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002177 import getopt
2178 class BadUsage: pass
2179
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002180 # Scripts don't get the current directory in their path by default.
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +00002181 scriptdir = os.path.dirname(sys.argv[0])
2182 if scriptdir in sys.path:
2183 sys.path.remove(scriptdir)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002184 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002185
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002186 try:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002187 opts, args = getopt.getopt(sys.argv[1:], 'gk:p:w')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002188 writing = 0
2189
2190 for opt, val in opts:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002191 if opt == '-g':
2192 gui()
2193 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002194 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002195 apropos(val)
2196 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002197 if opt == '-p':
2198 try:
2199 port = int(val)
2200 except ValueError:
2201 raise BadUsage
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002202 def ready(server):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002203 print 'pydoc server ready at %s' % server.url
2204 def stopped():
2205 print 'pydoc server stopped'
2206 serve(port, ready, stopped)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002207 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002208 if opt == '-w':
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002209 writing = 1
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002210
2211 if not args: raise BadUsage
2212 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002213 if ispath(arg) and not os.path.exists(arg):
2214 print 'file %r does not exist' % arg
2215 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002216 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002217 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002218 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002219 if writing:
2220 if ispath(arg) and os.path.isdir(arg):
2221 writedocs(arg)
2222 else:
2223 writedoc(arg)
2224 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002225 help.help(arg)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002226 except ErrorDuringImport, value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002227 print value
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002228
2229 except (getopt.error, BadUsage):
Martin v. Löwisf9b08b82003-10-31 13:05:21 +00002230 cmd = os.path.basename(sys.argv[0])
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002231 print """pydoc - the Python documentation tool
2232
2233%s <name> ...
2234 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002235 Python keyword, topic, function, module, or package, or a dotted
2236 reference to a class or function within a module or module in a
2237 package. If <name> contains a '%s', it is used as the path to a
2238 Python source file to document. If name is 'keywords', 'topics',
2239 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002240
2241%s -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002242 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002243
2244%s -p <port>
2245 Start an HTTP server on the given port on the local machine.
2246
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002247%s -g
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002248 Pop up a graphical interface for finding and serving documentation.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002249
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002250%s -w <name> ...
2251 Write out the HTML documentation for a module to a file in the current
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002252 directory. If <name> contains a '%s', it is treated as a filename; if
2253 it names a directory, documentation is written for all the contents.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002254""" % (cmd, os.sep, cmd, cmd, cmd, cmd, os.sep)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002255
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002256if __name__ == '__main__': cli()