blob: 218fd30d50e93aa36556f7183b31c1a1012c4795 [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)
R David Murray984f6302014-01-05 12:35:59 -050084 result = _encode(result)
Ka-Ping Yee239432a2001-03-02 02:45:08 +000085 return result and re.sub('^ *\n', '', rstrip(result)) or ''
Ka-Ping Yeedd175342001-02-27 14:43:46 +000086
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000087def splitdoc(doc):
88 """Split a doc string into a synopsis line (if any) and the rest."""
89 lines = split(strip(doc), '\n')
90 if len(lines) == 1:
91 return lines[0], ''
92 elif len(lines) >= 2 and not rstrip(lines[1]):
93 return lines[0], join(lines[2:], '\n')
94 return '', join(lines, '\n')
95
Ka-Ping Yeedd175342001-02-27 14:43:46 +000096def classname(object, modname):
97 """Get a class name and qualify it with a module name if necessary."""
98 name = object.__name__
99 if object.__module__ != modname:
100 name = object.__module__ + '.' + name
101 return name
102
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000103def isdata(object):
Georg Brandl94432422005-07-22 21:52:25 +0000104 """Check if an object is of a type that probably means it's data."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000105 return not (inspect.ismodule(object) or inspect.isclass(object) or
106 inspect.isroutine(object) or inspect.isframe(object) or
107 inspect.istraceback(object) or inspect.iscode(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000108
109def replace(text, *pairs):
110 """Do a series of global replacements on a string."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000111 while pairs:
112 text = join(split(text, pairs[0]), pairs[1])
113 pairs = pairs[2:]
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000114 return text
115
116def cram(text, maxlen):
117 """Omit part of a string if needed to make it fit in a maximum length."""
118 if len(text) > maxlen:
Raymond Hettingerfca3bb62002-10-21 04:44:11 +0000119 pre = max(0, (maxlen-3)//2)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000120 post = max(0, maxlen-3-pre)
121 return text[:pre] + '...' + text[len(text)-post:]
122 return text
123
Brett Cannon84601f12004-06-19 01:22:48 +0000124_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000125def stripid(text):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000126 """Remove the hexadecimal id from a Python object representation."""
Brett Cannonc6c1f472004-06-19 01:02:51 +0000127 # The behaviour of %p is implementation-dependent in terms of case.
Ezio Melottie511fc72010-02-16 23:26:09 +0000128 return _re_stripid.sub(r'\1', text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000129
Brett Cannonc6c1f472004-06-19 01:02:51 +0000130def _is_some_method(obj):
131 return inspect.ismethod(obj) or inspect.ismethoddescriptor(obj)
Tim Peters536d2262001-09-20 05:13:38 +0000132
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000133def allmethods(cl):
134 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000135 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000136 methods[key] = 1
137 for base in cl.__bases__:
138 methods.update(allmethods(base)) # all your base are belong to us
139 for key in methods.keys():
140 methods[key] = getattr(cl, key)
141 return methods
142
Tim Petersfa26f7c2001-09-24 08:05:11 +0000143def _split_list(s, predicate):
144 """Split sequence s via predicate, and return pair ([true], [false]).
145
146 The return value is a 2-tuple of lists,
147 ([x for x in s if predicate(x)],
148 [x for x in s if not predicate(x)])
149 """
150
Tim Peters28355492001-09-23 21:29:55 +0000151 yes = []
152 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000153 for x in s:
154 if predicate(x):
155 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000156 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000157 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000158 return yes, no
159
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700160def visiblename(name, all=None, obj=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000161 """Decide whether to show documentation on a variable."""
162 # Certain special names are redundant.
Nick Coghlanc060b0e2008-07-02 13:09:19 +0000163 _hidden_names = ('__builtins__', '__doc__', '__file__', '__path__',
164 '__module__', '__name__', '__slots__', '__package__')
165 if name in _hidden_names: return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000166 # Private names are hidden, but special names are displayed.
167 if name.startswith('__') and name.endswith('__'): return 1
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700168 # Namedtuples have public fields and methods with a single leading underscore
169 if name.startswith('_') and hasattr(obj, '_fields'):
170 return 1
Skip Montanaroa5616d22004-06-11 04:46:12 +0000171 if all is not None:
172 # only document that which the programmer exported in __all__
173 return name in all
174 else:
175 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000176
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000177def classify_class_attrs(object):
178 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Brett Cannonaca98b02008-08-03 00:58:51 +0000179 def fixup(data):
180 name, kind, cls, value = data
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000181 if inspect.isdatadescriptor(value):
182 kind = 'data descriptor'
183 return name, kind, cls, value
184 return map(fixup, inspect.classify_class_attrs(object))
185
R David Murray984f6302014-01-05 12:35:59 -0500186# ----------------------------------------------------- Unicode support helpers
187
188try:
189 _unicode = unicode
190except NameError:
191 # If Python is built without Unicode support, the unicode type
192 # will not exist. Fake one that nothing will match, and make
193 # the _encode function that do nothing.
194 class _unicode(object):
195 pass
196 _encoding = 'ascii'
197 def _encode(text, encoding='ascii'):
198 return text
199else:
200 import locale
201 _encoding = locale.getpreferredencoding()
202
203 def _encode(text, encoding=None):
204 if isinstance(text, unicode):
205 return text.encode(encoding or _encoding, 'xmlcharrefreplace')
206 else:
207 return text
208
209def _binstr(obj):
210 # Ensure that we have an encoded (binary) string representation of obj,
211 # even if it is a unicode string.
R David Murray875565b2014-01-05 17:14:08 -0500212 if isinstance(obj, _unicode):
213 return obj.encode(_encoding, 'xmlcharrefreplace')
214 return str(obj)
R David Murray984f6302014-01-05 12:35:59 -0500215
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000216# ----------------------------------------------------- module manipulation
217
218def ispackage(path):
219 """Guess whether a path refers to a package directory."""
220 if os.path.isdir(path):
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000221 for ext in ('.py', '.pyc', '.pyo'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000222 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000223 return True
224 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000225
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000226def source_synopsis(file):
227 line = file.readline()
228 while line[:1] == '#' or not strip(line):
229 line = file.readline()
230 if not line: break
231 line = strip(line)
232 if line[:4] == 'r"""': line = line[1:]
233 if line[:3] == '"""':
234 line = line[3:]
235 if line[-1:] == '\\': line = line[:-1]
236 while not strip(line):
237 line = file.readline()
238 if not line: break
239 result = strip(split(line, '"""')[0])
240 else: result = None
241 return result
242
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000243def synopsis(filename, cache={}):
244 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000245 mtime = os.stat(filename).st_mtime
Charles-François Natali0cf7e252011-07-27 19:36:40 +0200246 lastupdate, result = cache.get(filename, (None, None))
247 if lastupdate is None or lastupdate < mtime:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000248 info = inspect.getmoduleinfo(filename)
Georg Brandl26fd2e12006-03-08 09:34:53 +0000249 try:
250 file = open(filename)
251 except IOError:
252 # module can't be opened, so skip it
253 return None
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000254 if info and 'b' in info[2]: # binary modules have to be imported
255 try: module = imp.load_module('__temp__', file, filename, info[1:])
256 except: return None
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000257 result = (module.__doc__ or '').splitlines()[0]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000258 del sys.modules['__temp__']
259 else: # text modules can be directly examined
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000260 result = source_synopsis(file)
261 file.close()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000262 cache[filename] = (mtime, result)
263 return result
264
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000265class ErrorDuringImport(Exception):
266 """Errors that occurred while trying to import something to document it."""
Brett Cannonaca98b02008-08-03 00:58:51 +0000267 def __init__(self, filename, exc_info):
268 exc, value, tb = exc_info
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000269 self.filename = filename
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000270 self.exc = exc
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000271 self.value = value
272 self.tb = tb
273
274 def __str__(self):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000275 exc = self.exc
276 if type(exc) is types.ClassType:
277 exc = exc.__name__
278 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000279
280def importfile(path):
281 """Import a Python source file or compiled file given its path."""
282 magic = imp.get_magic()
283 file = open(path, 'r')
284 if file.read(len(magic)) == magic:
285 kind = imp.PY_COMPILED
286 else:
287 kind = imp.PY_SOURCE
288 file.close()
289 filename = os.path.basename(path)
290 name, ext = os.path.splitext(filename)
291 file = open(path, 'r')
292 try:
293 module = imp.load_module(name, file, path, (ext, 'r', kind))
294 except:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000295 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000296 file.close()
297 return module
298
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000299def safeimport(path, forceload=0, cache={}):
300 """Import a module; handle errors; return None if the module isn't found.
301
302 If the module *is* found but an exception occurs, it's wrapped in an
303 ErrorDuringImport exception and reraised. Unlike __import__, if a
304 package path is specified, the module at the end of the path is returned,
305 not the package at the beginning. If the optional 'forceload' argument
306 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000307 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000308 # If forceload is 1 and the module has been previously loaded from
309 # disk, we always have to reload the module. Checking the file's
310 # mtime isn't good enough (e.g. the module could contain a class
311 # that inherits from another module that has changed).
312 if forceload and path in sys.modules:
313 if path not in sys.builtin_module_names:
314 # Avoid simply calling reload() because it leaves names in
315 # the currently loaded module lying around if they're not
316 # defined in the new source file. Instead, remove the
317 # module from sys.modules and re-import. Also remove any
318 # submodules because they won't appear in the newly loaded
319 # module's namespace if they're already in sys.modules.
320 subs = [m for m in sys.modules if m.startswith(path + '.')]
321 for key in [path] + subs:
322 # Prevent garbage collection.
323 cache[key] = sys.modules[key]
324 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000325 module = __import__(path)
326 except:
327 # Did the error occur before or after the module was found?
328 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000329 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000330 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000331 raise ErrorDuringImport(sys.modules[path].__file__, info)
332 elif exc is SyntaxError:
333 # A SyntaxError occurred before we could execute the module.
334 raise ErrorDuringImport(value.filename, info)
R. David Murrayef087da2009-06-23 18:02:46 +0000335 elif exc is ImportError and extract_tb(tb)[-1][2]=='safeimport':
336 # The import error occurred directly in this function,
337 # which means there is no such module in the path.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000338 return None
339 else:
340 # Some other error occurred during the importing process.
341 raise ErrorDuringImport(path, sys.exc_info())
342 for part in split(path, '.')[1:]:
343 try: module = getattr(module, part)
344 except AttributeError: return None
345 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000346
347# ---------------------------------------------------- formatter base class
348
349class Doc:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000350 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000351 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000352 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000353 # 'try' clause is to attempt to handle the possibility that inspect
354 # identifies something in a way that pydoc itself has issues handling;
355 # think 'super' and how it is a descriptor (which raises the exception
356 # by lacking a __name__ attribute) and an instance.
Barry Warsaw00decd72006-07-27 23:43:15 +0000357 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
358 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000359 try:
360 if inspect.ismodule(object): return self.docmodule(*args)
361 if inspect.isclass(object): return self.docclass(*args)
362 if inspect.isroutine(object): return self.docroutine(*args)
363 except AttributeError:
364 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000365 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000366 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000367
368 def fail(self, object, name=None, *args):
369 """Raise an exception for unimplemented types."""
370 message = "don't know how to document object%s of type %s" % (
371 name and ' ' + repr(name), type(object).__name__)
372 raise TypeError, message
373
Barry Warsaw00decd72006-07-27 23:43:15 +0000374 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000375
Skip Montanaro4997a692003-09-10 16:47:51 +0000376 def getdocloc(self, object):
377 """Return the location of module docs or None"""
378
379 try:
380 file = inspect.getabsfile(object)
381 except TypeError:
382 file = '(built-in)'
383
384 docloc = os.environ.get("PYTHONDOCS",
Georg Brandl0751d1a2008-01-21 17:13:03 +0000385 "http://docs.python.org/library")
Skip Montanaro4997a692003-09-10 16:47:51 +0000386 basedir = os.path.join(sys.exec_prefix, "lib",
387 "python"+sys.version[0:3])
388 if (isinstance(object, type(os)) and
389 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
390 'marshal', 'posix', 'signal', 'sys',
391 'thread', 'zipimport') or
392 (file.startswith(basedir) and
Brian Curtinaeb2e822010-03-31 03:10:21 +0000393 not file.startswith(os.path.join(basedir, 'site-packages')))) and
Brian Curtina01da932010-04-01 04:02:00 +0000394 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
Skip Montanaro4997a692003-09-10 16:47:51 +0000395 if docloc.startswith("http://"):
Georg Brandl0751d1a2008-01-21 17:13:03 +0000396 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
Skip Montanaro4997a692003-09-10 16:47:51 +0000397 else:
Georg Brandl0751d1a2008-01-21 17:13:03 +0000398 docloc = os.path.join(docloc, object.__name__ + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000399 else:
400 docloc = None
401 return docloc
402
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000403# -------------------------------------------- HTML documentation generator
404
405class HTMLRepr(Repr):
406 """Class for safely making an HTML representation of a Python object."""
407 def __init__(self):
408 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000409 self.maxlist = self.maxtuple = 20
410 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000411 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000412
413 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000414 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000415
416 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000417 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000418
419 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000420 if hasattr(type(x), '__name__'):
421 methodname = 'repr_' + join(split(type(x).__name__), '_')
422 if hasattr(self, methodname):
423 return getattr(self, methodname)(x, level)
424 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000425
426 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000427 test = cram(x, self.maxstring)
428 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000429 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000430 # Backslashes are only literal in the string and are never
431 # needed to make any special characters, so show a raw string.
432 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000433 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000434 r'<font color="#c040c0">\1</font>',
435 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000436
Skip Montanarodf708782002-03-07 22:58:02 +0000437 repr_str = repr_string
438
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000439 def repr_instance(self, x, level):
440 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000441 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000442 except:
443 return self.escape('<%s instance>' % x.__class__.__name__)
444
445 repr_unicode = repr_string
446
447class HTMLDoc(Doc):
448 """Formatter class for HTML documentation."""
449
450 # ------------------------------------------- HTML formatting utilities
451
452 _repr_instance = HTMLRepr()
453 repr = _repr_instance.repr
454 escape = _repr_instance.escape
455
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000456 def page(self, title, contents):
457 """Format an HTML page."""
R David Murray984f6302014-01-05 12:35:59 -0500458 return _encode('''
Georg Brandle0197062009-04-10 08:20:23 +0000459<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000460<html><head><title>Python: %s</title>
R David Murray984f6302014-01-05 12:35:59 -0500461<meta charset="utf-8">
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000462</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000463%s
R David Murray984f6302014-01-05 12:35:59 -0500464</body></html>''' % (title, contents), 'ascii')
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000465
466 def heading(self, title, fgcol, bgcol, extras=''):
467 """Format a page heading."""
468 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000469<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000470<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000471<td valign=bottom>&nbsp;<br>
472<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000473><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000474><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000475 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
476
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000477 def section(self, title, fgcol, bgcol, contents, width=6,
478 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000479 """Format a section with a heading."""
480 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000481 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000482 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000483<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000484<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000485<td colspan=3 valign=bottom>&nbsp;<br>
486<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000487 ''' % (bgcol, fgcol, title)
488 if prelude:
489 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000490<tr bgcolor="%s"><td rowspan=2>%s</td>
491<td colspan=2>%s</td></tr>
492<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
493 else:
494 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000495<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000496
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000497 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000498
499 def bigsection(self, title, *args):
500 """Format a section with a big heading."""
501 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000502 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000503
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000504 def preformat(self, text):
505 """Format literal preformatted text."""
506 text = self.escape(expandtabs(text))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000507 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
508 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000509
510 def multicolumn(self, list, format, cols=4):
511 """Format a list of items into a multi-column list."""
512 result = ''
Victor Stinnerdbfba162011-05-26 13:37:25 +0200513 rows = (len(list)+cols-1)//cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000514 for col in range(cols):
Victor Stinnerdbfba162011-05-26 13:37:25 +0200515 result = result + '<td width="%d%%" valign=top>' % (100//cols)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000516 for i in range(rows*col, rows*col+rows):
517 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000518 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000519 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000520 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000521
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000522 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000523
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000524 def namelink(self, name, *dicts):
525 """Make a link for an identifier, given name-to-URL mappings."""
526 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000527 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000528 return '<a href="%s">%s</a>' % (dict[name], name)
529 return name
530
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000531 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000532 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000533 name, module = object.__name__, sys.modules.get(object.__module__)
534 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000535 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000536 module.__name__, name, classname(object, modname))
537 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000538
539 def modulelink(self, object):
540 """Make a link for a module."""
541 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
542
Brett Cannonaca98b02008-08-03 00:58:51 +0000543 def modpkglink(self, data):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000544 """Make a link for a module or package to display in an index."""
Brett Cannonaca98b02008-08-03 00:58:51 +0000545 name, path, ispackage, shadowed = data
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000546 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000547 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000548 if path:
549 url = '%s.%s.html' % (path, name)
550 else:
551 url = '%s.html' % name
552 if ispackage:
553 text = '<strong>%s</strong>&nbsp;(package)' % name
554 else:
555 text = name
556 return '<a href="%s">%s</a>' % (url, text)
557
558 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
559 """Mark up some plain text, given a context of symbols to look for.
560 Each context dictionary maps object names to anchor names."""
561 escape = escape or self.escape
562 results = []
563 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000564 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
565 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000566 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000567 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000568 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000569 match = pattern.search(text, here)
570 if not match: break
571 start, end = match.span()
572 results.append(escape(text[here:start]))
573
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000574 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000575 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000576 url = escape(all).replace('"', '&quot;')
577 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000578 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000579 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
580 results.append('<a href="%s">%s</a>' % (url, escape(all)))
581 elif pep:
Andrew M. Kuchling727a5902008-02-05 16:06:57 +0000582 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000583 results.append('<a href="%s">%s</a>' % (url, escape(all)))
Benjamin Petersonc3e1e902014-06-07 16:44:00 -0700584 elif selfdot:
585 # Create a link for methods like 'self.method(...)'
586 # and use <strong> for attributes like 'self.attr'
587 if text[end:end+1] == '(':
588 results.append('self.' + self.namelink(name, methods))
589 else:
590 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000591 elif text[end:end+1] == '(':
592 results.append(self.namelink(name, methods, funcs, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000593 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000594 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000595 here = end
596 results.append(escape(text[here:]))
597 return join(results, '')
598
599 # ---------------------------------------------- type-specific routines
600
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000601 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000602 """Produce HTML for a class tree as given by inspect.getclasstree()."""
603 result = ''
604 for entry in tree:
605 if type(entry) is type(()):
606 c, bases = entry
Tim Peters2306d242001-09-25 03:18:32 +0000607 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000608 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000609 if bases and bases != (parent,):
610 parents = []
611 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000612 parents.append(self.classlink(base, modname))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000613 result = result + '(' + join(parents, ', ') + ')'
Tim Peters2306d242001-09-25 03:18:32 +0000614 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000615 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000616 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000617 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000618 return '<dl>\n%s</dl>\n' % result
619
Tim Peters8dd7ade2001-10-18 19:56:17 +0000620 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000621 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000622 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000623 try:
624 all = object.__all__
625 except AttributeError:
626 all = None
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000627 parts = split(name, '.')
628 links = []
629 for i in range(len(parts)-1):
630 links.append(
631 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
632 (join(parts[:i+1], '.'), parts[i]))
633 linkedname = join(links + parts[-1:], '.')
634 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000635 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000636 path = inspect.getabsfile(object)
Ka-Ping Yee6191a232001-04-13 15:00:27 +0000637 url = path
638 if sys.platform == 'win32':
639 import nturl2path
640 url = nturl2path.pathname2url(path)
641 filelink = '<a href="file:%s">%s</a>' % (url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000642 except TypeError:
643 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000644 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000645 if hasattr(object, '__version__'):
R David Murray984f6302014-01-05 12:35:59 -0500646 version = _binstr(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000647 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
648 version = strip(version[11:-1])
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000649 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000650 if hasattr(object, '__date__'):
R David Murray984f6302014-01-05 12:35:59 -0500651 info.append(self.escape(_binstr(object.__date__)))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000652 if info:
653 head = head + ' (%s)' % join(info, ', ')
Skip Montanaro4997a692003-09-10 16:47:51 +0000654 docloc = self.getdocloc(object)
655 if docloc is not None:
656 docloc = '<br><a href="%(docloc)s">Module Docs</a>' % locals()
657 else:
658 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000659 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000660 head, '#ffffff', '#7799ee',
661 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000662
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000663 modules = inspect.getmembers(object, inspect.ismodule)
664
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000665 classes, cdict = [], {}
666 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000667 # if __all__ exists, believe it. Otherwise use old heuristic.
668 if (all is not None or
669 (inspect.getmodule(value) or object) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700670 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000671 classes.append((key, value))
672 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000673 for key, value in classes:
674 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000675 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000676 module = sys.modules.get(modname)
677 if modname != name and module and hasattr(module, key):
678 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000679 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000680 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000681 funcs, fdict = [], {}
682 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000683 # if __all__ exists, believe it. Otherwise use old heuristic.
684 if (all is not None or
685 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700686 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000687 funcs.append((key, value))
688 fdict[key] = '#-' + key
689 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000690 data = []
691 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700692 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000693 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000694
695 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
696 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000697 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000698
699 if hasattr(object, '__path__'):
700 modpkgs = []
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000701 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
702 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000703 modpkgs.sort()
704 contents = self.multicolumn(modpkgs, self.modpkglink)
705 result = result + self.bigsection(
706 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000707 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000708 contents = self.multicolumn(
Brett Cannonaca98b02008-08-03 00:58:51 +0000709 modules, lambda key_value, s=self: s.modulelink(key_value[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000710 result = result + self.bigsection(
Georg Brandlb169eaa2008-02-17 21:18:55 +0000711 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000712
713 if classes:
Brett Cannonaca98b02008-08-03 00:58:51 +0000714 classlist = map(lambda key_value: key_value[1], classes)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000715 contents = [
716 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000717 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000718 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000719 result = result + self.bigsection(
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000720 'Classes', '#ffffff', '#ee77aa', join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000721 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000722 contents = []
723 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000724 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000725 result = result + self.bigsection(
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000726 'Functions', '#ffffff', '#eeaa77', join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000727 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000728 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000729 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000730 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000731 result = result + self.bigsection(
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000732 'Data', '#ffffff', '#55aa55', join(contents, '<br>\n'))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000733 if hasattr(object, '__author__'):
R David Murray984f6302014-01-05 12:35:59 -0500734 contents = self.markup(_binstr(object.__author__), self.preformat)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000735 result = result + self.bigsection(
736 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000737 if hasattr(object, '__credits__'):
R David Murray984f6302014-01-05 12:35:59 -0500738 contents = self.markup(_binstr(object.__credits__), self.preformat)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000739 result = result + self.bigsection(
740 'Credits', '#ffffff', '#7799ee', contents)
741
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000742 return result
743
Tim Peters8dd7ade2001-10-18 19:56:17 +0000744 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
745 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000746 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000747 realname = object.__name__
748 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000749 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000750
Tim Petersb47879b2001-09-24 04:47:19 +0000751 contents = []
752 push = contents.append
753
Tim Petersfa26f7c2001-09-24 08:05:11 +0000754 # Cute little class to pump out a horizontal rule between sections.
755 class HorizontalRule:
756 def __init__(self):
757 self.needone = 0
758 def maybe(self):
759 if self.needone:
760 push('<hr>\n')
761 self.needone = 1
762 hr = HorizontalRule()
763
Tim Petersc86f6ca2001-09-26 21:31:51 +0000764 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000765 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000766 if len(mro) > 2:
767 hr.maybe()
768 push('<dl><dt>Method resolution order:</dt>\n')
769 for base in mro:
770 push('<dd>%s</dd>\n' % self.classlink(base,
771 object.__module__))
772 push('</dl>\n')
773
Tim Petersb47879b2001-09-24 04:47:19 +0000774 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000775 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000776 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000777 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000778 push(msg)
779 for name, kind, homecls, value in ok:
Antoine Pitroub8572a12011-12-21 10:16:14 +0100780 try:
781 value = getattr(object, name)
782 except Exception:
783 # Some descriptors may meet a failure in their __get__.
784 # (bug #1785)
785 push(self._docdescriptor(name, value, mod))
786 else:
787 push(self.document(value, name, mod,
788 funcs, classes, mdict, object))
Tim Petersb47879b2001-09-24 04:47:19 +0000789 push('\n')
790 return attrs
791
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000792 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000793 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000794 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000795 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000796 push(msg)
797 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000798 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000799 return attrs
800
Tim Petersfa26f7c2001-09-24 08:05:11 +0000801 def spilldata(msg, attrs, predicate):
802 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000803 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000804 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000805 push(msg)
806 for name, kind, homecls, value in ok:
807 base = self.docother(getattr(object, name), name, mod)
Brett Cannonaca98b02008-08-03 00:58:51 +0000808 if (hasattr(value, '__call__') or
809 inspect.isdatadescriptor(value)):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000810 doc = getattr(value, "__doc__", None)
811 else:
812 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000813 if doc is None:
814 push('<dl><dt>%s</dl>\n' % base)
815 else:
816 doc = self.markup(getdoc(value), self.preformat,
817 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000818 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000819 push('<dl><dt>%s%s</dl>\n' % (base, doc))
820 push('\n')
821 return attrs
822
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700823 attrs = filter(lambda data: visiblename(data[0], obj=object),
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000824 classify_class_attrs(object))
Tim Petersb47879b2001-09-24 04:47:19 +0000825 mdict = {}
826 for key, kind, homecls, value in attrs:
827 mdict[key] = anchor = '#' + name + '-' + key
Antoine Pitroub8572a12011-12-21 10:16:14 +0100828 try:
829 value = getattr(object, name)
830 except Exception:
831 # Some descriptors may meet a failure in their __get__.
832 # (bug #1785)
833 pass
Tim Petersb47879b2001-09-24 04:47:19 +0000834 try:
835 # The value may not be hashable (e.g., a data attr with
836 # a dict or list value).
837 mdict[value] = anchor
838 except TypeError:
839 pass
840
Tim Petersfa26f7c2001-09-24 08:05:11 +0000841 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000842 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000843 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000844 else:
845 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000846 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
847
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000848 if thisclass is __builtin__.object:
849 attrs = inherited
850 continue
851 elif thisclass is object:
852 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000853 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000854 tag = 'inherited from %s' % self.classlink(thisclass,
855 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000856 tag += ':<br>\n'
857
858 # Sort attrs by name.
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000859 try:
860 attrs.sort(key=lambda t: t[0])
861 except TypeError:
862 attrs.sort(lambda t1, t2: cmp(t1[0], t2[0])) # 2.3 compat
Tim Petersb47879b2001-09-24 04:47:19 +0000863
864 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000865 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000866 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000867 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000868 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000869 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000870 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000871 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
872 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000873 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000874 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000875 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000876 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000877
878 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000879
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000880 if name == realname:
881 title = '<a name="%s">class <strong>%s</strong></a>' % (
882 name, realname)
883 else:
884 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
885 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000886 if bases:
887 parents = []
888 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000889 parents.append(self.classlink(base, object.__module__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000890 title = title + '(%s)' % join(parents, ', ')
Tim Peters2306d242001-09-25 03:18:32 +0000891 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000892 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000893
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000894 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000895
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000896 def formatvalue(self, object):
897 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000898 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000899
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000900 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000901 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000902 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000903 realname = object.__name__
904 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000905 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000906 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000907 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000908 if inspect.ismethod(object):
Ka-Ping Yee6dcfa382001-04-12 20:27:31 +0000909 imclass = object.im_class
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000910 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000911 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000912 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000913 else:
Georg Brandl7e2b6bb2007-03-13 22:16:30 +0000914 if object.im_self is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000915 note = ' method of %s instance' % self.classlink(
916 object.im_self.__class__, mod)
917 else:
918 note = ' unbound %s method' % self.classlink(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000919 object = object.im_func
920
921 if name == realname:
922 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
923 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000924 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000925 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000926 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000927 cl.__name__ + '-' + realname, realname)
928 skipdocs = 1
929 else:
930 reallink = realname
931 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
932 anchor, name, reallink)
Tim Peters4bcfa312001-09-20 06:08:24 +0000933 if inspect.isfunction(object):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000934 args, varargs, varkw, defaults = inspect.getargspec(object)
935 argspec = inspect.formatargspec(
936 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000937 if realname == '<lambda>':
Tim Peters59ed4482001-10-31 04:20:26 +0000938 title = '<strong>%s</strong> <em>lambda</em> ' % name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000939 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +0000940 else:
941 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000942
Tim Peters2306d242001-09-25 03:18:32 +0000943 decl = title + argspec + (note and self.grey(
944 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000945
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000946 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000947 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000948 else:
949 doc = self.markup(
950 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000951 doc = doc and '<dd><tt>%s</tt></dd>' % doc
952 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000953
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000954 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000955 results = []
956 push = results.append
957
958 if name:
959 push('<dl><dt><strong>%s</strong></dt>\n' % name)
960 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000961 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000962 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000963 push('</dl>\n')
964
965 return ''.join(results)
966
967 def docproperty(self, object, name=None, mod=None, cl=None):
968 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000969 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000970
Tim Peters8dd7ade2001-10-18 19:56:17 +0000971 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000972 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000973 lhs = name and '<strong>%s</strong> = ' % name or ''
974 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000975
Barry Warsaw00decd72006-07-27 23:43:15 +0000976 def docdata(self, object, name=None, mod=None, cl=None):
977 """Produce html documentation for a data descriptor."""
978 return self._docdescriptor(name, object, mod)
979
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000980 def index(self, dir, shadowed=None):
981 """Generate an HTML index for a directory of modules."""
982 modpkgs = []
983 if shadowed is None: shadowed = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000984 for importer, name, ispkg in pkgutil.iter_modules([dir]):
985 modpkgs.append((name, '', ispkg, name in shadowed))
986 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000987
988 modpkgs.sort()
989 contents = self.multicolumn(modpkgs, self.modpkglink)
990 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
991
992# -------------------------------------------- text documentation generator
993
994class TextRepr(Repr):
995 """Class for safely making a text representation of a Python object."""
996 def __init__(self):
997 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000998 self.maxlist = self.maxtuple = 20
999 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001000 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001001
1002 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001003 if hasattr(type(x), '__name__'):
1004 methodname = 'repr_' + join(split(type(x).__name__), '_')
1005 if hasattr(self, methodname):
1006 return getattr(self, methodname)(x, level)
1007 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001008
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001009 def repr_string(self, x, level):
1010 test = cram(x, self.maxstring)
1011 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001012 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001013 # Backslashes are only literal in the string and are never
1014 # needed to make any special characters, so show a raw string.
1015 return 'r' + testrepr[0] + test + testrepr[0]
1016 return testrepr
1017
Skip Montanarodf708782002-03-07 22:58:02 +00001018 repr_str = repr_string
1019
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001020 def repr_instance(self, x, level):
1021 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001022 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001023 except:
1024 return '<%s instance>' % x.__class__.__name__
1025
1026class TextDoc(Doc):
1027 """Formatter class for text documentation."""
1028
1029 # ------------------------------------------- text formatting utilities
1030
1031 _repr_instance = TextRepr()
1032 repr = _repr_instance.repr
1033
1034 def bold(self, text):
1035 """Format a string in bold by overstriking."""
1036 return join(map(lambda ch: ch + '\b' + ch, text), '')
1037
1038 def indent(self, text, prefix=' '):
1039 """Indent text by prepending a given prefix to each line."""
1040 if not text: return ''
1041 lines = split(text, '\n')
1042 lines = map(lambda line, prefix=prefix: prefix + line, lines)
1043 if lines: lines[-1] = rstrip(lines[-1])
1044 return join(lines, '\n')
1045
1046 def section(self, title, contents):
1047 """Format a section with a given heading."""
1048 return self.bold(title) + '\n' + rstrip(self.indent(contents)) + '\n\n'
1049
1050 # ---------------------------------------------- type-specific routines
1051
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001052 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001053 """Render in text a class tree as returned by inspect.getclasstree()."""
1054 result = ''
1055 for entry in tree:
1056 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001057 c, bases = entry
1058 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001059 if bases and bases != (parent,):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001060 parents = map(lambda c, m=modname: classname(c, m), bases)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001061 result = result + '(%s)' % join(parents, ', ')
1062 result = result + '\n'
1063 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001064 result = result + self.formattree(
1065 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001066 return result
1067
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001068 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001069 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001070 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001071 synop, desc = splitdoc(getdoc(object))
1072 result = self.section('NAME', name + (synop and ' - ' + synop))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001073
1074 try:
Skip Montanaroa5616d22004-06-11 04:46:12 +00001075 all = object.__all__
1076 except AttributeError:
1077 all = None
1078
1079 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001080 file = inspect.getabsfile(object)
1081 except TypeError:
1082 file = '(built-in)'
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001083 result = result + self.section('FILE', file)
Skip Montanaro4997a692003-09-10 16:47:51 +00001084
1085 docloc = self.getdocloc(object)
1086 if docloc is not None:
1087 result = result + self.section('MODULE DOCS', docloc)
1088
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001089 if desc:
1090 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001091
1092 classes = []
1093 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001094 # if __all__ exists, believe it. Otherwise use old heuristic.
1095 if (all is not None
1096 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001097 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001098 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001099 funcs = []
1100 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001101 # if __all__ exists, believe it. Otherwise use old heuristic.
1102 if (all is not None or
1103 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001104 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001105 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001106 data = []
1107 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001108 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001109 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001110
Georg Brandlf2dae0e2008-01-21 21:05:49 +00001111 modpkgs = []
1112 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001113 if hasattr(object, '__path__'):
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001114 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Georg Brandlf2dae0e2008-01-21 21:05:49 +00001115 modpkgs_names.add(modname)
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001116 if ispkg:
1117 modpkgs.append(modname + ' (package)')
1118 else:
1119 modpkgs.append(modname)
1120
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001121 modpkgs.sort()
1122 result = result + self.section(
1123 'PACKAGE CONTENTS', join(modpkgs, '\n'))
1124
Georg Brandlf2dae0e2008-01-21 21:05:49 +00001125 # Detect submodules as sometimes created by C extensions
1126 submodules = []
1127 for key, value in inspect.getmembers(object, inspect.ismodule):
1128 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1129 submodules.append(key)
1130 if submodules:
1131 submodules.sort()
1132 result = result + self.section(
1133 'SUBMODULES', join(submodules, '\n'))
1134
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001135 if classes:
Brett Cannonaca98b02008-08-03 00:58:51 +00001136 classlist = map(lambda key_value: key_value[1], classes)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001137 contents = [self.formattree(
1138 inspect.getclasstree(classlist, 1), name)]
1139 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001140 contents.append(self.document(value, key, name))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001141 result = result + self.section('CLASSES', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001142
1143 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001144 contents = []
1145 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001146 contents.append(self.document(value, key, name))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001147 result = result + self.section('FUNCTIONS', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001148
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001149 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001150 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001151 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001152 contents.append(self.docother(value, key, name, maxlen=70))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001153 result = result + self.section('DATA', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001154
1155 if hasattr(object, '__version__'):
R David Murray984f6302014-01-05 12:35:59 -05001156 version = _binstr(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001157 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
1158 version = strip(version[11:-1])
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001159 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001160 if hasattr(object, '__date__'):
R David Murray984f6302014-01-05 12:35:59 -05001161 result = result + self.section('DATE', _binstr(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001162 if hasattr(object, '__author__'):
R David Murray984f6302014-01-05 12:35:59 -05001163 result = result + self.section('AUTHOR', _binstr(object.__author__))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001164 if hasattr(object, '__credits__'):
R David Murray984f6302014-01-05 12:35:59 -05001165 result = result + self.section('CREDITS', _binstr(object.__credits__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001166 return result
1167
Georg Brandl52f83952011-02-25 10:39:23 +00001168 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001169 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001170 realname = object.__name__
1171 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001172 bases = object.__bases__
1173
Tim Petersc86f6ca2001-09-26 21:31:51 +00001174 def makename(c, m=object.__module__):
1175 return classname(c, m)
1176
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001177 if name == realname:
1178 title = 'class ' + self.bold(realname)
1179 else:
1180 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001181 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001182 parents = map(makename, bases)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001183 title = title + '(%s)' % join(parents, ', ')
1184
1185 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001186 contents = doc and [doc + '\n'] or []
1187 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001188
Tim Petersc86f6ca2001-09-26 21:31:51 +00001189 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001190 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001191 if len(mro) > 2:
1192 push("Method resolution order:")
1193 for base in mro:
1194 push(' ' + makename(base))
1195 push('')
1196
Tim Petersf4aad8e2001-09-24 22:40:47 +00001197 # Cute little class to pump out a horizontal rule between sections.
1198 class HorizontalRule:
1199 def __init__(self):
1200 self.needone = 0
1201 def maybe(self):
1202 if self.needone:
1203 push('-' * 70)
1204 self.needone = 1
1205 hr = HorizontalRule()
1206
Tim Peters28355492001-09-23 21:29:55 +00001207 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001208 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001209 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001210 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001211 push(msg)
1212 for name, kind, homecls, value in ok:
Antoine Pitroub8572a12011-12-21 10:16:14 +01001213 try:
1214 value = getattr(object, name)
1215 except Exception:
1216 # Some descriptors may meet a failure in their __get__.
1217 # (bug #1785)
1218 push(self._docdescriptor(name, value, mod))
1219 else:
1220 push(self.document(value,
1221 name, mod, object))
Tim Peters28355492001-09-23 21:29:55 +00001222 return attrs
1223
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001224 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001225 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001226 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001227 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001228 push(msg)
1229 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001230 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001231 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001232
Tim Petersfa26f7c2001-09-24 08:05:11 +00001233 def spilldata(msg, attrs, predicate):
1234 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001235 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001236 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001237 push(msg)
1238 for name, kind, homecls, value in ok:
Brett Cannonaca98b02008-08-03 00:58:51 +00001239 if (hasattr(value, '__call__') or
1240 inspect.isdatadescriptor(value)):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001241 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001242 else:
1243 doc = None
Tim Peters28355492001-09-23 21:29:55 +00001244 push(self.docother(getattr(object, name),
Georg Brandl8b813db2005-10-01 16:32:31 +00001245 name, mod, maxlen=70, doc=doc) + '\n')
Tim Peters28355492001-09-23 21:29:55 +00001246 return attrs
1247
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001248 attrs = filter(lambda data: visiblename(data[0], obj=object),
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001249 classify_class_attrs(object))
Tim Petersfa26f7c2001-09-24 08:05:11 +00001250 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001251 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001252 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001253 else:
1254 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001255 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1256
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001257 if thisclass is __builtin__.object:
1258 attrs = inherited
1259 continue
1260 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001261 tag = "defined here"
1262 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001263 tag = "inherited from %s" % classname(thisclass,
1264 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001265
1266 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001267 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001268
1269 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001270 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001271 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001272 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001273 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001274 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001275 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001276 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1277 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001278 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1279 lambda t: t[1] == 'data')
Tim Peters28355492001-09-23 21:29:55 +00001280 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001281 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001282
1283 contents = '\n'.join(contents)
1284 if not contents:
1285 return title + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001286 return title + '\n' + self.indent(rstrip(contents), ' | ') + '\n'
1287
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001288 def formatvalue(self, object):
1289 """Format an argument default value as text."""
1290 return '=' + self.repr(object)
1291
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001292 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001293 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001294 realname = object.__name__
1295 name = name or realname
1296 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001297 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001298 if inspect.ismethod(object):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001299 imclass = object.im_class
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001300 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001301 if imclass is not cl:
1302 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001303 else:
Georg Brandl7e2b6bb2007-03-13 22:16:30 +00001304 if object.im_self is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001305 note = ' method of %s instance' % classname(
1306 object.im_self.__class__, mod)
1307 else:
1308 note = ' unbound %s method' % classname(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001309 object = object.im_func
1310
1311 if name == realname:
1312 title = self.bold(realname)
1313 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001314 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001315 cl.__dict__[realname] is object):
1316 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001317 title = self.bold(name) + ' = ' + realname
Tim Peters4bcfa312001-09-20 06:08:24 +00001318 if inspect.isfunction(object):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001319 args, varargs, varkw, defaults = inspect.getargspec(object)
1320 argspec = inspect.formatargspec(
1321 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001322 if realname == '<lambda>':
Georg Brandl501dd0d2006-02-17 09:45:40 +00001323 title = self.bold(name) + ' lambda '
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001324 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +00001325 else:
1326 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001327 decl = title + argspec + note
1328
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001329 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001330 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001331 else:
1332 doc = getdoc(object) or ''
1333 return decl + '\n' + (doc and rstrip(self.indent(doc)) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001334
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001335 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001336 results = []
1337 push = results.append
1338
1339 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001340 push(self.bold(name))
1341 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001342 doc = getdoc(value) or ''
1343 if doc:
1344 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001345 push('\n')
1346 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001347
1348 def docproperty(self, object, name=None, mod=None, cl=None):
1349 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001350 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001351
Barry Warsaw00decd72006-07-27 23:43:15 +00001352 def docdata(self, object, name=None, mod=None, cl=None):
1353 """Produce text documentation for a data descriptor."""
1354 return self._docdescriptor(name, object, mod)
1355
Georg Brandl8b813db2005-10-01 16:32:31 +00001356 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001357 """Produce text documentation for a data object."""
1358 repr = self.repr(object)
1359 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001360 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001361 chop = maxlen - len(line)
1362 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001363 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001364 if doc is not None:
1365 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001366 return line
1367
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001368# --------------------------------------------------------- user interfaces
1369
1370def pager(text):
1371 """The first time this is called, determine what kind of pager to use."""
1372 global pager
1373 pager = getpager()
1374 pager(text)
1375
1376def getpager():
1377 """Decide what method to use for paging through text."""
1378 if type(sys.stdout) is not types.FileType:
1379 return plainpager
Benjamin Peterson75a55c32014-06-07 20:14:26 -07001380 if not hasattr(sys.stdin, "isatty"):
1381 return plainpager
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001382 if not sys.stdin.isatty() or not sys.stdout.isatty():
1383 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001384 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001385 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001386 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001387 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001388 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001389 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001390 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001391 if os.environ.get('TERM') in ('dumb', 'emacs'):
1392 return plainpager
Andrew MacIntyre54e0eab2002-03-03 03:12:30 +00001393 if sys.platform == 'win32' or sys.platform.startswith('os2'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001394 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001395 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001396 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001397
1398 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001399 (fd, filename) = tempfile.mkstemp()
1400 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001401 try:
Georg Brandlb32dea52008-07-16 21:19:28 +00001402 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001403 return lambda text: pipepager(text, 'more')
1404 else:
1405 return ttypager
1406 finally:
1407 os.unlink(filename)
1408
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001409def plain(text):
1410 """Remove boldface formatting from text."""
1411 return re.sub('.\b', '', text)
1412
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001413def pipepager(text, cmd):
1414 """Page through text by feeding it to another program."""
1415 pipe = os.popen(cmd, 'w')
1416 try:
R David Murray984f6302014-01-05 12:35:59 -05001417 pipe.write(_encode(text))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001418 pipe.close()
1419 except IOError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001420 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001421
1422def tempfilepager(text, cmd):
1423 """Page through text by invoking a program on a temporary file."""
1424 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001425 filename = tempfile.mktemp()
1426 file = open(filename, 'w')
R David Murray984f6302014-01-05 12:35:59 -05001427 file.write(_encode(text))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001428 file.close()
1429 try:
Georg Brandlb32dea52008-07-16 21:19:28 +00001430 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001431 finally:
1432 os.unlink(filename)
1433
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001434def ttypager(text):
1435 """Page through text on a text terminal."""
R David Murray984f6302014-01-05 12:35:59 -05001436 lines = plain(_encode(plain(text), getattr(sys.stdout, 'encoding', _encoding))).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001437 try:
1438 import tty
1439 fd = sys.stdin.fileno()
1440 old = tty.tcgetattr(fd)
1441 tty.setcbreak(fd)
1442 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001443 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001444 tty = None
1445 getchar = lambda: sys.stdin.readline()[:-1][:1]
1446
1447 try:
1448 r = inc = os.environ.get('LINES', 25) - 1
1449 sys.stdout.write(join(lines[:inc], '\n') + '\n')
1450 while lines[r:]:
1451 sys.stdout.write('-- more --')
1452 sys.stdout.flush()
1453 c = getchar()
1454
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001455 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001456 sys.stdout.write('\r \r')
1457 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001458 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001459 sys.stdout.write('\r \r' + lines[r] + '\n')
1460 r = r + 1
1461 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001462 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001463 r = r - inc - inc
1464 if r < 0: r = 0
1465 sys.stdout.write('\n' + join(lines[r:r+inc], '\n') + '\n')
1466 r = r + inc
1467
1468 finally:
1469 if tty:
1470 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1471
1472def plainpager(text):
1473 """Simply print unformatted text. This is the ultimate fallback."""
R David Murray984f6302014-01-05 12:35:59 -05001474 sys.stdout.write(_encode(plain(text), getattr(sys.stdout, 'encoding', _encoding)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001475
1476def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001477 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001478 if inspect.ismodule(thing):
1479 if thing.__name__ in sys.builtin_module_names:
1480 return 'built-in module ' + thing.__name__
1481 if hasattr(thing, '__path__'):
1482 return 'package ' + thing.__name__
1483 else:
1484 return 'module ' + thing.__name__
1485 if inspect.isbuiltin(thing):
1486 return 'built-in function ' + thing.__name__
Barry Warsaw00decd72006-07-27 23:43:15 +00001487 if inspect.isgetsetdescriptor(thing):
1488 return 'getset descriptor %s.%s.%s' % (
1489 thing.__objclass__.__module__, thing.__objclass__.__name__,
1490 thing.__name__)
1491 if inspect.ismemberdescriptor(thing):
1492 return 'member descriptor %s.%s.%s' % (
1493 thing.__objclass__.__module__, thing.__objclass__.__name__,
1494 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001495 if inspect.isclass(thing):
1496 return 'class ' + thing.__name__
1497 if inspect.isfunction(thing):
1498 return 'function ' + thing.__name__
1499 if inspect.ismethod(thing):
1500 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001501 if type(thing) is types.InstanceType:
1502 return 'instance of ' + thing.__class__.__name__
1503 return type(thing).__name__
1504
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001505def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001506 """Locate an object by name or dotted path, importing as necessary."""
Guido van Rossum97dede02003-02-16 01:12:32 +00001507 parts = [part for part in split(path, '.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001508 module, n = None, 0
1509 while n < len(parts):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001510 nextmodule = safeimport(join(parts[:n+1], '.'), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001511 if nextmodule: module, n = nextmodule, n + 1
1512 else: break
1513 if module:
1514 object = module
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001515 else:
Éric Araujo9a528302011-07-29 17:34:35 +02001516 object = __builtin__
1517 for part in parts[n:]:
1518 try:
1519 object = getattr(object, part)
1520 except AttributeError:
1521 return None
1522 return object
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001523
1524# --------------------------------------- interactive interpreter interface
1525
1526text = TextDoc()
1527html = HTMLDoc()
1528
Ka-Ping Yee8ef1cf32007-01-14 04:25:15 +00001529class _OldStyleClass: pass
1530_OLD_INSTANCE_TYPE = type(_OldStyleClass())
1531
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001532def resolve(thing, forceload=0):
1533 """Given an object or a path to an object, get the object and its name."""
1534 if isinstance(thing, str):
1535 object = locate(thing, forceload)
1536 if not object:
1537 raise ImportError, 'no Python documentation found for %r' % thing
1538 return object, thing
1539 else:
R David Murrayc313b1d2012-04-23 13:27:11 -04001540 name = getattr(thing, '__name__', None)
1541 return thing, name if isinstance(name, str) else None
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001542
Georg Brandl8441f152007-03-13 20:02:57 +00001543def render_doc(thing, title='Python Library Documentation: %s', forceload=0):
1544 """Render text documentation, given an object or a path to an object."""
1545 object, name = resolve(thing, forceload)
1546 desc = describe(object)
1547 module = inspect.getmodule(object)
1548 if name and '.' in name:
1549 desc += ' in ' + name[:name.rfind('.')]
1550 elif module and module is not object:
1551 desc += ' in module ' + module.__name__
1552 if type(object) is _OLD_INSTANCE_TYPE:
1553 # If the passed object is an instance of an old-style class,
1554 # document its available methods instead of its value.
1555 object = object.__class__
1556 elif not (inspect.ismodule(object) or
1557 inspect.isclass(object) or
1558 inspect.isroutine(object) or
1559 inspect.isgetsetdescriptor(object) or
1560 inspect.ismemberdescriptor(object) or
1561 isinstance(object, property)):
1562 # If the passed object is a piece of data or an instance,
1563 # document its available methods instead of its value.
1564 object = type(object)
1565 desc += ' object'
1566 return title % desc + '\n\n' + text.document(object, name)
1567
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001568def doc(thing, title='Python Library Documentation: %s', forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001569 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001570 try:
Georg Brandl8441f152007-03-13 20:02:57 +00001571 pager(render_doc(thing, title, forceload))
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001572 except (ImportError, ErrorDuringImport), value:
1573 print value
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001574
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001575def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001576 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001577 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001578 object, name = resolve(thing, forceload)
1579 page = html.page(describe(object), html.document(object, name))
1580 file = open(name + '.html', 'w')
1581 file.write(page)
1582 file.close()
1583 print 'wrote', name + '.html'
1584 except (ImportError, ErrorDuringImport), value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001585 print value
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001586
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001587def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001588 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001589 if done is None: done = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001590 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1591 writedoc(modname)
1592 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001593
1594class Helper:
Georg Brandl681001e2008-06-01 20:33:55 +00001595
1596 # These dictionaries map a topic name to either an alias, or a tuple
1597 # (label, seealso-items). The "label" is the label of the corresponding
1598 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl43819252009-04-26 09:56:44 +00001599 # in pydoc_data/topics.py.
Georg Brandl681001e2008-06-01 20:33:55 +00001600 #
1601 # CAUTION: if you change one of these dictionaries, be sure to adapt the
1602 # list of needed labels in Doc/tools/sphinxext/pyspecific.py and
Georg Brandl43819252009-04-26 09:56:44 +00001603 # regenerate the pydoc_data/topics.py file by running
Georg Brandl681001e2008-06-01 20:33:55 +00001604 # make pydoc-topics
1605 # in Doc/ and copying the output file into the Lib/ directory.
1606
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001607 keywords = {
1608 'and': 'BOOLEAN',
Georg Brandlb6a87542007-03-13 10:06:48 +00001609 'as': 'with',
Georg Brandl681001e2008-06-01 20:33:55 +00001610 'assert': ('assert', ''),
1611 'break': ('break', 'while for'),
1612 'class': ('class', 'CLASSES SPECIALMETHODS'),
1613 'continue': ('continue', 'while for'),
1614 'def': ('function', ''),
1615 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001616 'elif': 'if',
Georg Brandl681001e2008-06-01 20:33:55 +00001617 'else': ('else', 'while for'),
Georg Brandl5c669db2008-08-30 19:03:43 +00001618 'except': 'try',
Georg Brandl681001e2008-06-01 20:33:55 +00001619 'exec': ('exec', ''),
Georg Brandl5c669db2008-08-30 19:03:43 +00001620 'finally': 'try',
Georg Brandl681001e2008-06-01 20:33:55 +00001621 'for': ('for', 'break continue while'),
Georg Brandl5c669db2008-08-30 19:03:43 +00001622 'from': 'import',
Georg Brandl681001e2008-06-01 20:33:55 +00001623 'global': ('global', 'NAMESPACES'),
1624 'if': ('if', 'TRUTHVALUE'),
1625 'import': ('import', 'MODULES'),
1626 'in': ('in', 'SEQUENCEMETHODS2'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001627 'is': 'COMPARISON',
Georg Brandl681001e2008-06-01 20:33:55 +00001628 'lambda': ('lambda', 'FUNCTIONS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001629 'not': 'BOOLEAN',
1630 'or': 'BOOLEAN',
Georg Brandl681001e2008-06-01 20:33:55 +00001631 'pass': ('pass', ''),
1632 'print': ('print', ''),
1633 'raise': ('raise', 'EXCEPTIONS'),
1634 'return': ('return', 'FUNCTIONS'),
1635 'try': ('try', 'EXCEPTIONS'),
1636 'while': ('while', 'break continue if TRUTHVALUE'),
1637 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1638 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001639 }
Georg Brandlc3a98032008-12-27 18:20:04 +00001640 # Either add symbols to this dictionary or to the symbols dictionary
1641 # directly: Whichever is easier. They are merged later.
1642 _symbols_inverse = {
1643 'STRINGS' : ("'", "'''", "r'", "u'", '"""', '"', 'r"', 'u"'),
1644 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1645 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1646 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1647 'UNARY' : ('-', '~'),
1648 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1649 '^=', '<<=', '>>=', '**=', '//='),
1650 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1651 'COMPLEX' : ('j', 'J')
1652 }
1653 symbols = {
1654 '%': 'OPERATORS FORMATTING',
1655 '**': 'POWER',
1656 ',': 'TUPLES LISTS FUNCTIONS',
1657 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1658 '...': 'ELLIPSIS',
1659 ':': 'SLICINGS DICTIONARYLITERALS',
1660 '@': 'def class',
1661 '\\': 'STRINGS',
1662 '_': 'PRIVATENAMES',
1663 '__': 'PRIVATENAMES SPECIALMETHODS',
1664 '`': 'BACKQUOTES',
1665 '(': 'TUPLES FUNCTIONS CALLS',
1666 ')': 'TUPLES FUNCTIONS CALLS',
1667 '[': 'LISTS SUBSCRIPTS SLICINGS',
1668 ']': 'LISTS SUBSCRIPTS SLICINGS'
1669 }
1670 for topic, symbols_ in _symbols_inverse.iteritems():
1671 for symbol in symbols_:
1672 topics = symbols.get(symbol, topic)
1673 if topic not in topics:
1674 topics = topics + ' ' + topic
1675 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001676
1677 topics = {
Georg Brandl681001e2008-06-01 20:33:55 +00001678 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1679 'FUNCTIONS CLASSES MODULES FILES inspect'),
1680 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS FORMATTING '
1681 'TYPES'),
1682 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1683 'FORMATTING': ('formatstrings', 'OPERATORS'),
1684 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1685 'FORMATTING TYPES'),
1686 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1687 'INTEGER': ('integers', 'int range'),
1688 'FLOAT': ('floating', 'float math'),
1689 'COMPLEX': ('imaginary', 'complex cmath'),
1690 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING xrange LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001691 'MAPPINGS': 'DICTIONARIES',
Georg Brandl681001e2008-06-01 20:33:55 +00001692 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1693 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1694 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1695 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001696 'FRAMEOBJECTS': 'TYPES',
1697 'TRACEBACKS': 'TYPES',
Georg Brandl681001e2008-06-01 20:33:55 +00001698 'NONE': ('bltin-null-object', ''),
1699 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
1700 'FILES': ('bltin-file-objects', ''),
1701 'SPECIALATTRIBUTES': ('specialattrs', ''),
1702 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1703 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001704 'PACKAGES': 'import',
Georg Brandl681001e2008-06-01 20:33:55 +00001705 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1706 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1707 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1708 'LISTS DICTIONARIES BACKQUOTES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001709 'OPERATORS': 'EXPRESSIONS',
1710 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl681001e2008-06-01 20:33:55 +00001711 'OBJECTS': ('objects', 'TYPES'),
1712 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
1713 'CALLABLEMETHODS SEQUENCEMETHODS1 MAPPINGMETHODS '
1714 'SEQUENCEMETHODS2 NUMBERMETHODS CLASSES'),
1715 'BASICMETHODS': ('customization', 'cmp hash repr str SPECIALMETHODS'),
1716 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1717 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
1718 'SEQUENCEMETHODS1': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS2 '
1719 'SPECIALMETHODS'),
1720 'SEQUENCEMETHODS2': ('sequence-methods', 'SEQUENCES SEQUENCEMETHODS1 '
1721 'SPECIALMETHODS'),
1722 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1723 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1724 'SPECIALMETHODS'),
1725 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
1726 'NAMESPACES': ('naming', 'global ASSIGNMENT DELETION DYNAMICFEATURES'),
1727 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001728 'SCOPING': 'NAMESPACES',
1729 'FRAMES': 'NAMESPACES',
Georg Brandl681001e2008-06-01 20:33:55 +00001730 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1731 'COERCIONS': ('coercion-rules','CONVERSIONS'),
1732 'CONVERSIONS': ('conversions', 'COERCIONS'),
1733 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1734 'SPECIALIDENTIFIERS': ('id-classes', ''),
1735 'PRIVATENAMES': ('atom-identifiers', ''),
1736 'LITERALS': ('atom-literals', 'STRINGS BACKQUOTES NUMBERS '
1737 'TUPLELITERALS LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001738 'TUPLES': 'SEQUENCES',
Georg Brandl681001e2008-06-01 20:33:55 +00001739 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1740 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1741 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1742 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1743 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1744 'BACKQUOTES': ('string-conversions', 'repr str STRINGS LITERALS'),
1745 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr '
1746 'ATTRIBUTEMETHODS'),
1747 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS1'),
1748 'SLICINGS': ('slicings', 'SEQUENCEMETHODS2'),
1749 'CALLS': ('calls', 'EXPRESSIONS'),
1750 'POWER': ('power', 'EXPRESSIONS'),
1751 'UNARY': ('unary', 'EXPRESSIONS'),
1752 'BINARY': ('binary', 'EXPRESSIONS'),
1753 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1754 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1755 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1756 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001757 'ASSERTION': 'assert',
Georg Brandl681001e2008-06-01 20:33:55 +00001758 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1759 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001760 'DELETION': 'del',
1761 'PRINTING': 'print',
1762 'RETURNING': 'return',
1763 'IMPORTING': 'import',
1764 'CONDITIONAL': 'if',
Georg Brandl681001e2008-06-01 20:33:55 +00001765 'LOOPING': ('compound', 'for while break continue'),
1766 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1767 'DEBUGGING': ('debugger', 'pdb'),
1768 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001769 }
1770
Georg Brandl004c74d2010-08-01 19:06:51 +00001771 def __init__(self, input=None, output=None):
1772 self._input = input
1773 self._output = output
1774
1775 input = property(lambda self: self._input or sys.stdin)
1776 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001777
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001778 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001779 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001780 self()
1781 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001782 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001783
Alexander Belopolskyd501dde2011-01-11 15:35:23 +00001784 _GoInteractive = object()
1785 def __call__(self, request=_GoInteractive):
1786 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001787 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001788 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001789 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001790 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001791 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001792You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001793If you want to ask for help on a particular object directly from the
1794interpreter, you can type "help(object)". Executing "help('string')"
1795has the same effect as typing a particular string at the help> prompt.
1796''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001797
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001798 def interact(self):
1799 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001800 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001801 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001802 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001803 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001804 except (KeyboardInterrupt, EOFError):
1805 break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001806 request = strip(replace(request, '"', '', "'", ''))
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001807 if lower(request) in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001808 self.help(request)
1809
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001810 def getline(self, prompt):
1811 """Read one line, using raw_input when available."""
1812 if self.input is sys.stdin:
1813 return raw_input(prompt)
1814 else:
1815 self.output.write(prompt)
1816 self.output.flush()
1817 return self.input.readline()
1818
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001819 def help(self, request):
1820 if type(request) is type(''):
R. David Murrayd67ea7d2009-05-27 20:07:21 +00001821 request = request.strip()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001822 if request == 'help': self.intro()
1823 elif request == 'keywords': self.listkeywords()
Georg Brandlc3a98032008-12-27 18:20:04 +00001824 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001825 elif request == 'topics': self.listtopics()
1826 elif request == 'modules': self.listmodules()
1827 elif request[:8] == 'modules ':
1828 self.listmodules(split(request)[1])
Georg Brandlc3a98032008-12-27 18:20:04 +00001829 elif request in self.symbols: self.showsymbol(request)
Raymond Hettinger54f02222002-06-01 14:18:47 +00001830 elif request in self.keywords: self.showtopic(request)
1831 elif request in self.topics: self.showtopic(request)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001832 elif request: doc(request, 'Help on %s:')
1833 elif isinstance(request, Helper): self()
1834 else: doc(request, 'Help on %s:')
1835 self.output.write('\n')
1836
1837 def intro(self):
1838 self.output.write('''
1839Welcome to Python %s! This is the online help utility.
1840
1841If this is your first time using Python, you should definitely check out
R David Murray93a224d2012-03-31 12:10:48 -04001842the tutorial on the Internet at http://docs.python.org/%s/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001843
1844Enter the name of any module, keyword, or topic to get help on writing
1845Python programs and using Python modules. To quit this help utility and
1846return to the interpreter, just type "quit".
1847
1848To get a list of available modules, keywords, or topics, type "modules",
1849"keywords", or "topics". Each module also comes with a one-line summary
1850of what it does; to list the modules whose summaries contain a given word
1851such as "spam", type "modules spam".
R David Murray93a224d2012-03-31 12:10:48 -04001852''' % tuple([sys.version[:3]]*2))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001853
1854 def list(self, items, columns=4, width=80):
1855 items = items[:]
1856 items.sort()
1857 colw = width / columns
1858 rows = (len(items) + columns - 1) / columns
1859 for row in range(rows):
1860 for col in range(columns):
1861 i = col * rows + row
1862 if i < len(items):
1863 self.output.write(items[i])
1864 if col < columns - 1:
1865 self.output.write(' ' + ' ' * (colw-1 - len(items[i])))
1866 self.output.write('\n')
1867
1868 def listkeywords(self):
1869 self.output.write('''
1870Here is a list of the Python keywords. Enter any keyword to get more help.
1871
1872''')
1873 self.list(self.keywords.keys())
1874
Georg Brandlc3a98032008-12-27 18:20:04 +00001875 def listsymbols(self):
1876 self.output.write('''
1877Here is a list of the punctuation symbols which Python assigns special meaning
1878to. Enter any symbol to get more help.
1879
1880''')
1881 self.list(self.symbols.keys())
1882
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001883 def listtopics(self):
1884 self.output.write('''
1885Here is a list of available topics. Enter any topic name to get more help.
1886
1887''')
1888 self.list(self.topics.keys())
1889
Georg Brandlc3a98032008-12-27 18:20:04 +00001890 def showtopic(self, topic, more_xrefs=''):
Georg Brandl681001e2008-06-01 20:33:55 +00001891 try:
Georg Brandl43819252009-04-26 09:56:44 +00001892 import pydoc_data.topics
Georg Brandl681001e2008-06-01 20:33:55 +00001893 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001894 self.output.write('''
Georg Brandl681001e2008-06-01 20:33:55 +00001895Sorry, topic and keyword documentation is not available because the
Georg Brandl43819252009-04-26 09:56:44 +00001896module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001897''')
1898 return
1899 target = self.topics.get(topic, self.keywords.get(topic))
1900 if not target:
1901 self.output.write('no documentation found for %s\n' % repr(topic))
1902 return
1903 if type(target) is type(''):
Georg Brandlc3a98032008-12-27 18:20:04 +00001904 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001905
Georg Brandl681001e2008-06-01 20:33:55 +00001906 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001907 try:
Georg Brandl43819252009-04-26 09:56:44 +00001908 doc = pydoc_data.topics.topics[label]
Georg Brandl681001e2008-06-01 20:33:55 +00001909 except KeyError:
1910 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001911 return
Georg Brandl681001e2008-06-01 20:33:55 +00001912 pager(strip(doc) + '\n')
Georg Brandlc3a98032008-12-27 18:20:04 +00001913 if more_xrefs:
1914 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001915 if xrefs:
Georg Brandl681001e2008-06-01 20:33:55 +00001916 import StringIO, formatter
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001917 buffer = StringIO.StringIO()
1918 formatter.DumbWriter(buffer).send_flowing_data(
1919 'Related help topics: ' + join(split(xrefs), ', ') + '\n')
1920 self.output.write('\n%s\n' % buffer.getvalue())
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001921
Georg Brandlc3a98032008-12-27 18:20:04 +00001922 def showsymbol(self, symbol):
1923 target = self.symbols[symbol]
1924 topic, _, xrefs = target.partition(' ')
1925 self.showtopic(topic, xrefs)
1926
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001927 def listmodules(self, key=''):
1928 if key:
1929 self.output.write('''
1930Here is a list of matching modules. Enter any module name to get more help.
1931
1932''')
1933 apropos(key)
1934 else:
1935 self.output.write('''
1936Please wait a moment while I gather a list of all available modules...
1937
1938''')
1939 modules = {}
1940 def callback(path, modname, desc, modules=modules):
1941 if modname and modname[-9:] == '.__init__':
1942 modname = modname[:-9] + ' (package)'
1943 if find(modname, '.') < 0:
1944 modules[modname] = 1
Ka-Ping Yee9e0f1162008-01-13 11:25:13 +00001945 def onerror(modname):
1946 callback(None, modname, None)
1947 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001948 self.list(modules.keys())
1949 self.output.write('''
1950Enter any module name to get more help. Or, type "modules spam" to search
1951for modules whose descriptions contain the word "spam".
1952''')
1953
Georg Brandl004c74d2010-08-01 19:06:51 +00001954help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001955
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001956class Scanner:
1957 """A generic tree iterator."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001958 def __init__(self, roots, children, descendp):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001959 self.roots = roots[:]
1960 self.state = []
1961 self.children = children
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001962 self.descendp = descendp
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001963
1964 def next(self):
1965 if not self.state:
1966 if not self.roots:
1967 return None
1968 root = self.roots.pop(0)
1969 self.state = [(root, self.children(root))]
1970 node, children = self.state[-1]
1971 if not children:
1972 self.state.pop()
1973 return self.next()
1974 child = children.pop(0)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001975 if self.descendp(child):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001976 self.state.append((child, self.children(child)))
1977 return child
1978
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001979
1980class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001981 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001982
Ka-Ping Yee9e0f1162008-01-13 11:25:13 +00001983 def run(self, callback, key=None, completer=None, onerror=None):
Ka-Ping Yee66246962001-04-12 11:59:50 +00001984 if key: key = lower(key)
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001985 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001986 seen = {}
1987
1988 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001989 if modname != '__main__':
1990 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00001991 if key is None:
1992 callback(None, modname, '')
1993 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001994 desc = split(__import__(modname).__doc__ or '', '\n')[0]
Ka-Ping Yee66246962001-04-12 11:59:50 +00001995 if find(lower(modname + ' - ' + desc), key) >= 0:
1996 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001997
Ka-Ping Yee9e0f1162008-01-13 11:25:13 +00001998 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001999 if self.quit:
2000 break
2001 if key is None:
2002 callback(None, modname, '')
2003 else:
2004 loader = importer.find_module(modname)
2005 if hasattr(loader,'get_source'):
2006 import StringIO
2007 desc = source_synopsis(
2008 StringIO.StringIO(loader.get_source(modname))
2009 ) or ''
2010 if hasattr(loader,'get_filename'):
2011 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002012 else:
Phillip J. Ebyceb30872006-04-18 00:59:55 +00002013 path = None
2014 else:
2015 module = loader.load_module(modname)
2016 desc = (module.__doc__ or '').splitlines()[0]
2017 path = getattr(module,'__file__',None)
2018 if find(lower(modname + ' - ' + desc), key) >= 0:
2019 callback(path, modname, desc)
2020
2021 if completer:
2022 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002023
2024def apropos(key):
2025 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002026 def callback(path, modname, desc):
2027 if modname[-9:] == '.__init__':
2028 modname = modname[:-9] + ' (package)'
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002029 print modname, desc and '- ' + desc
Ned Deily0096fb52011-10-06 14:17:44 -07002030 def onerror(modname):
2031 pass
2032 with warnings.catch_warnings():
2033 warnings.filterwarnings('ignore') # ignore problems during import
2034 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002035
2036# --------------------------------------------------- web browser interface
2037
Ka-Ping Yee66246962001-04-12 11:59:50 +00002038def serve(port, callback=None, completer=None):
Ka-Ping Yeefd540692001-04-12 12:54:36 +00002039 import BaseHTTPServer, mimetools, select
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002040
2041 # Patch up mimetools.Message so it doesn't break if rfc822 is reloaded.
2042 class Message(mimetools.Message):
2043 def __init__(self, fp, seekable=1):
2044 Message = self.__class__
2045 Message.__bases__[0].__bases__[0].__init__(self, fp, seekable)
2046 self.encodingheader = self.getheader('content-transfer-encoding')
2047 self.typeheader = self.getheader('content-type')
2048 self.parsetype()
2049 self.parseplist()
2050
2051 class DocHandler(BaseHTTPServer.BaseHTTPRequestHandler):
2052 def send_document(self, title, contents):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002053 try:
2054 self.send_response(200)
2055 self.send_header('Content-Type', 'text/html')
2056 self.end_headers()
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002057 self.wfile.write(html.page(title, contents))
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002058 except IOError: pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002059
2060 def do_GET(self):
2061 path = self.path
2062 if path[-5:] == '.html': path = path[:-5]
2063 if path[:1] == '/': path = path[1:]
2064 if path and path != '.':
2065 try:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00002066 obj = locate(path, forceload=1)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002067 except ErrorDuringImport, value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002068 self.send_document(path, html.escape(str(value)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002069 return
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002070 if obj:
2071 self.send_document(describe(obj), html.document(obj, path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002072 else:
2073 self.send_document(path,
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002074'no Python documentation found for %s' % repr(path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002075 else:
2076 heading = html.heading(
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002077'<big><big><strong>Python: Index of Modules</strong></big></big>',
2078'#ffffff', '#7799ee')
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002079 def bltinlink(name):
2080 return '<a href="%s.html">%s</a>' % (name, name)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002081 names = filter(lambda x: x != '__main__',
2082 sys.builtin_module_names)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002083 contents = html.multicolumn(names, bltinlink)
2084 indices = ['<p>' + html.bigsection(
2085 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2086
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002087 seen = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +00002088 for dir in sys.path:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002089 indices.append(html.index(dir, seen))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002090 contents = heading + join(indices) + '''<p align=right>
Tim Peters2306d242001-09-25 03:18:32 +00002091<font color="#909090" face="helvetica, arial"><strong>
2092pydoc</strong> by Ka-Ping Yee &lt;ping@lfw.org&gt;</font>'''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002093 self.send_document('Index of Modules', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002094
2095 def log_message(self, *args): pass
2096
Ka-Ping Yeefd540692001-04-12 12:54:36 +00002097 class DocServer(BaseHTTPServer.HTTPServer):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002098 def __init__(self, port, callback):
Ronald Oussoren9545a232010-05-05 19:09:31 +00002099 host = 'localhost'
Senthil Kumaranaa895452010-08-18 19:35:53 +00002100 self.address = (host, port)
Ka-Ping Yeedb8ed152001-03-02 05:58:17 +00002101 self.url = 'http://%s:%d/' % (host, port)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002102 self.callback = callback
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002103 self.base.__init__(self, self.address, self.handler)
2104
2105 def serve_until_quit(self):
2106 import select
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002107 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002108 while not self.quit:
2109 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2110 if rd: self.handle_request()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002111
2112 def server_activate(self):
2113 self.base.server_activate(self)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002114 if self.callback: self.callback(self)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002115
2116 DocServer.base = BaseHTTPServer.HTTPServer
2117 DocServer.handler = DocHandler
2118 DocHandler.MessageClass = Message
2119 try:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002120 try:
2121 DocServer(port, callback).serve_until_quit()
2122 except (KeyboardInterrupt, select.error):
2123 pass
2124 finally:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002125 if completer: completer()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002126
2127# ----------------------------------------------------- graphical interface
2128
2129def gui():
2130 """Graphical interface (starts web server and pops up a control window)."""
2131 class GUI:
2132 def __init__(self, window, port=7464):
2133 self.window = window
2134 self.server = None
2135 self.scanner = None
2136
Georg Brandl6634bf22008-05-20 07:13:37 +00002137 import Tkinter
2138 self.server_frm = Tkinter.Frame(window)
2139 self.title_lbl = Tkinter.Label(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002140 text='Starting server...\n ')
Georg Brandl6634bf22008-05-20 07:13:37 +00002141 self.open_btn = Tkinter.Button(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002142 text='open browser', command=self.open, state='disabled')
Georg Brandl6634bf22008-05-20 07:13:37 +00002143 self.quit_btn = Tkinter.Button(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002144 text='quit serving', command=self.quit, state='disabled')
2145
Georg Brandl6634bf22008-05-20 07:13:37 +00002146 self.search_frm = Tkinter.Frame(window)
2147 self.search_lbl = Tkinter.Label(self.search_frm, text='Search for')
2148 self.search_ent = Tkinter.Entry(self.search_frm)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002149 self.search_ent.bind('<Return>', self.search)
Georg Brandl6634bf22008-05-20 07:13:37 +00002150 self.stop_btn = Tkinter.Button(self.search_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002151 text='stop', pady=0, command=self.stop, state='disabled')
2152 if sys.platform == 'win32':
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002153 # Trying to hide and show this button crashes under Windows.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002154 self.stop_btn.pack(side='right')
2155
2156 self.window.title('pydoc')
2157 self.window.protocol('WM_DELETE_WINDOW', self.quit)
2158 self.title_lbl.pack(side='top', fill='x')
2159 self.open_btn.pack(side='left', fill='x', expand=1)
2160 self.quit_btn.pack(side='right', fill='x', expand=1)
2161 self.server_frm.pack(side='top', fill='x')
2162
2163 self.search_lbl.pack(side='left')
2164 self.search_ent.pack(side='right', fill='x', expand=1)
2165 self.search_frm.pack(side='top', fill='x')
2166 self.search_ent.focus_set()
2167
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002168 font = ('helvetica', sys.platform == 'win32' and 8 or 10)
Georg Brandl6634bf22008-05-20 07:13:37 +00002169 self.result_lst = Tkinter.Listbox(window, font=font, height=6)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002170 self.result_lst.bind('<Button-1>', self.select)
2171 self.result_lst.bind('<Double-Button-1>', self.goto)
Georg Brandl6634bf22008-05-20 07:13:37 +00002172 self.result_scr = Tkinter.Scrollbar(window,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002173 orient='vertical', command=self.result_lst.yview)
2174 self.result_lst.config(yscrollcommand=self.result_scr.set)
2175
Georg Brandl6634bf22008-05-20 07:13:37 +00002176 self.result_frm = Tkinter.Frame(window)
2177 self.goto_btn = Tkinter.Button(self.result_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002178 text='go to selected', command=self.goto)
Georg Brandl6634bf22008-05-20 07:13:37 +00002179 self.hide_btn = Tkinter.Button(self.result_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002180 text='hide results', command=self.hide)
2181 self.goto_btn.pack(side='left', fill='x', expand=1)
2182 self.hide_btn.pack(side='right', fill='x', expand=1)
2183
2184 self.window.update()
2185 self.minwidth = self.window.winfo_width()
2186 self.minheight = self.window.winfo_height()
2187 self.bigminheight = (self.server_frm.winfo_reqheight() +
2188 self.search_frm.winfo_reqheight() +
2189 self.result_lst.winfo_reqheight() +
2190 self.result_frm.winfo_reqheight())
2191 self.bigwidth, self.bigheight = self.minwidth, self.bigminheight
2192 self.expanded = 0
2193 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2194 self.window.wm_minsize(self.minwidth, self.minheight)
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002195 self.window.tk.willdispatch()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002196
2197 import threading
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002198 threading.Thread(
2199 target=serve, args=(port, self.ready, self.quit)).start()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002200
2201 def ready(self, server):
2202 self.server = server
2203 self.title_lbl.config(
2204 text='Python documentation server at\n' + server.url)
2205 self.open_btn.config(state='normal')
2206 self.quit_btn.config(state='normal')
2207
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002208 def open(self, event=None, url=None):
2209 url = url or self.server.url
2210 try:
2211 import webbrowser
2212 webbrowser.open(url)
2213 except ImportError: # pre-webbrowser.py compatibility
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002214 if sys.platform == 'win32':
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002215 os.system('start "%s"' % url)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002216 else:
2217 rc = os.system('netscape -remote "openURL(%s)" &' % url)
2218 if rc: os.system('netscape "%s" &' % url)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002219
2220 def quit(self, event=None):
2221 if self.server:
2222 self.server.quit = 1
2223 self.window.quit()
2224
2225 def search(self, event=None):
2226 key = self.search_ent.get()
2227 self.stop_btn.pack(side='right')
2228 self.stop_btn.config(state='normal')
2229 self.search_lbl.config(text='Searching for "%s"...' % key)
2230 self.search_ent.forget()
2231 self.search_lbl.pack(side='left')
2232 self.result_lst.delete(0, 'end')
2233 self.goto_btn.config(state='disabled')
2234 self.expand()
2235
2236 import threading
2237 if self.scanner:
2238 self.scanner.quit = 1
2239 self.scanner = ModuleScanner()
2240 threading.Thread(target=self.scanner.run,
Ka-Ping Yee6dcfa382001-04-12 20:27:31 +00002241 args=(self.update, key, self.done)).start()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002242
2243 def update(self, path, modname, desc):
2244 if modname[-9:] == '.__init__':
2245 modname = modname[:-9] + ' (package)'
2246 self.result_lst.insert('end',
2247 modname + ' - ' + (desc or '(no description)'))
2248
2249 def stop(self, event=None):
2250 if self.scanner:
2251 self.scanner.quit = 1
2252 self.scanner = None
2253
2254 def done(self):
2255 self.scanner = None
2256 self.search_lbl.config(text='Search for')
2257 self.search_lbl.pack(side='left')
2258 self.search_ent.pack(side='right', fill='x', expand=1)
2259 if sys.platform != 'win32': self.stop_btn.forget()
2260 self.stop_btn.config(state='disabled')
2261
2262 def select(self, event=None):
2263 self.goto_btn.config(state='normal')
2264
2265 def goto(self, event=None):
2266 selection = self.result_lst.curselection()
2267 if selection:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002268 modname = split(self.result_lst.get(selection[0]))[0]
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002269 self.open(url=self.server.url + modname + '.html')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002270
2271 def collapse(self):
2272 if not self.expanded: return
2273 self.result_frm.forget()
2274 self.result_scr.forget()
2275 self.result_lst.forget()
2276 self.bigwidth = self.window.winfo_width()
2277 self.bigheight = self.window.winfo_height()
2278 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2279 self.window.wm_minsize(self.minwidth, self.minheight)
2280 self.expanded = 0
2281
2282 def expand(self):
2283 if self.expanded: return
2284 self.result_frm.pack(side='bottom', fill='x')
2285 self.result_scr.pack(side='right', fill='y')
2286 self.result_lst.pack(side='top', fill='both', expand=1)
2287 self.window.wm_geometry('%dx%d' % (self.bigwidth, self.bigheight))
2288 self.window.wm_minsize(self.minwidth, self.bigminheight)
2289 self.expanded = 1
2290
2291 def hide(self, event=None):
2292 self.stop()
2293 self.collapse()
2294
Georg Brandl6634bf22008-05-20 07:13:37 +00002295 import Tkinter
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002296 try:
Georg Brandl6634bf22008-05-20 07:13:37 +00002297 root = Tkinter.Tk()
Martin v. Löwise09bd932004-08-22 16:13:26 +00002298 # Tk will crash if pythonw.exe has an XP .manifest
2299 # file and the root has is not destroyed explicitly.
2300 # If the problem is ever fixed in Tk, the explicit
2301 # destroy can go.
2302 try:
2303 gui = GUI(root)
2304 root.mainloop()
2305 finally:
2306 root.destroy()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002307 except KeyboardInterrupt:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002308 pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002309
2310# -------------------------------------------------- command-line interface
2311
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002312def ispath(x):
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002313 return isinstance(x, str) and find(x, os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002314
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002315def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002316 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002317 import getopt
2318 class BadUsage: pass
2319
Nick Coghlan11db64e2009-11-15 22:36:47 +00002320 # Scripts don't get the current directory in their path by default
2321 # unless they are run with the '-m' switch
2322 if '' not in sys.path:
2323 scriptdir = os.path.dirname(sys.argv[0])
2324 if scriptdir in sys.path:
2325 sys.path.remove(scriptdir)
2326 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002327
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002328 try:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002329 opts, args = getopt.getopt(sys.argv[1:], 'gk:p:w')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002330 writing = 0
2331
2332 for opt, val in opts:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002333 if opt == '-g':
2334 gui()
2335 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002336 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002337 apropos(val)
2338 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002339 if opt == '-p':
2340 try:
2341 port = int(val)
2342 except ValueError:
2343 raise BadUsage
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002344 def ready(server):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002345 print 'pydoc server ready at %s' % server.url
2346 def stopped():
2347 print 'pydoc server stopped'
2348 serve(port, ready, stopped)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002349 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002350 if opt == '-w':
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002351 writing = 1
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002352
2353 if not args: raise BadUsage
2354 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002355 if ispath(arg) and not os.path.exists(arg):
2356 print 'file %r does not exist' % arg
2357 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002358 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002359 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002360 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002361 if writing:
2362 if ispath(arg) and os.path.isdir(arg):
2363 writedocs(arg)
2364 else:
2365 writedoc(arg)
2366 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002367 help.help(arg)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002368 except ErrorDuringImport, value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002369 print value
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002370
2371 except (getopt.error, BadUsage):
Martin v. Löwisf9b08b82003-10-31 13:05:21 +00002372 cmd = os.path.basename(sys.argv[0])
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002373 print """pydoc - the Python documentation tool
2374
2375%s <name> ...
2376 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002377 Python keyword, topic, function, module, or package, or a dotted
2378 reference to a class or function within a module or module in a
2379 package. If <name> contains a '%s', it is used as the path to a
2380 Python source file to document. If name is 'keywords', 'topics',
2381 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002382
2383%s -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002384 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002385
2386%s -p <port>
2387 Start an HTTP server on the given port on the local machine.
2388
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002389%s -g
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002390 Pop up a graphical interface for finding and serving documentation.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002391
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002392%s -w <name> ...
2393 Write out the HTML documentation for a module to a file in the current
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002394 directory. If <name> contains a '%s', it is treated as a filename; if
2395 it names a directory, documentation is written for all the contents.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002396""" % (cmd, os.sep, cmd, cmd, cmd, cmd, os.sep)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002397
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002398if __name__ == '__main__': cli()