blob: 7da75b65bf0fb95f5d6dd659c92a94cc5736ed20 [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.
127 if _re_stripid.search(repr(Exception)):
128 return _re_stripid.sub(r'\1', text)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000129 return text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000130
Brett Cannonc6c1f472004-06-19 01:02:51 +0000131def _is_some_method(obj):
132 return inspect.ismethod(obj) or inspect.ismethoddescriptor(obj)
Tim Peters536d2262001-09-20 05:13:38 +0000133
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000134def allmethods(cl):
135 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000136 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000137 methods[key] = 1
138 for base in cl.__bases__:
139 methods.update(allmethods(base)) # all your base are belong to us
140 for key in methods.keys():
141 methods[key] = getattr(cl, key)
142 return methods
143
Tim Petersfa26f7c2001-09-24 08:05:11 +0000144def _split_list(s, predicate):
145 """Split sequence s via predicate, and return pair ([true], [false]).
146
147 The return value is a 2-tuple of lists,
148 ([x for x in s if predicate(x)],
149 [x for x in s if not predicate(x)])
150 """
151
Tim Peters28355492001-09-23 21:29:55 +0000152 yes = []
153 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000154 for x in s:
155 if predicate(x):
156 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000157 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000158 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000159 return yes, no
160
Skip Montanaroa5616d22004-06-11 04:46:12 +0000161def visiblename(name, all=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000162 """Decide whether to show documentation on a variable."""
163 # Certain special names are redundant.
Nick Coghlanc060b0e2008-07-02 13:09:19 +0000164 _hidden_names = ('__builtins__', '__doc__', '__file__', '__path__',
165 '__module__', '__name__', '__slots__', '__package__')
166 if name in _hidden_names: return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000167 # Private names are hidden, but special names are displayed.
168 if name.startswith('__') and name.endswith('__'): return 1
Skip Montanaroa5616d22004-06-11 04:46:12 +0000169 if all is not None:
170 # only document that which the programmer exported in __all__
171 return name in all
172 else:
173 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000174
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000175def classify_class_attrs(object):
176 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Brett Cannonaca98b02008-08-03 00:58:51 +0000177 def fixup(data):
178 name, kind, cls, value = data
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000179 if inspect.isdatadescriptor(value):
180 kind = 'data descriptor'
181 return name, kind, cls, value
182 return map(fixup, inspect.classify_class_attrs(object))
183
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000184# ----------------------------------------------------- module manipulation
185
186def ispackage(path):
187 """Guess whether a path refers to a package directory."""
188 if os.path.isdir(path):
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000189 for ext in ('.py', '.pyc', '.pyo'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000190 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000191 return True
192 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000193
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000194def source_synopsis(file):
195 line = file.readline()
196 while line[:1] == '#' or not strip(line):
197 line = file.readline()
198 if not line: break
199 line = strip(line)
200 if line[:4] == 'r"""': line = line[1:]
201 if line[:3] == '"""':
202 line = line[3:]
203 if line[-1:] == '\\': line = line[:-1]
204 while not strip(line):
205 line = file.readline()
206 if not line: break
207 result = strip(split(line, '"""')[0])
208 else: result = None
209 return result
210
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000211def synopsis(filename, cache={}):
212 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000213 mtime = os.stat(filename).st_mtime
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000214 lastupdate, result = cache.get(filename, (0, None))
215 if lastupdate < mtime:
216 info = inspect.getmoduleinfo(filename)
Georg Brandl26fd2e12006-03-08 09:34:53 +0000217 try:
218 file = open(filename)
219 except IOError:
220 # module can't be opened, so skip it
221 return None
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000222 if info and 'b' in info[2]: # binary modules have to be imported
223 try: module = imp.load_module('__temp__', file, filename, info[1:])
224 except: return None
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000225 result = (module.__doc__ or '').splitlines()[0]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000226 del sys.modules['__temp__']
227 else: # text modules can be directly examined
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000228 result = source_synopsis(file)
229 file.close()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000230 cache[filename] = (mtime, result)
231 return result
232
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000233class ErrorDuringImport(Exception):
234 """Errors that occurred while trying to import something to document it."""
Brett Cannonaca98b02008-08-03 00:58:51 +0000235 def __init__(self, filename, exc_info):
236 exc, value, tb = exc_info
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000237 self.filename = filename
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000238 self.exc = exc
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000239 self.value = value
240 self.tb = tb
241
242 def __str__(self):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000243 exc = self.exc
244 if type(exc) is types.ClassType:
245 exc = exc.__name__
246 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000247
248def importfile(path):
249 """Import a Python source file or compiled file given its path."""
250 magic = imp.get_magic()
251 file = open(path, 'r')
252 if file.read(len(magic)) == magic:
253 kind = imp.PY_COMPILED
254 else:
255 kind = imp.PY_SOURCE
256 file.close()
257 filename = os.path.basename(path)
258 name, ext = os.path.splitext(filename)
259 file = open(path, 'r')
260 try:
261 module = imp.load_module(name, file, path, (ext, 'r', kind))
262 except:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000263 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000264 file.close()
265 return module
266
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000267def safeimport(path, forceload=0, cache={}):
268 """Import a module; handle errors; return None if the module isn't found.
269
270 If the module *is* found but an exception occurs, it's wrapped in an
271 ErrorDuringImport exception and reraised. Unlike __import__, if a
272 package path is specified, the module at the end of the path is returned,
273 not the package at the beginning. If the optional 'forceload' argument
274 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000275 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000276 # If forceload is 1 and the module has been previously loaded from
277 # disk, we always have to reload the module. Checking the file's
278 # mtime isn't good enough (e.g. the module could contain a class
279 # that inherits from another module that has changed).
280 if forceload and path in sys.modules:
281 if path not in sys.builtin_module_names:
282 # Avoid simply calling reload() because it leaves names in
283 # the currently loaded module lying around if they're not
284 # defined in the new source file. Instead, remove the
285 # module from sys.modules and re-import. Also remove any
286 # submodules because they won't appear in the newly loaded
287 # module's namespace if they're already in sys.modules.
288 subs = [m for m in sys.modules if m.startswith(path + '.')]
289 for key in [path] + subs:
290 # Prevent garbage collection.
291 cache[key] = sys.modules[key]
292 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000293 module = __import__(path)
294 except:
295 # Did the error occur before or after the module was found?
296 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000297 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000298 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000299 raise ErrorDuringImport(sys.modules[path].__file__, info)
300 elif exc is SyntaxError:
301 # A SyntaxError occurred before we could execute the module.
302 raise ErrorDuringImport(value.filename, info)
R. David Murrayef087da2009-06-23 18:02:46 +0000303 elif exc is ImportError and extract_tb(tb)[-1][2]=='safeimport':
304 # The import error occurred directly in this function,
305 # which means there is no such module in the path.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000306 return None
307 else:
308 # Some other error occurred during the importing process.
309 raise ErrorDuringImport(path, sys.exc_info())
310 for part in split(path, '.')[1:]:
311 try: module = getattr(module, part)
312 except AttributeError: return None
313 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000314
315# ---------------------------------------------------- formatter base class
316
317class Doc:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000318 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000319 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000320 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000321 # 'try' clause is to attempt to handle the possibility that inspect
322 # identifies something in a way that pydoc itself has issues handling;
323 # think 'super' and how it is a descriptor (which raises the exception
324 # by lacking a __name__ attribute) and an instance.
Barry Warsaw00decd72006-07-27 23:43:15 +0000325 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
326 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000327 try:
328 if inspect.ismodule(object): return self.docmodule(*args)
329 if inspect.isclass(object): return self.docclass(*args)
330 if inspect.isroutine(object): return self.docroutine(*args)
331 except AttributeError:
332 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000333 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000334 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000335
336 def fail(self, object, name=None, *args):
337 """Raise an exception for unimplemented types."""
338 message = "don't know how to document object%s of type %s" % (
339 name and ' ' + repr(name), type(object).__name__)
340 raise TypeError, message
341
Barry Warsaw00decd72006-07-27 23:43:15 +0000342 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000343
Skip Montanaro4997a692003-09-10 16:47:51 +0000344 def getdocloc(self, object):
345 """Return the location of module docs or None"""
346
347 try:
348 file = inspect.getabsfile(object)
349 except TypeError:
350 file = '(built-in)'
351
352 docloc = os.environ.get("PYTHONDOCS",
Georg Brandl0751d1a2008-01-21 17:13:03 +0000353 "http://docs.python.org/library")
Skip Montanaro4997a692003-09-10 16:47:51 +0000354 basedir = os.path.join(sys.exec_prefix, "lib",
355 "python"+sys.version[0:3])
356 if (isinstance(object, type(os)) and
357 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
358 'marshal', 'posix', 'signal', 'sys',
359 'thread', 'zipimport') or
360 (file.startswith(basedir) and
361 not file.startswith(os.path.join(basedir, 'site-packages'))))):
362 if docloc.startswith("http://"):
Georg Brandl0751d1a2008-01-21 17:13:03 +0000363 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
Skip Montanaro4997a692003-09-10 16:47:51 +0000364 else:
Georg Brandl0751d1a2008-01-21 17:13:03 +0000365 docloc = os.path.join(docloc, object.__name__ + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000366 else:
367 docloc = None
368 return docloc
369
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000370# -------------------------------------------- HTML documentation generator
371
372class HTMLRepr(Repr):
373 """Class for safely making an HTML representation of a Python object."""
374 def __init__(self):
375 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000376 self.maxlist = self.maxtuple = 20
377 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000378 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000379
380 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000381 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000382
383 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000384 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000385
386 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000387 if hasattr(type(x), '__name__'):
388 methodname = 'repr_' + join(split(type(x).__name__), '_')
389 if hasattr(self, methodname):
390 return getattr(self, methodname)(x, level)
391 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000392
393 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000394 test = cram(x, self.maxstring)
395 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000396 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000397 # Backslashes are only literal in the string and are never
398 # needed to make any special characters, so show a raw string.
399 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000400 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000401 r'<font color="#c040c0">\1</font>',
402 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000403
Skip Montanarodf708782002-03-07 22:58:02 +0000404 repr_str = repr_string
405
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000406 def repr_instance(self, x, level):
407 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000408 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000409 except:
410 return self.escape('<%s instance>' % x.__class__.__name__)
411
412 repr_unicode = repr_string
413
414class HTMLDoc(Doc):
415 """Formatter class for HTML documentation."""
416
417 # ------------------------------------------- HTML formatting utilities
418
419 _repr_instance = HTMLRepr()
420 repr = _repr_instance.repr
421 escape = _repr_instance.escape
422
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000423 def page(self, title, contents):
424 """Format an HTML page."""
425 return '''
Georg Brandle0197062009-04-10 08:20:23 +0000426<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000427<html><head><title>Python: %s</title>
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000428</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000429%s
430</body></html>''' % (title, contents)
431
432 def heading(self, title, fgcol, bgcol, extras=''):
433 """Format a page heading."""
434 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000435<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000436<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000437<td valign=bottom>&nbsp;<br>
438<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000439><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000440><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000441 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
442
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000443 def section(self, title, fgcol, bgcol, contents, width=6,
444 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000445 """Format a section with a heading."""
446 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000447 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000448 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000449<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000450<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000451<td colspan=3 valign=bottom>&nbsp;<br>
452<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000453 ''' % (bgcol, fgcol, title)
454 if prelude:
455 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000456<tr bgcolor="%s"><td rowspan=2>%s</td>
457<td colspan=2>%s</td></tr>
458<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
459 else:
460 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000461<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000462
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000463 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000464
465 def bigsection(self, title, *args):
466 """Format a section with a big heading."""
467 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000468 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000469
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000470 def preformat(self, text):
471 """Format literal preformatted text."""
472 text = self.escape(expandtabs(text))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000473 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
474 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000475
476 def multicolumn(self, list, format, cols=4):
477 """Format a list of items into a multi-column list."""
478 result = ''
479 rows = (len(list)+cols-1)/cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000480 for col in range(cols):
481 result = result + '<td width="%d%%" valign=top>' % (100/cols)
482 for i in range(rows*col, rows*col+rows):
483 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000484 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000485 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000486 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000487
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000488 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000489
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000490 def namelink(self, name, *dicts):
491 """Make a link for an identifier, given name-to-URL mappings."""
492 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000493 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000494 return '<a href="%s">%s</a>' % (dict[name], name)
495 return name
496
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000497 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000498 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000499 name, module = object.__name__, sys.modules.get(object.__module__)
500 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000501 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000502 module.__name__, name, classname(object, modname))
503 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000504
505 def modulelink(self, object):
506 """Make a link for a module."""
507 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
508
Brett Cannonaca98b02008-08-03 00:58:51 +0000509 def modpkglink(self, data):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000510 """Make a link for a module or package to display in an index."""
Brett Cannonaca98b02008-08-03 00:58:51 +0000511 name, path, ispackage, shadowed = data
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000512 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000513 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000514 if path:
515 url = '%s.%s.html' % (path, name)
516 else:
517 url = '%s.html' % name
518 if ispackage:
519 text = '<strong>%s</strong>&nbsp;(package)' % name
520 else:
521 text = name
522 return '<a href="%s">%s</a>' % (url, text)
523
524 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
525 """Mark up some plain text, given a context of symbols to look for.
526 Each context dictionary maps object names to anchor names."""
527 escape = escape or self.escape
528 results = []
529 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000530 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
531 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000532 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000533 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000534 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000535 match = pattern.search(text, here)
536 if not match: break
537 start, end = match.span()
538 results.append(escape(text[here:start]))
539
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000540 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000541 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000542 url = escape(all).replace('"', '&quot;')
543 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000544 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000545 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
546 results.append('<a href="%s">%s</a>' % (url, escape(all)))
547 elif pep:
Andrew M. Kuchling727a5902008-02-05 16:06:57 +0000548 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000549 results.append('<a href="%s">%s</a>' % (url, escape(all)))
550 elif text[end:end+1] == '(':
551 results.append(self.namelink(name, methods, funcs, classes))
552 elif selfdot:
553 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000554 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000555 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000556 here = end
557 results.append(escape(text[here:]))
558 return join(results, '')
559
560 # ---------------------------------------------- type-specific routines
561
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000562 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000563 """Produce HTML for a class tree as given by inspect.getclasstree()."""
564 result = ''
565 for entry in tree:
566 if type(entry) is type(()):
567 c, bases = entry
Tim Peters2306d242001-09-25 03:18:32 +0000568 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000569 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000570 if bases and bases != (parent,):
571 parents = []
572 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000573 parents.append(self.classlink(base, modname))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000574 result = result + '(' + join(parents, ', ') + ')'
Tim Peters2306d242001-09-25 03:18:32 +0000575 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000576 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000577 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000578 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000579 return '<dl>\n%s</dl>\n' % result
580
Tim Peters8dd7ade2001-10-18 19:56:17 +0000581 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000582 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000583 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000584 try:
585 all = object.__all__
586 except AttributeError:
587 all = None
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000588 parts = split(name, '.')
589 links = []
590 for i in range(len(parts)-1):
591 links.append(
592 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
593 (join(parts[:i+1], '.'), parts[i]))
594 linkedname = join(links + parts[-1:], '.')
595 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000596 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000597 path = inspect.getabsfile(object)
Ka-Ping Yee6191a232001-04-13 15:00:27 +0000598 url = path
599 if sys.platform == 'win32':
600 import nturl2path
601 url = nturl2path.pathname2url(path)
602 filelink = '<a href="file:%s">%s</a>' % (url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000603 except TypeError:
604 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000605 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000606 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000607 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000608 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
609 version = strip(version[11:-1])
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000610 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000611 if hasattr(object, '__date__'):
612 info.append(self.escape(str(object.__date__)))
613 if info:
614 head = head + ' (%s)' % join(info, ', ')
Skip Montanaro4997a692003-09-10 16:47:51 +0000615 docloc = self.getdocloc(object)
616 if docloc is not None:
617 docloc = '<br><a href="%(docloc)s">Module Docs</a>' % locals()
618 else:
619 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000620 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000621 head, '#ffffff', '#7799ee',
622 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000623
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000624 modules = inspect.getmembers(object, inspect.ismodule)
625
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000626 classes, cdict = [], {}
627 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000628 # if __all__ exists, believe it. Otherwise use old heuristic.
629 if (all is not None or
630 (inspect.getmodule(value) or object) is object):
Skip Montanaroa5616d22004-06-11 04:46:12 +0000631 if visiblename(key, all):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000632 classes.append((key, value))
633 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000634 for key, value in classes:
635 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000636 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000637 module = sys.modules.get(modname)
638 if modname != name and module and hasattr(module, key):
639 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000640 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000641 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000642 funcs, fdict = [], {}
643 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000644 # if __all__ exists, believe it. Otherwise use old heuristic.
645 if (all is not None or
646 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Skip Montanaroa5616d22004-06-11 04:46:12 +0000647 if visiblename(key, all):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000648 funcs.append((key, value))
649 fdict[key] = '#-' + key
650 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000651 data = []
652 for key, value in inspect.getmembers(object, isdata):
Skip Montanaroa5616d22004-06-11 04:46:12 +0000653 if visiblename(key, all):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000654 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000655
656 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
657 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000658 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000659
660 if hasattr(object, '__path__'):
661 modpkgs = []
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000662 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
663 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000664 modpkgs.sort()
665 contents = self.multicolumn(modpkgs, self.modpkglink)
666 result = result + self.bigsection(
667 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000668 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000669 contents = self.multicolumn(
Brett Cannonaca98b02008-08-03 00:58:51 +0000670 modules, lambda key_value, s=self: s.modulelink(key_value[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000671 result = result + self.bigsection(
Georg Brandlb169eaa2008-02-17 21:18:55 +0000672 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000673
674 if classes:
Brett Cannonaca98b02008-08-03 00:58:51 +0000675 classlist = map(lambda key_value: key_value[1], classes)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000676 contents = [
677 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000678 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000679 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000680 result = result + self.bigsection(
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000681 'Classes', '#ffffff', '#ee77aa', join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000682 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000683 contents = []
684 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000685 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000686 result = result + self.bigsection(
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000687 'Functions', '#ffffff', '#eeaa77', join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000688 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000689 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000690 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000691 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000692 result = result + self.bigsection(
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000693 'Data', '#ffffff', '#55aa55', join(contents, '<br>\n'))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000694 if hasattr(object, '__author__'):
695 contents = self.markup(str(object.__author__), self.preformat)
696 result = result + self.bigsection(
697 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000698 if hasattr(object, '__credits__'):
699 contents = self.markup(str(object.__credits__), self.preformat)
700 result = result + self.bigsection(
701 'Credits', '#ffffff', '#7799ee', contents)
702
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000703 return result
704
Tim Peters8dd7ade2001-10-18 19:56:17 +0000705 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
706 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000707 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000708 realname = object.__name__
709 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000710 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000711
Tim Petersb47879b2001-09-24 04:47:19 +0000712 contents = []
713 push = contents.append
714
Tim Petersfa26f7c2001-09-24 08:05:11 +0000715 # Cute little class to pump out a horizontal rule between sections.
716 class HorizontalRule:
717 def __init__(self):
718 self.needone = 0
719 def maybe(self):
720 if self.needone:
721 push('<hr>\n')
722 self.needone = 1
723 hr = HorizontalRule()
724
Tim Petersc86f6ca2001-09-26 21:31:51 +0000725 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000726 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000727 if len(mro) > 2:
728 hr.maybe()
729 push('<dl><dt>Method resolution order:</dt>\n')
730 for base in mro:
731 push('<dd>%s</dd>\n' % self.classlink(base,
732 object.__module__))
733 push('</dl>\n')
734
Tim Petersb47879b2001-09-24 04:47:19 +0000735 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000736 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000737 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000738 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000739 push(msg)
740 for name, kind, homecls, value in ok:
741 push(self.document(getattr(object, name), name, mod,
742 funcs, classes, mdict, object))
743 push('\n')
744 return attrs
745
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000746 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000747 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000748 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000749 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000750 push(msg)
751 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000752 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000753 return attrs
754
Tim Petersfa26f7c2001-09-24 08:05:11 +0000755 def spilldata(msg, attrs, predicate):
756 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000757 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000758 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000759 push(msg)
760 for name, kind, homecls, value in ok:
761 base = self.docother(getattr(object, name), name, mod)
Brett Cannonaca98b02008-08-03 00:58:51 +0000762 if (hasattr(value, '__call__') or
763 inspect.isdatadescriptor(value)):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000764 doc = getattr(value, "__doc__", None)
765 else:
766 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000767 if doc is None:
768 push('<dl><dt>%s</dl>\n' % base)
769 else:
770 doc = self.markup(getdoc(value), self.preformat,
771 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000772 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000773 push('<dl><dt>%s%s</dl>\n' % (base, doc))
774 push('\n')
775 return attrs
776
Brett Cannonaca98b02008-08-03 00:58:51 +0000777 attrs = filter(lambda data: visiblename(data[0]),
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000778 classify_class_attrs(object))
Tim Petersb47879b2001-09-24 04:47:19 +0000779 mdict = {}
780 for key, kind, homecls, value in attrs:
781 mdict[key] = anchor = '#' + name + '-' + key
782 value = getattr(object, key)
783 try:
784 # The value may not be hashable (e.g., a data attr with
785 # a dict or list value).
786 mdict[value] = anchor
787 except TypeError:
788 pass
789
Tim Petersfa26f7c2001-09-24 08:05:11 +0000790 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000791 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000792 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000793 else:
794 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000795 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
796
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000797 if thisclass is __builtin__.object:
798 attrs = inherited
799 continue
800 elif thisclass is object:
801 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000802 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000803 tag = 'inherited from %s' % self.classlink(thisclass,
804 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000805 tag += ':<br>\n'
806
807 # Sort attrs by name.
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000808 try:
809 attrs.sort(key=lambda t: t[0])
810 except TypeError:
811 attrs.sort(lambda t1, t2: cmp(t1[0], t2[0])) # 2.3 compat
Tim Petersb47879b2001-09-24 04:47:19 +0000812
813 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000814 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000815 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000816 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000817 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000818 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000819 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000820 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
821 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000822 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000823 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000824 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000825 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000826
827 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000828
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000829 if name == realname:
830 title = '<a name="%s">class <strong>%s</strong></a>' % (
831 name, realname)
832 else:
833 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
834 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000835 if bases:
836 parents = []
837 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000838 parents.append(self.classlink(base, object.__module__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000839 title = title + '(%s)' % join(parents, ', ')
Tim Peters2306d242001-09-25 03:18:32 +0000840 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000841 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000842
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000843 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000844
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000845 def formatvalue(self, object):
846 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000847 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000848
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000849 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000850 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000851 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000852 realname = object.__name__
853 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000854 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000855 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000856 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000857 if inspect.ismethod(object):
Ka-Ping Yee6dcfa382001-04-12 20:27:31 +0000858 imclass = object.im_class
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000859 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000860 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000861 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000862 else:
Georg Brandl7e2b6bb2007-03-13 22:16:30 +0000863 if object.im_self is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000864 note = ' method of %s instance' % self.classlink(
865 object.im_self.__class__, mod)
866 else:
867 note = ' unbound %s method' % self.classlink(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000868 object = object.im_func
869
870 if name == realname:
871 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
872 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000873 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000874 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000875 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000876 cl.__name__ + '-' + realname, realname)
877 skipdocs = 1
878 else:
879 reallink = realname
880 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
881 anchor, name, reallink)
Tim Peters4bcfa312001-09-20 06:08:24 +0000882 if inspect.isfunction(object):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000883 args, varargs, varkw, defaults = inspect.getargspec(object)
884 argspec = inspect.formatargspec(
885 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000886 if realname == '<lambda>':
Tim Peters59ed4482001-10-31 04:20:26 +0000887 title = '<strong>%s</strong> <em>lambda</em> ' % name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000888 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +0000889 else:
890 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000891
Tim Peters2306d242001-09-25 03:18:32 +0000892 decl = title + argspec + (note and self.grey(
893 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000894
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000895 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000896 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000897 else:
898 doc = self.markup(
899 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000900 doc = doc and '<dd><tt>%s</tt></dd>' % doc
901 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000902
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000903 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000904 results = []
905 push = results.append
906
907 if name:
908 push('<dl><dt><strong>%s</strong></dt>\n' % name)
909 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000910 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000911 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000912 push('</dl>\n')
913
914 return ''.join(results)
915
916 def docproperty(self, object, name=None, mod=None, cl=None):
917 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000918 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000919
Tim Peters8dd7ade2001-10-18 19:56:17 +0000920 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000921 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000922 lhs = name and '<strong>%s</strong> = ' % name or ''
923 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000924
Barry Warsaw00decd72006-07-27 23:43:15 +0000925 def docdata(self, object, name=None, mod=None, cl=None):
926 """Produce html documentation for a data descriptor."""
927 return self._docdescriptor(name, object, mod)
928
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000929 def index(self, dir, shadowed=None):
930 """Generate an HTML index for a directory of modules."""
931 modpkgs = []
932 if shadowed is None: shadowed = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000933 for importer, name, ispkg in pkgutil.iter_modules([dir]):
934 modpkgs.append((name, '', ispkg, name in shadowed))
935 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000936
937 modpkgs.sort()
938 contents = self.multicolumn(modpkgs, self.modpkglink)
939 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
940
941# -------------------------------------------- text documentation generator
942
943class TextRepr(Repr):
944 """Class for safely making a text representation of a Python object."""
945 def __init__(self):
946 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000947 self.maxlist = self.maxtuple = 20
948 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000949 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000950
951 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000952 if hasattr(type(x), '__name__'):
953 methodname = 'repr_' + join(split(type(x).__name__), '_')
954 if hasattr(self, methodname):
955 return getattr(self, methodname)(x, level)
956 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000957
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000958 def repr_string(self, x, level):
959 test = cram(x, self.maxstring)
960 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000961 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000962 # Backslashes are only literal in the string and are never
963 # needed to make any special characters, so show a raw string.
964 return 'r' + testrepr[0] + test + testrepr[0]
965 return testrepr
966
Skip Montanarodf708782002-03-07 22:58:02 +0000967 repr_str = repr_string
968
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000969 def repr_instance(self, x, level):
970 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000971 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000972 except:
973 return '<%s instance>' % x.__class__.__name__
974
975class TextDoc(Doc):
976 """Formatter class for text documentation."""
977
978 # ------------------------------------------- text formatting utilities
979
980 _repr_instance = TextRepr()
981 repr = _repr_instance.repr
982
983 def bold(self, text):
984 """Format a string in bold by overstriking."""
985 return join(map(lambda ch: ch + '\b' + ch, text), '')
986
987 def indent(self, text, prefix=' '):
988 """Indent text by prepending a given prefix to each line."""
989 if not text: return ''
990 lines = split(text, '\n')
991 lines = map(lambda line, prefix=prefix: prefix + line, lines)
992 if lines: lines[-1] = rstrip(lines[-1])
993 return join(lines, '\n')
994
995 def section(self, title, contents):
996 """Format a section with a given heading."""
997 return self.bold(title) + '\n' + rstrip(self.indent(contents)) + '\n\n'
998
999 # ---------------------------------------------- type-specific routines
1000
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001001 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001002 """Render in text a class tree as returned by inspect.getclasstree()."""
1003 result = ''
1004 for entry in tree:
1005 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001006 c, bases = entry
1007 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001008 if bases and bases != (parent,):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001009 parents = map(lambda c, m=modname: classname(c, m), bases)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001010 result = result + '(%s)' % join(parents, ', ')
1011 result = result + '\n'
1012 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001013 result = result + self.formattree(
1014 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001015 return result
1016
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001017 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001018 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001019 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001020 synop, desc = splitdoc(getdoc(object))
1021 result = self.section('NAME', name + (synop and ' - ' + synop))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001022
1023 try:
Skip Montanaroa5616d22004-06-11 04:46:12 +00001024 all = object.__all__
1025 except AttributeError:
1026 all = None
1027
1028 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001029 file = inspect.getabsfile(object)
1030 except TypeError:
1031 file = '(built-in)'
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001032 result = result + self.section('FILE', file)
Skip Montanaro4997a692003-09-10 16:47:51 +00001033
1034 docloc = self.getdocloc(object)
1035 if docloc is not None:
1036 result = result + self.section('MODULE DOCS', docloc)
1037
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001038 if desc:
1039 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001040
1041 classes = []
1042 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001043 # if __all__ exists, believe it. Otherwise use old heuristic.
1044 if (all is not None
1045 or (inspect.getmodule(value) or object) is object):
Skip Montanaroa5616d22004-06-11 04:46:12 +00001046 if visiblename(key, all):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001047 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001048 funcs = []
1049 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001050 # if __all__ exists, believe it. Otherwise use old heuristic.
1051 if (all is not None or
1052 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Skip Montanaroa5616d22004-06-11 04:46:12 +00001053 if visiblename(key, all):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001054 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001055 data = []
1056 for key, value in inspect.getmembers(object, isdata):
Skip Montanaroa5616d22004-06-11 04:46:12 +00001057 if visiblename(key, all):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001058 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001059
Georg Brandlf2dae0e2008-01-21 21:05:49 +00001060 modpkgs = []
1061 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001062 if hasattr(object, '__path__'):
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001063 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Georg Brandlf2dae0e2008-01-21 21:05:49 +00001064 modpkgs_names.add(modname)
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001065 if ispkg:
1066 modpkgs.append(modname + ' (package)')
1067 else:
1068 modpkgs.append(modname)
1069
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001070 modpkgs.sort()
1071 result = result + self.section(
1072 'PACKAGE CONTENTS', join(modpkgs, '\n'))
1073
Georg Brandlf2dae0e2008-01-21 21:05:49 +00001074 # Detect submodules as sometimes created by C extensions
1075 submodules = []
1076 for key, value in inspect.getmembers(object, inspect.ismodule):
1077 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1078 submodules.append(key)
1079 if submodules:
1080 submodules.sort()
1081 result = result + self.section(
1082 'SUBMODULES', join(submodules, '\n'))
1083
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001084 if classes:
Brett Cannonaca98b02008-08-03 00:58:51 +00001085 classlist = map(lambda key_value: key_value[1], classes)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001086 contents = [self.formattree(
1087 inspect.getclasstree(classlist, 1), name)]
1088 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001089 contents.append(self.document(value, key, name))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001090 result = result + self.section('CLASSES', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001091
1092 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001093 contents = []
1094 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001095 contents.append(self.document(value, key, name))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001096 result = result + self.section('FUNCTIONS', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001097
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001098 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001099 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001100 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001101 contents.append(self.docother(value, key, name, maxlen=70))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001102 result = result + self.section('DATA', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001103
1104 if hasattr(object, '__version__'):
1105 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001106 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
1107 version = strip(version[11:-1])
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001108 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001109 if hasattr(object, '__date__'):
1110 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001111 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001112 result = result + self.section('AUTHOR', str(object.__author__))
1113 if hasattr(object, '__credits__'):
1114 result = result + self.section('CREDITS', str(object.__credits__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001115 return result
1116
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001117 def docclass(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001118 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001119 realname = object.__name__
1120 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001121 bases = object.__bases__
1122
Tim Petersc86f6ca2001-09-26 21:31:51 +00001123 def makename(c, m=object.__module__):
1124 return classname(c, m)
1125
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001126 if name == realname:
1127 title = 'class ' + self.bold(realname)
1128 else:
1129 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001130 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001131 parents = map(makename, bases)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001132 title = title + '(%s)' % join(parents, ', ')
1133
1134 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001135 contents = doc and [doc + '\n'] or []
1136 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001137
Tim Petersc86f6ca2001-09-26 21:31:51 +00001138 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001139 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001140 if len(mro) > 2:
1141 push("Method resolution order:")
1142 for base in mro:
1143 push(' ' + makename(base))
1144 push('')
1145
Tim Petersf4aad8e2001-09-24 22:40:47 +00001146 # Cute little class to pump out a horizontal rule between sections.
1147 class HorizontalRule:
1148 def __init__(self):
1149 self.needone = 0
1150 def maybe(self):
1151 if self.needone:
1152 push('-' * 70)
1153 self.needone = 1
1154 hr = HorizontalRule()
1155
Tim Peters28355492001-09-23 21:29:55 +00001156 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001157 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001158 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001159 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001160 push(msg)
1161 for name, kind, homecls, value in ok:
1162 push(self.document(getattr(object, name),
1163 name, mod, object))
1164 return attrs
1165
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001166 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001167 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001168 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001169 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001170 push(msg)
1171 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001172 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001173 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001174
Tim Petersfa26f7c2001-09-24 08:05:11 +00001175 def spilldata(msg, attrs, predicate):
1176 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001177 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001178 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001179 push(msg)
1180 for name, kind, homecls, value in ok:
Brett Cannonaca98b02008-08-03 00:58:51 +00001181 if (hasattr(value, '__call__') or
1182 inspect.isdatadescriptor(value)):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001183 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001184 else:
1185 doc = None
Tim Peters28355492001-09-23 21:29:55 +00001186 push(self.docother(getattr(object, name),
Georg Brandl8b813db2005-10-01 16:32:31 +00001187 name, mod, maxlen=70, doc=doc) + '\n')
Tim Peters28355492001-09-23 21:29:55 +00001188 return attrs
1189
Brett Cannonaca98b02008-08-03 00:58:51 +00001190 attrs = filter(lambda data: visiblename(data[0]),
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001191 classify_class_attrs(object))
Tim Petersfa26f7c2001-09-24 08:05:11 +00001192 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001193 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001194 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001195 else:
1196 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001197 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1198
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001199 if thisclass is __builtin__.object:
1200 attrs = inherited
1201 continue
1202 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001203 tag = "defined here"
1204 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001205 tag = "inherited from %s" % classname(thisclass,
1206 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001207
1208 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001209 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001210
1211 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001212 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001213 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001214 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001215 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001216 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001217 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001218 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1219 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001220 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1221 lambda t: t[1] == 'data')
Tim Peters28355492001-09-23 21:29:55 +00001222 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001223 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001224
1225 contents = '\n'.join(contents)
1226 if not contents:
1227 return title + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001228 return title + '\n' + self.indent(rstrip(contents), ' | ') + '\n'
1229
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001230 def formatvalue(self, object):
1231 """Format an argument default value as text."""
1232 return '=' + self.repr(object)
1233
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001234 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001235 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001236 realname = object.__name__
1237 name = name or realname
1238 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001239 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001240 if inspect.ismethod(object):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001241 imclass = object.im_class
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001242 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001243 if imclass is not cl:
1244 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001245 else:
Georg Brandl7e2b6bb2007-03-13 22:16:30 +00001246 if object.im_self is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001247 note = ' method of %s instance' % classname(
1248 object.im_self.__class__, mod)
1249 else:
1250 note = ' unbound %s method' % classname(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001251 object = object.im_func
1252
1253 if name == realname:
1254 title = self.bold(realname)
1255 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001256 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001257 cl.__dict__[realname] is object):
1258 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001259 title = self.bold(name) + ' = ' + realname
Tim Peters4bcfa312001-09-20 06:08:24 +00001260 if inspect.isfunction(object):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001261 args, varargs, varkw, defaults = inspect.getargspec(object)
1262 argspec = inspect.formatargspec(
1263 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001264 if realname == '<lambda>':
Georg Brandl501dd0d2006-02-17 09:45:40 +00001265 title = self.bold(name) + ' lambda '
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001266 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +00001267 else:
1268 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001269 decl = title + argspec + note
1270
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001271 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001272 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001273 else:
1274 doc = getdoc(object) or ''
1275 return decl + '\n' + (doc and rstrip(self.indent(doc)) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001276
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001277 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001278 results = []
1279 push = results.append
1280
1281 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001282 push(self.bold(name))
1283 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001284 doc = getdoc(value) or ''
1285 if doc:
1286 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001287 push('\n')
1288 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001289
1290 def docproperty(self, object, name=None, mod=None, cl=None):
1291 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001292 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001293
Barry Warsaw00decd72006-07-27 23:43:15 +00001294 def docdata(self, object, name=None, mod=None, cl=None):
1295 """Produce text documentation for a data descriptor."""
1296 return self._docdescriptor(name, object, mod)
1297
Georg Brandl8b813db2005-10-01 16:32:31 +00001298 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001299 """Produce text documentation for a data object."""
1300 repr = self.repr(object)
1301 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001302 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001303 chop = maxlen - len(line)
1304 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001305 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001306 if doc is not None:
1307 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001308 return line
1309
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001310# --------------------------------------------------------- user interfaces
1311
1312def pager(text):
1313 """The first time this is called, determine what kind of pager to use."""
1314 global pager
1315 pager = getpager()
1316 pager(text)
1317
1318def getpager():
1319 """Decide what method to use for paging through text."""
1320 if type(sys.stdout) is not types.FileType:
1321 return plainpager
1322 if not sys.stdin.isatty() or not sys.stdout.isatty():
1323 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001324 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001325 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001326 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001327 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001328 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001329 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001330 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001331 if os.environ.get('TERM') in ('dumb', 'emacs'):
1332 return plainpager
Andrew MacIntyre54e0eab2002-03-03 03:12:30 +00001333 if sys.platform == 'win32' or sys.platform.startswith('os2'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001334 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001335 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001336 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001337
1338 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001339 (fd, filename) = tempfile.mkstemp()
1340 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001341 try:
Georg Brandlb32dea52008-07-16 21:19:28 +00001342 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001343 return lambda text: pipepager(text, 'more')
1344 else:
1345 return ttypager
1346 finally:
1347 os.unlink(filename)
1348
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001349def plain(text):
1350 """Remove boldface formatting from text."""
1351 return re.sub('.\b', '', text)
1352
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001353def pipepager(text, cmd):
1354 """Page through text by feeding it to another program."""
1355 pipe = os.popen(cmd, 'w')
1356 try:
1357 pipe.write(text)
1358 pipe.close()
1359 except IOError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001360 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001361
1362def tempfilepager(text, cmd):
1363 """Page through text by invoking a program on a temporary file."""
1364 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001365 filename = tempfile.mktemp()
1366 file = open(filename, 'w')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001367 file.write(text)
1368 file.close()
1369 try:
Georg Brandlb32dea52008-07-16 21:19:28 +00001370 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001371 finally:
1372 os.unlink(filename)
1373
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001374def ttypager(text):
1375 """Page through text on a text terminal."""
1376 lines = split(plain(text), '\n')
1377 try:
1378 import tty
1379 fd = sys.stdin.fileno()
1380 old = tty.tcgetattr(fd)
1381 tty.setcbreak(fd)
1382 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001383 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001384 tty = None
1385 getchar = lambda: sys.stdin.readline()[:-1][:1]
1386
1387 try:
1388 r = inc = os.environ.get('LINES', 25) - 1
1389 sys.stdout.write(join(lines[:inc], '\n') + '\n')
1390 while lines[r:]:
1391 sys.stdout.write('-- more --')
1392 sys.stdout.flush()
1393 c = getchar()
1394
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001395 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001396 sys.stdout.write('\r \r')
1397 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001398 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001399 sys.stdout.write('\r \r' + lines[r] + '\n')
1400 r = r + 1
1401 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001402 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001403 r = r - inc - inc
1404 if r < 0: r = 0
1405 sys.stdout.write('\n' + join(lines[r:r+inc], '\n') + '\n')
1406 r = r + inc
1407
1408 finally:
1409 if tty:
1410 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1411
1412def plainpager(text):
1413 """Simply print unformatted text. This is the ultimate fallback."""
1414 sys.stdout.write(plain(text))
1415
1416def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001417 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001418 if inspect.ismodule(thing):
1419 if thing.__name__ in sys.builtin_module_names:
1420 return 'built-in module ' + thing.__name__
1421 if hasattr(thing, '__path__'):
1422 return 'package ' + thing.__name__
1423 else:
1424 return 'module ' + thing.__name__
1425 if inspect.isbuiltin(thing):
1426 return 'built-in function ' + thing.__name__
Barry Warsaw00decd72006-07-27 23:43:15 +00001427 if inspect.isgetsetdescriptor(thing):
1428 return 'getset descriptor %s.%s.%s' % (
1429 thing.__objclass__.__module__, thing.__objclass__.__name__,
1430 thing.__name__)
1431 if inspect.ismemberdescriptor(thing):
1432 return 'member descriptor %s.%s.%s' % (
1433 thing.__objclass__.__module__, thing.__objclass__.__name__,
1434 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001435 if inspect.isclass(thing):
1436 return 'class ' + thing.__name__
1437 if inspect.isfunction(thing):
1438 return 'function ' + thing.__name__
1439 if inspect.ismethod(thing):
1440 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001441 if type(thing) is types.InstanceType:
1442 return 'instance of ' + thing.__class__.__name__
1443 return type(thing).__name__
1444
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001445def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001446 """Locate an object by name or dotted path, importing as necessary."""
Guido van Rossum97dede02003-02-16 01:12:32 +00001447 parts = [part for part in split(path, '.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001448 module, n = None, 0
1449 while n < len(parts):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001450 nextmodule = safeimport(join(parts[:n+1], '.'), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001451 if nextmodule: module, n = nextmodule, n + 1
1452 else: break
1453 if module:
1454 object = module
1455 for part in parts[n:]:
1456 try: object = getattr(object, part)
1457 except AttributeError: return None
1458 return object
1459 else:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001460 if hasattr(__builtin__, path):
1461 return getattr(__builtin__, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001462
1463# --------------------------------------- interactive interpreter interface
1464
1465text = TextDoc()
1466html = HTMLDoc()
1467
Ka-Ping Yee8ef1cf32007-01-14 04:25:15 +00001468class _OldStyleClass: pass
1469_OLD_INSTANCE_TYPE = type(_OldStyleClass())
1470
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001471def resolve(thing, forceload=0):
1472 """Given an object or a path to an object, get the object and its name."""
1473 if isinstance(thing, str):
1474 object = locate(thing, forceload)
1475 if not object:
1476 raise ImportError, 'no Python documentation found for %r' % thing
1477 return object, thing
1478 else:
1479 return thing, getattr(thing, '__name__', None)
1480
Georg Brandl8441f152007-03-13 20:02:57 +00001481def render_doc(thing, title='Python Library Documentation: %s', forceload=0):
1482 """Render text documentation, given an object or a path to an object."""
1483 object, name = resolve(thing, forceload)
1484 desc = describe(object)
1485 module = inspect.getmodule(object)
1486 if name and '.' in name:
1487 desc += ' in ' + name[:name.rfind('.')]
1488 elif module and module is not object:
1489 desc += ' in module ' + module.__name__
1490 if type(object) is _OLD_INSTANCE_TYPE:
1491 # If the passed object is an instance of an old-style class,
1492 # document its available methods instead of its value.
1493 object = object.__class__
1494 elif not (inspect.ismodule(object) or
1495 inspect.isclass(object) or
1496 inspect.isroutine(object) or
1497 inspect.isgetsetdescriptor(object) or
1498 inspect.ismemberdescriptor(object) or
1499 isinstance(object, property)):
1500 # If the passed object is a piece of data or an instance,
1501 # document its available methods instead of its value.
1502 object = type(object)
1503 desc += ' object'
1504 return title % desc + '\n\n' + text.document(object, name)
1505
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001506def doc(thing, title='Python Library Documentation: %s', forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001507 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001508 try:
Georg Brandl8441f152007-03-13 20:02:57 +00001509 pager(render_doc(thing, title, forceload))
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001510 except (ImportError, ErrorDuringImport), value:
1511 print value
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001512
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001513def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001514 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001515 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001516 object, name = resolve(thing, forceload)
1517 page = html.page(describe(object), html.document(object, name))
1518 file = open(name + '.html', 'w')
1519 file.write(page)
1520 file.close()
1521 print 'wrote', name + '.html'
1522 except (ImportError, ErrorDuringImport), value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001523 print value
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001524
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001525def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001526 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001527 if done is None: done = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001528 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1529 writedoc(modname)
1530 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001531
1532class Helper:
Georg Brandl681001e2008-06-01 20:33:55 +00001533
1534 # These dictionaries map a topic name to either an alias, or a tuple
1535 # (label, seealso-items). The "label" is the label of the corresponding
1536 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl43819252009-04-26 09:56:44 +00001537 # in pydoc_data/topics.py.
Georg Brandl681001e2008-06-01 20:33:55 +00001538 #
1539 # CAUTION: if you change one of these dictionaries, be sure to adapt the
1540 # list of needed labels in Doc/tools/sphinxext/pyspecific.py and
Georg Brandl43819252009-04-26 09:56:44 +00001541 # regenerate the pydoc_data/topics.py file by running
Georg Brandl681001e2008-06-01 20:33:55 +00001542 # make pydoc-topics
1543 # in Doc/ and copying the output file into the Lib/ directory.
1544
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001545 keywords = {
1546 'and': 'BOOLEAN',
Georg Brandlb6a87542007-03-13 10:06:48 +00001547 'as': 'with',
Georg Brandl681001e2008-06-01 20:33:55 +00001548 'assert': ('assert', ''),
1549 'break': ('break', 'while for'),
1550 'class': ('class', 'CLASSES SPECIALMETHODS'),
1551 'continue': ('continue', 'while for'),
1552 'def': ('function', ''),
1553 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001554 'elif': 'if',
Georg Brandl681001e2008-06-01 20:33:55 +00001555 'else': ('else', 'while for'),
Georg Brandl5c669db2008-08-30 19:03:43 +00001556 'except': 'try',
Georg Brandl681001e2008-06-01 20:33:55 +00001557 'exec': ('exec', ''),
Georg Brandl5c669db2008-08-30 19:03:43 +00001558 'finally': 'try',
Georg Brandl681001e2008-06-01 20:33:55 +00001559 'for': ('for', 'break continue while'),
Georg Brandl5c669db2008-08-30 19:03:43 +00001560 'from': 'import',
Georg Brandl681001e2008-06-01 20:33:55 +00001561 'global': ('global', 'NAMESPACES'),
1562 'if': ('if', 'TRUTHVALUE'),
1563 'import': ('import', 'MODULES'),
1564 'in': ('in', 'SEQUENCEMETHODS2'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001565 'is': 'COMPARISON',
Georg Brandl681001e2008-06-01 20:33:55 +00001566 'lambda': ('lambda', 'FUNCTIONS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001567 'not': 'BOOLEAN',
1568 'or': 'BOOLEAN',
Georg Brandl681001e2008-06-01 20:33:55 +00001569 'pass': ('pass', ''),
1570 'print': ('print', ''),
1571 'raise': ('raise', 'EXCEPTIONS'),
1572 'return': ('return', 'FUNCTIONS'),
1573 'try': ('try', 'EXCEPTIONS'),
1574 'while': ('while', 'break continue if TRUTHVALUE'),
1575 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1576 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001577 }
Georg Brandlc3a98032008-12-27 18:20:04 +00001578 # Either add symbols to this dictionary or to the symbols dictionary
1579 # directly: Whichever is easier. They are merged later.
1580 _symbols_inverse = {
1581 'STRINGS' : ("'", "'''", "r'", "u'", '"""', '"', 'r"', 'u"'),
1582 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1583 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1584 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1585 'UNARY' : ('-', '~'),
1586 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1587 '^=', '<<=', '>>=', '**=', '//='),
1588 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1589 'COMPLEX' : ('j', 'J')
1590 }
1591 symbols = {
1592 '%': 'OPERATORS FORMATTING',
1593 '**': 'POWER',
1594 ',': 'TUPLES LISTS FUNCTIONS',
1595 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1596 '...': 'ELLIPSIS',
1597 ':': 'SLICINGS DICTIONARYLITERALS',
1598 '@': 'def class',
1599 '\\': 'STRINGS',
1600 '_': 'PRIVATENAMES',
1601 '__': 'PRIVATENAMES SPECIALMETHODS',
1602 '`': 'BACKQUOTES',
1603 '(': 'TUPLES FUNCTIONS CALLS',
1604 ')': 'TUPLES FUNCTIONS CALLS',
1605 '[': 'LISTS SUBSCRIPTS SLICINGS',
1606 ']': 'LISTS SUBSCRIPTS SLICINGS'
1607 }
1608 for topic, symbols_ in _symbols_inverse.iteritems():
1609 for symbol in symbols_:
1610 topics = symbols.get(symbol, topic)
1611 if topic not in topics:
1612 topics = topics + ' ' + topic
1613 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001614
1615 topics = {
Georg Brandl681001e2008-06-01 20:33:55 +00001616 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1617 'FUNCTIONS CLASSES MODULES FILES inspect'),
1618 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS FORMATTING '
1619 'TYPES'),
1620 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1621 'FORMATTING': ('formatstrings', 'OPERATORS'),
1622 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1623 'FORMATTING TYPES'),
1624 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1625 'INTEGER': ('integers', 'int range'),
1626 'FLOAT': ('floating', 'float math'),
1627 'COMPLEX': ('imaginary', 'complex cmath'),
1628 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING xrange LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001629 'MAPPINGS': 'DICTIONARIES',
Georg Brandl681001e2008-06-01 20:33:55 +00001630 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1631 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1632 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1633 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001634 'FRAMEOBJECTS': 'TYPES',
1635 'TRACEBACKS': 'TYPES',
Georg Brandl681001e2008-06-01 20:33:55 +00001636 'NONE': ('bltin-null-object', ''),
1637 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
1638 'FILES': ('bltin-file-objects', ''),
1639 'SPECIALATTRIBUTES': ('specialattrs', ''),
1640 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1641 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001642 'PACKAGES': 'import',
Georg Brandl681001e2008-06-01 20:33:55 +00001643 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1644 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1645 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1646 'LISTS DICTIONARIES BACKQUOTES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001647 'OPERATORS': 'EXPRESSIONS',
1648 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl681001e2008-06-01 20:33:55 +00001649 'OBJECTS': ('objects', 'TYPES'),
1650 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
1651 'CALLABLEMETHODS SEQUENCEMETHODS1 MAPPINGMETHODS '
1652 'SEQUENCEMETHODS2 NUMBERMETHODS CLASSES'),
1653 'BASICMETHODS': ('customization', 'cmp hash repr str SPECIALMETHODS'),
1654 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1655 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
1656 'SEQUENCEMETHODS1': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS2 '
1657 'SPECIALMETHODS'),
1658 'SEQUENCEMETHODS2': ('sequence-methods', 'SEQUENCES SEQUENCEMETHODS1 '
1659 'SPECIALMETHODS'),
1660 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1661 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1662 'SPECIALMETHODS'),
1663 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
1664 'NAMESPACES': ('naming', 'global ASSIGNMENT DELETION DYNAMICFEATURES'),
1665 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001666 'SCOPING': 'NAMESPACES',
1667 'FRAMES': 'NAMESPACES',
Georg Brandl681001e2008-06-01 20:33:55 +00001668 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1669 'COERCIONS': ('coercion-rules','CONVERSIONS'),
1670 'CONVERSIONS': ('conversions', 'COERCIONS'),
1671 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1672 'SPECIALIDENTIFIERS': ('id-classes', ''),
1673 'PRIVATENAMES': ('atom-identifiers', ''),
1674 'LITERALS': ('atom-literals', 'STRINGS BACKQUOTES NUMBERS '
1675 'TUPLELITERALS LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001676 'TUPLES': 'SEQUENCES',
Georg Brandl681001e2008-06-01 20:33:55 +00001677 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1678 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1679 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1680 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1681 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1682 'BACKQUOTES': ('string-conversions', 'repr str STRINGS LITERALS'),
1683 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr '
1684 'ATTRIBUTEMETHODS'),
1685 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS1'),
1686 'SLICINGS': ('slicings', 'SEQUENCEMETHODS2'),
1687 'CALLS': ('calls', 'EXPRESSIONS'),
1688 'POWER': ('power', 'EXPRESSIONS'),
1689 'UNARY': ('unary', 'EXPRESSIONS'),
1690 'BINARY': ('binary', 'EXPRESSIONS'),
1691 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1692 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1693 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1694 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001695 'ASSERTION': 'assert',
Georg Brandl681001e2008-06-01 20:33:55 +00001696 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1697 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001698 'DELETION': 'del',
1699 'PRINTING': 'print',
1700 'RETURNING': 'return',
1701 'IMPORTING': 'import',
1702 'CONDITIONAL': 'if',
Georg Brandl681001e2008-06-01 20:33:55 +00001703 'LOOPING': ('compound', 'for while break continue'),
1704 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1705 'DEBUGGING': ('debugger', 'pdb'),
1706 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001707 }
1708
1709 def __init__(self, input, output):
1710 self.input = input
1711 self.output = output
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001712
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001713 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001714 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001715 self()
1716 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001717 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001718
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001719 def __call__(self, request=None):
1720 if request is not None:
1721 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001722 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001723 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001724 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001725 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001726You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001727If you want to ask for help on a particular object directly from the
1728interpreter, you can type "help(object)". Executing "help('string')"
1729has the same effect as typing a particular string at the help> prompt.
1730''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001731
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001732 def interact(self):
1733 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001734 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001735 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001736 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001737 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001738 except (KeyboardInterrupt, EOFError):
1739 break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001740 request = strip(replace(request, '"', '', "'", ''))
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001741 if lower(request) in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001742 self.help(request)
1743
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001744 def getline(self, prompt):
1745 """Read one line, using raw_input when available."""
1746 if self.input is sys.stdin:
1747 return raw_input(prompt)
1748 else:
1749 self.output.write(prompt)
1750 self.output.flush()
1751 return self.input.readline()
1752
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001753 def help(self, request):
1754 if type(request) is type(''):
R. David Murrayd67ea7d2009-05-27 20:07:21 +00001755 request = request.strip()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001756 if request == 'help': self.intro()
1757 elif request == 'keywords': self.listkeywords()
Georg Brandlc3a98032008-12-27 18:20:04 +00001758 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001759 elif request == 'topics': self.listtopics()
1760 elif request == 'modules': self.listmodules()
1761 elif request[:8] == 'modules ':
1762 self.listmodules(split(request)[1])
Georg Brandlc3a98032008-12-27 18:20:04 +00001763 elif request in self.symbols: self.showsymbol(request)
Raymond Hettinger54f02222002-06-01 14:18:47 +00001764 elif request in self.keywords: self.showtopic(request)
1765 elif request in self.topics: self.showtopic(request)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001766 elif request: doc(request, 'Help on %s:')
1767 elif isinstance(request, Helper): self()
1768 else: doc(request, 'Help on %s:')
1769 self.output.write('\n')
1770
1771 def intro(self):
1772 self.output.write('''
1773Welcome to Python %s! This is the online help utility.
1774
1775If this is your first time using Python, you should definitely check out
Georg Brandl0751d1a2008-01-21 17:13:03 +00001776the tutorial on the Internet at http://docs.python.org/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001777
1778Enter the name of any module, keyword, or topic to get help on writing
1779Python programs and using Python modules. To quit this help utility and
1780return to the interpreter, just type "quit".
1781
1782To get a list of available modules, keywords, or topics, type "modules",
1783"keywords", or "topics". Each module also comes with a one-line summary
1784of what it does; to list the modules whose summaries contain a given word
1785such as "spam", type "modules spam".
1786''' % sys.version[:3])
1787
1788 def list(self, items, columns=4, width=80):
1789 items = items[:]
1790 items.sort()
1791 colw = width / columns
1792 rows = (len(items) + columns - 1) / columns
1793 for row in range(rows):
1794 for col in range(columns):
1795 i = col * rows + row
1796 if i < len(items):
1797 self.output.write(items[i])
1798 if col < columns - 1:
1799 self.output.write(' ' + ' ' * (colw-1 - len(items[i])))
1800 self.output.write('\n')
1801
1802 def listkeywords(self):
1803 self.output.write('''
1804Here is a list of the Python keywords. Enter any keyword to get more help.
1805
1806''')
1807 self.list(self.keywords.keys())
1808
Georg Brandlc3a98032008-12-27 18:20:04 +00001809 def listsymbols(self):
1810 self.output.write('''
1811Here is a list of the punctuation symbols which Python assigns special meaning
1812to. Enter any symbol to get more help.
1813
1814''')
1815 self.list(self.symbols.keys())
1816
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001817 def listtopics(self):
1818 self.output.write('''
1819Here is a list of available topics. Enter any topic name to get more help.
1820
1821''')
1822 self.list(self.topics.keys())
1823
Georg Brandlc3a98032008-12-27 18:20:04 +00001824 def showtopic(self, topic, more_xrefs=''):
Georg Brandl681001e2008-06-01 20:33:55 +00001825 try:
Georg Brandl43819252009-04-26 09:56:44 +00001826 import pydoc_data.topics
Georg Brandl681001e2008-06-01 20:33:55 +00001827 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001828 self.output.write('''
Georg Brandl681001e2008-06-01 20:33:55 +00001829Sorry, topic and keyword documentation is not available because the
Georg Brandl43819252009-04-26 09:56:44 +00001830module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001831''')
1832 return
1833 target = self.topics.get(topic, self.keywords.get(topic))
1834 if not target:
1835 self.output.write('no documentation found for %s\n' % repr(topic))
1836 return
1837 if type(target) is type(''):
Georg Brandlc3a98032008-12-27 18:20:04 +00001838 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001839
Georg Brandl681001e2008-06-01 20:33:55 +00001840 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001841 try:
Georg Brandl43819252009-04-26 09:56:44 +00001842 doc = pydoc_data.topics.topics[label]
Georg Brandl681001e2008-06-01 20:33:55 +00001843 except KeyError:
1844 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001845 return
Georg Brandl681001e2008-06-01 20:33:55 +00001846 pager(strip(doc) + '\n')
Georg Brandlc3a98032008-12-27 18:20:04 +00001847 if more_xrefs:
1848 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001849 if xrefs:
Georg Brandl681001e2008-06-01 20:33:55 +00001850 import StringIO, formatter
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001851 buffer = StringIO.StringIO()
1852 formatter.DumbWriter(buffer).send_flowing_data(
1853 'Related help topics: ' + join(split(xrefs), ', ') + '\n')
1854 self.output.write('\n%s\n' % buffer.getvalue())
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001855
Georg Brandlc3a98032008-12-27 18:20:04 +00001856 def showsymbol(self, symbol):
1857 target = self.symbols[symbol]
1858 topic, _, xrefs = target.partition(' ')
1859 self.showtopic(topic, xrefs)
1860
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001861 def listmodules(self, key=''):
1862 if key:
1863 self.output.write('''
1864Here is a list of matching modules. Enter any module name to get more help.
1865
1866''')
1867 apropos(key)
1868 else:
1869 self.output.write('''
1870Please wait a moment while I gather a list of all available modules...
1871
1872''')
1873 modules = {}
1874 def callback(path, modname, desc, modules=modules):
1875 if modname and modname[-9:] == '.__init__':
1876 modname = modname[:-9] + ' (package)'
1877 if find(modname, '.') < 0:
1878 modules[modname] = 1
Ka-Ping Yee9e0f1162008-01-13 11:25:13 +00001879 def onerror(modname):
1880 callback(None, modname, None)
1881 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001882 self.list(modules.keys())
1883 self.output.write('''
1884Enter any module name to get more help. Or, type "modules spam" to search
1885for modules whose descriptions contain the word "spam".
1886''')
1887
1888help = Helper(sys.stdin, sys.stdout)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001889
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001890class Scanner:
1891 """A generic tree iterator."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001892 def __init__(self, roots, children, descendp):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001893 self.roots = roots[:]
1894 self.state = []
1895 self.children = children
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001896 self.descendp = descendp
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001897
1898 def next(self):
1899 if not self.state:
1900 if not self.roots:
1901 return None
1902 root = self.roots.pop(0)
1903 self.state = [(root, self.children(root))]
1904 node, children = self.state[-1]
1905 if not children:
1906 self.state.pop()
1907 return self.next()
1908 child = children.pop(0)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001909 if self.descendp(child):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001910 self.state.append((child, self.children(child)))
1911 return child
1912
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001913
1914class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001915 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001916
Ka-Ping Yee9e0f1162008-01-13 11:25:13 +00001917 def run(self, callback, key=None, completer=None, onerror=None):
Ka-Ping Yee66246962001-04-12 11:59:50 +00001918 if key: key = lower(key)
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001919 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001920 seen = {}
1921
1922 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001923 if modname != '__main__':
1924 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00001925 if key is None:
1926 callback(None, modname, '')
1927 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001928 desc = split(__import__(modname).__doc__ or '', '\n')[0]
Ka-Ping Yee66246962001-04-12 11:59:50 +00001929 if find(lower(modname + ' - ' + desc), key) >= 0:
1930 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001931
Ka-Ping Yee9e0f1162008-01-13 11:25:13 +00001932 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001933 if self.quit:
1934 break
1935 if key is None:
1936 callback(None, modname, '')
1937 else:
1938 loader = importer.find_module(modname)
1939 if hasattr(loader,'get_source'):
1940 import StringIO
1941 desc = source_synopsis(
1942 StringIO.StringIO(loader.get_source(modname))
1943 ) or ''
1944 if hasattr(loader,'get_filename'):
1945 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00001946 else:
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001947 path = None
1948 else:
1949 module = loader.load_module(modname)
1950 desc = (module.__doc__ or '').splitlines()[0]
1951 path = getattr(module,'__file__',None)
1952 if find(lower(modname + ' - ' + desc), key) >= 0:
1953 callback(path, modname, desc)
1954
1955 if completer:
1956 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001957
1958def apropos(key):
1959 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001960 def callback(path, modname, desc):
1961 if modname[-9:] == '.__init__':
1962 modname = modname[:-9] + ' (package)'
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001963 print modname, desc and '- ' + desc
1964 try: import warnings
1965 except ImportError: pass
1966 else: warnings.filterwarnings('ignore') # ignore problems during import
Ka-Ping Yee66246962001-04-12 11:59:50 +00001967 ModuleScanner().run(callback, key)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001968
1969# --------------------------------------------------- web browser interface
1970
Ka-Ping Yee66246962001-04-12 11:59:50 +00001971def serve(port, callback=None, completer=None):
Ka-Ping Yeefd540692001-04-12 12:54:36 +00001972 import BaseHTTPServer, mimetools, select
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001973
1974 # Patch up mimetools.Message so it doesn't break if rfc822 is reloaded.
1975 class Message(mimetools.Message):
1976 def __init__(self, fp, seekable=1):
1977 Message = self.__class__
1978 Message.__bases__[0].__bases__[0].__init__(self, fp, seekable)
1979 self.encodingheader = self.getheader('content-transfer-encoding')
1980 self.typeheader = self.getheader('content-type')
1981 self.parsetype()
1982 self.parseplist()
1983
1984 class DocHandler(BaseHTTPServer.BaseHTTPRequestHandler):
1985 def send_document(self, title, contents):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001986 try:
1987 self.send_response(200)
1988 self.send_header('Content-Type', 'text/html')
1989 self.end_headers()
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001990 self.wfile.write(html.page(title, contents))
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001991 except IOError: pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001992
1993 def do_GET(self):
1994 path = self.path
1995 if path[-5:] == '.html': path = path[:-5]
1996 if path[:1] == '/': path = path[1:]
1997 if path and path != '.':
1998 try:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001999 obj = locate(path, forceload=1)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002000 except ErrorDuringImport, value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002001 self.send_document(path, html.escape(str(value)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002002 return
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002003 if obj:
2004 self.send_document(describe(obj), html.document(obj, path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002005 else:
2006 self.send_document(path,
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002007'no Python documentation found for %s' % repr(path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002008 else:
2009 heading = html.heading(
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002010'<big><big><strong>Python: Index of Modules</strong></big></big>',
2011'#ffffff', '#7799ee')
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002012 def bltinlink(name):
2013 return '<a href="%s.html">%s</a>' % (name, name)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002014 names = filter(lambda x: x != '__main__',
2015 sys.builtin_module_names)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002016 contents = html.multicolumn(names, bltinlink)
2017 indices = ['<p>' + html.bigsection(
2018 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2019
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002020 seen = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +00002021 for dir in sys.path:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002022 indices.append(html.index(dir, seen))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002023 contents = heading + join(indices) + '''<p align=right>
Tim Peters2306d242001-09-25 03:18:32 +00002024<font color="#909090" face="helvetica, arial"><strong>
2025pydoc</strong> by Ka-Ping Yee &lt;ping@lfw.org&gt;</font>'''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002026 self.send_document('Index of Modules', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002027
2028 def log_message(self, *args): pass
2029
Ka-Ping Yeefd540692001-04-12 12:54:36 +00002030 class DocServer(BaseHTTPServer.HTTPServer):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002031 def __init__(self, port, callback):
Ka-Ping Yeedb8ed152001-03-02 05:58:17 +00002032 host = (sys.platform == 'mac') and '127.0.0.1' or 'localhost'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002033 self.address = ('', port)
Ka-Ping Yeedb8ed152001-03-02 05:58:17 +00002034 self.url = 'http://%s:%d/' % (host, port)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002035 self.callback = callback
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002036 self.base.__init__(self, self.address, self.handler)
2037
2038 def serve_until_quit(self):
2039 import select
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002040 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002041 while not self.quit:
2042 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2043 if rd: self.handle_request()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002044
2045 def server_activate(self):
2046 self.base.server_activate(self)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002047 if self.callback: self.callback(self)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002048
2049 DocServer.base = BaseHTTPServer.HTTPServer
2050 DocServer.handler = DocHandler
2051 DocHandler.MessageClass = Message
2052 try:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002053 try:
2054 DocServer(port, callback).serve_until_quit()
2055 except (KeyboardInterrupt, select.error):
2056 pass
2057 finally:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002058 if completer: completer()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002059
2060# ----------------------------------------------------- graphical interface
2061
2062def gui():
2063 """Graphical interface (starts web server and pops up a control window)."""
2064 class GUI:
2065 def __init__(self, window, port=7464):
2066 self.window = window
2067 self.server = None
2068 self.scanner = None
2069
Georg Brandl6634bf22008-05-20 07:13:37 +00002070 import Tkinter
2071 self.server_frm = Tkinter.Frame(window)
2072 self.title_lbl = Tkinter.Label(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002073 text='Starting server...\n ')
Georg Brandl6634bf22008-05-20 07:13:37 +00002074 self.open_btn = Tkinter.Button(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002075 text='open browser', command=self.open, state='disabled')
Georg Brandl6634bf22008-05-20 07:13:37 +00002076 self.quit_btn = Tkinter.Button(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002077 text='quit serving', command=self.quit, state='disabled')
2078
Georg Brandl6634bf22008-05-20 07:13:37 +00002079 self.search_frm = Tkinter.Frame(window)
2080 self.search_lbl = Tkinter.Label(self.search_frm, text='Search for')
2081 self.search_ent = Tkinter.Entry(self.search_frm)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002082 self.search_ent.bind('<Return>', self.search)
Georg Brandl6634bf22008-05-20 07:13:37 +00002083 self.stop_btn = Tkinter.Button(self.search_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002084 text='stop', pady=0, command=self.stop, state='disabled')
2085 if sys.platform == 'win32':
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002086 # Trying to hide and show this button crashes under Windows.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002087 self.stop_btn.pack(side='right')
2088
2089 self.window.title('pydoc')
2090 self.window.protocol('WM_DELETE_WINDOW', self.quit)
2091 self.title_lbl.pack(side='top', fill='x')
2092 self.open_btn.pack(side='left', fill='x', expand=1)
2093 self.quit_btn.pack(side='right', fill='x', expand=1)
2094 self.server_frm.pack(side='top', fill='x')
2095
2096 self.search_lbl.pack(side='left')
2097 self.search_ent.pack(side='right', fill='x', expand=1)
2098 self.search_frm.pack(side='top', fill='x')
2099 self.search_ent.focus_set()
2100
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002101 font = ('helvetica', sys.platform == 'win32' and 8 or 10)
Georg Brandl6634bf22008-05-20 07:13:37 +00002102 self.result_lst = Tkinter.Listbox(window, font=font, height=6)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002103 self.result_lst.bind('<Button-1>', self.select)
2104 self.result_lst.bind('<Double-Button-1>', self.goto)
Georg Brandl6634bf22008-05-20 07:13:37 +00002105 self.result_scr = Tkinter.Scrollbar(window,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002106 orient='vertical', command=self.result_lst.yview)
2107 self.result_lst.config(yscrollcommand=self.result_scr.set)
2108
Georg Brandl6634bf22008-05-20 07:13:37 +00002109 self.result_frm = Tkinter.Frame(window)
2110 self.goto_btn = Tkinter.Button(self.result_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002111 text='go to selected', command=self.goto)
Georg Brandl6634bf22008-05-20 07:13:37 +00002112 self.hide_btn = Tkinter.Button(self.result_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002113 text='hide results', command=self.hide)
2114 self.goto_btn.pack(side='left', fill='x', expand=1)
2115 self.hide_btn.pack(side='right', fill='x', expand=1)
2116
2117 self.window.update()
2118 self.minwidth = self.window.winfo_width()
2119 self.minheight = self.window.winfo_height()
2120 self.bigminheight = (self.server_frm.winfo_reqheight() +
2121 self.search_frm.winfo_reqheight() +
2122 self.result_lst.winfo_reqheight() +
2123 self.result_frm.winfo_reqheight())
2124 self.bigwidth, self.bigheight = self.minwidth, self.bigminheight
2125 self.expanded = 0
2126 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2127 self.window.wm_minsize(self.minwidth, self.minheight)
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002128 self.window.tk.willdispatch()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002129
2130 import threading
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002131 threading.Thread(
2132 target=serve, args=(port, self.ready, self.quit)).start()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002133
2134 def ready(self, server):
2135 self.server = server
2136 self.title_lbl.config(
2137 text='Python documentation server at\n' + server.url)
2138 self.open_btn.config(state='normal')
2139 self.quit_btn.config(state='normal')
2140
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002141 def open(self, event=None, url=None):
2142 url = url or self.server.url
2143 try:
2144 import webbrowser
2145 webbrowser.open(url)
2146 except ImportError: # pre-webbrowser.py compatibility
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002147 if sys.platform == 'win32':
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002148 os.system('start "%s"' % url)
2149 elif sys.platform == 'mac':
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002150 try: import ic
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002151 except ImportError: pass
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002152 else: ic.launchurl(url)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002153 else:
2154 rc = os.system('netscape -remote "openURL(%s)" &' % url)
2155 if rc: os.system('netscape "%s" &' % url)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002156
2157 def quit(self, event=None):
2158 if self.server:
2159 self.server.quit = 1
2160 self.window.quit()
2161
2162 def search(self, event=None):
2163 key = self.search_ent.get()
2164 self.stop_btn.pack(side='right')
2165 self.stop_btn.config(state='normal')
2166 self.search_lbl.config(text='Searching for "%s"...' % key)
2167 self.search_ent.forget()
2168 self.search_lbl.pack(side='left')
2169 self.result_lst.delete(0, 'end')
2170 self.goto_btn.config(state='disabled')
2171 self.expand()
2172
2173 import threading
2174 if self.scanner:
2175 self.scanner.quit = 1
2176 self.scanner = ModuleScanner()
2177 threading.Thread(target=self.scanner.run,
Ka-Ping Yee6dcfa382001-04-12 20:27:31 +00002178 args=(self.update, key, self.done)).start()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002179
2180 def update(self, path, modname, desc):
2181 if modname[-9:] == '.__init__':
2182 modname = modname[:-9] + ' (package)'
2183 self.result_lst.insert('end',
2184 modname + ' - ' + (desc or '(no description)'))
2185
2186 def stop(self, event=None):
2187 if self.scanner:
2188 self.scanner.quit = 1
2189 self.scanner = None
2190
2191 def done(self):
2192 self.scanner = None
2193 self.search_lbl.config(text='Search for')
2194 self.search_lbl.pack(side='left')
2195 self.search_ent.pack(side='right', fill='x', expand=1)
2196 if sys.platform != 'win32': self.stop_btn.forget()
2197 self.stop_btn.config(state='disabled')
2198
2199 def select(self, event=None):
2200 self.goto_btn.config(state='normal')
2201
2202 def goto(self, event=None):
2203 selection = self.result_lst.curselection()
2204 if selection:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002205 modname = split(self.result_lst.get(selection[0]))[0]
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002206 self.open(url=self.server.url + modname + '.html')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002207
2208 def collapse(self):
2209 if not self.expanded: return
2210 self.result_frm.forget()
2211 self.result_scr.forget()
2212 self.result_lst.forget()
2213 self.bigwidth = self.window.winfo_width()
2214 self.bigheight = self.window.winfo_height()
2215 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2216 self.window.wm_minsize(self.minwidth, self.minheight)
2217 self.expanded = 0
2218
2219 def expand(self):
2220 if self.expanded: return
2221 self.result_frm.pack(side='bottom', fill='x')
2222 self.result_scr.pack(side='right', fill='y')
2223 self.result_lst.pack(side='top', fill='both', expand=1)
2224 self.window.wm_geometry('%dx%d' % (self.bigwidth, self.bigheight))
2225 self.window.wm_minsize(self.minwidth, self.bigminheight)
2226 self.expanded = 1
2227
2228 def hide(self, event=None):
2229 self.stop()
2230 self.collapse()
2231
Georg Brandl6634bf22008-05-20 07:13:37 +00002232 import Tkinter
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002233 try:
Georg Brandl6634bf22008-05-20 07:13:37 +00002234 root = Tkinter.Tk()
Martin v. Löwise09bd932004-08-22 16:13:26 +00002235 # Tk will crash if pythonw.exe has an XP .manifest
2236 # file and the root has is not destroyed explicitly.
2237 # If the problem is ever fixed in Tk, the explicit
2238 # destroy can go.
2239 try:
2240 gui = GUI(root)
2241 root.mainloop()
2242 finally:
2243 root.destroy()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002244 except KeyboardInterrupt:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002245 pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002246
2247# -------------------------------------------------- command-line interface
2248
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002249def ispath(x):
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002250 return isinstance(x, str) and find(x, os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002251
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002252def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002253 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002254 import getopt
2255 class BadUsage: pass
2256
Nick Coghlan11db64e2009-11-15 22:36:47 +00002257 # Scripts don't get the current directory in their path by default
2258 # unless they are run with the '-m' switch
2259 if '' not in sys.path:
2260 scriptdir = os.path.dirname(sys.argv[0])
2261 if scriptdir in sys.path:
2262 sys.path.remove(scriptdir)
2263 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002264
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002265 try:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002266 opts, args = getopt.getopt(sys.argv[1:], 'gk:p:w')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002267 writing = 0
2268
2269 for opt, val in opts:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002270 if opt == '-g':
2271 gui()
2272 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002273 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002274 apropos(val)
2275 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002276 if opt == '-p':
2277 try:
2278 port = int(val)
2279 except ValueError:
2280 raise BadUsage
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002281 def ready(server):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002282 print 'pydoc server ready at %s' % server.url
2283 def stopped():
2284 print 'pydoc server stopped'
2285 serve(port, ready, stopped)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002286 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002287 if opt == '-w':
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002288 writing = 1
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002289
2290 if not args: raise BadUsage
2291 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002292 if ispath(arg) and not os.path.exists(arg):
2293 print 'file %r does not exist' % arg
2294 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002295 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002296 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002297 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002298 if writing:
2299 if ispath(arg) and os.path.isdir(arg):
2300 writedocs(arg)
2301 else:
2302 writedoc(arg)
2303 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002304 help.help(arg)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002305 except ErrorDuringImport, value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002306 print value
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002307
2308 except (getopt.error, BadUsage):
Martin v. Löwisf9b08b82003-10-31 13:05:21 +00002309 cmd = os.path.basename(sys.argv[0])
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002310 print """pydoc - the Python documentation tool
2311
2312%s <name> ...
2313 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002314 Python keyword, topic, function, module, or package, or a dotted
2315 reference to a class or function within a module or module in a
2316 package. If <name> contains a '%s', it is used as the path to a
2317 Python source file to document. If name is 'keywords', 'topics',
2318 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002319
2320%s -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002321 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002322
2323%s -p <port>
2324 Start an HTTP server on the given port on the local machine.
2325
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002326%s -g
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002327 Pop up a graphical interface for finding and serving documentation.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002328
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002329%s -w <name> ...
2330 Write out the HTML documentation for a module to a file in the current
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002331 directory. If <name> contains a '%s', it is treated as a filename; if
2332 it names a directory, documentation is written for all the contents.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002333""" % (cmd, os.sep, cmd, cmd, cmd, cmd, os.sep)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002334
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002335if __name__ == '__main__': cli()