blob: 68ba21f30fc51e95abfe327b0a4ac4fbab2b0a02 [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
Senthil Kumaran4af1c6a2011-07-28 22:30:27 +080040__version__ = "$Revision: 88564 $"
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
Ned Deily0096fb52011-10-06 14:17:44 -070055import sys, imp, os, re, types, inspect, __builtin__, pkgutil, warnings
Brett Cannon2ee0e8e2008-05-23 05:03:59 +000056from repr import Repr
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000057from string import expandtabs, find, join, lower, split, strip, rfind, rstrip
R. David Murrayef087da2009-06-23 18:02:46 +000058from traceback import extract_tb
Phillip J. Ebyceb30872006-04-18 00:59:55 +000059try:
60 from collections import deque
61except ImportError:
62 # Python 2.3 compatibility
63 class deque(list):
64 def popleft(self):
65 return self.pop(0)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000066
67# --------------------------------------------------------- common routines
68
Ka-Ping Yeedd175342001-02-27 14:43:46 +000069def pathdirs():
70 """Convert sys.path into a list of absolute, existing, unique paths."""
71 dirs = []
Ka-Ping Yee1d384632001-03-01 00:24:32 +000072 normdirs = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +000073 for dir in sys.path:
74 dir = os.path.abspath(dir or '.')
Ka-Ping Yee1d384632001-03-01 00:24:32 +000075 normdir = os.path.normcase(dir)
76 if normdir not in normdirs and os.path.isdir(dir):
Ka-Ping Yeedd175342001-02-27 14:43:46 +000077 dirs.append(dir)
Ka-Ping Yee1d384632001-03-01 00:24:32 +000078 normdirs.append(normdir)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000079 return dirs
80
81def getdoc(object):
82 """Get the doc string or comments for an object."""
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000083 result = inspect.getdoc(object) or inspect.getcomments(object)
Ka-Ping Yee239432a2001-03-02 02:45:08 +000084 return result and re.sub('^ *\n', '', rstrip(result)) or ''
Ka-Ping Yeedd175342001-02-27 14:43:46 +000085
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000086def splitdoc(doc):
87 """Split a doc string into a synopsis line (if any) and the rest."""
88 lines = split(strip(doc), '\n')
89 if len(lines) == 1:
90 return lines[0], ''
91 elif len(lines) >= 2 and not rstrip(lines[1]):
92 return lines[0], join(lines[2:], '\n')
93 return '', join(lines, '\n')
94
Ka-Ping Yeedd175342001-02-27 14:43:46 +000095def classname(object, modname):
96 """Get a class name and qualify it with a module name if necessary."""
97 name = object.__name__
98 if object.__module__ != modname:
99 name = object.__module__ + '.' + name
100 return name
101
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000102def isdata(object):
Georg Brandl94432422005-07-22 21:52:25 +0000103 """Check if an object is of a type that probably means it's data."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000104 return not (inspect.ismodule(object) or inspect.isclass(object) or
105 inspect.isroutine(object) or inspect.isframe(object) or
106 inspect.istraceback(object) or inspect.iscode(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000107
108def replace(text, *pairs):
109 """Do a series of global replacements on a string."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000110 while pairs:
111 text = join(split(text, pairs[0]), pairs[1])
112 pairs = pairs[2:]
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000113 return text
114
115def cram(text, maxlen):
116 """Omit part of a string if needed to make it fit in a maximum length."""
117 if len(text) > maxlen:
Raymond Hettingerfca3bb62002-10-21 04:44:11 +0000118 pre = max(0, (maxlen-3)//2)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000119 post = max(0, maxlen-3-pre)
120 return text[:pre] + '...' + text[len(text)-post:]
121 return text
122
Brett Cannon84601f12004-06-19 01:22:48 +0000123_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000124def stripid(text):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000125 """Remove the hexadecimal id from a Python object representation."""
Brett Cannonc6c1f472004-06-19 01:02:51 +0000126 # The behaviour of %p is implementation-dependent in terms of case.
Ezio Melottie511fc72010-02-16 23:26:09 +0000127 return _re_stripid.sub(r'\1', text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000128
Brett Cannonc6c1f472004-06-19 01:02:51 +0000129def _is_some_method(obj):
130 return inspect.ismethod(obj) or inspect.ismethoddescriptor(obj)
Tim Peters536d2262001-09-20 05:13:38 +0000131
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000132def allmethods(cl):
133 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000134 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000135 methods[key] = 1
136 for base in cl.__bases__:
137 methods.update(allmethods(base)) # all your base are belong to us
138 for key in methods.keys():
139 methods[key] = getattr(cl, key)
140 return methods
141
Tim Petersfa26f7c2001-09-24 08:05:11 +0000142def _split_list(s, predicate):
143 """Split sequence s via predicate, and return pair ([true], [false]).
144
145 The return value is a 2-tuple of lists,
146 ([x for x in s if predicate(x)],
147 [x for x in s if not predicate(x)])
148 """
149
Tim Peters28355492001-09-23 21:29:55 +0000150 yes = []
151 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000152 for x in s:
153 if predicate(x):
154 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000155 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000156 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000157 return yes, no
158
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700159def visiblename(name, all=None, obj=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000160 """Decide whether to show documentation on a variable."""
161 # Certain special names are redundant.
Nick Coghlanc060b0e2008-07-02 13:09:19 +0000162 _hidden_names = ('__builtins__', '__doc__', '__file__', '__path__',
163 '__module__', '__name__', '__slots__', '__package__')
164 if name in _hidden_names: return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000165 # Private names are hidden, but special names are displayed.
166 if name.startswith('__') and name.endswith('__'): return 1
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700167 # Namedtuples have public fields and methods with a single leading underscore
168 if name.startswith('_') and hasattr(obj, '_fields'):
169 return 1
Skip Montanaroa5616d22004-06-11 04:46:12 +0000170 if all is not None:
171 # only document that which the programmer exported in __all__
172 return name in all
173 else:
174 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000175
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000176def classify_class_attrs(object):
177 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Brett Cannonaca98b02008-08-03 00:58:51 +0000178 def fixup(data):
179 name, kind, cls, value = data
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000180 if inspect.isdatadescriptor(value):
181 kind = 'data descriptor'
182 return name, kind, cls, value
183 return map(fixup, inspect.classify_class_attrs(object))
184
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000185# ----------------------------------------------------- module manipulation
186
187def ispackage(path):
188 """Guess whether a path refers to a package directory."""
189 if os.path.isdir(path):
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000190 for ext in ('.py', '.pyc', '.pyo'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000191 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000192 return True
193 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000194
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000195def source_synopsis(file):
196 line = file.readline()
197 while line[:1] == '#' or not strip(line):
198 line = file.readline()
199 if not line: break
200 line = strip(line)
201 if line[:4] == 'r"""': line = line[1:]
202 if line[:3] == '"""':
203 line = line[3:]
204 if line[-1:] == '\\': line = line[:-1]
205 while not strip(line):
206 line = file.readline()
207 if not line: break
208 result = strip(split(line, '"""')[0])
209 else: result = None
210 return result
211
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000212def synopsis(filename, cache={}):
213 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000214 mtime = os.stat(filename).st_mtime
Charles-François Natali0cf7e252011-07-27 19:36:40 +0200215 lastupdate, result = cache.get(filename, (None, None))
216 if lastupdate is None or lastupdate < mtime:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000217 info = inspect.getmoduleinfo(filename)
Georg Brandl26fd2e12006-03-08 09:34:53 +0000218 try:
219 file = open(filename)
220 except IOError:
221 # module can't be opened, so skip it
222 return None
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000223 if info and 'b' in info[2]: # binary modules have to be imported
224 try: module = imp.load_module('__temp__', file, filename, info[1:])
225 except: return None
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000226 result = (module.__doc__ or '').splitlines()[0]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000227 del sys.modules['__temp__']
228 else: # text modules can be directly examined
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000229 result = source_synopsis(file)
230 file.close()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000231 cache[filename] = (mtime, result)
232 return result
233
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000234class ErrorDuringImport(Exception):
235 """Errors that occurred while trying to import something to document it."""
Brett Cannonaca98b02008-08-03 00:58:51 +0000236 def __init__(self, filename, exc_info):
237 exc, value, tb = exc_info
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000238 self.filename = filename
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000239 self.exc = exc
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000240 self.value = value
241 self.tb = tb
242
243 def __str__(self):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000244 exc = self.exc
245 if type(exc) is types.ClassType:
246 exc = exc.__name__
247 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000248
249def importfile(path):
250 """Import a Python source file or compiled file given its path."""
251 magic = imp.get_magic()
252 file = open(path, 'r')
253 if file.read(len(magic)) == magic:
254 kind = imp.PY_COMPILED
255 else:
256 kind = imp.PY_SOURCE
257 file.close()
258 filename = os.path.basename(path)
259 name, ext = os.path.splitext(filename)
260 file = open(path, 'r')
261 try:
262 module = imp.load_module(name, file, path, (ext, 'r', kind))
263 except:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000264 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000265 file.close()
266 return module
267
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000268def safeimport(path, forceload=0, cache={}):
269 """Import a module; handle errors; return None if the module isn't found.
270
271 If the module *is* found but an exception occurs, it's wrapped in an
272 ErrorDuringImport exception and reraised. Unlike __import__, if a
273 package path is specified, the module at the end of the path is returned,
274 not the package at the beginning. If the optional 'forceload' argument
275 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000276 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000277 # If forceload is 1 and the module has been previously loaded from
278 # disk, we always have to reload the module. Checking the file's
279 # mtime isn't good enough (e.g. the module could contain a class
280 # that inherits from another module that has changed).
281 if forceload and path in sys.modules:
282 if path not in sys.builtin_module_names:
283 # Avoid simply calling reload() because it leaves names in
284 # the currently loaded module lying around if they're not
285 # defined in the new source file. Instead, remove the
286 # module from sys.modules and re-import. Also remove any
287 # submodules because they won't appear in the newly loaded
288 # module's namespace if they're already in sys.modules.
289 subs = [m for m in sys.modules if m.startswith(path + '.')]
290 for key in [path] + subs:
291 # Prevent garbage collection.
292 cache[key] = sys.modules[key]
293 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000294 module = __import__(path)
295 except:
296 # Did the error occur before or after the module was found?
297 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000298 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000299 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000300 raise ErrorDuringImport(sys.modules[path].__file__, info)
301 elif exc is SyntaxError:
302 # A SyntaxError occurred before we could execute the module.
303 raise ErrorDuringImport(value.filename, info)
R. David Murrayef087da2009-06-23 18:02:46 +0000304 elif exc is ImportError and extract_tb(tb)[-1][2]=='safeimport':
305 # The import error occurred directly in this function,
306 # which means there is no such module in the path.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000307 return None
308 else:
309 # Some other error occurred during the importing process.
310 raise ErrorDuringImport(path, sys.exc_info())
311 for part in split(path, '.')[1:]:
312 try: module = getattr(module, part)
313 except AttributeError: return None
314 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000315
316# ---------------------------------------------------- formatter base class
317
318class Doc:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000319 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000320 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000321 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000322 # 'try' clause is to attempt to handle the possibility that inspect
323 # identifies something in a way that pydoc itself has issues handling;
324 # think 'super' and how it is a descriptor (which raises the exception
325 # by lacking a __name__ attribute) and an instance.
Barry Warsaw00decd72006-07-27 23:43:15 +0000326 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
327 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000328 try:
329 if inspect.ismodule(object): return self.docmodule(*args)
330 if inspect.isclass(object): return self.docclass(*args)
331 if inspect.isroutine(object): return self.docroutine(*args)
332 except AttributeError:
333 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000334 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000335 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000336
337 def fail(self, object, name=None, *args):
338 """Raise an exception for unimplemented types."""
339 message = "don't know how to document object%s of type %s" % (
340 name and ' ' + repr(name), type(object).__name__)
341 raise TypeError, message
342
Barry Warsaw00decd72006-07-27 23:43:15 +0000343 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000344
Skip Montanaro4997a692003-09-10 16:47:51 +0000345 def getdocloc(self, object):
346 """Return the location of module docs or None"""
347
348 try:
349 file = inspect.getabsfile(object)
350 except TypeError:
351 file = '(built-in)'
352
353 docloc = os.environ.get("PYTHONDOCS",
Georg Brandl0751d1a2008-01-21 17:13:03 +0000354 "http://docs.python.org/library")
Skip Montanaro4997a692003-09-10 16:47:51 +0000355 basedir = os.path.join(sys.exec_prefix, "lib",
356 "python"+sys.version[0:3])
357 if (isinstance(object, type(os)) and
358 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
359 'marshal', 'posix', 'signal', 'sys',
360 'thread', 'zipimport') or
361 (file.startswith(basedir) and
Brian Curtinaeb2e822010-03-31 03:10:21 +0000362 not file.startswith(os.path.join(basedir, 'site-packages')))) and
Brian Curtina01da932010-04-01 04:02:00 +0000363 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
Skip Montanaro4997a692003-09-10 16:47:51 +0000364 if docloc.startswith("http://"):
Georg Brandl0751d1a2008-01-21 17:13:03 +0000365 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
Skip Montanaro4997a692003-09-10 16:47:51 +0000366 else:
Georg Brandl0751d1a2008-01-21 17:13:03 +0000367 docloc = os.path.join(docloc, object.__name__ + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000368 else:
369 docloc = None
370 return docloc
371
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000372# -------------------------------------------- HTML documentation generator
373
374class HTMLRepr(Repr):
375 """Class for safely making an HTML representation of a Python object."""
376 def __init__(self):
377 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000378 self.maxlist = self.maxtuple = 20
379 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000380 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000381
382 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000383 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000384
385 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000386 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000387
388 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000389 if hasattr(type(x), '__name__'):
390 methodname = 'repr_' + join(split(type(x).__name__), '_')
391 if hasattr(self, methodname):
392 return getattr(self, methodname)(x, level)
393 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000394
395 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000396 test = cram(x, self.maxstring)
397 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000398 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000399 # Backslashes are only literal in the string and are never
400 # needed to make any special characters, so show a raw string.
401 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000402 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000403 r'<font color="#c040c0">\1</font>',
404 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000405
Skip Montanarodf708782002-03-07 22:58:02 +0000406 repr_str = repr_string
407
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000408 def repr_instance(self, x, level):
409 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000410 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000411 except:
412 return self.escape('<%s instance>' % x.__class__.__name__)
413
414 repr_unicode = repr_string
415
416class HTMLDoc(Doc):
417 """Formatter class for HTML documentation."""
418
419 # ------------------------------------------- HTML formatting utilities
420
421 _repr_instance = HTMLRepr()
422 repr = _repr_instance.repr
423 escape = _repr_instance.escape
424
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000425 def page(self, title, contents):
426 """Format an HTML page."""
427 return '''
Georg Brandle0197062009-04-10 08:20:23 +0000428<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000429<html><head><title>Python: %s</title>
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000430</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000431%s
432</body></html>''' % (title, contents)
433
434 def heading(self, title, fgcol, bgcol, extras=''):
435 """Format a page heading."""
436 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000437<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000438<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000439<td valign=bottom>&nbsp;<br>
440<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000441><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000442><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000443 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
444
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000445 def section(self, title, fgcol, bgcol, contents, width=6,
446 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000447 """Format a section with a heading."""
448 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000449 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000450 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000451<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000452<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000453<td colspan=3 valign=bottom>&nbsp;<br>
454<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000455 ''' % (bgcol, fgcol, title)
456 if prelude:
457 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000458<tr bgcolor="%s"><td rowspan=2>%s</td>
459<td colspan=2>%s</td></tr>
460<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
461 else:
462 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000463<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000464
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000465 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000466
467 def bigsection(self, title, *args):
468 """Format a section with a big heading."""
469 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000470 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000471
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000472 def preformat(self, text):
473 """Format literal preformatted text."""
474 text = self.escape(expandtabs(text))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000475 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
476 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000477
478 def multicolumn(self, list, format, cols=4):
479 """Format a list of items into a multi-column list."""
480 result = ''
Victor Stinnerdbfba162011-05-26 13:37:25 +0200481 rows = (len(list)+cols-1)//cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000482 for col in range(cols):
Victor Stinnerdbfba162011-05-26 13:37:25 +0200483 result = result + '<td width="%d%%" valign=top>' % (100//cols)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000484 for i in range(rows*col, rows*col+rows):
485 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000486 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000487 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000488 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000489
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000490 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000491
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000492 def namelink(self, name, *dicts):
493 """Make a link for an identifier, given name-to-URL mappings."""
494 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000495 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000496 return '<a href="%s">%s</a>' % (dict[name], name)
497 return name
498
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000499 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000500 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000501 name, module = object.__name__, sys.modules.get(object.__module__)
502 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000503 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000504 module.__name__, name, classname(object, modname))
505 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000506
507 def modulelink(self, object):
508 """Make a link for a module."""
509 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
510
Brett Cannonaca98b02008-08-03 00:58:51 +0000511 def modpkglink(self, data):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000512 """Make a link for a module or package to display in an index."""
Brett Cannonaca98b02008-08-03 00:58:51 +0000513 name, path, ispackage, shadowed = data
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000514 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000515 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000516 if path:
517 url = '%s.%s.html' % (path, name)
518 else:
519 url = '%s.html' % name
520 if ispackage:
521 text = '<strong>%s</strong>&nbsp;(package)' % name
522 else:
523 text = name
524 return '<a href="%s">%s</a>' % (url, text)
525
526 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
527 """Mark up some plain text, given a context of symbols to look for.
528 Each context dictionary maps object names to anchor names."""
529 escape = escape or self.escape
530 results = []
531 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000532 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
533 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000534 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000535 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000536 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000537 match = pattern.search(text, here)
538 if not match: break
539 start, end = match.span()
540 results.append(escape(text[here:start]))
541
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000542 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000543 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000544 url = escape(all).replace('"', '&quot;')
545 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000546 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000547 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
548 results.append('<a href="%s">%s</a>' % (url, escape(all)))
549 elif pep:
Andrew M. Kuchling727a5902008-02-05 16:06:57 +0000550 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000551 results.append('<a href="%s">%s</a>' % (url, escape(all)))
552 elif text[end:end+1] == '(':
553 results.append(self.namelink(name, methods, funcs, classes))
554 elif selfdot:
555 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000556 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000557 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000558 here = end
559 results.append(escape(text[here:]))
560 return join(results, '')
561
562 # ---------------------------------------------- type-specific routines
563
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000564 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000565 """Produce HTML for a class tree as given by inspect.getclasstree()."""
566 result = ''
567 for entry in tree:
568 if type(entry) is type(()):
569 c, bases = entry
Tim Peters2306d242001-09-25 03:18:32 +0000570 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000571 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000572 if bases and bases != (parent,):
573 parents = []
574 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000575 parents.append(self.classlink(base, modname))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000576 result = result + '(' + join(parents, ', ') + ')'
Tim Peters2306d242001-09-25 03:18:32 +0000577 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000578 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000579 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000580 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000581 return '<dl>\n%s</dl>\n' % result
582
Tim Peters8dd7ade2001-10-18 19:56:17 +0000583 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000584 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000585 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000586 try:
587 all = object.__all__
588 except AttributeError:
589 all = None
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000590 parts = split(name, '.')
591 links = []
592 for i in range(len(parts)-1):
593 links.append(
594 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
595 (join(parts[:i+1], '.'), parts[i]))
596 linkedname = join(links + parts[-1:], '.')
597 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000598 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000599 path = inspect.getabsfile(object)
Ka-Ping Yee6191a232001-04-13 15:00:27 +0000600 url = path
601 if sys.platform == 'win32':
602 import nturl2path
603 url = nturl2path.pathname2url(path)
604 filelink = '<a href="file:%s">%s</a>' % (url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000605 except TypeError:
606 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000607 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000608 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000609 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000610 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
611 version = strip(version[11:-1])
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000612 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000613 if hasattr(object, '__date__'):
614 info.append(self.escape(str(object.__date__)))
615 if info:
616 head = head + ' (%s)' % join(info, ', ')
Skip Montanaro4997a692003-09-10 16:47:51 +0000617 docloc = self.getdocloc(object)
618 if docloc is not None:
619 docloc = '<br><a href="%(docloc)s">Module Docs</a>' % locals()
620 else:
621 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000622 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000623 head, '#ffffff', '#7799ee',
624 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000625
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000626 modules = inspect.getmembers(object, inspect.ismodule)
627
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000628 classes, cdict = [], {}
629 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000630 # if __all__ exists, believe it. Otherwise use old heuristic.
631 if (all is not None or
632 (inspect.getmodule(value) or object) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700633 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000634 classes.append((key, value))
635 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000636 for key, value in classes:
637 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000638 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000639 module = sys.modules.get(modname)
640 if modname != name and module and hasattr(module, key):
641 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000642 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000643 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000644 funcs, fdict = [], {}
645 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000646 # if __all__ exists, believe it. Otherwise use old heuristic.
647 if (all is not None or
648 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700649 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000650 funcs.append((key, value))
651 fdict[key] = '#-' + key
652 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000653 data = []
654 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700655 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000656 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000657
658 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
659 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000660 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000661
662 if hasattr(object, '__path__'):
663 modpkgs = []
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000664 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
665 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000666 modpkgs.sort()
667 contents = self.multicolumn(modpkgs, self.modpkglink)
668 result = result + self.bigsection(
669 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000670 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000671 contents = self.multicolumn(
Brett Cannonaca98b02008-08-03 00:58:51 +0000672 modules, lambda key_value, s=self: s.modulelink(key_value[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000673 result = result + self.bigsection(
Georg Brandlb169eaa2008-02-17 21:18:55 +0000674 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000675
676 if classes:
Brett Cannonaca98b02008-08-03 00:58:51 +0000677 classlist = map(lambda key_value: key_value[1], classes)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000678 contents = [
679 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000680 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000681 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000682 result = result + self.bigsection(
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000683 'Classes', '#ffffff', '#ee77aa', join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000684 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000685 contents = []
686 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000687 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000688 result = result + self.bigsection(
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000689 'Functions', '#ffffff', '#eeaa77', join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000690 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000691 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000692 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000693 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000694 result = result + self.bigsection(
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000695 'Data', '#ffffff', '#55aa55', join(contents, '<br>\n'))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000696 if hasattr(object, '__author__'):
697 contents = self.markup(str(object.__author__), self.preformat)
698 result = result + self.bigsection(
699 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000700 if hasattr(object, '__credits__'):
701 contents = self.markup(str(object.__credits__), self.preformat)
702 result = result + self.bigsection(
703 'Credits', '#ffffff', '#7799ee', contents)
704
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000705 return result
706
Tim Peters8dd7ade2001-10-18 19:56:17 +0000707 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
708 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000709 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000710 realname = object.__name__
711 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000712 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000713
Tim Petersb47879b2001-09-24 04:47:19 +0000714 contents = []
715 push = contents.append
716
Tim Petersfa26f7c2001-09-24 08:05:11 +0000717 # Cute little class to pump out a horizontal rule between sections.
718 class HorizontalRule:
719 def __init__(self):
720 self.needone = 0
721 def maybe(self):
722 if self.needone:
723 push('<hr>\n')
724 self.needone = 1
725 hr = HorizontalRule()
726
Tim Petersc86f6ca2001-09-26 21:31:51 +0000727 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000728 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000729 if len(mro) > 2:
730 hr.maybe()
731 push('<dl><dt>Method resolution order:</dt>\n')
732 for base in mro:
733 push('<dd>%s</dd>\n' % self.classlink(base,
734 object.__module__))
735 push('</dl>\n')
736
Tim Petersb47879b2001-09-24 04:47:19 +0000737 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000738 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000739 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000740 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000741 push(msg)
742 for name, kind, homecls, value in ok:
Antoine Pitroub8572a12011-12-21 10:16:14 +0100743 try:
744 value = getattr(object, name)
745 except Exception:
746 # Some descriptors may meet a failure in their __get__.
747 # (bug #1785)
748 push(self._docdescriptor(name, value, mod))
749 else:
750 push(self.document(value, name, mod,
751 funcs, classes, mdict, object))
Tim Petersb47879b2001-09-24 04:47:19 +0000752 push('\n')
753 return attrs
754
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000755 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000756 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:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000761 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000762 return attrs
763
Tim Petersfa26f7c2001-09-24 08:05:11 +0000764 def spilldata(msg, attrs, predicate):
765 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000766 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000767 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000768 push(msg)
769 for name, kind, homecls, value in ok:
770 base = self.docother(getattr(object, name), name, mod)
Brett Cannonaca98b02008-08-03 00:58:51 +0000771 if (hasattr(value, '__call__') or
772 inspect.isdatadescriptor(value)):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000773 doc = getattr(value, "__doc__", None)
774 else:
775 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000776 if doc is None:
777 push('<dl><dt>%s</dl>\n' % base)
778 else:
779 doc = self.markup(getdoc(value), self.preformat,
780 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000781 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000782 push('<dl><dt>%s%s</dl>\n' % (base, doc))
783 push('\n')
784 return attrs
785
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700786 attrs = filter(lambda data: visiblename(data[0], obj=object),
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000787 classify_class_attrs(object))
Tim Petersb47879b2001-09-24 04:47:19 +0000788 mdict = {}
789 for key, kind, homecls, value in attrs:
790 mdict[key] = anchor = '#' + name + '-' + key
Antoine Pitroub8572a12011-12-21 10:16:14 +0100791 try:
792 value = getattr(object, name)
793 except Exception:
794 # Some descriptors may meet a failure in their __get__.
795 # (bug #1785)
796 pass
Tim Petersb47879b2001-09-24 04:47:19 +0000797 try:
798 # The value may not be hashable (e.g., a data attr with
799 # a dict or list value).
800 mdict[value] = anchor
801 except TypeError:
802 pass
803
Tim Petersfa26f7c2001-09-24 08:05:11 +0000804 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000805 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000806 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000807 else:
808 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000809 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
810
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000811 if thisclass is __builtin__.object:
812 attrs = inherited
813 continue
814 elif thisclass is object:
815 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000816 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000817 tag = 'inherited from %s' % self.classlink(thisclass,
818 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000819 tag += ':<br>\n'
820
821 # Sort attrs by name.
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000822 try:
823 attrs.sort(key=lambda t: t[0])
824 except TypeError:
825 attrs.sort(lambda t1, t2: cmp(t1[0], t2[0])) # 2.3 compat
Tim Petersb47879b2001-09-24 04:47:19 +0000826
827 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000828 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000829 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000830 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000831 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000832 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000833 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000834 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
835 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000836 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000837 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000838 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000839 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000840
841 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000842
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000843 if name == realname:
844 title = '<a name="%s">class <strong>%s</strong></a>' % (
845 name, realname)
846 else:
847 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
848 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000849 if bases:
850 parents = []
851 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000852 parents.append(self.classlink(base, object.__module__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000853 title = title + '(%s)' % join(parents, ', ')
Tim Peters2306d242001-09-25 03:18:32 +0000854 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000855 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000856
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000857 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000858
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000859 def formatvalue(self, object):
860 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000861 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000862
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000863 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000864 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000865 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000866 realname = object.__name__
867 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000868 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000869 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000870 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000871 if inspect.ismethod(object):
Ka-Ping Yee6dcfa382001-04-12 20:27:31 +0000872 imclass = object.im_class
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000873 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000874 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000875 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000876 else:
Georg Brandl7e2b6bb2007-03-13 22:16:30 +0000877 if object.im_self is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000878 note = ' method of %s instance' % self.classlink(
879 object.im_self.__class__, mod)
880 else:
881 note = ' unbound %s method' % self.classlink(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000882 object = object.im_func
883
884 if name == realname:
885 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
886 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000887 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000888 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000889 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000890 cl.__name__ + '-' + realname, realname)
891 skipdocs = 1
892 else:
893 reallink = realname
894 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
895 anchor, name, reallink)
Tim Peters4bcfa312001-09-20 06:08:24 +0000896 if inspect.isfunction(object):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000897 args, varargs, varkw, defaults = inspect.getargspec(object)
898 argspec = inspect.formatargspec(
899 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000900 if realname == '<lambda>':
Tim Peters59ed4482001-10-31 04:20:26 +0000901 title = '<strong>%s</strong> <em>lambda</em> ' % name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000902 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +0000903 else:
904 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000905
Tim Peters2306d242001-09-25 03:18:32 +0000906 decl = title + argspec + (note and self.grey(
907 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000908
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000909 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000910 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000911 else:
912 doc = self.markup(
913 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000914 doc = doc and '<dd><tt>%s</tt></dd>' % doc
915 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000916
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000917 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000918 results = []
919 push = results.append
920
921 if name:
922 push('<dl><dt><strong>%s</strong></dt>\n' % name)
923 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000924 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000925 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000926 push('</dl>\n')
927
928 return ''.join(results)
929
930 def docproperty(self, object, name=None, mod=None, cl=None):
931 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000932 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000933
Tim Peters8dd7ade2001-10-18 19:56:17 +0000934 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000935 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000936 lhs = name and '<strong>%s</strong> = ' % name or ''
937 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000938
Barry Warsaw00decd72006-07-27 23:43:15 +0000939 def docdata(self, object, name=None, mod=None, cl=None):
940 """Produce html documentation for a data descriptor."""
941 return self._docdescriptor(name, object, mod)
942
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000943 def index(self, dir, shadowed=None):
944 """Generate an HTML index for a directory of modules."""
945 modpkgs = []
946 if shadowed is None: shadowed = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000947 for importer, name, ispkg in pkgutil.iter_modules([dir]):
948 modpkgs.append((name, '', ispkg, name in shadowed))
949 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000950
951 modpkgs.sort()
952 contents = self.multicolumn(modpkgs, self.modpkglink)
953 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
954
955# -------------------------------------------- text documentation generator
956
957class TextRepr(Repr):
958 """Class for safely making a text representation of a Python object."""
959 def __init__(self):
960 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000961 self.maxlist = self.maxtuple = 20
962 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000963 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000964
965 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000966 if hasattr(type(x), '__name__'):
967 methodname = 'repr_' + join(split(type(x).__name__), '_')
968 if hasattr(self, methodname):
969 return getattr(self, methodname)(x, level)
970 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000971
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000972 def repr_string(self, x, level):
973 test = cram(x, self.maxstring)
974 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000975 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000976 # Backslashes are only literal in the string and are never
977 # needed to make any special characters, so show a raw string.
978 return 'r' + testrepr[0] + test + testrepr[0]
979 return testrepr
980
Skip Montanarodf708782002-03-07 22:58:02 +0000981 repr_str = repr_string
982
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000983 def repr_instance(self, x, level):
984 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000985 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000986 except:
987 return '<%s instance>' % x.__class__.__name__
988
989class TextDoc(Doc):
990 """Formatter class for text documentation."""
991
992 # ------------------------------------------- text formatting utilities
993
994 _repr_instance = TextRepr()
995 repr = _repr_instance.repr
996
997 def bold(self, text):
998 """Format a string in bold by overstriking."""
999 return join(map(lambda ch: ch + '\b' + ch, text), '')
1000
1001 def indent(self, text, prefix=' '):
1002 """Indent text by prepending a given prefix to each line."""
1003 if not text: return ''
1004 lines = split(text, '\n')
1005 lines = map(lambda line, prefix=prefix: prefix + line, lines)
1006 if lines: lines[-1] = rstrip(lines[-1])
1007 return join(lines, '\n')
1008
1009 def section(self, title, contents):
1010 """Format a section with a given heading."""
1011 return self.bold(title) + '\n' + rstrip(self.indent(contents)) + '\n\n'
1012
1013 # ---------------------------------------------- type-specific routines
1014
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001015 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001016 """Render in text a class tree as returned by inspect.getclasstree()."""
1017 result = ''
1018 for entry in tree:
1019 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001020 c, bases = entry
1021 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001022 if bases and bases != (parent,):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001023 parents = map(lambda c, m=modname: classname(c, m), bases)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001024 result = result + '(%s)' % join(parents, ', ')
1025 result = result + '\n'
1026 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001027 result = result + self.formattree(
1028 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001029 return result
1030
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001031 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001032 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001033 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001034 synop, desc = splitdoc(getdoc(object))
1035 result = self.section('NAME', name + (synop and ' - ' + synop))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001036
1037 try:
Skip Montanaroa5616d22004-06-11 04:46:12 +00001038 all = object.__all__
1039 except AttributeError:
1040 all = None
1041
1042 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001043 file = inspect.getabsfile(object)
1044 except TypeError:
1045 file = '(built-in)'
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001046 result = result + self.section('FILE', file)
Skip Montanaro4997a692003-09-10 16:47:51 +00001047
1048 docloc = self.getdocloc(object)
1049 if docloc is not None:
1050 result = result + self.section('MODULE DOCS', docloc)
1051
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001052 if desc:
1053 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001054
1055 classes = []
1056 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001057 # if __all__ exists, believe it. Otherwise use old heuristic.
1058 if (all is not None
1059 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001060 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001061 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001062 funcs = []
1063 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001064 # if __all__ exists, believe it. Otherwise use old heuristic.
1065 if (all is not None or
1066 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001067 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001068 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001069 data = []
1070 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001071 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001072 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001073
Georg Brandlf2dae0e2008-01-21 21:05:49 +00001074 modpkgs = []
1075 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001076 if hasattr(object, '__path__'):
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001077 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Georg Brandlf2dae0e2008-01-21 21:05:49 +00001078 modpkgs_names.add(modname)
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001079 if ispkg:
1080 modpkgs.append(modname + ' (package)')
1081 else:
1082 modpkgs.append(modname)
1083
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001084 modpkgs.sort()
1085 result = result + self.section(
1086 'PACKAGE CONTENTS', join(modpkgs, '\n'))
1087
Georg Brandlf2dae0e2008-01-21 21:05:49 +00001088 # Detect submodules as sometimes created by C extensions
1089 submodules = []
1090 for key, value in inspect.getmembers(object, inspect.ismodule):
1091 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1092 submodules.append(key)
1093 if submodules:
1094 submodules.sort()
1095 result = result + self.section(
1096 'SUBMODULES', join(submodules, '\n'))
1097
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001098 if classes:
Brett Cannonaca98b02008-08-03 00:58:51 +00001099 classlist = map(lambda key_value: key_value[1], classes)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001100 contents = [self.formattree(
1101 inspect.getclasstree(classlist, 1), name)]
1102 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001103 contents.append(self.document(value, key, name))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001104 result = result + self.section('CLASSES', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001105
1106 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001107 contents = []
1108 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001109 contents.append(self.document(value, key, name))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001110 result = result + self.section('FUNCTIONS', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001111
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001112 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001113 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001114 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001115 contents.append(self.docother(value, key, name, maxlen=70))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001116 result = result + self.section('DATA', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001117
1118 if hasattr(object, '__version__'):
1119 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001120 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
1121 version = strip(version[11:-1])
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001122 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001123 if hasattr(object, '__date__'):
1124 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001125 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001126 result = result + self.section('AUTHOR', str(object.__author__))
1127 if hasattr(object, '__credits__'):
1128 result = result + self.section('CREDITS', str(object.__credits__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001129 return result
1130
Georg Brandl52f83952011-02-25 10:39:23 +00001131 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001132 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001133 realname = object.__name__
1134 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001135 bases = object.__bases__
1136
Tim Petersc86f6ca2001-09-26 21:31:51 +00001137 def makename(c, m=object.__module__):
1138 return classname(c, m)
1139
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001140 if name == realname:
1141 title = 'class ' + self.bold(realname)
1142 else:
1143 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001144 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001145 parents = map(makename, bases)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001146 title = title + '(%s)' % join(parents, ', ')
1147
1148 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001149 contents = doc and [doc + '\n'] or []
1150 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001151
Tim Petersc86f6ca2001-09-26 21:31:51 +00001152 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001153 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001154 if len(mro) > 2:
1155 push("Method resolution order:")
1156 for base in mro:
1157 push(' ' + makename(base))
1158 push('')
1159
Tim Petersf4aad8e2001-09-24 22:40:47 +00001160 # Cute little class to pump out a horizontal rule between sections.
1161 class HorizontalRule:
1162 def __init__(self):
1163 self.needone = 0
1164 def maybe(self):
1165 if self.needone:
1166 push('-' * 70)
1167 self.needone = 1
1168 hr = HorizontalRule()
1169
Tim Peters28355492001-09-23 21:29:55 +00001170 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001171 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001172 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001173 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001174 push(msg)
1175 for name, kind, homecls, value in ok:
Antoine Pitroub8572a12011-12-21 10:16:14 +01001176 try:
1177 value = getattr(object, name)
1178 except Exception:
1179 # Some descriptors may meet a failure in their __get__.
1180 # (bug #1785)
1181 push(self._docdescriptor(name, value, mod))
1182 else:
1183 push(self.document(value,
1184 name, mod, object))
Tim Peters28355492001-09-23 21:29:55 +00001185 return attrs
1186
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001187 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001188 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001189 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001190 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001191 push(msg)
1192 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001193 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001194 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001195
Tim Petersfa26f7c2001-09-24 08:05:11 +00001196 def spilldata(msg, attrs, predicate):
1197 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001198 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001199 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001200 push(msg)
1201 for name, kind, homecls, value in ok:
Brett Cannonaca98b02008-08-03 00:58:51 +00001202 if (hasattr(value, '__call__') or
1203 inspect.isdatadescriptor(value)):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001204 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001205 else:
1206 doc = None
Tim Peters28355492001-09-23 21:29:55 +00001207 push(self.docother(getattr(object, name),
Georg Brandl8b813db2005-10-01 16:32:31 +00001208 name, mod, maxlen=70, doc=doc) + '\n')
Tim Peters28355492001-09-23 21:29:55 +00001209 return attrs
1210
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001211 attrs = filter(lambda data: visiblename(data[0], obj=object),
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001212 classify_class_attrs(object))
Tim Petersfa26f7c2001-09-24 08:05:11 +00001213 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001214 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001215 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001216 else:
1217 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001218 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1219
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001220 if thisclass is __builtin__.object:
1221 attrs = inherited
1222 continue
1223 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001224 tag = "defined here"
1225 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001226 tag = "inherited from %s" % classname(thisclass,
1227 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001228
1229 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001230 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001231
1232 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001233 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001234 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001235 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001236 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001237 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001238 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001239 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1240 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001241 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1242 lambda t: t[1] == 'data')
Tim Peters28355492001-09-23 21:29:55 +00001243 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001244 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001245
1246 contents = '\n'.join(contents)
1247 if not contents:
1248 return title + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001249 return title + '\n' + self.indent(rstrip(contents), ' | ') + '\n'
1250
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001251 def formatvalue(self, object):
1252 """Format an argument default value as text."""
1253 return '=' + self.repr(object)
1254
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001255 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001256 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001257 realname = object.__name__
1258 name = name or realname
1259 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001260 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001261 if inspect.ismethod(object):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001262 imclass = object.im_class
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001263 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001264 if imclass is not cl:
1265 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001266 else:
Georg Brandl7e2b6bb2007-03-13 22:16:30 +00001267 if object.im_self is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001268 note = ' method of %s instance' % classname(
1269 object.im_self.__class__, mod)
1270 else:
1271 note = ' unbound %s method' % classname(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001272 object = object.im_func
1273
1274 if name == realname:
1275 title = self.bold(realname)
1276 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001277 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001278 cl.__dict__[realname] is object):
1279 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001280 title = self.bold(name) + ' = ' + realname
Tim Peters4bcfa312001-09-20 06:08:24 +00001281 if inspect.isfunction(object):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001282 args, varargs, varkw, defaults = inspect.getargspec(object)
1283 argspec = inspect.formatargspec(
1284 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001285 if realname == '<lambda>':
Georg Brandl501dd0d2006-02-17 09:45:40 +00001286 title = self.bold(name) + ' lambda '
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001287 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +00001288 else:
1289 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001290 decl = title + argspec + note
1291
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001292 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001293 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001294 else:
1295 doc = getdoc(object) or ''
1296 return decl + '\n' + (doc and rstrip(self.indent(doc)) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001297
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001298 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001299 results = []
1300 push = results.append
1301
1302 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001303 push(self.bold(name))
1304 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001305 doc = getdoc(value) or ''
1306 if doc:
1307 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001308 push('\n')
1309 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001310
1311 def docproperty(self, object, name=None, mod=None, cl=None):
1312 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001313 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001314
Barry Warsaw00decd72006-07-27 23:43:15 +00001315 def docdata(self, object, name=None, mod=None, cl=None):
1316 """Produce text documentation for a data descriptor."""
1317 return self._docdescriptor(name, object, mod)
1318
Georg Brandl8b813db2005-10-01 16:32:31 +00001319 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001320 """Produce text documentation for a data object."""
1321 repr = self.repr(object)
1322 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001323 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001324 chop = maxlen - len(line)
1325 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001326 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001327 if doc is not None:
1328 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001329 return line
1330
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001331# --------------------------------------------------------- user interfaces
1332
1333def pager(text):
1334 """The first time this is called, determine what kind of pager to use."""
1335 global pager
1336 pager = getpager()
1337 pager(text)
1338
1339def getpager():
1340 """Decide what method to use for paging through text."""
1341 if type(sys.stdout) is not types.FileType:
1342 return plainpager
1343 if not sys.stdin.isatty() or not sys.stdout.isatty():
1344 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001345 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001346 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001347 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001348 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001349 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001350 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001351 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001352 if os.environ.get('TERM') in ('dumb', 'emacs'):
1353 return plainpager
Andrew MacIntyre54e0eab2002-03-03 03:12:30 +00001354 if sys.platform == 'win32' or sys.platform.startswith('os2'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001355 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001356 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001357 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001358
1359 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001360 (fd, filename) = tempfile.mkstemp()
1361 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001362 try:
Georg Brandlb32dea52008-07-16 21:19:28 +00001363 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001364 return lambda text: pipepager(text, 'more')
1365 else:
1366 return ttypager
1367 finally:
1368 os.unlink(filename)
1369
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001370def plain(text):
1371 """Remove boldface formatting from text."""
1372 return re.sub('.\b', '', text)
1373
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001374def pipepager(text, cmd):
1375 """Page through text by feeding it to another program."""
1376 pipe = os.popen(cmd, 'w')
1377 try:
1378 pipe.write(text)
1379 pipe.close()
1380 except IOError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001381 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001382
1383def tempfilepager(text, cmd):
1384 """Page through text by invoking a program on a temporary file."""
1385 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001386 filename = tempfile.mktemp()
1387 file = open(filename, 'w')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001388 file.write(text)
1389 file.close()
1390 try:
Georg Brandlb32dea52008-07-16 21:19:28 +00001391 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001392 finally:
1393 os.unlink(filename)
1394
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001395def ttypager(text):
1396 """Page through text on a text terminal."""
1397 lines = split(plain(text), '\n')
1398 try:
1399 import tty
1400 fd = sys.stdin.fileno()
1401 old = tty.tcgetattr(fd)
1402 tty.setcbreak(fd)
1403 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001404 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001405 tty = None
1406 getchar = lambda: sys.stdin.readline()[:-1][:1]
1407
1408 try:
1409 r = inc = os.environ.get('LINES', 25) - 1
1410 sys.stdout.write(join(lines[:inc], '\n') + '\n')
1411 while lines[r:]:
1412 sys.stdout.write('-- more --')
1413 sys.stdout.flush()
1414 c = getchar()
1415
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001416 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001417 sys.stdout.write('\r \r')
1418 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001419 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001420 sys.stdout.write('\r \r' + lines[r] + '\n')
1421 r = r + 1
1422 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001423 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001424 r = r - inc - inc
1425 if r < 0: r = 0
1426 sys.stdout.write('\n' + join(lines[r:r+inc], '\n') + '\n')
1427 r = r + inc
1428
1429 finally:
1430 if tty:
1431 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1432
1433def plainpager(text):
1434 """Simply print unformatted text. This is the ultimate fallback."""
1435 sys.stdout.write(plain(text))
1436
1437def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001438 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001439 if inspect.ismodule(thing):
1440 if thing.__name__ in sys.builtin_module_names:
1441 return 'built-in module ' + thing.__name__
1442 if hasattr(thing, '__path__'):
1443 return 'package ' + thing.__name__
1444 else:
1445 return 'module ' + thing.__name__
1446 if inspect.isbuiltin(thing):
1447 return 'built-in function ' + thing.__name__
Barry Warsaw00decd72006-07-27 23:43:15 +00001448 if inspect.isgetsetdescriptor(thing):
1449 return 'getset descriptor %s.%s.%s' % (
1450 thing.__objclass__.__module__, thing.__objclass__.__name__,
1451 thing.__name__)
1452 if inspect.ismemberdescriptor(thing):
1453 return 'member descriptor %s.%s.%s' % (
1454 thing.__objclass__.__module__, thing.__objclass__.__name__,
1455 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001456 if inspect.isclass(thing):
1457 return 'class ' + thing.__name__
1458 if inspect.isfunction(thing):
1459 return 'function ' + thing.__name__
1460 if inspect.ismethod(thing):
1461 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001462 if type(thing) is types.InstanceType:
1463 return 'instance of ' + thing.__class__.__name__
1464 return type(thing).__name__
1465
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001466def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001467 """Locate an object by name or dotted path, importing as necessary."""
Guido van Rossum97dede02003-02-16 01:12:32 +00001468 parts = [part for part in split(path, '.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001469 module, n = None, 0
1470 while n < len(parts):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001471 nextmodule = safeimport(join(parts[:n+1], '.'), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001472 if nextmodule: module, n = nextmodule, n + 1
1473 else: break
1474 if module:
1475 object = module
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001476 else:
Éric Araujo9a528302011-07-29 17:34:35 +02001477 object = __builtin__
1478 for part in parts[n:]:
1479 try:
1480 object = getattr(object, part)
1481 except AttributeError:
1482 return None
1483 return object
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001484
1485# --------------------------------------- interactive interpreter interface
1486
1487text = TextDoc()
1488html = HTMLDoc()
1489
Ka-Ping Yee8ef1cf32007-01-14 04:25:15 +00001490class _OldStyleClass: pass
1491_OLD_INSTANCE_TYPE = type(_OldStyleClass())
1492
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001493def resolve(thing, forceload=0):
1494 """Given an object or a path to an object, get the object and its name."""
1495 if isinstance(thing, str):
1496 object = locate(thing, forceload)
1497 if not object:
1498 raise ImportError, 'no Python documentation found for %r' % thing
1499 return object, thing
1500 else:
R David Murrayc313b1d2012-04-23 13:27:11 -04001501 name = getattr(thing, '__name__', None)
1502 return thing, name if isinstance(name, str) else None
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001503
Georg Brandl8441f152007-03-13 20:02:57 +00001504def render_doc(thing, title='Python Library Documentation: %s', forceload=0):
1505 """Render text documentation, given an object or a path to an object."""
1506 object, name = resolve(thing, forceload)
1507 desc = describe(object)
1508 module = inspect.getmodule(object)
1509 if name and '.' in name:
1510 desc += ' in ' + name[:name.rfind('.')]
1511 elif module and module is not object:
1512 desc += ' in module ' + module.__name__
1513 if type(object) is _OLD_INSTANCE_TYPE:
1514 # If the passed object is an instance of an old-style class,
1515 # document its available methods instead of its value.
1516 object = object.__class__
1517 elif not (inspect.ismodule(object) or
1518 inspect.isclass(object) or
1519 inspect.isroutine(object) or
1520 inspect.isgetsetdescriptor(object) or
1521 inspect.ismemberdescriptor(object) or
1522 isinstance(object, property)):
1523 # If the passed object is a piece of data or an instance,
1524 # document its available methods instead of its value.
1525 object = type(object)
1526 desc += ' object'
1527 return title % desc + '\n\n' + text.document(object, name)
1528
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001529def doc(thing, title='Python Library Documentation: %s', forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001530 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001531 try:
Georg Brandl8441f152007-03-13 20:02:57 +00001532 pager(render_doc(thing, title, forceload))
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001533 except (ImportError, ErrorDuringImport), value:
1534 print value
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001535
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001536def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001537 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001538 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001539 object, name = resolve(thing, forceload)
1540 page = html.page(describe(object), html.document(object, name))
1541 file = open(name + '.html', 'w')
1542 file.write(page)
1543 file.close()
1544 print 'wrote', name + '.html'
1545 except (ImportError, ErrorDuringImport), value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001546 print value
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001547
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001548def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001549 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001550 if done is None: done = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001551 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1552 writedoc(modname)
1553 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001554
1555class Helper:
Georg Brandl681001e2008-06-01 20:33:55 +00001556
1557 # These dictionaries map a topic name to either an alias, or a tuple
1558 # (label, seealso-items). The "label" is the label of the corresponding
1559 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl43819252009-04-26 09:56:44 +00001560 # in pydoc_data/topics.py.
Georg Brandl681001e2008-06-01 20:33:55 +00001561 #
1562 # CAUTION: if you change one of these dictionaries, be sure to adapt the
1563 # list of needed labels in Doc/tools/sphinxext/pyspecific.py and
Georg Brandl43819252009-04-26 09:56:44 +00001564 # regenerate the pydoc_data/topics.py file by running
Georg Brandl681001e2008-06-01 20:33:55 +00001565 # make pydoc-topics
1566 # in Doc/ and copying the output file into the Lib/ directory.
1567
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001568 keywords = {
1569 'and': 'BOOLEAN',
Georg Brandlb6a87542007-03-13 10:06:48 +00001570 'as': 'with',
Georg Brandl681001e2008-06-01 20:33:55 +00001571 'assert': ('assert', ''),
1572 'break': ('break', 'while for'),
1573 'class': ('class', 'CLASSES SPECIALMETHODS'),
1574 'continue': ('continue', 'while for'),
1575 'def': ('function', ''),
1576 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001577 'elif': 'if',
Georg Brandl681001e2008-06-01 20:33:55 +00001578 'else': ('else', 'while for'),
Georg Brandl5c669db2008-08-30 19:03:43 +00001579 'except': 'try',
Georg Brandl681001e2008-06-01 20:33:55 +00001580 'exec': ('exec', ''),
Georg Brandl5c669db2008-08-30 19:03:43 +00001581 'finally': 'try',
Georg Brandl681001e2008-06-01 20:33:55 +00001582 'for': ('for', 'break continue while'),
Georg Brandl5c669db2008-08-30 19:03:43 +00001583 'from': 'import',
Georg Brandl681001e2008-06-01 20:33:55 +00001584 'global': ('global', 'NAMESPACES'),
1585 'if': ('if', 'TRUTHVALUE'),
1586 'import': ('import', 'MODULES'),
1587 'in': ('in', 'SEQUENCEMETHODS2'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001588 'is': 'COMPARISON',
Georg Brandl681001e2008-06-01 20:33:55 +00001589 'lambda': ('lambda', 'FUNCTIONS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001590 'not': 'BOOLEAN',
1591 'or': 'BOOLEAN',
Georg Brandl681001e2008-06-01 20:33:55 +00001592 'pass': ('pass', ''),
1593 'print': ('print', ''),
1594 'raise': ('raise', 'EXCEPTIONS'),
1595 'return': ('return', 'FUNCTIONS'),
1596 'try': ('try', 'EXCEPTIONS'),
1597 'while': ('while', 'break continue if TRUTHVALUE'),
1598 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1599 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001600 }
Georg Brandlc3a98032008-12-27 18:20:04 +00001601 # Either add symbols to this dictionary or to the symbols dictionary
1602 # directly: Whichever is easier. They are merged later.
1603 _symbols_inverse = {
1604 'STRINGS' : ("'", "'''", "r'", "u'", '"""', '"', 'r"', 'u"'),
1605 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1606 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1607 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1608 'UNARY' : ('-', '~'),
1609 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1610 '^=', '<<=', '>>=', '**=', '//='),
1611 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1612 'COMPLEX' : ('j', 'J')
1613 }
1614 symbols = {
1615 '%': 'OPERATORS FORMATTING',
1616 '**': 'POWER',
1617 ',': 'TUPLES LISTS FUNCTIONS',
1618 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1619 '...': 'ELLIPSIS',
1620 ':': 'SLICINGS DICTIONARYLITERALS',
1621 '@': 'def class',
1622 '\\': 'STRINGS',
1623 '_': 'PRIVATENAMES',
1624 '__': 'PRIVATENAMES SPECIALMETHODS',
1625 '`': 'BACKQUOTES',
1626 '(': 'TUPLES FUNCTIONS CALLS',
1627 ')': 'TUPLES FUNCTIONS CALLS',
1628 '[': 'LISTS SUBSCRIPTS SLICINGS',
1629 ']': 'LISTS SUBSCRIPTS SLICINGS'
1630 }
1631 for topic, symbols_ in _symbols_inverse.iteritems():
1632 for symbol in symbols_:
1633 topics = symbols.get(symbol, topic)
1634 if topic not in topics:
1635 topics = topics + ' ' + topic
1636 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001637
1638 topics = {
Georg Brandl681001e2008-06-01 20:33:55 +00001639 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1640 'FUNCTIONS CLASSES MODULES FILES inspect'),
1641 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS FORMATTING '
1642 'TYPES'),
1643 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1644 'FORMATTING': ('formatstrings', 'OPERATORS'),
1645 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1646 'FORMATTING TYPES'),
1647 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1648 'INTEGER': ('integers', 'int range'),
1649 'FLOAT': ('floating', 'float math'),
1650 'COMPLEX': ('imaginary', 'complex cmath'),
1651 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING xrange LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001652 'MAPPINGS': 'DICTIONARIES',
Georg Brandl681001e2008-06-01 20:33:55 +00001653 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1654 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1655 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1656 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001657 'FRAMEOBJECTS': 'TYPES',
1658 'TRACEBACKS': 'TYPES',
Georg Brandl681001e2008-06-01 20:33:55 +00001659 'NONE': ('bltin-null-object', ''),
1660 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
1661 'FILES': ('bltin-file-objects', ''),
1662 'SPECIALATTRIBUTES': ('specialattrs', ''),
1663 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1664 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001665 'PACKAGES': 'import',
Georg Brandl681001e2008-06-01 20:33:55 +00001666 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1667 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1668 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1669 'LISTS DICTIONARIES BACKQUOTES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001670 'OPERATORS': 'EXPRESSIONS',
1671 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl681001e2008-06-01 20:33:55 +00001672 'OBJECTS': ('objects', 'TYPES'),
1673 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
1674 'CALLABLEMETHODS SEQUENCEMETHODS1 MAPPINGMETHODS '
1675 'SEQUENCEMETHODS2 NUMBERMETHODS CLASSES'),
1676 'BASICMETHODS': ('customization', 'cmp hash repr str SPECIALMETHODS'),
1677 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1678 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
1679 'SEQUENCEMETHODS1': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS2 '
1680 'SPECIALMETHODS'),
1681 'SEQUENCEMETHODS2': ('sequence-methods', 'SEQUENCES SEQUENCEMETHODS1 '
1682 'SPECIALMETHODS'),
1683 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1684 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1685 'SPECIALMETHODS'),
1686 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
1687 'NAMESPACES': ('naming', 'global ASSIGNMENT DELETION DYNAMICFEATURES'),
1688 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001689 'SCOPING': 'NAMESPACES',
1690 'FRAMES': 'NAMESPACES',
Georg Brandl681001e2008-06-01 20:33:55 +00001691 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1692 'COERCIONS': ('coercion-rules','CONVERSIONS'),
1693 'CONVERSIONS': ('conversions', 'COERCIONS'),
1694 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1695 'SPECIALIDENTIFIERS': ('id-classes', ''),
1696 'PRIVATENAMES': ('atom-identifiers', ''),
1697 'LITERALS': ('atom-literals', 'STRINGS BACKQUOTES NUMBERS '
1698 'TUPLELITERALS LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001699 'TUPLES': 'SEQUENCES',
Georg Brandl681001e2008-06-01 20:33:55 +00001700 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1701 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1702 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1703 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1704 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1705 'BACKQUOTES': ('string-conversions', 'repr str STRINGS LITERALS'),
1706 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr '
1707 'ATTRIBUTEMETHODS'),
1708 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS1'),
1709 'SLICINGS': ('slicings', 'SEQUENCEMETHODS2'),
1710 'CALLS': ('calls', 'EXPRESSIONS'),
1711 'POWER': ('power', 'EXPRESSIONS'),
1712 'UNARY': ('unary', 'EXPRESSIONS'),
1713 'BINARY': ('binary', 'EXPRESSIONS'),
1714 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1715 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1716 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1717 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001718 'ASSERTION': 'assert',
Georg Brandl681001e2008-06-01 20:33:55 +00001719 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1720 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001721 'DELETION': 'del',
1722 'PRINTING': 'print',
1723 'RETURNING': 'return',
1724 'IMPORTING': 'import',
1725 'CONDITIONAL': 'if',
Georg Brandl681001e2008-06-01 20:33:55 +00001726 'LOOPING': ('compound', 'for while break continue'),
1727 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1728 'DEBUGGING': ('debugger', 'pdb'),
1729 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001730 }
1731
Georg Brandl004c74d2010-08-01 19:06:51 +00001732 def __init__(self, input=None, output=None):
1733 self._input = input
1734 self._output = output
1735
1736 input = property(lambda self: self._input or sys.stdin)
1737 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001738
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001739 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001740 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001741 self()
1742 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001743 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001744
Alexander Belopolskyd501dde2011-01-11 15:35:23 +00001745 _GoInteractive = object()
1746 def __call__(self, request=_GoInteractive):
1747 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001748 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001749 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001750 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001751 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001752 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001753You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001754If you want to ask for help on a particular object directly from the
1755interpreter, you can type "help(object)". Executing "help('string')"
1756has the same effect as typing a particular string at the help> prompt.
1757''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001758
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001759 def interact(self):
1760 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001761 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001762 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001763 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001764 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001765 except (KeyboardInterrupt, EOFError):
1766 break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001767 request = strip(replace(request, '"', '', "'", ''))
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001768 if lower(request) in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001769 self.help(request)
1770
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001771 def getline(self, prompt):
1772 """Read one line, using raw_input when available."""
1773 if self.input is sys.stdin:
1774 return raw_input(prompt)
1775 else:
1776 self.output.write(prompt)
1777 self.output.flush()
1778 return self.input.readline()
1779
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001780 def help(self, request):
1781 if type(request) is type(''):
R. David Murrayd67ea7d2009-05-27 20:07:21 +00001782 request = request.strip()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001783 if request == 'help': self.intro()
1784 elif request == 'keywords': self.listkeywords()
Georg Brandlc3a98032008-12-27 18:20:04 +00001785 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001786 elif request == 'topics': self.listtopics()
1787 elif request == 'modules': self.listmodules()
1788 elif request[:8] == 'modules ':
1789 self.listmodules(split(request)[1])
Georg Brandlc3a98032008-12-27 18:20:04 +00001790 elif request in self.symbols: self.showsymbol(request)
Raymond Hettinger54f02222002-06-01 14:18:47 +00001791 elif request in self.keywords: self.showtopic(request)
1792 elif request in self.topics: self.showtopic(request)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001793 elif request: doc(request, 'Help on %s:')
1794 elif isinstance(request, Helper): self()
1795 else: doc(request, 'Help on %s:')
1796 self.output.write('\n')
1797
1798 def intro(self):
1799 self.output.write('''
1800Welcome to Python %s! This is the online help utility.
1801
1802If this is your first time using Python, you should definitely check out
R David Murray93a224d2012-03-31 12:10:48 -04001803the tutorial on the Internet at http://docs.python.org/%s/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001804
1805Enter the name of any module, keyword, or topic to get help on writing
1806Python programs and using Python modules. To quit this help utility and
1807return to the interpreter, just type "quit".
1808
1809To get a list of available modules, keywords, or topics, type "modules",
1810"keywords", or "topics". Each module also comes with a one-line summary
1811of what it does; to list the modules whose summaries contain a given word
1812such as "spam", type "modules spam".
R David Murray93a224d2012-03-31 12:10:48 -04001813''' % tuple([sys.version[:3]]*2))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001814
1815 def list(self, items, columns=4, width=80):
1816 items = items[:]
1817 items.sort()
1818 colw = width / columns
1819 rows = (len(items) + columns - 1) / columns
1820 for row in range(rows):
1821 for col in range(columns):
1822 i = col * rows + row
1823 if i < len(items):
1824 self.output.write(items[i])
1825 if col < columns - 1:
1826 self.output.write(' ' + ' ' * (colw-1 - len(items[i])))
1827 self.output.write('\n')
1828
1829 def listkeywords(self):
1830 self.output.write('''
1831Here is a list of the Python keywords. Enter any keyword to get more help.
1832
1833''')
1834 self.list(self.keywords.keys())
1835
Georg Brandlc3a98032008-12-27 18:20:04 +00001836 def listsymbols(self):
1837 self.output.write('''
1838Here is a list of the punctuation symbols which Python assigns special meaning
1839to. Enter any symbol to get more help.
1840
1841''')
1842 self.list(self.symbols.keys())
1843
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001844 def listtopics(self):
1845 self.output.write('''
1846Here is a list of available topics. Enter any topic name to get more help.
1847
1848''')
1849 self.list(self.topics.keys())
1850
Georg Brandlc3a98032008-12-27 18:20:04 +00001851 def showtopic(self, topic, more_xrefs=''):
Georg Brandl681001e2008-06-01 20:33:55 +00001852 try:
Georg Brandl43819252009-04-26 09:56:44 +00001853 import pydoc_data.topics
Georg Brandl681001e2008-06-01 20:33:55 +00001854 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001855 self.output.write('''
Georg Brandl681001e2008-06-01 20:33:55 +00001856Sorry, topic and keyword documentation is not available because the
Georg Brandl43819252009-04-26 09:56:44 +00001857module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001858''')
1859 return
1860 target = self.topics.get(topic, self.keywords.get(topic))
1861 if not target:
1862 self.output.write('no documentation found for %s\n' % repr(topic))
1863 return
1864 if type(target) is type(''):
Georg Brandlc3a98032008-12-27 18:20:04 +00001865 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001866
Georg Brandl681001e2008-06-01 20:33:55 +00001867 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001868 try:
Georg Brandl43819252009-04-26 09:56:44 +00001869 doc = pydoc_data.topics.topics[label]
Georg Brandl681001e2008-06-01 20:33:55 +00001870 except KeyError:
1871 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001872 return
Georg Brandl681001e2008-06-01 20:33:55 +00001873 pager(strip(doc) + '\n')
Georg Brandlc3a98032008-12-27 18:20:04 +00001874 if more_xrefs:
1875 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001876 if xrefs:
Georg Brandl681001e2008-06-01 20:33:55 +00001877 import StringIO, formatter
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001878 buffer = StringIO.StringIO()
1879 formatter.DumbWriter(buffer).send_flowing_data(
1880 'Related help topics: ' + join(split(xrefs), ', ') + '\n')
1881 self.output.write('\n%s\n' % buffer.getvalue())
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001882
Georg Brandlc3a98032008-12-27 18:20:04 +00001883 def showsymbol(self, symbol):
1884 target = self.symbols[symbol]
1885 topic, _, xrefs = target.partition(' ')
1886 self.showtopic(topic, xrefs)
1887
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001888 def listmodules(self, key=''):
1889 if key:
1890 self.output.write('''
1891Here is a list of matching modules. Enter any module name to get more help.
1892
1893''')
1894 apropos(key)
1895 else:
1896 self.output.write('''
1897Please wait a moment while I gather a list of all available modules...
1898
1899''')
1900 modules = {}
1901 def callback(path, modname, desc, modules=modules):
1902 if modname and modname[-9:] == '.__init__':
1903 modname = modname[:-9] + ' (package)'
1904 if find(modname, '.') < 0:
1905 modules[modname] = 1
Ka-Ping Yee9e0f1162008-01-13 11:25:13 +00001906 def onerror(modname):
1907 callback(None, modname, None)
1908 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001909 self.list(modules.keys())
1910 self.output.write('''
1911Enter any module name to get more help. Or, type "modules spam" to search
1912for modules whose descriptions contain the word "spam".
1913''')
1914
Georg Brandl004c74d2010-08-01 19:06:51 +00001915help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001916
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001917class Scanner:
1918 """A generic tree iterator."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001919 def __init__(self, roots, children, descendp):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001920 self.roots = roots[:]
1921 self.state = []
1922 self.children = children
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001923 self.descendp = descendp
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001924
1925 def next(self):
1926 if not self.state:
1927 if not self.roots:
1928 return None
1929 root = self.roots.pop(0)
1930 self.state = [(root, self.children(root))]
1931 node, children = self.state[-1]
1932 if not children:
1933 self.state.pop()
1934 return self.next()
1935 child = children.pop(0)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001936 if self.descendp(child):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001937 self.state.append((child, self.children(child)))
1938 return child
1939
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001940
1941class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001942 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001943
Ka-Ping Yee9e0f1162008-01-13 11:25:13 +00001944 def run(self, callback, key=None, completer=None, onerror=None):
Ka-Ping Yee66246962001-04-12 11:59:50 +00001945 if key: key = lower(key)
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001946 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001947 seen = {}
1948
1949 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001950 if modname != '__main__':
1951 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00001952 if key is None:
1953 callback(None, modname, '')
1954 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001955 desc = split(__import__(modname).__doc__ or '', '\n')[0]
Ka-Ping Yee66246962001-04-12 11:59:50 +00001956 if find(lower(modname + ' - ' + desc), key) >= 0:
1957 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001958
Ka-Ping Yee9e0f1162008-01-13 11:25:13 +00001959 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001960 if self.quit:
1961 break
1962 if key is None:
1963 callback(None, modname, '')
1964 else:
1965 loader = importer.find_module(modname)
1966 if hasattr(loader,'get_source'):
1967 import StringIO
1968 desc = source_synopsis(
1969 StringIO.StringIO(loader.get_source(modname))
1970 ) or ''
1971 if hasattr(loader,'get_filename'):
1972 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00001973 else:
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001974 path = None
1975 else:
1976 module = loader.load_module(modname)
1977 desc = (module.__doc__ or '').splitlines()[0]
1978 path = getattr(module,'__file__',None)
1979 if find(lower(modname + ' - ' + desc), key) >= 0:
1980 callback(path, modname, desc)
1981
1982 if completer:
1983 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001984
1985def apropos(key):
1986 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001987 def callback(path, modname, desc):
1988 if modname[-9:] == '.__init__':
1989 modname = modname[:-9] + ' (package)'
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001990 print modname, desc and '- ' + desc
Ned Deily0096fb52011-10-06 14:17:44 -07001991 def onerror(modname):
1992 pass
1993 with warnings.catch_warnings():
1994 warnings.filterwarnings('ignore') # ignore problems during import
1995 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001996
1997# --------------------------------------------------- web browser interface
1998
Ka-Ping Yee66246962001-04-12 11:59:50 +00001999def serve(port, callback=None, completer=None):
Ka-Ping Yeefd540692001-04-12 12:54:36 +00002000 import BaseHTTPServer, mimetools, select
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002001
2002 # Patch up mimetools.Message so it doesn't break if rfc822 is reloaded.
2003 class Message(mimetools.Message):
2004 def __init__(self, fp, seekable=1):
2005 Message = self.__class__
2006 Message.__bases__[0].__bases__[0].__init__(self, fp, seekable)
2007 self.encodingheader = self.getheader('content-transfer-encoding')
2008 self.typeheader = self.getheader('content-type')
2009 self.parsetype()
2010 self.parseplist()
2011
2012 class DocHandler(BaseHTTPServer.BaseHTTPRequestHandler):
2013 def send_document(self, title, contents):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002014 try:
2015 self.send_response(200)
2016 self.send_header('Content-Type', 'text/html')
2017 self.end_headers()
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002018 self.wfile.write(html.page(title, contents))
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002019 except IOError: pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002020
2021 def do_GET(self):
2022 path = self.path
2023 if path[-5:] == '.html': path = path[:-5]
2024 if path[:1] == '/': path = path[1:]
2025 if path and path != '.':
2026 try:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00002027 obj = locate(path, forceload=1)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002028 except ErrorDuringImport, value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002029 self.send_document(path, html.escape(str(value)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002030 return
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002031 if obj:
2032 self.send_document(describe(obj), html.document(obj, path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002033 else:
2034 self.send_document(path,
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002035'no Python documentation found for %s' % repr(path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002036 else:
2037 heading = html.heading(
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002038'<big><big><strong>Python: Index of Modules</strong></big></big>',
2039'#ffffff', '#7799ee')
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002040 def bltinlink(name):
2041 return '<a href="%s.html">%s</a>' % (name, name)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002042 names = filter(lambda x: x != '__main__',
2043 sys.builtin_module_names)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002044 contents = html.multicolumn(names, bltinlink)
2045 indices = ['<p>' + html.bigsection(
2046 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2047
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002048 seen = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +00002049 for dir in sys.path:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002050 indices.append(html.index(dir, seen))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002051 contents = heading + join(indices) + '''<p align=right>
Tim Peters2306d242001-09-25 03:18:32 +00002052<font color="#909090" face="helvetica, arial"><strong>
2053pydoc</strong> by Ka-Ping Yee &lt;ping@lfw.org&gt;</font>'''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002054 self.send_document('Index of Modules', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002055
2056 def log_message(self, *args): pass
2057
Ka-Ping Yeefd540692001-04-12 12:54:36 +00002058 class DocServer(BaseHTTPServer.HTTPServer):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002059 def __init__(self, port, callback):
Ronald Oussoren9545a232010-05-05 19:09:31 +00002060 host = 'localhost'
Senthil Kumaranaa895452010-08-18 19:35:53 +00002061 self.address = (host, port)
Ka-Ping Yeedb8ed152001-03-02 05:58:17 +00002062 self.url = 'http://%s:%d/' % (host, port)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002063 self.callback = callback
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002064 self.base.__init__(self, self.address, self.handler)
2065
2066 def serve_until_quit(self):
2067 import select
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002068 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002069 while not self.quit:
2070 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2071 if rd: self.handle_request()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002072
2073 def server_activate(self):
2074 self.base.server_activate(self)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002075 if self.callback: self.callback(self)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002076
2077 DocServer.base = BaseHTTPServer.HTTPServer
2078 DocServer.handler = DocHandler
2079 DocHandler.MessageClass = Message
2080 try:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002081 try:
2082 DocServer(port, callback).serve_until_quit()
2083 except (KeyboardInterrupt, select.error):
2084 pass
2085 finally:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002086 if completer: completer()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002087
2088# ----------------------------------------------------- graphical interface
2089
2090def gui():
2091 """Graphical interface (starts web server and pops up a control window)."""
2092 class GUI:
2093 def __init__(self, window, port=7464):
2094 self.window = window
2095 self.server = None
2096 self.scanner = None
2097
Georg Brandl6634bf22008-05-20 07:13:37 +00002098 import Tkinter
2099 self.server_frm = Tkinter.Frame(window)
2100 self.title_lbl = Tkinter.Label(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002101 text='Starting server...\n ')
Georg Brandl6634bf22008-05-20 07:13:37 +00002102 self.open_btn = Tkinter.Button(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002103 text='open browser', command=self.open, state='disabled')
Georg Brandl6634bf22008-05-20 07:13:37 +00002104 self.quit_btn = Tkinter.Button(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002105 text='quit serving', command=self.quit, state='disabled')
2106
Georg Brandl6634bf22008-05-20 07:13:37 +00002107 self.search_frm = Tkinter.Frame(window)
2108 self.search_lbl = Tkinter.Label(self.search_frm, text='Search for')
2109 self.search_ent = Tkinter.Entry(self.search_frm)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002110 self.search_ent.bind('<Return>', self.search)
Georg Brandl6634bf22008-05-20 07:13:37 +00002111 self.stop_btn = Tkinter.Button(self.search_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002112 text='stop', pady=0, command=self.stop, state='disabled')
2113 if sys.platform == 'win32':
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002114 # Trying to hide and show this button crashes under Windows.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002115 self.stop_btn.pack(side='right')
2116
2117 self.window.title('pydoc')
2118 self.window.protocol('WM_DELETE_WINDOW', self.quit)
2119 self.title_lbl.pack(side='top', fill='x')
2120 self.open_btn.pack(side='left', fill='x', expand=1)
2121 self.quit_btn.pack(side='right', fill='x', expand=1)
2122 self.server_frm.pack(side='top', fill='x')
2123
2124 self.search_lbl.pack(side='left')
2125 self.search_ent.pack(side='right', fill='x', expand=1)
2126 self.search_frm.pack(side='top', fill='x')
2127 self.search_ent.focus_set()
2128
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002129 font = ('helvetica', sys.platform == 'win32' and 8 or 10)
Georg Brandl6634bf22008-05-20 07:13:37 +00002130 self.result_lst = Tkinter.Listbox(window, font=font, height=6)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002131 self.result_lst.bind('<Button-1>', self.select)
2132 self.result_lst.bind('<Double-Button-1>', self.goto)
Georg Brandl6634bf22008-05-20 07:13:37 +00002133 self.result_scr = Tkinter.Scrollbar(window,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002134 orient='vertical', command=self.result_lst.yview)
2135 self.result_lst.config(yscrollcommand=self.result_scr.set)
2136
Georg Brandl6634bf22008-05-20 07:13:37 +00002137 self.result_frm = Tkinter.Frame(window)
2138 self.goto_btn = Tkinter.Button(self.result_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002139 text='go to selected', command=self.goto)
Georg Brandl6634bf22008-05-20 07:13:37 +00002140 self.hide_btn = Tkinter.Button(self.result_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002141 text='hide results', command=self.hide)
2142 self.goto_btn.pack(side='left', fill='x', expand=1)
2143 self.hide_btn.pack(side='right', fill='x', expand=1)
2144
2145 self.window.update()
2146 self.minwidth = self.window.winfo_width()
2147 self.minheight = self.window.winfo_height()
2148 self.bigminheight = (self.server_frm.winfo_reqheight() +
2149 self.search_frm.winfo_reqheight() +
2150 self.result_lst.winfo_reqheight() +
2151 self.result_frm.winfo_reqheight())
2152 self.bigwidth, self.bigheight = self.minwidth, self.bigminheight
2153 self.expanded = 0
2154 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2155 self.window.wm_minsize(self.minwidth, self.minheight)
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002156 self.window.tk.willdispatch()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002157
2158 import threading
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002159 threading.Thread(
2160 target=serve, args=(port, self.ready, self.quit)).start()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002161
2162 def ready(self, server):
2163 self.server = server
2164 self.title_lbl.config(
2165 text='Python documentation server at\n' + server.url)
2166 self.open_btn.config(state='normal')
2167 self.quit_btn.config(state='normal')
2168
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002169 def open(self, event=None, url=None):
2170 url = url or self.server.url
2171 try:
2172 import webbrowser
2173 webbrowser.open(url)
2174 except ImportError: # pre-webbrowser.py compatibility
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002175 if sys.platform == 'win32':
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002176 os.system('start "%s"' % url)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002177 else:
2178 rc = os.system('netscape -remote "openURL(%s)" &' % url)
2179 if rc: os.system('netscape "%s" &' % url)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002180
2181 def quit(self, event=None):
2182 if self.server:
2183 self.server.quit = 1
2184 self.window.quit()
2185
2186 def search(self, event=None):
2187 key = self.search_ent.get()
2188 self.stop_btn.pack(side='right')
2189 self.stop_btn.config(state='normal')
2190 self.search_lbl.config(text='Searching for "%s"...' % key)
2191 self.search_ent.forget()
2192 self.search_lbl.pack(side='left')
2193 self.result_lst.delete(0, 'end')
2194 self.goto_btn.config(state='disabled')
2195 self.expand()
2196
2197 import threading
2198 if self.scanner:
2199 self.scanner.quit = 1
2200 self.scanner = ModuleScanner()
2201 threading.Thread(target=self.scanner.run,
Ka-Ping Yee6dcfa382001-04-12 20:27:31 +00002202 args=(self.update, key, self.done)).start()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002203
2204 def update(self, path, modname, desc):
2205 if modname[-9:] == '.__init__':
2206 modname = modname[:-9] + ' (package)'
2207 self.result_lst.insert('end',
2208 modname + ' - ' + (desc or '(no description)'))
2209
2210 def stop(self, event=None):
2211 if self.scanner:
2212 self.scanner.quit = 1
2213 self.scanner = None
2214
2215 def done(self):
2216 self.scanner = None
2217 self.search_lbl.config(text='Search for')
2218 self.search_lbl.pack(side='left')
2219 self.search_ent.pack(side='right', fill='x', expand=1)
2220 if sys.platform != 'win32': self.stop_btn.forget()
2221 self.stop_btn.config(state='disabled')
2222
2223 def select(self, event=None):
2224 self.goto_btn.config(state='normal')
2225
2226 def goto(self, event=None):
2227 selection = self.result_lst.curselection()
2228 if selection:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002229 modname = split(self.result_lst.get(selection[0]))[0]
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002230 self.open(url=self.server.url + modname + '.html')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002231
2232 def collapse(self):
2233 if not self.expanded: return
2234 self.result_frm.forget()
2235 self.result_scr.forget()
2236 self.result_lst.forget()
2237 self.bigwidth = self.window.winfo_width()
2238 self.bigheight = self.window.winfo_height()
2239 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2240 self.window.wm_minsize(self.minwidth, self.minheight)
2241 self.expanded = 0
2242
2243 def expand(self):
2244 if self.expanded: return
2245 self.result_frm.pack(side='bottom', fill='x')
2246 self.result_scr.pack(side='right', fill='y')
2247 self.result_lst.pack(side='top', fill='both', expand=1)
2248 self.window.wm_geometry('%dx%d' % (self.bigwidth, self.bigheight))
2249 self.window.wm_minsize(self.minwidth, self.bigminheight)
2250 self.expanded = 1
2251
2252 def hide(self, event=None):
2253 self.stop()
2254 self.collapse()
2255
Georg Brandl6634bf22008-05-20 07:13:37 +00002256 import Tkinter
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002257 try:
Georg Brandl6634bf22008-05-20 07:13:37 +00002258 root = Tkinter.Tk()
Martin v. Löwise09bd932004-08-22 16:13:26 +00002259 # Tk will crash if pythonw.exe has an XP .manifest
2260 # file and the root has is not destroyed explicitly.
2261 # If the problem is ever fixed in Tk, the explicit
2262 # destroy can go.
2263 try:
2264 gui = GUI(root)
2265 root.mainloop()
2266 finally:
2267 root.destroy()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002268 except KeyboardInterrupt:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002269 pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002270
2271# -------------------------------------------------- command-line interface
2272
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002273def ispath(x):
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002274 return isinstance(x, str) and find(x, os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002275
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002276def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002277 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002278 import getopt
2279 class BadUsage: pass
2280
Nick Coghlan11db64e2009-11-15 22:36:47 +00002281 # Scripts don't get the current directory in their path by default
2282 # unless they are run with the '-m' switch
2283 if '' not in sys.path:
2284 scriptdir = os.path.dirname(sys.argv[0])
2285 if scriptdir in sys.path:
2286 sys.path.remove(scriptdir)
2287 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002288
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002289 try:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002290 opts, args = getopt.getopt(sys.argv[1:], 'gk:p:w')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002291 writing = 0
2292
2293 for opt, val in opts:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002294 if opt == '-g':
2295 gui()
2296 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002297 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002298 apropos(val)
2299 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002300 if opt == '-p':
2301 try:
2302 port = int(val)
2303 except ValueError:
2304 raise BadUsage
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002305 def ready(server):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002306 print 'pydoc server ready at %s' % server.url
2307 def stopped():
2308 print 'pydoc server stopped'
2309 serve(port, ready, stopped)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002310 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002311 if opt == '-w':
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002312 writing = 1
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002313
2314 if not args: raise BadUsage
2315 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002316 if ispath(arg) and not os.path.exists(arg):
2317 print 'file %r does not exist' % arg
2318 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002319 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002320 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002321 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002322 if writing:
2323 if ispath(arg) and os.path.isdir(arg):
2324 writedocs(arg)
2325 else:
2326 writedoc(arg)
2327 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002328 help.help(arg)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002329 except ErrorDuringImport, value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002330 print value
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002331
2332 except (getopt.error, BadUsage):
Martin v. Löwisf9b08b82003-10-31 13:05:21 +00002333 cmd = os.path.basename(sys.argv[0])
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002334 print """pydoc - the Python documentation tool
2335
2336%s <name> ...
2337 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002338 Python keyword, topic, function, module, or package, or a dotted
2339 reference to a class or function within a module or module in a
2340 package. If <name> contains a '%s', it is used as the path to a
2341 Python source file to document. If name is 'keywords', 'topics',
2342 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002343
2344%s -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002345 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002346
2347%s -p <port>
2348 Start an HTTP server on the given port on the local machine.
2349
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002350%s -g
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002351 Pop up a graphical interface for finding and serving documentation.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002352
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002353%s -w <name> ...
2354 Write out the HTML documentation for a module to a file in the current
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002355 directory. If <name> contains a '%s', it is treated as a filename; if
2356 it names a directory, documentation is written for all the contents.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002357""" % (cmd, os.sep, cmd, cmd, cmd, cmd, os.sep)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002358
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002359if __name__ == '__main__': cli()