blob: b4b190f3f9a6597b08c5ed2984e34a123d661c7d [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
Martin Pantere52140c2016-06-12 05:25:16 +000031 https://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
Martin Pantere52140c2016-06-12 05:25:16 +0000377 def getdocloc(self, object,
378 basedir=os.path.join(sys.exec_prefix, "lib",
379 "python"+sys.version[0:3])):
Skip Montanaro4997a692003-09-10 16:47:51 +0000380 """Return the location of module docs or None"""
381
382 try:
383 file = inspect.getabsfile(object)
384 except TypeError:
385 file = '(built-in)'
386
387 docloc = os.environ.get("PYTHONDOCS",
Martin Pantere52140c2016-06-12 05:25:16 +0000388 "https://docs.python.org/library")
389 basedir = os.path.normcase(basedir)
Skip Montanaro4997a692003-09-10 16:47:51 +0000390 if (isinstance(object, type(os)) and
391 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
392 'marshal', 'posix', 'signal', 'sys',
393 'thread', 'zipimport') or
394 (file.startswith(basedir) and
Brian Curtinaeb2e822010-03-31 03:10:21 +0000395 not file.startswith(os.path.join(basedir, 'site-packages')))) and
Brian Curtina01da932010-04-01 04:02:00 +0000396 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
Martin Pantere52140c2016-06-12 05:25:16 +0000397 if docloc.startswith(("http://", "https://")):
398 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__.lower())
Skip Montanaro4997a692003-09-10 16:47:51 +0000399 else:
Martin Pantere52140c2016-06-12 05:25:16 +0000400 docloc = os.path.join(docloc, object.__name__.lower() + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000401 else:
402 docloc = None
403 return docloc
404
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000405# -------------------------------------------- HTML documentation generator
406
407class HTMLRepr(Repr):
408 """Class for safely making an HTML representation of a Python object."""
409 def __init__(self):
410 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000411 self.maxlist = self.maxtuple = 20
412 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000413 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000414
415 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000416 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000417
418 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000419 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000420
421 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000422 if hasattr(type(x), '__name__'):
423 methodname = 'repr_' + join(split(type(x).__name__), '_')
424 if hasattr(self, methodname):
425 return getattr(self, methodname)(x, level)
426 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000427
428 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000429 test = cram(x, self.maxstring)
430 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000431 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000432 # Backslashes are only literal in the string and are never
433 # needed to make any special characters, so show a raw string.
434 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000435 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000436 r'<font color="#c040c0">\1</font>',
437 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000438
Skip Montanarodf708782002-03-07 22:58:02 +0000439 repr_str = repr_string
440
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000441 def repr_instance(self, x, level):
442 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000443 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000444 except:
445 return self.escape('<%s instance>' % x.__class__.__name__)
446
447 repr_unicode = repr_string
448
449class HTMLDoc(Doc):
450 """Formatter class for HTML documentation."""
451
452 # ------------------------------------------- HTML formatting utilities
453
454 _repr_instance = HTMLRepr()
455 repr = _repr_instance.repr
456 escape = _repr_instance.escape
457
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000458 def page(self, title, contents):
459 """Format an HTML page."""
R David Murray984f6302014-01-05 12:35:59 -0500460 return _encode('''
Georg Brandle0197062009-04-10 08:20:23 +0000461<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000462<html><head><title>Python: %s</title>
R David Murray984f6302014-01-05 12:35:59 -0500463<meta charset="utf-8">
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000464</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000465%s
R David Murray984f6302014-01-05 12:35:59 -0500466</body></html>''' % (title, contents), 'ascii')
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000467
468 def heading(self, title, fgcol, bgcol, extras=''):
469 """Format a page heading."""
470 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000471<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000472<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000473<td valign=bottom>&nbsp;<br>
474<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000475><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000476><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000477 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
478
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000479 def section(self, title, fgcol, bgcol, contents, width=6,
480 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000481 """Format a section with a heading."""
482 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000483 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000484 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000485<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000486<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000487<td colspan=3 valign=bottom>&nbsp;<br>
488<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000489 ''' % (bgcol, fgcol, title)
490 if prelude:
491 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000492<tr bgcolor="%s"><td rowspan=2>%s</td>
493<td colspan=2>%s</td></tr>
494<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
495 else:
496 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000497<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000498
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000499 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000500
501 def bigsection(self, title, *args):
502 """Format a section with a big heading."""
503 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000504 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000505
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000506 def preformat(self, text):
507 """Format literal preformatted text."""
508 text = self.escape(expandtabs(text))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000509 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
510 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000511
512 def multicolumn(self, list, format, cols=4):
513 """Format a list of items into a multi-column list."""
514 result = ''
Victor Stinnerdbfba162011-05-26 13:37:25 +0200515 rows = (len(list)+cols-1)//cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000516 for col in range(cols):
Victor Stinnerdbfba162011-05-26 13:37:25 +0200517 result = result + '<td width="%d%%" valign=top>' % (100//cols)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000518 for i in range(rows*col, rows*col+rows):
519 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000520 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000521 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000522 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000523
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000524 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000525
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000526 def namelink(self, name, *dicts):
527 """Make a link for an identifier, given name-to-URL mappings."""
528 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000529 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000530 return '<a href="%s">%s</a>' % (dict[name], name)
531 return name
532
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000533 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000534 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000535 name, module = object.__name__, sys.modules.get(object.__module__)
536 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000537 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000538 module.__name__, name, classname(object, modname))
539 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000540
541 def modulelink(self, object):
542 """Make a link for a module."""
543 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
544
Brett Cannonaca98b02008-08-03 00:58:51 +0000545 def modpkglink(self, data):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000546 """Make a link for a module or package to display in an index."""
Brett Cannonaca98b02008-08-03 00:58:51 +0000547 name, path, ispackage, shadowed = data
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000548 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000549 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000550 if path:
551 url = '%s.%s.html' % (path, name)
552 else:
553 url = '%s.html' % name
554 if ispackage:
555 text = '<strong>%s</strong>&nbsp;(package)' % name
556 else:
557 text = name
558 return '<a href="%s">%s</a>' % (url, text)
559
560 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
561 """Mark up some plain text, given a context of symbols to look for.
562 Each context dictionary maps object names to anchor names."""
563 escape = escape or self.escape
564 results = []
565 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000566 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
567 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000568 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000569 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000570 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000571 match = pattern.search(text, here)
572 if not match: break
573 start, end = match.span()
574 results.append(escape(text[here:start]))
575
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000576 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000577 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000578 url = escape(all).replace('"', '&quot;')
579 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000580 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000581 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
582 results.append('<a href="%s">%s</a>' % (url, escape(all)))
583 elif pep:
Andrew M. Kuchling727a5902008-02-05 16:06:57 +0000584 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000585 results.append('<a href="%s">%s</a>' % (url, escape(all)))
Benjamin Petersonc3e1e902014-06-07 16:44:00 -0700586 elif selfdot:
587 # Create a link for methods like 'self.method(...)'
588 # and use <strong> for attributes like 'self.attr'
589 if text[end:end+1] == '(':
590 results.append('self.' + self.namelink(name, methods))
591 else:
592 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000593 elif text[end:end+1] == '(':
594 results.append(self.namelink(name, methods, funcs, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000595 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000596 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000597 here = end
598 results.append(escape(text[here:]))
599 return join(results, '')
600
601 # ---------------------------------------------- type-specific routines
602
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000603 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000604 """Produce HTML for a class tree as given by inspect.getclasstree()."""
605 result = ''
606 for entry in tree:
607 if type(entry) is type(()):
608 c, bases = entry
Tim Peters2306d242001-09-25 03:18:32 +0000609 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000610 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000611 if bases and bases != (parent,):
612 parents = []
613 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000614 parents.append(self.classlink(base, modname))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000615 result = result + '(' + join(parents, ', ') + ')'
Tim Peters2306d242001-09-25 03:18:32 +0000616 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000617 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000618 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000619 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000620 return '<dl>\n%s</dl>\n' % result
621
Tim Peters8dd7ade2001-10-18 19:56:17 +0000622 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000623 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000624 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000625 try:
626 all = object.__all__
627 except AttributeError:
628 all = None
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000629 parts = split(name, '.')
630 links = []
631 for i in range(len(parts)-1):
632 links.append(
633 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
634 (join(parts[:i+1], '.'), parts[i]))
635 linkedname = join(links + parts[-1:], '.')
636 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000637 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000638 path = inspect.getabsfile(object)
Ka-Ping Yee6191a232001-04-13 15:00:27 +0000639 url = path
640 if sys.platform == 'win32':
641 import nturl2path
642 url = nturl2path.pathname2url(path)
643 filelink = '<a href="file:%s">%s</a>' % (url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000644 except TypeError:
645 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000646 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000647 if hasattr(object, '__version__'):
R David Murray984f6302014-01-05 12:35:59 -0500648 version = _binstr(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000649 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
650 version = strip(version[11:-1])
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000651 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000652 if hasattr(object, '__date__'):
R David Murray984f6302014-01-05 12:35:59 -0500653 info.append(self.escape(_binstr(object.__date__)))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000654 if info:
655 head = head + ' (%s)' % join(info, ', ')
Skip Montanaro4997a692003-09-10 16:47:51 +0000656 docloc = self.getdocloc(object)
657 if docloc is not None:
658 docloc = '<br><a href="%(docloc)s">Module Docs</a>' % locals()
659 else:
660 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000661 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000662 head, '#ffffff', '#7799ee',
663 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000664
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000665 modules = inspect.getmembers(object, inspect.ismodule)
666
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000667 classes, cdict = [], {}
668 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000669 # if __all__ exists, believe it. Otherwise use old heuristic.
670 if (all is not None or
671 (inspect.getmodule(value) or object) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700672 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000673 classes.append((key, value))
674 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000675 for key, value in classes:
676 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000677 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000678 module = sys.modules.get(modname)
679 if modname != name and module and hasattr(module, key):
680 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000681 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000682 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000683 funcs, fdict = [], {}
684 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000685 # if __all__ exists, believe it. Otherwise use old heuristic.
686 if (all is not None or
687 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700688 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000689 funcs.append((key, value))
690 fdict[key] = '#-' + key
691 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000692 data = []
693 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700694 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000695 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000696
697 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
698 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000699 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000700
701 if hasattr(object, '__path__'):
702 modpkgs = []
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000703 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
704 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000705 modpkgs.sort()
706 contents = self.multicolumn(modpkgs, self.modpkglink)
707 result = result + self.bigsection(
708 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000709 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000710 contents = self.multicolumn(
Brett Cannonaca98b02008-08-03 00:58:51 +0000711 modules, lambda key_value, s=self: s.modulelink(key_value[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000712 result = result + self.bigsection(
Georg Brandlb169eaa2008-02-17 21:18:55 +0000713 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000714
715 if classes:
Brett Cannonaca98b02008-08-03 00:58:51 +0000716 classlist = map(lambda key_value: key_value[1], classes)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000717 contents = [
718 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000719 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000720 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000721 result = result + self.bigsection(
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000722 'Classes', '#ffffff', '#ee77aa', join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000723 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000724 contents = []
725 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000726 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000727 result = result + self.bigsection(
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000728 'Functions', '#ffffff', '#eeaa77', join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000729 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000730 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000731 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000732 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000733 result = result + self.bigsection(
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000734 'Data', '#ffffff', '#55aa55', join(contents, '<br>\n'))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000735 if hasattr(object, '__author__'):
R David Murray984f6302014-01-05 12:35:59 -0500736 contents = self.markup(_binstr(object.__author__), self.preformat)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000737 result = result + self.bigsection(
738 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000739 if hasattr(object, '__credits__'):
R David Murray984f6302014-01-05 12:35:59 -0500740 contents = self.markup(_binstr(object.__credits__), self.preformat)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000741 result = result + self.bigsection(
742 'Credits', '#ffffff', '#7799ee', contents)
743
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000744 return result
745
Tim Peters8dd7ade2001-10-18 19:56:17 +0000746 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
747 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000748 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000749 realname = object.__name__
750 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000751 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000752
Tim Petersb47879b2001-09-24 04:47:19 +0000753 contents = []
754 push = contents.append
755
Tim Petersfa26f7c2001-09-24 08:05:11 +0000756 # Cute little class to pump out a horizontal rule between sections.
757 class HorizontalRule:
758 def __init__(self):
759 self.needone = 0
760 def maybe(self):
761 if self.needone:
762 push('<hr>\n')
763 self.needone = 1
764 hr = HorizontalRule()
765
Tim Petersc86f6ca2001-09-26 21:31:51 +0000766 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000767 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000768 if len(mro) > 2:
769 hr.maybe()
770 push('<dl><dt>Method resolution order:</dt>\n')
771 for base in mro:
772 push('<dd>%s</dd>\n' % self.classlink(base,
773 object.__module__))
774 push('</dl>\n')
775
Tim Petersb47879b2001-09-24 04:47:19 +0000776 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000777 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000778 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000779 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000780 push(msg)
781 for name, kind, homecls, value in ok:
Antoine Pitroub8572a12011-12-21 10:16:14 +0100782 try:
783 value = getattr(object, name)
784 except Exception:
785 # Some descriptors may meet a failure in their __get__.
786 # (bug #1785)
787 push(self._docdescriptor(name, value, mod))
788 else:
789 push(self.document(value, name, mod,
790 funcs, classes, mdict, object))
Tim Petersb47879b2001-09-24 04:47:19 +0000791 push('\n')
792 return attrs
793
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000794 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000795 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000796 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000797 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000798 push(msg)
799 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000800 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000801 return attrs
802
Tim Petersfa26f7c2001-09-24 08:05:11 +0000803 def spilldata(msg, attrs, predicate):
804 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000805 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000806 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000807 push(msg)
808 for name, kind, homecls, value in ok:
809 base = self.docother(getattr(object, name), name, mod)
Brett Cannonaca98b02008-08-03 00:58:51 +0000810 if (hasattr(value, '__call__') or
811 inspect.isdatadescriptor(value)):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000812 doc = getattr(value, "__doc__", None)
813 else:
814 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000815 if doc is None:
816 push('<dl><dt>%s</dl>\n' % base)
817 else:
818 doc = self.markup(getdoc(value), self.preformat,
819 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000820 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000821 push('<dl><dt>%s%s</dl>\n' % (base, doc))
822 push('\n')
823 return attrs
824
Raymond Hettinger9aa5a342011-03-25 16:00:13 -0700825 attrs = filter(lambda data: visiblename(data[0], obj=object),
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000826 classify_class_attrs(object))
Tim Petersb47879b2001-09-24 04:47:19 +0000827 mdict = {}
828 for key, kind, homecls, value in attrs:
829 mdict[key] = anchor = '#' + name + '-' + key
Antoine Pitroub8572a12011-12-21 10:16:14 +0100830 try:
831 value = getattr(object, name)
832 except Exception:
833 # Some descriptors may meet a failure in their __get__.
834 # (bug #1785)
835 pass
Tim Petersb47879b2001-09-24 04:47:19 +0000836 try:
837 # The value may not be hashable (e.g., a data attr with
838 # a dict or list value).
839 mdict[value] = anchor
840 except TypeError:
841 pass
842
Tim Petersfa26f7c2001-09-24 08:05:11 +0000843 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000844 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000845 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000846 else:
847 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000848 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
849
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000850 if thisclass is __builtin__.object:
851 attrs = inherited
852 continue
853 elif thisclass is object:
854 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000855 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000856 tag = 'inherited from %s' % self.classlink(thisclass,
857 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000858 tag += ':<br>\n'
859
860 # Sort attrs by name.
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000861 try:
862 attrs.sort(key=lambda t: t[0])
863 except TypeError:
864 attrs.sort(lambda t1, t2: cmp(t1[0], t2[0])) # 2.3 compat
Tim Petersb47879b2001-09-24 04:47:19 +0000865
866 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000867 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000868 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000869 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000870 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000871 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000872 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000873 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
874 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000875 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000876 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000877 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000878 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000879
880 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000881
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000882 if name == realname:
883 title = '<a name="%s">class <strong>%s</strong></a>' % (
884 name, realname)
885 else:
886 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
887 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000888 if bases:
889 parents = []
890 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000891 parents.append(self.classlink(base, object.__module__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000892 title = title + '(%s)' % join(parents, ', ')
Tim Peters2306d242001-09-25 03:18:32 +0000893 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000894 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000895
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000896 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000897
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000898 def formatvalue(self, object):
899 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000900 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000901
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000902 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000903 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000904 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000905 realname = object.__name__
906 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000907 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000908 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000909 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000910 if inspect.ismethod(object):
Ka-Ping Yee6dcfa382001-04-12 20:27:31 +0000911 imclass = object.im_class
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000912 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000913 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000914 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000915 else:
Georg Brandl7e2b6bb2007-03-13 22:16:30 +0000916 if object.im_self is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000917 note = ' method of %s instance' % self.classlink(
918 object.im_self.__class__, mod)
919 else:
920 note = ' unbound %s method' % self.classlink(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000921 object = object.im_func
922
923 if name == realname:
924 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
925 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000926 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000927 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000928 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000929 cl.__name__ + '-' + realname, realname)
930 skipdocs = 1
931 else:
932 reallink = realname
933 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
934 anchor, name, reallink)
Tim Peters4bcfa312001-09-20 06:08:24 +0000935 if inspect.isfunction(object):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000936 args, varargs, varkw, defaults = inspect.getargspec(object)
937 argspec = inspect.formatargspec(
938 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000939 if realname == '<lambda>':
Tim Peters59ed4482001-10-31 04:20:26 +0000940 title = '<strong>%s</strong> <em>lambda</em> ' % name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000941 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +0000942 else:
943 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000944
Tim Peters2306d242001-09-25 03:18:32 +0000945 decl = title + argspec + (note and self.grey(
946 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000947
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000948 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000949 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000950 else:
951 doc = self.markup(
952 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000953 doc = doc and '<dd><tt>%s</tt></dd>' % doc
954 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000955
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000956 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000957 results = []
958 push = results.append
959
960 if name:
961 push('<dl><dt><strong>%s</strong></dt>\n' % name)
962 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000963 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000964 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000965 push('</dl>\n')
966
967 return ''.join(results)
968
969 def docproperty(self, object, name=None, mod=None, cl=None):
970 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000971 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000972
Tim Peters8dd7ade2001-10-18 19:56:17 +0000973 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000974 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000975 lhs = name and '<strong>%s</strong> = ' % name or ''
976 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000977
Barry Warsaw00decd72006-07-27 23:43:15 +0000978 def docdata(self, object, name=None, mod=None, cl=None):
979 """Produce html documentation for a data descriptor."""
980 return self._docdescriptor(name, object, mod)
981
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000982 def index(self, dir, shadowed=None):
983 """Generate an HTML index for a directory of modules."""
984 modpkgs = []
985 if shadowed is None: shadowed = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +0000986 for importer, name, ispkg in pkgutil.iter_modules([dir]):
987 modpkgs.append((name, '', ispkg, name in shadowed))
988 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000989
990 modpkgs.sort()
991 contents = self.multicolumn(modpkgs, self.modpkglink)
992 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
993
994# -------------------------------------------- text documentation generator
995
996class TextRepr(Repr):
997 """Class for safely making a text representation of a Python object."""
998 def __init__(self):
999 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001000 self.maxlist = self.maxtuple = 20
1001 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001002 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001003
1004 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001005 if hasattr(type(x), '__name__'):
1006 methodname = 'repr_' + join(split(type(x).__name__), '_')
1007 if hasattr(self, methodname):
1008 return getattr(self, methodname)(x, level)
1009 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001010
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001011 def repr_string(self, x, level):
1012 test = cram(x, self.maxstring)
1013 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001014 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001015 # Backslashes are only literal in the string and are never
1016 # needed to make any special characters, so show a raw string.
1017 return 'r' + testrepr[0] + test + testrepr[0]
1018 return testrepr
1019
Skip Montanarodf708782002-03-07 22:58:02 +00001020 repr_str = repr_string
1021
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001022 def repr_instance(self, x, level):
1023 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001024 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001025 except:
1026 return '<%s instance>' % x.__class__.__name__
1027
1028class TextDoc(Doc):
1029 """Formatter class for text documentation."""
1030
1031 # ------------------------------------------- text formatting utilities
1032
1033 _repr_instance = TextRepr()
1034 repr = _repr_instance.repr
1035
1036 def bold(self, text):
1037 """Format a string in bold by overstriking."""
1038 return join(map(lambda ch: ch + '\b' + ch, text), '')
1039
1040 def indent(self, text, prefix=' '):
1041 """Indent text by prepending a given prefix to each line."""
1042 if not text: return ''
1043 lines = split(text, '\n')
1044 lines = map(lambda line, prefix=prefix: prefix + line, lines)
1045 if lines: lines[-1] = rstrip(lines[-1])
1046 return join(lines, '\n')
1047
1048 def section(self, title, contents):
1049 """Format a section with a given heading."""
1050 return self.bold(title) + '\n' + rstrip(self.indent(contents)) + '\n\n'
1051
1052 # ---------------------------------------------- type-specific routines
1053
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001054 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001055 """Render in text a class tree as returned by inspect.getclasstree()."""
1056 result = ''
1057 for entry in tree:
1058 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001059 c, bases = entry
1060 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001061 if bases and bases != (parent,):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001062 parents = map(lambda c, m=modname: classname(c, m), bases)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001063 result = result + '(%s)' % join(parents, ', ')
1064 result = result + '\n'
1065 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001066 result = result + self.formattree(
1067 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001068 return result
1069
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001070 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001071 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001072 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001073 synop, desc = splitdoc(getdoc(object))
1074 result = self.section('NAME', name + (synop and ' - ' + synop))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001075
1076 try:
Skip Montanaroa5616d22004-06-11 04:46:12 +00001077 all = object.__all__
1078 except AttributeError:
1079 all = None
1080
1081 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001082 file = inspect.getabsfile(object)
1083 except TypeError:
1084 file = '(built-in)'
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001085 result = result + self.section('FILE', file)
Skip Montanaro4997a692003-09-10 16:47:51 +00001086
1087 docloc = self.getdocloc(object)
1088 if docloc is not None:
1089 result = result + self.section('MODULE DOCS', docloc)
1090
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001091 if desc:
1092 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001093
1094 classes = []
1095 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001096 # if __all__ exists, believe it. Otherwise use old heuristic.
1097 if (all is not None
1098 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001099 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001100 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001101 funcs = []
1102 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001103 # if __all__ exists, believe it. Otherwise use old heuristic.
1104 if (all is not None or
1105 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001106 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001107 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001108 data = []
1109 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001110 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001111 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001112
Georg Brandlf2dae0e2008-01-21 21:05:49 +00001113 modpkgs = []
1114 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001115 if hasattr(object, '__path__'):
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001116 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Georg Brandlf2dae0e2008-01-21 21:05:49 +00001117 modpkgs_names.add(modname)
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001118 if ispkg:
1119 modpkgs.append(modname + ' (package)')
1120 else:
1121 modpkgs.append(modname)
1122
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001123 modpkgs.sort()
1124 result = result + self.section(
1125 'PACKAGE CONTENTS', join(modpkgs, '\n'))
1126
Georg Brandlf2dae0e2008-01-21 21:05:49 +00001127 # Detect submodules as sometimes created by C extensions
1128 submodules = []
1129 for key, value in inspect.getmembers(object, inspect.ismodule):
1130 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1131 submodules.append(key)
1132 if submodules:
1133 submodules.sort()
1134 result = result + self.section(
1135 'SUBMODULES', join(submodules, '\n'))
1136
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001137 if classes:
Brett Cannonaca98b02008-08-03 00:58:51 +00001138 classlist = map(lambda key_value: key_value[1], classes)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001139 contents = [self.formattree(
1140 inspect.getclasstree(classlist, 1), name)]
1141 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001142 contents.append(self.document(value, key, name))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001143 result = result + self.section('CLASSES', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001144
1145 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001146 contents = []
1147 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001148 contents.append(self.document(value, key, name))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001149 result = result + self.section('FUNCTIONS', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001150
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001151 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001152 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001153 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001154 contents.append(self.docother(value, key, name, maxlen=70))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001155 result = result + self.section('DATA', join(contents, '\n'))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001156
1157 if hasattr(object, '__version__'):
R David Murray984f6302014-01-05 12:35:59 -05001158 version = _binstr(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001159 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
1160 version = strip(version[11:-1])
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001161 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001162 if hasattr(object, '__date__'):
R David Murray984f6302014-01-05 12:35:59 -05001163 result = result + self.section('DATE', _binstr(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001164 if hasattr(object, '__author__'):
R David Murray984f6302014-01-05 12:35:59 -05001165 result = result + self.section('AUTHOR', _binstr(object.__author__))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001166 if hasattr(object, '__credits__'):
R David Murray984f6302014-01-05 12:35:59 -05001167 result = result + self.section('CREDITS', _binstr(object.__credits__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001168 return result
1169
Georg Brandl52f83952011-02-25 10:39:23 +00001170 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001171 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001172 realname = object.__name__
1173 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001174 bases = object.__bases__
1175
Tim Petersc86f6ca2001-09-26 21:31:51 +00001176 def makename(c, m=object.__module__):
1177 return classname(c, m)
1178
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001179 if name == realname:
1180 title = 'class ' + self.bold(realname)
1181 else:
1182 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001183 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001184 parents = map(makename, bases)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001185 title = title + '(%s)' % join(parents, ', ')
1186
1187 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001188 contents = doc and [doc + '\n'] or []
1189 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001190
Tim Petersc86f6ca2001-09-26 21:31:51 +00001191 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001192 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001193 if len(mro) > 2:
1194 push("Method resolution order:")
1195 for base in mro:
1196 push(' ' + makename(base))
1197 push('')
1198
Tim Petersf4aad8e2001-09-24 22:40:47 +00001199 # Cute little class to pump out a horizontal rule between sections.
1200 class HorizontalRule:
1201 def __init__(self):
1202 self.needone = 0
1203 def maybe(self):
1204 if self.needone:
1205 push('-' * 70)
1206 self.needone = 1
1207 hr = HorizontalRule()
1208
Tim Peters28355492001-09-23 21:29:55 +00001209 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001210 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001211 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001212 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001213 push(msg)
1214 for name, kind, homecls, value in ok:
Antoine Pitroub8572a12011-12-21 10:16:14 +01001215 try:
1216 value = getattr(object, name)
1217 except Exception:
1218 # Some descriptors may meet a failure in their __get__.
1219 # (bug #1785)
1220 push(self._docdescriptor(name, value, mod))
1221 else:
1222 push(self.document(value,
1223 name, mod, object))
Tim Peters28355492001-09-23 21:29:55 +00001224 return attrs
1225
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001226 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001227 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001228 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001229 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001230 push(msg)
1231 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001232 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001233 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001234
Tim Petersfa26f7c2001-09-24 08:05:11 +00001235 def spilldata(msg, attrs, predicate):
1236 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001237 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001238 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001239 push(msg)
1240 for name, kind, homecls, value in ok:
Brett Cannonaca98b02008-08-03 00:58:51 +00001241 if (hasattr(value, '__call__') or
1242 inspect.isdatadescriptor(value)):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001243 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001244 else:
1245 doc = None
Tim Peters28355492001-09-23 21:29:55 +00001246 push(self.docother(getattr(object, name),
Georg Brandl8b813db2005-10-01 16:32:31 +00001247 name, mod, maxlen=70, doc=doc) + '\n')
Tim Peters28355492001-09-23 21:29:55 +00001248 return attrs
1249
Raymond Hettinger9aa5a342011-03-25 16:00:13 -07001250 attrs = filter(lambda data: visiblename(data[0], obj=object),
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001251 classify_class_attrs(object))
Tim Petersfa26f7c2001-09-24 08:05:11 +00001252 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001253 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001254 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001255 else:
1256 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001257 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1258
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001259 if thisclass is __builtin__.object:
1260 attrs = inherited
1261 continue
1262 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001263 tag = "defined here"
1264 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001265 tag = "inherited from %s" % classname(thisclass,
1266 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001267
1268 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001269 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001270
1271 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001272 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001273 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001274 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001275 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001276 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001277 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001278 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1279 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001280 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1281 lambda t: t[1] == 'data')
Tim Peters28355492001-09-23 21:29:55 +00001282 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001283 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001284
1285 contents = '\n'.join(contents)
1286 if not contents:
1287 return title + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001288 return title + '\n' + self.indent(rstrip(contents), ' | ') + '\n'
1289
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001290 def formatvalue(self, object):
1291 """Format an argument default value as text."""
1292 return '=' + self.repr(object)
1293
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001294 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001295 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001296 realname = object.__name__
1297 name = name or realname
1298 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001299 skipdocs = 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001300 if inspect.ismethod(object):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001301 imclass = object.im_class
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001302 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001303 if imclass is not cl:
1304 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001305 else:
Georg Brandl7e2b6bb2007-03-13 22:16:30 +00001306 if object.im_self is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001307 note = ' method of %s instance' % classname(
1308 object.im_self.__class__, mod)
1309 else:
1310 note = ' unbound %s method' % classname(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001311 object = object.im_func
1312
1313 if name == realname:
1314 title = self.bold(realname)
1315 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001316 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001317 cl.__dict__[realname] is object):
1318 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001319 title = self.bold(name) + ' = ' + realname
Tim Peters4bcfa312001-09-20 06:08:24 +00001320 if inspect.isfunction(object):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001321 args, varargs, varkw, defaults = inspect.getargspec(object)
1322 argspec = inspect.formatargspec(
1323 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001324 if realname == '<lambda>':
Georg Brandl501dd0d2006-02-17 09:45:40 +00001325 title = self.bold(name) + ' lambda '
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001326 argspec = argspec[1:-1] # remove parentheses
Tim Peters4bcfa312001-09-20 06:08:24 +00001327 else:
1328 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001329 decl = title + argspec + note
1330
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001331 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001332 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001333 else:
1334 doc = getdoc(object) or ''
1335 return decl + '\n' + (doc and rstrip(self.indent(doc)) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001336
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001337 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001338 results = []
1339 push = results.append
1340
1341 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001342 push(self.bold(name))
1343 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001344 doc = getdoc(value) or ''
1345 if doc:
1346 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001347 push('\n')
1348 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001349
1350 def docproperty(self, object, name=None, mod=None, cl=None):
1351 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001352 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001353
Barry Warsaw00decd72006-07-27 23:43:15 +00001354 def docdata(self, object, name=None, mod=None, cl=None):
1355 """Produce text documentation for a data descriptor."""
1356 return self._docdescriptor(name, object, mod)
1357
Georg Brandl8b813db2005-10-01 16:32:31 +00001358 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001359 """Produce text documentation for a data object."""
1360 repr = self.repr(object)
1361 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001362 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001363 chop = maxlen - len(line)
1364 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001365 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001366 if doc is not None:
1367 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001368 return line
1369
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001370# --------------------------------------------------------- user interfaces
1371
1372def pager(text):
1373 """The first time this is called, determine what kind of pager to use."""
1374 global pager
1375 pager = getpager()
1376 pager(text)
1377
1378def getpager():
1379 """Decide what method to use for paging through text."""
1380 if type(sys.stdout) is not types.FileType:
1381 return plainpager
Benjamin Peterson75a55c32014-06-07 20:14:26 -07001382 if not hasattr(sys.stdin, "isatty"):
1383 return plainpager
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001384 if not sys.stdin.isatty() or not sys.stdout.isatty():
1385 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001386 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001387 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001388 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001389 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001390 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001391 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001392 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001393 if os.environ.get('TERM') in ('dumb', 'emacs'):
1394 return plainpager
Andrew MacIntyre54e0eab2002-03-03 03:12:30 +00001395 if sys.platform == 'win32' or sys.platform.startswith('os2'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001396 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001397 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001398 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001399
1400 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001401 (fd, filename) = tempfile.mkstemp()
1402 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001403 try:
Georg Brandlb32dea52008-07-16 21:19:28 +00001404 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001405 return lambda text: pipepager(text, 'more')
1406 else:
1407 return ttypager
1408 finally:
1409 os.unlink(filename)
1410
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001411def plain(text):
1412 """Remove boldface formatting from text."""
1413 return re.sub('.\b', '', text)
1414
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001415def pipepager(text, cmd):
1416 """Page through text by feeding it to another program."""
1417 pipe = os.popen(cmd, 'w')
1418 try:
R David Murray984f6302014-01-05 12:35:59 -05001419 pipe.write(_encode(text))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001420 pipe.close()
1421 except IOError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001422 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001423
1424def tempfilepager(text, cmd):
1425 """Page through text by invoking a program on a temporary file."""
1426 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001427 filename = tempfile.mktemp()
1428 file = open(filename, 'w')
R David Murray984f6302014-01-05 12:35:59 -05001429 file.write(_encode(text))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001430 file.close()
1431 try:
Georg Brandlb32dea52008-07-16 21:19:28 +00001432 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001433 finally:
1434 os.unlink(filename)
1435
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001436def ttypager(text):
1437 """Page through text on a text terminal."""
R David Murray984f6302014-01-05 12:35:59 -05001438 lines = plain(_encode(plain(text), getattr(sys.stdout, 'encoding', _encoding))).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001439 try:
1440 import tty
1441 fd = sys.stdin.fileno()
1442 old = tty.tcgetattr(fd)
1443 tty.setcbreak(fd)
1444 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001445 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001446 tty = None
1447 getchar = lambda: sys.stdin.readline()[:-1][:1]
1448
1449 try:
Serhiy Storchaka46e92502014-11-28 00:09:05 +02001450 try:
1451 h = int(os.environ.get('LINES', 0))
1452 except ValueError:
1453 h = 0
1454 if h <= 1:
1455 h = 25
1456 r = inc = h - 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001457 sys.stdout.write(join(lines[:inc], '\n') + '\n')
1458 while lines[r:]:
1459 sys.stdout.write('-- more --')
1460 sys.stdout.flush()
1461 c = getchar()
1462
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001463 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001464 sys.stdout.write('\r \r')
1465 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001466 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001467 sys.stdout.write('\r \r' + lines[r] + '\n')
1468 r = r + 1
1469 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001470 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001471 r = r - inc - inc
1472 if r < 0: r = 0
1473 sys.stdout.write('\n' + join(lines[r:r+inc], '\n') + '\n')
1474 r = r + inc
1475
1476 finally:
1477 if tty:
1478 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1479
1480def plainpager(text):
1481 """Simply print unformatted text. This is the ultimate fallback."""
R David Murray984f6302014-01-05 12:35:59 -05001482 sys.stdout.write(_encode(plain(text), getattr(sys.stdout, 'encoding', _encoding)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001483
1484def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001485 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001486 if inspect.ismodule(thing):
1487 if thing.__name__ in sys.builtin_module_names:
1488 return 'built-in module ' + thing.__name__
1489 if hasattr(thing, '__path__'):
1490 return 'package ' + thing.__name__
1491 else:
1492 return 'module ' + thing.__name__
1493 if inspect.isbuiltin(thing):
1494 return 'built-in function ' + thing.__name__
Barry Warsaw00decd72006-07-27 23:43:15 +00001495 if inspect.isgetsetdescriptor(thing):
1496 return 'getset descriptor %s.%s.%s' % (
1497 thing.__objclass__.__module__, thing.__objclass__.__name__,
1498 thing.__name__)
1499 if inspect.ismemberdescriptor(thing):
1500 return 'member descriptor %s.%s.%s' % (
1501 thing.__objclass__.__module__, thing.__objclass__.__name__,
1502 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001503 if inspect.isclass(thing):
1504 return 'class ' + thing.__name__
1505 if inspect.isfunction(thing):
1506 return 'function ' + thing.__name__
1507 if inspect.ismethod(thing):
1508 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001509 if type(thing) is types.InstanceType:
1510 return 'instance of ' + thing.__class__.__name__
1511 return type(thing).__name__
1512
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001513def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001514 """Locate an object by name or dotted path, importing as necessary."""
Guido van Rossum97dede02003-02-16 01:12:32 +00001515 parts = [part for part in split(path, '.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001516 module, n = None, 0
1517 while n < len(parts):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001518 nextmodule = safeimport(join(parts[:n+1], '.'), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001519 if nextmodule: module, n = nextmodule, n + 1
1520 else: break
1521 if module:
1522 object = module
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001523 else:
Éric Araujo9a528302011-07-29 17:34:35 +02001524 object = __builtin__
1525 for part in parts[n:]:
1526 try:
1527 object = getattr(object, part)
1528 except AttributeError:
1529 return None
1530 return object
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001531
1532# --------------------------------------- interactive interpreter interface
1533
1534text = TextDoc()
1535html = HTMLDoc()
1536
Ka-Ping Yee8ef1cf32007-01-14 04:25:15 +00001537class _OldStyleClass: pass
1538_OLD_INSTANCE_TYPE = type(_OldStyleClass())
1539
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001540def resolve(thing, forceload=0):
1541 """Given an object or a path to an object, get the object and its name."""
1542 if isinstance(thing, str):
1543 object = locate(thing, forceload)
Serhiy Storchakaa8e65752015-04-21 21:09:23 +03001544 if object is None:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001545 raise ImportError, 'no Python documentation found for %r' % thing
1546 return object, thing
1547 else:
R David Murrayc313b1d2012-04-23 13:27:11 -04001548 name = getattr(thing, '__name__', None)
1549 return thing, name if isinstance(name, str) else None
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001550
Georg Brandl8441f152007-03-13 20:02:57 +00001551def render_doc(thing, title='Python Library Documentation: %s', forceload=0):
1552 """Render text documentation, given an object or a path to an object."""
1553 object, name = resolve(thing, forceload)
1554 desc = describe(object)
1555 module = inspect.getmodule(object)
1556 if name and '.' in name:
1557 desc += ' in ' + name[:name.rfind('.')]
1558 elif module and module is not object:
1559 desc += ' in module ' + module.__name__
1560 if type(object) is _OLD_INSTANCE_TYPE:
1561 # If the passed object is an instance of an old-style class,
1562 # document its available methods instead of its value.
1563 object = object.__class__
1564 elif not (inspect.ismodule(object) or
1565 inspect.isclass(object) or
1566 inspect.isroutine(object) or
1567 inspect.isgetsetdescriptor(object) or
1568 inspect.ismemberdescriptor(object) or
1569 isinstance(object, property)):
1570 # If the passed object is a piece of data or an instance,
1571 # document its available methods instead of its value.
1572 object = type(object)
1573 desc += ' object'
1574 return title % desc + '\n\n' + text.document(object, name)
1575
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001576def doc(thing, title='Python Library Documentation: %s', forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001577 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001578 try:
Georg Brandl8441f152007-03-13 20:02:57 +00001579 pager(render_doc(thing, title, forceload))
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001580 except (ImportError, ErrorDuringImport), value:
1581 print value
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001582
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001583def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001584 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001585 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001586 object, name = resolve(thing, forceload)
1587 page = html.page(describe(object), html.document(object, name))
1588 file = open(name + '.html', 'w')
1589 file.write(page)
1590 file.close()
1591 print 'wrote', name + '.html'
1592 except (ImportError, ErrorDuringImport), value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001593 print value
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001594
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001595def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001596 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001597 if done is None: done = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001598 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1599 writedoc(modname)
1600 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001601
1602class Helper:
Georg Brandl681001e2008-06-01 20:33:55 +00001603
1604 # These dictionaries map a topic name to either an alias, or a tuple
1605 # (label, seealso-items). The "label" is the label of the corresponding
1606 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl43819252009-04-26 09:56:44 +00001607 # in pydoc_data/topics.py.
Georg Brandl681001e2008-06-01 20:33:55 +00001608 #
1609 # CAUTION: if you change one of these dictionaries, be sure to adapt the
Georg Brandlf16fbf92014-09-30 22:51:30 +02001610 # list of needed labels in Doc/tools/pyspecific.py and
Georg Brandl43819252009-04-26 09:56:44 +00001611 # regenerate the pydoc_data/topics.py file by running
Georg Brandl681001e2008-06-01 20:33:55 +00001612 # make pydoc-topics
1613 # in Doc/ and copying the output file into the Lib/ directory.
1614
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001615 keywords = {
1616 'and': 'BOOLEAN',
Georg Brandlb6a87542007-03-13 10:06:48 +00001617 'as': 'with',
Georg Brandl681001e2008-06-01 20:33:55 +00001618 'assert': ('assert', ''),
1619 'break': ('break', 'while for'),
1620 'class': ('class', 'CLASSES SPECIALMETHODS'),
1621 'continue': ('continue', 'while for'),
1622 'def': ('function', ''),
1623 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001624 'elif': 'if',
Georg Brandl681001e2008-06-01 20:33:55 +00001625 'else': ('else', 'while for'),
Georg Brandl5c669db2008-08-30 19:03:43 +00001626 'except': 'try',
Georg Brandl681001e2008-06-01 20:33:55 +00001627 'exec': ('exec', ''),
Georg Brandl5c669db2008-08-30 19:03:43 +00001628 'finally': 'try',
Georg Brandl681001e2008-06-01 20:33:55 +00001629 'for': ('for', 'break continue while'),
Georg Brandl5c669db2008-08-30 19:03:43 +00001630 'from': 'import',
Georg Brandl681001e2008-06-01 20:33:55 +00001631 'global': ('global', 'NAMESPACES'),
1632 'if': ('if', 'TRUTHVALUE'),
1633 'import': ('import', 'MODULES'),
1634 'in': ('in', 'SEQUENCEMETHODS2'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001635 'is': 'COMPARISON',
Georg Brandl681001e2008-06-01 20:33:55 +00001636 'lambda': ('lambda', 'FUNCTIONS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001637 'not': 'BOOLEAN',
1638 'or': 'BOOLEAN',
Georg Brandl681001e2008-06-01 20:33:55 +00001639 'pass': ('pass', ''),
1640 'print': ('print', ''),
1641 'raise': ('raise', 'EXCEPTIONS'),
1642 'return': ('return', 'FUNCTIONS'),
1643 'try': ('try', 'EXCEPTIONS'),
1644 'while': ('while', 'break continue if TRUTHVALUE'),
1645 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1646 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001647 }
Georg Brandlc3a98032008-12-27 18:20:04 +00001648 # Either add symbols to this dictionary or to the symbols dictionary
1649 # directly: Whichever is easier. They are merged later.
1650 _symbols_inverse = {
1651 'STRINGS' : ("'", "'''", "r'", "u'", '"""', '"', 'r"', 'u"'),
1652 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1653 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1654 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1655 'UNARY' : ('-', '~'),
1656 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1657 '^=', '<<=', '>>=', '**=', '//='),
1658 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1659 'COMPLEX' : ('j', 'J')
1660 }
1661 symbols = {
1662 '%': 'OPERATORS FORMATTING',
1663 '**': 'POWER',
1664 ',': 'TUPLES LISTS FUNCTIONS',
1665 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1666 '...': 'ELLIPSIS',
1667 ':': 'SLICINGS DICTIONARYLITERALS',
1668 '@': 'def class',
1669 '\\': 'STRINGS',
1670 '_': 'PRIVATENAMES',
1671 '__': 'PRIVATENAMES SPECIALMETHODS',
1672 '`': 'BACKQUOTES',
1673 '(': 'TUPLES FUNCTIONS CALLS',
1674 ')': 'TUPLES FUNCTIONS CALLS',
1675 '[': 'LISTS SUBSCRIPTS SLICINGS',
1676 ']': 'LISTS SUBSCRIPTS SLICINGS'
1677 }
1678 for topic, symbols_ in _symbols_inverse.iteritems():
1679 for symbol in symbols_:
1680 topics = symbols.get(symbol, topic)
1681 if topic not in topics:
1682 topics = topics + ' ' + topic
1683 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001684
1685 topics = {
Georg Brandl681001e2008-06-01 20:33:55 +00001686 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1687 'FUNCTIONS CLASSES MODULES FILES inspect'),
1688 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS FORMATTING '
1689 'TYPES'),
1690 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1691 'FORMATTING': ('formatstrings', 'OPERATORS'),
1692 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1693 'FORMATTING TYPES'),
1694 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1695 'INTEGER': ('integers', 'int range'),
1696 'FLOAT': ('floating', 'float math'),
1697 'COMPLEX': ('imaginary', 'complex cmath'),
1698 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING xrange LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001699 'MAPPINGS': 'DICTIONARIES',
Georg Brandl681001e2008-06-01 20:33:55 +00001700 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1701 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1702 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1703 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001704 'FRAMEOBJECTS': 'TYPES',
1705 'TRACEBACKS': 'TYPES',
Georg Brandl681001e2008-06-01 20:33:55 +00001706 'NONE': ('bltin-null-object', ''),
1707 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
1708 'FILES': ('bltin-file-objects', ''),
1709 'SPECIALATTRIBUTES': ('specialattrs', ''),
1710 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1711 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001712 'PACKAGES': 'import',
Georg Brandl681001e2008-06-01 20:33:55 +00001713 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1714 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1715 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1716 'LISTS DICTIONARIES BACKQUOTES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001717 'OPERATORS': 'EXPRESSIONS',
1718 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl681001e2008-06-01 20:33:55 +00001719 'OBJECTS': ('objects', 'TYPES'),
1720 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
1721 'CALLABLEMETHODS SEQUENCEMETHODS1 MAPPINGMETHODS '
1722 'SEQUENCEMETHODS2 NUMBERMETHODS CLASSES'),
1723 'BASICMETHODS': ('customization', 'cmp hash repr str SPECIALMETHODS'),
1724 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1725 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
1726 'SEQUENCEMETHODS1': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS2 '
1727 'SPECIALMETHODS'),
1728 'SEQUENCEMETHODS2': ('sequence-methods', 'SEQUENCES SEQUENCEMETHODS1 '
1729 'SPECIALMETHODS'),
1730 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1731 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1732 'SPECIALMETHODS'),
1733 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
1734 'NAMESPACES': ('naming', 'global ASSIGNMENT DELETION DYNAMICFEATURES'),
1735 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001736 'SCOPING': 'NAMESPACES',
1737 'FRAMES': 'NAMESPACES',
Georg Brandl681001e2008-06-01 20:33:55 +00001738 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1739 'COERCIONS': ('coercion-rules','CONVERSIONS'),
1740 'CONVERSIONS': ('conversions', 'COERCIONS'),
1741 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1742 'SPECIALIDENTIFIERS': ('id-classes', ''),
1743 'PRIVATENAMES': ('atom-identifiers', ''),
1744 'LITERALS': ('atom-literals', 'STRINGS BACKQUOTES NUMBERS '
1745 'TUPLELITERALS LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001746 'TUPLES': 'SEQUENCES',
Georg Brandl681001e2008-06-01 20:33:55 +00001747 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1748 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1749 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1750 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1751 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1752 'BACKQUOTES': ('string-conversions', 'repr str STRINGS LITERALS'),
1753 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr '
1754 'ATTRIBUTEMETHODS'),
1755 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS1'),
1756 'SLICINGS': ('slicings', 'SEQUENCEMETHODS2'),
1757 'CALLS': ('calls', 'EXPRESSIONS'),
1758 'POWER': ('power', 'EXPRESSIONS'),
1759 'UNARY': ('unary', 'EXPRESSIONS'),
1760 'BINARY': ('binary', 'EXPRESSIONS'),
1761 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1762 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1763 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1764 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001765 'ASSERTION': 'assert',
Georg Brandl681001e2008-06-01 20:33:55 +00001766 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1767 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001768 'DELETION': 'del',
1769 'PRINTING': 'print',
1770 'RETURNING': 'return',
1771 'IMPORTING': 'import',
1772 'CONDITIONAL': 'if',
Georg Brandl681001e2008-06-01 20:33:55 +00001773 'LOOPING': ('compound', 'for while break continue'),
1774 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1775 'DEBUGGING': ('debugger', 'pdb'),
1776 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001777 }
1778
Georg Brandl004c74d2010-08-01 19:06:51 +00001779 def __init__(self, input=None, output=None):
1780 self._input = input
1781 self._output = output
1782
1783 input = property(lambda self: self._input or sys.stdin)
1784 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001785
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001786 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001787 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001788 self()
1789 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001790 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001791
Alexander Belopolskyd501dde2011-01-11 15:35:23 +00001792 _GoInteractive = object()
1793 def __call__(self, request=_GoInteractive):
1794 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001795 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001796 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001797 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001798 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001799 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001800You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001801If you want to ask for help on a particular object directly from the
1802interpreter, you can type "help(object)". Executing "help('string')"
1803has the same effect as typing a particular string at the help> prompt.
1804''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001805
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001806 def interact(self):
1807 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001808 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001809 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001810 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001811 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001812 except (KeyboardInterrupt, EOFError):
1813 break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001814 request = strip(replace(request, '"', '', "'", ''))
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001815 if lower(request) in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001816 self.help(request)
1817
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001818 def getline(self, prompt):
1819 """Read one line, using raw_input when available."""
1820 if self.input is sys.stdin:
1821 return raw_input(prompt)
1822 else:
1823 self.output.write(prompt)
1824 self.output.flush()
1825 return self.input.readline()
1826
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001827 def help(self, request):
1828 if type(request) is type(''):
R. David Murrayd67ea7d2009-05-27 20:07:21 +00001829 request = request.strip()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001830 if request == 'help': self.intro()
1831 elif request == 'keywords': self.listkeywords()
Georg Brandlc3a98032008-12-27 18:20:04 +00001832 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001833 elif request == 'topics': self.listtopics()
1834 elif request == 'modules': self.listmodules()
1835 elif request[:8] == 'modules ':
1836 self.listmodules(split(request)[1])
Georg Brandlc3a98032008-12-27 18:20:04 +00001837 elif request in self.symbols: self.showsymbol(request)
Raymond Hettinger54f02222002-06-01 14:18:47 +00001838 elif request in self.keywords: self.showtopic(request)
1839 elif request in self.topics: self.showtopic(request)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001840 elif request: doc(request, 'Help on %s:')
1841 elif isinstance(request, Helper): self()
1842 else: doc(request, 'Help on %s:')
1843 self.output.write('\n')
1844
1845 def intro(self):
1846 self.output.write('''
1847Welcome to Python %s! This is the online help utility.
1848
1849If this is your first time using Python, you should definitely check out
R David Murray93a224d2012-03-31 12:10:48 -04001850the tutorial on the Internet at http://docs.python.org/%s/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001851
1852Enter the name of any module, keyword, or topic to get help on writing
1853Python programs and using Python modules. To quit this help utility and
1854return to the interpreter, just type "quit".
1855
1856To get a list of available modules, keywords, or topics, type "modules",
1857"keywords", or "topics". Each module also comes with a one-line summary
1858of what it does; to list the modules whose summaries contain a given word
1859such as "spam", type "modules spam".
R David Murray93a224d2012-03-31 12:10:48 -04001860''' % tuple([sys.version[:3]]*2))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001861
1862 def list(self, items, columns=4, width=80):
1863 items = items[:]
1864 items.sort()
1865 colw = width / columns
1866 rows = (len(items) + columns - 1) / columns
1867 for row in range(rows):
1868 for col in range(columns):
1869 i = col * rows + row
1870 if i < len(items):
1871 self.output.write(items[i])
1872 if col < columns - 1:
1873 self.output.write(' ' + ' ' * (colw-1 - len(items[i])))
1874 self.output.write('\n')
1875
1876 def listkeywords(self):
1877 self.output.write('''
1878Here is a list of the Python keywords. Enter any keyword to get more help.
1879
1880''')
1881 self.list(self.keywords.keys())
1882
Georg Brandlc3a98032008-12-27 18:20:04 +00001883 def listsymbols(self):
1884 self.output.write('''
1885Here is a list of the punctuation symbols which Python assigns special meaning
1886to. Enter any symbol to get more help.
1887
1888''')
1889 self.list(self.symbols.keys())
1890
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001891 def listtopics(self):
1892 self.output.write('''
1893Here is a list of available topics. Enter any topic name to get more help.
1894
1895''')
1896 self.list(self.topics.keys())
1897
Georg Brandlc3a98032008-12-27 18:20:04 +00001898 def showtopic(self, topic, more_xrefs=''):
Georg Brandl681001e2008-06-01 20:33:55 +00001899 try:
Georg Brandl43819252009-04-26 09:56:44 +00001900 import pydoc_data.topics
Georg Brandl681001e2008-06-01 20:33:55 +00001901 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001902 self.output.write('''
Georg Brandl681001e2008-06-01 20:33:55 +00001903Sorry, topic and keyword documentation is not available because the
Georg Brandl43819252009-04-26 09:56:44 +00001904module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001905''')
1906 return
1907 target = self.topics.get(topic, self.keywords.get(topic))
1908 if not target:
1909 self.output.write('no documentation found for %s\n' % repr(topic))
1910 return
1911 if type(target) is type(''):
Georg Brandlc3a98032008-12-27 18:20:04 +00001912 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001913
Georg Brandl681001e2008-06-01 20:33:55 +00001914 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001915 try:
Georg Brandl43819252009-04-26 09:56:44 +00001916 doc = pydoc_data.topics.topics[label]
Georg Brandl681001e2008-06-01 20:33:55 +00001917 except KeyError:
1918 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001919 return
Georg Brandl681001e2008-06-01 20:33:55 +00001920 pager(strip(doc) + '\n')
Georg Brandlc3a98032008-12-27 18:20:04 +00001921 if more_xrefs:
1922 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001923 if xrefs:
Georg Brandl681001e2008-06-01 20:33:55 +00001924 import StringIO, formatter
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001925 buffer = StringIO.StringIO()
1926 formatter.DumbWriter(buffer).send_flowing_data(
1927 'Related help topics: ' + join(split(xrefs), ', ') + '\n')
1928 self.output.write('\n%s\n' % buffer.getvalue())
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001929
Georg Brandlc3a98032008-12-27 18:20:04 +00001930 def showsymbol(self, symbol):
1931 target = self.symbols[symbol]
1932 topic, _, xrefs = target.partition(' ')
1933 self.showtopic(topic, xrefs)
1934
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001935 def listmodules(self, key=''):
1936 if key:
1937 self.output.write('''
1938Here is a list of matching modules. Enter any module name to get more help.
1939
1940''')
1941 apropos(key)
1942 else:
1943 self.output.write('''
1944Please wait a moment while I gather a list of all available modules...
1945
1946''')
1947 modules = {}
1948 def callback(path, modname, desc, modules=modules):
1949 if modname and modname[-9:] == '.__init__':
1950 modname = modname[:-9] + ' (package)'
1951 if find(modname, '.') < 0:
1952 modules[modname] = 1
Ka-Ping Yee9e0f1162008-01-13 11:25:13 +00001953 def onerror(modname):
1954 callback(None, modname, None)
1955 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001956 self.list(modules.keys())
1957 self.output.write('''
1958Enter any module name to get more help. Or, type "modules spam" to search
1959for modules whose descriptions contain the word "spam".
1960''')
1961
Georg Brandl004c74d2010-08-01 19:06:51 +00001962help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001963
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001964class Scanner:
1965 """A generic tree iterator."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001966 def __init__(self, roots, children, descendp):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001967 self.roots = roots[:]
1968 self.state = []
1969 self.children = children
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001970 self.descendp = descendp
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001971
1972 def next(self):
1973 if not self.state:
1974 if not self.roots:
1975 return None
1976 root = self.roots.pop(0)
1977 self.state = [(root, self.children(root))]
1978 node, children = self.state[-1]
1979 if not children:
1980 self.state.pop()
1981 return self.next()
1982 child = children.pop(0)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001983 if self.descendp(child):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001984 self.state.append((child, self.children(child)))
1985 return child
1986
Phillip J. Ebyceb30872006-04-18 00:59:55 +00001987
1988class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001989 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001990
Ka-Ping Yee9e0f1162008-01-13 11:25:13 +00001991 def run(self, callback, key=None, completer=None, onerror=None):
Ka-Ping Yee66246962001-04-12 11:59:50 +00001992 if key: key = lower(key)
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001993 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001994 seen = {}
1995
1996 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00001997 if modname != '__main__':
1998 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00001999 if key is None:
2000 callback(None, modname, '')
2001 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00002002 desc = split(__import__(modname).__doc__ or '', '\n')[0]
Ka-Ping Yee66246962001-04-12 11:59:50 +00002003 if find(lower(modname + ' - ' + desc), key) >= 0:
2004 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002005
Ka-Ping Yee9e0f1162008-01-13 11:25:13 +00002006 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Phillip J. Ebyceb30872006-04-18 00:59:55 +00002007 if self.quit:
2008 break
2009 if key is None:
2010 callback(None, modname, '')
2011 else:
2012 loader = importer.find_module(modname)
2013 if hasattr(loader,'get_source'):
2014 import StringIO
2015 desc = source_synopsis(
2016 StringIO.StringIO(loader.get_source(modname))
2017 ) or ''
2018 if hasattr(loader,'get_filename'):
2019 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002020 else:
Phillip J. Ebyceb30872006-04-18 00:59:55 +00002021 path = None
2022 else:
2023 module = loader.load_module(modname)
Berker Peksagdc9d41d2015-02-20 12:10:33 +02002024 desc = module.__doc__.splitlines()[0] if module.__doc__ else ''
Phillip J. Ebyceb30872006-04-18 00:59:55 +00002025 path = getattr(module,'__file__',None)
2026 if find(lower(modname + ' - ' + desc), key) >= 0:
2027 callback(path, modname, desc)
2028
2029 if completer:
2030 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002031
2032def apropos(key):
2033 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002034 def callback(path, modname, desc):
2035 if modname[-9:] == '.__init__':
2036 modname = modname[:-9] + ' (package)'
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002037 print modname, desc and '- ' + desc
Ned Deily0096fb52011-10-06 14:17:44 -07002038 def onerror(modname):
2039 pass
2040 with warnings.catch_warnings():
2041 warnings.filterwarnings('ignore') # ignore problems during import
2042 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002043
2044# --------------------------------------------------- web browser interface
2045
Ka-Ping Yee66246962001-04-12 11:59:50 +00002046def serve(port, callback=None, completer=None):
Ka-Ping Yeefd540692001-04-12 12:54:36 +00002047 import BaseHTTPServer, mimetools, select
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002048
2049 # Patch up mimetools.Message so it doesn't break if rfc822 is reloaded.
2050 class Message(mimetools.Message):
2051 def __init__(self, fp, seekable=1):
2052 Message = self.__class__
2053 Message.__bases__[0].__bases__[0].__init__(self, fp, seekable)
2054 self.encodingheader = self.getheader('content-transfer-encoding')
2055 self.typeheader = self.getheader('content-type')
2056 self.parsetype()
2057 self.parseplist()
2058
2059 class DocHandler(BaseHTTPServer.BaseHTTPRequestHandler):
2060 def send_document(self, title, contents):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002061 try:
2062 self.send_response(200)
2063 self.send_header('Content-Type', 'text/html')
2064 self.end_headers()
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002065 self.wfile.write(html.page(title, contents))
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002066 except IOError: pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002067
2068 def do_GET(self):
2069 path = self.path
2070 if path[-5:] == '.html': path = path[:-5]
2071 if path[:1] == '/': path = path[1:]
2072 if path and path != '.':
2073 try:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00002074 obj = locate(path, forceload=1)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002075 except ErrorDuringImport, value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002076 self.send_document(path, html.escape(str(value)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002077 return
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002078 if obj:
2079 self.send_document(describe(obj), html.document(obj, path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002080 else:
2081 self.send_document(path,
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002082'no Python documentation found for %s' % repr(path))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002083 else:
2084 heading = html.heading(
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002085'<big><big><strong>Python: Index of Modules</strong></big></big>',
2086'#ffffff', '#7799ee')
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002087 def bltinlink(name):
2088 return '<a href="%s.html">%s</a>' % (name, name)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002089 names = filter(lambda x: x != '__main__',
2090 sys.builtin_module_names)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002091 contents = html.multicolumn(names, bltinlink)
2092 indices = ['<p>' + html.bigsection(
2093 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2094
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002095 seen = {}
Phillip J. Ebyceb30872006-04-18 00:59:55 +00002096 for dir in sys.path:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002097 indices.append(html.index(dir, seen))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002098 contents = heading + join(indices) + '''<p align=right>
Tim Peters2306d242001-09-25 03:18:32 +00002099<font color="#909090" face="helvetica, arial"><strong>
2100pydoc</strong> by Ka-Ping Yee &lt;ping@lfw.org&gt;</font>'''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002101 self.send_document('Index of Modules', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002102
2103 def log_message(self, *args): pass
2104
Ka-Ping Yeefd540692001-04-12 12:54:36 +00002105 class DocServer(BaseHTTPServer.HTTPServer):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002106 def __init__(self, port, callback):
Ronald Oussoren9545a232010-05-05 19:09:31 +00002107 host = 'localhost'
Senthil Kumaranaa895452010-08-18 19:35:53 +00002108 self.address = (host, port)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002109 self.callback = callback
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002110 self.base.__init__(self, self.address, self.handler)
2111
2112 def serve_until_quit(self):
2113 import select
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002114 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002115 while not self.quit:
2116 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2117 if rd: self.handle_request()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002118
2119 def server_activate(self):
2120 self.base.server_activate(self)
Serhiy Storchaka86ef95d2014-11-27 23:45:37 +02002121 self.url = 'http://%s:%d/' % (self.address[0], self.server_port)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002122 if self.callback: self.callback(self)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002123
2124 DocServer.base = BaseHTTPServer.HTTPServer
2125 DocServer.handler = DocHandler
2126 DocHandler.MessageClass = Message
2127 try:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002128 try:
2129 DocServer(port, callback).serve_until_quit()
2130 except (KeyboardInterrupt, select.error):
2131 pass
2132 finally:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002133 if completer: completer()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002134
2135# ----------------------------------------------------- graphical interface
2136
2137def gui():
2138 """Graphical interface (starts web server and pops up a control window)."""
2139 class GUI:
2140 def __init__(self, window, port=7464):
2141 self.window = window
2142 self.server = None
2143 self.scanner = None
2144
Georg Brandl6634bf22008-05-20 07:13:37 +00002145 import Tkinter
2146 self.server_frm = Tkinter.Frame(window)
2147 self.title_lbl = Tkinter.Label(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002148 text='Starting server...\n ')
Georg Brandl6634bf22008-05-20 07:13:37 +00002149 self.open_btn = Tkinter.Button(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002150 text='open browser', command=self.open, state='disabled')
Georg Brandl6634bf22008-05-20 07:13:37 +00002151 self.quit_btn = Tkinter.Button(self.server_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002152 text='quit serving', command=self.quit, state='disabled')
2153
Georg Brandl6634bf22008-05-20 07:13:37 +00002154 self.search_frm = Tkinter.Frame(window)
2155 self.search_lbl = Tkinter.Label(self.search_frm, text='Search for')
2156 self.search_ent = Tkinter.Entry(self.search_frm)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002157 self.search_ent.bind('<Return>', self.search)
Georg Brandl6634bf22008-05-20 07:13:37 +00002158 self.stop_btn = Tkinter.Button(self.search_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002159 text='stop', pady=0, command=self.stop, state='disabled')
2160 if sys.platform == 'win32':
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002161 # Trying to hide and show this button crashes under Windows.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002162 self.stop_btn.pack(side='right')
2163
2164 self.window.title('pydoc')
2165 self.window.protocol('WM_DELETE_WINDOW', self.quit)
2166 self.title_lbl.pack(side='top', fill='x')
2167 self.open_btn.pack(side='left', fill='x', expand=1)
2168 self.quit_btn.pack(side='right', fill='x', expand=1)
2169 self.server_frm.pack(side='top', fill='x')
2170
2171 self.search_lbl.pack(side='left')
2172 self.search_ent.pack(side='right', fill='x', expand=1)
2173 self.search_frm.pack(side='top', fill='x')
2174 self.search_ent.focus_set()
2175
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002176 font = ('helvetica', sys.platform == 'win32' and 8 or 10)
Georg Brandl6634bf22008-05-20 07:13:37 +00002177 self.result_lst = Tkinter.Listbox(window, font=font, height=6)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002178 self.result_lst.bind('<Button-1>', self.select)
2179 self.result_lst.bind('<Double-Button-1>', self.goto)
Georg Brandl6634bf22008-05-20 07:13:37 +00002180 self.result_scr = Tkinter.Scrollbar(window,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002181 orient='vertical', command=self.result_lst.yview)
2182 self.result_lst.config(yscrollcommand=self.result_scr.set)
2183
Georg Brandl6634bf22008-05-20 07:13:37 +00002184 self.result_frm = Tkinter.Frame(window)
2185 self.goto_btn = Tkinter.Button(self.result_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002186 text='go to selected', command=self.goto)
Georg Brandl6634bf22008-05-20 07:13:37 +00002187 self.hide_btn = Tkinter.Button(self.result_frm,
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002188 text='hide results', command=self.hide)
2189 self.goto_btn.pack(side='left', fill='x', expand=1)
2190 self.hide_btn.pack(side='right', fill='x', expand=1)
2191
2192 self.window.update()
2193 self.minwidth = self.window.winfo_width()
2194 self.minheight = self.window.winfo_height()
2195 self.bigminheight = (self.server_frm.winfo_reqheight() +
2196 self.search_frm.winfo_reqheight() +
2197 self.result_lst.winfo_reqheight() +
2198 self.result_frm.winfo_reqheight())
2199 self.bigwidth, self.bigheight = self.minwidth, self.bigminheight
2200 self.expanded = 0
2201 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2202 self.window.wm_minsize(self.minwidth, self.minheight)
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002203 self.window.tk.willdispatch()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002204
2205 import threading
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002206 threading.Thread(
2207 target=serve, args=(port, self.ready, self.quit)).start()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002208
2209 def ready(self, server):
2210 self.server = server
2211 self.title_lbl.config(
2212 text='Python documentation server at\n' + server.url)
2213 self.open_btn.config(state='normal')
2214 self.quit_btn.config(state='normal')
2215
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002216 def open(self, event=None, url=None):
2217 url = url or self.server.url
2218 try:
2219 import webbrowser
2220 webbrowser.open(url)
2221 except ImportError: # pre-webbrowser.py compatibility
Ka-Ping Yeec92cdf72001-03-02 05:54:35 +00002222 if sys.platform == 'win32':
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002223 os.system('start "%s"' % url)
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002224 else:
2225 rc = os.system('netscape -remote "openURL(%s)" &' % url)
2226 if rc: os.system('netscape "%s" &' % url)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002227
2228 def quit(self, event=None):
2229 if self.server:
2230 self.server.quit = 1
2231 self.window.quit()
2232
2233 def search(self, event=None):
2234 key = self.search_ent.get()
2235 self.stop_btn.pack(side='right')
2236 self.stop_btn.config(state='normal')
2237 self.search_lbl.config(text='Searching for "%s"...' % key)
2238 self.search_ent.forget()
2239 self.search_lbl.pack(side='left')
2240 self.result_lst.delete(0, 'end')
2241 self.goto_btn.config(state='disabled')
2242 self.expand()
2243
2244 import threading
2245 if self.scanner:
2246 self.scanner.quit = 1
2247 self.scanner = ModuleScanner()
Martin Panter43415ba2015-11-07 05:41:47 +00002248 def onerror(modname):
2249 pass
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002250 threading.Thread(target=self.scanner.run,
Martin Panter43415ba2015-11-07 05:41:47 +00002251 args=(self.update, key, self.done),
2252 kwargs=dict(onerror=onerror)).start()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002253
2254 def update(self, path, modname, desc):
2255 if modname[-9:] == '.__init__':
2256 modname = modname[:-9] + ' (package)'
2257 self.result_lst.insert('end',
2258 modname + ' - ' + (desc or '(no description)'))
2259
2260 def stop(self, event=None):
2261 if self.scanner:
2262 self.scanner.quit = 1
2263 self.scanner = None
2264
2265 def done(self):
2266 self.scanner = None
2267 self.search_lbl.config(text='Search for')
2268 self.search_lbl.pack(side='left')
2269 self.search_ent.pack(side='right', fill='x', expand=1)
2270 if sys.platform != 'win32': self.stop_btn.forget()
2271 self.stop_btn.config(state='disabled')
2272
2273 def select(self, event=None):
2274 self.goto_btn.config(state='normal')
2275
2276 def goto(self, event=None):
2277 selection = self.result_lst.curselection()
2278 if selection:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002279 modname = split(self.result_lst.get(selection[0]))[0]
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002280 self.open(url=self.server.url + modname + '.html')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002281
2282 def collapse(self):
2283 if not self.expanded: return
2284 self.result_frm.forget()
2285 self.result_scr.forget()
2286 self.result_lst.forget()
2287 self.bigwidth = self.window.winfo_width()
2288 self.bigheight = self.window.winfo_height()
2289 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2290 self.window.wm_minsize(self.minwidth, self.minheight)
2291 self.expanded = 0
2292
2293 def expand(self):
2294 if self.expanded: return
2295 self.result_frm.pack(side='bottom', fill='x')
2296 self.result_scr.pack(side='right', fill='y')
2297 self.result_lst.pack(side='top', fill='both', expand=1)
2298 self.window.wm_geometry('%dx%d' % (self.bigwidth, self.bigheight))
2299 self.window.wm_minsize(self.minwidth, self.bigminheight)
2300 self.expanded = 1
2301
2302 def hide(self, event=None):
2303 self.stop()
2304 self.collapse()
2305
Georg Brandl6634bf22008-05-20 07:13:37 +00002306 import Tkinter
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002307 try:
Georg Brandl6634bf22008-05-20 07:13:37 +00002308 root = Tkinter.Tk()
Martin v. Löwise09bd932004-08-22 16:13:26 +00002309 # Tk will crash if pythonw.exe has an XP .manifest
2310 # file and the root has is not destroyed explicitly.
2311 # If the problem is ever fixed in Tk, the explicit
2312 # destroy can go.
2313 try:
2314 gui = GUI(root)
2315 root.mainloop()
2316 finally:
2317 root.destroy()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002318 except KeyboardInterrupt:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002319 pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002320
2321# -------------------------------------------------- command-line interface
2322
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002323def ispath(x):
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002324 return isinstance(x, str) and find(x, os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002325
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002326def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002327 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002328 import getopt
2329 class BadUsage: pass
2330
Nick Coghlan11db64e2009-11-15 22:36:47 +00002331 # Scripts don't get the current directory in their path by default
2332 # unless they are run with the '-m' switch
2333 if '' not in sys.path:
2334 scriptdir = os.path.dirname(sys.argv[0])
2335 if scriptdir in sys.path:
2336 sys.path.remove(scriptdir)
2337 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002338
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002339 try:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002340 opts, args = getopt.getopt(sys.argv[1:], 'gk:p:w')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002341 writing = 0
2342
2343 for opt, val in opts:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002344 if opt == '-g':
2345 gui()
2346 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002347 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002348 apropos(val)
2349 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002350 if opt == '-p':
2351 try:
2352 port = int(val)
2353 except ValueError:
2354 raise BadUsage
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002355 def ready(server):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00002356 print 'pydoc server ready at %s' % server.url
2357 def stopped():
2358 print 'pydoc server stopped'
2359 serve(port, ready, stopped)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002360 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002361 if opt == '-w':
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002362 writing = 1
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002363
2364 if not args: raise BadUsage
2365 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002366 if ispath(arg) and not os.path.exists(arg):
2367 print 'file %r does not exist' % arg
2368 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002369 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002370 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002371 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002372 if writing:
2373 if ispath(arg) and os.path.isdir(arg):
2374 writedocs(arg)
2375 else:
2376 writedoc(arg)
2377 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002378 help.help(arg)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002379 except ErrorDuringImport, value:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002380 print value
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002381
2382 except (getopt.error, BadUsage):
Martin v. Löwisf9b08b82003-10-31 13:05:21 +00002383 cmd = os.path.basename(sys.argv[0])
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002384 print """pydoc - the Python documentation tool
2385
2386%s <name> ...
2387 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002388 Python keyword, topic, function, module, or package, or a dotted
2389 reference to a class or function within a module or module in a
2390 package. If <name> contains a '%s', it is used as the path to a
2391 Python source file to document. If name is 'keywords', 'topics',
2392 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002393
2394%s -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002395 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002396
2397%s -p <port>
Serhiy Storchaka86ef95d2014-11-27 23:45:37 +02002398 Start an HTTP server on the given port on the local machine. Port
2399 number 0 can be used to get an arbitrary unused port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002400
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002401%s -g
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002402 Pop up a graphical interface for finding and serving documentation.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002403
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002404%s -w <name> ...
2405 Write out the HTML documentation for a module to a file in the current
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002406 directory. If <name> contains a '%s', it is treated as a filename; if
2407 it names a directory, documentation is written for all the contents.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002408""" % (cmd, os.sep, cmd, cmd, cmd, cmd, os.sep)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002409
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002410if __name__ == '__main__': cli()