blob: 0d0d0abec1ba7efb4b20730a3a7a172edd8c0a37 [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
Martin Panter4f8aaf62016-06-12 04:24:06 +000031 https://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",
R David Murrayead9bfc2016-06-03 19:28:35 -0400357 "https://docs.python.org/%d.%d/library"
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000358 % 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
R David Murrayead9bfc2016-06-03 19:28:35 -0400386 def getdocloc(self, object,
387 basedir=os.path.join(sys.base_exec_prefix, "lib",
388 "python%d.%d" % sys.version_info[:2])):
Skip Montanaro4997a692003-09-10 16:47:51 +0000389 """Return the location of module docs or None"""
390
391 try:
392 file = inspect.getabsfile(object)
393 except TypeError:
394 file = '(built-in)'
395
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000396 docloc = os.environ.get("PYTHONDOCS", self.PYTHONDOCS)
397
Martin Panter4f8aaf62016-06-12 04:24:06 +0000398 basedir = os.path.normcase(basedir)
Skip Montanaro4997a692003-09-10 16:47:51 +0000399 if (isinstance(object, type(os)) and
400 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
401 'marshal', 'posix', 'signal', 'sys',
Georg Brandl2067bfd2008-05-25 13:05:15 +0000402 '_thread', 'zipimport') or
Skip Montanaro4997a692003-09-10 16:47:51 +0000403 (file.startswith(basedir) and
Brian Curtin49c284c2010-03-31 03:19:28 +0000404 not file.startswith(os.path.join(basedir, 'site-packages')))) and
Brian Curtinedef05b2010-04-01 04:05:25 +0000405 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
Martin Panter4f8aaf62016-06-12 04:24:06 +0000406 if docloc.startswith(("http://", "https://")):
R David Murrayead9bfc2016-06-03 19:28:35 -0400407 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__.lower())
Skip Montanaro4997a692003-09-10 16:47:51 +0000408 else:
R David Murrayead9bfc2016-06-03 19:28:35 -0400409 docloc = os.path.join(docloc, object.__name__.lower() + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000410 else:
411 docloc = None
412 return docloc
413
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000414# -------------------------------------------- HTML documentation generator
415
416class HTMLRepr(Repr):
417 """Class for safely making an HTML representation of a Python object."""
418 def __init__(self):
419 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000420 self.maxlist = self.maxtuple = 20
421 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000422 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000423
424 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000425 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000426
427 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000428 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000429
430 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000431 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000432 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000433 if hasattr(self, methodname):
434 return getattr(self, methodname)(x, level)
435 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000436
437 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000438 test = cram(x, self.maxstring)
439 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000440 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000441 # Backslashes are only literal in the string and are never
442 # needed to make any special characters, so show a raw string.
443 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000444 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000445 r'<font color="#c040c0">\1</font>',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000446 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000447
Skip Montanarodf708782002-03-07 22:58:02 +0000448 repr_str = repr_string
449
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000450 def repr_instance(self, x, level):
451 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000452 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000453 except:
454 return self.escape('<%s instance>' % x.__class__.__name__)
455
456 repr_unicode = repr_string
457
458class HTMLDoc(Doc):
459 """Formatter class for HTML documentation."""
460
461 # ------------------------------------------- HTML formatting utilities
462
463 _repr_instance = HTMLRepr()
464 repr = _repr_instance.repr
465 escape = _repr_instance.escape
466
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000467 def page(self, title, contents):
468 """Format an HTML page."""
Georg Brandl388faac2009-04-10 08:31:48 +0000469 return '''\
Georg Brandle6066942009-04-10 08:28:28 +0000470<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000471<html><head><title>Python: %s</title>
Georg Brandl388faac2009-04-10 08:31:48 +0000472<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000473</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000474%s
475</body></html>''' % (title, contents)
476
477 def heading(self, title, fgcol, bgcol, extras=''):
478 """Format a page heading."""
479 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000480<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000481<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000482<td valign=bottom>&nbsp;<br>
483<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000484><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000485><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000486 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
487
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000488 def section(self, title, fgcol, bgcol, contents, width=6,
489 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000490 """Format a section with a heading."""
491 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000492 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000493 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000494<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000495<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000496<td colspan=3 valign=bottom>&nbsp;<br>
497<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000498 ''' % (bgcol, fgcol, title)
499 if prelude:
500 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000501<tr bgcolor="%s"><td rowspan=2>%s</td>
502<td colspan=2>%s</td></tr>
503<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
504 else:
505 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000506<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000507
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000508 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000509
510 def bigsection(self, title, *args):
511 """Format a section with a big heading."""
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000512 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000513 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000514
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000515 def preformat(self, text):
516 """Format literal preformatted text."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000517 text = self.escape(text.expandtabs())
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000518 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
519 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000520
521 def multicolumn(self, list, format, cols=4):
522 """Format a list of items into a multi-column list."""
523 result = ''
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000524 rows = (len(list)+cols-1)//cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000525 for col in range(cols):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000526 result = result + '<td width="%d%%" valign=top>' % (100//cols)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000527 for i in range(rows*col, rows*col+rows):
528 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000529 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000530 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000531 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000532
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000533 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000534
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000535 def namelink(self, name, *dicts):
536 """Make a link for an identifier, given name-to-URL mappings."""
537 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000538 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000539 return '<a href="%s">%s</a>' % (dict[name], name)
540 return name
541
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000542 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000543 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000544 name, module = object.__name__, sys.modules.get(object.__module__)
545 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000546 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000547 module.__name__, name, classname(object, modname))
548 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000549
550 def modulelink(self, object):
551 """Make a link for a module."""
552 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
553
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000554 def modpkglink(self, modpkginfo):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000555 """Make a link for a module or package to display in an index."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000556 name, path, ispackage, shadowed = modpkginfo
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000557 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000558 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000559 if path:
560 url = '%s.%s.html' % (path, name)
561 else:
562 url = '%s.html' % name
563 if ispackage:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000564 text = '<strong>%s</strong>&nbsp;(package)' % name
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000565 else:
566 text = name
567 return '<a href="%s">%s</a>' % (url, text)
568
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000569 def filelink(self, url, path):
570 """Make a link to source file."""
571 return '<a href="file:%s">%s</a>' % (url, path)
572
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000573 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
574 """Mark up some plain text, given a context of symbols to look for.
575 Each context dictionary maps object names to anchor names."""
576 escape = escape or self.escape
577 results = []
578 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000579 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
580 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000581 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000582 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000583 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000584 match = pattern.search(text, here)
585 if not match: break
586 start, end = match.span()
587 results.append(escape(text[here:start]))
588
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000589 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000590 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000591 url = escape(all).replace('"', '&quot;')
592 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000593 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000594 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
595 results.append('<a href="%s">%s</a>' % (url, escape(all)))
596 elif pep:
Christian Heimes2202f872008-02-06 14:31:34 +0000597 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000598 results.append('<a href="%s">%s</a>' % (url, escape(all)))
Benjamin Petersoned1160b2014-06-07 16:44:00 -0700599 elif selfdot:
600 # Create a link for methods like 'self.method(...)'
601 # and use <strong> for attributes like 'self.attr'
602 if text[end:end+1] == '(':
603 results.append('self.' + self.namelink(name, methods))
604 else:
605 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000606 elif text[end:end+1] == '(':
607 results.append(self.namelink(name, methods, funcs, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000608 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000609 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000610 here = end
611 results.append(escape(text[here:]))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000612 return ''.join(results)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000613
614 # ---------------------------------------------- type-specific routines
615
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000616 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000617 """Produce HTML for a class tree as given by inspect.getclasstree()."""
618 result = ''
619 for entry in tree:
620 if type(entry) is type(()):
621 c, bases = entry
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000622 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000623 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000624 if bases and bases != (parent,):
625 parents = []
626 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000627 parents.append(self.classlink(base, modname))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000628 result = result + '(' + ', '.join(parents) + ')'
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000629 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000630 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000631 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000632 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000633 return '<dl>\n%s</dl>\n' % result
634
Tim Peters8dd7ade2001-10-18 19:56:17 +0000635 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000636 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000637 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000638 try:
639 all = object.__all__
640 except AttributeError:
641 all = None
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000642 parts = name.split('.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000643 links = []
644 for i in range(len(parts)-1):
645 links.append(
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000646 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000647 ('.'.join(parts[:i+1]), parts[i]))
648 linkedname = '.'.join(links + parts[-1:])
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000649 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000650 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000651 path = inspect.getabsfile(object)
Zachary Wareeb432142014-07-10 11:18:00 -0500652 url = urllib.parse.quote(path)
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000653 filelink = self.filelink(url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000654 except TypeError:
655 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000656 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000657 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000658 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000659 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000660 version = version[11:-1].strip()
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000661 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000662 if hasattr(object, '__date__'):
663 info.append(self.escape(str(object.__date__)))
664 if info:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000665 head = head + ' (%s)' % ', '.join(info)
Skip Montanaro4997a692003-09-10 16:47:51 +0000666 docloc = self.getdocloc(object)
667 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000668 docloc = '<br><a href="%(docloc)s">Module Reference</a>' % locals()
Skip Montanaro4997a692003-09-10 16:47:51 +0000669 else:
670 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000671 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000672 head, '#ffffff', '#7799ee',
673 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000674
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000675 modules = inspect.getmembers(object, inspect.ismodule)
676
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000677 classes, cdict = [], {}
678 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000679 # if __all__ exists, believe it. Otherwise use old heuristic.
680 if (all is not None or
681 (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700682 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000683 classes.append((key, value))
684 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000685 for key, value in classes:
686 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000687 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000688 module = sys.modules.get(modname)
689 if modname != name and module and hasattr(module, key):
690 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000691 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000692 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000693 funcs, fdict = [], {}
694 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000695 # if __all__ exists, believe it. Otherwise use old heuristic.
696 if (all is not None or
697 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700698 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000699 funcs.append((key, value))
700 fdict[key] = '#-' + key
701 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000702 data = []
703 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700704 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000705 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000706
707 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
708 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000709 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000710
711 if hasattr(object, '__path__'):
712 modpkgs = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000713 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
714 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000715 modpkgs.sort()
716 contents = self.multicolumn(modpkgs, self.modpkglink)
717 result = result + self.bigsection(
718 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000719 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000720 contents = self.multicolumn(
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000721 modules, lambda t: self.modulelink(t[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000722 result = result + self.bigsection(
Christian Heimes7131fd92008-02-19 14:21:46 +0000723 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000724
725 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000726 classlist = [value for (key, value) in classes]
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000727 contents = [
728 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000729 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000730 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000731 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000732 'Classes', '#ffffff', '#ee77aa', ' '.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000733 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000734 contents = []
735 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000736 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000737 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000738 'Functions', '#ffffff', '#eeaa77', ' '.join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000739 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000740 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000741 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000742 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000743 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000744 'Data', '#ffffff', '#55aa55', '<br>\n'.join(contents))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000745 if hasattr(object, '__author__'):
746 contents = self.markup(str(object.__author__), self.preformat)
747 result = result + self.bigsection(
748 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000749 if hasattr(object, '__credits__'):
750 contents = self.markup(str(object.__credits__), self.preformat)
751 result = result + self.bigsection(
752 'Credits', '#ffffff', '#7799ee', contents)
753
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000754 return result
755
Tim Peters8dd7ade2001-10-18 19:56:17 +0000756 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
757 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000758 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000759 realname = object.__name__
760 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000761 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000762
Tim Petersb47879b2001-09-24 04:47:19 +0000763 contents = []
764 push = contents.append
765
Tim Petersfa26f7c2001-09-24 08:05:11 +0000766 # Cute little class to pump out a horizontal rule between sections.
767 class HorizontalRule:
768 def __init__(self):
769 self.needone = 0
770 def maybe(self):
771 if self.needone:
772 push('<hr>\n')
773 self.needone = 1
774 hr = HorizontalRule()
775
Tim Petersc86f6ca2001-09-26 21:31:51 +0000776 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000777 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000778 if len(mro) > 2:
779 hr.maybe()
780 push('<dl><dt>Method resolution order:</dt>\n')
781 for base in mro:
782 push('<dd>%s</dd>\n' % self.classlink(base,
783 object.__module__))
784 push('</dl>\n')
785
Tim Petersb47879b2001-09-24 04:47:19 +0000786 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000787 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000788 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000789 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000790 push(msg)
791 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100792 try:
793 value = getattr(object, name)
794 except Exception:
795 # Some descriptors may meet a failure in their __get__.
796 # (bug #1785)
797 push(self._docdescriptor(name, value, mod))
798 else:
799 push(self.document(value, name, mod,
800 funcs, classes, mdict, object))
Tim Petersb47879b2001-09-24 04:47:19 +0000801 push('\n')
802 return attrs
803
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000804 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000805 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000806 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000807 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000808 push(msg)
809 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000810 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000811 return attrs
812
Tim Petersfa26f7c2001-09-24 08:05:11 +0000813 def spilldata(msg, attrs, predicate):
814 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000815 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000816 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000817 push(msg)
818 for name, kind, homecls, value in ok:
819 base = self.docother(getattr(object, name), name, mod)
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200820 if callable(value) or inspect.isdatadescriptor(value):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000821 doc = getattr(value, "__doc__", None)
822 else:
823 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000824 if doc is None:
825 push('<dl><dt>%s</dl>\n' % base)
826 else:
827 doc = self.markup(getdoc(value), self.preformat,
828 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000829 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000830 push('<dl><dt>%s%s</dl>\n' % (base, doc))
831 push('\n')
832 return attrs
833
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000834 attrs = [(name, kind, cls, value)
835 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -0700836 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000837
Tim Petersb47879b2001-09-24 04:47:19 +0000838 mdict = {}
839 for key, kind, homecls, value in attrs:
840 mdict[key] = anchor = '#' + name + '-' + key
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100841 try:
842 value = getattr(object, name)
843 except Exception:
844 # Some descriptors may meet a failure in their __get__.
845 # (bug #1785)
846 pass
Tim Petersb47879b2001-09-24 04:47:19 +0000847 try:
848 # The value may not be hashable (e.g., a data attr with
849 # a dict or list value).
850 mdict[value] = anchor
851 except TypeError:
852 pass
853
Tim Petersfa26f7c2001-09-24 08:05:11 +0000854 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000855 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000856 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000857 else:
858 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000859 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
860
Georg Brandl1a3284e2007-12-02 09:40:06 +0000861 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000862 attrs = inherited
863 continue
864 elif thisclass is object:
865 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000866 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000867 tag = 'inherited from %s' % self.classlink(thisclass,
868 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000869 tag += ':<br>\n'
870
871 # Sort attrs by name.
Raymond Hettingerd4cb56d2008-01-30 02:55:10 +0000872 attrs.sort(key=lambda t: t[0])
Tim Petersb47879b2001-09-24 04:47:19 +0000873
874 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000875 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000876 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000877 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000878 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000879 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000880 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000881 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
882 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000883 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000884 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000885 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000886 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000887
888 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000889
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000890 if name == realname:
891 title = '<a name="%s">class <strong>%s</strong></a>' % (
892 name, realname)
893 else:
894 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
895 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000896 if bases:
897 parents = []
898 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000899 parents.append(self.classlink(base, object.__module__))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000900 title = title + '(%s)' % ', '.join(parents)
Tim Peters2306d242001-09-25 03:18:32 +0000901 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000902 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000903
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000904 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000905
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000906 def formatvalue(self, object):
907 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000908 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000909
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000910 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000911 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000912 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000913 realname = object.__name__
914 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000915 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000916 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000917 skipdocs = 0
Larry Hastings24a882b2014-02-20 23:34:46 -0800918 if _is_bound_method(object):
Christian Heimesff737952007-11-27 10:40:20 +0000919 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000920 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000921 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000922 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000923 else:
Christian Heimesff737952007-11-27 10:40:20 +0000924 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000925 note = ' method of %s instance' % self.classlink(
Christian Heimesff737952007-11-27 10:40:20 +0000926 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000927 else:
928 note = ' unbound %s method' % self.classlink(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000929
930 if name == realname:
931 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
932 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000933 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000934 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000935 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000936 cl.__name__ + '-' + realname, realname)
937 skipdocs = 1
938 else:
939 reallink = realname
940 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
941 anchor, name, reallink)
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800942 argspec = None
Larry Hastings24a882b2014-02-20 23:34:46 -0800943 if inspect.isroutine(object):
Larry Hastings5c661892014-01-24 06:17:25 -0800944 try:
945 signature = inspect.signature(object)
946 except (ValueError, TypeError):
947 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800948 if signature:
949 argspec = str(signature)
950 if realname == '<lambda>':
951 title = '<strong>%s</strong> <em>lambda</em> ' % name
952 # XXX lambda's won't usually have func_annotations['return']
953 # since the syntax doesn't support but it is possible.
954 # So removing parentheses isn't truly safe.
955 argspec = argspec[1:-1] # remove parentheses
956 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +0000957 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000958
Serhiy Storchaka66dd4aa2014-11-17 23:48:02 +0200959 decl = title + self.escape(argspec) + (note and self.grey(
Tim Peters2306d242001-09-25 03:18:32 +0000960 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000961
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000962 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000963 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000964 else:
965 doc = self.markup(
966 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000967 doc = doc and '<dd><tt>%s</tt></dd>' % doc
968 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000969
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000970 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000971 results = []
972 push = results.append
973
974 if name:
975 push('<dl><dt><strong>%s</strong></dt>\n' % name)
976 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000977 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000978 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000979 push('</dl>\n')
980
981 return ''.join(results)
982
983 def docproperty(self, object, name=None, mod=None, cl=None):
984 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000985 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000986
Tim Peters8dd7ade2001-10-18 19:56:17 +0000987 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000988 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000989 lhs = name and '<strong>%s</strong> = ' % name or ''
990 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000991
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000992 def docdata(self, object, name=None, mod=None, cl=None):
993 """Produce html documentation for a data descriptor."""
994 return self._docdescriptor(name, object, mod)
995
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000996 def index(self, dir, shadowed=None):
997 """Generate an HTML index for a directory of modules."""
998 modpkgs = []
999 if shadowed is None: shadowed = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001000 for importer, name, ispkg in pkgutil.iter_modules([dir]):
Victor Stinner4d652242011-04-12 23:41:50 +02001001 if any((0xD800 <= ord(ch) <= 0xDFFF) for ch in name):
1002 # ignore a module if its name contains a surrogate character
1003 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001004 modpkgs.append((name, '', ispkg, name in shadowed))
1005 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001006
1007 modpkgs.sort()
1008 contents = self.multicolumn(modpkgs, self.modpkglink)
1009 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
1010
1011# -------------------------------------------- text documentation generator
1012
1013class TextRepr(Repr):
1014 """Class for safely making a text representation of a Python object."""
1015 def __init__(self):
1016 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001017 self.maxlist = self.maxtuple = 20
1018 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001019 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001020
1021 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001022 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001023 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001024 if hasattr(self, methodname):
1025 return getattr(self, methodname)(x, level)
1026 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001027
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001028 def repr_string(self, x, level):
1029 test = cram(x, self.maxstring)
1030 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001031 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001032 # Backslashes are only literal in the string and are never
1033 # needed to make any special characters, so show a raw string.
1034 return 'r' + testrepr[0] + test + testrepr[0]
1035 return testrepr
1036
Skip Montanarodf708782002-03-07 22:58:02 +00001037 repr_str = repr_string
1038
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001039 def repr_instance(self, x, level):
1040 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001041 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001042 except:
1043 return '<%s instance>' % x.__class__.__name__
1044
1045class TextDoc(Doc):
1046 """Formatter class for text documentation."""
1047
1048 # ------------------------------------------- text formatting utilities
1049
1050 _repr_instance = TextRepr()
1051 repr = _repr_instance.repr
1052
1053 def bold(self, text):
1054 """Format a string in bold by overstriking."""
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001055 return ''.join(ch + '\b' + ch for ch in text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001056
1057 def indent(self, text, prefix=' '):
1058 """Indent text by prepending a given prefix to each line."""
1059 if not text: return ''
Collin Winter72e110c2007-07-17 00:27:30 +00001060 lines = [prefix + line for line in text.split('\n')]
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001061 if lines: lines[-1] = lines[-1].rstrip()
1062 return '\n'.join(lines)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001063
1064 def section(self, title, contents):
1065 """Format a section with a given heading."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001066 clean_contents = self.indent(contents).rstrip()
1067 return self.bold(title) + '\n' + clean_contents + '\n\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001068
1069 # ---------------------------------------------- type-specific routines
1070
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001071 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001072 """Render in text a class tree as returned by inspect.getclasstree()."""
1073 result = ''
1074 for entry in tree:
1075 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001076 c, bases = entry
1077 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001078 if bases and bases != (parent,):
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001079 parents = (classname(c, modname) for c in bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001080 result = result + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001081 result = result + '\n'
1082 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001083 result = result + self.formattree(
1084 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001085 return result
1086
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001087 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001088 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001089 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001090 synop, desc = splitdoc(getdoc(object))
1091 result = self.section('NAME', name + (synop and ' - ' + synop))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001092 all = getattr(object, '__all__', None)
Skip Montanaro4997a692003-09-10 16:47:51 +00001093 docloc = self.getdocloc(object)
1094 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001095 result = result + self.section('MODULE REFERENCE', docloc + """
1096
Éric Araujo647ef8c2011-09-11 00:43:20 +02001097The following documentation is automatically generated from the Python
1098source files. It may be incomplete, incorrect or include features that
1099are considered implementation detail and may vary between Python
1100implementations. When in doubt, consult the module reference at the
1101location listed above.
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001102""")
Skip Montanaro4997a692003-09-10 16:47:51 +00001103
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001104 if desc:
1105 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001106
1107 classes = []
1108 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001109 # if __all__ exists, believe it. Otherwise use old heuristic.
1110 if (all is not None
1111 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001112 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001113 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001114 funcs = []
1115 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001116 # if __all__ exists, believe it. Otherwise use old heuristic.
1117 if (all is not None or
1118 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001119 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001120 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001121 data = []
1122 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001123 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001124 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001125
Christian Heimes1af737c2008-01-23 08:24:23 +00001126 modpkgs = []
1127 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001128 if hasattr(object, '__path__'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001129 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Christian Heimes1af737c2008-01-23 08:24:23 +00001130 modpkgs_names.add(modname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001131 if ispkg:
1132 modpkgs.append(modname + ' (package)')
1133 else:
1134 modpkgs.append(modname)
1135
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001136 modpkgs.sort()
1137 result = result + self.section(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001138 'PACKAGE CONTENTS', '\n'.join(modpkgs))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001139
Christian Heimes1af737c2008-01-23 08:24:23 +00001140 # Detect submodules as sometimes created by C extensions
1141 submodules = []
1142 for key, value in inspect.getmembers(object, inspect.ismodule):
1143 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1144 submodules.append(key)
1145 if submodules:
1146 submodules.sort()
1147 result = result + self.section(
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001148 'SUBMODULES', '\n'.join(submodules))
Christian Heimes1af737c2008-01-23 08:24:23 +00001149
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001150 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001151 classlist = [value for key, value in classes]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001152 contents = [self.formattree(
1153 inspect.getclasstree(classlist, 1), name)]
1154 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001155 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001156 result = result + self.section('CLASSES', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001157
1158 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001159 contents = []
1160 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001161 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001162 result = result + self.section('FUNCTIONS', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001163
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001164 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001165 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001166 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001167 contents.append(self.docother(value, key, name, maxlen=70))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001168 result = result + self.section('DATA', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001169
1170 if hasattr(object, '__version__'):
1171 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001172 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001173 version = version[11:-1].strip()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001174 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001175 if hasattr(object, '__date__'):
1176 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001177 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001178 result = result + self.section('AUTHOR', str(object.__author__))
1179 if hasattr(object, '__credits__'):
1180 result = result + self.section('CREDITS', str(object.__credits__))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001181 try:
1182 file = inspect.getabsfile(object)
1183 except TypeError:
1184 file = '(built-in)'
1185 result = result + self.section('FILE', file)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001186 return result
1187
Georg Brandl9bd45f992010-12-03 09:58:38 +00001188 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001189 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001190 realname = object.__name__
1191 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001192 bases = object.__bases__
1193
Tim Petersc86f6ca2001-09-26 21:31:51 +00001194 def makename(c, m=object.__module__):
1195 return classname(c, m)
1196
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001197 if name == realname:
1198 title = 'class ' + self.bold(realname)
1199 else:
1200 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001201 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001202 parents = map(makename, bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001203 title = title + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001204
1205 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001206 contents = doc and [doc + '\n'] or []
1207 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001208
Tim Petersc86f6ca2001-09-26 21:31:51 +00001209 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001210 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001211 if len(mro) > 2:
1212 push("Method resolution order:")
1213 for base in mro:
1214 push(' ' + makename(base))
1215 push('')
1216
Tim Petersf4aad8e2001-09-24 22:40:47 +00001217 # Cute little class to pump out a horizontal rule between sections.
1218 class HorizontalRule:
1219 def __init__(self):
1220 self.needone = 0
1221 def maybe(self):
1222 if self.needone:
1223 push('-' * 70)
1224 self.needone = 1
1225 hr = HorizontalRule()
1226
Tim Peters28355492001-09-23 21:29:55 +00001227 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001228 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001229 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001230 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001231 push(msg)
1232 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001233 try:
1234 value = getattr(object, name)
1235 except Exception:
1236 # Some descriptors may meet a failure in their __get__.
1237 # (bug #1785)
1238 push(self._docdescriptor(name, value, mod))
1239 else:
1240 push(self.document(value,
1241 name, mod, object))
Tim Peters28355492001-09-23 21:29:55 +00001242 return attrs
1243
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001244 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001245 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001246 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001247 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001248 push(msg)
1249 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001250 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001251 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001252
Tim Petersfa26f7c2001-09-24 08:05:11 +00001253 def spilldata(msg, attrs, predicate):
1254 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001255 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001256 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001257 push(msg)
1258 for name, kind, homecls, value in ok:
Florent Xicluna5d1155c2011-10-28 14:45:05 +02001259 if callable(value) or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001260 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001261 else:
1262 doc = None
Serhiy Storchaka056eb022014-02-19 23:05:12 +02001263 try:
1264 obj = getattr(object, name)
1265 except AttributeError:
1266 obj = homecls.__dict__[name]
1267 push(self.docother(obj, name, mod, maxlen=70, doc=doc) +
1268 '\n')
Tim Peters28355492001-09-23 21:29:55 +00001269 return attrs
1270
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001271 attrs = [(name, kind, cls, value)
1272 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -07001273 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001274
Tim Petersfa26f7c2001-09-24 08:05:11 +00001275 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001276 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001277 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001278 else:
1279 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001280 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1281
Georg Brandl1a3284e2007-12-02 09:40:06 +00001282 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001283 attrs = inherited
1284 continue
1285 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001286 tag = "defined here"
1287 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001288 tag = "inherited from %s" % classname(thisclass,
1289 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001290 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001291 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001292
1293 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001294 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001295 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001296 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001297 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001298 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001299 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001300 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1301 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001302 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1303 lambda t: t[1] == 'data')
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001304
Tim Peters28355492001-09-23 21:29:55 +00001305 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001306 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001307
1308 contents = '\n'.join(contents)
1309 if not contents:
1310 return title + '\n'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001311 return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001312
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001313 def formatvalue(self, object):
1314 """Format an argument default value as text."""
1315 return '=' + self.repr(object)
1316
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001317 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001318 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001319 realname = object.__name__
1320 name = name or realname
1321 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001322 skipdocs = 0
Larry Hastings24a882b2014-02-20 23:34:46 -08001323 if _is_bound_method(object):
Christian Heimesff737952007-11-27 10:40:20 +00001324 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001325 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001326 if imclass is not cl:
1327 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001328 else:
Christian Heimesff737952007-11-27 10:40:20 +00001329 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001330 note = ' method of %s instance' % classname(
Christian Heimesff737952007-11-27 10:40:20 +00001331 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001332 else:
1333 note = ' unbound %s method' % classname(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001334
1335 if name == realname:
1336 title = self.bold(realname)
1337 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001338 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001339 cl.__dict__[realname] is object):
1340 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001341 title = self.bold(name) + ' = ' + realname
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001342 argspec = None
Larry Hastings5c661892014-01-24 06:17:25 -08001343
1344 if inspect.isroutine(object):
1345 try:
1346 signature = inspect.signature(object)
1347 except (ValueError, TypeError):
1348 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001349 if signature:
1350 argspec = str(signature)
1351 if realname == '<lambda>':
1352 title = self.bold(name) + ' lambda '
1353 # XXX lambda's won't usually have func_annotations['return']
1354 # since the syntax doesn't support but it is possible.
1355 # So removing parentheses isn't truly safe.
1356 argspec = argspec[1:-1] # remove parentheses
1357 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +00001358 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001359 decl = title + argspec + note
1360
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001361 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001362 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001363 else:
1364 doc = getdoc(object) or ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001365 return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001366
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001367 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001368 results = []
1369 push = results.append
1370
1371 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001372 push(self.bold(name))
1373 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001374 doc = getdoc(value) or ''
1375 if doc:
1376 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001377 push('\n')
1378 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001379
1380 def docproperty(self, object, name=None, mod=None, cl=None):
1381 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001382 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001383
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001384 def docdata(self, object, name=None, mod=None, cl=None):
1385 """Produce text documentation for a data descriptor."""
1386 return self._docdescriptor(name, object, mod)
1387
Georg Brandl8b813db2005-10-01 16:32:31 +00001388 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001389 """Produce text documentation for a data object."""
1390 repr = self.repr(object)
1391 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001392 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001393 chop = maxlen - len(line)
1394 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001395 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001396 if doc is not None:
1397 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001398 return line
1399
Georg Brandld80d5f42010-12-03 07:47:22 +00001400class _PlainTextDoc(TextDoc):
1401 """Subclass of TextDoc which overrides string styling"""
1402 def bold(self, text):
1403 return text
1404
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001405# --------------------------------------------------------- user interfaces
1406
1407def pager(text):
1408 """The first time this is called, determine what kind of pager to use."""
1409 global pager
1410 pager = getpager()
1411 pager(text)
1412
1413def getpager():
1414 """Decide what method to use for paging through text."""
Benjamin Peterson159824e2014-06-07 20:14:26 -07001415 if not hasattr(sys.stdin, "isatty"):
1416 return plainpager
Guido van Rossuma01a8b62007-05-27 09:20:14 +00001417 if not hasattr(sys.stdout, "isatty"):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001418 return plainpager
1419 if not sys.stdin.isatty() or not sys.stdout.isatty():
1420 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001421 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001422 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001423 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001424 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001425 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001426 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001427 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001428 if os.environ.get('TERM') in ('dumb', 'emacs'):
1429 return plainpager
Jesus Cea4791a242012-10-05 03:15:39 +02001430 if sys.platform == 'win32':
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001431 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001432 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001433 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001434
1435 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001436 (fd, filename) = tempfile.mkstemp()
1437 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001438 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001439 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001440 return lambda text: pipepager(text, 'more')
1441 else:
1442 return ttypager
1443 finally:
1444 os.unlink(filename)
1445
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001446def plain(text):
1447 """Remove boldface formatting from text."""
1448 return re.sub('.\b', '', text)
1449
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001450def pipepager(text, cmd):
1451 """Page through text by feeding it to another program."""
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001452 import subprocess
1453 proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001454 try:
R David Murray1058cda2015-03-29 15:15:40 -04001455 with io.TextIOWrapper(proc.stdin, errors='backslashreplace') as pipe:
R David Murraye7f5e142015-03-30 10:14:47 -04001456 try:
1457 pipe.write(text)
1458 except KeyboardInterrupt:
1459 # We've hereby abandoned whatever text hasn't been written,
1460 # but the pager is still in control of the terminal.
1461 pass
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001462 except OSError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001463 pass # Ignore broken pipes caused by quitting the pager program.
R David Murray1058cda2015-03-29 15:15:40 -04001464 while True:
1465 try:
1466 proc.wait()
1467 break
1468 except KeyboardInterrupt:
1469 # Ignore ctl-c like the pager itself does. Otherwise the pager is
1470 # left running and the terminal is in raw mode and unusable.
1471 pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001472
1473def tempfilepager(text, cmd):
1474 """Page through text by invoking a program on a temporary file."""
1475 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001476 filename = tempfile.mktemp()
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001477 with open(filename, 'w', errors='backslashreplace') as file:
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +01001478 file.write(text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001479 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001480 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001481 finally:
1482 os.unlink(filename)
1483
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001484def _escape_stdout(text):
1485 # Escape non-encodable characters to avoid encoding errors later
1486 encoding = getattr(sys.stdout, 'encoding', None) or 'utf-8'
1487 return text.encode(encoding, 'backslashreplace').decode(encoding)
1488
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001489def ttypager(text):
1490 """Page through text on a text terminal."""
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001491 lines = plain(_escape_stdout(text)).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001492 try:
1493 import tty
1494 fd = sys.stdin.fileno()
1495 old = tty.tcgetattr(fd)
1496 tty.setcbreak(fd)
1497 getchar = lambda: sys.stdin.read(1)
Serhiy Storchakaab5e9b92014-11-28 00:09:29 +02001498 except (ImportError, AttributeError, io.UnsupportedOperation):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001499 tty = None
1500 getchar = lambda: sys.stdin.readline()[:-1][:1]
1501
1502 try:
Serhiy Storchakaab5e9b92014-11-28 00:09:29 +02001503 try:
1504 h = int(os.environ.get('LINES', 0))
1505 except ValueError:
1506 h = 0
1507 if h <= 1:
1508 h = 25
1509 r = inc = h - 1
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001510 sys.stdout.write('\n'.join(lines[:inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001511 while lines[r:]:
1512 sys.stdout.write('-- more --')
1513 sys.stdout.flush()
1514 c = getchar()
1515
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001516 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001517 sys.stdout.write('\r \r')
1518 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001519 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001520 sys.stdout.write('\r \r' + lines[r] + '\n')
1521 r = r + 1
1522 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001523 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001524 r = r - inc - inc
1525 if r < 0: r = 0
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001526 sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001527 r = r + inc
1528
1529 finally:
1530 if tty:
1531 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1532
1533def plainpager(text):
1534 """Simply print unformatted text. This is the ultimate fallback."""
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001535 sys.stdout.write(plain(_escape_stdout(text)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001536
1537def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001538 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001539 if inspect.ismodule(thing):
1540 if thing.__name__ in sys.builtin_module_names:
1541 return 'built-in module ' + thing.__name__
1542 if hasattr(thing, '__path__'):
1543 return 'package ' + thing.__name__
1544 else:
1545 return 'module ' + thing.__name__
1546 if inspect.isbuiltin(thing):
1547 return 'built-in function ' + thing.__name__
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001548 if inspect.isgetsetdescriptor(thing):
1549 return 'getset descriptor %s.%s.%s' % (
1550 thing.__objclass__.__module__, thing.__objclass__.__name__,
1551 thing.__name__)
1552 if inspect.ismemberdescriptor(thing):
1553 return 'member descriptor %s.%s.%s' % (
1554 thing.__objclass__.__module__, thing.__objclass__.__name__,
1555 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001556 if inspect.isclass(thing):
1557 return 'class ' + thing.__name__
1558 if inspect.isfunction(thing):
1559 return 'function ' + thing.__name__
1560 if inspect.ismethod(thing):
1561 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001562 return type(thing).__name__
1563
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001564def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001565 """Locate an object by name or dotted path, importing as necessary."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001566 parts = [part for part in path.split('.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001567 module, n = None, 0
1568 while n < len(parts):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001569 nextmodule = safeimport('.'.join(parts[:n+1]), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001570 if nextmodule: module, n = nextmodule, n + 1
1571 else: break
1572 if module:
1573 object = module
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001574 else:
Éric Araujoe64e51b2011-07-29 17:03:55 +02001575 object = builtins
1576 for part in parts[n:]:
1577 try:
1578 object = getattr(object, part)
1579 except AttributeError:
1580 return None
1581 return object
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001582
1583# --------------------------------------- interactive interpreter interface
1584
1585text = TextDoc()
Georg Brandld80d5f42010-12-03 07:47:22 +00001586plaintext = _PlainTextDoc()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001587html = HTMLDoc()
1588
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001589def resolve(thing, forceload=0):
1590 """Given an object or a path to an object, get the object and its name."""
1591 if isinstance(thing, str):
1592 object = locate(thing, forceload)
Serhiy Storchakab6076fb2015-04-21 21:09:48 +03001593 if object is None:
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001594 raise ImportError('''\
1595No Python documentation found for %r.
1596Use help() to get the interactive help utility.
1597Use help(str) for help on the str class.''' % thing)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001598 return object, thing
1599 else:
R David Murrayc43125a2012-04-23 13:23:57 -04001600 name = getattr(thing, '__name__', None)
1601 return thing, name if isinstance(name, str) else None
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001602
Georg Brandld80d5f42010-12-03 07:47:22 +00001603def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
1604 renderer=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001605 """Render text documentation, given an object or a path to an object."""
Georg Brandld80d5f42010-12-03 07:47:22 +00001606 if renderer is None:
1607 renderer = text
Guido van Rossumd8faa362007-04-27 19:54:29 +00001608 object, name = resolve(thing, forceload)
1609 desc = describe(object)
1610 module = inspect.getmodule(object)
1611 if name and '.' in name:
1612 desc += ' in ' + name[:name.rfind('.')]
1613 elif module and module is not object:
1614 desc += ' in module ' + module.__name__
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001615
1616 if not (inspect.ismodule(object) or
Guido van Rossumd8faa362007-04-27 19:54:29 +00001617 inspect.isclass(object) or
1618 inspect.isroutine(object) or
1619 inspect.isgetsetdescriptor(object) or
1620 inspect.ismemberdescriptor(object) or
1621 isinstance(object, property)):
1622 # If the passed object is a piece of data or an instance,
1623 # document its available methods instead of its value.
1624 object = type(object)
1625 desc += ' object'
Georg Brandld80d5f42010-12-03 07:47:22 +00001626 return title % desc + '\n\n' + renderer.document(object, name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001627
Georg Brandld80d5f42010-12-03 07:47:22 +00001628def doc(thing, title='Python Library Documentation: %s', forceload=0,
1629 output=None):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001630 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001631 try:
Georg Brandld80d5f42010-12-03 07:47:22 +00001632 if output is None:
1633 pager(render_doc(thing, title, forceload))
1634 else:
1635 output.write(render_doc(thing, title, forceload, plaintext))
Guido van Rossumb940e112007-01-10 16:19:56 +00001636 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001637 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001638
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001639def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001640 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001641 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001642 object, name = resolve(thing, forceload)
1643 page = html.page(describe(object), html.document(object, name))
Serhiy Storchaka46ba6c82015-04-04 11:01:02 +03001644 with open(name + '.html', 'w', encoding='utf-8') as file:
1645 file.write(page)
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001646 print('wrote', name + '.html')
Guido van Rossumb940e112007-01-10 16:19:56 +00001647 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001648 print(value)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001649
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001650def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001651 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001652 if done is None: done = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001653 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1654 writedoc(modname)
1655 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001656
1657class Helper:
Georg Brandl6b38daa2008-06-01 21:05:17 +00001658
1659 # These dictionaries map a topic name to either an alias, or a tuple
1660 # (label, seealso-items). The "label" is the label of the corresponding
1661 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl5617db82009-04-27 16:28:57 +00001662 # in pydoc_data/topics.py.
Georg Brandl6b38daa2008-06-01 21:05:17 +00001663 #
1664 # CAUTION: if you change one of these dictionaries, be sure to adapt the
Georg Brandl61bd1dc2014-09-30 22:56:38 +02001665 # list of needed labels in Doc/tools/pyspecific.py and
Georg Brandl5617db82009-04-27 16:28:57 +00001666 # regenerate the pydoc_data/topics.py file by running
Georg Brandl6b38daa2008-06-01 21:05:17 +00001667 # make pydoc-topics
1668 # in Doc/ and copying the output file into the Lib/ directory.
1669
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001670 keywords = {
Ezio Melottib185a042011-04-28 07:42:55 +03001671 'False': '',
1672 'None': '',
1673 'True': '',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001674 'and': 'BOOLEAN',
Guido van Rossumd8faa362007-04-27 19:54:29 +00001675 'as': 'with',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001676 'assert': ('assert', ''),
1677 'break': ('break', 'while for'),
1678 'class': ('class', 'CLASSES SPECIALMETHODS'),
1679 'continue': ('continue', 'while for'),
1680 'def': ('function', ''),
1681 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001682 'elif': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001683 'else': ('else', 'while for'),
Georg Brandl0d855392008-08-30 19:53:05 +00001684 'except': 'try',
1685 'finally': 'try',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001686 'for': ('for', 'break continue while'),
Georg Brandl0d855392008-08-30 19:53:05 +00001687 'from': 'import',
Georg Brandl74abf6f2010-11-20 19:54:36 +00001688 'global': ('global', 'nonlocal NAMESPACES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001689 'if': ('if', 'TRUTHVALUE'),
1690 'import': ('import', 'MODULES'),
Georg Brandl395ed242009-09-04 08:07:32 +00001691 'in': ('in', 'SEQUENCEMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001692 'is': 'COMPARISON',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001693 'lambda': ('lambda', 'FUNCTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001694 'nonlocal': ('nonlocal', 'global NAMESPACES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001695 'not': 'BOOLEAN',
1696 'or': 'BOOLEAN',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001697 'pass': ('pass', ''),
1698 'raise': ('raise', 'EXCEPTIONS'),
1699 'return': ('return', 'FUNCTIONS'),
1700 'try': ('try', 'EXCEPTIONS'),
1701 'while': ('while', 'break continue if TRUTHVALUE'),
1702 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1703 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001704 }
Georg Brandldb7b6b92009-01-01 15:53:14 +00001705 # Either add symbols to this dictionary or to the symbols dictionary
1706 # directly: Whichever is easier. They are merged later.
1707 _symbols_inverse = {
1708 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'),
1709 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1710 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1711 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1712 'UNARY' : ('-', '~'),
1713 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1714 '^=', '<<=', '>>=', '**=', '//='),
1715 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1716 'COMPLEX' : ('j', 'J')
1717 }
1718 symbols = {
1719 '%': 'OPERATORS FORMATTING',
1720 '**': 'POWER',
1721 ',': 'TUPLES LISTS FUNCTIONS',
1722 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1723 '...': 'ELLIPSIS',
1724 ':': 'SLICINGS DICTIONARYLITERALS',
1725 '@': 'def class',
1726 '\\': 'STRINGS',
1727 '_': 'PRIVATENAMES',
1728 '__': 'PRIVATENAMES SPECIALMETHODS',
1729 '`': 'BACKQUOTES',
1730 '(': 'TUPLES FUNCTIONS CALLS',
1731 ')': 'TUPLES FUNCTIONS CALLS',
1732 '[': 'LISTS SUBSCRIPTS SLICINGS',
1733 ']': 'LISTS SUBSCRIPTS SLICINGS'
1734 }
1735 for topic, symbols_ in _symbols_inverse.items():
1736 for symbol in symbols_:
1737 topics = symbols.get(symbol, topic)
1738 if topic not in topics:
1739 topics = topics + ' ' + topic
1740 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001741
1742 topics = {
Georg Brandl6b38daa2008-06-01 21:05:17 +00001743 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1744 'FUNCTIONS CLASSES MODULES FILES inspect'),
1745 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS '
1746 'FORMATTING TYPES'),
1747 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1748 'FORMATTING': ('formatstrings', 'OPERATORS'),
1749 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1750 'FORMATTING TYPES'),
1751 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1752 'INTEGER': ('integers', 'int range'),
1753 'FLOAT': ('floating', 'float math'),
1754 'COMPLEX': ('imaginary', 'complex cmath'),
1755 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING range LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001756 'MAPPINGS': 'DICTIONARIES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001757 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1758 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1759 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1760 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001761 'FRAMEOBJECTS': 'TYPES',
1762 'TRACEBACKS': 'TYPES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001763 'NONE': ('bltin-null-object', ''),
1764 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001765 'SPECIALATTRIBUTES': ('specialattrs', ''),
1766 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1767 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001768 'PACKAGES': 'import',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001769 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1770 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1771 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1772 'LISTS DICTIONARIES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001773 'OPERATORS': 'EXPRESSIONS',
1774 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001775 'OBJECTS': ('objects', 'TYPES'),
1776 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
Georg Brandl395ed242009-09-04 08:07:32 +00001777 'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS '
1778 'NUMBERMETHODS CLASSES'),
Mark Dickinsona56c4672009-01-27 18:17:45 +00001779 'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001780 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1781 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001782 'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS '
Georg Brandl6b38daa2008-06-01 21:05:17 +00001783 'SPECIALMETHODS'),
1784 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1785 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1786 'SPECIALMETHODS'),
1787 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001788 'NAMESPACES': ('naming', 'global nonlocal ASSIGNMENT DELETION DYNAMICFEATURES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001789 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001790 'SCOPING': 'NAMESPACES',
1791 'FRAMES': 'NAMESPACES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001792 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1793 'CONVERSIONS': ('conversions', ''),
1794 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1795 'SPECIALIDENTIFIERS': ('id-classes', ''),
1796 'PRIVATENAMES': ('atom-identifiers', ''),
1797 'LITERALS': ('atom-literals', 'STRINGS NUMBERS TUPLELITERALS '
1798 'LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001799 'TUPLES': 'SEQUENCES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001800 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1801 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1802 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1803 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1804 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1805 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001806 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'),
1807 'SLICINGS': ('slicings', 'SEQUENCEMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001808 'CALLS': ('calls', 'EXPRESSIONS'),
1809 'POWER': ('power', 'EXPRESSIONS'),
1810 'UNARY': ('unary', 'EXPRESSIONS'),
1811 'BINARY': ('binary', 'EXPRESSIONS'),
1812 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1813 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1814 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1815 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001816 'ASSERTION': 'assert',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001817 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1818 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001819 'DELETION': 'del',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001820 'RETURNING': 'return',
1821 'IMPORTING': 'import',
1822 'CONDITIONAL': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001823 'LOOPING': ('compound', 'for while break continue'),
1824 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1825 'DEBUGGING': ('debugger', 'pdb'),
1826 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001827 }
1828
Georg Brandl78aa3962010-07-31 21:51:48 +00001829 def __init__(self, input=None, output=None):
1830 self._input = input
1831 self._output = output
1832
Georg Brandl76ae3972010-08-01 06:32:55 +00001833 input = property(lambda self: self._input or sys.stdin)
1834 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001835
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001836 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001837 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001838 self()
1839 return ''
Serhiy Storchaka465e60e2014-07-25 23:36:00 +03001840 return '<%s.%s instance>' % (self.__class__.__module__,
1841 self.__class__.__qualname__)
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001842
Alexander Belopolsky2e733c92010-07-04 17:00:20 +00001843 _GoInteractive = object()
1844 def __call__(self, request=_GoInteractive):
1845 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001846 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001847 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001848 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001849 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001850 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001851You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001852If you want to ask for help on a particular object directly from the
1853interpreter, you can type "help(object)". Executing "help('string')"
1854has the same effect as typing a particular string at the help> prompt.
1855''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001856
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001857 def interact(self):
1858 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001859 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001860 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001861 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001862 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001863 except (KeyboardInterrupt, EOFError):
1864 break
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001865 request = replace(request, '"', '', "'", '').strip()
1866 if request.lower() in ('q', 'quit'): break
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001867 if request == 'help':
1868 self.intro()
1869 else:
1870 self.help(request)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001871
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001872 def getline(self, prompt):
Guido van Rossum7c086c02008-01-02 03:52:38 +00001873 """Read one line, using input() when appropriate."""
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001874 if self.input is sys.stdin:
Guido van Rossum7c086c02008-01-02 03:52:38 +00001875 return input(prompt)
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001876 else:
1877 self.output.write(prompt)
1878 self.output.flush()
1879 return self.input.readline()
1880
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001881 def help(self, request):
1882 if type(request) is type(''):
R. David Murray1f1b9d32009-05-27 20:56:59 +00001883 request = request.strip()
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001884 if request == 'keywords': self.listkeywords()
Georg Brandldb7b6b92009-01-01 15:53:14 +00001885 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001886 elif request == 'topics': self.listtopics()
1887 elif request == 'modules': self.listmodules()
1888 elif request[:8] == 'modules ':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001889 self.listmodules(request.split()[1])
Georg Brandldb7b6b92009-01-01 15:53:14 +00001890 elif request in self.symbols: self.showsymbol(request)
Ezio Melottib185a042011-04-28 07:42:55 +03001891 elif request in ['True', 'False', 'None']:
1892 # special case these keywords since they are objects too
1893 doc(eval(request), 'Help on %s:')
Raymond Hettinger54f02222002-06-01 14:18:47 +00001894 elif request in self.keywords: self.showtopic(request)
1895 elif request in self.topics: self.showtopic(request)
Georg Brandld80d5f42010-12-03 07:47:22 +00001896 elif request: doc(request, 'Help on %s:', output=self._output)
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001897 else: doc(str, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001898 elif isinstance(request, Helper): self()
Georg Brandld80d5f42010-12-03 07:47:22 +00001899 else: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001900 self.output.write('\n')
1901
1902 def intro(self):
1903 self.output.write('''
R David Murray3d050dd2014-04-19 12:59:30 -04001904Welcome to Python %s's help utility!
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001905
1906If this is your first time using Python, you should definitely check out
R David Murrayde0f6292012-03-31 12:06:35 -04001907the tutorial on the Internet at http://docs.python.org/%s/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001908
1909Enter the name of any module, keyword, or topic to get help on writing
1910Python programs and using Python modules. To quit this help utility and
1911return to the interpreter, just type "quit".
1912
Terry Jan Reedy34200572013-02-11 02:23:13 -05001913To get a list of available modules, keywords, symbols, or topics, type
1914"modules", "keywords", "symbols", or "topics". Each module also comes
1915with a one-line summary of what it does; to list the modules whose name
1916or summary contain a given string such as "spam", type "modules spam".
R David Murrayde0f6292012-03-31 12:06:35 -04001917''' % tuple([sys.version[:3]]*2))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001918
1919 def list(self, items, columns=4, width=80):
Guido van Rossum486364b2007-06-30 05:01:58 +00001920 items = list(sorted(items))
1921 colw = width // columns
1922 rows = (len(items) + columns - 1) // columns
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001923 for row in range(rows):
1924 for col in range(columns):
1925 i = col * rows + row
1926 if i < len(items):
1927 self.output.write(items[i])
1928 if col < columns - 1:
Guido van Rossum486364b2007-06-30 05:01:58 +00001929 self.output.write(' ' + ' ' * (colw - 1 - len(items[i])))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001930 self.output.write('\n')
1931
1932 def listkeywords(self):
1933 self.output.write('''
1934Here is a list of the Python keywords. Enter any keyword to get more help.
1935
1936''')
1937 self.list(self.keywords.keys())
1938
Georg Brandldb7b6b92009-01-01 15:53:14 +00001939 def listsymbols(self):
1940 self.output.write('''
1941Here is a list of the punctuation symbols which Python assigns special meaning
1942to. Enter any symbol to get more help.
1943
1944''')
1945 self.list(self.symbols.keys())
1946
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001947 def listtopics(self):
1948 self.output.write('''
1949Here is a list of available topics. Enter any topic name to get more help.
1950
1951''')
1952 self.list(self.topics.keys())
1953
Georg Brandldb7b6b92009-01-01 15:53:14 +00001954 def showtopic(self, topic, more_xrefs=''):
Georg Brandl6b38daa2008-06-01 21:05:17 +00001955 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001956 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04001957 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001958 self.output.write('''
Georg Brandl6b38daa2008-06-01 21:05:17 +00001959Sorry, topic and keyword documentation is not available because the
Georg Brandl5617db82009-04-27 16:28:57 +00001960module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001961''')
1962 return
1963 target = self.topics.get(topic, self.keywords.get(topic))
1964 if not target:
1965 self.output.write('no documentation found for %s\n' % repr(topic))
1966 return
1967 if type(target) is type(''):
Georg Brandldb7b6b92009-01-01 15:53:14 +00001968 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001969
Georg Brandl6b38daa2008-06-01 21:05:17 +00001970 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001971 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001972 doc = pydoc_data.topics.topics[label]
Georg Brandl6b38daa2008-06-01 21:05:17 +00001973 except KeyError:
1974 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001975 return
Georg Brandl6b38daa2008-06-01 21:05:17 +00001976 pager(doc.strip() + '\n')
Georg Brandldb7b6b92009-01-01 15:53:14 +00001977 if more_xrefs:
1978 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001979 if xrefs:
Brett Cannon1448ecf2013-10-04 11:38:59 -04001980 import textwrap
1981 text = 'Related help topics: ' + ', '.join(xrefs.split()) + '\n'
1982 wrapped_text = textwrap.wrap(text, 72)
1983 self.output.write('\n%s\n' % ''.join(wrapped_text))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001984
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001985 def _gettopic(self, topic, more_xrefs=''):
1986 """Return unbuffered tuple of (topic, xrefs).
1987
Georg Brandld2f38572011-01-30 08:37:19 +00001988 If an error occurs here, the exception is caught and displayed by
1989 the url handler.
1990
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001991 This function duplicates the showtopic method but returns its
1992 result directly so it can be formatted for display in an html page.
1993 """
1994 try:
1995 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04001996 except ImportError:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001997 return('''
1998Sorry, topic and keyword documentation is not available because the
1999module "pydoc_data.topics" could not be found.
2000''' , '')
2001 target = self.topics.get(topic, self.keywords.get(topic))
2002 if not target:
Georg Brandld2f38572011-01-30 08:37:19 +00002003 raise ValueError('could not find topic')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002004 if isinstance(target, str):
2005 return self._gettopic(target, more_xrefs)
2006 label, xrefs = target
Georg Brandld2f38572011-01-30 08:37:19 +00002007 doc = pydoc_data.topics.topics[label]
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002008 if more_xrefs:
2009 xrefs = (xrefs or '') + ' ' + more_xrefs
2010 return doc, xrefs
2011
Georg Brandldb7b6b92009-01-01 15:53:14 +00002012 def showsymbol(self, symbol):
2013 target = self.symbols[symbol]
2014 topic, _, xrefs = target.partition(' ')
2015 self.showtopic(topic, xrefs)
2016
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002017 def listmodules(self, key=''):
2018 if key:
2019 self.output.write('''
Terry Jan Reedy34200572013-02-11 02:23:13 -05002020Here is a list of modules whose name or summary contains '{}'.
2021If there are any, enter a module name to get more help.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002022
Terry Jan Reedy34200572013-02-11 02:23:13 -05002023'''.format(key))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002024 apropos(key)
2025 else:
2026 self.output.write('''
2027Please wait a moment while I gather a list of all available modules...
2028
2029''')
2030 modules = {}
2031 def callback(path, modname, desc, modules=modules):
2032 if modname and modname[-9:] == '.__init__':
2033 modname = modname[:-9] + ' (package)'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002034 if modname.find('.') < 0:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002035 modules[modname] = 1
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002036 def onerror(modname):
2037 callback(None, modname, None)
2038 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002039 self.list(modules.keys())
2040 self.output.write('''
2041Enter any module name to get more help. Or, type "modules spam" to search
Terry Jan Reedy34200572013-02-11 02:23:13 -05002042for modules whose name or summary contain the string "spam".
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002043''')
2044
Georg Brandl78aa3962010-07-31 21:51:48 +00002045help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002046
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002047class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002048 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002049
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002050 def run(self, callback, key=None, completer=None, onerror=None):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002051 if key: key = key.lower()
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002052 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002053 seen = {}
2054
2055 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002056 if modname != '__main__':
2057 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00002058 if key is None:
2059 callback(None, modname, '')
2060 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002061 name = __import__(modname).__doc__ or ''
2062 desc = name.split('\n')[0]
2063 name = modname + ' - ' + desc
2064 if name.lower().find(key) >= 0:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002065 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002066
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002067 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002068 if self.quit:
2069 break
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002070
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002071 if key is None:
2072 callback(None, modname, '')
2073 else:
Georg Brandl126c8792009-04-05 15:05:48 +00002074 try:
Eric Snow3a62d142014-01-06 20:42:59 -07002075 spec = pkgutil._get_spec(importer, modname)
Georg Brandl126c8792009-04-05 15:05:48 +00002076 except SyntaxError:
2077 # raised by tests for bad coding cookies or BOM
2078 continue
Eric Snow3a62d142014-01-06 20:42:59 -07002079 loader = spec.loader
Georg Brandl126c8792009-04-05 15:05:48 +00002080 if hasattr(loader, 'get_source'):
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002081 try:
2082 source = loader.get_source(modname)
Nick Coghlan2824cb52012-07-15 22:12:14 +10002083 except Exception:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002084 if onerror:
2085 onerror(modname)
2086 continue
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002087 desc = source_synopsis(io.StringIO(source)) or ''
Georg Brandl126c8792009-04-05 15:05:48 +00002088 if hasattr(loader, 'get_filename'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002089 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002090 else:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002091 path = None
2092 else:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002093 try:
Brett Cannon2a17bde2014-05-30 14:55:29 -04002094 module = importlib._bootstrap._load(spec)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002095 except ImportError:
2096 if onerror:
2097 onerror(modname)
2098 continue
Benjamin Peterson54237f92015-02-16 19:45:01 -05002099 desc = module.__doc__.splitlines()[0] if module.__doc__ else ''
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002100 path = getattr(module,'__file__',None)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002101 name = modname + ' - ' + desc
2102 if name.lower().find(key) >= 0:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002103 callback(path, modname, desc)
2104
2105 if completer:
2106 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002107
2108def apropos(key):
2109 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002110 def callback(path, modname, desc):
2111 if modname[-9:] == '.__init__':
2112 modname = modname[:-9] + ' (package)'
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002113 print(modname, desc and '- ' + desc)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002114 def onerror(modname):
2115 pass
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002116 with warnings.catch_warnings():
2117 warnings.filterwarnings('ignore') # ignore problems during import
2118 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002119
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002120# --------------------------------------- enhanced Web browser interface
2121
2122def _start_server(urlhandler, port):
2123 """Start an HTTP server thread on a specific port.
2124
2125 Start an HTML/text server thread, so HTML or text documents can be
2126 browsed dynamically and interactively with a Web browser. Example use:
2127
2128 >>> import time
2129 >>> import pydoc
2130
2131 Define a URL handler. To determine what the client is asking
2132 for, check the URL and content_type.
2133
2134 Then get or generate some text or HTML code and return it.
2135
2136 >>> def my_url_handler(url, content_type):
2137 ... text = 'the URL sent was: (%s, %s)' % (url, content_type)
2138 ... return text
2139
2140 Start server thread on port 0.
2141 If you use port 0, the server will pick a random port number.
2142 You can then use serverthread.port to get the port number.
2143
2144 >>> port = 0
2145 >>> serverthread = pydoc._start_server(my_url_handler, port)
2146
2147 Check that the server is really started. If it is, open browser
2148 and get first page. Use serverthread.url as the starting page.
2149
2150 >>> if serverthread.serving:
2151 ... import webbrowser
2152
2153 The next two lines are commented out so a browser doesn't open if
2154 doctest is run on this module.
2155
2156 #... webbrowser.open(serverthread.url)
2157 #True
2158
2159 Let the server do its thing. We just need to monitor its status.
2160 Use time.sleep so the loop doesn't hog the CPU.
2161
2162 >>> starttime = time.time()
2163 >>> timeout = 1 #seconds
2164
2165 This is a short timeout for testing purposes.
2166
2167 >>> while serverthread.serving:
2168 ... time.sleep(.01)
2169 ... if serverthread.serving and time.time() - starttime > timeout:
2170 ... serverthread.stop()
2171 ... break
2172
2173 Print any errors that may have occurred.
2174
2175 >>> print(serverthread.error)
2176 None
2177 """
2178 import http.server
2179 import email.message
2180 import select
2181 import threading
2182
2183 class DocHandler(http.server.BaseHTTPRequestHandler):
2184
2185 def do_GET(self):
2186 """Process a request from an HTML browser.
2187
2188 The URL received is in self.path.
2189 Get an HTML page from self.urlhandler and send it.
2190 """
2191 if self.path.endswith('.css'):
2192 content_type = 'text/css'
2193 else:
2194 content_type = 'text/html'
2195 self.send_response(200)
Georg Brandld2f38572011-01-30 08:37:19 +00002196 self.send_header('Content-Type', '%s; charset=UTF-8' % content_type)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002197 self.end_headers()
2198 self.wfile.write(self.urlhandler(
2199 self.path, content_type).encode('utf-8'))
2200
2201 def log_message(self, *args):
2202 # Don't log messages.
2203 pass
2204
2205 class DocServer(http.server.HTTPServer):
2206
2207 def __init__(self, port, callback):
Senthil Kumaran2a42a0b2014-09-17 13:17:58 +08002208 self.host = 'localhost'
2209 self.address = (self.host, port)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002210 self.callback = callback
2211 self.base.__init__(self, self.address, self.handler)
2212 self.quit = False
2213
2214 def serve_until_quit(self):
2215 while not self.quit:
2216 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2217 if rd:
2218 self.handle_request()
Victor Stinnera3abd1d2011-01-03 16:12:39 +00002219 self.server_close()
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002220
2221 def server_activate(self):
2222 self.base.server_activate(self)
2223 if self.callback:
2224 self.callback(self)
2225
2226 class ServerThread(threading.Thread):
2227
2228 def __init__(self, urlhandler, port):
2229 self.urlhandler = urlhandler
2230 self.port = int(port)
2231 threading.Thread.__init__(self)
2232 self.serving = False
2233 self.error = None
2234
2235 def run(self):
2236 """Start the server."""
2237 try:
2238 DocServer.base = http.server.HTTPServer
2239 DocServer.handler = DocHandler
2240 DocHandler.MessageClass = email.message.Message
2241 DocHandler.urlhandler = staticmethod(self.urlhandler)
2242 docsvr = DocServer(self.port, self.ready)
2243 self.docserver = docsvr
2244 docsvr.serve_until_quit()
2245 except Exception as e:
2246 self.error = e
2247
2248 def ready(self, server):
2249 self.serving = True
2250 self.host = server.host
2251 self.port = server.server_port
2252 self.url = 'http://%s:%d/' % (self.host, self.port)
2253
2254 def stop(self):
2255 """Stop the server and this thread nicely"""
2256 self.docserver.quit = True
2257 self.serving = False
2258 self.url = None
2259
2260 thread = ServerThread(urlhandler, port)
2261 thread.start()
2262 # Wait until thread.serving is True to make sure we are
2263 # really up before returning.
2264 while not thread.error and not thread.serving:
2265 time.sleep(.01)
2266 return thread
2267
2268
2269def _url_handler(url, content_type="text/html"):
2270 """The pydoc url handler for use with the pydoc server.
2271
2272 If the content_type is 'text/css', the _pydoc.css style
2273 sheet is read and returned if it exits.
2274
2275 If the content_type is 'text/html', then the result of
2276 get_html_page(url) is returned.
2277 """
2278 class _HTMLDoc(HTMLDoc):
2279
2280 def page(self, title, contents):
2281 """Format an HTML page."""
2282 css_path = "pydoc_data/_pydoc.css"
2283 css_link = (
2284 '<link rel="stylesheet" type="text/css" href="%s">' %
2285 css_path)
2286 return '''\
2287<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Georg Brandld2f38572011-01-30 08:37:19 +00002288<html><head><title>Pydoc: %s</title>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002289<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Georg Brandld2f38572011-01-30 08:37:19 +00002290%s</head><body bgcolor="#f0f0f8">%s<div style="clear:both;padding-top:.5em;">%s</div>
2291</body></html>''' % (title, css_link, html_navbar(), contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002292
2293 def filelink(self, url, path):
2294 return '<a href="getfile?key=%s">%s</a>' % (url, path)
2295
2296
2297 html = _HTMLDoc()
2298
2299 def html_navbar():
Georg Brandld2f38572011-01-30 08:37:19 +00002300 version = html.escape("%s [%s, %s]" % (platform.python_version(),
2301 platform.python_build()[0],
2302 platform.python_compiler()))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002303 return """
2304 <div style='float:left'>
Georg Brandld2f38572011-01-30 08:37:19 +00002305 Python %s<br>%s
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002306 </div>
2307 <div style='float:right'>
2308 <div style='text-align:center'>
2309 <a href="index.html">Module Index</a>
2310 : <a href="topics.html">Topics</a>
2311 : <a href="keywords.html">Keywords</a>
2312 </div>
2313 <div>
Georg Brandld2f38572011-01-30 08:37:19 +00002314 <form action="get" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002315 <input type=text name=key size=15>
2316 <input type=submit value="Get">
Georg Brandld2f38572011-01-30 08:37:19 +00002317 </form>&nbsp;
2318 <form action="search" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002319 <input type=text name=key size=15>
2320 <input type=submit value="Search">
2321 </form>
2322 </div>
2323 </div>
Georg Brandld2f38572011-01-30 08:37:19 +00002324 """ % (version, html.escape(platform.platform(terse=True)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002325
2326 def html_index():
2327 """Module Index page."""
2328
2329 def bltinlink(name):
2330 return '<a href="%s.html">%s</a>' % (name, name)
2331
2332 heading = html.heading(
2333 '<big><big><strong>Index of Modules</strong></big></big>',
2334 '#ffffff', '#7799ee')
2335 names = [name for name in sys.builtin_module_names
2336 if name != '__main__']
2337 contents = html.multicolumn(names, bltinlink)
2338 contents = [heading, '<p>' + html.bigsection(
2339 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2340
2341 seen = {}
2342 for dir in sys.path:
2343 contents.append(html.index(dir, seen))
2344
2345 contents.append(
2346 '<p align=right><font color="#909090" face="helvetica,'
2347 'arial"><strong>pydoc</strong> by Ka-Ping Yee'
2348 '&lt;ping@lfw.org&gt;</font>')
Nick Coghlanecace282010-12-03 16:08:46 +00002349 return 'Index of Modules', ''.join(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002350
2351 def html_search(key):
2352 """Search results page."""
2353 # scan for modules
2354 search_result = []
2355
2356 def callback(path, modname, desc):
2357 if modname[-9:] == '.__init__':
2358 modname = modname[:-9] + ' (package)'
2359 search_result.append((modname, desc and '- ' + desc))
2360
2361 with warnings.catch_warnings():
2362 warnings.filterwarnings('ignore') # ignore problems during import
Martin Panter9ad0aae2015-11-06 00:27:14 +00002363 def onerror(modname):
2364 pass
2365 ModuleScanner().run(callback, key, onerror=onerror)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002366
2367 # format page
2368 def bltinlink(name):
2369 return '<a href="%s.html">%s</a>' % (name, name)
2370
2371 results = []
2372 heading = html.heading(
2373 '<big><big><strong>Search Results</strong></big></big>',
2374 '#ffffff', '#7799ee')
2375 for name, desc in search_result:
2376 results.append(bltinlink(name) + desc)
2377 contents = heading + html.bigsection(
2378 'key = %s' % key, '#ffffff', '#ee77aa', '<br>'.join(results))
Nick Coghlanecace282010-12-03 16:08:46 +00002379 return 'Search Results', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002380
2381 def html_getfile(path):
2382 """Get and display a source file listing safely."""
Zachary Wareeb432142014-07-10 11:18:00 -05002383 path = urllib.parse.unquote(path)
Victor Stinner91e08772011-07-05 14:30:41 +02002384 with tokenize.open(path) as fp:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002385 lines = html.escape(fp.read())
2386 body = '<pre>%s</pre>' % lines
2387 heading = html.heading(
2388 '<big><big><strong>File Listing</strong></big></big>',
2389 '#ffffff', '#7799ee')
2390 contents = heading + html.bigsection(
2391 'File: %s' % path, '#ffffff', '#ee77aa', body)
Nick Coghlanecace282010-12-03 16:08:46 +00002392 return 'getfile %s' % path, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002393
2394 def html_topics():
2395 """Index of topic texts available."""
2396
2397 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002398 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002399
2400 heading = html.heading(
2401 '<big><big><strong>INDEX</strong></big></big>',
2402 '#ffffff', '#7799ee')
2403 names = sorted(Helper.topics.keys())
2404
2405 contents = html.multicolumn(names, bltinlink)
2406 contents = heading + html.bigsection(
2407 'Topics', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002408 return 'Topics', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002409
2410 def html_keywords():
2411 """Index of keywords."""
2412 heading = html.heading(
2413 '<big><big><strong>INDEX</strong></big></big>',
2414 '#ffffff', '#7799ee')
2415 names = sorted(Helper.keywords.keys())
2416
2417 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002418 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002419
2420 contents = html.multicolumn(names, bltinlink)
2421 contents = heading + html.bigsection(
2422 'Keywords', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002423 return 'Keywords', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002424
2425 def html_topicpage(topic):
2426 """Topic or keyword help page."""
2427 buf = io.StringIO()
2428 htmlhelp = Helper(buf, buf)
2429 contents, xrefs = htmlhelp._gettopic(topic)
2430 if topic in htmlhelp.keywords:
2431 title = 'KEYWORD'
2432 else:
2433 title = 'TOPIC'
2434 heading = html.heading(
2435 '<big><big><strong>%s</strong></big></big>' % title,
2436 '#ffffff', '#7799ee')
Georg Brandld2f38572011-01-30 08:37:19 +00002437 contents = '<pre>%s</pre>' % html.markup(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002438 contents = html.bigsection(topic , '#ffffff','#ee77aa', contents)
Georg Brandld2f38572011-01-30 08:37:19 +00002439 if xrefs:
2440 xrefs = sorted(xrefs.split())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002441
Georg Brandld2f38572011-01-30 08:37:19 +00002442 def bltinlink(name):
2443 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002444
Georg Brandld2f38572011-01-30 08:37:19 +00002445 xrefs = html.multicolumn(xrefs, bltinlink)
2446 xrefs = html.section('Related help topics: ',
2447 '#ffffff', '#ee77aa', xrefs)
Nick Coghlanecace282010-12-03 16:08:46 +00002448 return ('%s %s' % (title, topic),
2449 ''.join((heading, contents, xrefs)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002450
Georg Brandld2f38572011-01-30 08:37:19 +00002451 def html_getobj(url):
2452 obj = locate(url, forceload=1)
2453 if obj is None and url != 'None':
2454 raise ValueError('could not find object')
2455 title = describe(obj)
2456 content = html.document(obj, url)
2457 return title, content
2458
2459 def html_error(url, exc):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002460 heading = html.heading(
2461 '<big><big><strong>Error</strong></big></big>',
Georg Brandld2f38572011-01-30 08:37:19 +00002462 '#ffffff', '#7799ee')
2463 contents = '<br>'.join(html.escape(line) for line in
2464 format_exception_only(type(exc), exc))
2465 contents = heading + html.bigsection(url, '#ffffff', '#bb0000',
2466 contents)
2467 return "Error - %s" % url, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002468
2469 def get_html_page(url):
2470 """Generate an HTML page for url."""
Georg Brandld2f38572011-01-30 08:37:19 +00002471 complete_url = url
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002472 if url.endswith('.html'):
2473 url = url[:-5]
Georg Brandld2f38572011-01-30 08:37:19 +00002474 try:
2475 if url in ("", "index"):
2476 title, content = html_index()
2477 elif url == "topics":
2478 title, content = html_topics()
2479 elif url == "keywords":
2480 title, content = html_keywords()
2481 elif '=' in url:
2482 op, _, url = url.partition('=')
2483 if op == "search?key":
2484 title, content = html_search(url)
2485 elif op == "getfile?key":
2486 title, content = html_getfile(url)
2487 elif op == "topic?key":
2488 # try topics first, then objects.
2489 try:
2490 title, content = html_topicpage(url)
2491 except ValueError:
2492 title, content = html_getobj(url)
2493 elif op == "get?key":
2494 # try objects first, then topics.
2495 if url in ("", "index"):
2496 title, content = html_index()
2497 else:
2498 try:
2499 title, content = html_getobj(url)
2500 except ValueError:
2501 title, content = html_topicpage(url)
2502 else:
2503 raise ValueError('bad pydoc url')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002504 else:
Georg Brandld2f38572011-01-30 08:37:19 +00002505 title, content = html_getobj(url)
2506 except Exception as exc:
2507 # Catch any errors and display them in an error page.
2508 title, content = html_error(complete_url, exc)
2509 return html.page(title, content)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002510
2511 if url.startswith('/'):
2512 url = url[1:]
2513 if content_type == 'text/css':
2514 path_here = os.path.dirname(os.path.realpath(__file__))
Georg Brandld2f38572011-01-30 08:37:19 +00002515 css_path = os.path.join(path_here, url)
2516 with open(css_path) as fp:
2517 return ''.join(fp.readlines())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002518 elif content_type == 'text/html':
2519 return get_html_page(url)
Georg Brandld2f38572011-01-30 08:37:19 +00002520 # Errors outside the url handler are caught by the server.
2521 raise TypeError('unknown content type %r for url %s' % (content_type, url))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002522
2523
2524def browse(port=0, *, open_browser=True):
2525 """Start the enhanced pydoc Web server and open a Web browser.
2526
2527 Use port '0' to start the server on an arbitrary port.
2528 Set open_browser to False to suppress opening a browser.
2529 """
2530 import webbrowser
2531 serverthread = _start_server(_url_handler, port)
2532 if serverthread.error:
2533 print(serverthread.error)
2534 return
2535 if serverthread.serving:
2536 server_help_msg = 'Server commands: [b]rowser, [q]uit'
2537 if open_browser:
2538 webbrowser.open(serverthread.url)
2539 try:
2540 print('Server ready at', serverthread.url)
2541 print(server_help_msg)
2542 while serverthread.serving:
2543 cmd = input('server> ')
2544 cmd = cmd.lower()
2545 if cmd == 'q':
2546 break
2547 elif cmd == 'b':
2548 webbrowser.open(serverthread.url)
2549 else:
2550 print(server_help_msg)
2551 except (KeyboardInterrupt, EOFError):
2552 print()
2553 finally:
2554 if serverthread.serving:
2555 serverthread.stop()
2556 print('Server stopped')
2557
2558
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002559# -------------------------------------------------- command-line interface
2560
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002561def ispath(x):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002562 return isinstance(x, str) and x.find(os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002563
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002564def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002565 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002566 import getopt
Guido van Rossum756aa932007-04-07 03:04:01 +00002567 class BadUsage(Exception): pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002568
Nick Coghlan106274b2009-11-15 23:04:33 +00002569 # Scripts don't get the current directory in their path by default
2570 # unless they are run with the '-m' switch
2571 if '' not in sys.path:
2572 scriptdir = os.path.dirname(sys.argv[0])
2573 if scriptdir in sys.path:
2574 sys.path.remove(scriptdir)
2575 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002576
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002577 try:
Victor Stinner383c3fc2011-05-25 01:35:05 +02002578 opts, args = getopt.getopt(sys.argv[1:], 'bk:p:w')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002579 writing = False
2580 start_server = False
2581 open_browser = False
2582 port = None
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002583 for opt, val in opts:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002584 if opt == '-b':
2585 start_server = True
2586 open_browser = True
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002587 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002588 apropos(val)
2589 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002590 if opt == '-p':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002591 start_server = True
2592 port = val
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002593 if opt == '-w':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002594 writing = True
2595
Benjamin Petersonb29614e2012-10-09 11:16:03 -04002596 if start_server:
2597 if port is None:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002598 port = 0
2599 browse(port, open_browser=open_browser)
2600 return
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002601
2602 if not args: raise BadUsage
2603 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002604 if ispath(arg) and not os.path.exists(arg):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002605 print('file %r does not exist' % arg)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002606 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002607 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002608 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002609 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002610 if writing:
2611 if ispath(arg) and os.path.isdir(arg):
2612 writedocs(arg)
2613 else:
2614 writedoc(arg)
2615 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002616 help.help(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +00002617 except ErrorDuringImport as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002618 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002619
2620 except (getopt.error, BadUsage):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002621 cmd = os.path.splitext(os.path.basename(sys.argv[0]))[0]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002622 print("""pydoc - the Python documentation tool
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002623
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002624{cmd} <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002625 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002626 Python keyword, topic, function, module, or package, or a dotted
2627 reference to a class or function within a module or module in a
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002628 package. If <name> contains a '{sep}', it is used as the path to a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002629 Python source file to document. If name is 'keywords', 'topics',
2630 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002631
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002632{cmd} -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002633 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002634
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002635{cmd} -p <port>
2636 Start an HTTP server on the given port on the local machine. Port
2637 number 0 can be used to get an arbitrary unused port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002638
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002639{cmd} -b
2640 Start an HTTP server on an arbitrary unused port and open a Web browser
2641 to interactively browse documentation. The -p option can be used with
2642 the -b option to explicitly specify the server port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002643
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002644{cmd} -w <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002645 Write out the HTML documentation for a module to a file in the current
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002646 directory. If <name> contains a '{sep}', it is treated as a filename; if
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002647 it names a directory, documentation is written for all the contents.
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002648""".format(cmd=cmd, sep=os.sep))
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002649
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002650if __name__ == '__main__':
2651 cli()