blob: 9316fff1515017ebf30c39c34266f4c5c2808a75 [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
Serhiy Storchaka86ef95d2014-11-27 23:45:37 +020020local machine to generate documentation web pages. Port number 0 can be
21used to get an arbitrary unused port.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000022
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000023For platforms without a command line, "pydoc -g" starts the HTTP server
24and also pops up a little window for controlling it.
25
26Run "pydoc -w <name>" to write out the HTML documentation for a module
27to a file named "<name>.html".
Skip Montanaro4997a692003-09-10 16:47:51 +000028
29Module docs for core modules are assumed to be in
30
Georg Brandl0751d1a2008-01-21 17:13:03 +000031 http://docs.python.org/library/
Skip Montanaro4997a692003-09-10 16:47:51 +000032
33This can be overridden by setting the PYTHONDOCS environment variable
34to a different URL or to a local directory containing the Library
35Reference Manual pages.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000036"""
Ka-Ping Yeedd175342001-02-27 14:43:46 +000037
38__author__ = "Ka-Ping Yee <ping@lfw.org>"
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000039__date__ = "26 February 2001"
Jeremy Hylton3e0055f2005-10-20 19:59:25 +000040
Senthil Kumaran4af1c6a2011-07-28 22:30:27 +080041__version__ = "$Revision: 88564 $"
Martin v. Löwis6fe8f192004-11-14 10:21:04 +000042__credits__ = """Guido van Rossum, for an excellent programming language.
Ka-Ping Yee5e2b1732001-02-27 23:35:09 +000043Tommy Burnette, the original creator of manpy.
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000044Paul Prescod, for all his work on onlinehelp.
45Richard Chamberlain, for the first implementation of textdoc.
Raymond Hettingered2dbe32005-01-01 07:51:01 +000046"""
Ka-Ping Yeedd175342001-02-27 14:43:46 +000047
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000048# Known bugs that can't be fixed here:
49# - imp.load_module() cannot be prevented from clobbering existing
50# loaded modules, so calling synopsis() on a binary module file
51# changes the contents of any existing module with the same name.
52# - If the __file__ attribute on a module is a relative path and
53# the current directory is changed with os.chdir(), an incorrect
54# path will be displayed.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000055
Ned Deily0096fb52011-10-06 14:17:44 -070056import sys, imp, os, re, types, inspect, __builtin__, pkgutil, warnings
Brett Cannon2ee0e8e2008-05-23 05:03:59 +000057from repr import Repr
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000058from string import expandtabs, find, join, lower, split, strip, rfind, rstrip
R. David Murrayef087da2009-06-23 18:02:46 +000059from traceback import extract_tb
Phillip J. Ebyceb30872006-04-18 00:59:55 +000060try:
61 from collections import deque
62except ImportError:
63 # Python 2.3 compatibility
64 class deque(list):
65 def popleft(self):
66 return self.pop(0)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000067
68# --------------------------------------------------------- common routines
69
Ka-Ping Yeedd175342001-02-27 14:43:46 +000070def pathdirs():
71 """Convert sys.path into a list of absolute, existing, unique paths."""
72 dirs = []
Ka-Ping Yee1d384632001-03-01 00:24:32 +000073 normdirs = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +000074 for dir in sys.path:
75 dir = os.path.abspath(dir or '.')
Ka-Ping Yee1d384632001-03-01 00:24:32 +000076 normdir = os.path.normcase(dir)
77 if normdir not in normdirs and os.path.isdir(dir):
Ka-Ping Yeedd175342001-02-27 14:43:46 +000078 dirs.append(dir)
Ka-Ping Yee1d384632001-03-01 00:24:32 +000079 normdirs.append(normdir)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000080 return dirs
81
82def getdoc(object):
83 """Get the doc string or comments for an object."""
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000084 result = inspect.getdoc(object) or inspect.getcomments(object)
R David Murray984f6302014-01-05 12:35:59 -050085 result = _encode(result)
Ka-Ping Yee239432a2001-03-02 02:45:08 +000086 return result and re.sub('^ *\n', '', rstrip(result)) or ''
Ka-Ping Yeedd175342001-02-27 14:43:46 +000087
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000088def splitdoc(doc):
89 """Split a doc string into a synopsis line (if any) and the rest."""
90 lines = split(strip(doc), '\n')
91 if len(lines) == 1:
92 return lines[0], ''
93 elif len(lines) >= 2 and not rstrip(lines[1]):
94 return lines[0], join(lines[2:], '\n')
95 return '', join(lines, '\n')
96
Ka-Ping Yeedd175342001-02-27 14:43:46 +000097def classname(object, modname):
98 """Get a class name and qualify it with a module name if necessary."""
99 name = object.__name__
100 if object.__module__ != modname:
101 name = object.__module__ + '.' + name
102 return name
103
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000104def isdata(object):
Georg Brandl94432422005-07-22 21:52:25 +0000105 """Check if an object is of a type that probably means it's data."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000106 return not (inspect.ismodule(object) or inspect.isclass(object) or
107 inspect.isroutine(object) or inspect.isframe(object) or
108 inspect.istraceback(object) or inspect.iscode(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000109
110def replace(text, *pairs):
111 """Do a series of global replacements on a string."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000112 while pairs:
113 text = join(split(text, pairs[0]), pairs[1])
114 pairs = pairs[2:]
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000115 return text
116
117def cram(text, maxlen):
118 """Omit part of a string if needed to make it fit in a maximum length."""
119 if len(text) > maxlen:
Raymond Hettingerfca3bb62002-10-21 04:44:11 +0000120 pre = max(0, (maxlen-3)//2)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000121 post = max(0, maxlen-3-pre)
122 return text[:pre] + '...' + text[len(text)-post:]
123 return text
124
Brett Cannon84601f12004-06-19 01:22:48 +0000125_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000126def stripid(text):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000127 """Remove the hexadecimal id from a Python object representation."""
Brett Cannonc6c1f472004-06-19 01:02:51 +0000128 # The behaviour of %p is implementation-dependent in terms of case.
Ezio Melottie511fc72010-02-16 23:26:09 +0000129 return _re_stripid.sub(r'\1', text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000130
Brett Cannonc6c1f472004-06-19 01:02:51 +0000131def _is_some_method(obj):
132 return inspect.ismethod(obj) or inspect.ismethoddescriptor(obj)
Tim Peters536d2262001-09-20 05:13:38 +0000133
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000134def allmethods(cl):
135 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000136 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000137 methods[key] = 1
138 for base in cl.__bases__:
139 methods.update(allmethods(base)) # all your base are belong to us
140 for key in methods.keys():
141 methods[key] = getattr(cl, key)
142 return methods
143
Tim Petersfa26f7c2001-09-24 08:05:11 +0000144def _split_list(s, predicate):
145 """Split sequence s via predicate, and return pair ([true], [false]).
146
147 The return value is a 2-tuple of lists,
148 ([x for x in s if predicate(x)],
149 [x for x in s if not predicate(x)])
150 """
151
Tim Peters28355492001-09-23 21:29:55 +0000152 yes = []
153 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000154 for x in s:
155 if predicate(x):
156 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000157 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000158 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000159 return yes, no
160
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700161def visiblename(name, all=None, obj=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000162 """Decide whether to show documentation on a variable."""
163 # Certain special names are redundant.
Nick Coghlanc060b0e2008-07-02 13:09:19 +0000164 _hidden_names = ('__builtins__', '__doc__', '__file__', '__path__',
165 '__module__', '__name__', '__slots__', '__package__')
166 if name in _hidden_names: return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000167 # Private names are hidden, but special names are displayed.
168 if name.startswith('__') and name.endswith('__'): return 1
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700169 # Namedtuples have public fields and methods with a single leading underscore
170 if name.startswith('_') and hasattr(obj, '_fields'):
171 return 1
Skip Montanaroa5616d22004-06-11 04:46:12 +0000172 if all is not None:
173 # only document that which the programmer exported in __all__
174 return name in all
175 else:
176 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000177
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000178def classify_class_attrs(object):
179 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Brett Cannonaca98b02008-08-03 00:58:51 +0000180 def fixup(data):
181 name, kind, cls, value = data
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000182 if inspect.isdatadescriptor(value):
183 kind = 'data descriptor'
184 return name, kind, cls, value
185 return map(fixup, inspect.classify_class_attrs(object))
186
R David Murray984f6302014-01-05 12:35:59 -0500187# ----------------------------------------------------- Unicode support helpers
188
189try:
190 _unicode = unicode
191except NameError:
192 # If Python is built without Unicode support, the unicode type
193 # will not exist. Fake one that nothing will match, and make
194 # the _encode function that do nothing.
195 class _unicode(object):
196 pass
197 _encoding = 'ascii'
198 def _encode(text, encoding='ascii'):
199 return text
200else:
201 import locale
202 _encoding = locale.getpreferredencoding()
203
204 def _encode(text, encoding=None):
205 if isinstance(text, unicode):
206 return text.encode(encoding or _encoding, 'xmlcharrefreplace')
207 else:
208 return text
209
210def _binstr(obj):
211 # Ensure that we have an encoded (binary) string representation of obj,
212 # even if it is a unicode string.
R David Murray875565b2014-01-05 17:14:08 -0500213 if isinstance(obj, _unicode):
214 return obj.encode(_encoding, 'xmlcharrefreplace')
215 return str(obj)
R David Murray984f6302014-01-05 12:35:59 -0500216
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000217# ----------------------------------------------------- module manipulation
218
219def ispackage(path):
220 """Guess whether a path refers to a package directory."""
221 if os.path.isdir(path):
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000222 for ext in ('.py', '.pyc', '.pyo'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000223 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000224 return True
225 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000226
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000227def source_synopsis(file):
228 line = file.readline()
229 while line[:1] == '#' or not strip(line):
230 line = file.readline()
231 if not line: break
232 line = strip(line)
233 if line[:4] == 'r"""': line = line[1:]
234 if line[:3] == '"""':
235 line = line[3:]
236 if line[-1:] == '\\': line = line[:-1]
237 while not strip(line):
238 line = file.readline()
239 if not line: break
240 result = strip(split(line, '"""')[0])
241 else: result = None
242 return result
243
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000244def synopsis(filename, cache={}):
245 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000246 mtime = os.stat(filename).st_mtime
Charles-François Natali0cf7e252011-07-27 19:36:40 +0200247 lastupdate, result = cache.get(filename, (None, None))
248 if lastupdate is None or lastupdate < mtime:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000249 info = inspect.getmoduleinfo(filename)
Georg Brandl26fd2e12006-03-08 09:34:53 +0000250 try:
251 file = open(filename)
252 except IOError:
253 # module can't be opened, so skip it
254 return None
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000255 if info and 'b' in info[2]: # binary modules have to be imported
256 try: module = imp.load_module('__temp__', file, filename, info[1:])
257 except: return None
Berker Peksagdc9d41d2015-02-20 12:10:33 +0200258 result = module.__doc__.splitlines()[0] if module.__doc__ else None
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000259 del sys.modules['__temp__']
260 else: # text modules can be directly examined
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000261 result = source_synopsis(file)
262 file.close()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000263 cache[filename] = (mtime, result)
264 return result
265
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000266class ErrorDuringImport(Exception):
267 """Errors that occurred while trying to import something to document it."""
Brett Cannonaca98b02008-08-03 00:58:51 +0000268 def __init__(self, filename, exc_info):
269 exc, value, tb = exc_info
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000270 self.filename = filename
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000271 self.exc = exc
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000272 self.value = value
273 self.tb = tb
274
275 def __str__(self):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000276 exc = self.exc
277 if type(exc) is types.ClassType:
278 exc = exc.__name__
279 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000280
281def importfile(path):
282 """Import a Python source file or compiled file given its path."""
283 magic = imp.get_magic()
284 file = open(path, 'r')
285 if file.read(len(magic)) == magic:
286 kind = imp.PY_COMPILED
287 else:
288 kind = imp.PY_SOURCE
289 file.close()
290 filename = os.path.basename(path)
291 name, ext = os.path.splitext(filename)
292 file = open(path, 'r')
293 try:
294 module = imp.load_module(name, file, path, (ext, 'r', kind))
295 except:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000296 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000297 file.close()
298 return module
299
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000300def safeimport(path, forceload=0, cache={}):
301 """Import a module; handle errors; return None if the module isn't found.
302
303 If the module *is* found but an exception occurs, it's wrapped in an
304 ErrorDuringImport exception and reraised. Unlike __import__, if a
305 package path is specified, the module at the end of the path is returned,
306 not the package at the beginning. If the optional 'forceload' argument
307 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000308 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000309 # If forceload is 1 and the module has been previously loaded from
310 # disk, we always have to reload the module. Checking the file's
311 # mtime isn't good enough (e.g. the module could contain a class
312 # that inherits from another module that has changed).
313 if forceload and path in sys.modules:
314 if path not in sys.builtin_module_names:
315 # Avoid simply calling reload() because it leaves names in
316 # the currently loaded module lying around if they're not
317 # defined in the new source file. Instead, remove the
318 # module from sys.modules and re-import. Also remove any
319 # submodules because they won't appear in the newly loaded
320 # module's namespace if they're already in sys.modules.
321 subs = [m for m in sys.modules if m.startswith(path + '.')]
322 for key in [path] + subs:
323 # Prevent garbage collection.
324 cache[key] = sys.modules[key]
325 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000326 module = __import__(path)
327 except:
328 # Did the error occur before or after the module was found?
329 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000330 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000331 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000332 raise ErrorDuringImport(sys.modules[path].__file__, info)
333 elif exc is SyntaxError:
334 # A SyntaxError occurred before we could execute the module.
335 raise ErrorDuringImport(value.filename, info)
R. David Murrayef087da2009-06-23 18:02:46 +0000336 elif exc is ImportError and extract_tb(tb)[-1][2]=='safeimport':
337 # The import error occurred directly in this function,
338 # which means there is no such module in the path.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000339 return None
340 else:
341 # Some other error occurred during the importing process.
342 raise ErrorDuringImport(path, sys.exc_info())
343 for part in split(path, '.')[1:]:
344 try: module = getattr(module, part)
345 except AttributeError: return None
346 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000347
348# ---------------------------------------------------- formatter base class
349
350class Doc:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000351 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000352 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000353 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000354 # 'try' clause is to attempt to handle the possibility that inspect
355 # identifies something in a way that pydoc itself has issues handling;
356 # think 'super' and how it is a descriptor (which raises the exception
357 # by lacking a __name__ attribute) and an instance.
Barry Warsaw00decd72006-07-27 23:43:15 +0000358 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
359 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000360 try:
361 if inspect.ismodule(object): return self.docmodule(*args)
362 if inspect.isclass(object): return self.docclass(*args)
363 if inspect.isroutine(object): return self.docroutine(*args)
364 except AttributeError:
365 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000366 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000367 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000368
369 def fail(self, object, name=None, *args):
370 """Raise an exception for unimplemented types."""
371 message = "don't know how to document object%s of type %s" % (
372 name and ' ' + repr(name), type(object).__name__)
373 raise TypeError, message
374
Barry Warsaw00decd72006-07-27 23:43:15 +0000375 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000376
Skip Montanaro4997a692003-09-10 16:47:51 +0000377 def getdocloc(self, object):
378 """Return the location of module docs or None"""
379
380 try:
381 file = inspect.getabsfile(object)
382 except TypeError:
383 file = '(built-in)'
384
385 docloc = os.environ.get("PYTHONDOCS",
Georg Brandl0751d1a2008-01-21 17:13:03 +0000386 "http://docs.python.org/library")
Skip Montanaro4997a692003-09-10 16:47:51 +0000387 basedir = os.path.join(sys.exec_prefix, "lib",
388 "python"+sys.version[0:3])
389 if (isinstance(object, type(os)) and
390 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
391 'marshal', 'posix', 'signal', 'sys',
392 'thread', 'zipimport') or
393 (file.startswith(basedir) and
Brian Curtinaeb2e822010-03-31 03:10:21 +0000394 not file.startswith(os.path.join(basedir, 'site-packages')))) and
Brian Curtina01da932010-04-01 04:02:00 +0000395 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
Skip Montanaro4997a692003-09-10 16:47:51 +0000396 if docloc.startswith("http://"):
Georg Brandl0751d1a2008-01-21 17:13:03 +0000397 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
Skip Montanaro4997a692003-09-10 16:47:51 +0000398 else:
Georg Brandl0751d1a2008-01-21 17:13:03 +0000399 docloc = os.path.join(docloc, object.__name__ + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000400 else:
401 docloc = None
402 return docloc
403
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000404# -------------------------------------------- HTML documentation generator
405
406class HTMLRepr(Repr):
407 """Class for safely making an HTML representation of a Python object."""
408 def __init__(self):
409 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000410 self.maxlist = self.maxtuple = 20
411 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000412 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000413
414 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000415 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000416
417 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000418 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000419
420 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000421 if hasattr(type(x), '__name__'):
422 methodname = 'repr_' + join(split(type(x).__name__), '_')
423 if hasattr(self, methodname):
424 return getattr(self, methodname)(x, level)
425 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000426
427 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000428 test = cram(x, self.maxstring)
429 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000430 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000431 # Backslashes are only literal in the string and are never
432 # needed to make any special characters, so show a raw string.
433 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000434 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000435 r'<font color="#c040c0">\1</font>',
436 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000437
Skip Montanarodf708782002-03-07 22:58:02 +0000438 repr_str = repr_string
439
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000440 def repr_instance(self, x, level):
441 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000442 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000443 except:
444 return self.escape('<%s instance>' % x.__class__.__name__)
445
446 repr_unicode = repr_string
447
448class HTMLDoc(Doc):
449 """Formatter class for HTML documentation."""
450
451 # ------------------------------------------- HTML formatting utilities
452
453 _repr_instance = HTMLRepr()
454 repr = _repr_instance.repr
455 escape = _repr_instance.escape
456
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000457 def page(self, title, contents):
458 """Format an HTML page."""
R David Murray984f6302014-01-05 12:35:59 -0500459 return _encode('''
Georg Brandle0197062009-04-10 08:20:23 +0000460<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000461<html><head><title>Python: %s</title>
R David Murray984f6302014-01-05 12:35:59 -0500462<meta charset="utf-8">
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000463</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000464%s
R David Murray984f6302014-01-05 12:35:59 -0500465</body></html>''' % (title, contents), 'ascii')
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000466
467 def heading(self, title, fgcol, bgcol, extras=''):
468 """Format a page heading."""
469 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000470<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000471<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000472<td valign=bottom>&nbsp;<br>
473<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000474><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000475><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000476 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
477
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000478 def section(self, title, fgcol, bgcol, contents, width=6,
479 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000480 """Format a section with a heading."""
481 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000482 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000483 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000484<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000485<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000486<td colspan=3 valign=bottom>&nbsp;<br>
487<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000488 ''' % (bgcol, fgcol, title)
489 if prelude:
490 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000491<tr bgcolor="%s"><td rowspan=2>%s</td>
492<td colspan=2>%s</td></tr>
493<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
494 else:
495 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000496<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000497
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000498 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000499
500 def bigsection(self, title, *args):
501 """Format a section with a big heading."""
502 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000503 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000504
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000505 def preformat(self, text):
506 """Format literal preformatted text."""
507 text = self.escape(expandtabs(text))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000508 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
509 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000510
511 def multicolumn(self, list, format, cols=4):
512 """Format a list of items into a multi-column list."""
513 result = ''
Victor Stinnerdbfba162011-05-26 13:37:25 +0200514 rows = (len(list)+cols-1)//cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000515 for col in range(cols):
Victor Stinnerdbfba162011-05-26 13:37:25 +0200516 result = result + '<td width="%d%%" valign=top>' % (100//cols)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000517 for i in range(rows*col, rows*col+rows):
518 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000519 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000520 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000521 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000522
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000523 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000524
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000525 def namelink(self, name, *dicts):
526 """Make a link for an identifier, given name-to-URL mappings."""
527 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000528 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000529 return '<a href="%s">%s</a>' % (dict[name], name)
530 return name
531
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000532 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000533 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000534 name, module = object.__name__, sys.modules.get(object.__module__)
535 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000536 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000537 module.__name__, name, classname(object, modname))
538 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000539
540 def modulelink(self, object):
541 """Make a link for a module."""
542 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
543
Brett Cannonaca98b02008-08-03 00:58:51 +0000544 def modpkglink(self, data):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000545 """Make a link for a module or package to display in an index."""
Brett Cannonaca98b02008-08-03 00:58:51 +0000546 name, path, ispackage, shadowed = data
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000547 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000548 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000549 if path:
550 url = '%s.%s.html' % (path, name)
551 else:
552 url = '%s.html' % name
553 if ispackage:
554 text = '<strong>%s</strong>&nbsp;(package)' % name
555 else:
556 text = name
557 return '<a href="%s">%s</a>' % (url, text)
558
559 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
560 """Mark up some plain text, given a context of symbols to look for.
561 Each context dictionary maps object names to anchor names."""
562 escape = escape or self.escape
563 results = []
564 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000565 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
566 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000567 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000568 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000569 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000570 match = pattern.search(text, here)
571 if not match: break
572 start, end = match.span()
573 results.append(escape(text[here:start]))
574
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000575 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000576 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000577 url = escape(all).replace('"', '&quot;')
578 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000579 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000580 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
581 results.append('<a href="%s">%s</a>' % (url, escape(all)))
582 elif pep:
Andrew M. Kuchling727a5902008-02-05 16:06:57 +0000583 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000584 results.append('<a href="%s">%s</a>' % (url, escape(all)))
Benjamin Petersonc3e1e902014-06-07 16:44:00 -0700585 elif selfdot:
586 # Create a link for methods like 'self.method(...)'
587 # and use <strong> for attributes like 'self.attr'
588 if text[end:end+1] == '(':
589 results.append('self.' + self.namelink(name, methods))
590 else:
591 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000592 elif text[end:end+1] == '(':
593 results.append(self.namelink(name, methods, funcs, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000594 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000595 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000596 here = end
597 results.append(escape(text[here:]))
598 return join(results, '')
599
600 # ---------------------------------------------- type-specific routines
601
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000602 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000603 """Produce HTML for a class tree as given by inspect.getclasstree()."""
604 result = ''
605 for entry in tree:
606 if type(entry) is type(()):
607 c, bases = entry
Tim Peters2306d242001-09-25 03:18:32 +0000608 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000609 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000610 if bases and bases != (parent,):
611 parents = []
612 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000613 parents.append(self.classlink(base, modname))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000614 result = result + '(' + join(parents, ', ') + ')'
Tim Peters2306d242001-09-25 03:18:32 +0000615 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000616 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000617 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000618 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000619 return '<dl>\n%s</dl>\n' % result
620
Tim Peters8dd7ade2001-10-18 19:56:17 +0000621 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000622 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000623 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000624 try:
625 all = object.__all__
626 except AttributeError:
627 all = None
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000628 parts = split(name, '.')
629 links = []
630 for i in range(len(parts)-1):
631 links.append(
632 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
633 (join(parts[:i+1], '.'), parts[i]))
634 linkedname = join(links + parts[-1:], '.')
635 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000636 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000637 path = inspect.getabsfile(object)
Ka-Ping Yee6191a232001-04-13 15:00:27 +0000638 url = path
639 if sys.platform == 'win32':
640 import nturl2path
641 url = nturl2path.pathname2url(path)
642 filelink = '<a href="file:%s">%s</a>' % (url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000643 except TypeError:
644 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000645 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000646 if hasattr(object, '__version__'):
R David Murray984f6302014-01-05 12:35:59 -0500647 version = _binstr(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000648 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
649 version = strip(version[11:-1])
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000650 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000651 if hasattr(object, '__date__'):
R David Murray984f6302014-01-05 12:35:59 -0500652 info.append(self.escape(_binstr(object.__date__)))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000653 if info:
654 head = head + ' (%s)' % join(info, ', ')
Skip Montanaro4997a692003-09-10 16:47:51 +0000655 docloc = self.getdocloc(object)
656 if docloc is not None:
657 docloc = '<br><a href="%(docloc)s">Module Docs</a>' % locals()
658 else:
659 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000660 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000661 head, '#ffffff', '#7799ee',
662 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000663
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000664 modules = inspect.getmembers(object, inspect.ismodule)
665
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000666 classes, cdict = [], {}
667 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000668 # if __all__ exists, believe it. Otherwise use old heuristic.
669 if (all is not None or
670 (inspect.getmodule(value) or object) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700671 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000672 classes.append((key, value))
673 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000674 for key, value in classes:
675 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000676 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000677 module = sys.modules.get(modname)
678 if modname != name and module and hasattr(module, key):
679 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000680 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000681 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000682 funcs, fdict = [], {}
683 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000684 # if __all__ exists, believe it. Otherwise use old heuristic.
685 if (all is not None or
686 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700687 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000688 funcs.append((key, value))
689 fdict[key] = '#-' + key
690 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000691 data = []
692 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700693 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000694 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000695
696 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
697 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000698 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000699
700 if hasattr(object, '__path__'):
701 modpkgs = []
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000702 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
703 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000704 modpkgs.sort()
705 contents = self.multicolumn(modpkgs, self.modpkglink)
706 result = result + self.bigsection(
707 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000708 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000709 contents = self.multicolumn(
Brett Cannonaca98b02008-08-03 00:58:51 +0000710 modules, lambda key_value, s=self: s.modulelink(key_value[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000711 result = result + self.bigsection(
Georg Brandlb169eaa2008-02-17 21:18:55 +0000712 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000713
714 if classes:
Brett Cannonaca98b02008-08-03 00:58:51 +0000715 classlist = map(lambda key_value: key_value[1], classes)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000716 contents = [
717 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000718 for key, value in classes:
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 'Classes', '#ffffff', '#ee77aa', join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000722 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000723 contents = []
724 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000725 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000726 result = result + self.bigsection(
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000727 'Functions', '#ffffff', '#eeaa77', join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000728 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000729 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000730 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000731 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000732 result = result + self.bigsection(
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000733 'Data', '#ffffff', '#55aa55', join(contents, '<br>\n'))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000734 if hasattr(object, '__author__'):
R David Murray984f6302014-01-05 12:35:59 -0500735 contents = self.markup(_binstr(object.__author__), self.preformat)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000736 result = result + self.bigsection(
737 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000738 if hasattr(object, '__credits__'):
R David Murray984f6302014-01-05 12:35:59 -0500739 contents = self.markup(_binstr(object.__credits__), self.preformat)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000740 result = result + self.bigsection(
741 'Credits', '#ffffff', '#7799ee', contents)
742
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000743 return result
744
Tim Peters8dd7ade2001-10-18 19:56:17 +0000745 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
746 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000747 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000748 realname = object.__name__
749 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000750 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000751
Tim Petersb47879b2001-09-24 04:47:19 +0000752 contents = []
753 push = contents.append
754
Tim Petersfa26f7c2001-09-24 08:05:11 +0000755 # Cute little class to pump out a horizontal rule between sections.
756 class HorizontalRule:
757 def __init__(self):
758 self.needone = 0
759 def maybe(self):
760 if self.needone:
761 push('<hr>\n')
762 self.needone = 1
763 hr = HorizontalRule()
764
Tim Petersc86f6ca2001-09-26 21:31:51 +0000765 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000766 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000767 if len(mro) > 2:
768 hr.maybe()
769 push('<dl><dt>Method resolution order:</dt>\n')
770 for base in mro:
771 push('<dd>%s</dd>\n' % self.classlink(base,
772 object.__module__))
773 push('</dl>\n')
774
Tim Petersb47879b2001-09-24 04:47:19 +0000775 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000776 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000777 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000778 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000779 push(msg)
780 for name, kind, homecls, value in ok:
Antoine Pitroub8572a12011-12-21 10:16:14 +0100781 try:
782 value = getattr(object, name)
783 except Exception:
784 # Some descriptors may meet a failure in their __get__.
785 # (bug #1785)
786 push(self._docdescriptor(name, value, mod))
787 else:
788 push(self.document(value, name, mod,
789 funcs, classes, mdict, object))
Tim Petersb47879b2001-09-24 04:47:19 +0000790 push('\n')
791 return attrs
792
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000793 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000794 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000795 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000796 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000797 push(msg)
798 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000799 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000800 return attrs
801
Tim Petersfa26f7c2001-09-24 08:05:11 +0000802 def spilldata(msg, attrs, predicate):
803 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000804 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000805 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000806 push(msg)
807 for name, kind, homecls, value in ok:
808 base = self.docother(getattr(object, name), name, mod)
Brett Cannonaca98b02008-08-03 00:58:51 +0000809 if (hasattr(value, '__call__') or
810 inspect.isdatadescriptor(value)):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000811 doc = getattr(value, "__doc__", None)
812 else:
813 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000814 if doc is None:
815 push('<dl><dt>%s</dl>\n' % base)
816 else:
817 doc = self.markup(getdoc(value), self.preformat,
818 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000819 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000820 push('<dl><dt>%s%s</dl>\n' % (base, doc))
821 push('\n')
822 return attrs
823
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700824 attrs = filter(lambda data: visiblename(data[0], obj=object),
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000825 classify_class_attrs(object))
Tim Petersb47879b2001-09-24 04:47:19 +0000826 mdict = {}
827 for key, kind, homecls, value in attrs:
828 mdict[key] = anchor = '#' + name + '-' + key
Antoine Pitroub8572a12011-12-21 10:16:14 +0100829 try:
830 value = getattr(object, name)
831 except Exception:
832 # Some descriptors may meet a failure in their __get__.
833 # (bug #1785)
834 pass
Tim Petersb47879b2001-09-24 04:47:19 +0000835 try:
836 # The value may not be hashable (e.g., a data attr with
837 # a dict or list value).
838 mdict[value] = anchor
839 except TypeError:
840 pass
841
Tim Petersfa26f7c2001-09-24 08:05:11 +0000842 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000843 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000844 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000845 else:
846 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000847 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
848
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000849 if thisclass is __builtin__.object:
850 attrs = inherited
851 continue
852 elif thisclass is object:
853 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000854 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000855 tag = 'inherited from %s' % self.classlink(thisclass,
856 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000857 tag += ':<br>\n'
858
859 # Sort attrs by name.
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000860 try:
861 attrs.sort(key=lambda t: t[0])
862 except TypeError:
863 attrs.sort(lambda t1, t2: cmp(t1[0], t2[0])) # 2.3 compat
Tim Petersb47879b2001-09-24 04:47:19 +0000864
865 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000866 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000867 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000868 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000869 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000870 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000871 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000872 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
873 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000874 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000875 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000876 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000877 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000878
879 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000880
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000881 if name == realname:
882 title = '<a name="%s">class <strong>%s</strong></a>' % (
883 name, realname)
884 else:
885 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
886 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000887 if bases:
888 parents = []
889 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000890 parents.append(self.classlink(base, object.__module__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000891 title = title + '(%s)' % join(parents, ', ')
Tim Peters2306d242001-09-25 03:18:32 +0000892 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000893 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000894
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000895 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000896
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000897 def formatvalue(self, object):
898 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000899 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000900
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000901 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000902 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000903 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000904 realname = object.__name__
905 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000906 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000907 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000908 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000909 if inspect.ismethod(object):
Ka-Ping Yee6dcfa382001-04-12 20:27:31 +0000910 imclass = object.im_class
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000911 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000912 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000913 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000914 else:
Georg Brandl7e2b6bb2007-03-13 22:16:30 +0000915 if object.im_self is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000916 note = ' method of %s instance' % self.classlink(
917 object.im_self.__class__, mod)
918 else:
919 note = ' unbound %s method' % self.classlink(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000920 object = object.im_func
921
922 if name == realname:
923 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
924 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000925 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000926 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000927 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000928 cl.__name__ + '-' + realname, realname)
929 skipdocs = 1
930 else:
931 reallink = realname
932 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
933 anchor, name, reallink)
Tim Peters4bcfa312001-09-20 06:08:24 +0000934 if inspect.isfunction(object):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000935 args, varargs, varkw, defaults = inspect.getargspec(object)
936 argspec = inspect.formatargspec(
937 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000938 if realname == '<lambda>':
Tim Peters59ed4482001-10-31 04:20:26 +0000939 title = '<strong>%s</strong> <em>lambda</em> ' % name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000940 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +0000941 else:
942 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000943
Tim Peters2306d242001-09-25 03:18:32 +0000944 decl = title + argspec + (note and self.grey(
945 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000946
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000947 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000948 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000949 else:
950 doc = self.markup(
951 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000952 doc = doc and '<dd><tt>%s</tt></dd>' % doc
953 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000954
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000955 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000956 results = []
957 push = results.append
958
959 if name:
960 push('<dl><dt><strong>%s</strong></dt>\n' % name)
961 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000962 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000963 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000964 push('</dl>\n')
965
966 return ''.join(results)
967
968 def docproperty(self, object, name=None, mod=None, cl=None):
969 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000970 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000971
Tim Peters8dd7ade2001-10-18 19:56:17 +0000972 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000973 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000974 lhs = name and '<strong>%s</strong> = ' % name or ''
975 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000976
Barry Warsaw00decd72006-07-27 23:43:15 +0000977 def docdata(self, object, name=None, mod=None, cl=None):
978 """Produce html documentation for a data descriptor."""
979 return self._docdescriptor(name, object, mod)
980
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000981 def index(self, dir, shadowed=None):
982 """Generate an HTML index for a directory of modules."""
983 modpkgs = []
984 if shadowed is None: shadowed = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000985 for importer, name, ispkg in pkgutil.iter_modules([dir]):
986 modpkgs.append((name, '', ispkg, name in shadowed))
987 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000988
989 modpkgs.sort()
990 contents = self.multicolumn(modpkgs, self.modpkglink)
991 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
992
993# -------------------------------------------- text documentation generator
994
995class TextRepr(Repr):
996 """Class for safely making a text representation of a Python object."""
997 def __init__(self):
998 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000999 self.maxlist = self.maxtuple = 20
1000 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001001 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001002
1003 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001004 if hasattr(type(x), '__name__'):
1005 methodname = 'repr_' + join(split(type(x).__name__), '_')
1006 if hasattr(self, methodname):
1007 return getattr(self, methodname)(x, level)
1008 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001009
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001010 def repr_string(self, x, level):
1011 test = cram(x, self.maxstring)
1012 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001013 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001014 # Backslashes are only literal in the string and are never
1015 # needed to make any special characters, so show a raw string.
1016 return 'r' + testrepr[0] + test + testrepr[0]
1017 return testrepr
1018
Skip Montanarodf708782002-03-07 22:58:02 +00001019 repr_str = repr_string
1020
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001021 def repr_instance(self, x, level):
1022 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001023 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001024 except:
1025 return '<%s instance>' % x.__class__.__name__
1026
1027class TextDoc(Doc):
1028 """Formatter class for text documentation."""
1029
1030 # ------------------------------------------- text formatting utilities
1031
1032 _repr_instance = TextRepr()
1033 repr = _repr_instance.repr
1034
1035 def bold(self, text):
1036 """Format a string in bold by overstriking."""
1037 return join(map(lambda ch: ch + '\b' + ch, text), '')
1038
1039 def indent(self, text, prefix=' '):
1040 """Indent text by prepending a given prefix to each line."""
1041 if not text: return ''
1042 lines = split(text, '\n')
1043 lines = map(lambda line, prefix=prefix: prefix + line, lines)
1044 if lines: lines[-1] = rstrip(lines[-1])
1045 return join(lines, '\n')
1046
1047 def section(self, title, contents):
1048 """Format a section with a given heading."""
1049 return self.bold(title) + '\n' + rstrip(self.indent(contents)) + '\n\n'
1050
1051 # ---------------------------------------------- type-specific routines
1052
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001053 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001054 """Render in text a class tree as returned by inspect.getclasstree()."""
1055 result = ''
1056 for entry in tree:
1057 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001058 c, bases = entry
1059 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001060 if bases and bases != (parent,):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001061 parents = map(lambda c, m=modname: classname(c, m), bases)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001062 result = result + '(%s)' % join(parents, ', ')
1063 result = result + '\n'
1064 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001065 result = result + self.formattree(
1066 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001067 return result
1068
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001069 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001070 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001071 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001072 synop, desc = splitdoc(getdoc(object))
1073 result = self.section('NAME', name + (synop and ' - ' + synop))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001074
1075 try:
Skip Montanaroa5616d22004-06-11 04:46:12 +00001076 all = object.__all__
1077 except AttributeError:
1078 all = None
1079
1080 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001081 file = inspect.getabsfile(object)
1082 except TypeError:
1083 file = '(built-in)'
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001084 result = result + self.section('FILE', file)
Skip Montanaro4997a692003-09-10 16:47:51 +00001085
1086 docloc = self.getdocloc(object)
1087 if docloc is not None:
1088 result = result + self.section('MODULE DOCS', docloc)
1089
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001090 if desc:
1091 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001092
1093 classes = []
1094 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001095 # if __all__ exists, believe it. Otherwise use old heuristic.
1096 if (all is not None
1097 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001098 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001099 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001100 funcs = []
1101 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001102 # if __all__ exists, believe it. Otherwise use old heuristic.
1103 if (all is not None or
1104 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001105 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001106 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001107 data = []
1108 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001109 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001110 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001111
Georg Brandlf2dae0e2008-01-21 21:05:49 +00001112 modpkgs = []
1113 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001114 if hasattr(object, '__path__'):
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001115 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Georg Brandlf2dae0e2008-01-21 21:05:49 +00001116 modpkgs_names.add(modname)
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001117 if ispkg:
1118 modpkgs.append(modname + ' (package)')
1119 else:
1120 modpkgs.append(modname)
1121
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001122 modpkgs.sort()
1123 result = result + self.section(
1124 'PACKAGE CONTENTS', join(modpkgs, '\n'))
1125
Georg Brandlf2dae0e2008-01-21 21:05:49 +00001126 # Detect submodules as sometimes created by C extensions
1127 submodules = []
1128 for key, value in inspect.getmembers(object, inspect.ismodule):
1129 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1130 submodules.append(key)
1131 if submodules:
1132 submodules.sort()
1133 result = result + self.section(
1134 'SUBMODULES', join(submodules, '\n'))
1135
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001136 if classes:
Brett Cannonaca98b02008-08-03 00:58:51 +00001137 classlist = map(lambda key_value: key_value[1], classes)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001138 contents = [self.formattree(
1139 inspect.getclasstree(classlist, 1), name)]
1140 for key, value in classes:
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('CLASSES', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001143
1144 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001145 contents = []
1146 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001147 contents.append(self.document(value, key, name))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001148 result = result + self.section('FUNCTIONS', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001149
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001150 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001151 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001152 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001153 contents.append(self.docother(value, key, name, maxlen=70))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001154 result = result + self.section('DATA', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001155
1156 if hasattr(object, '__version__'):
R David Murray984f6302014-01-05 12:35:59 -05001157 version = _binstr(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001158 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
1159 version = strip(version[11:-1])
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001160 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001161 if hasattr(object, '__date__'):
R David Murray984f6302014-01-05 12:35:59 -05001162 result = result + self.section('DATE', _binstr(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001163 if hasattr(object, '__author__'):
R David Murray984f6302014-01-05 12:35:59 -05001164 result = result + self.section('AUTHOR', _binstr(object.__author__))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001165 if hasattr(object, '__credits__'):
R David Murray984f6302014-01-05 12:35:59 -05001166 result = result + self.section('CREDITS', _binstr(object.__credits__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001167 return result
1168
Georg Brandl52f83952011-02-25 10:39:23 +00001169 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001170 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001171 realname = object.__name__
1172 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001173 bases = object.__bases__
1174
Tim Petersc86f6ca2001-09-26 21:31:51 +00001175 def makename(c, m=object.__module__):
1176 return classname(c, m)
1177
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001178 if name == realname:
1179 title = 'class ' + self.bold(realname)
1180 else:
1181 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001182 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001183 parents = map(makename, bases)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001184 title = title + '(%s)' % join(parents, ', ')
1185
1186 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001187 contents = doc and [doc + '\n'] or []
1188 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001189
Tim Petersc86f6ca2001-09-26 21:31:51 +00001190 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001191 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001192 if len(mro) > 2:
1193 push("Method resolution order:")
1194 for base in mro:
1195 push(' ' + makename(base))
1196 push('')
1197
Tim Petersf4aad8e2001-09-24 22:40:47 +00001198 # Cute little class to pump out a horizontal rule between sections.
1199 class HorizontalRule:
1200 def __init__(self):
1201 self.needone = 0
1202 def maybe(self):
1203 if self.needone:
1204 push('-' * 70)
1205 self.needone = 1
1206 hr = HorizontalRule()
1207
Tim Peters28355492001-09-23 21:29:55 +00001208 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001209 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001210 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001211 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001212 push(msg)
1213 for name, kind, homecls, value in ok:
Antoine Pitroub8572a12011-12-21 10:16:14 +01001214 try:
1215 value = getattr(object, name)
1216 except Exception:
1217 # Some descriptors may meet a failure in their __get__.
1218 # (bug #1785)
1219 push(self._docdescriptor(name, value, mod))
1220 else:
1221 push(self.document(value,
1222 name, mod, object))
Tim Peters28355492001-09-23 21:29:55 +00001223 return attrs
1224
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001225 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001226 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001227 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001228 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001229 push(msg)
1230 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001231 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001232 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001233
Tim Petersfa26f7c2001-09-24 08:05:11 +00001234 def spilldata(msg, attrs, predicate):
1235 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001236 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001237 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001238 push(msg)
1239 for name, kind, homecls, value in ok:
Brett Cannonaca98b02008-08-03 00:58:51 +00001240 if (hasattr(value, '__call__') or
1241 inspect.isdatadescriptor(value)):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001242 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001243 else:
1244 doc = None
Tim Peters28355492001-09-23 21:29:55 +00001245 push(self.docother(getattr(object, name),
Georg Brandl8b813db2005-10-01 16:32:31 +00001246 name, mod, maxlen=70, doc=doc) + '\n')
Tim Peters28355492001-09-23 21:29:55 +00001247 return attrs
1248
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001249 attrs = filter(lambda data: visiblename(data[0], obj=object),
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001250 classify_class_attrs(object))
Tim Petersfa26f7c2001-09-24 08:05:11 +00001251 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001252 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001253 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001254 else:
1255 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001256 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1257
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001258 if thisclass is __builtin__.object:
1259 attrs = inherited
1260 continue
1261 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001262 tag = "defined here"
1263 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001264 tag = "inherited from %s" % classname(thisclass,
1265 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001266
1267 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001268 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001269
1270 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001271 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001272 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001273 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001274 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001275 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001276 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001277 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1278 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001279 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1280 lambda t: t[1] == 'data')
Tim Peters28355492001-09-23 21:29:55 +00001281 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001282 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001283
1284 contents = '\n'.join(contents)
1285 if not contents:
1286 return title + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001287 return title + '\n' + self.indent(rstrip(contents), ' | ') + '\n'
1288
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001289 def formatvalue(self, object):
1290 """Format an argument default value as text."""
1291 return '=' + self.repr(object)
1292
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001293 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001294 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001295 realname = object.__name__
1296 name = name or realname
1297 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001298 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001299 if inspect.ismethod(object):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001300 imclass = object.im_class
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001301 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001302 if imclass is not cl:
1303 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001304 else:
Georg Brandl7e2b6bb2007-03-13 22:16:30 +00001305 if object.im_self is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001306 note = ' method of %s instance' % classname(
1307 object.im_self.__class__, mod)
1308 else:
1309 note = ' unbound %s method' % classname(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001310 object = object.im_func
1311
1312 if name == realname:
1313 title = self.bold(realname)
1314 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001315 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001316 cl.__dict__[realname] is object):
1317 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001318 title = self.bold(name) + ' = ' + realname
Tim Peters4bcfa312001-09-20 06:08:24 +00001319 if inspect.isfunction(object):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001320 args, varargs, varkw, defaults = inspect.getargspec(object)
1321 argspec = inspect.formatargspec(
1322 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001323 if realname == '<lambda>':
Georg Brandl501dd0d2006-02-17 09:45:40 +00001324 title = self.bold(name) + ' lambda '
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001325 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +00001326 else:
1327 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001328 decl = title + argspec + note
1329
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001330 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001331 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001332 else:
1333 doc = getdoc(object) or ''
1334 return decl + '\n' + (doc and rstrip(self.indent(doc)) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001335
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001336 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001337 results = []
1338 push = results.append
1339
1340 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001341 push(self.bold(name))
1342 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001343 doc = getdoc(value) or ''
1344 if doc:
1345 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001346 push('\n')
1347 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001348
1349 def docproperty(self, object, name=None, mod=None, cl=None):
1350 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001351 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001352
Barry Warsaw00decd72006-07-27 23:43:15 +00001353 def docdata(self, object, name=None, mod=None, cl=None):
1354 """Produce text documentation for a data descriptor."""
1355 return self._docdescriptor(name, object, mod)
1356
Georg Brandl8b813db2005-10-01 16:32:31 +00001357 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001358 """Produce text documentation for a data object."""
1359 repr = self.repr(object)
1360 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001361 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001362 chop = maxlen - len(line)
1363 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001364 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001365 if doc is not None:
1366 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001367 return line
1368
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001369# --------------------------------------------------------- user interfaces
1370
1371def pager(text):
1372 """The first time this is called, determine what kind of pager to use."""
1373 global pager
1374 pager = getpager()
1375 pager(text)
1376
1377def getpager():
1378 """Decide what method to use for paging through text."""
1379 if type(sys.stdout) is not types.FileType:
1380 return plainpager
Benjamin Peterson75a55c32014-06-07 20:14:26 -07001381 if not hasattr(sys.stdin, "isatty"):
1382 return plainpager
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001383 if not sys.stdin.isatty() or not sys.stdout.isatty():
1384 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001385 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001386 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001387 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001388 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001389 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001390 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001391 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001392 if os.environ.get('TERM') in ('dumb', 'emacs'):
1393 return plainpager
Andrew MacIntyre54e0eab2002-03-03 03:12:30 +00001394 if sys.platform == 'win32' or sys.platform.startswith('os2'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001395 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001396 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001397 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001398
1399 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001400 (fd, filename) = tempfile.mkstemp()
1401 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001402 try:
Georg Brandlb32dea52008-07-16 21:19:28 +00001403 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001404 return lambda text: pipepager(text, 'more')
1405 else:
1406 return ttypager
1407 finally:
1408 os.unlink(filename)
1409
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001410def plain(text):
1411 """Remove boldface formatting from text."""
1412 return re.sub('.\b', '', text)
1413
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001414def pipepager(text, cmd):
1415 """Page through text by feeding it to another program."""
1416 pipe = os.popen(cmd, 'w')
1417 try:
R David Murray984f6302014-01-05 12:35:59 -05001418 pipe.write(_encode(text))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001419 pipe.close()
1420 except IOError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001421 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001422
1423def tempfilepager(text, cmd):
1424 """Page through text by invoking a program on a temporary file."""
1425 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001426 filename = tempfile.mktemp()
1427 file = open(filename, 'w')
R David Murray984f6302014-01-05 12:35:59 -05001428 file.write(_encode(text))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001429 file.close()
1430 try:
Georg Brandlb32dea52008-07-16 21:19:28 +00001431 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001432 finally:
1433 os.unlink(filename)
1434
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001435def ttypager(text):
1436 """Page through text on a text terminal."""
R David Murray984f6302014-01-05 12:35:59 -05001437 lines = plain(_encode(plain(text), getattr(sys.stdout, 'encoding', _encoding))).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001438 try:
1439 import tty
1440 fd = sys.stdin.fileno()
1441 old = tty.tcgetattr(fd)
1442 tty.setcbreak(fd)
1443 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001444 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001445 tty = None
1446 getchar = lambda: sys.stdin.readline()[:-1][:1]
1447
1448 try:
Serhiy Storchaka46e92502014-11-28 00:09:05 +02001449 try:
1450 h = int(os.environ.get('LINES', 0))
1451 except ValueError:
1452 h = 0
1453 if h <= 1:
1454 h = 25
1455 r = inc = h - 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001456 sys.stdout.write(join(lines[:inc], '\n') + '\n')
1457 while lines[r:]:
1458 sys.stdout.write('-- more --')
1459 sys.stdout.flush()
1460 c = getchar()
1461
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001462 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001463 sys.stdout.write('\r \r')
1464 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001465 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001466 sys.stdout.write('\r \r' + lines[r] + '\n')
1467 r = r + 1
1468 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001469 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001470 r = r - inc - inc
1471 if r < 0: r = 0
1472 sys.stdout.write('\n' + join(lines[r:r+inc], '\n') + '\n')
1473 r = r + inc
1474
1475 finally:
1476 if tty:
1477 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1478
1479def plainpager(text):
1480 """Simply print unformatted text. This is the ultimate fallback."""
R David Murray984f6302014-01-05 12:35:59 -05001481 sys.stdout.write(_encode(plain(text), getattr(sys.stdout, 'encoding', _encoding)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001482
1483def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001484 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001485 if inspect.ismodule(thing):
1486 if thing.__name__ in sys.builtin_module_names:
1487 return 'built-in module ' + thing.__name__
1488 if hasattr(thing, '__path__'):
1489 return 'package ' + thing.__name__
1490 else:
1491 return 'module ' + thing.__name__
1492 if inspect.isbuiltin(thing):
1493 return 'built-in function ' + thing.__name__
Barry Warsaw00decd72006-07-27 23:43:15 +00001494 if inspect.isgetsetdescriptor(thing):
1495 return 'getset descriptor %s.%s.%s' % (
1496 thing.__objclass__.__module__, thing.__objclass__.__name__,
1497 thing.__name__)
1498 if inspect.ismemberdescriptor(thing):
1499 return 'member descriptor %s.%s.%s' % (
1500 thing.__objclass__.__module__, thing.__objclass__.__name__,
1501 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001502 if inspect.isclass(thing):
1503 return 'class ' + thing.__name__
1504 if inspect.isfunction(thing):
1505 return 'function ' + thing.__name__
1506 if inspect.ismethod(thing):
1507 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001508 if type(thing) is types.InstanceType:
1509 return 'instance of ' + thing.__class__.__name__
1510 return type(thing).__name__
1511
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001512def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001513 """Locate an object by name or dotted path, importing as necessary."""
Guido van Rossum97dede02003-02-16 01:12:32 +00001514 parts = [part for part in split(path, '.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001515 module, n = None, 0
1516 while n < len(parts):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001517 nextmodule = safeimport(join(parts[:n+1], '.'), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001518 if nextmodule: module, n = nextmodule, n + 1
1519 else: break
1520 if module:
1521 object = module
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001522 else:
Éric Araujo9a528302011-07-29 17:34:35 +02001523 object = __builtin__
1524 for part in parts[n:]:
1525 try:
1526 object = getattr(object, part)
1527 except AttributeError:
1528 return None
1529 return object
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001530
1531# --------------------------------------- interactive interpreter interface
1532
1533text = TextDoc()
1534html = HTMLDoc()
1535
Ka-Ping Yee8ef1cf32007-01-14 04:25:15 +00001536class _OldStyleClass: pass
1537_OLD_INSTANCE_TYPE = type(_OldStyleClass())
1538
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001539def resolve(thing, forceload=0):
1540 """Given an object or a path to an object, get the object and its name."""
1541 if isinstance(thing, str):
1542 object = locate(thing, forceload)
Serhiy Storchakaa8e65752015-04-21 21:09:23 +03001543 if object is None:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001544 raise ImportError, 'no Python documentation found for %r' % thing
1545 return object, thing
1546 else:
R David Murrayc313b1d2012-04-23 13:27:11 -04001547 name = getattr(thing, '__name__', None)
1548 return thing, name if isinstance(name, str) else None
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001549
Georg Brandl8441f152007-03-13 20:02:57 +00001550def render_doc(thing, title='Python Library Documentation: %s', forceload=0):
1551 """Render text documentation, given an object or a path to an object."""
1552 object, name = resolve(thing, forceload)
1553 desc = describe(object)
1554 module = inspect.getmodule(object)
1555 if name and '.' in name:
1556 desc += ' in ' + name[:name.rfind('.')]
1557 elif module and module is not object:
1558 desc += ' in module ' + module.__name__
1559 if type(object) is _OLD_INSTANCE_TYPE:
1560 # If the passed object is an instance of an old-style class,
1561 # document its available methods instead of its value.
1562 object = object.__class__
1563 elif not (inspect.ismodule(object) or
1564 inspect.isclass(object) or
1565 inspect.isroutine(object) or
1566 inspect.isgetsetdescriptor(object) or
1567 inspect.ismemberdescriptor(object) or
1568 isinstance(object, property)):
1569 # If the passed object is a piece of data or an instance,
1570 # document its available methods instead of its value.
1571 object = type(object)
1572 desc += ' object'
1573 return title % desc + '\n\n' + text.document(object, name)
1574
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001575def doc(thing, title='Python Library Documentation: %s', forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001576 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001577 try:
Georg Brandl8441f152007-03-13 20:02:57 +00001578 pager(render_doc(thing, title, forceload))
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001579 except (ImportError, ErrorDuringImport), value:
1580 print value
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001581
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001582def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001583 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001584 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001585 object, name = resolve(thing, forceload)
1586 page = html.page(describe(object), html.document(object, name))
1587 file = open(name + '.html', 'w')
1588 file.write(page)
1589 file.close()
1590 print 'wrote', name + '.html'
1591 except (ImportError, ErrorDuringImport), value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001592 print value
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001593
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001594def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001595 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001596 if done is None: done = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001597 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1598 writedoc(modname)
1599 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001600
1601class Helper:
Georg Brandl681001e2008-06-01 20:33:55 +00001602
1603 # These dictionaries map a topic name to either an alias, or a tuple
1604 # (label, seealso-items). The "label" is the label of the corresponding
1605 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl43819252009-04-26 09:56:44 +00001606 # in pydoc_data/topics.py.
Georg Brandl681001e2008-06-01 20:33:55 +00001607 #
1608 # CAUTION: if you change one of these dictionaries, be sure to adapt the
Georg Brandlf16fbf92014-09-30 22:51:30 +02001609 # list of needed labels in Doc/tools/pyspecific.py and
Georg Brandl43819252009-04-26 09:56:44 +00001610 # regenerate the pydoc_data/topics.py file by running
Georg Brandl681001e2008-06-01 20:33:55 +00001611 # make pydoc-topics
1612 # in Doc/ and copying the output file into the Lib/ directory.
1613
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001614 keywords = {
1615 'and': 'BOOLEAN',
Georg Brandlb6a87542007-03-13 10:06:48 +00001616 'as': 'with',
Georg Brandl681001e2008-06-01 20:33:55 +00001617 'assert': ('assert', ''),
1618 'break': ('break', 'while for'),
1619 'class': ('class', 'CLASSES SPECIALMETHODS'),
1620 'continue': ('continue', 'while for'),
1621 'def': ('function', ''),
1622 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001623 'elif': 'if',
Georg Brandl681001e2008-06-01 20:33:55 +00001624 'else': ('else', 'while for'),
Georg Brandl5c669db2008-08-30 19:03:43 +00001625 'except': 'try',
Georg Brandl681001e2008-06-01 20:33:55 +00001626 'exec': ('exec', ''),
Georg Brandl5c669db2008-08-30 19:03:43 +00001627 'finally': 'try',
Georg Brandl681001e2008-06-01 20:33:55 +00001628 'for': ('for', 'break continue while'),
Georg Brandl5c669db2008-08-30 19:03:43 +00001629 'from': 'import',
Georg Brandl681001e2008-06-01 20:33:55 +00001630 'global': ('global', 'NAMESPACES'),
1631 'if': ('if', 'TRUTHVALUE'),
1632 'import': ('import', 'MODULES'),
1633 'in': ('in', 'SEQUENCEMETHODS2'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001634 'is': 'COMPARISON',
Georg Brandl681001e2008-06-01 20:33:55 +00001635 'lambda': ('lambda', 'FUNCTIONS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001636 'not': 'BOOLEAN',
1637 'or': 'BOOLEAN',
Georg Brandl681001e2008-06-01 20:33:55 +00001638 'pass': ('pass', ''),
1639 'print': ('print', ''),
1640 'raise': ('raise', 'EXCEPTIONS'),
1641 'return': ('return', 'FUNCTIONS'),
1642 'try': ('try', 'EXCEPTIONS'),
1643 'while': ('while', 'break continue if TRUTHVALUE'),
1644 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1645 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001646 }
Georg Brandlc3a98032008-12-27 18:20:04 +00001647 # Either add symbols to this dictionary or to the symbols dictionary
1648 # directly: Whichever is easier. They are merged later.
1649 _symbols_inverse = {
1650 'STRINGS' : ("'", "'''", "r'", "u'", '"""', '"', 'r"', 'u"'),
1651 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1652 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1653 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1654 'UNARY' : ('-', '~'),
1655 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1656 '^=', '<<=', '>>=', '**=', '//='),
1657 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1658 'COMPLEX' : ('j', 'J')
1659 }
1660 symbols = {
1661 '%': 'OPERATORS FORMATTING',
1662 '**': 'POWER',
1663 ',': 'TUPLES LISTS FUNCTIONS',
1664 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1665 '...': 'ELLIPSIS',
1666 ':': 'SLICINGS DICTIONARYLITERALS',
1667 '@': 'def class',
1668 '\\': 'STRINGS',
1669 '_': 'PRIVATENAMES',
1670 '__': 'PRIVATENAMES SPECIALMETHODS',
1671 '`': 'BACKQUOTES',
1672 '(': 'TUPLES FUNCTIONS CALLS',
1673 ')': 'TUPLES FUNCTIONS CALLS',
1674 '[': 'LISTS SUBSCRIPTS SLICINGS',
1675 ']': 'LISTS SUBSCRIPTS SLICINGS'
1676 }
1677 for topic, symbols_ in _symbols_inverse.iteritems():
1678 for symbol in symbols_:
1679 topics = symbols.get(symbol, topic)
1680 if topic not in topics:
1681 topics = topics + ' ' + topic
1682 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001683
1684 topics = {
Georg Brandl681001e2008-06-01 20:33:55 +00001685 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1686 'FUNCTIONS CLASSES MODULES FILES inspect'),
1687 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS FORMATTING '
1688 'TYPES'),
1689 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1690 'FORMATTING': ('formatstrings', 'OPERATORS'),
1691 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1692 'FORMATTING TYPES'),
1693 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1694 'INTEGER': ('integers', 'int range'),
1695 'FLOAT': ('floating', 'float math'),
1696 'COMPLEX': ('imaginary', 'complex cmath'),
1697 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING xrange LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001698 'MAPPINGS': 'DICTIONARIES',
Georg Brandl681001e2008-06-01 20:33:55 +00001699 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1700 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1701 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1702 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001703 'FRAMEOBJECTS': 'TYPES',
1704 'TRACEBACKS': 'TYPES',
Georg Brandl681001e2008-06-01 20:33:55 +00001705 'NONE': ('bltin-null-object', ''),
1706 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
1707 'FILES': ('bltin-file-objects', ''),
1708 'SPECIALATTRIBUTES': ('specialattrs', ''),
1709 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1710 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001711 'PACKAGES': 'import',
Georg Brandl681001e2008-06-01 20:33:55 +00001712 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1713 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1714 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1715 'LISTS DICTIONARIES BACKQUOTES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001716 'OPERATORS': 'EXPRESSIONS',
1717 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl681001e2008-06-01 20:33:55 +00001718 'OBJECTS': ('objects', 'TYPES'),
1719 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
1720 'CALLABLEMETHODS SEQUENCEMETHODS1 MAPPINGMETHODS '
1721 'SEQUENCEMETHODS2 NUMBERMETHODS CLASSES'),
1722 'BASICMETHODS': ('customization', 'cmp hash repr str SPECIALMETHODS'),
1723 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1724 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
1725 'SEQUENCEMETHODS1': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS2 '
1726 'SPECIALMETHODS'),
1727 'SEQUENCEMETHODS2': ('sequence-methods', 'SEQUENCES SEQUENCEMETHODS1 '
1728 'SPECIALMETHODS'),
1729 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1730 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1731 'SPECIALMETHODS'),
1732 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
1733 'NAMESPACES': ('naming', 'global ASSIGNMENT DELETION DYNAMICFEATURES'),
1734 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001735 'SCOPING': 'NAMESPACES',
1736 'FRAMES': 'NAMESPACES',
Georg Brandl681001e2008-06-01 20:33:55 +00001737 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1738 'COERCIONS': ('coercion-rules','CONVERSIONS'),
1739 'CONVERSIONS': ('conversions', 'COERCIONS'),
1740 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1741 'SPECIALIDENTIFIERS': ('id-classes', ''),
1742 'PRIVATENAMES': ('atom-identifiers', ''),
1743 'LITERALS': ('atom-literals', 'STRINGS BACKQUOTES NUMBERS '
1744 'TUPLELITERALS LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001745 'TUPLES': 'SEQUENCES',
Georg Brandl681001e2008-06-01 20:33:55 +00001746 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1747 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1748 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1749 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1750 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1751 'BACKQUOTES': ('string-conversions', 'repr str STRINGS LITERALS'),
1752 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr '
1753 'ATTRIBUTEMETHODS'),
1754 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS1'),
1755 'SLICINGS': ('slicings', 'SEQUENCEMETHODS2'),
1756 'CALLS': ('calls', 'EXPRESSIONS'),
1757 'POWER': ('power', 'EXPRESSIONS'),
1758 'UNARY': ('unary', 'EXPRESSIONS'),
1759 'BINARY': ('binary', 'EXPRESSIONS'),
1760 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1761 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1762 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1763 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001764 'ASSERTION': 'assert',
Georg Brandl681001e2008-06-01 20:33:55 +00001765 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1766 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001767 'DELETION': 'del',
1768 'PRINTING': 'print',
1769 'RETURNING': 'return',
1770 'IMPORTING': 'import',
1771 'CONDITIONAL': 'if',
Georg Brandl681001e2008-06-01 20:33:55 +00001772 'LOOPING': ('compound', 'for while break continue'),
1773 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1774 'DEBUGGING': ('debugger', 'pdb'),
1775 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001776 }
1777
Georg Brandl004c74d2010-08-01 19:06:51 +00001778 def __init__(self, input=None, output=None):
1779 self._input = input
1780 self._output = output
1781
1782 input = property(lambda self: self._input or sys.stdin)
1783 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001784
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001785 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001786 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001787 self()
1788 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001789 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001790
Alexander Belopolskyd501dde2011-01-11 15:35:23 +00001791 _GoInteractive = object()
1792 def __call__(self, request=_GoInteractive):
1793 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001794 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001795 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001796 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001797 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001798 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001799You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001800If you want to ask for help on a particular object directly from the
1801interpreter, you can type "help(object)". Executing "help('string')"
1802has the same effect as typing a particular string at the help> prompt.
1803''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001804
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001805 def interact(self):
1806 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001807 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001808 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001809 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001810 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001811 except (KeyboardInterrupt, EOFError):
1812 break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001813 request = strip(replace(request, '"', '', "'", ''))
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001814 if lower(request) in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001815 self.help(request)
1816
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001817 def getline(self, prompt):
1818 """Read one line, using raw_input when available."""
1819 if self.input is sys.stdin:
1820 return raw_input(prompt)
1821 else:
1822 self.output.write(prompt)
1823 self.output.flush()
1824 return self.input.readline()
1825
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001826 def help(self, request):
1827 if type(request) is type(''):
R. David Murrayd67ea7d2009-05-27 20:07:21 +00001828 request = request.strip()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001829 if request == 'help': self.intro()
1830 elif request == 'keywords': self.listkeywords()
Georg Brandlc3a98032008-12-27 18:20:04 +00001831 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001832 elif request == 'topics': self.listtopics()
1833 elif request == 'modules': self.listmodules()
1834 elif request[:8] == 'modules ':
1835 self.listmodules(split(request)[1])
Georg Brandlc3a98032008-12-27 18:20:04 +00001836 elif request in self.symbols: self.showsymbol(request)
Raymond Hettinger54f02222002-06-01 14:18:47 +00001837 elif request in self.keywords: self.showtopic(request)
1838 elif request in self.topics: self.showtopic(request)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001839 elif request: doc(request, 'Help on %s:')
1840 elif isinstance(request, Helper): self()
1841 else: doc(request, 'Help on %s:')
1842 self.output.write('\n')
1843
1844 def intro(self):
1845 self.output.write('''
1846Welcome to Python %s! This is the online help utility.
1847
1848If this is your first time using Python, you should definitely check out
R David Murray93a224d2012-03-31 12:10:48 -04001849the tutorial on the Internet at http://docs.python.org/%s/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001850
1851Enter the name of any module, keyword, or topic to get help on writing
1852Python programs and using Python modules. To quit this help utility and
1853return to the interpreter, just type "quit".
1854
1855To get a list of available modules, keywords, or topics, type "modules",
1856"keywords", or "topics". Each module also comes with a one-line summary
1857of what it does; to list the modules whose summaries contain a given word
1858such as "spam", type "modules spam".
R David Murray93a224d2012-03-31 12:10:48 -04001859''' % tuple([sys.version[:3]]*2))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001860
1861 def list(self, items, columns=4, width=80):
1862 items = items[:]
1863 items.sort()
1864 colw = width / columns
1865 rows = (len(items) + columns - 1) / columns
1866 for row in range(rows):
1867 for col in range(columns):
1868 i = col * rows + row
1869 if i < len(items):
1870 self.output.write(items[i])
1871 if col < columns - 1:
1872 self.output.write(' ' + ' ' * (colw-1 - len(items[i])))
1873 self.output.write('\n')
1874
1875 def listkeywords(self):
1876 self.output.write('''
1877Here is a list of the Python keywords. Enter any keyword to get more help.
1878
1879''')
1880 self.list(self.keywords.keys())
1881
Georg Brandlc3a98032008-12-27 18:20:04 +00001882 def listsymbols(self):
1883 self.output.write('''
1884Here is a list of the punctuation symbols which Python assigns special meaning
1885to. Enter any symbol to get more help.
1886
1887''')
1888 self.list(self.symbols.keys())
1889
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001890 def listtopics(self):
1891 self.output.write('''
1892Here is a list of available topics. Enter any topic name to get more help.
1893
1894''')
1895 self.list(self.topics.keys())
1896
Georg Brandlc3a98032008-12-27 18:20:04 +00001897 def showtopic(self, topic, more_xrefs=''):
Georg Brandl681001e2008-06-01 20:33:55 +00001898 try:
Georg Brandl43819252009-04-26 09:56:44 +00001899 import pydoc_data.topics
Georg Brandl681001e2008-06-01 20:33:55 +00001900 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001901 self.output.write('''
Georg Brandl681001e2008-06-01 20:33:55 +00001902Sorry, topic and keyword documentation is not available because the
Georg Brandl43819252009-04-26 09:56:44 +00001903module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001904''')
1905 return
1906 target = self.topics.get(topic, self.keywords.get(topic))
1907 if not target:
1908 self.output.write('no documentation found for %s\n' % repr(topic))
1909 return
1910 if type(target) is type(''):
Georg Brandlc3a98032008-12-27 18:20:04 +00001911 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001912
Georg Brandl681001e2008-06-01 20:33:55 +00001913 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001914 try:
Georg Brandl43819252009-04-26 09:56:44 +00001915 doc = pydoc_data.topics.topics[label]
Georg Brandl681001e2008-06-01 20:33:55 +00001916 except KeyError:
1917 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001918 return
Georg Brandl681001e2008-06-01 20:33:55 +00001919 pager(strip(doc) + '\n')
Georg Brandlc3a98032008-12-27 18:20:04 +00001920 if more_xrefs:
1921 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001922 if xrefs:
Georg Brandl681001e2008-06-01 20:33:55 +00001923 import StringIO, formatter
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001924 buffer = StringIO.StringIO()
1925 formatter.DumbWriter(buffer).send_flowing_data(
1926 'Related help topics: ' + join(split(xrefs), ', ') + '\n')
1927 self.output.write('\n%s\n' % buffer.getvalue())
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001928
Georg Brandlc3a98032008-12-27 18:20:04 +00001929 def showsymbol(self, symbol):
1930 target = self.symbols[symbol]
1931 topic, _, xrefs = target.partition(' ')
1932 self.showtopic(topic, xrefs)
1933
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001934 def listmodules(self, key=''):
1935 if key:
1936 self.output.write('''
1937Here is a list of matching modules. Enter any module name to get more help.
1938
1939''')
1940 apropos(key)
1941 else:
1942 self.output.write('''
1943Please wait a moment while I gather a list of all available modules...
1944
1945''')
1946 modules = {}
1947 def callback(path, modname, desc, modules=modules):
1948 if modname and modname[-9:] == '.__init__':
1949 modname = modname[:-9] + ' (package)'
1950 if find(modname, '.') < 0:
1951 modules[modname] = 1
Ka-Ping Yee9e0f1162008-01-13 11:25:13 +00001952 def onerror(modname):
1953 callback(None, modname, None)
1954 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001955 self.list(modules.keys())
1956 self.output.write('''
1957Enter any module name to get more help. Or, type "modules spam" to search
1958for modules whose descriptions contain the word "spam".
1959''')
1960
Georg Brandl004c74d2010-08-01 19:06:51 +00001961help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001962
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001963class Scanner:
1964 """A generic tree iterator."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001965 def __init__(self, roots, children, descendp):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001966 self.roots = roots[:]
1967 self.state = []
1968 self.children = children
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001969 self.descendp = descendp
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001970
1971 def next(self):
1972 if not self.state:
1973 if not self.roots:
1974 return None
1975 root = self.roots.pop(0)
1976 self.state = [(root, self.children(root))]
1977 node, children = self.state[-1]
1978 if not children:
1979 self.state.pop()
1980 return self.next()
1981 child = children.pop(0)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001982 if self.descendp(child):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001983 self.state.append((child, self.children(child)))
1984 return child
1985
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001986
1987class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001988 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001989
Ka-Ping Yee9e0f1162008-01-13 11:25:13 +00001990 def run(self, callback, key=None, completer=None, onerror=None):
Ka-Ping Yee66246962001-04-12 11:59:50 +00001991 if key: key = lower(key)
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001992 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001993 seen = {}
1994
1995 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001996 if modname != '__main__':
1997 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00001998 if key is None:
1999 callback(None, modname, '')
2000 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00002001 desc = split(__import__(modname).__doc__ or '', '\n')[0]
Ka-Ping Yee66246962001-04-12 11:59:50 +00002002 if find(lower(modname + ' - ' + desc), key) >= 0:
2003 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002004
Ka-Ping Yee9e0f1162008-01-13 11:25:13 +00002005 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Phillip J. Ebyceb30872006-04-18 00:59:55 +00002006 if self.quit:
2007 break
2008 if key is None:
2009 callback(None, modname, '')
2010 else:
2011 loader = importer.find_module(modname)
2012 if hasattr(loader,'get_source'):
2013 import StringIO
2014 desc = source_synopsis(
2015 StringIO.StringIO(loader.get_source(modname))
2016 ) or ''
2017 if hasattr(loader,'get_filename'):
2018 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002019 else:
Phillip J. Ebyceb30872006-04-18 00:59:55 +00002020 path = None
2021 else:
2022 module = loader.load_module(modname)
Berker Peksagdc9d41d2015-02-20 12:10:33 +02002023 desc = module.__doc__.splitlines()[0] if module.__doc__ else ''
Phillip J. Ebyceb30872006-04-18 00:59:55 +00002024 path = getattr(module,'__file__',None)
2025 if find(lower(modname + ' - ' + desc), key) >= 0:
2026 callback(path, modname, desc)
2027
2028 if completer:
2029 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002030
2031def apropos(key):
2032 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002033 def callback(path, modname, desc):
2034 if modname[-9:] == '.__init__':
2035 modname = modname[:-9] + ' (package)'
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002036 print modname, desc and '- ' + desc
Ned Deily0096fb52011-10-06 14:17:44 -07002037 def onerror(modname):
2038 pass
2039 with warnings.catch_warnings():
2040 warnings.filterwarnings('ignore') # ignore problems during import
2041 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002042
2043# --------------------------------------------------- web browser interface
2044
Ka-Ping Yee66246962001-04-12 11:59:50 +00002045def serve(port, callback=None, completer=None):
Ka-Ping Yeefd540692001-04-12 12:54:36 +00002046 import BaseHTTPServer, mimetools, select
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002047
2048 # Patch up mimetools.Message so it doesn't break if rfc822 is reloaded.
2049 class Message(mimetools.Message):
2050 def __init__(self, fp, seekable=1):
2051 Message = self.__class__
2052 Message.__bases__[0].__bases__[0].__init__(self, fp, seekable)
2053 self.encodingheader = self.getheader('content-transfer-encoding')
2054 self.typeheader = self.getheader('content-type')
2055 self.parsetype()
2056 self.parseplist()
2057
2058 class DocHandler(BaseHTTPServer.BaseHTTPRequestHandler):
2059 def send_document(self, title, contents):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002060 try:
2061 self.send_response(200)
2062 self.send_header('Content-Type', 'text/html')
2063 self.end_headers()
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002064 self.wfile.write(html.page(title, contents))
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002065 except IOError: pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002066
2067 def do_GET(self):
2068 path = self.path
2069 if path[-5:] == '.html': path = path[:-5]
2070 if path[:1] == '/': path = path[1:]
2071 if path and path != '.':
2072 try:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00002073 obj = locate(path, forceload=1)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002074 except ErrorDuringImport, value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002075 self.send_document(path, html.escape(str(value)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002076 return
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002077 if obj:
2078 self.send_document(describe(obj), html.document(obj, path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002079 else:
2080 self.send_document(path,
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002081'no Python documentation found for %s' % repr(path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002082 else:
2083 heading = html.heading(
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002084'<big><big><strong>Python: Index of Modules</strong></big></big>',
2085'#ffffff', '#7799ee')
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002086 def bltinlink(name):
2087 return '<a href="%s.html">%s</a>' % (name, name)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002088 names = filter(lambda x: x != '__main__',
2089 sys.builtin_module_names)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002090 contents = html.multicolumn(names, bltinlink)
2091 indices = ['<p>' + html.bigsection(
2092 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2093
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002094 seen = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +00002095 for dir in sys.path:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002096 indices.append(html.index(dir, seen))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002097 contents = heading + join(indices) + '''<p align=right>
Tim Peters2306d242001-09-25 03:18:32 +00002098<font color="#909090" face="helvetica, arial"><strong>
2099pydoc</strong> by Ka-Ping Yee &lt;ping@lfw.org&gt;</font>'''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002100 self.send_document('Index of Modules', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002101
2102 def log_message(self, *args): pass
2103
Ka-Ping Yeefd540692001-04-12 12:54:36 +00002104 class DocServer(BaseHTTPServer.HTTPServer):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002105 def __init__(self, port, callback):
Ronald Oussoren9545a232010-05-05 19:09:31 +00002106 host = 'localhost'
Senthil Kumaranaa895452010-08-18 19:35:53 +00002107 self.address = (host, port)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002108 self.callback = callback
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002109 self.base.__init__(self, self.address, self.handler)
2110
2111 def serve_until_quit(self):
2112 import select
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002113 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002114 while not self.quit:
2115 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2116 if rd: self.handle_request()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002117
2118 def server_activate(self):
2119 self.base.server_activate(self)
Serhiy Storchaka86ef95d2014-11-27 23:45:37 +02002120 self.url = 'http://%s:%d/' % (self.address[0], self.server_port)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002121 if self.callback: self.callback(self)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002122
2123 DocServer.base = BaseHTTPServer.HTTPServer
2124 DocServer.handler = DocHandler
2125 DocHandler.MessageClass = Message
2126 try:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002127 try:
2128 DocServer(port, callback).serve_until_quit()
2129 except (KeyboardInterrupt, select.error):
2130 pass
2131 finally:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002132 if completer: completer()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002133
2134# ----------------------------------------------------- graphical interface
2135
2136def gui():
2137 """Graphical interface (starts web server and pops up a control window)."""
2138 class GUI:
2139 def __init__(self, window, port=7464):
2140 self.window = window
2141 self.server = None
2142 self.scanner = None
2143
Georg Brandl6634bf22008-05-20 07:13:37 +00002144 import Tkinter
2145 self.server_frm = Tkinter.Frame(window)
2146 self.title_lbl = Tkinter.Label(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002147 text='Starting server...\n ')
Georg Brandl6634bf22008-05-20 07:13:37 +00002148 self.open_btn = Tkinter.Button(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002149 text='open browser', command=self.open, state='disabled')
Georg Brandl6634bf22008-05-20 07:13:37 +00002150 self.quit_btn = Tkinter.Button(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002151 text='quit serving', command=self.quit, state='disabled')
2152
Georg Brandl6634bf22008-05-20 07:13:37 +00002153 self.search_frm = Tkinter.Frame(window)
2154 self.search_lbl = Tkinter.Label(self.search_frm, text='Search for')
2155 self.search_ent = Tkinter.Entry(self.search_frm)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002156 self.search_ent.bind('<Return>', self.search)
Georg Brandl6634bf22008-05-20 07:13:37 +00002157 self.stop_btn = Tkinter.Button(self.search_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002158 text='stop', pady=0, command=self.stop, state='disabled')
2159 if sys.platform == 'win32':
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002160 # Trying to hide and show this button crashes under Windows.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002161 self.stop_btn.pack(side='right')
2162
2163 self.window.title('pydoc')
2164 self.window.protocol('WM_DELETE_WINDOW', self.quit)
2165 self.title_lbl.pack(side='top', fill='x')
2166 self.open_btn.pack(side='left', fill='x', expand=1)
2167 self.quit_btn.pack(side='right', fill='x', expand=1)
2168 self.server_frm.pack(side='top', fill='x')
2169
2170 self.search_lbl.pack(side='left')
2171 self.search_ent.pack(side='right', fill='x', expand=1)
2172 self.search_frm.pack(side='top', fill='x')
2173 self.search_ent.focus_set()
2174
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002175 font = ('helvetica', sys.platform == 'win32' and 8 or 10)
Georg Brandl6634bf22008-05-20 07:13:37 +00002176 self.result_lst = Tkinter.Listbox(window, font=font, height=6)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002177 self.result_lst.bind('<Button-1>', self.select)
2178 self.result_lst.bind('<Double-Button-1>', self.goto)
Georg Brandl6634bf22008-05-20 07:13:37 +00002179 self.result_scr = Tkinter.Scrollbar(window,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002180 orient='vertical', command=self.result_lst.yview)
2181 self.result_lst.config(yscrollcommand=self.result_scr.set)
2182
Georg Brandl6634bf22008-05-20 07:13:37 +00002183 self.result_frm = Tkinter.Frame(window)
2184 self.goto_btn = Tkinter.Button(self.result_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002185 text='go to selected', command=self.goto)
Georg Brandl6634bf22008-05-20 07:13:37 +00002186 self.hide_btn = Tkinter.Button(self.result_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002187 text='hide results', command=self.hide)
2188 self.goto_btn.pack(side='left', fill='x', expand=1)
2189 self.hide_btn.pack(side='right', fill='x', expand=1)
2190
2191 self.window.update()
2192 self.minwidth = self.window.winfo_width()
2193 self.minheight = self.window.winfo_height()
2194 self.bigminheight = (self.server_frm.winfo_reqheight() +
2195 self.search_frm.winfo_reqheight() +
2196 self.result_lst.winfo_reqheight() +
2197 self.result_frm.winfo_reqheight())
2198 self.bigwidth, self.bigheight = self.minwidth, self.bigminheight
2199 self.expanded = 0
2200 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2201 self.window.wm_minsize(self.minwidth, self.minheight)
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002202 self.window.tk.willdispatch()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002203
2204 import threading
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002205 threading.Thread(
2206 target=serve, args=(port, self.ready, self.quit)).start()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002207
2208 def ready(self, server):
2209 self.server = server
2210 self.title_lbl.config(
2211 text='Python documentation server at\n' + server.url)
2212 self.open_btn.config(state='normal')
2213 self.quit_btn.config(state='normal')
2214
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002215 def open(self, event=None, url=None):
2216 url = url or self.server.url
2217 try:
2218 import webbrowser
2219 webbrowser.open(url)
2220 except ImportError: # pre-webbrowser.py compatibility
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002221 if sys.platform == 'win32':
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002222 os.system('start "%s"' % url)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002223 else:
2224 rc = os.system('netscape -remote "openURL(%s)" &' % url)
2225 if rc: os.system('netscape "%s" &' % url)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002226
2227 def quit(self, event=None):
2228 if self.server:
2229 self.server.quit = 1
2230 self.window.quit()
2231
2232 def search(self, event=None):
2233 key = self.search_ent.get()
2234 self.stop_btn.pack(side='right')
2235 self.stop_btn.config(state='normal')
2236 self.search_lbl.config(text='Searching for "%s"...' % key)
2237 self.search_ent.forget()
2238 self.search_lbl.pack(side='left')
2239 self.result_lst.delete(0, 'end')
2240 self.goto_btn.config(state='disabled')
2241 self.expand()
2242
2243 import threading
2244 if self.scanner:
2245 self.scanner.quit = 1
2246 self.scanner = ModuleScanner()
Martin Panter43415ba2015-11-07 05:41:47 +00002247 def onerror(modname):
2248 pass
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002249 threading.Thread(target=self.scanner.run,
Martin Panter43415ba2015-11-07 05:41:47 +00002250 args=(self.update, key, self.done),
2251 kwargs=dict(onerror=onerror)).start()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002252
2253 def update(self, path, modname, desc):
2254 if modname[-9:] == '.__init__':
2255 modname = modname[:-9] + ' (package)'
2256 self.result_lst.insert('end',
2257 modname + ' - ' + (desc or '(no description)'))
2258
2259 def stop(self, event=None):
2260 if self.scanner:
2261 self.scanner.quit = 1
2262 self.scanner = None
2263
2264 def done(self):
2265 self.scanner = None
2266 self.search_lbl.config(text='Search for')
2267 self.search_lbl.pack(side='left')
2268 self.search_ent.pack(side='right', fill='x', expand=1)
2269 if sys.platform != 'win32': self.stop_btn.forget()
2270 self.stop_btn.config(state='disabled')
2271
2272 def select(self, event=None):
2273 self.goto_btn.config(state='normal')
2274
2275 def goto(self, event=None):
2276 selection = self.result_lst.curselection()
2277 if selection:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002278 modname = split(self.result_lst.get(selection[0]))[0]
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002279 self.open(url=self.server.url + modname + '.html')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002280
2281 def collapse(self):
2282 if not self.expanded: return
2283 self.result_frm.forget()
2284 self.result_scr.forget()
2285 self.result_lst.forget()
2286 self.bigwidth = self.window.winfo_width()
2287 self.bigheight = self.window.winfo_height()
2288 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2289 self.window.wm_minsize(self.minwidth, self.minheight)
2290 self.expanded = 0
2291
2292 def expand(self):
2293 if self.expanded: return
2294 self.result_frm.pack(side='bottom', fill='x')
2295 self.result_scr.pack(side='right', fill='y')
2296 self.result_lst.pack(side='top', fill='both', expand=1)
2297 self.window.wm_geometry('%dx%d' % (self.bigwidth, self.bigheight))
2298 self.window.wm_minsize(self.minwidth, self.bigminheight)
2299 self.expanded = 1
2300
2301 def hide(self, event=None):
2302 self.stop()
2303 self.collapse()
2304
Georg Brandl6634bf22008-05-20 07:13:37 +00002305 import Tkinter
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002306 try:
Georg Brandl6634bf22008-05-20 07:13:37 +00002307 root = Tkinter.Tk()
Martin v. Löwise09bd932004-08-22 16:13:26 +00002308 # Tk will crash if pythonw.exe has an XP .manifest
2309 # file and the root has is not destroyed explicitly.
2310 # If the problem is ever fixed in Tk, the explicit
2311 # destroy can go.
2312 try:
2313 gui = GUI(root)
2314 root.mainloop()
2315 finally:
2316 root.destroy()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002317 except KeyboardInterrupt:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002318 pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002319
2320# -------------------------------------------------- command-line interface
2321
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002322def ispath(x):
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002323 return isinstance(x, str) and find(x, os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002324
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002325def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002326 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002327 import getopt
2328 class BadUsage: pass
2329
Nick Coghlan11db64e2009-11-15 22:36:47 +00002330 # Scripts don't get the current directory in their path by default
2331 # unless they are run with the '-m' switch
2332 if '' not in sys.path:
2333 scriptdir = os.path.dirname(sys.argv[0])
2334 if scriptdir in sys.path:
2335 sys.path.remove(scriptdir)
2336 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002337
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002338 try:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002339 opts, args = getopt.getopt(sys.argv[1:], 'gk:p:w')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002340 writing = 0
2341
2342 for opt, val in opts:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002343 if opt == '-g':
2344 gui()
2345 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002346 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002347 apropos(val)
2348 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002349 if opt == '-p':
2350 try:
2351 port = int(val)
2352 except ValueError:
2353 raise BadUsage
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002354 def ready(server):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002355 print 'pydoc server ready at %s' % server.url
2356 def stopped():
2357 print 'pydoc server stopped'
2358 serve(port, ready, stopped)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002359 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002360 if opt == '-w':
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002361 writing = 1
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002362
2363 if not args: raise BadUsage
2364 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002365 if ispath(arg) and not os.path.exists(arg):
2366 print 'file %r does not exist' % arg
2367 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002368 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002369 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002370 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002371 if writing:
2372 if ispath(arg) and os.path.isdir(arg):
2373 writedocs(arg)
2374 else:
2375 writedoc(arg)
2376 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002377 help.help(arg)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002378 except ErrorDuringImport, value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002379 print value
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002380
2381 except (getopt.error, BadUsage):
Martin v. Löwisf9b08b82003-10-31 13:05:21 +00002382 cmd = os.path.basename(sys.argv[0])
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002383 print """pydoc - the Python documentation tool
2384
2385%s <name> ...
2386 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002387 Python keyword, topic, function, module, or package, or a dotted
2388 reference to a class or function within a module or module in a
2389 package. If <name> contains a '%s', it is used as the path to a
2390 Python source file to document. If name is 'keywords', 'topics',
2391 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002392
2393%s -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002394 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002395
2396%s -p <port>
Serhiy Storchaka86ef95d2014-11-27 23:45:37 +02002397 Start an HTTP server on the given port on the local machine. Port
2398 number 0 can be used to get an arbitrary unused port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002399
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002400%s -g
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002401 Pop up a graphical interface for finding and serving documentation.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002402
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002403%s -w <name> ...
2404 Write out the HTML documentation for a module to a file in the current
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002405 directory. If <name> contains a '%s', it is treated as a filename; if
2406 it names a directory, documentation is written for all the contents.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002407""" % (cmd, os.sep, cmd, cmd, cmd, cmd, os.sep)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002408
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002409if __name__ == '__main__': cli()