blob: ee558bfea3b58a1b9489c5252cbb1d042a7f3918 [file] [log] [blame]
Benjamin Peterson90f5ba52010-03-11 22:53:45 +00001#!/usr/bin/env python3
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002"""Generate Python documentation in HTML or text for interactive use.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00003
R David Murray3d050dd2014-04-19 12:59:30 -04004At the Python interactive prompt, calling help(thing) on a Python object
5documents the object, and calling help() starts up an interactive
6help session.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00007
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
Nick Coghlan7bb30b72010-12-03 09:29:11 +000019Run "pydoc -p <port>" to start an HTTP server on the given port on the
20local machine. Port number 0 can be used to get an arbitrary unused port.
21
22Run "pydoc -b" to start an HTTP server on an arbitrary unused port and
23open a Web browser to interactively browse documentation. The -p option
24can be used with the -b option to explicitly specify the server port.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000025
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000026Run "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
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000031 http://docs.python.org/X.Y/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"""
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000037__all__ = ['help']
Ka-Ping Yeedd175342001-02-27 14:43:46 +000038__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
Martin v. Löwis6fe8f192004-11-14 10:21:04 +000041__credits__ = """Guido van Rossum, for an excellent programming language.
Ka-Ping Yee5e2b1732001-02-27 23:35:09 +000042Tommy Burnette, the original creator of manpy.
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000043Paul Prescod, for all his work on onlinehelp.
44Richard Chamberlain, for the first implementation of textdoc.
Raymond Hettingered2dbe32005-01-01 07:51:01 +000045"""
Ka-Ping Yeedd175342001-02-27 14:43:46 +000046
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000047# Known bugs that can't be fixed here:
Brett Cannonf4ba4ec2013-06-15 14:25:04 -040048# - synopsis() cannot be prevented from clobbering existing
49# loaded modules.
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000050# - If the __file__ attribute on a module is a relative path and
51# the current directory is changed with os.chdir(), an incorrect
52# path will be displayed.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000053
Nick Coghlan7bb30b72010-12-03 09:29:11 +000054import builtins
Brett Cannond5e6f2e2013-06-11 17:09:36 -040055import importlib._bootstrap
Eric Snow32439d62015-05-02 19:15:18 -060056import importlib._bootstrap_external
Brett Cannoncb66eb02012-05-11 12:58:42 -040057import importlib.machinery
Brett Cannonf4ba4ec2013-06-15 14:25:04 -040058import importlib.util
Nick Coghlan7bb30b72010-12-03 09:29:11 +000059import inspect
Victor Stinnere6c910e2011-06-30 15:55:43 +020060import io
61import os
Nick Coghlan7bb30b72010-12-03 09:29:11 +000062import pkgutil
63import platform
64import re
Victor Stinnere6c910e2011-06-30 15:55:43 +020065import sys
Nick Coghlan7bb30b72010-12-03 09:29:11 +000066import time
Victor Stinnere6c910e2011-06-30 15:55:43 +020067import tokenize
Zachary Wareeb432142014-07-10 11:18:00 -050068import urllib.parse
Nick Coghlan7bb30b72010-12-03 09:29:11 +000069import warnings
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000070from collections import deque
Nick Coghlan7bb30b72010-12-03 09:29:11 +000071from reprlib import Repr
Victor Stinner7fa767e2014-03-20 09:16:38 +010072from traceback import format_exception_only
Nick Coghlan7bb30b72010-12-03 09:29:11 +000073
74
Ka-Ping Yeedd175342001-02-27 14:43:46 +000075# --------------------------------------------------------- common routines
76
Ka-Ping Yeedd175342001-02-27 14:43:46 +000077def pathdirs():
78 """Convert sys.path into a list of absolute, existing, unique paths."""
79 dirs = []
Ka-Ping Yee1d384632001-03-01 00:24:32 +000080 normdirs = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +000081 for dir in sys.path:
82 dir = os.path.abspath(dir or '.')
Ka-Ping Yee1d384632001-03-01 00:24:32 +000083 normdir = os.path.normcase(dir)
84 if normdir not in normdirs and os.path.isdir(dir):
Ka-Ping Yeedd175342001-02-27 14:43:46 +000085 dirs.append(dir)
Ka-Ping Yee1d384632001-03-01 00:24:32 +000086 normdirs.append(normdir)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000087 return dirs
88
89def getdoc(object):
90 """Get the doc string or comments for an object."""
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000091 result = inspect.getdoc(object) or inspect.getcomments(object)
Neal Norwitz9d72bb42007-04-17 08:48:32 +000092 return result and re.sub('^ *\n', '', result.rstrip()) or ''
Ka-Ping Yeedd175342001-02-27 14:43:46 +000093
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000094def splitdoc(doc):
95 """Split a doc string into a synopsis line (if any) and the rest."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +000096 lines = doc.strip().split('\n')
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000097 if len(lines) == 1:
98 return lines[0], ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +000099 elif len(lines) >= 2 and not lines[1].rstrip():
100 return lines[0], '\n'.join(lines[2:])
101 return '', '\n'.join(lines)
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000102
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000103def classname(object, modname):
104 """Get a class name and qualify it with a module name if necessary."""
105 name = object.__name__
106 if object.__module__ != modname:
107 name = object.__module__ + '.' + name
108 return name
109
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000110def isdata(object):
Georg Brandl94432422005-07-22 21:52:25 +0000111 """Check if an object is of a type that probably means it's data."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000112 return not (inspect.ismodule(object) or inspect.isclass(object) or
113 inspect.isroutine(object) or inspect.isframe(object) or
114 inspect.istraceback(object) or inspect.iscode(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000115
116def replace(text, *pairs):
117 """Do a series of global replacements on a string."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000118 while pairs:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000119 text = pairs[1].join(text.split(pairs[0]))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000120 pairs = pairs[2:]
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000121 return text
122
123def cram(text, maxlen):
124 """Omit part of a string if needed to make it fit in a maximum length."""
125 if len(text) > maxlen:
Raymond Hettingerfca3bb62002-10-21 04:44:11 +0000126 pre = max(0, (maxlen-3)//2)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000127 post = max(0, maxlen-3-pre)
128 return text[:pre] + '...' + text[len(text)-post:]
129 return text
130
Brett Cannon84601f12004-06-19 01:22:48 +0000131_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000132def stripid(text):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000133 """Remove the hexadecimal id from a Python object representation."""
Brett Cannonc6c1f472004-06-19 01:02:51 +0000134 # The behaviour of %p is implementation-dependent in terms of case.
Ezio Melotti412c95a2010-02-16 23:31:04 +0000135 return _re_stripid.sub(r'\1', text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000136
Brett Cannonc6c1f472004-06-19 01:02:51 +0000137def _is_some_method(obj):
R David Murrayac0cea52013-03-19 02:47:44 -0400138 return (inspect.isfunction(obj) or
139 inspect.ismethod(obj) or
140 inspect.isbuiltin(obj) or
141 inspect.ismethoddescriptor(obj))
Tim Peters536d2262001-09-20 05:13:38 +0000142
Larry Hastings24a882b2014-02-20 23:34:46 -0800143def _is_bound_method(fn):
144 """
145 Returns True if fn is a bound method, regardless of whether
146 fn was implemented in Python or in C.
147 """
148 if inspect.ismethod(fn):
149 return True
150 if inspect.isbuiltin(fn):
151 self = getattr(fn, '__self__', None)
152 return not (inspect.ismodule(self) or (self is None))
153 return False
154
155
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000156def allmethods(cl):
157 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000158 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000159 methods[key] = 1
160 for base in cl.__bases__:
161 methods.update(allmethods(base)) # all your base are belong to us
162 for key in methods.keys():
163 methods[key] = getattr(cl, key)
164 return methods
165
Tim Petersfa26f7c2001-09-24 08:05:11 +0000166def _split_list(s, predicate):
167 """Split sequence s via predicate, and return pair ([true], [false]).
168
169 The return value is a 2-tuple of lists,
170 ([x for x in s if predicate(x)],
171 [x for x in s if not predicate(x)])
172 """
173
Tim Peters28355492001-09-23 21:29:55 +0000174 yes = []
175 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000176 for x in s:
177 if predicate(x):
178 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000179 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000180 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000181 return yes, no
182
Raymond Hettinger1103d052011-03-25 14:15:24 -0700183def visiblename(name, all=None, obj=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000184 """Decide whether to show documentation on a variable."""
Brett Cannond340b432012-08-06 17:19:22 -0400185 # Certain special names are redundant or internal.
Eric Snowb523f842013-11-22 09:05:39 -0700186 # XXX Remove __initializing__?
Brett Cannond340b432012-08-06 17:19:22 -0400187 if name in {'__author__', '__builtins__', '__cached__', '__credits__',
Eric Snowb523f842013-11-22 09:05:39 -0700188 '__date__', '__doc__', '__file__', '__spec__',
Brett Cannond340b432012-08-06 17:19:22 -0400189 '__loader__', '__module__', '__name__', '__package__',
190 '__path__', '__qualname__', '__slots__', '__version__'}:
Raymond Hettinger68272942011-03-18 02:22:15 -0700191 return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000192 # Private names are hidden, but special names are displayed.
193 if name.startswith('__') and name.endswith('__'): return 1
Raymond Hettinger1103d052011-03-25 14:15:24 -0700194 # Namedtuples have public fields and methods with a single leading underscore
195 if name.startswith('_') and hasattr(obj, '_fields'):
196 return True
Skip Montanaroa5616d22004-06-11 04:46:12 +0000197 if all is not None:
198 # only document that which the programmer exported in __all__
199 return name in all
200 else:
201 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000202
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000203def classify_class_attrs(object):
204 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000205 results = []
206 for (name, kind, cls, value) in inspect.classify_class_attrs(object):
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000207 if inspect.isdatadescriptor(value):
208 kind = 'data descriptor'
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000209 results.append((name, kind, cls, value))
210 return results
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000211
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000212# ----------------------------------------------------- module manipulation
213
214def ispackage(path):
215 """Guess whether a path refers to a package directory."""
216 if os.path.isdir(path):
Brett Cannonf299abd2015-04-13 14:21:02 -0400217 for ext in ('.py', '.pyc'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000218 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000219 return True
220 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000221
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000222def source_synopsis(file):
223 line = file.readline()
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000224 while line[:1] == '#' or not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000225 line = file.readline()
226 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000227 line = line.strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000228 if line[:4] == 'r"""': line = line[1:]
229 if line[:3] == '"""':
230 line = line[3:]
231 if line[-1:] == '\\': line = line[:-1]
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000232 while not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000233 line = file.readline()
234 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000235 result = line.split('"""')[0].strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000236 else: result = None
237 return result
238
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000239def synopsis(filename, cache={}):
240 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000241 mtime = os.stat(filename).st_mtime
Charles-François Natali27c4e882011-07-27 19:40:02 +0200242 lastupdate, result = cache.get(filename, (None, None))
243 if lastupdate is None or lastupdate < mtime:
Eric Snowaed5b222014-01-04 20:38:11 -0700244 # Look for binary suffixes first, falling back to source.
245 if filename.endswith(tuple(importlib.machinery.BYTECODE_SUFFIXES)):
246 loader_cls = importlib.machinery.SourcelessFileLoader
247 elif filename.endswith(tuple(importlib.machinery.EXTENSION_SUFFIXES)):
248 loader_cls = importlib.machinery.ExtensionFileLoader
249 else:
250 loader_cls = None
251 # Now handle the choice.
252 if loader_cls is None:
253 # Must be a source file.
254 try:
255 file = tokenize.open(filename)
256 except OSError:
257 # module can't be opened, so skip it
258 return None
259 # text modules can be directly examined
260 with file:
261 result = source_synopsis(file)
262 else:
263 # Must be a binary module, which has to be imported.
264 loader = loader_cls('__temp__', filename)
Eric Snow3a62d142014-01-06 20:42:59 -0700265 # XXX We probably don't need to pass in the loader here.
266 spec = importlib.util.spec_from_file_location('__temp__', filename,
267 loader=loader)
Brett Cannoncb66eb02012-05-11 12:58:42 -0400268 try:
Brett Cannon2a17bde2014-05-30 14:55:29 -0400269 module = importlib._bootstrap._load(spec)
Brett Cannoncb66eb02012-05-11 12:58:42 -0400270 except:
271 return None
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000272 del sys.modules['__temp__']
Benjamin Peterson54237f92015-02-16 19:45:01 -0500273 result = module.__doc__.splitlines()[0] if module.__doc__ else None
Eric Snowaed5b222014-01-04 20:38:11 -0700274 # Cache the result.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000275 cache[filename] = (mtime, result)
276 return result
277
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000278class ErrorDuringImport(Exception):
279 """Errors that occurred while trying to import something to document it."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000280 def __init__(self, filename, exc_info):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000281 self.filename = filename
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000282 self.exc, self.value, self.tb = exc_info
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000283
284 def __str__(self):
Guido van Rossuma01a8b62007-05-27 09:20:14 +0000285 exc = self.exc.__name__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000286 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000287
288def importfile(path):
289 """Import a Python source file or compiled file given its path."""
Brett Cannonf4ba4ec2013-06-15 14:25:04 -0400290 magic = importlib.util.MAGIC_NUMBER
Victor Stinnere975af62011-07-04 02:08:50 +0200291 with open(path, 'rb') as file:
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400292 is_bytecode = magic == file.read(len(magic))
293 filename = os.path.basename(path)
294 name, ext = os.path.splitext(filename)
295 if is_bytecode:
Eric Snow32439d62015-05-02 19:15:18 -0600296 loader = importlib._bootstrap_external.SourcelessFileLoader(name, path)
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400297 else:
Eric Snow32439d62015-05-02 19:15:18 -0600298 loader = importlib._bootstrap_external.SourceFileLoader(name, path)
Eric Snow3a62d142014-01-06 20:42:59 -0700299 # XXX We probably don't need to pass in the loader here.
300 spec = importlib.util.spec_from_file_location(name, path, loader=loader)
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400301 try:
Brett Cannon2a17bde2014-05-30 14:55:29 -0400302 return importlib._bootstrap._load(spec)
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400303 except:
304 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000305
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000306def safeimport(path, forceload=0, cache={}):
307 """Import a module; handle errors; return None if the module isn't found.
308
309 If the module *is* found but an exception occurs, it's wrapped in an
310 ErrorDuringImport exception and reraised. Unlike __import__, if a
311 package path is specified, the module at the end of the path is returned,
312 not the package at the beginning. If the optional 'forceload' argument
313 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000314 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000315 # If forceload is 1 and the module has been previously loaded from
316 # disk, we always have to reload the module. Checking the file's
317 # mtime isn't good enough (e.g. the module could contain a class
318 # that inherits from another module that has changed).
319 if forceload and path in sys.modules:
320 if path not in sys.builtin_module_names:
Guido van Rossume7ba4952007-06-06 23:52:48 +0000321 # Remove the module from sys.modules and re-import to try
322 # and avoid problems with partially loaded modules.
323 # Also remove any submodules because they won't appear
324 # in the newly loaded module's namespace if they're already
325 # in sys.modules.
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000326 subs = [m for m in sys.modules if m.startswith(path + '.')]
327 for key in [path] + subs:
328 # Prevent garbage collection.
329 cache[key] = sys.modules[key]
330 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000331 module = __import__(path)
332 except:
333 # Did the error occur before or after the module was found?
334 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000335 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000336 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000337 raise ErrorDuringImport(sys.modules[path].__file__, info)
338 elif exc is SyntaxError:
339 # A SyntaxError occurred before we could execute the module.
340 raise ErrorDuringImport(value.filename, info)
Brett Cannon679ecb52013-07-04 17:51:50 -0400341 elif exc is ImportError and value.name == path:
Brett Cannonfd074152012-04-14 14:10:13 -0400342 # No such module in the path.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000343 return None
344 else:
345 # Some other error occurred during the importing process.
346 raise ErrorDuringImport(path, sys.exc_info())
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000347 for part in path.split('.')[1:]:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000348 try: module = getattr(module, part)
349 except AttributeError: return None
350 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000351
352# ---------------------------------------------------- formatter base class
353
354class Doc:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000355
356 PYTHONDOCS = os.environ.get("PYTHONDOCS",
357 "http://docs.python.org/%d.%d/library"
358 % sys.version_info[:2])
359
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000360 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000361 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000362 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000363 # 'try' clause is to attempt to handle the possibility that inspect
364 # identifies something in a way that pydoc itself has issues handling;
365 # think 'super' and how it is a descriptor (which raises the exception
366 # by lacking a __name__ attribute) and an instance.
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000367 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
368 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000369 try:
370 if inspect.ismodule(object): return self.docmodule(*args)
371 if inspect.isclass(object): return self.docclass(*args)
372 if inspect.isroutine(object): return self.docroutine(*args)
373 except AttributeError:
374 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000375 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000376 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000377
378 def fail(self, object, name=None, *args):
379 """Raise an exception for unimplemented types."""
380 message = "don't know how to document object%s of type %s" % (
381 name and ' ' + repr(name), type(object).__name__)
Collin Winterce36ad82007-08-30 01:19:48 +0000382 raise TypeError(message)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000383
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000384 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000385
Skip Montanaro4997a692003-09-10 16:47:51 +0000386 def getdocloc(self, object):
387 """Return the location of module docs or None"""
388
389 try:
390 file = inspect.getabsfile(object)
391 except TypeError:
392 file = '(built-in)'
393
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000394 docloc = os.environ.get("PYTHONDOCS", self.PYTHONDOCS)
395
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100396 basedir = os.path.join(sys.base_exec_prefix, "lib",
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000397 "python%d.%d" % sys.version_info[:2])
Skip Montanaro4997a692003-09-10 16:47:51 +0000398 if (isinstance(object, type(os)) and
399 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
400 'marshal', 'posix', 'signal', 'sys',
Georg Brandl2067bfd2008-05-25 13:05:15 +0000401 '_thread', 'zipimport') or
Skip Montanaro4997a692003-09-10 16:47:51 +0000402 (file.startswith(basedir) and
Brian Curtin49c284c2010-03-31 03:19:28 +0000403 not file.startswith(os.path.join(basedir, 'site-packages')))) and
Brian Curtinedef05b2010-04-01 04:05:25 +0000404 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
Skip Montanaro4997a692003-09-10 16:47:51 +0000405 if docloc.startswith("http://"):
Georg Brandl86def6c2008-01-21 20:36:10 +0000406 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
Skip Montanaro4997a692003-09-10 16:47:51 +0000407 else:
Georg Brandl86def6c2008-01-21 20:36:10 +0000408 docloc = os.path.join(docloc, object.__name__ + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000409 else:
410 docloc = None
411 return docloc
412
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000413# -------------------------------------------- HTML documentation generator
414
415class HTMLRepr(Repr):
416 """Class for safely making an HTML representation of a Python object."""
417 def __init__(self):
418 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000419 self.maxlist = self.maxtuple = 20
420 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000421 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000422
423 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000424 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000425
426 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000427 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000428
429 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000430 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000431 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000432 if hasattr(self, methodname):
433 return getattr(self, methodname)(x, level)
434 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000435
436 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000437 test = cram(x, self.maxstring)
438 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000439 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000440 # Backslashes are only literal in the string and are never
441 # needed to make any special characters, so show a raw string.
442 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000443 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000444 r'<font color="#c040c0">\1</font>',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000445 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000446
Skip Montanarodf708782002-03-07 22:58:02 +0000447 repr_str = repr_string
448
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000449 def repr_instance(self, x, level):
450 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000451 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000452 except:
453 return self.escape('<%s instance>' % x.__class__.__name__)
454
455 repr_unicode = repr_string
456
457class HTMLDoc(Doc):
458 """Formatter class for HTML documentation."""
459
460 # ------------------------------------------- HTML formatting utilities
461
462 _repr_instance = HTMLRepr()
463 repr = _repr_instance.repr
464 escape = _repr_instance.escape
465
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000466 def page(self, title, contents):
467 """Format an HTML page."""
Georg Brandl388faac2009-04-10 08:31:48 +0000468 return '''\
Georg Brandle6066942009-04-10 08:28:28 +0000469<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000470<html><head><title>Python: %s</title>
Georg Brandl388faac2009-04-10 08:31:48 +0000471<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000472</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000473%s
474</body></html>''' % (title, contents)
475
476 def heading(self, title, fgcol, bgcol, extras=''):
477 """Format a page heading."""
478 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000479<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000480<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000481<td valign=bottom>&nbsp;<br>
482<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000483><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000484><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000485 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
486
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000487 def section(self, title, fgcol, bgcol, contents, width=6,
488 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000489 """Format a section with a heading."""
490 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000491 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000492 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000493<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000494<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000495<td colspan=3 valign=bottom>&nbsp;<br>
496<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000497 ''' % (bgcol, fgcol, title)
498 if prelude:
499 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000500<tr bgcolor="%s"><td rowspan=2>%s</td>
501<td colspan=2>%s</td></tr>
502<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
503 else:
504 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000505<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000506
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000507 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000508
509 def bigsection(self, title, *args):
510 """Format a section with a big heading."""
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000511 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000512 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000513
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000514 def preformat(self, text):
515 """Format literal preformatted text."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000516 text = self.escape(text.expandtabs())
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000517 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
518 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000519
520 def multicolumn(self, list, format, cols=4):
521 """Format a list of items into a multi-column list."""
522 result = ''
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000523 rows = (len(list)+cols-1)//cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000524 for col in range(cols):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000525 result = result + '<td width="%d%%" valign=top>' % (100//cols)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000526 for i in range(rows*col, rows*col+rows):
527 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000528 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000529 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000530 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000531
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000532 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000533
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000534 def namelink(self, name, *dicts):
535 """Make a link for an identifier, given name-to-URL mappings."""
536 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000537 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000538 return '<a href="%s">%s</a>' % (dict[name], name)
539 return name
540
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000541 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000542 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000543 name, module = object.__name__, sys.modules.get(object.__module__)
544 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000545 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000546 module.__name__, name, classname(object, modname))
547 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000548
549 def modulelink(self, object):
550 """Make a link for a module."""
551 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
552
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000553 def modpkglink(self, modpkginfo):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000554 """Make a link for a module or package to display in an index."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000555 name, path, ispackage, shadowed = modpkginfo
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000556 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000557 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000558 if path:
559 url = '%s.%s.html' % (path, name)
560 else:
561 url = '%s.html' % name
562 if ispackage:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000563 text = '<strong>%s</strong>&nbsp;(package)' % name
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000564 else:
565 text = name
566 return '<a href="%s">%s</a>' % (url, text)
567
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000568 def filelink(self, url, path):
569 """Make a link to source file."""
570 return '<a href="file:%s">%s</a>' % (url, path)
571
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000572 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
573 """Mark up some plain text, given a context of symbols to look for.
574 Each context dictionary maps object names to anchor names."""
575 escape = escape or self.escape
576 results = []
577 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000578 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
579 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000580 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000581 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000582 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000583 match = pattern.search(text, here)
584 if not match: break
585 start, end = match.span()
586 results.append(escape(text[here:start]))
587
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000588 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000589 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000590 url = escape(all).replace('"', '&quot;')
591 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000592 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000593 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
594 results.append('<a href="%s">%s</a>' % (url, escape(all)))
595 elif pep:
Christian Heimes2202f872008-02-06 14:31:34 +0000596 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000597 results.append('<a href="%s">%s</a>' % (url, escape(all)))
Benjamin Petersoned1160b2014-06-07 16:44:00 -0700598 elif selfdot:
599 # Create a link for methods like 'self.method(...)'
600 # and use <strong> for attributes like 'self.attr'
601 if text[end:end+1] == '(':
602 results.append('self.' + self.namelink(name, methods))
603 else:
604 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000605 elif text[end:end+1] == '(':
606 results.append(self.namelink(name, methods, funcs, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000607 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000608 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000609 here = end
610 results.append(escape(text[here:]))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000611 return ''.join(results)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000612
613 # ---------------------------------------------- type-specific routines
614
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000615 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000616 """Produce HTML for a class tree as given by inspect.getclasstree()."""
617 result = ''
618 for entry in tree:
619 if type(entry) is type(()):
620 c, bases = entry
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000621 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000622 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000623 if bases and bases != (parent,):
624 parents = []
625 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000626 parents.append(self.classlink(base, modname))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000627 result = result + '(' + ', '.join(parents) + ')'
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000628 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000629 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000630 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000631 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000632 return '<dl>\n%s</dl>\n' % result
633
Tim Peters8dd7ade2001-10-18 19:56:17 +0000634 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000635 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000636 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000637 try:
638 all = object.__all__
639 except AttributeError:
640 all = None
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000641 parts = name.split('.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000642 links = []
643 for i in range(len(parts)-1):
644 links.append(
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000645 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000646 ('.'.join(parts[:i+1]), parts[i]))
647 linkedname = '.'.join(links + parts[-1:])
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000648 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000649 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000650 path = inspect.getabsfile(object)
Zachary Wareeb432142014-07-10 11:18:00 -0500651 url = urllib.parse.quote(path)
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000652 filelink = self.filelink(url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000653 except TypeError:
654 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000655 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000656 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000657 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000658 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000659 version = version[11:-1].strip()
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000660 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000661 if hasattr(object, '__date__'):
662 info.append(self.escape(str(object.__date__)))
663 if info:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000664 head = head + ' (%s)' % ', '.join(info)
Skip Montanaro4997a692003-09-10 16:47:51 +0000665 docloc = self.getdocloc(object)
666 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000667 docloc = '<br><a href="%(docloc)s">Module Reference</a>' % locals()
Skip Montanaro4997a692003-09-10 16:47:51 +0000668 else:
669 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000670 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000671 head, '#ffffff', '#7799ee',
672 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000673
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000674 modules = inspect.getmembers(object, inspect.ismodule)
675
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000676 classes, cdict = [], {}
677 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000678 # if __all__ exists, believe it. Otherwise use old heuristic.
679 if (all is not None or
680 (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700681 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000682 classes.append((key, value))
683 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000684 for key, value in classes:
685 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000686 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000687 module = sys.modules.get(modname)
688 if modname != name and module and hasattr(module, key):
689 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000690 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000691 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000692 funcs, fdict = [], {}
693 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000694 # if __all__ exists, believe it. Otherwise use old heuristic.
695 if (all is not None or
696 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700697 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000698 funcs.append((key, value))
699 fdict[key] = '#-' + key
700 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000701 data = []
702 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700703 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000704 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000705
706 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
707 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000708 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000709
710 if hasattr(object, '__path__'):
711 modpkgs = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000712 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
713 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000714 modpkgs.sort()
715 contents = self.multicolumn(modpkgs, self.modpkglink)
716 result = result + self.bigsection(
717 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000718 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000719 contents = self.multicolumn(
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000720 modules, lambda t: self.modulelink(t[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000721 result = result + self.bigsection(
Christian Heimes7131fd92008-02-19 14:21:46 +0000722 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000723
724 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000725 classlist = [value for (key, value) in classes]
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000726 contents = [
727 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000728 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000729 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000730 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000731 'Classes', '#ffffff', '#ee77aa', ' '.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000732 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000733 contents = []
734 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000735 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000736 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000737 'Functions', '#ffffff', '#eeaa77', ' '.join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000738 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000739 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000740 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000741 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000742 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000743 'Data', '#ffffff', '#55aa55', '<br>\n'.join(contents))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000744 if hasattr(object, '__author__'):
745 contents = self.markup(str(object.__author__), self.preformat)
746 result = result + self.bigsection(
747 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000748 if hasattr(object, '__credits__'):
749 contents = self.markup(str(object.__credits__), self.preformat)
750 result = result + self.bigsection(
751 'Credits', '#ffffff', '#7799ee', contents)
752
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000753 return result
754
Tim Peters8dd7ade2001-10-18 19:56:17 +0000755 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
756 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000757 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000758 realname = object.__name__
759 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000760 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000761
Tim Petersb47879b2001-09-24 04:47:19 +0000762 contents = []
763 push = contents.append
764
Tim Petersfa26f7c2001-09-24 08:05:11 +0000765 # Cute little class to pump out a horizontal rule between sections.
766 class HorizontalRule:
767 def __init__(self):
768 self.needone = 0
769 def maybe(self):
770 if self.needone:
771 push('<hr>\n')
772 self.needone = 1
773 hr = HorizontalRule()
774
Tim Petersc86f6ca2001-09-26 21:31:51 +0000775 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000776 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000777 if len(mro) > 2:
778 hr.maybe()
779 push('<dl><dt>Method resolution order:</dt>\n')
780 for base in mro:
781 push('<dd>%s</dd>\n' % self.classlink(base,
782 object.__module__))
783 push('</dl>\n')
784
Tim Petersb47879b2001-09-24 04:47:19 +0000785 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000786 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000787 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000788 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000789 push(msg)
790 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100791 try:
792 value = getattr(object, name)
793 except Exception:
794 # Some descriptors may meet a failure in their __get__.
795 # (bug #1785)
796 push(self._docdescriptor(name, value, mod))
797 else:
798 push(self.document(value, name, mod,
799 funcs, classes, mdict, object))
Tim Petersb47879b2001-09-24 04:47:19 +0000800 push('\n')
801 return attrs
802
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000803 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000804 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:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000809 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000810 return attrs
811
Tim Petersfa26f7c2001-09-24 08:05:11 +0000812 def spilldata(msg, attrs, predicate):
813 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000814 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000815 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000816 push(msg)
817 for name, kind, homecls, value in ok:
818 base = self.docother(getattr(object, name), name, mod)
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200819 if callable(value) or inspect.isdatadescriptor(value):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000820 doc = getattr(value, "__doc__", None)
821 else:
822 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000823 if doc is None:
824 push('<dl><dt>%s</dl>\n' % base)
825 else:
826 doc = self.markup(getdoc(value), self.preformat,
827 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000828 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000829 push('<dl><dt>%s%s</dl>\n' % (base, doc))
830 push('\n')
831 return attrs
832
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000833 attrs = [(name, kind, cls, value)
834 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -0700835 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000836
Tim Petersb47879b2001-09-24 04:47:19 +0000837 mdict = {}
838 for key, kind, homecls, value in attrs:
839 mdict[key] = anchor = '#' + name + '-' + key
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100840 try:
841 value = getattr(object, name)
842 except Exception:
843 # Some descriptors may meet a failure in their __get__.
844 # (bug #1785)
845 pass
Tim Petersb47879b2001-09-24 04:47:19 +0000846 try:
847 # The value may not be hashable (e.g., a data attr with
848 # a dict or list value).
849 mdict[value] = anchor
850 except TypeError:
851 pass
852
Tim Petersfa26f7c2001-09-24 08:05:11 +0000853 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000854 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000855 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000856 else:
857 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000858 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
859
Georg Brandl1a3284e2007-12-02 09:40:06 +0000860 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000861 attrs = inherited
862 continue
863 elif thisclass is object:
864 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000865 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000866 tag = 'inherited from %s' % self.classlink(thisclass,
867 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000868 tag += ':<br>\n'
869
870 # Sort attrs by name.
Raymond Hettingerd4cb56d2008-01-30 02:55:10 +0000871 attrs.sort(key=lambda t: t[0])
Tim Petersb47879b2001-09-24 04:47:19 +0000872
873 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000874 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000875 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000876 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000877 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000878 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000879 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000880 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
881 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000882 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000883 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000884 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000885 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000886
887 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000888
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000889 if name == realname:
890 title = '<a name="%s">class <strong>%s</strong></a>' % (
891 name, realname)
892 else:
893 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
894 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000895 if bases:
896 parents = []
897 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000898 parents.append(self.classlink(base, object.__module__))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000899 title = title + '(%s)' % ', '.join(parents)
Tim Peters2306d242001-09-25 03:18:32 +0000900 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000901 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000902
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000903 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000904
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000905 def formatvalue(self, object):
906 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000907 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000908
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000909 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000910 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000911 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000912 realname = object.__name__
913 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000914 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000915 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000916 skipdocs = 0
Larry Hastings24a882b2014-02-20 23:34:46 -0800917 if _is_bound_method(object):
Christian Heimesff737952007-11-27 10:40:20 +0000918 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000919 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000920 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000921 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000922 else:
Christian Heimesff737952007-11-27 10:40:20 +0000923 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000924 note = ' method of %s instance' % self.classlink(
Christian Heimesff737952007-11-27 10:40:20 +0000925 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000926 else:
927 note = ' unbound %s method' % self.classlink(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000928
929 if name == realname:
930 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
931 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000932 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000933 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000934 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000935 cl.__name__ + '-' + realname, realname)
936 skipdocs = 1
937 else:
938 reallink = realname
939 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
940 anchor, name, reallink)
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800941 argspec = None
Larry Hastings24a882b2014-02-20 23:34:46 -0800942 if inspect.isroutine(object):
Larry Hastings5c661892014-01-24 06:17:25 -0800943 try:
944 signature = inspect.signature(object)
945 except (ValueError, TypeError):
946 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800947 if signature:
948 argspec = str(signature)
949 if realname == '<lambda>':
950 title = '<strong>%s</strong> <em>lambda</em> ' % name
951 # XXX lambda's won't usually have func_annotations['return']
952 # since the syntax doesn't support but it is possible.
953 # So removing parentheses isn't truly safe.
954 argspec = argspec[1:-1] # remove parentheses
955 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +0000956 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000957
Serhiy Storchaka66dd4aa2014-11-17 23:48:02 +0200958 decl = title + self.escape(argspec) + (note and self.grey(
Tim Peters2306d242001-09-25 03:18:32 +0000959 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000960
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000961 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000962 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000963 else:
964 doc = self.markup(
965 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000966 doc = doc and '<dd><tt>%s</tt></dd>' % doc
967 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000968
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000969 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000970 results = []
971 push = results.append
972
973 if name:
974 push('<dl><dt><strong>%s</strong></dt>\n' % name)
975 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000976 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000977 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000978 push('</dl>\n')
979
980 return ''.join(results)
981
982 def docproperty(self, object, name=None, mod=None, cl=None):
983 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000984 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000985
Tim Peters8dd7ade2001-10-18 19:56:17 +0000986 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000987 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000988 lhs = name and '<strong>%s</strong> = ' % name or ''
989 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000990
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000991 def docdata(self, object, name=None, mod=None, cl=None):
992 """Produce html documentation for a data descriptor."""
993 return self._docdescriptor(name, object, mod)
994
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000995 def index(self, dir, shadowed=None):
996 """Generate an HTML index for a directory of modules."""
997 modpkgs = []
998 if shadowed is None: shadowed = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000999 for importer, name, ispkg in pkgutil.iter_modules([dir]):
Victor Stinner4d652242011-04-12 23:41:50 +02001000 if any((0xD800 <= ord(ch) <= 0xDFFF) for ch in name):
1001 # ignore a module if its name contains a surrogate character
1002 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001003 modpkgs.append((name, '', ispkg, name in shadowed))
1004 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001005
1006 modpkgs.sort()
1007 contents = self.multicolumn(modpkgs, self.modpkglink)
1008 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
1009
1010# -------------------------------------------- text documentation generator
1011
1012class TextRepr(Repr):
1013 """Class for safely making a text representation of a Python object."""
1014 def __init__(self):
1015 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001016 self.maxlist = self.maxtuple = 20
1017 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001018 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001019
1020 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001021 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001022 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001023 if hasattr(self, methodname):
1024 return getattr(self, methodname)(x, level)
1025 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001026
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001027 def repr_string(self, x, level):
1028 test = cram(x, self.maxstring)
1029 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001030 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001031 # Backslashes are only literal in the string and are never
1032 # needed to make any special characters, so show a raw string.
1033 return 'r' + testrepr[0] + test + testrepr[0]
1034 return testrepr
1035
Skip Montanarodf708782002-03-07 22:58:02 +00001036 repr_str = repr_string
1037
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001038 def repr_instance(self, x, level):
1039 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001040 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001041 except:
1042 return '<%s instance>' % x.__class__.__name__
1043
1044class TextDoc(Doc):
1045 """Formatter class for text documentation."""
1046
1047 # ------------------------------------------- text formatting utilities
1048
1049 _repr_instance = TextRepr()
1050 repr = _repr_instance.repr
1051
1052 def bold(self, text):
1053 """Format a string in bold by overstriking."""
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001054 return ''.join(ch + '\b' + ch for ch in text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001055
1056 def indent(self, text, prefix=' '):
1057 """Indent text by prepending a given prefix to each line."""
1058 if not text: return ''
Collin Winter72e110c2007-07-17 00:27:30 +00001059 lines = [prefix + line for line in text.split('\n')]
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001060 if lines: lines[-1] = lines[-1].rstrip()
1061 return '\n'.join(lines)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001062
1063 def section(self, title, contents):
1064 """Format a section with a given heading."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001065 clean_contents = self.indent(contents).rstrip()
1066 return self.bold(title) + '\n' + clean_contents + '\n\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001067
1068 # ---------------------------------------------- type-specific routines
1069
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001070 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001071 """Render in text a class tree as returned by inspect.getclasstree()."""
1072 result = ''
1073 for entry in tree:
1074 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001075 c, bases = entry
1076 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001077 if bases and bases != (parent,):
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001078 parents = (classname(c, modname) for c in bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001079 result = result + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001080 result = result + '\n'
1081 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001082 result = result + self.formattree(
1083 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001084 return result
1085
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001086 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001087 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001088 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001089 synop, desc = splitdoc(getdoc(object))
1090 result = self.section('NAME', name + (synop and ' - ' + synop))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001091 all = getattr(object, '__all__', None)
Skip Montanaro4997a692003-09-10 16:47:51 +00001092 docloc = self.getdocloc(object)
1093 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001094 result = result + self.section('MODULE REFERENCE', docloc + """
1095
Éric Araujo647ef8c2011-09-11 00:43:20 +02001096The following documentation is automatically generated from the Python
1097source files. It may be incomplete, incorrect or include features that
1098are considered implementation detail and may vary between Python
1099implementations. When in doubt, consult the module reference at the
1100location listed above.
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001101""")
Skip Montanaro4997a692003-09-10 16:47:51 +00001102
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001103 if desc:
1104 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001105
1106 classes = []
1107 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001108 # if __all__ exists, believe it. Otherwise use old heuristic.
1109 if (all is not None
1110 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001111 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001112 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001113 funcs = []
1114 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001115 # if __all__ exists, believe it. Otherwise use old heuristic.
1116 if (all is not None or
1117 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001118 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001119 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001120 data = []
1121 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001122 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001123 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001124
Christian Heimes1af737c2008-01-23 08:24:23 +00001125 modpkgs = []
1126 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001127 if hasattr(object, '__path__'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001128 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Christian Heimes1af737c2008-01-23 08:24:23 +00001129 modpkgs_names.add(modname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001130 if ispkg:
1131 modpkgs.append(modname + ' (package)')
1132 else:
1133 modpkgs.append(modname)
1134
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001135 modpkgs.sort()
1136 result = result + self.section(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001137 'PACKAGE CONTENTS', '\n'.join(modpkgs))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001138
Christian Heimes1af737c2008-01-23 08:24:23 +00001139 # Detect submodules as sometimes created by C extensions
1140 submodules = []
1141 for key, value in inspect.getmembers(object, inspect.ismodule):
1142 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1143 submodules.append(key)
1144 if submodules:
1145 submodules.sort()
1146 result = result + self.section(
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001147 'SUBMODULES', '\n'.join(submodules))
Christian Heimes1af737c2008-01-23 08:24:23 +00001148
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001149 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001150 classlist = [value for key, value in classes]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001151 contents = [self.formattree(
1152 inspect.getclasstree(classlist, 1), name)]
1153 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001154 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001155 result = result + self.section('CLASSES', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001156
1157 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001158 contents = []
1159 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001160 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001161 result = result + self.section('FUNCTIONS', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001162
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001163 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001164 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001165 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001166 contents.append(self.docother(value, key, name, maxlen=70))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001167 result = result + self.section('DATA', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001168
1169 if hasattr(object, '__version__'):
1170 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001171 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001172 version = version[11:-1].strip()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001173 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001174 if hasattr(object, '__date__'):
1175 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001176 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001177 result = result + self.section('AUTHOR', str(object.__author__))
1178 if hasattr(object, '__credits__'):
1179 result = result + self.section('CREDITS', str(object.__credits__))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001180 try:
1181 file = inspect.getabsfile(object)
1182 except TypeError:
1183 file = '(built-in)'
1184 result = result + self.section('FILE', file)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001185 return result
1186
Georg Brandl9bd45f992010-12-03 09:58:38 +00001187 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001188 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001189 realname = object.__name__
1190 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001191 bases = object.__bases__
1192
Tim Petersc86f6ca2001-09-26 21:31:51 +00001193 def makename(c, m=object.__module__):
1194 return classname(c, m)
1195
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001196 if name == realname:
1197 title = 'class ' + self.bold(realname)
1198 else:
1199 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001200 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001201 parents = map(makename, bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001202 title = title + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001203
1204 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001205 contents = doc and [doc + '\n'] or []
1206 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001207
Tim Petersc86f6ca2001-09-26 21:31:51 +00001208 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001209 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001210 if len(mro) > 2:
1211 push("Method resolution order:")
1212 for base in mro:
1213 push(' ' + makename(base))
1214 push('')
1215
Tim Petersf4aad8e2001-09-24 22:40:47 +00001216 # Cute little class to pump out a horizontal rule between sections.
1217 class HorizontalRule:
1218 def __init__(self):
1219 self.needone = 0
1220 def maybe(self):
1221 if self.needone:
1222 push('-' * 70)
1223 self.needone = 1
1224 hr = HorizontalRule()
1225
Tim Peters28355492001-09-23 21:29:55 +00001226 def spill(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:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001232 try:
1233 value = getattr(object, name)
1234 except Exception:
1235 # Some descriptors may meet a failure in their __get__.
1236 # (bug #1785)
1237 push(self._docdescriptor(name, value, mod))
1238 else:
1239 push(self.document(value,
1240 name, mod, object))
Tim Peters28355492001-09-23 21:29:55 +00001241 return attrs
1242
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001243 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001244 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001245 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001246 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001247 push(msg)
1248 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001249 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001250 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001251
Tim Petersfa26f7c2001-09-24 08:05:11 +00001252 def spilldata(msg, attrs, predicate):
1253 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001254 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001255 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001256 push(msg)
1257 for name, kind, homecls, value in ok:
Florent Xicluna5d1155c2011-10-28 14:45:05 +02001258 if callable(value) or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001259 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001260 else:
1261 doc = None
Serhiy Storchaka056eb022014-02-19 23:05:12 +02001262 try:
1263 obj = getattr(object, name)
1264 except AttributeError:
1265 obj = homecls.__dict__[name]
1266 push(self.docother(obj, name, mod, maxlen=70, doc=doc) +
1267 '\n')
Tim Peters28355492001-09-23 21:29:55 +00001268 return attrs
1269
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001270 attrs = [(name, kind, cls, value)
1271 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -07001272 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001273
Tim Petersfa26f7c2001-09-24 08:05:11 +00001274 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001275 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001276 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001277 else:
1278 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001279 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1280
Georg Brandl1a3284e2007-12-02 09:40:06 +00001281 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001282 attrs = inherited
1283 continue
1284 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001285 tag = "defined here"
1286 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001287 tag = "inherited from %s" % classname(thisclass,
1288 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001289 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001290 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001291
1292 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001293 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001294 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001295 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001296 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001297 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001298 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001299 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1300 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001301 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1302 lambda t: t[1] == 'data')
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001303
Tim Peters28355492001-09-23 21:29:55 +00001304 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001305 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001306
1307 contents = '\n'.join(contents)
1308 if not contents:
1309 return title + '\n'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001310 return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001311
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001312 def formatvalue(self, object):
1313 """Format an argument default value as text."""
1314 return '=' + self.repr(object)
1315
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001316 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001317 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001318 realname = object.__name__
1319 name = name or realname
1320 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001321 skipdocs = 0
Larry Hastings24a882b2014-02-20 23:34:46 -08001322 if _is_bound_method(object):
Christian Heimesff737952007-11-27 10:40:20 +00001323 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001324 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001325 if imclass is not cl:
1326 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001327 else:
Christian Heimesff737952007-11-27 10:40:20 +00001328 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001329 note = ' method of %s instance' % classname(
Christian Heimesff737952007-11-27 10:40:20 +00001330 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001331 else:
1332 note = ' unbound %s method' % classname(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001333
1334 if name == realname:
1335 title = self.bold(realname)
1336 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001337 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001338 cl.__dict__[realname] is object):
1339 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001340 title = self.bold(name) + ' = ' + realname
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001341 argspec = None
Larry Hastings5c661892014-01-24 06:17:25 -08001342
1343 if inspect.isroutine(object):
1344 try:
1345 signature = inspect.signature(object)
1346 except (ValueError, TypeError):
1347 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001348 if signature:
1349 argspec = str(signature)
1350 if realname == '<lambda>':
1351 title = self.bold(name) + ' lambda '
1352 # XXX lambda's won't usually have func_annotations['return']
1353 # since the syntax doesn't support but it is possible.
1354 # So removing parentheses isn't truly safe.
1355 argspec = argspec[1:-1] # remove parentheses
1356 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +00001357 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001358 decl = title + argspec + note
1359
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001360 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001361 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001362 else:
1363 doc = getdoc(object) or ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001364 return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001365
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001366 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001367 results = []
1368 push = results.append
1369
1370 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001371 push(self.bold(name))
1372 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001373 doc = getdoc(value) or ''
1374 if doc:
1375 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001376 push('\n')
1377 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001378
1379 def docproperty(self, object, name=None, mod=None, cl=None):
1380 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001381 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001382
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001383 def docdata(self, object, name=None, mod=None, cl=None):
1384 """Produce text documentation for a data descriptor."""
1385 return self._docdescriptor(name, object, mod)
1386
Georg Brandl8b813db2005-10-01 16:32:31 +00001387 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001388 """Produce text documentation for a data object."""
1389 repr = self.repr(object)
1390 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001391 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001392 chop = maxlen - len(line)
1393 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001394 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001395 if doc is not None:
1396 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001397 return line
1398
Georg Brandld80d5f42010-12-03 07:47:22 +00001399class _PlainTextDoc(TextDoc):
1400 """Subclass of TextDoc which overrides string styling"""
1401 def bold(self, text):
1402 return text
1403
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001404# --------------------------------------------------------- user interfaces
1405
1406def pager(text):
1407 """The first time this is called, determine what kind of pager to use."""
1408 global pager
1409 pager = getpager()
1410 pager(text)
1411
1412def getpager():
1413 """Decide what method to use for paging through text."""
Benjamin Peterson159824e2014-06-07 20:14:26 -07001414 if not hasattr(sys.stdin, "isatty"):
1415 return plainpager
Guido van Rossuma01a8b62007-05-27 09:20:14 +00001416 if not hasattr(sys.stdout, "isatty"):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001417 return plainpager
1418 if not sys.stdin.isatty() or not sys.stdout.isatty():
1419 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001420 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001421 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001422 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001423 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001424 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001425 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001426 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001427 if os.environ.get('TERM') in ('dumb', 'emacs'):
1428 return plainpager
Jesus Cea4791a242012-10-05 03:15:39 +02001429 if sys.platform == 'win32':
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001430 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001431 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001432 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001433
1434 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001435 (fd, filename) = tempfile.mkstemp()
1436 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001437 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001438 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001439 return lambda text: pipepager(text, 'more')
1440 else:
1441 return ttypager
1442 finally:
1443 os.unlink(filename)
1444
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001445def plain(text):
1446 """Remove boldface formatting from text."""
1447 return re.sub('.\b', '', text)
1448
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001449def pipepager(text, cmd):
1450 """Page through text by feeding it to another program."""
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001451 import subprocess
1452 proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001453 try:
R David Murray1058cda2015-03-29 15:15:40 -04001454 with io.TextIOWrapper(proc.stdin, errors='backslashreplace') as pipe:
R David Murraye7f5e142015-03-30 10:14:47 -04001455 try:
1456 pipe.write(text)
1457 except KeyboardInterrupt:
1458 # We've hereby abandoned whatever text hasn't been written,
1459 # but the pager is still in control of the terminal.
1460 pass
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001461 except OSError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001462 pass # Ignore broken pipes caused by quitting the pager program.
R David Murray1058cda2015-03-29 15:15:40 -04001463 while True:
1464 try:
1465 proc.wait()
1466 break
1467 except KeyboardInterrupt:
1468 # Ignore ctl-c like the pager itself does. Otherwise the pager is
1469 # left running and the terminal is in raw mode and unusable.
1470 pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001471
1472def tempfilepager(text, cmd):
1473 """Page through text by invoking a program on a temporary file."""
1474 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001475 filename = tempfile.mktemp()
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001476 with open(filename, 'w', errors='backslashreplace') as file:
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +01001477 file.write(text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001478 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001479 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001480 finally:
1481 os.unlink(filename)
1482
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001483def _escape_stdout(text):
1484 # Escape non-encodable characters to avoid encoding errors later
1485 encoding = getattr(sys.stdout, 'encoding', None) or 'utf-8'
1486 return text.encode(encoding, 'backslashreplace').decode(encoding)
1487
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001488def ttypager(text):
1489 """Page through text on a text terminal."""
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001490 lines = plain(_escape_stdout(text)).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001491 try:
1492 import tty
1493 fd = sys.stdin.fileno()
1494 old = tty.tcgetattr(fd)
1495 tty.setcbreak(fd)
1496 getchar = lambda: sys.stdin.read(1)
Serhiy Storchakaab5e9b92014-11-28 00:09:29 +02001497 except (ImportError, AttributeError, io.UnsupportedOperation):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001498 tty = None
1499 getchar = lambda: sys.stdin.readline()[:-1][:1]
1500
1501 try:
Serhiy Storchakaab5e9b92014-11-28 00:09:29 +02001502 try:
1503 h = int(os.environ.get('LINES', 0))
1504 except ValueError:
1505 h = 0
1506 if h <= 1:
1507 h = 25
1508 r = inc = h - 1
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001509 sys.stdout.write('\n'.join(lines[:inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001510 while lines[r:]:
1511 sys.stdout.write('-- more --')
1512 sys.stdout.flush()
1513 c = getchar()
1514
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001515 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001516 sys.stdout.write('\r \r')
1517 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001518 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001519 sys.stdout.write('\r \r' + lines[r] + '\n')
1520 r = r + 1
1521 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001522 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001523 r = r - inc - inc
1524 if r < 0: r = 0
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001525 sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001526 r = r + inc
1527
1528 finally:
1529 if tty:
1530 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1531
1532def plainpager(text):
1533 """Simply print unformatted text. This is the ultimate fallback."""
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001534 sys.stdout.write(plain(_escape_stdout(text)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001535
1536def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001537 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001538 if inspect.ismodule(thing):
1539 if thing.__name__ in sys.builtin_module_names:
1540 return 'built-in module ' + thing.__name__
1541 if hasattr(thing, '__path__'):
1542 return 'package ' + thing.__name__
1543 else:
1544 return 'module ' + thing.__name__
1545 if inspect.isbuiltin(thing):
1546 return 'built-in function ' + thing.__name__
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001547 if inspect.isgetsetdescriptor(thing):
1548 return 'getset descriptor %s.%s.%s' % (
1549 thing.__objclass__.__module__, thing.__objclass__.__name__,
1550 thing.__name__)
1551 if inspect.ismemberdescriptor(thing):
1552 return 'member descriptor %s.%s.%s' % (
1553 thing.__objclass__.__module__, thing.__objclass__.__name__,
1554 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001555 if inspect.isclass(thing):
1556 return 'class ' + thing.__name__
1557 if inspect.isfunction(thing):
1558 return 'function ' + thing.__name__
1559 if inspect.ismethod(thing):
1560 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001561 return type(thing).__name__
1562
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001563def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001564 """Locate an object by name or dotted path, importing as necessary."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001565 parts = [part for part in path.split('.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001566 module, n = None, 0
1567 while n < len(parts):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001568 nextmodule = safeimport('.'.join(parts[:n+1]), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001569 if nextmodule: module, n = nextmodule, n + 1
1570 else: break
1571 if module:
1572 object = module
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001573 else:
Éric Araujoe64e51b2011-07-29 17:03:55 +02001574 object = builtins
1575 for part in parts[n:]:
1576 try:
1577 object = getattr(object, part)
1578 except AttributeError:
1579 return None
1580 return object
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001581
1582# --------------------------------------- interactive interpreter interface
1583
1584text = TextDoc()
Georg Brandld80d5f42010-12-03 07:47:22 +00001585plaintext = _PlainTextDoc()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001586html = HTMLDoc()
1587
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001588def resolve(thing, forceload=0):
1589 """Given an object or a path to an object, get the object and its name."""
1590 if isinstance(thing, str):
1591 object = locate(thing, forceload)
Serhiy Storchakab6076fb2015-04-21 21:09:48 +03001592 if object is None:
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001593 raise ImportError('''\
1594No Python documentation found for %r.
1595Use help() to get the interactive help utility.
1596Use help(str) for help on the str class.''' % thing)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001597 return object, thing
1598 else:
R David Murrayc43125a2012-04-23 13:23:57 -04001599 name = getattr(thing, '__name__', None)
1600 return thing, name if isinstance(name, str) else None
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001601
Georg Brandld80d5f42010-12-03 07:47:22 +00001602def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
1603 renderer=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001604 """Render text documentation, given an object or a path to an object."""
Georg Brandld80d5f42010-12-03 07:47:22 +00001605 if renderer is None:
1606 renderer = text
Guido van Rossumd8faa362007-04-27 19:54:29 +00001607 object, name = resolve(thing, forceload)
1608 desc = describe(object)
1609 module = inspect.getmodule(object)
1610 if name and '.' in name:
1611 desc += ' in ' + name[:name.rfind('.')]
1612 elif module and module is not object:
1613 desc += ' in module ' + module.__name__
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001614
1615 if not (inspect.ismodule(object) or
Guido van Rossumd8faa362007-04-27 19:54:29 +00001616 inspect.isclass(object) or
1617 inspect.isroutine(object) or
1618 inspect.isgetsetdescriptor(object) or
1619 inspect.ismemberdescriptor(object) or
1620 isinstance(object, property)):
1621 # If the passed object is a piece of data or an instance,
1622 # document its available methods instead of its value.
1623 object = type(object)
1624 desc += ' object'
Georg Brandld80d5f42010-12-03 07:47:22 +00001625 return title % desc + '\n\n' + renderer.document(object, name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001626
Georg Brandld80d5f42010-12-03 07:47:22 +00001627def doc(thing, title='Python Library Documentation: %s', forceload=0,
1628 output=None):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001629 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001630 try:
Georg Brandld80d5f42010-12-03 07:47:22 +00001631 if output is None:
1632 pager(render_doc(thing, title, forceload))
1633 else:
1634 output.write(render_doc(thing, title, forceload, plaintext))
Guido van Rossumb940e112007-01-10 16:19:56 +00001635 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001636 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001637
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001638def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001639 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001640 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001641 object, name = resolve(thing, forceload)
1642 page = html.page(describe(object), html.document(object, name))
Serhiy Storchaka46ba6c82015-04-04 11:01:02 +03001643 with open(name + '.html', 'w', encoding='utf-8') as file:
1644 file.write(page)
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001645 print('wrote', name + '.html')
Guido van Rossumb940e112007-01-10 16:19:56 +00001646 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001647 print(value)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001648
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001649def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001650 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001651 if done is None: done = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001652 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1653 writedoc(modname)
1654 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001655
1656class Helper:
Georg Brandl6b38daa2008-06-01 21:05:17 +00001657
1658 # These dictionaries map a topic name to either an alias, or a tuple
1659 # (label, seealso-items). The "label" is the label of the corresponding
1660 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl5617db82009-04-27 16:28:57 +00001661 # in pydoc_data/topics.py.
Georg Brandl6b38daa2008-06-01 21:05:17 +00001662 #
1663 # CAUTION: if you change one of these dictionaries, be sure to adapt the
Georg Brandl61bd1dc2014-09-30 22:56:38 +02001664 # list of needed labels in Doc/tools/pyspecific.py and
Georg Brandl5617db82009-04-27 16:28:57 +00001665 # regenerate the pydoc_data/topics.py file by running
Georg Brandl6b38daa2008-06-01 21:05:17 +00001666 # make pydoc-topics
1667 # in Doc/ and copying the output file into the Lib/ directory.
1668
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001669 keywords = {
Ezio Melottib185a042011-04-28 07:42:55 +03001670 'False': '',
1671 'None': '',
1672 'True': '',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001673 'and': 'BOOLEAN',
Guido van Rossumd8faa362007-04-27 19:54:29 +00001674 'as': 'with',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001675 'assert': ('assert', ''),
1676 'break': ('break', 'while for'),
1677 'class': ('class', 'CLASSES SPECIALMETHODS'),
1678 'continue': ('continue', 'while for'),
1679 'def': ('function', ''),
1680 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001681 'elif': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001682 'else': ('else', 'while for'),
Georg Brandl0d855392008-08-30 19:53:05 +00001683 'except': 'try',
1684 'finally': 'try',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001685 'for': ('for', 'break continue while'),
Georg Brandl0d855392008-08-30 19:53:05 +00001686 'from': 'import',
Georg Brandl74abf6f2010-11-20 19:54:36 +00001687 'global': ('global', 'nonlocal NAMESPACES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001688 'if': ('if', 'TRUTHVALUE'),
1689 'import': ('import', 'MODULES'),
Georg Brandl395ed242009-09-04 08:07:32 +00001690 'in': ('in', 'SEQUENCEMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001691 'is': 'COMPARISON',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001692 'lambda': ('lambda', 'FUNCTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001693 'nonlocal': ('nonlocal', 'global NAMESPACES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001694 'not': 'BOOLEAN',
1695 'or': 'BOOLEAN',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001696 'pass': ('pass', ''),
1697 'raise': ('raise', 'EXCEPTIONS'),
1698 'return': ('return', 'FUNCTIONS'),
1699 'try': ('try', 'EXCEPTIONS'),
1700 'while': ('while', 'break continue if TRUTHVALUE'),
1701 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1702 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001703 }
Georg Brandldb7b6b92009-01-01 15:53:14 +00001704 # Either add symbols to this dictionary or to the symbols dictionary
1705 # directly: Whichever is easier. They are merged later.
1706 _symbols_inverse = {
1707 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'),
1708 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1709 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1710 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1711 'UNARY' : ('-', '~'),
1712 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1713 '^=', '<<=', '>>=', '**=', '//='),
1714 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1715 'COMPLEX' : ('j', 'J')
1716 }
1717 symbols = {
1718 '%': 'OPERATORS FORMATTING',
1719 '**': 'POWER',
1720 ',': 'TUPLES LISTS FUNCTIONS',
1721 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1722 '...': 'ELLIPSIS',
1723 ':': 'SLICINGS DICTIONARYLITERALS',
1724 '@': 'def class',
1725 '\\': 'STRINGS',
1726 '_': 'PRIVATENAMES',
1727 '__': 'PRIVATENAMES SPECIALMETHODS',
1728 '`': 'BACKQUOTES',
1729 '(': 'TUPLES FUNCTIONS CALLS',
1730 ')': 'TUPLES FUNCTIONS CALLS',
1731 '[': 'LISTS SUBSCRIPTS SLICINGS',
1732 ']': 'LISTS SUBSCRIPTS SLICINGS'
1733 }
1734 for topic, symbols_ in _symbols_inverse.items():
1735 for symbol in symbols_:
1736 topics = symbols.get(symbol, topic)
1737 if topic not in topics:
1738 topics = topics + ' ' + topic
1739 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001740
1741 topics = {
Georg Brandl6b38daa2008-06-01 21:05:17 +00001742 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1743 'FUNCTIONS CLASSES MODULES FILES inspect'),
1744 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS '
1745 'FORMATTING TYPES'),
1746 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1747 'FORMATTING': ('formatstrings', 'OPERATORS'),
1748 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1749 'FORMATTING TYPES'),
1750 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1751 'INTEGER': ('integers', 'int range'),
1752 'FLOAT': ('floating', 'float math'),
1753 'COMPLEX': ('imaginary', 'complex cmath'),
1754 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING range LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001755 'MAPPINGS': 'DICTIONARIES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001756 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1757 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1758 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1759 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001760 'FRAMEOBJECTS': 'TYPES',
1761 'TRACEBACKS': 'TYPES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001762 'NONE': ('bltin-null-object', ''),
1763 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001764 'SPECIALATTRIBUTES': ('specialattrs', ''),
1765 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1766 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001767 'PACKAGES': 'import',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001768 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1769 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1770 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1771 'LISTS DICTIONARIES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001772 'OPERATORS': 'EXPRESSIONS',
1773 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001774 'OBJECTS': ('objects', 'TYPES'),
1775 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
Georg Brandl395ed242009-09-04 08:07:32 +00001776 'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS '
1777 'NUMBERMETHODS CLASSES'),
Mark Dickinsona56c4672009-01-27 18:17:45 +00001778 'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001779 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1780 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001781 'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS '
Georg Brandl6b38daa2008-06-01 21:05:17 +00001782 'SPECIALMETHODS'),
1783 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1784 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1785 'SPECIALMETHODS'),
1786 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001787 'NAMESPACES': ('naming', 'global nonlocal ASSIGNMENT DELETION DYNAMICFEATURES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001788 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001789 'SCOPING': 'NAMESPACES',
1790 'FRAMES': 'NAMESPACES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001791 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1792 'CONVERSIONS': ('conversions', ''),
1793 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1794 'SPECIALIDENTIFIERS': ('id-classes', ''),
1795 'PRIVATENAMES': ('atom-identifiers', ''),
1796 'LITERALS': ('atom-literals', 'STRINGS NUMBERS TUPLELITERALS '
1797 'LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001798 'TUPLES': 'SEQUENCES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001799 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1800 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1801 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1802 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1803 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1804 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001805 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'),
1806 'SLICINGS': ('slicings', 'SEQUENCEMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001807 'CALLS': ('calls', 'EXPRESSIONS'),
1808 'POWER': ('power', 'EXPRESSIONS'),
1809 'UNARY': ('unary', 'EXPRESSIONS'),
1810 'BINARY': ('binary', 'EXPRESSIONS'),
1811 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1812 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1813 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1814 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001815 'ASSERTION': 'assert',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001816 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1817 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001818 'DELETION': 'del',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001819 'RETURNING': 'return',
1820 'IMPORTING': 'import',
1821 'CONDITIONAL': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001822 'LOOPING': ('compound', 'for while break continue'),
1823 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1824 'DEBUGGING': ('debugger', 'pdb'),
1825 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001826 }
1827
Georg Brandl78aa3962010-07-31 21:51:48 +00001828 def __init__(self, input=None, output=None):
1829 self._input = input
1830 self._output = output
1831
Georg Brandl76ae3972010-08-01 06:32:55 +00001832 input = property(lambda self: self._input or sys.stdin)
1833 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001834
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001835 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001836 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001837 self()
1838 return ''
Serhiy Storchaka465e60e2014-07-25 23:36:00 +03001839 return '<%s.%s instance>' % (self.__class__.__module__,
1840 self.__class__.__qualname__)
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001841
Alexander Belopolsky2e733c92010-07-04 17:00:20 +00001842 _GoInteractive = object()
1843 def __call__(self, request=_GoInteractive):
1844 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001845 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001846 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001847 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001848 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001849 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001850You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001851If you want to ask for help on a particular object directly from the
1852interpreter, you can type "help(object)". Executing "help('string')"
1853has the same effect as typing a particular string at the help> prompt.
1854''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001855
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001856 def interact(self):
1857 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001858 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001859 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001860 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001861 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001862 except (KeyboardInterrupt, EOFError):
1863 break
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001864 request = replace(request, '"', '', "'", '').strip()
1865 if request.lower() in ('q', 'quit'): break
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001866 if request == 'help':
1867 self.intro()
1868 else:
1869 self.help(request)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001870
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001871 def getline(self, prompt):
Guido van Rossum7c086c02008-01-02 03:52:38 +00001872 """Read one line, using input() when appropriate."""
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001873 if self.input is sys.stdin:
Guido van Rossum7c086c02008-01-02 03:52:38 +00001874 return input(prompt)
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001875 else:
1876 self.output.write(prompt)
1877 self.output.flush()
1878 return self.input.readline()
1879
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001880 def help(self, request):
1881 if type(request) is type(''):
R. David Murray1f1b9d32009-05-27 20:56:59 +00001882 request = request.strip()
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001883 if request == 'keywords': self.listkeywords()
Georg Brandldb7b6b92009-01-01 15:53:14 +00001884 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001885 elif request == 'topics': self.listtopics()
1886 elif request == 'modules': self.listmodules()
1887 elif request[:8] == 'modules ':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001888 self.listmodules(request.split()[1])
Georg Brandldb7b6b92009-01-01 15:53:14 +00001889 elif request in self.symbols: self.showsymbol(request)
Ezio Melottib185a042011-04-28 07:42:55 +03001890 elif request in ['True', 'False', 'None']:
1891 # special case these keywords since they are objects too
1892 doc(eval(request), 'Help on %s:')
Raymond Hettinger54f02222002-06-01 14:18:47 +00001893 elif request in self.keywords: self.showtopic(request)
1894 elif request in self.topics: self.showtopic(request)
Georg Brandld80d5f42010-12-03 07:47:22 +00001895 elif request: doc(request, 'Help on %s:', output=self._output)
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001896 else: doc(str, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001897 elif isinstance(request, Helper): self()
Georg Brandld80d5f42010-12-03 07:47:22 +00001898 else: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001899 self.output.write('\n')
1900
1901 def intro(self):
1902 self.output.write('''
R David Murray3d050dd2014-04-19 12:59:30 -04001903Welcome to Python %s's help utility!
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001904
1905If this is your first time using Python, you should definitely check out
R David Murrayde0f6292012-03-31 12:06:35 -04001906the tutorial on the Internet at http://docs.python.org/%s/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001907
1908Enter the name of any module, keyword, or topic to get help on writing
1909Python programs and using Python modules. To quit this help utility and
1910return to the interpreter, just type "quit".
1911
Terry Jan Reedy34200572013-02-11 02:23:13 -05001912To get a list of available modules, keywords, symbols, or topics, type
1913"modules", "keywords", "symbols", or "topics". Each module also comes
1914with a one-line summary of what it does; to list the modules whose name
1915or summary contain a given string such as "spam", type "modules spam".
R David Murrayde0f6292012-03-31 12:06:35 -04001916''' % tuple([sys.version[:3]]*2))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001917
1918 def list(self, items, columns=4, width=80):
Guido van Rossum486364b2007-06-30 05:01:58 +00001919 items = list(sorted(items))
1920 colw = width // columns
1921 rows = (len(items) + columns - 1) // columns
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001922 for row in range(rows):
1923 for col in range(columns):
1924 i = col * rows + row
1925 if i < len(items):
1926 self.output.write(items[i])
1927 if col < columns - 1:
Guido van Rossum486364b2007-06-30 05:01:58 +00001928 self.output.write(' ' + ' ' * (colw - 1 - len(items[i])))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001929 self.output.write('\n')
1930
1931 def listkeywords(self):
1932 self.output.write('''
1933Here is a list of the Python keywords. Enter any keyword to get more help.
1934
1935''')
1936 self.list(self.keywords.keys())
1937
Georg Brandldb7b6b92009-01-01 15:53:14 +00001938 def listsymbols(self):
1939 self.output.write('''
1940Here is a list of the punctuation symbols which Python assigns special meaning
1941to. Enter any symbol to get more help.
1942
1943''')
1944 self.list(self.symbols.keys())
1945
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001946 def listtopics(self):
1947 self.output.write('''
1948Here is a list of available topics. Enter any topic name to get more help.
1949
1950''')
1951 self.list(self.topics.keys())
1952
Georg Brandldb7b6b92009-01-01 15:53:14 +00001953 def showtopic(self, topic, more_xrefs=''):
Georg Brandl6b38daa2008-06-01 21:05:17 +00001954 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001955 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04001956 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001957 self.output.write('''
Georg Brandl6b38daa2008-06-01 21:05:17 +00001958Sorry, topic and keyword documentation is not available because the
Georg Brandl5617db82009-04-27 16:28:57 +00001959module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001960''')
1961 return
1962 target = self.topics.get(topic, self.keywords.get(topic))
1963 if not target:
1964 self.output.write('no documentation found for %s\n' % repr(topic))
1965 return
1966 if type(target) is type(''):
Georg Brandldb7b6b92009-01-01 15:53:14 +00001967 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001968
Georg Brandl6b38daa2008-06-01 21:05:17 +00001969 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001970 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001971 doc = pydoc_data.topics.topics[label]
Georg Brandl6b38daa2008-06-01 21:05:17 +00001972 except KeyError:
1973 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001974 return
Georg Brandl6b38daa2008-06-01 21:05:17 +00001975 pager(doc.strip() + '\n')
Georg Brandldb7b6b92009-01-01 15:53:14 +00001976 if more_xrefs:
1977 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001978 if xrefs:
Brett Cannon1448ecf2013-10-04 11:38:59 -04001979 import textwrap
1980 text = 'Related help topics: ' + ', '.join(xrefs.split()) + '\n'
1981 wrapped_text = textwrap.wrap(text, 72)
1982 self.output.write('\n%s\n' % ''.join(wrapped_text))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001983
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001984 def _gettopic(self, topic, more_xrefs=''):
1985 """Return unbuffered tuple of (topic, xrefs).
1986
Georg Brandld2f38572011-01-30 08:37:19 +00001987 If an error occurs here, the exception is caught and displayed by
1988 the url handler.
1989
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001990 This function duplicates the showtopic method but returns its
1991 result directly so it can be formatted for display in an html page.
1992 """
1993 try:
1994 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04001995 except ImportError:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001996 return('''
1997Sorry, topic and keyword documentation is not available because the
1998module "pydoc_data.topics" could not be found.
1999''' , '')
2000 target = self.topics.get(topic, self.keywords.get(topic))
2001 if not target:
Georg Brandld2f38572011-01-30 08:37:19 +00002002 raise ValueError('could not find topic')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002003 if isinstance(target, str):
2004 return self._gettopic(target, more_xrefs)
2005 label, xrefs = target
Georg Brandld2f38572011-01-30 08:37:19 +00002006 doc = pydoc_data.topics.topics[label]
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002007 if more_xrefs:
2008 xrefs = (xrefs or '') + ' ' + more_xrefs
2009 return doc, xrefs
2010
Georg Brandldb7b6b92009-01-01 15:53:14 +00002011 def showsymbol(self, symbol):
2012 target = self.symbols[symbol]
2013 topic, _, xrefs = target.partition(' ')
2014 self.showtopic(topic, xrefs)
2015
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002016 def listmodules(self, key=''):
2017 if key:
2018 self.output.write('''
Terry Jan Reedy34200572013-02-11 02:23:13 -05002019Here is a list of modules whose name or summary contains '{}'.
2020If there are any, enter a module name to get more help.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002021
Terry Jan Reedy34200572013-02-11 02:23:13 -05002022'''.format(key))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002023 apropos(key)
2024 else:
2025 self.output.write('''
2026Please wait a moment while I gather a list of all available modules...
2027
2028''')
2029 modules = {}
2030 def callback(path, modname, desc, modules=modules):
2031 if modname and modname[-9:] == '.__init__':
2032 modname = modname[:-9] + ' (package)'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002033 if modname.find('.') < 0:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002034 modules[modname] = 1
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002035 def onerror(modname):
2036 callback(None, modname, None)
2037 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002038 self.list(modules.keys())
2039 self.output.write('''
2040Enter any module name to get more help. Or, type "modules spam" to search
Terry Jan Reedy34200572013-02-11 02:23:13 -05002041for modules whose name or summary contain the string "spam".
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002042''')
2043
Georg Brandl78aa3962010-07-31 21:51:48 +00002044help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002045
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002046class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002047 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002048
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002049 def run(self, callback, key=None, completer=None, onerror=None):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002050 if key: key = key.lower()
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002051 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002052 seen = {}
2053
2054 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002055 if modname != '__main__':
2056 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00002057 if key is None:
2058 callback(None, modname, '')
2059 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002060 name = __import__(modname).__doc__ or ''
2061 desc = name.split('\n')[0]
2062 name = modname + ' - ' + desc
2063 if name.lower().find(key) >= 0:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002064 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002065
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002066 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002067 if self.quit:
2068 break
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002069
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002070 if key is None:
2071 callback(None, modname, '')
2072 else:
Georg Brandl126c8792009-04-05 15:05:48 +00002073 try:
Eric Snow3a62d142014-01-06 20:42:59 -07002074 spec = pkgutil._get_spec(importer, modname)
Georg Brandl126c8792009-04-05 15:05:48 +00002075 except SyntaxError:
2076 # raised by tests for bad coding cookies or BOM
2077 continue
Eric Snow3a62d142014-01-06 20:42:59 -07002078 loader = spec.loader
Georg Brandl126c8792009-04-05 15:05:48 +00002079 if hasattr(loader, 'get_source'):
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002080 try:
2081 source = loader.get_source(modname)
Nick Coghlan2824cb52012-07-15 22:12:14 +10002082 except Exception:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002083 if onerror:
2084 onerror(modname)
2085 continue
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002086 desc = source_synopsis(io.StringIO(source)) or ''
Georg Brandl126c8792009-04-05 15:05:48 +00002087 if hasattr(loader, 'get_filename'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002088 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002089 else:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002090 path = None
2091 else:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002092 try:
Brett Cannon2a17bde2014-05-30 14:55:29 -04002093 module = importlib._bootstrap._load(spec)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002094 except ImportError:
2095 if onerror:
2096 onerror(modname)
2097 continue
Benjamin Peterson54237f92015-02-16 19:45:01 -05002098 desc = module.__doc__.splitlines()[0] if module.__doc__ else ''
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002099 path = getattr(module,'__file__',None)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002100 name = modname + ' - ' + desc
2101 if name.lower().find(key) >= 0:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002102 callback(path, modname, desc)
2103
2104 if completer:
2105 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002106
2107def apropos(key):
2108 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002109 def callback(path, modname, desc):
2110 if modname[-9:] == '.__init__':
2111 modname = modname[:-9] + ' (package)'
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002112 print(modname, desc and '- ' + desc)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002113 def onerror(modname):
2114 pass
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002115 with warnings.catch_warnings():
2116 warnings.filterwarnings('ignore') # ignore problems during import
2117 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002118
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002119# --------------------------------------- enhanced Web browser interface
2120
2121def _start_server(urlhandler, port):
2122 """Start an HTTP server thread on a specific port.
2123
2124 Start an HTML/text server thread, so HTML or text documents can be
2125 browsed dynamically and interactively with a Web browser. Example use:
2126
2127 >>> import time
2128 >>> import pydoc
2129
2130 Define a URL handler. To determine what the client is asking
2131 for, check the URL and content_type.
2132
2133 Then get or generate some text or HTML code and return it.
2134
2135 >>> def my_url_handler(url, content_type):
2136 ... text = 'the URL sent was: (%s, %s)' % (url, content_type)
2137 ... return text
2138
2139 Start server thread on port 0.
2140 If you use port 0, the server will pick a random port number.
2141 You can then use serverthread.port to get the port number.
2142
2143 >>> port = 0
2144 >>> serverthread = pydoc._start_server(my_url_handler, port)
2145
2146 Check that the server is really started. If it is, open browser
2147 and get first page. Use serverthread.url as the starting page.
2148
2149 >>> if serverthread.serving:
2150 ... import webbrowser
2151
2152 The next two lines are commented out so a browser doesn't open if
2153 doctest is run on this module.
2154
2155 #... webbrowser.open(serverthread.url)
2156 #True
2157
2158 Let the server do its thing. We just need to monitor its status.
2159 Use time.sleep so the loop doesn't hog the CPU.
2160
2161 >>> starttime = time.time()
2162 >>> timeout = 1 #seconds
2163
2164 This is a short timeout for testing purposes.
2165
2166 >>> while serverthread.serving:
2167 ... time.sleep(.01)
2168 ... if serverthread.serving and time.time() - starttime > timeout:
2169 ... serverthread.stop()
2170 ... break
2171
2172 Print any errors that may have occurred.
2173
2174 >>> print(serverthread.error)
2175 None
2176 """
2177 import http.server
2178 import email.message
2179 import select
2180 import threading
2181
2182 class DocHandler(http.server.BaseHTTPRequestHandler):
2183
2184 def do_GET(self):
2185 """Process a request from an HTML browser.
2186
2187 The URL received is in self.path.
2188 Get an HTML page from self.urlhandler and send it.
2189 """
2190 if self.path.endswith('.css'):
2191 content_type = 'text/css'
2192 else:
2193 content_type = 'text/html'
2194 self.send_response(200)
Georg Brandld2f38572011-01-30 08:37:19 +00002195 self.send_header('Content-Type', '%s; charset=UTF-8' % content_type)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002196 self.end_headers()
2197 self.wfile.write(self.urlhandler(
2198 self.path, content_type).encode('utf-8'))
2199
2200 def log_message(self, *args):
2201 # Don't log messages.
2202 pass
2203
2204 class DocServer(http.server.HTTPServer):
2205
2206 def __init__(self, port, callback):
Senthil Kumaran2a42a0b2014-09-17 13:17:58 +08002207 self.host = 'localhost'
2208 self.address = (self.host, port)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002209 self.callback = callback
2210 self.base.__init__(self, self.address, self.handler)
2211 self.quit = False
2212
2213 def serve_until_quit(self):
2214 while not self.quit:
2215 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2216 if rd:
2217 self.handle_request()
Victor Stinnera3abd1d2011-01-03 16:12:39 +00002218 self.server_close()
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002219
2220 def server_activate(self):
2221 self.base.server_activate(self)
2222 if self.callback:
2223 self.callback(self)
2224
2225 class ServerThread(threading.Thread):
2226
2227 def __init__(self, urlhandler, port):
2228 self.urlhandler = urlhandler
2229 self.port = int(port)
2230 threading.Thread.__init__(self)
2231 self.serving = False
2232 self.error = None
2233
2234 def run(self):
2235 """Start the server."""
2236 try:
2237 DocServer.base = http.server.HTTPServer
2238 DocServer.handler = DocHandler
2239 DocHandler.MessageClass = email.message.Message
2240 DocHandler.urlhandler = staticmethod(self.urlhandler)
2241 docsvr = DocServer(self.port, self.ready)
2242 self.docserver = docsvr
2243 docsvr.serve_until_quit()
2244 except Exception as e:
2245 self.error = e
2246
2247 def ready(self, server):
2248 self.serving = True
2249 self.host = server.host
2250 self.port = server.server_port
2251 self.url = 'http://%s:%d/' % (self.host, self.port)
2252
2253 def stop(self):
2254 """Stop the server and this thread nicely"""
2255 self.docserver.quit = True
2256 self.serving = False
2257 self.url = None
2258
2259 thread = ServerThread(urlhandler, port)
2260 thread.start()
2261 # Wait until thread.serving is True to make sure we are
2262 # really up before returning.
2263 while not thread.error and not thread.serving:
2264 time.sleep(.01)
2265 return thread
2266
2267
2268def _url_handler(url, content_type="text/html"):
2269 """The pydoc url handler for use with the pydoc server.
2270
2271 If the content_type is 'text/css', the _pydoc.css style
2272 sheet is read and returned if it exits.
2273
2274 If the content_type is 'text/html', then the result of
2275 get_html_page(url) is returned.
2276 """
2277 class _HTMLDoc(HTMLDoc):
2278
2279 def page(self, title, contents):
2280 """Format an HTML page."""
2281 css_path = "pydoc_data/_pydoc.css"
2282 css_link = (
2283 '<link rel="stylesheet" type="text/css" href="%s">' %
2284 css_path)
2285 return '''\
2286<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Georg Brandld2f38572011-01-30 08:37:19 +00002287<html><head><title>Pydoc: %s</title>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002288<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Georg Brandld2f38572011-01-30 08:37:19 +00002289%s</head><body bgcolor="#f0f0f8">%s<div style="clear:both;padding-top:.5em;">%s</div>
2290</body></html>''' % (title, css_link, html_navbar(), contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002291
2292 def filelink(self, url, path):
2293 return '<a href="getfile?key=%s">%s</a>' % (url, path)
2294
2295
2296 html = _HTMLDoc()
2297
2298 def html_navbar():
Georg Brandld2f38572011-01-30 08:37:19 +00002299 version = html.escape("%s [%s, %s]" % (platform.python_version(),
2300 platform.python_build()[0],
2301 platform.python_compiler()))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002302 return """
2303 <div style='float:left'>
Georg Brandld2f38572011-01-30 08:37:19 +00002304 Python %s<br>%s
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002305 </div>
2306 <div style='float:right'>
2307 <div style='text-align:center'>
2308 <a href="index.html">Module Index</a>
2309 : <a href="topics.html">Topics</a>
2310 : <a href="keywords.html">Keywords</a>
2311 </div>
2312 <div>
Georg Brandld2f38572011-01-30 08:37:19 +00002313 <form action="get" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002314 <input type=text name=key size=15>
2315 <input type=submit value="Get">
Georg Brandld2f38572011-01-30 08:37:19 +00002316 </form>&nbsp;
2317 <form action="search" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002318 <input type=text name=key size=15>
2319 <input type=submit value="Search">
2320 </form>
2321 </div>
2322 </div>
Georg Brandld2f38572011-01-30 08:37:19 +00002323 """ % (version, html.escape(platform.platform(terse=True)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002324
2325 def html_index():
2326 """Module Index page."""
2327
2328 def bltinlink(name):
2329 return '<a href="%s.html">%s</a>' % (name, name)
2330
2331 heading = html.heading(
2332 '<big><big><strong>Index of Modules</strong></big></big>',
2333 '#ffffff', '#7799ee')
2334 names = [name for name in sys.builtin_module_names
2335 if name != '__main__']
2336 contents = html.multicolumn(names, bltinlink)
2337 contents = [heading, '<p>' + html.bigsection(
2338 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2339
2340 seen = {}
2341 for dir in sys.path:
2342 contents.append(html.index(dir, seen))
2343
2344 contents.append(
2345 '<p align=right><font color="#909090" face="helvetica,'
2346 'arial"><strong>pydoc</strong> by Ka-Ping Yee'
2347 '&lt;ping@lfw.org&gt;</font>')
Nick Coghlanecace282010-12-03 16:08:46 +00002348 return 'Index of Modules', ''.join(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002349
2350 def html_search(key):
2351 """Search results page."""
2352 # scan for modules
2353 search_result = []
2354
2355 def callback(path, modname, desc):
2356 if modname[-9:] == '.__init__':
2357 modname = modname[:-9] + ' (package)'
2358 search_result.append((modname, desc and '- ' + desc))
2359
2360 with warnings.catch_warnings():
2361 warnings.filterwarnings('ignore') # ignore problems during import
2362 ModuleScanner().run(callback, key)
2363
2364 # format page
2365 def bltinlink(name):
2366 return '<a href="%s.html">%s</a>' % (name, name)
2367
2368 results = []
2369 heading = html.heading(
2370 '<big><big><strong>Search Results</strong></big></big>',
2371 '#ffffff', '#7799ee')
2372 for name, desc in search_result:
2373 results.append(bltinlink(name) + desc)
2374 contents = heading + html.bigsection(
2375 'key = %s' % key, '#ffffff', '#ee77aa', '<br>'.join(results))
Nick Coghlanecace282010-12-03 16:08:46 +00002376 return 'Search Results', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002377
2378 def html_getfile(path):
2379 """Get and display a source file listing safely."""
Zachary Wareeb432142014-07-10 11:18:00 -05002380 path = urllib.parse.unquote(path)
Victor Stinner91e08772011-07-05 14:30:41 +02002381 with tokenize.open(path) as fp:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002382 lines = html.escape(fp.read())
2383 body = '<pre>%s</pre>' % lines
2384 heading = html.heading(
2385 '<big><big><strong>File Listing</strong></big></big>',
2386 '#ffffff', '#7799ee')
2387 contents = heading + html.bigsection(
2388 'File: %s' % path, '#ffffff', '#ee77aa', body)
Nick Coghlanecace282010-12-03 16:08:46 +00002389 return 'getfile %s' % path, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002390
2391 def html_topics():
2392 """Index of topic texts available."""
2393
2394 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002395 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002396
2397 heading = html.heading(
2398 '<big><big><strong>INDEX</strong></big></big>',
2399 '#ffffff', '#7799ee')
2400 names = sorted(Helper.topics.keys())
2401
2402 contents = html.multicolumn(names, bltinlink)
2403 contents = heading + html.bigsection(
2404 'Topics', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002405 return 'Topics', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002406
2407 def html_keywords():
2408 """Index of keywords."""
2409 heading = html.heading(
2410 '<big><big><strong>INDEX</strong></big></big>',
2411 '#ffffff', '#7799ee')
2412 names = sorted(Helper.keywords.keys())
2413
2414 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002415 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002416
2417 contents = html.multicolumn(names, bltinlink)
2418 contents = heading + html.bigsection(
2419 'Keywords', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002420 return 'Keywords', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002421
2422 def html_topicpage(topic):
2423 """Topic or keyword help page."""
2424 buf = io.StringIO()
2425 htmlhelp = Helper(buf, buf)
2426 contents, xrefs = htmlhelp._gettopic(topic)
2427 if topic in htmlhelp.keywords:
2428 title = 'KEYWORD'
2429 else:
2430 title = 'TOPIC'
2431 heading = html.heading(
2432 '<big><big><strong>%s</strong></big></big>' % title,
2433 '#ffffff', '#7799ee')
Georg Brandld2f38572011-01-30 08:37:19 +00002434 contents = '<pre>%s</pre>' % html.markup(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002435 contents = html.bigsection(topic , '#ffffff','#ee77aa', contents)
Georg Brandld2f38572011-01-30 08:37:19 +00002436 if xrefs:
2437 xrefs = sorted(xrefs.split())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002438
Georg Brandld2f38572011-01-30 08:37:19 +00002439 def bltinlink(name):
2440 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002441
Georg Brandld2f38572011-01-30 08:37:19 +00002442 xrefs = html.multicolumn(xrefs, bltinlink)
2443 xrefs = html.section('Related help topics: ',
2444 '#ffffff', '#ee77aa', xrefs)
Nick Coghlanecace282010-12-03 16:08:46 +00002445 return ('%s %s' % (title, topic),
2446 ''.join((heading, contents, xrefs)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002447
Georg Brandld2f38572011-01-30 08:37:19 +00002448 def html_getobj(url):
2449 obj = locate(url, forceload=1)
2450 if obj is None and url != 'None':
2451 raise ValueError('could not find object')
2452 title = describe(obj)
2453 content = html.document(obj, url)
2454 return title, content
2455
2456 def html_error(url, exc):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002457 heading = html.heading(
2458 '<big><big><strong>Error</strong></big></big>',
Georg Brandld2f38572011-01-30 08:37:19 +00002459 '#ffffff', '#7799ee')
2460 contents = '<br>'.join(html.escape(line) for line in
2461 format_exception_only(type(exc), exc))
2462 contents = heading + html.bigsection(url, '#ffffff', '#bb0000',
2463 contents)
2464 return "Error - %s" % url, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002465
2466 def get_html_page(url):
2467 """Generate an HTML page for url."""
Georg Brandld2f38572011-01-30 08:37:19 +00002468 complete_url = url
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002469 if url.endswith('.html'):
2470 url = url[:-5]
Georg Brandld2f38572011-01-30 08:37:19 +00002471 try:
2472 if url in ("", "index"):
2473 title, content = html_index()
2474 elif url == "topics":
2475 title, content = html_topics()
2476 elif url == "keywords":
2477 title, content = html_keywords()
2478 elif '=' in url:
2479 op, _, url = url.partition('=')
2480 if op == "search?key":
2481 title, content = html_search(url)
2482 elif op == "getfile?key":
2483 title, content = html_getfile(url)
2484 elif op == "topic?key":
2485 # try topics first, then objects.
2486 try:
2487 title, content = html_topicpage(url)
2488 except ValueError:
2489 title, content = html_getobj(url)
2490 elif op == "get?key":
2491 # try objects first, then topics.
2492 if url in ("", "index"):
2493 title, content = html_index()
2494 else:
2495 try:
2496 title, content = html_getobj(url)
2497 except ValueError:
2498 title, content = html_topicpage(url)
2499 else:
2500 raise ValueError('bad pydoc url')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002501 else:
Georg Brandld2f38572011-01-30 08:37:19 +00002502 title, content = html_getobj(url)
2503 except Exception as exc:
2504 # Catch any errors and display them in an error page.
2505 title, content = html_error(complete_url, exc)
2506 return html.page(title, content)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002507
2508 if url.startswith('/'):
2509 url = url[1:]
2510 if content_type == 'text/css':
2511 path_here = os.path.dirname(os.path.realpath(__file__))
Georg Brandld2f38572011-01-30 08:37:19 +00002512 css_path = os.path.join(path_here, url)
2513 with open(css_path) as fp:
2514 return ''.join(fp.readlines())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002515 elif content_type == 'text/html':
2516 return get_html_page(url)
Georg Brandld2f38572011-01-30 08:37:19 +00002517 # Errors outside the url handler are caught by the server.
2518 raise TypeError('unknown content type %r for url %s' % (content_type, url))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002519
2520
2521def browse(port=0, *, open_browser=True):
2522 """Start the enhanced pydoc Web server and open a Web browser.
2523
2524 Use port '0' to start the server on an arbitrary port.
2525 Set open_browser to False to suppress opening a browser.
2526 """
2527 import webbrowser
2528 serverthread = _start_server(_url_handler, port)
2529 if serverthread.error:
2530 print(serverthread.error)
2531 return
2532 if serverthread.serving:
2533 server_help_msg = 'Server commands: [b]rowser, [q]uit'
2534 if open_browser:
2535 webbrowser.open(serverthread.url)
2536 try:
2537 print('Server ready at', serverthread.url)
2538 print(server_help_msg)
2539 while serverthread.serving:
2540 cmd = input('server> ')
2541 cmd = cmd.lower()
2542 if cmd == 'q':
2543 break
2544 elif cmd == 'b':
2545 webbrowser.open(serverthread.url)
2546 else:
2547 print(server_help_msg)
2548 except (KeyboardInterrupt, EOFError):
2549 print()
2550 finally:
2551 if serverthread.serving:
2552 serverthread.stop()
2553 print('Server stopped')
2554
2555
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002556# -------------------------------------------------- command-line interface
2557
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002558def ispath(x):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002559 return isinstance(x, str) and x.find(os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002560
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002561def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002562 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002563 import getopt
Guido van Rossum756aa932007-04-07 03:04:01 +00002564 class BadUsage(Exception): pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002565
Nick Coghlan106274b2009-11-15 23:04:33 +00002566 # Scripts don't get the current directory in their path by default
2567 # unless they are run with the '-m' switch
2568 if '' not in sys.path:
2569 scriptdir = os.path.dirname(sys.argv[0])
2570 if scriptdir in sys.path:
2571 sys.path.remove(scriptdir)
2572 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002573
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002574 try:
Victor Stinner383c3fc2011-05-25 01:35:05 +02002575 opts, args = getopt.getopt(sys.argv[1:], 'bk:p:w')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002576 writing = False
2577 start_server = False
2578 open_browser = False
2579 port = None
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002580 for opt, val in opts:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002581 if opt == '-b':
2582 start_server = True
2583 open_browser = True
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002584 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002585 apropos(val)
2586 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002587 if opt == '-p':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002588 start_server = True
2589 port = val
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002590 if opt == '-w':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002591 writing = True
2592
Benjamin Petersonb29614e2012-10-09 11:16:03 -04002593 if start_server:
2594 if port is None:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002595 port = 0
2596 browse(port, open_browser=open_browser)
2597 return
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002598
2599 if not args: raise BadUsage
2600 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002601 if ispath(arg) and not os.path.exists(arg):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002602 print('file %r does not exist' % arg)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002603 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002604 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002605 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002606 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002607 if writing:
2608 if ispath(arg) and os.path.isdir(arg):
2609 writedocs(arg)
2610 else:
2611 writedoc(arg)
2612 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002613 help.help(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +00002614 except ErrorDuringImport as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002615 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002616
2617 except (getopt.error, BadUsage):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002618 cmd = os.path.splitext(os.path.basename(sys.argv[0]))[0]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002619 print("""pydoc - the Python documentation tool
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002620
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002621{cmd} <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002622 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002623 Python keyword, topic, function, module, or package, or a dotted
2624 reference to a class or function within a module or module in a
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002625 package. If <name> contains a '{sep}', it is used as the path to a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002626 Python source file to document. If name is 'keywords', 'topics',
2627 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002628
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002629{cmd} -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002630 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002631
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002632{cmd} -p <port>
2633 Start an HTTP server on the given port on the local machine. Port
2634 number 0 can be used to get an arbitrary unused port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002635
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002636{cmd} -b
2637 Start an HTTP server on an arbitrary unused port and open a Web browser
2638 to interactively browse documentation. The -p option can be used with
2639 the -b option to explicitly specify the server port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002640
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002641{cmd} -w <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002642 Write out the HTML documentation for a module to a file in the current
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002643 directory. If <name> contains a '{sep}', it is treated as a filename; if
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002644 it names a directory, documentation is written for all the contents.
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002645""".format(cmd=cmd, sep=os.sep))
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002646
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002647if __name__ == '__main__':
2648 cli()