blob: 160ad4acf7dcc9f6a7afc446bddcf286cf645fc6 [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)))
584 elif text[end:end+1] == '(':
585 results.append(self.namelink(name, methods, funcs, classes))
586 elif selfdot:
587 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000588 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000589 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000590 here = end
591 results.append(escape(text[here:]))
592 return join(results, '')
593
594 # ---------------------------------------------- type-specific routines
595
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000596 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000597 """Produce HTML for a class tree as given by inspect.getclasstree()."""
598 result = ''
599 for entry in tree:
600 if type(entry) is type(()):
601 c, bases = entry
Tim Peters2306d242001-09-25 03:18:32 +0000602 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000603 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000604 if bases and bases != (parent,):
605 parents = []
606 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000607 parents.append(self.classlink(base, modname))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000608 result = result + '(' + join(parents, ', ') + ')'
Tim Peters2306d242001-09-25 03:18:32 +0000609 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000610 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000611 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000612 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000613 return '<dl>\n%s</dl>\n' % result
614
Tim Peters8dd7ade2001-10-18 19:56:17 +0000615 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000616 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000617 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000618 try:
619 all = object.__all__
620 except AttributeError:
621 all = None
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000622 parts = split(name, '.')
623 links = []
624 for i in range(len(parts)-1):
625 links.append(
626 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
627 (join(parts[:i+1], '.'), parts[i]))
628 linkedname = join(links + parts[-1:], '.')
629 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000630 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000631 path = inspect.getabsfile(object)
Ka-Ping Yee6191a232001-04-13 15:00:27 +0000632 url = path
633 if sys.platform == 'win32':
634 import nturl2path
635 url = nturl2path.pathname2url(path)
636 filelink = '<a href="file:%s">%s</a>' % (url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000637 except TypeError:
638 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000639 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000640 if hasattr(object, '__version__'):
R David Murray984f6302014-01-05 12:35:59 -0500641 version = _binstr(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000642 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
643 version = strip(version[11:-1])
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000644 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000645 if hasattr(object, '__date__'):
R David Murray984f6302014-01-05 12:35:59 -0500646 info.append(self.escape(_binstr(object.__date__)))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000647 if info:
648 head = head + ' (%s)' % join(info, ', ')
Skip Montanaro4997a692003-09-10 16:47:51 +0000649 docloc = self.getdocloc(object)
650 if docloc is not None:
651 docloc = '<br><a href="%(docloc)s">Module Docs</a>' % locals()
652 else:
653 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000654 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000655 head, '#ffffff', '#7799ee',
656 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000657
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000658 modules = inspect.getmembers(object, inspect.ismodule)
659
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000660 classes, cdict = [], {}
661 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000662 # if __all__ exists, believe it. Otherwise use old heuristic.
663 if (all is not None or
664 (inspect.getmodule(value) or object) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700665 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000666 classes.append((key, value))
667 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000668 for key, value in classes:
669 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000670 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000671 module = sys.modules.get(modname)
672 if modname != name and module and hasattr(module, key):
673 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000674 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000675 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000676 funcs, fdict = [], {}
677 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000678 # if __all__ exists, believe it. Otherwise use old heuristic.
679 if (all is not None or
680 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700681 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000682 funcs.append((key, value))
683 fdict[key] = '#-' + key
684 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000685 data = []
686 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700687 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000688 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000689
690 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
691 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000692 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000693
694 if hasattr(object, '__path__'):
695 modpkgs = []
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000696 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
697 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000698 modpkgs.sort()
699 contents = self.multicolumn(modpkgs, self.modpkglink)
700 result = result + self.bigsection(
701 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000702 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000703 contents = self.multicolumn(
Brett Cannonaca98b02008-08-03 00:58:51 +0000704 modules, lambda key_value, s=self: s.modulelink(key_value[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000705 result = result + self.bigsection(
Georg Brandlb169eaa2008-02-17 21:18:55 +0000706 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000707
708 if classes:
Brett Cannonaca98b02008-08-03 00:58:51 +0000709 classlist = map(lambda key_value: key_value[1], classes)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000710 contents = [
711 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000712 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000713 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000714 result = result + self.bigsection(
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000715 'Classes', '#ffffff', '#ee77aa', join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000716 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000717 contents = []
718 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000719 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000720 result = result + self.bigsection(
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000721 'Functions', '#ffffff', '#eeaa77', join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000722 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000723 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000724 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000725 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000726 result = result + self.bigsection(
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000727 'Data', '#ffffff', '#55aa55', join(contents, '<br>\n'))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000728 if hasattr(object, '__author__'):
R David Murray984f6302014-01-05 12:35:59 -0500729 contents = self.markup(_binstr(object.__author__), self.preformat)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000730 result = result + self.bigsection(
731 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000732 if hasattr(object, '__credits__'):
R David Murray984f6302014-01-05 12:35:59 -0500733 contents = self.markup(_binstr(object.__credits__), self.preformat)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000734 result = result + self.bigsection(
735 'Credits', '#ffffff', '#7799ee', contents)
736
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000737 return result
738
Tim Peters8dd7ade2001-10-18 19:56:17 +0000739 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
740 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000741 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000742 realname = object.__name__
743 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000744 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000745
Tim Petersb47879b2001-09-24 04:47:19 +0000746 contents = []
747 push = contents.append
748
Tim Petersfa26f7c2001-09-24 08:05:11 +0000749 # Cute little class to pump out a horizontal rule between sections.
750 class HorizontalRule:
751 def __init__(self):
752 self.needone = 0
753 def maybe(self):
754 if self.needone:
755 push('<hr>\n')
756 self.needone = 1
757 hr = HorizontalRule()
758
Tim Petersc86f6ca2001-09-26 21:31:51 +0000759 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000760 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000761 if len(mro) > 2:
762 hr.maybe()
763 push('<dl><dt>Method resolution order:</dt>\n')
764 for base in mro:
765 push('<dd>%s</dd>\n' % self.classlink(base,
766 object.__module__))
767 push('</dl>\n')
768
Tim Petersb47879b2001-09-24 04:47:19 +0000769 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000770 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000771 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000772 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000773 push(msg)
774 for name, kind, homecls, value in ok:
Antoine Pitroub8572a12011-12-21 10:16:14 +0100775 try:
776 value = getattr(object, name)
777 except Exception:
778 # Some descriptors may meet a failure in their __get__.
779 # (bug #1785)
780 push(self._docdescriptor(name, value, mod))
781 else:
782 push(self.document(value, name, mod,
783 funcs, classes, mdict, object))
Tim Petersb47879b2001-09-24 04:47:19 +0000784 push('\n')
785 return attrs
786
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000787 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000788 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000789 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000790 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000791 push(msg)
792 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000793 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000794 return attrs
795
Tim Petersfa26f7c2001-09-24 08:05:11 +0000796 def spilldata(msg, attrs, predicate):
797 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000798 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000799 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000800 push(msg)
801 for name, kind, homecls, value in ok:
802 base = self.docother(getattr(object, name), name, mod)
Brett Cannonaca98b02008-08-03 00:58:51 +0000803 if (hasattr(value, '__call__') or
804 inspect.isdatadescriptor(value)):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000805 doc = getattr(value, "__doc__", None)
806 else:
807 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000808 if doc is None:
809 push('<dl><dt>%s</dl>\n' % base)
810 else:
811 doc = self.markup(getdoc(value), self.preformat,
812 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000813 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000814 push('<dl><dt>%s%s</dl>\n' % (base, doc))
815 push('\n')
816 return attrs
817
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700818 attrs = filter(lambda data: visiblename(data[0], obj=object),
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000819 classify_class_attrs(object))
Tim Petersb47879b2001-09-24 04:47:19 +0000820 mdict = {}
821 for key, kind, homecls, value in attrs:
822 mdict[key] = anchor = '#' + name + '-' + key
Antoine Pitroub8572a12011-12-21 10:16:14 +0100823 try:
824 value = getattr(object, name)
825 except Exception:
826 # Some descriptors may meet a failure in their __get__.
827 # (bug #1785)
828 pass
Tim Petersb47879b2001-09-24 04:47:19 +0000829 try:
830 # The value may not be hashable (e.g., a data attr with
831 # a dict or list value).
832 mdict[value] = anchor
833 except TypeError:
834 pass
835
Tim Petersfa26f7c2001-09-24 08:05:11 +0000836 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000837 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000838 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000839 else:
840 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000841 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
842
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000843 if thisclass is __builtin__.object:
844 attrs = inherited
845 continue
846 elif thisclass is object:
847 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000848 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000849 tag = 'inherited from %s' % self.classlink(thisclass,
850 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000851 tag += ':<br>\n'
852
853 # Sort attrs by name.
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000854 try:
855 attrs.sort(key=lambda t: t[0])
856 except TypeError:
857 attrs.sort(lambda t1, t2: cmp(t1[0], t2[0])) # 2.3 compat
Tim Petersb47879b2001-09-24 04:47:19 +0000858
859 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000860 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000861 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000862 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000863 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000864 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000865 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000866 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
867 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000868 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000869 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000870 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000871 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000872
873 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000874
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000875 if name == realname:
876 title = '<a name="%s">class <strong>%s</strong></a>' % (
877 name, realname)
878 else:
879 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
880 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000881 if bases:
882 parents = []
883 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000884 parents.append(self.classlink(base, object.__module__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000885 title = title + '(%s)' % join(parents, ', ')
Tim Peters2306d242001-09-25 03:18:32 +0000886 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000887 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000888
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000889 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000890
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000891 def formatvalue(self, object):
892 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000893 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000894
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000895 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000896 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000897 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000898 realname = object.__name__
899 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000900 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000901 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000902 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000903 if inspect.ismethod(object):
Ka-Ping Yee6dcfa382001-04-12 20:27:31 +0000904 imclass = object.im_class
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000905 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000906 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000907 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000908 else:
Georg Brandl7e2b6bb2007-03-13 22:16:30 +0000909 if object.im_self is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000910 note = ' method of %s instance' % self.classlink(
911 object.im_self.__class__, mod)
912 else:
913 note = ' unbound %s method' % self.classlink(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000914 object = object.im_func
915
916 if name == realname:
917 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
918 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000919 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000920 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000921 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000922 cl.__name__ + '-' + realname, realname)
923 skipdocs = 1
924 else:
925 reallink = realname
926 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
927 anchor, name, reallink)
Tim Peters4bcfa312001-09-20 06:08:24 +0000928 if inspect.isfunction(object):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000929 args, varargs, varkw, defaults = inspect.getargspec(object)
930 argspec = inspect.formatargspec(
931 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000932 if realname == '<lambda>':
Tim Peters59ed4482001-10-31 04:20:26 +0000933 title = '<strong>%s</strong> <em>lambda</em> ' % name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000934 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +0000935 else:
936 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000937
Tim Peters2306d242001-09-25 03:18:32 +0000938 decl = title + argspec + (note and self.grey(
939 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000940
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000941 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000942 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000943 else:
944 doc = self.markup(
945 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000946 doc = doc and '<dd><tt>%s</tt></dd>' % doc
947 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000948
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000949 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000950 results = []
951 push = results.append
952
953 if name:
954 push('<dl><dt><strong>%s</strong></dt>\n' % name)
955 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000956 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000957 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000958 push('</dl>\n')
959
960 return ''.join(results)
961
962 def docproperty(self, object, name=None, mod=None, cl=None):
963 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000964 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000965
Tim Peters8dd7ade2001-10-18 19:56:17 +0000966 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000967 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000968 lhs = name and '<strong>%s</strong> = ' % name or ''
969 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000970
Barry Warsaw00decd72006-07-27 23:43:15 +0000971 def docdata(self, object, name=None, mod=None, cl=None):
972 """Produce html documentation for a data descriptor."""
973 return self._docdescriptor(name, object, mod)
974
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000975 def index(self, dir, shadowed=None):
976 """Generate an HTML index for a directory of modules."""
977 modpkgs = []
978 if shadowed is None: shadowed = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000979 for importer, name, ispkg in pkgutil.iter_modules([dir]):
980 modpkgs.append((name, '', ispkg, name in shadowed))
981 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000982
983 modpkgs.sort()
984 contents = self.multicolumn(modpkgs, self.modpkglink)
985 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
986
987# -------------------------------------------- text documentation generator
988
989class TextRepr(Repr):
990 """Class for safely making a text representation of a Python object."""
991 def __init__(self):
992 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000993 self.maxlist = self.maxtuple = 20
994 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000995 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000996
997 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000998 if hasattr(type(x), '__name__'):
999 methodname = 'repr_' + join(split(type(x).__name__), '_')
1000 if hasattr(self, methodname):
1001 return getattr(self, methodname)(x, level)
1002 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001003
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001004 def repr_string(self, x, level):
1005 test = cram(x, self.maxstring)
1006 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001007 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001008 # Backslashes are only literal in the string and are never
1009 # needed to make any special characters, so show a raw string.
1010 return 'r' + testrepr[0] + test + testrepr[0]
1011 return testrepr
1012
Skip Montanarodf708782002-03-07 22:58:02 +00001013 repr_str = repr_string
1014
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001015 def repr_instance(self, x, level):
1016 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001017 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001018 except:
1019 return '<%s instance>' % x.__class__.__name__
1020
1021class TextDoc(Doc):
1022 """Formatter class for text documentation."""
1023
1024 # ------------------------------------------- text formatting utilities
1025
1026 _repr_instance = TextRepr()
1027 repr = _repr_instance.repr
1028
1029 def bold(self, text):
1030 """Format a string in bold by overstriking."""
1031 return join(map(lambda ch: ch + '\b' + ch, text), '')
1032
1033 def indent(self, text, prefix=' '):
1034 """Indent text by prepending a given prefix to each line."""
1035 if not text: return ''
1036 lines = split(text, '\n')
1037 lines = map(lambda line, prefix=prefix: prefix + line, lines)
1038 if lines: lines[-1] = rstrip(lines[-1])
1039 return join(lines, '\n')
1040
1041 def section(self, title, contents):
1042 """Format a section with a given heading."""
1043 return self.bold(title) + '\n' + rstrip(self.indent(contents)) + '\n\n'
1044
1045 # ---------------------------------------------- type-specific routines
1046
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001047 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001048 """Render in text a class tree as returned by inspect.getclasstree()."""
1049 result = ''
1050 for entry in tree:
1051 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001052 c, bases = entry
1053 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001054 if bases and bases != (parent,):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001055 parents = map(lambda c, m=modname: classname(c, m), bases)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001056 result = result + '(%s)' % join(parents, ', ')
1057 result = result + '\n'
1058 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001059 result = result + self.formattree(
1060 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001061 return result
1062
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001063 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001064 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001065 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001066 synop, desc = splitdoc(getdoc(object))
1067 result = self.section('NAME', name + (synop and ' - ' + synop))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001068
1069 try:
Skip Montanaroa5616d22004-06-11 04:46:12 +00001070 all = object.__all__
1071 except AttributeError:
1072 all = None
1073
1074 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001075 file = inspect.getabsfile(object)
1076 except TypeError:
1077 file = '(built-in)'
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001078 result = result + self.section('FILE', file)
Skip Montanaro4997a692003-09-10 16:47:51 +00001079
1080 docloc = self.getdocloc(object)
1081 if docloc is not None:
1082 result = result + self.section('MODULE DOCS', docloc)
1083
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001084 if desc:
1085 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001086
1087 classes = []
1088 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001089 # if __all__ exists, believe it. Otherwise use old heuristic.
1090 if (all is not None
1091 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001092 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001093 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001094 funcs = []
1095 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001096 # if __all__ exists, believe it. Otherwise use old heuristic.
1097 if (all is not None or
1098 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001099 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001100 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001101 data = []
1102 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001103 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001104 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001105
Georg Brandlf2dae0e2008-01-21 21:05:49 +00001106 modpkgs = []
1107 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001108 if hasattr(object, '__path__'):
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001109 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Georg Brandlf2dae0e2008-01-21 21:05:49 +00001110 modpkgs_names.add(modname)
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001111 if ispkg:
1112 modpkgs.append(modname + ' (package)')
1113 else:
1114 modpkgs.append(modname)
1115
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001116 modpkgs.sort()
1117 result = result + self.section(
1118 'PACKAGE CONTENTS', join(modpkgs, '\n'))
1119
Georg Brandlf2dae0e2008-01-21 21:05:49 +00001120 # Detect submodules as sometimes created by C extensions
1121 submodules = []
1122 for key, value in inspect.getmembers(object, inspect.ismodule):
1123 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1124 submodules.append(key)
1125 if submodules:
1126 submodules.sort()
1127 result = result + self.section(
1128 'SUBMODULES', join(submodules, '\n'))
1129
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001130 if classes:
Brett Cannonaca98b02008-08-03 00:58:51 +00001131 classlist = map(lambda key_value: key_value[1], classes)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001132 contents = [self.formattree(
1133 inspect.getclasstree(classlist, 1), name)]
1134 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001135 contents.append(self.document(value, key, name))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001136 result = result + self.section('CLASSES', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001137
1138 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001139 contents = []
1140 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001141 contents.append(self.document(value, key, name))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001142 result = result + self.section('FUNCTIONS', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001143
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001144 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001145 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001146 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001147 contents.append(self.docother(value, key, name, maxlen=70))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001148 result = result + self.section('DATA', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001149
1150 if hasattr(object, '__version__'):
R David Murray984f6302014-01-05 12:35:59 -05001151 version = _binstr(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001152 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
1153 version = strip(version[11:-1])
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001154 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001155 if hasattr(object, '__date__'):
R David Murray984f6302014-01-05 12:35:59 -05001156 result = result + self.section('DATE', _binstr(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001157 if hasattr(object, '__author__'):
R David Murray984f6302014-01-05 12:35:59 -05001158 result = result + self.section('AUTHOR', _binstr(object.__author__))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001159 if hasattr(object, '__credits__'):
R David Murray984f6302014-01-05 12:35:59 -05001160 result = result + self.section('CREDITS', _binstr(object.__credits__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001161 return result
1162
Georg Brandl52f83952011-02-25 10:39:23 +00001163 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001164 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001165 realname = object.__name__
1166 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001167 bases = object.__bases__
1168
Tim Petersc86f6ca2001-09-26 21:31:51 +00001169 def makename(c, m=object.__module__):
1170 return classname(c, m)
1171
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001172 if name == realname:
1173 title = 'class ' + self.bold(realname)
1174 else:
1175 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001176 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001177 parents = map(makename, bases)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001178 title = title + '(%s)' % join(parents, ', ')
1179
1180 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001181 contents = doc and [doc + '\n'] or []
1182 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001183
Tim Petersc86f6ca2001-09-26 21:31:51 +00001184 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001185 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001186 if len(mro) > 2:
1187 push("Method resolution order:")
1188 for base in mro:
1189 push(' ' + makename(base))
1190 push('')
1191
Tim Petersf4aad8e2001-09-24 22:40:47 +00001192 # Cute little class to pump out a horizontal rule between sections.
1193 class HorizontalRule:
1194 def __init__(self):
1195 self.needone = 0
1196 def maybe(self):
1197 if self.needone:
1198 push('-' * 70)
1199 self.needone = 1
1200 hr = HorizontalRule()
1201
Tim Peters28355492001-09-23 21:29:55 +00001202 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001203 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001204 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001205 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001206 push(msg)
1207 for name, kind, homecls, value in ok:
Antoine Pitroub8572a12011-12-21 10:16:14 +01001208 try:
1209 value = getattr(object, name)
1210 except Exception:
1211 # Some descriptors may meet a failure in their __get__.
1212 # (bug #1785)
1213 push(self._docdescriptor(name, value, mod))
1214 else:
1215 push(self.document(value,
1216 name, mod, object))
Tim Peters28355492001-09-23 21:29:55 +00001217 return attrs
1218
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001219 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001220 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001221 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001222 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001223 push(msg)
1224 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001225 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001226 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001227
Tim Petersfa26f7c2001-09-24 08:05:11 +00001228 def spilldata(msg, attrs, predicate):
1229 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001230 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001231 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001232 push(msg)
1233 for name, kind, homecls, value in ok:
Brett Cannonaca98b02008-08-03 00:58:51 +00001234 if (hasattr(value, '__call__') or
1235 inspect.isdatadescriptor(value)):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001236 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001237 else:
1238 doc = None
Tim Peters28355492001-09-23 21:29:55 +00001239 push(self.docother(getattr(object, name),
Georg Brandl8b813db2005-10-01 16:32:31 +00001240 name, mod, maxlen=70, doc=doc) + '\n')
Tim Peters28355492001-09-23 21:29:55 +00001241 return attrs
1242
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001243 attrs = filter(lambda data: visiblename(data[0], obj=object),
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001244 classify_class_attrs(object))
Tim Petersfa26f7c2001-09-24 08:05:11 +00001245 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001246 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001247 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001248 else:
1249 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001250 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1251
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001252 if thisclass is __builtin__.object:
1253 attrs = inherited
1254 continue
1255 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001256 tag = "defined here"
1257 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001258 tag = "inherited from %s" % classname(thisclass,
1259 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001260
1261 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001262 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001263
1264 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001265 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001266 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001267 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001268 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001269 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001270 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001271 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1272 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001273 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1274 lambda t: t[1] == 'data')
Tim Peters28355492001-09-23 21:29:55 +00001275 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001276 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001277
1278 contents = '\n'.join(contents)
1279 if not contents:
1280 return title + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001281 return title + '\n' + self.indent(rstrip(contents), ' | ') + '\n'
1282
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001283 def formatvalue(self, object):
1284 """Format an argument default value as text."""
1285 return '=' + self.repr(object)
1286
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001287 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001288 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001289 realname = object.__name__
1290 name = name or realname
1291 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001292 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001293 if inspect.ismethod(object):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001294 imclass = object.im_class
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001295 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001296 if imclass is not cl:
1297 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001298 else:
Georg Brandl7e2b6bb2007-03-13 22:16:30 +00001299 if object.im_self is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001300 note = ' method of %s instance' % classname(
1301 object.im_self.__class__, mod)
1302 else:
1303 note = ' unbound %s method' % classname(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001304 object = object.im_func
1305
1306 if name == realname:
1307 title = self.bold(realname)
1308 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001309 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001310 cl.__dict__[realname] is object):
1311 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001312 title = self.bold(name) + ' = ' + realname
Tim Peters4bcfa312001-09-20 06:08:24 +00001313 if inspect.isfunction(object):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001314 args, varargs, varkw, defaults = inspect.getargspec(object)
1315 argspec = inspect.formatargspec(
1316 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001317 if realname == '<lambda>':
Georg Brandl501dd0d2006-02-17 09:45:40 +00001318 title = self.bold(name) + ' lambda '
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001319 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +00001320 else:
1321 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001322 decl = title + argspec + note
1323
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001324 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001325 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001326 else:
1327 doc = getdoc(object) or ''
1328 return decl + '\n' + (doc and rstrip(self.indent(doc)) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001329
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001330 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001331 results = []
1332 push = results.append
1333
1334 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001335 push(self.bold(name))
1336 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001337 doc = getdoc(value) or ''
1338 if doc:
1339 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001340 push('\n')
1341 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001342
1343 def docproperty(self, object, name=None, mod=None, cl=None):
1344 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001345 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001346
Barry Warsaw00decd72006-07-27 23:43:15 +00001347 def docdata(self, object, name=None, mod=None, cl=None):
1348 """Produce text documentation for a data descriptor."""
1349 return self._docdescriptor(name, object, mod)
1350
Georg Brandl8b813db2005-10-01 16:32:31 +00001351 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001352 """Produce text documentation for a data object."""
1353 repr = self.repr(object)
1354 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001355 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001356 chop = maxlen - len(line)
1357 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001358 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001359 if doc is not None:
1360 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001361 return line
1362
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001363# --------------------------------------------------------- user interfaces
1364
1365def pager(text):
1366 """The first time this is called, determine what kind of pager to use."""
1367 global pager
1368 pager = getpager()
1369 pager(text)
1370
1371def getpager():
1372 """Decide what method to use for paging through text."""
1373 if type(sys.stdout) is not types.FileType:
1374 return plainpager
1375 if not sys.stdin.isatty() or not sys.stdout.isatty():
1376 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001377 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001378 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001379 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001380 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001381 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001382 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001383 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001384 if os.environ.get('TERM') in ('dumb', 'emacs'):
1385 return plainpager
Andrew MacIntyre54e0eab2002-03-03 03:12:30 +00001386 if sys.platform == 'win32' or sys.platform.startswith('os2'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001387 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001388 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001389 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001390
1391 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001392 (fd, filename) = tempfile.mkstemp()
1393 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001394 try:
Georg Brandlb32dea52008-07-16 21:19:28 +00001395 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001396 return lambda text: pipepager(text, 'more')
1397 else:
1398 return ttypager
1399 finally:
1400 os.unlink(filename)
1401
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001402def plain(text):
1403 """Remove boldface formatting from text."""
1404 return re.sub('.\b', '', text)
1405
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001406def pipepager(text, cmd):
1407 """Page through text by feeding it to another program."""
1408 pipe = os.popen(cmd, 'w')
1409 try:
R David Murray984f6302014-01-05 12:35:59 -05001410 pipe.write(_encode(text))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001411 pipe.close()
1412 except IOError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001413 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001414
1415def tempfilepager(text, cmd):
1416 """Page through text by invoking a program on a temporary file."""
1417 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001418 filename = tempfile.mktemp()
1419 file = open(filename, 'w')
R David Murray984f6302014-01-05 12:35:59 -05001420 file.write(_encode(text))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001421 file.close()
1422 try:
Georg Brandlb32dea52008-07-16 21:19:28 +00001423 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001424 finally:
1425 os.unlink(filename)
1426
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001427def ttypager(text):
1428 """Page through text on a text terminal."""
R David Murray984f6302014-01-05 12:35:59 -05001429 lines = plain(_encode(plain(text), getattr(sys.stdout, 'encoding', _encoding))).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001430 try:
1431 import tty
1432 fd = sys.stdin.fileno()
1433 old = tty.tcgetattr(fd)
1434 tty.setcbreak(fd)
1435 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001436 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001437 tty = None
1438 getchar = lambda: sys.stdin.readline()[:-1][:1]
1439
1440 try:
1441 r = inc = os.environ.get('LINES', 25) - 1
1442 sys.stdout.write(join(lines[:inc], '\n') + '\n')
1443 while lines[r:]:
1444 sys.stdout.write('-- more --')
1445 sys.stdout.flush()
1446 c = getchar()
1447
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001448 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001449 sys.stdout.write('\r \r')
1450 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001451 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001452 sys.stdout.write('\r \r' + lines[r] + '\n')
1453 r = r + 1
1454 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001455 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001456 r = r - inc - inc
1457 if r < 0: r = 0
1458 sys.stdout.write('\n' + join(lines[r:r+inc], '\n') + '\n')
1459 r = r + inc
1460
1461 finally:
1462 if tty:
1463 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1464
1465def plainpager(text):
1466 """Simply print unformatted text. This is the ultimate fallback."""
R David Murray984f6302014-01-05 12:35:59 -05001467 sys.stdout.write(_encode(plain(text), getattr(sys.stdout, 'encoding', _encoding)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001468
1469def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001470 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001471 if inspect.ismodule(thing):
1472 if thing.__name__ in sys.builtin_module_names:
1473 return 'built-in module ' + thing.__name__
1474 if hasattr(thing, '__path__'):
1475 return 'package ' + thing.__name__
1476 else:
1477 return 'module ' + thing.__name__
1478 if inspect.isbuiltin(thing):
1479 return 'built-in function ' + thing.__name__
Barry Warsaw00decd72006-07-27 23:43:15 +00001480 if inspect.isgetsetdescriptor(thing):
1481 return 'getset descriptor %s.%s.%s' % (
1482 thing.__objclass__.__module__, thing.__objclass__.__name__,
1483 thing.__name__)
1484 if inspect.ismemberdescriptor(thing):
1485 return 'member descriptor %s.%s.%s' % (
1486 thing.__objclass__.__module__, thing.__objclass__.__name__,
1487 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001488 if inspect.isclass(thing):
1489 return 'class ' + thing.__name__
1490 if inspect.isfunction(thing):
1491 return 'function ' + thing.__name__
1492 if inspect.ismethod(thing):
1493 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001494 if type(thing) is types.InstanceType:
1495 return 'instance of ' + thing.__class__.__name__
1496 return type(thing).__name__
1497
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001498def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001499 """Locate an object by name or dotted path, importing as necessary."""
Guido van Rossum97dede02003-02-16 01:12:32 +00001500 parts = [part for part in split(path, '.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001501 module, n = None, 0
1502 while n < len(parts):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001503 nextmodule = safeimport(join(parts[:n+1], '.'), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001504 if nextmodule: module, n = nextmodule, n + 1
1505 else: break
1506 if module:
1507 object = module
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001508 else:
Éric Araujo9a528302011-07-29 17:34:35 +02001509 object = __builtin__
1510 for part in parts[n:]:
1511 try:
1512 object = getattr(object, part)
1513 except AttributeError:
1514 return None
1515 return object
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001516
1517# --------------------------------------- interactive interpreter interface
1518
1519text = TextDoc()
1520html = HTMLDoc()
1521
Ka-Ping Yee8ef1cf32007-01-14 04:25:15 +00001522class _OldStyleClass: pass
1523_OLD_INSTANCE_TYPE = type(_OldStyleClass())
1524
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001525def resolve(thing, forceload=0):
1526 """Given an object or a path to an object, get the object and its name."""
1527 if isinstance(thing, str):
1528 object = locate(thing, forceload)
1529 if not object:
1530 raise ImportError, 'no Python documentation found for %r' % thing
1531 return object, thing
1532 else:
R David Murrayc313b1d2012-04-23 13:27:11 -04001533 name = getattr(thing, '__name__', None)
1534 return thing, name if isinstance(name, str) else None
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001535
Georg Brandl8441f152007-03-13 20:02:57 +00001536def render_doc(thing, title='Python Library Documentation: %s', forceload=0):
1537 """Render text documentation, given an object or a path to an object."""
1538 object, name = resolve(thing, forceload)
1539 desc = describe(object)
1540 module = inspect.getmodule(object)
1541 if name and '.' in name:
1542 desc += ' in ' + name[:name.rfind('.')]
1543 elif module and module is not object:
1544 desc += ' in module ' + module.__name__
1545 if type(object) is _OLD_INSTANCE_TYPE:
1546 # If the passed object is an instance of an old-style class,
1547 # document its available methods instead of its value.
1548 object = object.__class__
1549 elif not (inspect.ismodule(object) or
1550 inspect.isclass(object) or
1551 inspect.isroutine(object) or
1552 inspect.isgetsetdescriptor(object) or
1553 inspect.ismemberdescriptor(object) or
1554 isinstance(object, property)):
1555 # If the passed object is a piece of data or an instance,
1556 # document its available methods instead of its value.
1557 object = type(object)
1558 desc += ' object'
1559 return title % desc + '\n\n' + text.document(object, name)
1560
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001561def doc(thing, title='Python Library Documentation: %s', forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001562 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001563 try:
Georg Brandl8441f152007-03-13 20:02:57 +00001564 pager(render_doc(thing, title, forceload))
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001565 except (ImportError, ErrorDuringImport), value:
1566 print value
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001567
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001568def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001569 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001570 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001571 object, name = resolve(thing, forceload)
1572 page = html.page(describe(object), html.document(object, name))
1573 file = open(name + '.html', 'w')
1574 file.write(page)
1575 file.close()
1576 print 'wrote', name + '.html'
1577 except (ImportError, ErrorDuringImport), value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001578 print value
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001579
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001580def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001581 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001582 if done is None: done = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001583 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1584 writedoc(modname)
1585 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001586
1587class Helper:
Georg Brandl681001e2008-06-01 20:33:55 +00001588
1589 # These dictionaries map a topic name to either an alias, or a tuple
1590 # (label, seealso-items). The "label" is the label of the corresponding
1591 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl43819252009-04-26 09:56:44 +00001592 # in pydoc_data/topics.py.
Georg Brandl681001e2008-06-01 20:33:55 +00001593 #
1594 # CAUTION: if you change one of these dictionaries, be sure to adapt the
1595 # list of needed labels in Doc/tools/sphinxext/pyspecific.py and
Georg Brandl43819252009-04-26 09:56:44 +00001596 # regenerate the pydoc_data/topics.py file by running
Georg Brandl681001e2008-06-01 20:33:55 +00001597 # make pydoc-topics
1598 # in Doc/ and copying the output file into the Lib/ directory.
1599
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001600 keywords = {
1601 'and': 'BOOLEAN',
Georg Brandlb6a87542007-03-13 10:06:48 +00001602 'as': 'with',
Georg Brandl681001e2008-06-01 20:33:55 +00001603 'assert': ('assert', ''),
1604 'break': ('break', 'while for'),
1605 'class': ('class', 'CLASSES SPECIALMETHODS'),
1606 'continue': ('continue', 'while for'),
1607 'def': ('function', ''),
1608 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001609 'elif': 'if',
Georg Brandl681001e2008-06-01 20:33:55 +00001610 'else': ('else', 'while for'),
Georg Brandl5c669db2008-08-30 19:03:43 +00001611 'except': 'try',
Georg Brandl681001e2008-06-01 20:33:55 +00001612 'exec': ('exec', ''),
Georg Brandl5c669db2008-08-30 19:03:43 +00001613 'finally': 'try',
Georg Brandl681001e2008-06-01 20:33:55 +00001614 'for': ('for', 'break continue while'),
Georg Brandl5c669db2008-08-30 19:03:43 +00001615 'from': 'import',
Georg Brandl681001e2008-06-01 20:33:55 +00001616 'global': ('global', 'NAMESPACES'),
1617 'if': ('if', 'TRUTHVALUE'),
1618 'import': ('import', 'MODULES'),
1619 'in': ('in', 'SEQUENCEMETHODS2'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001620 'is': 'COMPARISON',
Georg Brandl681001e2008-06-01 20:33:55 +00001621 'lambda': ('lambda', 'FUNCTIONS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001622 'not': 'BOOLEAN',
1623 'or': 'BOOLEAN',
Georg Brandl681001e2008-06-01 20:33:55 +00001624 'pass': ('pass', ''),
1625 'print': ('print', ''),
1626 'raise': ('raise', 'EXCEPTIONS'),
1627 'return': ('return', 'FUNCTIONS'),
1628 'try': ('try', 'EXCEPTIONS'),
1629 'while': ('while', 'break continue if TRUTHVALUE'),
1630 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1631 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001632 }
Georg Brandlc3a98032008-12-27 18:20:04 +00001633 # Either add symbols to this dictionary or to the symbols dictionary
1634 # directly: Whichever is easier. They are merged later.
1635 _symbols_inverse = {
1636 'STRINGS' : ("'", "'''", "r'", "u'", '"""', '"', 'r"', 'u"'),
1637 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1638 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1639 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1640 'UNARY' : ('-', '~'),
1641 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1642 '^=', '<<=', '>>=', '**=', '//='),
1643 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1644 'COMPLEX' : ('j', 'J')
1645 }
1646 symbols = {
1647 '%': 'OPERATORS FORMATTING',
1648 '**': 'POWER',
1649 ',': 'TUPLES LISTS FUNCTIONS',
1650 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1651 '...': 'ELLIPSIS',
1652 ':': 'SLICINGS DICTIONARYLITERALS',
1653 '@': 'def class',
1654 '\\': 'STRINGS',
1655 '_': 'PRIVATENAMES',
1656 '__': 'PRIVATENAMES SPECIALMETHODS',
1657 '`': 'BACKQUOTES',
1658 '(': 'TUPLES FUNCTIONS CALLS',
1659 ')': 'TUPLES FUNCTIONS CALLS',
1660 '[': 'LISTS SUBSCRIPTS SLICINGS',
1661 ']': 'LISTS SUBSCRIPTS SLICINGS'
1662 }
1663 for topic, symbols_ in _symbols_inverse.iteritems():
1664 for symbol in symbols_:
1665 topics = symbols.get(symbol, topic)
1666 if topic not in topics:
1667 topics = topics + ' ' + topic
1668 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001669
1670 topics = {
Georg Brandl681001e2008-06-01 20:33:55 +00001671 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1672 'FUNCTIONS CLASSES MODULES FILES inspect'),
1673 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS FORMATTING '
1674 'TYPES'),
1675 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1676 'FORMATTING': ('formatstrings', 'OPERATORS'),
1677 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1678 'FORMATTING TYPES'),
1679 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1680 'INTEGER': ('integers', 'int range'),
1681 'FLOAT': ('floating', 'float math'),
1682 'COMPLEX': ('imaginary', 'complex cmath'),
1683 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING xrange LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001684 'MAPPINGS': 'DICTIONARIES',
Georg Brandl681001e2008-06-01 20:33:55 +00001685 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1686 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1687 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1688 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001689 'FRAMEOBJECTS': 'TYPES',
1690 'TRACEBACKS': 'TYPES',
Georg Brandl681001e2008-06-01 20:33:55 +00001691 'NONE': ('bltin-null-object', ''),
1692 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
1693 'FILES': ('bltin-file-objects', ''),
1694 'SPECIALATTRIBUTES': ('specialattrs', ''),
1695 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1696 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001697 'PACKAGES': 'import',
Georg Brandl681001e2008-06-01 20:33:55 +00001698 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1699 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1700 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1701 'LISTS DICTIONARIES BACKQUOTES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001702 'OPERATORS': 'EXPRESSIONS',
1703 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl681001e2008-06-01 20:33:55 +00001704 'OBJECTS': ('objects', 'TYPES'),
1705 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
1706 'CALLABLEMETHODS SEQUENCEMETHODS1 MAPPINGMETHODS '
1707 'SEQUENCEMETHODS2 NUMBERMETHODS CLASSES'),
1708 'BASICMETHODS': ('customization', 'cmp hash repr str SPECIALMETHODS'),
1709 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1710 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
1711 'SEQUENCEMETHODS1': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS2 '
1712 'SPECIALMETHODS'),
1713 'SEQUENCEMETHODS2': ('sequence-methods', 'SEQUENCES SEQUENCEMETHODS1 '
1714 'SPECIALMETHODS'),
1715 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1716 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1717 'SPECIALMETHODS'),
1718 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
1719 'NAMESPACES': ('naming', 'global ASSIGNMENT DELETION DYNAMICFEATURES'),
1720 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001721 'SCOPING': 'NAMESPACES',
1722 'FRAMES': 'NAMESPACES',
Georg Brandl681001e2008-06-01 20:33:55 +00001723 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1724 'COERCIONS': ('coercion-rules','CONVERSIONS'),
1725 'CONVERSIONS': ('conversions', 'COERCIONS'),
1726 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1727 'SPECIALIDENTIFIERS': ('id-classes', ''),
1728 'PRIVATENAMES': ('atom-identifiers', ''),
1729 'LITERALS': ('atom-literals', 'STRINGS BACKQUOTES NUMBERS '
1730 'TUPLELITERALS LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001731 'TUPLES': 'SEQUENCES',
Georg Brandl681001e2008-06-01 20:33:55 +00001732 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1733 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1734 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1735 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1736 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1737 'BACKQUOTES': ('string-conversions', 'repr str STRINGS LITERALS'),
1738 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr '
1739 'ATTRIBUTEMETHODS'),
1740 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS1'),
1741 'SLICINGS': ('slicings', 'SEQUENCEMETHODS2'),
1742 'CALLS': ('calls', 'EXPRESSIONS'),
1743 'POWER': ('power', 'EXPRESSIONS'),
1744 'UNARY': ('unary', 'EXPRESSIONS'),
1745 'BINARY': ('binary', 'EXPRESSIONS'),
1746 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1747 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1748 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1749 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001750 'ASSERTION': 'assert',
Georg Brandl681001e2008-06-01 20:33:55 +00001751 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1752 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001753 'DELETION': 'del',
1754 'PRINTING': 'print',
1755 'RETURNING': 'return',
1756 'IMPORTING': 'import',
1757 'CONDITIONAL': 'if',
Georg Brandl681001e2008-06-01 20:33:55 +00001758 'LOOPING': ('compound', 'for while break continue'),
1759 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1760 'DEBUGGING': ('debugger', 'pdb'),
1761 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001762 }
1763
Georg Brandl004c74d2010-08-01 19:06:51 +00001764 def __init__(self, input=None, output=None):
1765 self._input = input
1766 self._output = output
1767
1768 input = property(lambda self: self._input or sys.stdin)
1769 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001770
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001771 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001772 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001773 self()
1774 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001775 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001776
Alexander Belopolskyd501dde2011-01-11 15:35:23 +00001777 _GoInteractive = object()
1778 def __call__(self, request=_GoInteractive):
1779 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001780 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001781 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001782 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001783 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001784 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001785You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001786If you want to ask for help on a particular object directly from the
1787interpreter, you can type "help(object)". Executing "help('string')"
1788has the same effect as typing a particular string at the help> prompt.
1789''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001790
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001791 def interact(self):
1792 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001793 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001794 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001795 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001796 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001797 except (KeyboardInterrupt, EOFError):
1798 break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001799 request = strip(replace(request, '"', '', "'", ''))
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001800 if lower(request) in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001801 self.help(request)
1802
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001803 def getline(self, prompt):
1804 """Read one line, using raw_input when available."""
1805 if self.input is sys.stdin:
1806 return raw_input(prompt)
1807 else:
1808 self.output.write(prompt)
1809 self.output.flush()
1810 return self.input.readline()
1811
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001812 def help(self, request):
1813 if type(request) is type(''):
R. David Murrayd67ea7d2009-05-27 20:07:21 +00001814 request = request.strip()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001815 if request == 'help': self.intro()
1816 elif request == 'keywords': self.listkeywords()
Georg Brandlc3a98032008-12-27 18:20:04 +00001817 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001818 elif request == 'topics': self.listtopics()
1819 elif request == 'modules': self.listmodules()
1820 elif request[:8] == 'modules ':
1821 self.listmodules(split(request)[1])
Georg Brandlc3a98032008-12-27 18:20:04 +00001822 elif request in self.symbols: self.showsymbol(request)
Raymond Hettinger54f02222002-06-01 14:18:47 +00001823 elif request in self.keywords: self.showtopic(request)
1824 elif request in self.topics: self.showtopic(request)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001825 elif request: doc(request, 'Help on %s:')
1826 elif isinstance(request, Helper): self()
1827 else: doc(request, 'Help on %s:')
1828 self.output.write('\n')
1829
1830 def intro(self):
1831 self.output.write('''
1832Welcome to Python %s! This is the online help utility.
1833
1834If this is your first time using Python, you should definitely check out
R David Murray93a224d2012-03-31 12:10:48 -04001835the tutorial on the Internet at http://docs.python.org/%s/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001836
1837Enter the name of any module, keyword, or topic to get help on writing
1838Python programs and using Python modules. To quit this help utility and
1839return to the interpreter, just type "quit".
1840
1841To get a list of available modules, keywords, or topics, type "modules",
1842"keywords", or "topics". Each module also comes with a one-line summary
1843of what it does; to list the modules whose summaries contain a given word
1844such as "spam", type "modules spam".
R David Murray93a224d2012-03-31 12:10:48 -04001845''' % tuple([sys.version[:3]]*2))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001846
1847 def list(self, items, columns=4, width=80):
1848 items = items[:]
1849 items.sort()
1850 colw = width / columns
1851 rows = (len(items) + columns - 1) / columns
1852 for row in range(rows):
1853 for col in range(columns):
1854 i = col * rows + row
1855 if i < len(items):
1856 self.output.write(items[i])
1857 if col < columns - 1:
1858 self.output.write(' ' + ' ' * (colw-1 - len(items[i])))
1859 self.output.write('\n')
1860
1861 def listkeywords(self):
1862 self.output.write('''
1863Here is a list of the Python keywords. Enter any keyword to get more help.
1864
1865''')
1866 self.list(self.keywords.keys())
1867
Georg Brandlc3a98032008-12-27 18:20:04 +00001868 def listsymbols(self):
1869 self.output.write('''
1870Here is a list of the punctuation symbols which Python assigns special meaning
1871to. Enter any symbol to get more help.
1872
1873''')
1874 self.list(self.symbols.keys())
1875
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001876 def listtopics(self):
1877 self.output.write('''
1878Here is a list of available topics. Enter any topic name to get more help.
1879
1880''')
1881 self.list(self.topics.keys())
1882
Georg Brandlc3a98032008-12-27 18:20:04 +00001883 def showtopic(self, topic, more_xrefs=''):
Georg Brandl681001e2008-06-01 20:33:55 +00001884 try:
Georg Brandl43819252009-04-26 09:56:44 +00001885 import pydoc_data.topics
Georg Brandl681001e2008-06-01 20:33:55 +00001886 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001887 self.output.write('''
Georg Brandl681001e2008-06-01 20:33:55 +00001888Sorry, topic and keyword documentation is not available because the
Georg Brandl43819252009-04-26 09:56:44 +00001889module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001890''')
1891 return
1892 target = self.topics.get(topic, self.keywords.get(topic))
1893 if not target:
1894 self.output.write('no documentation found for %s\n' % repr(topic))
1895 return
1896 if type(target) is type(''):
Georg Brandlc3a98032008-12-27 18:20:04 +00001897 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001898
Georg Brandl681001e2008-06-01 20:33:55 +00001899 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001900 try:
Georg Brandl43819252009-04-26 09:56:44 +00001901 doc = pydoc_data.topics.topics[label]
Georg Brandl681001e2008-06-01 20:33:55 +00001902 except KeyError:
1903 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001904 return
Georg Brandl681001e2008-06-01 20:33:55 +00001905 pager(strip(doc) + '\n')
Georg Brandlc3a98032008-12-27 18:20:04 +00001906 if more_xrefs:
1907 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001908 if xrefs:
Georg Brandl681001e2008-06-01 20:33:55 +00001909 import StringIO, formatter
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001910 buffer = StringIO.StringIO()
1911 formatter.DumbWriter(buffer).send_flowing_data(
1912 'Related help topics: ' + join(split(xrefs), ', ') + '\n')
1913 self.output.write('\n%s\n' % buffer.getvalue())
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001914
Georg Brandlc3a98032008-12-27 18:20:04 +00001915 def showsymbol(self, symbol):
1916 target = self.symbols[symbol]
1917 topic, _, xrefs = target.partition(' ')
1918 self.showtopic(topic, xrefs)
1919
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001920 def listmodules(self, key=''):
1921 if key:
1922 self.output.write('''
1923Here is a list of matching modules. Enter any module name to get more help.
1924
1925''')
1926 apropos(key)
1927 else:
1928 self.output.write('''
1929Please wait a moment while I gather a list of all available modules...
1930
1931''')
1932 modules = {}
1933 def callback(path, modname, desc, modules=modules):
1934 if modname and modname[-9:] == '.__init__':
1935 modname = modname[:-9] + ' (package)'
1936 if find(modname, '.') < 0:
1937 modules[modname] = 1
Ka-Ping Yee9e0f1162008-01-13 11:25:13 +00001938 def onerror(modname):
1939 callback(None, modname, None)
1940 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001941 self.list(modules.keys())
1942 self.output.write('''
1943Enter any module name to get more help. Or, type "modules spam" to search
1944for modules whose descriptions contain the word "spam".
1945''')
1946
Georg Brandl004c74d2010-08-01 19:06:51 +00001947help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001948
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001949class Scanner:
1950 """A generic tree iterator."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001951 def __init__(self, roots, children, descendp):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001952 self.roots = roots[:]
1953 self.state = []
1954 self.children = children
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001955 self.descendp = descendp
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001956
1957 def next(self):
1958 if not self.state:
1959 if not self.roots:
1960 return None
1961 root = self.roots.pop(0)
1962 self.state = [(root, self.children(root))]
1963 node, children = self.state[-1]
1964 if not children:
1965 self.state.pop()
1966 return self.next()
1967 child = children.pop(0)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001968 if self.descendp(child):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001969 self.state.append((child, self.children(child)))
1970 return child
1971
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001972
1973class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001974 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001975
Ka-Ping Yee9e0f1162008-01-13 11:25:13 +00001976 def run(self, callback, key=None, completer=None, onerror=None):
Ka-Ping Yee66246962001-04-12 11:59:50 +00001977 if key: key = lower(key)
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001978 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001979 seen = {}
1980
1981 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001982 if modname != '__main__':
1983 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00001984 if key is None:
1985 callback(None, modname, '')
1986 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001987 desc = split(__import__(modname).__doc__ or '', '\n')[0]
Ka-Ping Yee66246962001-04-12 11:59:50 +00001988 if find(lower(modname + ' - ' + desc), key) >= 0:
1989 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001990
Ka-Ping Yee9e0f1162008-01-13 11:25:13 +00001991 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001992 if self.quit:
1993 break
1994 if key is None:
1995 callback(None, modname, '')
1996 else:
1997 loader = importer.find_module(modname)
1998 if hasattr(loader,'get_source'):
1999 import StringIO
2000 desc = source_synopsis(
2001 StringIO.StringIO(loader.get_source(modname))
2002 ) or ''
2003 if hasattr(loader,'get_filename'):
2004 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002005 else:
Phillip J. Ebyceb30872006-04-18 00:59:55 +00002006 path = None
2007 else:
2008 module = loader.load_module(modname)
2009 desc = (module.__doc__ or '').splitlines()[0]
2010 path = getattr(module,'__file__',None)
2011 if find(lower(modname + ' - ' + desc), key) >= 0:
2012 callback(path, modname, desc)
2013
2014 if completer:
2015 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002016
2017def apropos(key):
2018 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002019 def callback(path, modname, desc):
2020 if modname[-9:] == '.__init__':
2021 modname = modname[:-9] + ' (package)'
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002022 print modname, desc and '- ' + desc
Ned Deily0096fb52011-10-06 14:17:44 -07002023 def onerror(modname):
2024 pass
2025 with warnings.catch_warnings():
2026 warnings.filterwarnings('ignore') # ignore problems during import
2027 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002028
2029# --------------------------------------------------- web browser interface
2030
Ka-Ping Yee66246962001-04-12 11:59:50 +00002031def serve(port, callback=None, completer=None):
Ka-Ping Yeefd540692001-04-12 12:54:36 +00002032 import BaseHTTPServer, mimetools, select
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002033
2034 # Patch up mimetools.Message so it doesn't break if rfc822 is reloaded.
2035 class Message(mimetools.Message):
2036 def __init__(self, fp, seekable=1):
2037 Message = self.__class__
2038 Message.__bases__[0].__bases__[0].__init__(self, fp, seekable)
2039 self.encodingheader = self.getheader('content-transfer-encoding')
2040 self.typeheader = self.getheader('content-type')
2041 self.parsetype()
2042 self.parseplist()
2043
2044 class DocHandler(BaseHTTPServer.BaseHTTPRequestHandler):
2045 def send_document(self, title, contents):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002046 try:
2047 self.send_response(200)
2048 self.send_header('Content-Type', 'text/html')
2049 self.end_headers()
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002050 self.wfile.write(html.page(title, contents))
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002051 except IOError: pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002052
2053 def do_GET(self):
2054 path = self.path
2055 if path[-5:] == '.html': path = path[:-5]
2056 if path[:1] == '/': path = path[1:]
2057 if path and path != '.':
2058 try:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00002059 obj = locate(path, forceload=1)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002060 except ErrorDuringImport, value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002061 self.send_document(path, html.escape(str(value)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002062 return
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002063 if obj:
2064 self.send_document(describe(obj), html.document(obj, path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002065 else:
2066 self.send_document(path,
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002067'no Python documentation found for %s' % repr(path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002068 else:
2069 heading = html.heading(
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002070'<big><big><strong>Python: Index of Modules</strong></big></big>',
2071'#ffffff', '#7799ee')
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002072 def bltinlink(name):
2073 return '<a href="%s.html">%s</a>' % (name, name)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002074 names = filter(lambda x: x != '__main__',
2075 sys.builtin_module_names)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002076 contents = html.multicolumn(names, bltinlink)
2077 indices = ['<p>' + html.bigsection(
2078 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2079
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002080 seen = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +00002081 for dir in sys.path:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002082 indices.append(html.index(dir, seen))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002083 contents = heading + join(indices) + '''<p align=right>
Tim Peters2306d242001-09-25 03:18:32 +00002084<font color="#909090" face="helvetica, arial"><strong>
2085pydoc</strong> by Ka-Ping Yee &lt;ping@lfw.org&gt;</font>'''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002086 self.send_document('Index of Modules', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002087
2088 def log_message(self, *args): pass
2089
Ka-Ping Yeefd540692001-04-12 12:54:36 +00002090 class DocServer(BaseHTTPServer.HTTPServer):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002091 def __init__(self, port, callback):
Ronald Oussoren9545a232010-05-05 19:09:31 +00002092 host = 'localhost'
Senthil Kumaranaa895452010-08-18 19:35:53 +00002093 self.address = (host, port)
Ka-Ping Yeedb8ed152001-03-02 05:58:17 +00002094 self.url = 'http://%s:%d/' % (host, port)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002095 self.callback = callback
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002096 self.base.__init__(self, self.address, self.handler)
2097
2098 def serve_until_quit(self):
2099 import select
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002100 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002101 while not self.quit:
2102 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2103 if rd: self.handle_request()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002104
2105 def server_activate(self):
2106 self.base.server_activate(self)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002107 if self.callback: self.callback(self)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002108
2109 DocServer.base = BaseHTTPServer.HTTPServer
2110 DocServer.handler = DocHandler
2111 DocHandler.MessageClass = Message
2112 try:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002113 try:
2114 DocServer(port, callback).serve_until_quit()
2115 except (KeyboardInterrupt, select.error):
2116 pass
2117 finally:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002118 if completer: completer()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002119
2120# ----------------------------------------------------- graphical interface
2121
2122def gui():
2123 """Graphical interface (starts web server and pops up a control window)."""
2124 class GUI:
2125 def __init__(self, window, port=7464):
2126 self.window = window
2127 self.server = None
2128 self.scanner = None
2129
Georg Brandl6634bf22008-05-20 07:13:37 +00002130 import Tkinter
2131 self.server_frm = Tkinter.Frame(window)
2132 self.title_lbl = Tkinter.Label(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002133 text='Starting server...\n ')
Georg Brandl6634bf22008-05-20 07:13:37 +00002134 self.open_btn = Tkinter.Button(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002135 text='open browser', command=self.open, state='disabled')
Georg Brandl6634bf22008-05-20 07:13:37 +00002136 self.quit_btn = Tkinter.Button(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002137 text='quit serving', command=self.quit, state='disabled')
2138
Georg Brandl6634bf22008-05-20 07:13:37 +00002139 self.search_frm = Tkinter.Frame(window)
2140 self.search_lbl = Tkinter.Label(self.search_frm, text='Search for')
2141 self.search_ent = Tkinter.Entry(self.search_frm)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002142 self.search_ent.bind('<Return>', self.search)
Georg Brandl6634bf22008-05-20 07:13:37 +00002143 self.stop_btn = Tkinter.Button(self.search_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002144 text='stop', pady=0, command=self.stop, state='disabled')
2145 if sys.platform == 'win32':
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002146 # Trying to hide and show this button crashes under Windows.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002147 self.stop_btn.pack(side='right')
2148
2149 self.window.title('pydoc')
2150 self.window.protocol('WM_DELETE_WINDOW', self.quit)
2151 self.title_lbl.pack(side='top', fill='x')
2152 self.open_btn.pack(side='left', fill='x', expand=1)
2153 self.quit_btn.pack(side='right', fill='x', expand=1)
2154 self.server_frm.pack(side='top', fill='x')
2155
2156 self.search_lbl.pack(side='left')
2157 self.search_ent.pack(side='right', fill='x', expand=1)
2158 self.search_frm.pack(side='top', fill='x')
2159 self.search_ent.focus_set()
2160
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002161 font = ('helvetica', sys.platform == 'win32' and 8 or 10)
Georg Brandl6634bf22008-05-20 07:13:37 +00002162 self.result_lst = Tkinter.Listbox(window, font=font, height=6)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002163 self.result_lst.bind('<Button-1>', self.select)
2164 self.result_lst.bind('<Double-Button-1>', self.goto)
Georg Brandl6634bf22008-05-20 07:13:37 +00002165 self.result_scr = Tkinter.Scrollbar(window,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002166 orient='vertical', command=self.result_lst.yview)
2167 self.result_lst.config(yscrollcommand=self.result_scr.set)
2168
Georg Brandl6634bf22008-05-20 07:13:37 +00002169 self.result_frm = Tkinter.Frame(window)
2170 self.goto_btn = Tkinter.Button(self.result_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002171 text='go to selected', command=self.goto)
Georg Brandl6634bf22008-05-20 07:13:37 +00002172 self.hide_btn = Tkinter.Button(self.result_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002173 text='hide results', command=self.hide)
2174 self.goto_btn.pack(side='left', fill='x', expand=1)
2175 self.hide_btn.pack(side='right', fill='x', expand=1)
2176
2177 self.window.update()
2178 self.minwidth = self.window.winfo_width()
2179 self.minheight = self.window.winfo_height()
2180 self.bigminheight = (self.server_frm.winfo_reqheight() +
2181 self.search_frm.winfo_reqheight() +
2182 self.result_lst.winfo_reqheight() +
2183 self.result_frm.winfo_reqheight())
2184 self.bigwidth, self.bigheight = self.minwidth, self.bigminheight
2185 self.expanded = 0
2186 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2187 self.window.wm_minsize(self.minwidth, self.minheight)
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002188 self.window.tk.willdispatch()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002189
2190 import threading
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002191 threading.Thread(
2192 target=serve, args=(port, self.ready, self.quit)).start()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002193
2194 def ready(self, server):
2195 self.server = server
2196 self.title_lbl.config(
2197 text='Python documentation server at\n' + server.url)
2198 self.open_btn.config(state='normal')
2199 self.quit_btn.config(state='normal')
2200
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002201 def open(self, event=None, url=None):
2202 url = url or self.server.url
2203 try:
2204 import webbrowser
2205 webbrowser.open(url)
2206 except ImportError: # pre-webbrowser.py compatibility
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002207 if sys.platform == 'win32':
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002208 os.system('start "%s"' % url)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002209 else:
2210 rc = os.system('netscape -remote "openURL(%s)" &' % url)
2211 if rc: os.system('netscape "%s" &' % url)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002212
2213 def quit(self, event=None):
2214 if self.server:
2215 self.server.quit = 1
2216 self.window.quit()
2217
2218 def search(self, event=None):
2219 key = self.search_ent.get()
2220 self.stop_btn.pack(side='right')
2221 self.stop_btn.config(state='normal')
2222 self.search_lbl.config(text='Searching for "%s"...' % key)
2223 self.search_ent.forget()
2224 self.search_lbl.pack(side='left')
2225 self.result_lst.delete(0, 'end')
2226 self.goto_btn.config(state='disabled')
2227 self.expand()
2228
2229 import threading
2230 if self.scanner:
2231 self.scanner.quit = 1
2232 self.scanner = ModuleScanner()
2233 threading.Thread(target=self.scanner.run,
Ka-Ping Yee6dcfa382001-04-12 20:27:31 +00002234 args=(self.update, key, self.done)).start()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002235
2236 def update(self, path, modname, desc):
2237 if modname[-9:] == '.__init__':
2238 modname = modname[:-9] + ' (package)'
2239 self.result_lst.insert('end',
2240 modname + ' - ' + (desc or '(no description)'))
2241
2242 def stop(self, event=None):
2243 if self.scanner:
2244 self.scanner.quit = 1
2245 self.scanner = None
2246
2247 def done(self):
2248 self.scanner = None
2249 self.search_lbl.config(text='Search for')
2250 self.search_lbl.pack(side='left')
2251 self.search_ent.pack(side='right', fill='x', expand=1)
2252 if sys.platform != 'win32': self.stop_btn.forget()
2253 self.stop_btn.config(state='disabled')
2254
2255 def select(self, event=None):
2256 self.goto_btn.config(state='normal')
2257
2258 def goto(self, event=None):
2259 selection = self.result_lst.curselection()
2260 if selection:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002261 modname = split(self.result_lst.get(selection[0]))[0]
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002262 self.open(url=self.server.url + modname + '.html')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002263
2264 def collapse(self):
2265 if not self.expanded: return
2266 self.result_frm.forget()
2267 self.result_scr.forget()
2268 self.result_lst.forget()
2269 self.bigwidth = self.window.winfo_width()
2270 self.bigheight = self.window.winfo_height()
2271 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2272 self.window.wm_minsize(self.minwidth, self.minheight)
2273 self.expanded = 0
2274
2275 def expand(self):
2276 if self.expanded: return
2277 self.result_frm.pack(side='bottom', fill='x')
2278 self.result_scr.pack(side='right', fill='y')
2279 self.result_lst.pack(side='top', fill='both', expand=1)
2280 self.window.wm_geometry('%dx%d' % (self.bigwidth, self.bigheight))
2281 self.window.wm_minsize(self.minwidth, self.bigminheight)
2282 self.expanded = 1
2283
2284 def hide(self, event=None):
2285 self.stop()
2286 self.collapse()
2287
Georg Brandl6634bf22008-05-20 07:13:37 +00002288 import Tkinter
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002289 try:
Georg Brandl6634bf22008-05-20 07:13:37 +00002290 root = Tkinter.Tk()
Martin v. Löwise09bd932004-08-22 16:13:26 +00002291 # Tk will crash if pythonw.exe has an XP .manifest
2292 # file and the root has is not destroyed explicitly.
2293 # If the problem is ever fixed in Tk, the explicit
2294 # destroy can go.
2295 try:
2296 gui = GUI(root)
2297 root.mainloop()
2298 finally:
2299 root.destroy()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002300 except KeyboardInterrupt:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002301 pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002302
2303# -------------------------------------------------- command-line interface
2304
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002305def ispath(x):
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002306 return isinstance(x, str) and find(x, os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002307
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002308def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002309 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002310 import getopt
2311 class BadUsage: pass
2312
Nick Coghlan11db64e2009-11-15 22:36:47 +00002313 # Scripts don't get the current directory in their path by default
2314 # unless they are run with the '-m' switch
2315 if '' not in sys.path:
2316 scriptdir = os.path.dirname(sys.argv[0])
2317 if scriptdir in sys.path:
2318 sys.path.remove(scriptdir)
2319 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002320
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002321 try:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002322 opts, args = getopt.getopt(sys.argv[1:], 'gk:p:w')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002323 writing = 0
2324
2325 for opt, val in opts:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002326 if opt == '-g':
2327 gui()
2328 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002329 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002330 apropos(val)
2331 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002332 if opt == '-p':
2333 try:
2334 port = int(val)
2335 except ValueError:
2336 raise BadUsage
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002337 def ready(server):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002338 print 'pydoc server ready at %s' % server.url
2339 def stopped():
2340 print 'pydoc server stopped'
2341 serve(port, ready, stopped)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002342 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002343 if opt == '-w':
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002344 writing = 1
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002345
2346 if not args: raise BadUsage
2347 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002348 if ispath(arg) and not os.path.exists(arg):
2349 print 'file %r does not exist' % arg
2350 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002351 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002352 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002353 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002354 if writing:
2355 if ispath(arg) and os.path.isdir(arg):
2356 writedocs(arg)
2357 else:
2358 writedoc(arg)
2359 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002360 help.help(arg)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002361 except ErrorDuringImport, value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002362 print value
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002363
2364 except (getopt.error, BadUsage):
Martin v. Löwisf9b08b82003-10-31 13:05:21 +00002365 cmd = os.path.basename(sys.argv[0])
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002366 print """pydoc - the Python documentation tool
2367
2368%s <name> ...
2369 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002370 Python keyword, topic, function, module, or package, or a dotted
2371 reference to a class or function within a module or module in a
2372 package. If <name> contains a '%s', it is used as the path to a
2373 Python source file to document. If name is 'keywords', 'topics',
2374 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002375
2376%s -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002377 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002378
2379%s -p <port>
2380 Start an HTTP server on the given port on the local machine.
2381
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002382%s -g
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002383 Pop up a graphical interface for finding and serving documentation.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002384
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002385%s -w <name> ...
2386 Write out the HTML documentation for a module to a file in the current
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002387 directory. If <name> contains a '%s', it is treated as a filename; if
2388 it names a directory, documentation is written for all the contents.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002389""" % (cmd, os.sep, cmd, cmd, cmd, cmd, os.sep)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002390
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002391if __name__ == '__main__': cli()