blob: 8b6f7ee2e3ec073a0440402fe7250c395c62de64 [file] [log] [blame]
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001#!/usr/bin/env python
Georg Brandl681001e2008-06-01 20:33:55 +00002# -*- coding: latin-1 -*-
Ka-Ping Yee1d384632001-03-01 00:24:32 +00003"""Generate Python documentation in HTML or text for interactive use.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00004
Ka-Ping Yeedd175342001-02-27 14:43:46 +00005In the Python interpreter, do "from pydoc import help" to provide online
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00006help. Calling help(thing) on a Python object documents the object.
7
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00008Or, at the shell command line outside of Python:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00009
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000010Run "pydoc <name>" to show documentation on something. <name> may be
11the name of a function, module, package, or a dotted reference to a
12class or function within a module or module in a package. If the
13argument contains a path segment delimiter (e.g. slash on Unix,
14backslash on Windows) it is treated as the path to a Python source file.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000015
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000016Run "pydoc -k <keyword>" to search for a keyword in the synopsis lines
17of all available modules.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000018
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000019Run "pydoc -p <port>" to start an HTTP server on a given port on the
20local machine to generate documentation web pages.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000021
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000022For platforms without a command line, "pydoc -g" starts the HTTP server
23and also pops up a little window for controlling it.
24
25Run "pydoc -w <name>" to write out the HTML documentation for a module
26to a file named "<name>.html".
Skip Montanaro4997a692003-09-10 16:47:51 +000027
28Module docs for core modules are assumed to be in
29
Georg Brandl0751d1a2008-01-21 17:13:03 +000030 http://docs.python.org/library/
Skip Montanaro4997a692003-09-10 16:47:51 +000031
32This can be overridden by setting the PYTHONDOCS environment variable
33to a different URL or to a local directory containing the Library
34Reference Manual pages.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000035"""
Ka-Ping Yeedd175342001-02-27 14:43:46 +000036
37__author__ = "Ka-Ping Yee <ping@lfw.org>"
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000038__date__ = "26 February 2001"
Jeremy Hylton3e0055f2005-10-20 19:59:25 +000039
Ka-Ping Yee09d7d9a2001-02-27 22:43:48 +000040__version__ = "$Revision$"
Martin v. Löwis6fe8f192004-11-14 10:21:04 +000041__credits__ = """Guido van Rossum, for an excellent programming language.
Ka-Ping Yee5e2b1732001-02-27 23:35:09 +000042Tommy Burnette, the original creator of manpy.
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000043Paul Prescod, for all his work on onlinehelp.
44Richard Chamberlain, for the first implementation of textdoc.
Raymond Hettingered2dbe32005-01-01 07:51:01 +000045"""
Ka-Ping Yeedd175342001-02-27 14:43:46 +000046
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000047# Known bugs that can't be fixed here:
48# - imp.load_module() cannot be prevented from clobbering existing
49# loaded modules, so calling synopsis() on a binary module file
50# changes the contents of any existing module with the same name.
51# - If the __file__ attribute on a module is a relative path and
52# the current directory is changed with os.chdir(), an incorrect
53# path will be displayed.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000054
Phillip J. Ebyceb30872006-04-18 00:59:55 +000055import sys, imp, os, re, types, inspect, __builtin__, pkgutil
Brett Cannon2ee0e8e2008-05-23 05:03:59 +000056from repr import Repr
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000057from string import expandtabs, find, join, lower, split, strip, rfind, rstrip
R. David Murrayef087da2009-06-23 18:02:46 +000058from traceback import extract_tb
Phillip J. Ebyceb30872006-04-18 00:59:55 +000059try:
60 from collections import deque
61except ImportError:
62 # Python 2.3 compatibility
63 class deque(list):
64 def popleft(self):
65 return self.pop(0)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000066
67# --------------------------------------------------------- common routines
68
Ka-Ping Yeedd175342001-02-27 14:43:46 +000069def pathdirs():
70 """Convert sys.path into a list of absolute, existing, unique paths."""
71 dirs = []
Ka-Ping Yee1d384632001-03-01 00:24:32 +000072 normdirs = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +000073 for dir in sys.path:
74 dir = os.path.abspath(dir or '.')
Ka-Ping Yee1d384632001-03-01 00:24:32 +000075 normdir = os.path.normcase(dir)
76 if normdir not in normdirs and os.path.isdir(dir):
Ka-Ping Yeedd175342001-02-27 14:43:46 +000077 dirs.append(dir)
Ka-Ping Yee1d384632001-03-01 00:24:32 +000078 normdirs.append(normdir)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000079 return dirs
80
81def getdoc(object):
82 """Get the doc string or comments for an object."""
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000083 result = inspect.getdoc(object) or inspect.getcomments(object)
Ka-Ping Yee239432a2001-03-02 02:45:08 +000084 return result and re.sub('^ *\n', '', rstrip(result)) or ''
Ka-Ping Yeedd175342001-02-27 14:43:46 +000085
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000086def splitdoc(doc):
87 """Split a doc string into a synopsis line (if any) and the rest."""
88 lines = split(strip(doc), '\n')
89 if len(lines) == 1:
90 return lines[0], ''
91 elif len(lines) >= 2 and not rstrip(lines[1]):
92 return lines[0], join(lines[2:], '\n')
93 return '', join(lines, '\n')
94
Ka-Ping Yeedd175342001-02-27 14:43:46 +000095def classname(object, modname):
96 """Get a class name and qualify it with a module name if necessary."""
97 name = object.__name__
98 if object.__module__ != modname:
99 name = object.__module__ + '.' + name
100 return name
101
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000102def isdata(object):
Georg Brandl94432422005-07-22 21:52:25 +0000103 """Check if an object is of a type that probably means it's data."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000104 return not (inspect.ismodule(object) or inspect.isclass(object) or
105 inspect.isroutine(object) or inspect.isframe(object) or
106 inspect.istraceback(object) or inspect.iscode(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000107
108def replace(text, *pairs):
109 """Do a series of global replacements on a string."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000110 while pairs:
111 text = join(split(text, pairs[0]), pairs[1])
112 pairs = pairs[2:]
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000113 return text
114
115def cram(text, maxlen):
116 """Omit part of a string if needed to make it fit in a maximum length."""
117 if len(text) > maxlen:
Raymond Hettingerfca3bb62002-10-21 04:44:11 +0000118 pre = max(0, (maxlen-3)//2)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000119 post = max(0, maxlen-3-pre)
120 return text[:pre] + '...' + text[len(text)-post:]
121 return text
122
Brett Cannon84601f12004-06-19 01:22:48 +0000123_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000124def stripid(text):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000125 """Remove the hexadecimal id from a Python object representation."""
Brett Cannonc6c1f472004-06-19 01:02:51 +0000126 # The behaviour of %p is implementation-dependent in terms of case.
Ezio Melottie511fc72010-02-16 23:26:09 +0000127 return _re_stripid.sub(r'\1', text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000128
Brett Cannonc6c1f472004-06-19 01:02:51 +0000129def _is_some_method(obj):
130 return inspect.ismethod(obj) or inspect.ismethoddescriptor(obj)
Tim Peters536d2262001-09-20 05:13:38 +0000131
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000132def allmethods(cl):
133 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000134 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000135 methods[key] = 1
136 for base in cl.__bases__:
137 methods.update(allmethods(base)) # all your base are belong to us
138 for key in methods.keys():
139 methods[key] = getattr(cl, key)
140 return methods
141
Tim Petersfa26f7c2001-09-24 08:05:11 +0000142def _split_list(s, predicate):
143 """Split sequence s via predicate, and return pair ([true], [false]).
144
145 The return value is a 2-tuple of lists,
146 ([x for x in s if predicate(x)],
147 [x for x in s if not predicate(x)])
148 """
149
Tim Peters28355492001-09-23 21:29:55 +0000150 yes = []
151 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000152 for x in s:
153 if predicate(x):
154 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000155 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000156 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000157 return yes, no
158
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700159def visiblename(name, all=None, obj=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000160 """Decide whether to show documentation on a variable."""
161 # Certain special names are redundant.
Nick Coghlanc060b0e2008-07-02 13:09:19 +0000162 _hidden_names = ('__builtins__', '__doc__', '__file__', '__path__',
163 '__module__', '__name__', '__slots__', '__package__')
164 if name in _hidden_names: return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000165 # Private names are hidden, but special names are displayed.
166 if name.startswith('__') and name.endswith('__'): return 1
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700167 # Namedtuples have public fields and methods with a single leading underscore
168 if name.startswith('_') and hasattr(obj, '_fields'):
169 return 1
Skip Montanaroa5616d22004-06-11 04:46:12 +0000170 if all is not None:
171 # only document that which the programmer exported in __all__
172 return name in all
173 else:
174 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000175
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000176def classify_class_attrs(object):
177 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Brett Cannonaca98b02008-08-03 00:58:51 +0000178 def fixup(data):
179 name, kind, cls, value = data
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000180 if inspect.isdatadescriptor(value):
181 kind = 'data descriptor'
182 return name, kind, cls, value
183 return map(fixup, inspect.classify_class_attrs(object))
184
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000185# ----------------------------------------------------- module manipulation
186
187def ispackage(path):
188 """Guess whether a path refers to a package directory."""
189 if os.path.isdir(path):
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000190 for ext in ('.py', '.pyc', '.pyo'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000191 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000192 return True
193 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000194
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000195def source_synopsis(file):
196 line = file.readline()
197 while line[:1] == '#' or not strip(line):
198 line = file.readline()
199 if not line: break
200 line = strip(line)
201 if line[:4] == 'r"""': line = line[1:]
202 if line[:3] == '"""':
203 line = line[3:]
204 if line[-1:] == '\\': line = line[:-1]
205 while not strip(line):
206 line = file.readline()
207 if not line: break
208 result = strip(split(line, '"""')[0])
209 else: result = None
210 return result
211
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000212def synopsis(filename, cache={}):
213 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000214 mtime = os.stat(filename).st_mtime
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000215 lastupdate, result = cache.get(filename, (0, None))
216 if lastupdate < mtime:
217 info = inspect.getmoduleinfo(filename)
Georg Brandl26fd2e12006-03-08 09:34:53 +0000218 try:
219 file = open(filename)
220 except IOError:
221 # module can't be opened, so skip it
222 return None
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000223 if info and 'b' in info[2]: # binary modules have to be imported
224 try: module = imp.load_module('__temp__', file, filename, info[1:])
225 except: return None
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000226 result = (module.__doc__ or '').splitlines()[0]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000227 del sys.modules['__temp__']
228 else: # text modules can be directly examined
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000229 result = source_synopsis(file)
230 file.close()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000231 cache[filename] = (mtime, result)
232 return result
233
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000234class ErrorDuringImport(Exception):
235 """Errors that occurred while trying to import something to document it."""
Brett Cannonaca98b02008-08-03 00:58:51 +0000236 def __init__(self, filename, exc_info):
237 exc, value, tb = exc_info
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000238 self.filename = filename
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000239 self.exc = exc
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000240 self.value = value
241 self.tb = tb
242
243 def __str__(self):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000244 exc = self.exc
245 if type(exc) is types.ClassType:
246 exc = exc.__name__
247 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000248
249def importfile(path):
250 """Import a Python source file or compiled file given its path."""
251 magic = imp.get_magic()
252 file = open(path, 'r')
253 if file.read(len(magic)) == magic:
254 kind = imp.PY_COMPILED
255 else:
256 kind = imp.PY_SOURCE
257 file.close()
258 filename = os.path.basename(path)
259 name, ext = os.path.splitext(filename)
260 file = open(path, 'r')
261 try:
262 module = imp.load_module(name, file, path, (ext, 'r', kind))
263 except:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000264 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000265 file.close()
266 return module
267
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000268def safeimport(path, forceload=0, cache={}):
269 """Import a module; handle errors; return None if the module isn't found.
270
271 If the module *is* found but an exception occurs, it's wrapped in an
272 ErrorDuringImport exception and reraised. Unlike __import__, if a
273 package path is specified, the module at the end of the path is returned,
274 not the package at the beginning. If the optional 'forceload' argument
275 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000276 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000277 # If forceload is 1 and the module has been previously loaded from
278 # disk, we always have to reload the module. Checking the file's
279 # mtime isn't good enough (e.g. the module could contain a class
280 # that inherits from another module that has changed).
281 if forceload and path in sys.modules:
282 if path not in sys.builtin_module_names:
283 # Avoid simply calling reload() because it leaves names in
284 # the currently loaded module lying around if they're not
285 # defined in the new source file. Instead, remove the
286 # module from sys.modules and re-import. Also remove any
287 # submodules because they won't appear in the newly loaded
288 # module's namespace if they're already in sys.modules.
289 subs = [m for m in sys.modules if m.startswith(path + '.')]
290 for key in [path] + subs:
291 # Prevent garbage collection.
292 cache[key] = sys.modules[key]
293 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000294 module = __import__(path)
295 except:
296 # Did the error occur before or after the module was found?
297 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000298 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000299 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000300 raise ErrorDuringImport(sys.modules[path].__file__, info)
301 elif exc is SyntaxError:
302 # A SyntaxError occurred before we could execute the module.
303 raise ErrorDuringImport(value.filename, info)
R. David Murrayef087da2009-06-23 18:02:46 +0000304 elif exc is ImportError and extract_tb(tb)[-1][2]=='safeimport':
305 # The import error occurred directly in this function,
306 # which means there is no such module in the path.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000307 return None
308 else:
309 # Some other error occurred during the importing process.
310 raise ErrorDuringImport(path, sys.exc_info())
311 for part in split(path, '.')[1:]:
312 try: module = getattr(module, part)
313 except AttributeError: return None
314 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000315
316# ---------------------------------------------------- formatter base class
317
318class Doc:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000319 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000320 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000321 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000322 # 'try' clause is to attempt to handle the possibility that inspect
323 # identifies something in a way that pydoc itself has issues handling;
324 # think 'super' and how it is a descriptor (which raises the exception
325 # by lacking a __name__ attribute) and an instance.
Barry Warsaw00decd72006-07-27 23:43:15 +0000326 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
327 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000328 try:
329 if inspect.ismodule(object): return self.docmodule(*args)
330 if inspect.isclass(object): return self.docclass(*args)
331 if inspect.isroutine(object): return self.docroutine(*args)
332 except AttributeError:
333 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000334 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000335 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000336
337 def fail(self, object, name=None, *args):
338 """Raise an exception for unimplemented types."""
339 message = "don't know how to document object%s of type %s" % (
340 name and ' ' + repr(name), type(object).__name__)
341 raise TypeError, message
342
Barry Warsaw00decd72006-07-27 23:43:15 +0000343 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000344
Skip Montanaro4997a692003-09-10 16:47:51 +0000345 def getdocloc(self, object):
346 """Return the location of module docs or None"""
347
348 try:
349 file = inspect.getabsfile(object)
350 except TypeError:
351 file = '(built-in)'
352
353 docloc = os.environ.get("PYTHONDOCS",
Georg Brandl0751d1a2008-01-21 17:13:03 +0000354 "http://docs.python.org/library")
Skip Montanaro4997a692003-09-10 16:47:51 +0000355 basedir = os.path.join(sys.exec_prefix, "lib",
356 "python"+sys.version[0:3])
357 if (isinstance(object, type(os)) and
358 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
359 'marshal', 'posix', 'signal', 'sys',
360 'thread', 'zipimport') or
361 (file.startswith(basedir) and
Brian Curtinaeb2e822010-03-31 03:10:21 +0000362 not file.startswith(os.path.join(basedir, 'site-packages')))) and
Brian Curtina01da932010-04-01 04:02:00 +0000363 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
Skip Montanaro4997a692003-09-10 16:47:51 +0000364 if docloc.startswith("http://"):
Georg Brandl0751d1a2008-01-21 17:13:03 +0000365 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
Skip Montanaro4997a692003-09-10 16:47:51 +0000366 else:
Georg Brandl0751d1a2008-01-21 17:13:03 +0000367 docloc = os.path.join(docloc, object.__name__ + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000368 else:
369 docloc = None
370 return docloc
371
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000372# -------------------------------------------- HTML documentation generator
373
374class HTMLRepr(Repr):
375 """Class for safely making an HTML representation of a Python object."""
376 def __init__(self):
377 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000378 self.maxlist = self.maxtuple = 20
379 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000380 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000381
382 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000383 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000384
385 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000386 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000387
388 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000389 if hasattr(type(x), '__name__'):
390 methodname = 'repr_' + join(split(type(x).__name__), '_')
391 if hasattr(self, methodname):
392 return getattr(self, methodname)(x, level)
393 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000394
395 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000396 test = cram(x, self.maxstring)
397 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000398 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000399 # Backslashes are only literal in the string and are never
400 # needed to make any special characters, so show a raw string.
401 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000402 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000403 r'<font color="#c040c0">\1</font>',
404 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000405
Skip Montanarodf708782002-03-07 22:58:02 +0000406 repr_str = repr_string
407
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000408 def repr_instance(self, x, level):
409 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000410 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000411 except:
412 return self.escape('<%s instance>' % x.__class__.__name__)
413
414 repr_unicode = repr_string
415
416class HTMLDoc(Doc):
417 """Formatter class for HTML documentation."""
418
419 # ------------------------------------------- HTML formatting utilities
420
421 _repr_instance = HTMLRepr()
422 repr = _repr_instance.repr
423 escape = _repr_instance.escape
424
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000425 def page(self, title, contents):
426 """Format an HTML page."""
427 return '''
Georg Brandle0197062009-04-10 08:20:23 +0000428<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000429<html><head><title>Python: %s</title>
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000430</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000431%s
432</body></html>''' % (title, contents)
433
434 def heading(self, title, fgcol, bgcol, extras=''):
435 """Format a page heading."""
436 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000437<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000438<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000439<td valign=bottom>&nbsp;<br>
440<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000441><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000442><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000443 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
444
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000445 def section(self, title, fgcol, bgcol, contents, width=6,
446 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000447 """Format a section with a heading."""
448 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000449 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000450 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000451<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000452<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000453<td colspan=3 valign=bottom>&nbsp;<br>
454<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000455 ''' % (bgcol, fgcol, title)
456 if prelude:
457 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000458<tr bgcolor="%s"><td rowspan=2>%s</td>
459<td colspan=2>%s</td></tr>
460<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
461 else:
462 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000463<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000464
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000465 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000466
467 def bigsection(self, title, *args):
468 """Format a section with a big heading."""
469 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000470 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000471
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000472 def preformat(self, text):
473 """Format literal preformatted text."""
474 text = self.escape(expandtabs(text))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000475 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
476 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000477
478 def multicolumn(self, list, format, cols=4):
479 """Format a list of items into a multi-column list."""
480 result = ''
481 rows = (len(list)+cols-1)/cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000482 for col in range(cols):
483 result = result + '<td width="%d%%" valign=top>' % (100/cols)
484 for i in range(rows*col, rows*col+rows):
485 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000486 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000487 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000488 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000489
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000490 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000491
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000492 def namelink(self, name, *dicts):
493 """Make a link for an identifier, given name-to-URL mappings."""
494 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000495 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000496 return '<a href="%s">%s</a>' % (dict[name], name)
497 return name
498
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000499 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000500 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000501 name, module = object.__name__, sys.modules.get(object.__module__)
502 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000503 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000504 module.__name__, name, classname(object, modname))
505 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000506
507 def modulelink(self, object):
508 """Make a link for a module."""
509 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
510
Brett Cannonaca98b02008-08-03 00:58:51 +0000511 def modpkglink(self, data):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000512 """Make a link for a module or package to display in an index."""
Brett Cannonaca98b02008-08-03 00:58:51 +0000513 name, path, ispackage, shadowed = data
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000514 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000515 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000516 if path:
517 url = '%s.%s.html' % (path, name)
518 else:
519 url = '%s.html' % name
520 if ispackage:
521 text = '<strong>%s</strong>&nbsp;(package)' % name
522 else:
523 text = name
524 return '<a href="%s">%s</a>' % (url, text)
525
526 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
527 """Mark up some plain text, given a context of symbols to look for.
528 Each context dictionary maps object names to anchor names."""
529 escape = escape or self.escape
530 results = []
531 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000532 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
533 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000534 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000535 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000536 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000537 match = pattern.search(text, here)
538 if not match: break
539 start, end = match.span()
540 results.append(escape(text[here:start]))
541
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000542 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000543 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000544 url = escape(all).replace('"', '&quot;')
545 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000546 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000547 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
548 results.append('<a href="%s">%s</a>' % (url, escape(all)))
549 elif pep:
Andrew M. Kuchling727a5902008-02-05 16:06:57 +0000550 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000551 results.append('<a href="%s">%s</a>' % (url, escape(all)))
552 elif text[end:end+1] == '(':
553 results.append(self.namelink(name, methods, funcs, classes))
554 elif selfdot:
555 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000556 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000557 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000558 here = end
559 results.append(escape(text[here:]))
560 return join(results, '')
561
562 # ---------------------------------------------- type-specific routines
563
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000564 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000565 """Produce HTML for a class tree as given by inspect.getclasstree()."""
566 result = ''
567 for entry in tree:
568 if type(entry) is type(()):
569 c, bases = entry
Tim Peters2306d242001-09-25 03:18:32 +0000570 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000571 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000572 if bases and bases != (parent,):
573 parents = []
574 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000575 parents.append(self.classlink(base, modname))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000576 result = result + '(' + join(parents, ', ') + ')'
Tim Peters2306d242001-09-25 03:18:32 +0000577 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000578 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000579 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000580 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000581 return '<dl>\n%s</dl>\n' % result
582
Tim Peters8dd7ade2001-10-18 19:56:17 +0000583 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000584 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000585 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000586 try:
587 all = object.__all__
588 except AttributeError:
589 all = None
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000590 parts = split(name, '.')
591 links = []
592 for i in range(len(parts)-1):
593 links.append(
594 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
595 (join(parts[:i+1], '.'), parts[i]))
596 linkedname = join(links + parts[-1:], '.')
597 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000598 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000599 path = inspect.getabsfile(object)
Ka-Ping Yee6191a232001-04-13 15:00:27 +0000600 url = path
601 if sys.platform == 'win32':
602 import nturl2path
603 url = nturl2path.pathname2url(path)
604 filelink = '<a href="file:%s">%s</a>' % (url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000605 except TypeError:
606 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000607 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000608 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000609 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000610 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
611 version = strip(version[11:-1])
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000612 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000613 if hasattr(object, '__date__'):
614 info.append(self.escape(str(object.__date__)))
615 if info:
616 head = head + ' (%s)' % join(info, ', ')
Skip Montanaro4997a692003-09-10 16:47:51 +0000617 docloc = self.getdocloc(object)
618 if docloc is not None:
619 docloc = '<br><a href="%(docloc)s">Module Docs</a>' % locals()
620 else:
621 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000622 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000623 head, '#ffffff', '#7799ee',
624 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000625
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000626 modules = inspect.getmembers(object, inspect.ismodule)
627
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000628 classes, cdict = [], {}
629 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000630 # if __all__ exists, believe it. Otherwise use old heuristic.
631 if (all is not None or
632 (inspect.getmodule(value) or object) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700633 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000634 classes.append((key, value))
635 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000636 for key, value in classes:
637 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000638 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000639 module = sys.modules.get(modname)
640 if modname != name and module and hasattr(module, key):
641 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000642 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000643 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000644 funcs, fdict = [], {}
645 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000646 # if __all__ exists, believe it. Otherwise use old heuristic.
647 if (all is not None or
648 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700649 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000650 funcs.append((key, value))
651 fdict[key] = '#-' + key
652 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000653 data = []
654 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700655 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000656 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000657
658 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
659 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000660 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000661
662 if hasattr(object, '__path__'):
663 modpkgs = []
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000664 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
665 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000666 modpkgs.sort()
667 contents = self.multicolumn(modpkgs, self.modpkglink)
668 result = result + self.bigsection(
669 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000670 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000671 contents = self.multicolumn(
Brett Cannonaca98b02008-08-03 00:58:51 +0000672 modules, lambda key_value, s=self: s.modulelink(key_value[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000673 result = result + self.bigsection(
Georg Brandlb169eaa2008-02-17 21:18:55 +0000674 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000675
676 if classes:
Brett Cannonaca98b02008-08-03 00:58:51 +0000677 classlist = map(lambda key_value: key_value[1], classes)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000678 contents = [
679 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000680 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000681 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000682 result = result + self.bigsection(
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000683 'Classes', '#ffffff', '#ee77aa', join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000684 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000685 contents = []
686 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000687 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000688 result = result + self.bigsection(
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000689 'Functions', '#ffffff', '#eeaa77', join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000690 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000691 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000692 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000693 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000694 result = result + self.bigsection(
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000695 'Data', '#ffffff', '#55aa55', join(contents, '<br>\n'))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000696 if hasattr(object, '__author__'):
697 contents = self.markup(str(object.__author__), self.preformat)
698 result = result + self.bigsection(
699 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000700 if hasattr(object, '__credits__'):
701 contents = self.markup(str(object.__credits__), self.preformat)
702 result = result + self.bigsection(
703 'Credits', '#ffffff', '#7799ee', contents)
704
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000705 return result
706
Tim Peters8dd7ade2001-10-18 19:56:17 +0000707 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
708 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000709 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000710 realname = object.__name__
711 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000712 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000713
Tim Petersb47879b2001-09-24 04:47:19 +0000714 contents = []
715 push = contents.append
716
Tim Petersfa26f7c2001-09-24 08:05:11 +0000717 # Cute little class to pump out a horizontal rule between sections.
718 class HorizontalRule:
719 def __init__(self):
720 self.needone = 0
721 def maybe(self):
722 if self.needone:
723 push('<hr>\n')
724 self.needone = 1
725 hr = HorizontalRule()
726
Tim Petersc86f6ca2001-09-26 21:31:51 +0000727 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000728 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000729 if len(mro) > 2:
730 hr.maybe()
731 push('<dl><dt>Method resolution order:</dt>\n')
732 for base in mro:
733 push('<dd>%s</dd>\n' % self.classlink(base,
734 object.__module__))
735 push('</dl>\n')
736
Tim Petersb47879b2001-09-24 04:47:19 +0000737 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000738 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000739 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000740 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000741 push(msg)
742 for name, kind, homecls, value in ok:
743 push(self.document(getattr(object, name), name, mod,
744 funcs, classes, mdict, object))
745 push('\n')
746 return attrs
747
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000748 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000749 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000750 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000751 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000752 push(msg)
753 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000754 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000755 return attrs
756
Tim Petersfa26f7c2001-09-24 08:05:11 +0000757 def spilldata(msg, attrs, predicate):
758 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000759 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000760 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000761 push(msg)
762 for name, kind, homecls, value in ok:
763 base = self.docother(getattr(object, name), name, mod)
Brett Cannonaca98b02008-08-03 00:58:51 +0000764 if (hasattr(value, '__call__') or
765 inspect.isdatadescriptor(value)):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000766 doc = getattr(value, "__doc__", None)
767 else:
768 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000769 if doc is None:
770 push('<dl><dt>%s</dl>\n' % base)
771 else:
772 doc = self.markup(getdoc(value), self.preformat,
773 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000774 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000775 push('<dl><dt>%s%s</dl>\n' % (base, doc))
776 push('\n')
777 return attrs
778
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700779 attrs = filter(lambda data: visiblename(data[0], obj=object),
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000780 classify_class_attrs(object))
Tim Petersb47879b2001-09-24 04:47:19 +0000781 mdict = {}
782 for key, kind, homecls, value in attrs:
783 mdict[key] = anchor = '#' + name + '-' + key
784 value = getattr(object, key)
785 try:
786 # The value may not be hashable (e.g., a data attr with
787 # a dict or list value).
788 mdict[value] = anchor
789 except TypeError:
790 pass
791
Tim Petersfa26f7c2001-09-24 08:05:11 +0000792 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000793 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000794 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000795 else:
796 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000797 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
798
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000799 if thisclass is __builtin__.object:
800 attrs = inherited
801 continue
802 elif thisclass is object:
803 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000804 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000805 tag = 'inherited from %s' % self.classlink(thisclass,
806 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000807 tag += ':<br>\n'
808
809 # Sort attrs by name.
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000810 try:
811 attrs.sort(key=lambda t: t[0])
812 except TypeError:
813 attrs.sort(lambda t1, t2: cmp(t1[0], t2[0])) # 2.3 compat
Tim Petersb47879b2001-09-24 04:47:19 +0000814
815 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000816 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000817 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000818 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000819 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000820 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000821 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000822 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
823 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000824 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000825 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000826 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000827 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000828
829 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000830
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000831 if name == realname:
832 title = '<a name="%s">class <strong>%s</strong></a>' % (
833 name, realname)
834 else:
835 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
836 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000837 if bases:
838 parents = []
839 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000840 parents.append(self.classlink(base, object.__module__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000841 title = title + '(%s)' % join(parents, ', ')
Tim Peters2306d242001-09-25 03:18:32 +0000842 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000843 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000844
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000845 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000846
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000847 def formatvalue(self, object):
848 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000849 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000850
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000851 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000852 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000853 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000854 realname = object.__name__
855 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000856 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000857 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000858 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000859 if inspect.ismethod(object):
Ka-Ping Yee6dcfa382001-04-12 20:27:31 +0000860 imclass = object.im_class
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000861 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000862 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000863 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000864 else:
Georg Brandl7e2b6bb2007-03-13 22:16:30 +0000865 if object.im_self is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000866 note = ' method of %s instance' % self.classlink(
867 object.im_self.__class__, mod)
868 else:
869 note = ' unbound %s method' % self.classlink(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000870 object = object.im_func
871
872 if name == realname:
873 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
874 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000875 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000876 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000877 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000878 cl.__name__ + '-' + realname, realname)
879 skipdocs = 1
880 else:
881 reallink = realname
882 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
883 anchor, name, reallink)
Tim Peters4bcfa312001-09-20 06:08:24 +0000884 if inspect.isfunction(object):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000885 args, varargs, varkw, defaults = inspect.getargspec(object)
886 argspec = inspect.formatargspec(
887 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000888 if realname == '<lambda>':
Tim Peters59ed4482001-10-31 04:20:26 +0000889 title = '<strong>%s</strong> <em>lambda</em> ' % name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000890 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +0000891 else:
892 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000893
Tim Peters2306d242001-09-25 03:18:32 +0000894 decl = title + argspec + (note and self.grey(
895 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000896
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000897 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000898 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000899 else:
900 doc = self.markup(
901 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000902 doc = doc and '<dd><tt>%s</tt></dd>' % doc
903 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000904
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000905 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000906 results = []
907 push = results.append
908
909 if name:
910 push('<dl><dt><strong>%s</strong></dt>\n' % name)
911 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000912 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000913 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000914 push('</dl>\n')
915
916 return ''.join(results)
917
918 def docproperty(self, object, name=None, mod=None, cl=None):
919 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000920 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000921
Tim Peters8dd7ade2001-10-18 19:56:17 +0000922 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000923 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000924 lhs = name and '<strong>%s</strong> = ' % name or ''
925 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000926
Barry Warsaw00decd72006-07-27 23:43:15 +0000927 def docdata(self, object, name=None, mod=None, cl=None):
928 """Produce html documentation for a data descriptor."""
929 return self._docdescriptor(name, object, mod)
930
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000931 def index(self, dir, shadowed=None):
932 """Generate an HTML index for a directory of modules."""
933 modpkgs = []
934 if shadowed is None: shadowed = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000935 for importer, name, ispkg in pkgutil.iter_modules([dir]):
936 modpkgs.append((name, '', ispkg, name in shadowed))
937 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000938
939 modpkgs.sort()
940 contents = self.multicolumn(modpkgs, self.modpkglink)
941 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
942
943# -------------------------------------------- text documentation generator
944
945class TextRepr(Repr):
946 """Class for safely making a text representation of a Python object."""
947 def __init__(self):
948 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000949 self.maxlist = self.maxtuple = 20
950 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000951 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000952
953 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000954 if hasattr(type(x), '__name__'):
955 methodname = 'repr_' + join(split(type(x).__name__), '_')
956 if hasattr(self, methodname):
957 return getattr(self, methodname)(x, level)
958 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000959
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000960 def repr_string(self, x, level):
961 test = cram(x, self.maxstring)
962 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000963 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000964 # Backslashes are only literal in the string and are never
965 # needed to make any special characters, so show a raw string.
966 return 'r' + testrepr[0] + test + testrepr[0]
967 return testrepr
968
Skip Montanarodf708782002-03-07 22:58:02 +0000969 repr_str = repr_string
970
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000971 def repr_instance(self, x, level):
972 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000973 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000974 except:
975 return '<%s instance>' % x.__class__.__name__
976
977class TextDoc(Doc):
978 """Formatter class for text documentation."""
979
980 # ------------------------------------------- text formatting utilities
981
982 _repr_instance = TextRepr()
983 repr = _repr_instance.repr
984
985 def bold(self, text):
986 """Format a string in bold by overstriking."""
987 return join(map(lambda ch: ch + '\b' + ch, text), '')
988
989 def indent(self, text, prefix=' '):
990 """Indent text by prepending a given prefix to each line."""
991 if not text: return ''
992 lines = split(text, '\n')
993 lines = map(lambda line, prefix=prefix: prefix + line, lines)
994 if lines: lines[-1] = rstrip(lines[-1])
995 return join(lines, '\n')
996
997 def section(self, title, contents):
998 """Format a section with a given heading."""
999 return self.bold(title) + '\n' + rstrip(self.indent(contents)) + '\n\n'
1000
1001 # ---------------------------------------------- type-specific routines
1002
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001003 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001004 """Render in text a class tree as returned by inspect.getclasstree()."""
1005 result = ''
1006 for entry in tree:
1007 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001008 c, bases = entry
1009 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001010 if bases and bases != (parent,):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001011 parents = map(lambda c, m=modname: classname(c, m), bases)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001012 result = result + '(%s)' % join(parents, ', ')
1013 result = result + '\n'
1014 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001015 result = result + self.formattree(
1016 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001017 return result
1018
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001019 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001020 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001021 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001022 synop, desc = splitdoc(getdoc(object))
1023 result = self.section('NAME', name + (synop and ' - ' + synop))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001024
1025 try:
Skip Montanaroa5616d22004-06-11 04:46:12 +00001026 all = object.__all__
1027 except AttributeError:
1028 all = None
1029
1030 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001031 file = inspect.getabsfile(object)
1032 except TypeError:
1033 file = '(built-in)'
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001034 result = result + self.section('FILE', file)
Skip Montanaro4997a692003-09-10 16:47:51 +00001035
1036 docloc = self.getdocloc(object)
1037 if docloc is not None:
1038 result = result + self.section('MODULE DOCS', docloc)
1039
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001040 if desc:
1041 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001042
1043 classes = []
1044 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001045 # if __all__ exists, believe it. Otherwise use old heuristic.
1046 if (all is not None
1047 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001048 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001049 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001050 funcs = []
1051 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001052 # if __all__ exists, believe it. Otherwise use old heuristic.
1053 if (all is not None or
1054 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001055 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001056 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001057 data = []
1058 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001059 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001060 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001061
Georg Brandlf2dae0e2008-01-21 21:05:49 +00001062 modpkgs = []
1063 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001064 if hasattr(object, '__path__'):
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001065 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Georg Brandlf2dae0e2008-01-21 21:05:49 +00001066 modpkgs_names.add(modname)
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001067 if ispkg:
1068 modpkgs.append(modname + ' (package)')
1069 else:
1070 modpkgs.append(modname)
1071
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001072 modpkgs.sort()
1073 result = result + self.section(
1074 'PACKAGE CONTENTS', join(modpkgs, '\n'))
1075
Georg Brandlf2dae0e2008-01-21 21:05:49 +00001076 # Detect submodules as sometimes created by C extensions
1077 submodules = []
1078 for key, value in inspect.getmembers(object, inspect.ismodule):
1079 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1080 submodules.append(key)
1081 if submodules:
1082 submodules.sort()
1083 result = result + self.section(
1084 'SUBMODULES', join(submodules, '\n'))
1085
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001086 if classes:
Brett Cannonaca98b02008-08-03 00:58:51 +00001087 classlist = map(lambda key_value: key_value[1], classes)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001088 contents = [self.formattree(
1089 inspect.getclasstree(classlist, 1), name)]
1090 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001091 contents.append(self.document(value, key, name))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001092 result = result + self.section('CLASSES', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001093
1094 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001095 contents = []
1096 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001097 contents.append(self.document(value, key, name))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001098 result = result + self.section('FUNCTIONS', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001099
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001100 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001101 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001102 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001103 contents.append(self.docother(value, key, name, maxlen=70))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001104 result = result + self.section('DATA', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001105
1106 if hasattr(object, '__version__'):
1107 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001108 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
1109 version = strip(version[11:-1])
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001110 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001111 if hasattr(object, '__date__'):
1112 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001113 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001114 result = result + self.section('AUTHOR', str(object.__author__))
1115 if hasattr(object, '__credits__'):
1116 result = result + self.section('CREDITS', str(object.__credits__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001117 return result
1118
Georg Brandl52f83952011-02-25 10:39:23 +00001119 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001120 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001121 realname = object.__name__
1122 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001123 bases = object.__bases__
1124
Tim Petersc86f6ca2001-09-26 21:31:51 +00001125 def makename(c, m=object.__module__):
1126 return classname(c, m)
1127
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001128 if name == realname:
1129 title = 'class ' + self.bold(realname)
1130 else:
1131 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001132 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001133 parents = map(makename, bases)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001134 title = title + '(%s)' % join(parents, ', ')
1135
1136 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001137 contents = doc and [doc + '\n'] or []
1138 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001139
Tim Petersc86f6ca2001-09-26 21:31:51 +00001140 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001141 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001142 if len(mro) > 2:
1143 push("Method resolution order:")
1144 for base in mro:
1145 push(' ' + makename(base))
1146 push('')
1147
Tim Petersf4aad8e2001-09-24 22:40:47 +00001148 # Cute little class to pump out a horizontal rule between sections.
1149 class HorizontalRule:
1150 def __init__(self):
1151 self.needone = 0
1152 def maybe(self):
1153 if self.needone:
1154 push('-' * 70)
1155 self.needone = 1
1156 hr = HorizontalRule()
1157
Tim Peters28355492001-09-23 21:29:55 +00001158 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001159 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001160 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001161 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001162 push(msg)
1163 for name, kind, homecls, value in ok:
1164 push(self.document(getattr(object, name),
1165 name, mod, object))
1166 return attrs
1167
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001168 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001169 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001170 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001171 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001172 push(msg)
1173 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001174 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001175 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001176
Tim Petersfa26f7c2001-09-24 08:05:11 +00001177 def spilldata(msg, attrs, predicate):
1178 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001179 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001180 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001181 push(msg)
1182 for name, kind, homecls, value in ok:
Brett Cannonaca98b02008-08-03 00:58:51 +00001183 if (hasattr(value, '__call__') or
1184 inspect.isdatadescriptor(value)):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001185 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001186 else:
1187 doc = None
Tim Peters28355492001-09-23 21:29:55 +00001188 push(self.docother(getattr(object, name),
Georg Brandl8b813db2005-10-01 16:32:31 +00001189 name, mod, maxlen=70, doc=doc) + '\n')
Tim Peters28355492001-09-23 21:29:55 +00001190 return attrs
1191
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001192 attrs = filter(lambda data: visiblename(data[0], obj=object),
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001193 classify_class_attrs(object))
Tim Petersfa26f7c2001-09-24 08:05:11 +00001194 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001195 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001196 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001197 else:
1198 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001199 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1200
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001201 if thisclass is __builtin__.object:
1202 attrs = inherited
1203 continue
1204 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001205 tag = "defined here"
1206 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001207 tag = "inherited from %s" % classname(thisclass,
1208 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001209
1210 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001211 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001212
1213 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001214 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001215 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001216 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001217 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001218 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001219 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001220 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1221 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001222 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1223 lambda t: t[1] == 'data')
Tim Peters28355492001-09-23 21:29:55 +00001224 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001225 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001226
1227 contents = '\n'.join(contents)
1228 if not contents:
1229 return title + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001230 return title + '\n' + self.indent(rstrip(contents), ' | ') + '\n'
1231
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001232 def formatvalue(self, object):
1233 """Format an argument default value as text."""
1234 return '=' + self.repr(object)
1235
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001236 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001237 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001238 realname = object.__name__
1239 name = name or realname
1240 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001241 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001242 if inspect.ismethod(object):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001243 imclass = object.im_class
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001244 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001245 if imclass is not cl:
1246 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001247 else:
Georg Brandl7e2b6bb2007-03-13 22:16:30 +00001248 if object.im_self is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001249 note = ' method of %s instance' % classname(
1250 object.im_self.__class__, mod)
1251 else:
1252 note = ' unbound %s method' % classname(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001253 object = object.im_func
1254
1255 if name == realname:
1256 title = self.bold(realname)
1257 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001258 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001259 cl.__dict__[realname] is object):
1260 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001261 title = self.bold(name) + ' = ' + realname
Tim Peters4bcfa312001-09-20 06:08:24 +00001262 if inspect.isfunction(object):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001263 args, varargs, varkw, defaults = inspect.getargspec(object)
1264 argspec = inspect.formatargspec(
1265 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001266 if realname == '<lambda>':
Georg Brandl501dd0d2006-02-17 09:45:40 +00001267 title = self.bold(name) + ' lambda '
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001268 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +00001269 else:
1270 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001271 decl = title + argspec + note
1272
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001273 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001274 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001275 else:
1276 doc = getdoc(object) or ''
1277 return decl + '\n' + (doc and rstrip(self.indent(doc)) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001278
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001279 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001280 results = []
1281 push = results.append
1282
1283 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001284 push(self.bold(name))
1285 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001286 doc = getdoc(value) or ''
1287 if doc:
1288 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001289 push('\n')
1290 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001291
1292 def docproperty(self, object, name=None, mod=None, cl=None):
1293 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001294 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001295
Barry Warsaw00decd72006-07-27 23:43:15 +00001296 def docdata(self, object, name=None, mod=None, cl=None):
1297 """Produce text documentation for a data descriptor."""
1298 return self._docdescriptor(name, object, mod)
1299
Georg Brandl8b813db2005-10-01 16:32:31 +00001300 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001301 """Produce text documentation for a data object."""
1302 repr = self.repr(object)
1303 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001304 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001305 chop = maxlen - len(line)
1306 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001307 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001308 if doc is not None:
1309 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001310 return line
1311
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001312# --------------------------------------------------------- user interfaces
1313
1314def pager(text):
1315 """The first time this is called, determine what kind of pager to use."""
1316 global pager
1317 pager = getpager()
1318 pager(text)
1319
1320def getpager():
1321 """Decide what method to use for paging through text."""
1322 if type(sys.stdout) is not types.FileType:
1323 return plainpager
1324 if not sys.stdin.isatty() or not sys.stdout.isatty():
1325 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001326 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001327 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001328 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001329 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001330 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001331 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001332 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001333 if os.environ.get('TERM') in ('dumb', 'emacs'):
1334 return plainpager
Andrew MacIntyre54e0eab2002-03-03 03:12:30 +00001335 if sys.platform == 'win32' or sys.platform.startswith('os2'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001336 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001337 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001338 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001339
1340 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001341 (fd, filename) = tempfile.mkstemp()
1342 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001343 try:
Georg Brandlb32dea52008-07-16 21:19:28 +00001344 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001345 return lambda text: pipepager(text, 'more')
1346 else:
1347 return ttypager
1348 finally:
1349 os.unlink(filename)
1350
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001351def plain(text):
1352 """Remove boldface formatting from text."""
1353 return re.sub('.\b', '', text)
1354
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001355def pipepager(text, cmd):
1356 """Page through text by feeding it to another program."""
1357 pipe = os.popen(cmd, 'w')
1358 try:
1359 pipe.write(text)
1360 pipe.close()
1361 except IOError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001362 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001363
1364def tempfilepager(text, cmd):
1365 """Page through text by invoking a program on a temporary file."""
1366 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001367 filename = tempfile.mktemp()
1368 file = open(filename, 'w')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001369 file.write(text)
1370 file.close()
1371 try:
Georg Brandlb32dea52008-07-16 21:19:28 +00001372 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001373 finally:
1374 os.unlink(filename)
1375
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001376def ttypager(text):
1377 """Page through text on a text terminal."""
1378 lines = split(plain(text), '\n')
1379 try:
1380 import tty
1381 fd = sys.stdin.fileno()
1382 old = tty.tcgetattr(fd)
1383 tty.setcbreak(fd)
1384 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001385 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001386 tty = None
1387 getchar = lambda: sys.stdin.readline()[:-1][:1]
1388
1389 try:
1390 r = inc = os.environ.get('LINES', 25) - 1
1391 sys.stdout.write(join(lines[:inc], '\n') + '\n')
1392 while lines[r:]:
1393 sys.stdout.write('-- more --')
1394 sys.stdout.flush()
1395 c = getchar()
1396
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001397 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001398 sys.stdout.write('\r \r')
1399 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001400 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001401 sys.stdout.write('\r \r' + lines[r] + '\n')
1402 r = r + 1
1403 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001404 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001405 r = r - inc - inc
1406 if r < 0: r = 0
1407 sys.stdout.write('\n' + join(lines[r:r+inc], '\n') + '\n')
1408 r = r + inc
1409
1410 finally:
1411 if tty:
1412 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1413
1414def plainpager(text):
1415 """Simply print unformatted text. This is the ultimate fallback."""
1416 sys.stdout.write(plain(text))
1417
1418def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001419 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001420 if inspect.ismodule(thing):
1421 if thing.__name__ in sys.builtin_module_names:
1422 return 'built-in module ' + thing.__name__
1423 if hasattr(thing, '__path__'):
1424 return 'package ' + thing.__name__
1425 else:
1426 return 'module ' + thing.__name__
1427 if inspect.isbuiltin(thing):
1428 return 'built-in function ' + thing.__name__
Barry Warsaw00decd72006-07-27 23:43:15 +00001429 if inspect.isgetsetdescriptor(thing):
1430 return 'getset descriptor %s.%s.%s' % (
1431 thing.__objclass__.__module__, thing.__objclass__.__name__,
1432 thing.__name__)
1433 if inspect.ismemberdescriptor(thing):
1434 return 'member descriptor %s.%s.%s' % (
1435 thing.__objclass__.__module__, thing.__objclass__.__name__,
1436 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001437 if inspect.isclass(thing):
1438 return 'class ' + thing.__name__
1439 if inspect.isfunction(thing):
1440 return 'function ' + thing.__name__
1441 if inspect.ismethod(thing):
1442 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001443 if type(thing) is types.InstanceType:
1444 return 'instance of ' + thing.__class__.__name__
1445 return type(thing).__name__
1446
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001447def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001448 """Locate an object by name or dotted path, importing as necessary."""
Guido van Rossum97dede02003-02-16 01:12:32 +00001449 parts = [part for part in split(path, '.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001450 module, n = None, 0
1451 while n < len(parts):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001452 nextmodule = safeimport(join(parts[:n+1], '.'), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001453 if nextmodule: module, n = nextmodule, n + 1
1454 else: break
1455 if module:
1456 object = module
1457 for part in parts[n:]:
1458 try: object = getattr(object, part)
1459 except AttributeError: return None
1460 return object
1461 else:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001462 if hasattr(__builtin__, path):
1463 return getattr(__builtin__, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001464
1465# --------------------------------------- interactive interpreter interface
1466
1467text = TextDoc()
1468html = HTMLDoc()
1469
Ka-Ping Yee8ef1cf32007-01-14 04:25:15 +00001470class _OldStyleClass: pass
1471_OLD_INSTANCE_TYPE = type(_OldStyleClass())
1472
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001473def resolve(thing, forceload=0):
1474 """Given an object or a path to an object, get the object and its name."""
1475 if isinstance(thing, str):
1476 object = locate(thing, forceload)
1477 if not object:
1478 raise ImportError, 'no Python documentation found for %r' % thing
1479 return object, thing
1480 else:
1481 return thing, getattr(thing, '__name__', None)
1482
Georg Brandl8441f152007-03-13 20:02:57 +00001483def render_doc(thing, title='Python Library Documentation: %s', forceload=0):
1484 """Render text documentation, given an object or a path to an object."""
1485 object, name = resolve(thing, forceload)
1486 desc = describe(object)
1487 module = inspect.getmodule(object)
1488 if name and '.' in name:
1489 desc += ' in ' + name[:name.rfind('.')]
1490 elif module and module is not object:
1491 desc += ' in module ' + module.__name__
1492 if type(object) is _OLD_INSTANCE_TYPE:
1493 # If the passed object is an instance of an old-style class,
1494 # document its available methods instead of its value.
1495 object = object.__class__
1496 elif not (inspect.ismodule(object) or
1497 inspect.isclass(object) or
1498 inspect.isroutine(object) or
1499 inspect.isgetsetdescriptor(object) or
1500 inspect.ismemberdescriptor(object) or
1501 isinstance(object, property)):
1502 # If the passed object is a piece of data or an instance,
1503 # document its available methods instead of its value.
1504 object = type(object)
1505 desc += ' object'
1506 return title % desc + '\n\n' + text.document(object, name)
1507
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001508def doc(thing, title='Python Library Documentation: %s', forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001509 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001510 try:
Georg Brandl8441f152007-03-13 20:02:57 +00001511 pager(render_doc(thing, title, forceload))
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001512 except (ImportError, ErrorDuringImport), value:
1513 print value
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001514
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001515def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001516 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001517 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001518 object, name = resolve(thing, forceload)
1519 page = html.page(describe(object), html.document(object, name))
1520 file = open(name + '.html', 'w')
1521 file.write(page)
1522 file.close()
1523 print 'wrote', name + '.html'
1524 except (ImportError, ErrorDuringImport), value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001525 print value
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001526
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001527def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001528 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001529 if done is None: done = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001530 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1531 writedoc(modname)
1532 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001533
1534class Helper:
Georg Brandl681001e2008-06-01 20:33:55 +00001535
1536 # These dictionaries map a topic name to either an alias, or a tuple
1537 # (label, seealso-items). The "label" is the label of the corresponding
1538 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl43819252009-04-26 09:56:44 +00001539 # in pydoc_data/topics.py.
Georg Brandl681001e2008-06-01 20:33:55 +00001540 #
1541 # CAUTION: if you change one of these dictionaries, be sure to adapt the
1542 # list of needed labels in Doc/tools/sphinxext/pyspecific.py and
Georg Brandl43819252009-04-26 09:56:44 +00001543 # regenerate the pydoc_data/topics.py file by running
Georg Brandl681001e2008-06-01 20:33:55 +00001544 # make pydoc-topics
1545 # in Doc/ and copying the output file into the Lib/ directory.
1546
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001547 keywords = {
1548 'and': 'BOOLEAN',
Georg Brandlb6a87542007-03-13 10:06:48 +00001549 'as': 'with',
Georg Brandl681001e2008-06-01 20:33:55 +00001550 'assert': ('assert', ''),
1551 'break': ('break', 'while for'),
1552 'class': ('class', 'CLASSES SPECIALMETHODS'),
1553 'continue': ('continue', 'while for'),
1554 'def': ('function', ''),
1555 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001556 'elif': 'if',
Georg Brandl681001e2008-06-01 20:33:55 +00001557 'else': ('else', 'while for'),
Georg Brandl5c669db2008-08-30 19:03:43 +00001558 'except': 'try',
Georg Brandl681001e2008-06-01 20:33:55 +00001559 'exec': ('exec', ''),
Georg Brandl5c669db2008-08-30 19:03:43 +00001560 'finally': 'try',
Georg Brandl681001e2008-06-01 20:33:55 +00001561 'for': ('for', 'break continue while'),
Georg Brandl5c669db2008-08-30 19:03:43 +00001562 'from': 'import',
Georg Brandl681001e2008-06-01 20:33:55 +00001563 'global': ('global', 'NAMESPACES'),
1564 'if': ('if', 'TRUTHVALUE'),
1565 'import': ('import', 'MODULES'),
1566 'in': ('in', 'SEQUENCEMETHODS2'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001567 'is': 'COMPARISON',
Georg Brandl681001e2008-06-01 20:33:55 +00001568 'lambda': ('lambda', 'FUNCTIONS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001569 'not': 'BOOLEAN',
1570 'or': 'BOOLEAN',
Georg Brandl681001e2008-06-01 20:33:55 +00001571 'pass': ('pass', ''),
1572 'print': ('print', ''),
1573 'raise': ('raise', 'EXCEPTIONS'),
1574 'return': ('return', 'FUNCTIONS'),
1575 'try': ('try', 'EXCEPTIONS'),
1576 'while': ('while', 'break continue if TRUTHVALUE'),
1577 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1578 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001579 }
Georg Brandlc3a98032008-12-27 18:20:04 +00001580 # Either add symbols to this dictionary or to the symbols dictionary
1581 # directly: Whichever is easier. They are merged later.
1582 _symbols_inverse = {
1583 'STRINGS' : ("'", "'''", "r'", "u'", '"""', '"', 'r"', 'u"'),
1584 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1585 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1586 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1587 'UNARY' : ('-', '~'),
1588 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1589 '^=', '<<=', '>>=', '**=', '//='),
1590 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1591 'COMPLEX' : ('j', 'J')
1592 }
1593 symbols = {
1594 '%': 'OPERATORS FORMATTING',
1595 '**': 'POWER',
1596 ',': 'TUPLES LISTS FUNCTIONS',
1597 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1598 '...': 'ELLIPSIS',
1599 ':': 'SLICINGS DICTIONARYLITERALS',
1600 '@': 'def class',
1601 '\\': 'STRINGS',
1602 '_': 'PRIVATENAMES',
1603 '__': 'PRIVATENAMES SPECIALMETHODS',
1604 '`': 'BACKQUOTES',
1605 '(': 'TUPLES FUNCTIONS CALLS',
1606 ')': 'TUPLES FUNCTIONS CALLS',
1607 '[': 'LISTS SUBSCRIPTS SLICINGS',
1608 ']': 'LISTS SUBSCRIPTS SLICINGS'
1609 }
1610 for topic, symbols_ in _symbols_inverse.iteritems():
1611 for symbol in symbols_:
1612 topics = symbols.get(symbol, topic)
1613 if topic not in topics:
1614 topics = topics + ' ' + topic
1615 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001616
1617 topics = {
Georg Brandl681001e2008-06-01 20:33:55 +00001618 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1619 'FUNCTIONS CLASSES MODULES FILES inspect'),
1620 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS FORMATTING '
1621 'TYPES'),
1622 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1623 'FORMATTING': ('formatstrings', 'OPERATORS'),
1624 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1625 'FORMATTING TYPES'),
1626 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1627 'INTEGER': ('integers', 'int range'),
1628 'FLOAT': ('floating', 'float math'),
1629 'COMPLEX': ('imaginary', 'complex cmath'),
1630 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING xrange LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001631 'MAPPINGS': 'DICTIONARIES',
Georg Brandl681001e2008-06-01 20:33:55 +00001632 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1633 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1634 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1635 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001636 'FRAMEOBJECTS': 'TYPES',
1637 'TRACEBACKS': 'TYPES',
Georg Brandl681001e2008-06-01 20:33:55 +00001638 'NONE': ('bltin-null-object', ''),
1639 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
1640 'FILES': ('bltin-file-objects', ''),
1641 'SPECIALATTRIBUTES': ('specialattrs', ''),
1642 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1643 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001644 'PACKAGES': 'import',
Georg Brandl681001e2008-06-01 20:33:55 +00001645 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1646 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1647 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1648 'LISTS DICTIONARIES BACKQUOTES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001649 'OPERATORS': 'EXPRESSIONS',
1650 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl681001e2008-06-01 20:33:55 +00001651 'OBJECTS': ('objects', 'TYPES'),
1652 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
1653 'CALLABLEMETHODS SEQUENCEMETHODS1 MAPPINGMETHODS '
1654 'SEQUENCEMETHODS2 NUMBERMETHODS CLASSES'),
1655 'BASICMETHODS': ('customization', 'cmp hash repr str SPECIALMETHODS'),
1656 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1657 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
1658 'SEQUENCEMETHODS1': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS2 '
1659 'SPECIALMETHODS'),
1660 'SEQUENCEMETHODS2': ('sequence-methods', 'SEQUENCES SEQUENCEMETHODS1 '
1661 'SPECIALMETHODS'),
1662 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1663 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1664 'SPECIALMETHODS'),
1665 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
1666 'NAMESPACES': ('naming', 'global ASSIGNMENT DELETION DYNAMICFEATURES'),
1667 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001668 'SCOPING': 'NAMESPACES',
1669 'FRAMES': 'NAMESPACES',
Georg Brandl681001e2008-06-01 20:33:55 +00001670 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1671 'COERCIONS': ('coercion-rules','CONVERSIONS'),
1672 'CONVERSIONS': ('conversions', 'COERCIONS'),
1673 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1674 'SPECIALIDENTIFIERS': ('id-classes', ''),
1675 'PRIVATENAMES': ('atom-identifiers', ''),
1676 'LITERALS': ('atom-literals', 'STRINGS BACKQUOTES NUMBERS '
1677 'TUPLELITERALS LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001678 'TUPLES': 'SEQUENCES',
Georg Brandl681001e2008-06-01 20:33:55 +00001679 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1680 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1681 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1682 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1683 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1684 'BACKQUOTES': ('string-conversions', 'repr str STRINGS LITERALS'),
1685 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr '
1686 'ATTRIBUTEMETHODS'),
1687 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS1'),
1688 'SLICINGS': ('slicings', 'SEQUENCEMETHODS2'),
1689 'CALLS': ('calls', 'EXPRESSIONS'),
1690 'POWER': ('power', 'EXPRESSIONS'),
1691 'UNARY': ('unary', 'EXPRESSIONS'),
1692 'BINARY': ('binary', 'EXPRESSIONS'),
1693 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1694 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1695 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1696 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001697 'ASSERTION': 'assert',
Georg Brandl681001e2008-06-01 20:33:55 +00001698 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1699 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001700 'DELETION': 'del',
1701 'PRINTING': 'print',
1702 'RETURNING': 'return',
1703 'IMPORTING': 'import',
1704 'CONDITIONAL': 'if',
Georg Brandl681001e2008-06-01 20:33:55 +00001705 'LOOPING': ('compound', 'for while break continue'),
1706 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1707 'DEBUGGING': ('debugger', 'pdb'),
1708 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001709 }
1710
Georg Brandl004c74d2010-08-01 19:06:51 +00001711 def __init__(self, input=None, output=None):
1712 self._input = input
1713 self._output = output
1714
1715 input = property(lambda self: self._input or sys.stdin)
1716 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001717
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001718 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001719 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001720 self()
1721 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001722 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001723
Alexander Belopolskyd501dde2011-01-11 15:35:23 +00001724 _GoInteractive = object()
1725 def __call__(self, request=_GoInteractive):
1726 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001727 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001728 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001729 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001730 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001731 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001732You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001733If you want to ask for help on a particular object directly from the
1734interpreter, you can type "help(object)". Executing "help('string')"
1735has the same effect as typing a particular string at the help> prompt.
1736''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001737
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001738 def interact(self):
1739 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001740 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001741 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001742 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001743 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001744 except (KeyboardInterrupt, EOFError):
1745 break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001746 request = strip(replace(request, '"', '', "'", ''))
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001747 if lower(request) in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001748 self.help(request)
1749
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001750 def getline(self, prompt):
1751 """Read one line, using raw_input when available."""
1752 if self.input is sys.stdin:
1753 return raw_input(prompt)
1754 else:
1755 self.output.write(prompt)
1756 self.output.flush()
1757 return self.input.readline()
1758
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001759 def help(self, request):
1760 if type(request) is type(''):
R. David Murrayd67ea7d2009-05-27 20:07:21 +00001761 request = request.strip()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001762 if request == 'help': self.intro()
1763 elif request == 'keywords': self.listkeywords()
Georg Brandlc3a98032008-12-27 18:20:04 +00001764 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001765 elif request == 'topics': self.listtopics()
1766 elif request == 'modules': self.listmodules()
1767 elif request[:8] == 'modules ':
1768 self.listmodules(split(request)[1])
Georg Brandlc3a98032008-12-27 18:20:04 +00001769 elif request in self.symbols: self.showsymbol(request)
Raymond Hettinger54f02222002-06-01 14:18:47 +00001770 elif request in self.keywords: self.showtopic(request)
1771 elif request in self.topics: self.showtopic(request)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001772 elif request: doc(request, 'Help on %s:')
1773 elif isinstance(request, Helper): self()
1774 else: doc(request, 'Help on %s:')
1775 self.output.write('\n')
1776
1777 def intro(self):
1778 self.output.write('''
1779Welcome to Python %s! This is the online help utility.
1780
1781If this is your first time using Python, you should definitely check out
Georg Brandl0751d1a2008-01-21 17:13:03 +00001782the tutorial on the Internet at http://docs.python.org/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001783
1784Enter the name of any module, keyword, or topic to get help on writing
1785Python programs and using Python modules. To quit this help utility and
1786return to the interpreter, just type "quit".
1787
1788To get a list of available modules, keywords, or topics, type "modules",
1789"keywords", or "topics". Each module also comes with a one-line summary
1790of what it does; to list the modules whose summaries contain a given word
1791such as "spam", type "modules spam".
1792''' % sys.version[:3])
1793
1794 def list(self, items, columns=4, width=80):
1795 items = items[:]
1796 items.sort()
1797 colw = width / columns
1798 rows = (len(items) + columns - 1) / columns
1799 for row in range(rows):
1800 for col in range(columns):
1801 i = col * rows + row
1802 if i < len(items):
1803 self.output.write(items[i])
1804 if col < columns - 1:
1805 self.output.write(' ' + ' ' * (colw-1 - len(items[i])))
1806 self.output.write('\n')
1807
1808 def listkeywords(self):
1809 self.output.write('''
1810Here is a list of the Python keywords. Enter any keyword to get more help.
1811
1812''')
1813 self.list(self.keywords.keys())
1814
Georg Brandlc3a98032008-12-27 18:20:04 +00001815 def listsymbols(self):
1816 self.output.write('''
1817Here is a list of the punctuation symbols which Python assigns special meaning
1818to. Enter any symbol to get more help.
1819
1820''')
1821 self.list(self.symbols.keys())
1822
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001823 def listtopics(self):
1824 self.output.write('''
1825Here is a list of available topics. Enter any topic name to get more help.
1826
1827''')
1828 self.list(self.topics.keys())
1829
Georg Brandlc3a98032008-12-27 18:20:04 +00001830 def showtopic(self, topic, more_xrefs=''):
Georg Brandl681001e2008-06-01 20:33:55 +00001831 try:
Georg Brandl43819252009-04-26 09:56:44 +00001832 import pydoc_data.topics
Georg Brandl681001e2008-06-01 20:33:55 +00001833 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001834 self.output.write('''
Georg Brandl681001e2008-06-01 20:33:55 +00001835Sorry, topic and keyword documentation is not available because the
Georg Brandl43819252009-04-26 09:56:44 +00001836module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001837''')
1838 return
1839 target = self.topics.get(topic, self.keywords.get(topic))
1840 if not target:
1841 self.output.write('no documentation found for %s\n' % repr(topic))
1842 return
1843 if type(target) is type(''):
Georg Brandlc3a98032008-12-27 18:20:04 +00001844 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001845
Georg Brandl681001e2008-06-01 20:33:55 +00001846 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001847 try:
Georg Brandl43819252009-04-26 09:56:44 +00001848 doc = pydoc_data.topics.topics[label]
Georg Brandl681001e2008-06-01 20:33:55 +00001849 except KeyError:
1850 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001851 return
Georg Brandl681001e2008-06-01 20:33:55 +00001852 pager(strip(doc) + '\n')
Georg Brandlc3a98032008-12-27 18:20:04 +00001853 if more_xrefs:
1854 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001855 if xrefs:
Georg Brandl681001e2008-06-01 20:33:55 +00001856 import StringIO, formatter
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001857 buffer = StringIO.StringIO()
1858 formatter.DumbWriter(buffer).send_flowing_data(
1859 'Related help topics: ' + join(split(xrefs), ', ') + '\n')
1860 self.output.write('\n%s\n' % buffer.getvalue())
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001861
Georg Brandlc3a98032008-12-27 18:20:04 +00001862 def showsymbol(self, symbol):
1863 target = self.symbols[symbol]
1864 topic, _, xrefs = target.partition(' ')
1865 self.showtopic(topic, xrefs)
1866
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001867 def listmodules(self, key=''):
1868 if key:
1869 self.output.write('''
1870Here is a list of matching modules. Enter any module name to get more help.
1871
1872''')
1873 apropos(key)
1874 else:
1875 self.output.write('''
1876Please wait a moment while I gather a list of all available modules...
1877
1878''')
1879 modules = {}
1880 def callback(path, modname, desc, modules=modules):
1881 if modname and modname[-9:] == '.__init__':
1882 modname = modname[:-9] + ' (package)'
1883 if find(modname, '.') < 0:
1884 modules[modname] = 1
Ka-Ping Yee9e0f1162008-01-13 11:25:13 +00001885 def onerror(modname):
1886 callback(None, modname, None)
1887 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001888 self.list(modules.keys())
1889 self.output.write('''
1890Enter any module name to get more help. Or, type "modules spam" to search
1891for modules whose descriptions contain the word "spam".
1892''')
1893
Georg Brandl004c74d2010-08-01 19:06:51 +00001894help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001895
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001896class Scanner:
1897 """A generic tree iterator."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001898 def __init__(self, roots, children, descendp):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001899 self.roots = roots[:]
1900 self.state = []
1901 self.children = children
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001902 self.descendp = descendp
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001903
1904 def next(self):
1905 if not self.state:
1906 if not self.roots:
1907 return None
1908 root = self.roots.pop(0)
1909 self.state = [(root, self.children(root))]
1910 node, children = self.state[-1]
1911 if not children:
1912 self.state.pop()
1913 return self.next()
1914 child = children.pop(0)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001915 if self.descendp(child):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001916 self.state.append((child, self.children(child)))
1917 return child
1918
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001919
1920class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001921 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001922
Ka-Ping Yee9e0f1162008-01-13 11:25:13 +00001923 def run(self, callback, key=None, completer=None, onerror=None):
Ka-Ping Yee66246962001-04-12 11:59:50 +00001924 if key: key = lower(key)
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001925 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001926 seen = {}
1927
1928 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001929 if modname != '__main__':
1930 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00001931 if key is None:
1932 callback(None, modname, '')
1933 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001934 desc = split(__import__(modname).__doc__ or '', '\n')[0]
Ka-Ping Yee66246962001-04-12 11:59:50 +00001935 if find(lower(modname + ' - ' + desc), key) >= 0:
1936 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001937
Ka-Ping Yee9e0f1162008-01-13 11:25:13 +00001938 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001939 if self.quit:
1940 break
1941 if key is None:
1942 callback(None, modname, '')
1943 else:
1944 loader = importer.find_module(modname)
1945 if hasattr(loader,'get_source'):
1946 import StringIO
1947 desc = source_synopsis(
1948 StringIO.StringIO(loader.get_source(modname))
1949 ) or ''
1950 if hasattr(loader,'get_filename'):
1951 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00001952 else:
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001953 path = None
1954 else:
1955 module = loader.load_module(modname)
1956 desc = (module.__doc__ or '').splitlines()[0]
1957 path = getattr(module,'__file__',None)
1958 if find(lower(modname + ' - ' + desc), key) >= 0:
1959 callback(path, modname, desc)
1960
1961 if completer:
1962 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001963
1964def apropos(key):
1965 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001966 def callback(path, modname, desc):
1967 if modname[-9:] == '.__init__':
1968 modname = modname[:-9] + ' (package)'
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001969 print modname, desc and '- ' + desc
1970 try: import warnings
1971 except ImportError: pass
1972 else: warnings.filterwarnings('ignore') # ignore problems during import
Ka-Ping Yee66246962001-04-12 11:59:50 +00001973 ModuleScanner().run(callback, key)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001974
1975# --------------------------------------------------- web browser interface
1976
Ka-Ping Yee66246962001-04-12 11:59:50 +00001977def serve(port, callback=None, completer=None):
Ka-Ping Yeefd540692001-04-12 12:54:36 +00001978 import BaseHTTPServer, mimetools, select
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001979
1980 # Patch up mimetools.Message so it doesn't break if rfc822 is reloaded.
1981 class Message(mimetools.Message):
1982 def __init__(self, fp, seekable=1):
1983 Message = self.__class__
1984 Message.__bases__[0].__bases__[0].__init__(self, fp, seekable)
1985 self.encodingheader = self.getheader('content-transfer-encoding')
1986 self.typeheader = self.getheader('content-type')
1987 self.parsetype()
1988 self.parseplist()
1989
1990 class DocHandler(BaseHTTPServer.BaseHTTPRequestHandler):
1991 def send_document(self, title, contents):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001992 try:
1993 self.send_response(200)
1994 self.send_header('Content-Type', 'text/html')
1995 self.end_headers()
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001996 self.wfile.write(html.page(title, contents))
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001997 except IOError: pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001998
1999 def do_GET(self):
2000 path = self.path
2001 if path[-5:] == '.html': path = path[:-5]
2002 if path[:1] == '/': path = path[1:]
2003 if path and path != '.':
2004 try:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00002005 obj = locate(path, forceload=1)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002006 except ErrorDuringImport, value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002007 self.send_document(path, html.escape(str(value)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002008 return
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002009 if obj:
2010 self.send_document(describe(obj), html.document(obj, path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002011 else:
2012 self.send_document(path,
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002013'no Python documentation found for %s' % repr(path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002014 else:
2015 heading = html.heading(
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002016'<big><big><strong>Python: Index of Modules</strong></big></big>',
2017'#ffffff', '#7799ee')
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002018 def bltinlink(name):
2019 return '<a href="%s.html">%s</a>' % (name, name)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002020 names = filter(lambda x: x != '__main__',
2021 sys.builtin_module_names)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002022 contents = html.multicolumn(names, bltinlink)
2023 indices = ['<p>' + html.bigsection(
2024 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2025
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002026 seen = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +00002027 for dir in sys.path:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002028 indices.append(html.index(dir, seen))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002029 contents = heading + join(indices) + '''<p align=right>
Tim Peters2306d242001-09-25 03:18:32 +00002030<font color="#909090" face="helvetica, arial"><strong>
2031pydoc</strong> by Ka-Ping Yee &lt;ping@lfw.org&gt;</font>'''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002032 self.send_document('Index of Modules', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002033
2034 def log_message(self, *args): pass
2035
Ka-Ping Yeefd540692001-04-12 12:54:36 +00002036 class DocServer(BaseHTTPServer.HTTPServer):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002037 def __init__(self, port, callback):
Ronald Oussoren9545a232010-05-05 19:09:31 +00002038 host = 'localhost'
Senthil Kumaranaa895452010-08-18 19:35:53 +00002039 self.address = (host, port)
Ka-Ping Yeedb8ed152001-03-02 05:58:17 +00002040 self.url = 'http://%s:%d/' % (host, port)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002041 self.callback = callback
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002042 self.base.__init__(self, self.address, self.handler)
2043
2044 def serve_until_quit(self):
2045 import select
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002046 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002047 while not self.quit:
2048 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2049 if rd: self.handle_request()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002050
2051 def server_activate(self):
2052 self.base.server_activate(self)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002053 if self.callback: self.callback(self)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002054
2055 DocServer.base = BaseHTTPServer.HTTPServer
2056 DocServer.handler = DocHandler
2057 DocHandler.MessageClass = Message
2058 try:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002059 try:
2060 DocServer(port, callback).serve_until_quit()
2061 except (KeyboardInterrupt, select.error):
2062 pass
2063 finally:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002064 if completer: completer()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002065
2066# ----------------------------------------------------- graphical interface
2067
2068def gui():
2069 """Graphical interface (starts web server and pops up a control window)."""
2070 class GUI:
2071 def __init__(self, window, port=7464):
2072 self.window = window
2073 self.server = None
2074 self.scanner = None
2075
Georg Brandl6634bf22008-05-20 07:13:37 +00002076 import Tkinter
2077 self.server_frm = Tkinter.Frame(window)
2078 self.title_lbl = Tkinter.Label(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002079 text='Starting server...\n ')
Georg Brandl6634bf22008-05-20 07:13:37 +00002080 self.open_btn = Tkinter.Button(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002081 text='open browser', command=self.open, state='disabled')
Georg Brandl6634bf22008-05-20 07:13:37 +00002082 self.quit_btn = Tkinter.Button(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002083 text='quit serving', command=self.quit, state='disabled')
2084
Georg Brandl6634bf22008-05-20 07:13:37 +00002085 self.search_frm = Tkinter.Frame(window)
2086 self.search_lbl = Tkinter.Label(self.search_frm, text='Search for')
2087 self.search_ent = Tkinter.Entry(self.search_frm)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002088 self.search_ent.bind('<Return>', self.search)
Georg Brandl6634bf22008-05-20 07:13:37 +00002089 self.stop_btn = Tkinter.Button(self.search_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002090 text='stop', pady=0, command=self.stop, state='disabled')
2091 if sys.platform == 'win32':
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002092 # Trying to hide and show this button crashes under Windows.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002093 self.stop_btn.pack(side='right')
2094
2095 self.window.title('pydoc')
2096 self.window.protocol('WM_DELETE_WINDOW', self.quit)
2097 self.title_lbl.pack(side='top', fill='x')
2098 self.open_btn.pack(side='left', fill='x', expand=1)
2099 self.quit_btn.pack(side='right', fill='x', expand=1)
2100 self.server_frm.pack(side='top', fill='x')
2101
2102 self.search_lbl.pack(side='left')
2103 self.search_ent.pack(side='right', fill='x', expand=1)
2104 self.search_frm.pack(side='top', fill='x')
2105 self.search_ent.focus_set()
2106
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002107 font = ('helvetica', sys.platform == 'win32' and 8 or 10)
Georg Brandl6634bf22008-05-20 07:13:37 +00002108 self.result_lst = Tkinter.Listbox(window, font=font, height=6)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002109 self.result_lst.bind('<Button-1>', self.select)
2110 self.result_lst.bind('<Double-Button-1>', self.goto)
Georg Brandl6634bf22008-05-20 07:13:37 +00002111 self.result_scr = Tkinter.Scrollbar(window,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002112 orient='vertical', command=self.result_lst.yview)
2113 self.result_lst.config(yscrollcommand=self.result_scr.set)
2114
Georg Brandl6634bf22008-05-20 07:13:37 +00002115 self.result_frm = Tkinter.Frame(window)
2116 self.goto_btn = Tkinter.Button(self.result_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002117 text='go to selected', command=self.goto)
Georg Brandl6634bf22008-05-20 07:13:37 +00002118 self.hide_btn = Tkinter.Button(self.result_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002119 text='hide results', command=self.hide)
2120 self.goto_btn.pack(side='left', fill='x', expand=1)
2121 self.hide_btn.pack(side='right', fill='x', expand=1)
2122
2123 self.window.update()
2124 self.minwidth = self.window.winfo_width()
2125 self.minheight = self.window.winfo_height()
2126 self.bigminheight = (self.server_frm.winfo_reqheight() +
2127 self.search_frm.winfo_reqheight() +
2128 self.result_lst.winfo_reqheight() +
2129 self.result_frm.winfo_reqheight())
2130 self.bigwidth, self.bigheight = self.minwidth, self.bigminheight
2131 self.expanded = 0
2132 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2133 self.window.wm_minsize(self.minwidth, self.minheight)
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002134 self.window.tk.willdispatch()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002135
2136 import threading
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002137 threading.Thread(
2138 target=serve, args=(port, self.ready, self.quit)).start()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002139
2140 def ready(self, server):
2141 self.server = server
2142 self.title_lbl.config(
2143 text='Python documentation server at\n' + server.url)
2144 self.open_btn.config(state='normal')
2145 self.quit_btn.config(state='normal')
2146
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002147 def open(self, event=None, url=None):
2148 url = url or self.server.url
2149 try:
2150 import webbrowser
2151 webbrowser.open(url)
2152 except ImportError: # pre-webbrowser.py compatibility
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002153 if sys.platform == 'win32':
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002154 os.system('start "%s"' % url)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002155 else:
2156 rc = os.system('netscape -remote "openURL(%s)" &' % url)
2157 if rc: os.system('netscape "%s" &' % url)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002158
2159 def quit(self, event=None):
2160 if self.server:
2161 self.server.quit = 1
2162 self.window.quit()
2163
2164 def search(self, event=None):
2165 key = self.search_ent.get()
2166 self.stop_btn.pack(side='right')
2167 self.stop_btn.config(state='normal')
2168 self.search_lbl.config(text='Searching for "%s"...' % key)
2169 self.search_ent.forget()
2170 self.search_lbl.pack(side='left')
2171 self.result_lst.delete(0, 'end')
2172 self.goto_btn.config(state='disabled')
2173 self.expand()
2174
2175 import threading
2176 if self.scanner:
2177 self.scanner.quit = 1
2178 self.scanner = ModuleScanner()
2179 threading.Thread(target=self.scanner.run,
Ka-Ping Yee6dcfa382001-04-12 20:27:31 +00002180 args=(self.update, key, self.done)).start()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002181
2182 def update(self, path, modname, desc):
2183 if modname[-9:] == '.__init__':
2184 modname = modname[:-9] + ' (package)'
2185 self.result_lst.insert('end',
2186 modname + ' - ' + (desc or '(no description)'))
2187
2188 def stop(self, event=None):
2189 if self.scanner:
2190 self.scanner.quit = 1
2191 self.scanner = None
2192
2193 def done(self):
2194 self.scanner = None
2195 self.search_lbl.config(text='Search for')
2196 self.search_lbl.pack(side='left')
2197 self.search_ent.pack(side='right', fill='x', expand=1)
2198 if sys.platform != 'win32': self.stop_btn.forget()
2199 self.stop_btn.config(state='disabled')
2200
2201 def select(self, event=None):
2202 self.goto_btn.config(state='normal')
2203
2204 def goto(self, event=None):
2205 selection = self.result_lst.curselection()
2206 if selection:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002207 modname = split(self.result_lst.get(selection[0]))[0]
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002208 self.open(url=self.server.url + modname + '.html')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002209
2210 def collapse(self):
2211 if not self.expanded: return
2212 self.result_frm.forget()
2213 self.result_scr.forget()
2214 self.result_lst.forget()
2215 self.bigwidth = self.window.winfo_width()
2216 self.bigheight = self.window.winfo_height()
2217 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2218 self.window.wm_minsize(self.minwidth, self.minheight)
2219 self.expanded = 0
2220
2221 def expand(self):
2222 if self.expanded: return
2223 self.result_frm.pack(side='bottom', fill='x')
2224 self.result_scr.pack(side='right', fill='y')
2225 self.result_lst.pack(side='top', fill='both', expand=1)
2226 self.window.wm_geometry('%dx%d' % (self.bigwidth, self.bigheight))
2227 self.window.wm_minsize(self.minwidth, self.bigminheight)
2228 self.expanded = 1
2229
2230 def hide(self, event=None):
2231 self.stop()
2232 self.collapse()
2233
Georg Brandl6634bf22008-05-20 07:13:37 +00002234 import Tkinter
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002235 try:
Georg Brandl6634bf22008-05-20 07:13:37 +00002236 root = Tkinter.Tk()
Martin v. Löwise09bd932004-08-22 16:13:26 +00002237 # Tk will crash if pythonw.exe has an XP .manifest
2238 # file and the root has is not destroyed explicitly.
2239 # If the problem is ever fixed in Tk, the explicit
2240 # destroy can go.
2241 try:
2242 gui = GUI(root)
2243 root.mainloop()
2244 finally:
2245 root.destroy()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002246 except KeyboardInterrupt:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002247 pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002248
2249# -------------------------------------------------- command-line interface
2250
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002251def ispath(x):
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002252 return isinstance(x, str) and find(x, os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002253
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002254def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002255 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002256 import getopt
2257 class BadUsage: pass
2258
Nick Coghlan11db64e2009-11-15 22:36:47 +00002259 # Scripts don't get the current directory in their path by default
2260 # unless they are run with the '-m' switch
2261 if '' not in sys.path:
2262 scriptdir = os.path.dirname(sys.argv[0])
2263 if scriptdir in sys.path:
2264 sys.path.remove(scriptdir)
2265 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002266
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002267 try:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002268 opts, args = getopt.getopt(sys.argv[1:], 'gk:p:w')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002269 writing = 0
2270
2271 for opt, val in opts:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002272 if opt == '-g':
2273 gui()
2274 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002275 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002276 apropos(val)
2277 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002278 if opt == '-p':
2279 try:
2280 port = int(val)
2281 except ValueError:
2282 raise BadUsage
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002283 def ready(server):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002284 print 'pydoc server ready at %s' % server.url
2285 def stopped():
2286 print 'pydoc server stopped'
2287 serve(port, ready, stopped)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002288 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002289 if opt == '-w':
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002290 writing = 1
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002291
2292 if not args: raise BadUsage
2293 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002294 if ispath(arg) and not os.path.exists(arg):
2295 print 'file %r does not exist' % arg
2296 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002297 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002298 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002299 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002300 if writing:
2301 if ispath(arg) and os.path.isdir(arg):
2302 writedocs(arg)
2303 else:
2304 writedoc(arg)
2305 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002306 help.help(arg)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002307 except ErrorDuringImport, value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002308 print value
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002309
2310 except (getopt.error, BadUsage):
Martin v. Löwisf9b08b82003-10-31 13:05:21 +00002311 cmd = os.path.basename(sys.argv[0])
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002312 print """pydoc - the Python documentation tool
2313
2314%s <name> ...
2315 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002316 Python keyword, topic, function, module, or package, or a dotted
2317 reference to a class or function within a module or module in a
2318 package. If <name> contains a '%s', it is used as the path to a
2319 Python source file to document. If name is 'keywords', 'topics',
2320 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002321
2322%s -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002323 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002324
2325%s -p <port>
2326 Start an HTTP server on the given port on the local machine.
2327
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002328%s -g
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002329 Pop up a graphical interface for finding and serving documentation.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002330
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002331%s -w <name> ...
2332 Write out the HTML documentation for a module to a file in the current
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002333 directory. If <name> contains a '%s', it is treated as a filename; if
2334 it names a directory, documentation is written for all the contents.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002335""" % (cmd, os.sep, cmd, cmd, cmd, cmd, os.sep)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002336
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002337if __name__ == '__main__': cli()