blob: 3a461714821d38dbb9953711db70256c28f6b6c5 [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
Feanil Patel6a396c92017-09-14 17:54:09 -040019Run "pydoc -n <hostname>" to start an HTTP server with the given
20hostname (default: localhost) on the local machine.
21
Nick Coghlan7bb30b72010-12-03 09:29:11 +000022Run "pydoc -p <port>" to start an HTTP server on the given port on the
23local machine. Port number 0 can be used to get an arbitrary unused port.
24
25Run "pydoc -b" to start an HTTP server on an arbitrary unused port and
Feanil Patel6a396c92017-09-14 17:54:09 -040026open a Web browser to interactively browse documentation. Combine with
27the -n and -p options to control the hostname and port used.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000028
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000029Run "pydoc -w <name>" to write out the HTML documentation for a module
30to a file named "<name>.html".
Skip Montanaro4997a692003-09-10 16:47:51 +000031
32Module docs for core modules are assumed to be in
33
Martin Panter4f8aaf62016-06-12 04:24:06 +000034 https://docs.python.org/X.Y/library/
Skip Montanaro4997a692003-09-10 16:47:51 +000035
36This can be overridden by setting the PYTHONDOCS environment variable
37to a different URL or to a local directory containing the Library
38Reference Manual pages.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000039"""
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000040__all__ = ['help']
Ka-Ping Yeedd175342001-02-27 14:43:46 +000041__author__ = "Ka-Ping Yee <ping@lfw.org>"
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000042__date__ = "26 February 2001"
Jeremy Hylton3e0055f2005-10-20 19:59:25 +000043
Martin v. Löwis6fe8f192004-11-14 10:21:04 +000044__credits__ = """Guido van Rossum, for an excellent programming language.
Ka-Ping Yee5e2b1732001-02-27 23:35:09 +000045Tommy Burnette, the original creator of manpy.
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000046Paul Prescod, for all his work on onlinehelp.
47Richard Chamberlain, for the first implementation of textdoc.
Raymond Hettingered2dbe32005-01-01 07:51:01 +000048"""
Ka-Ping Yeedd175342001-02-27 14:43:46 +000049
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000050# Known bugs that can't be fixed here:
Brett Cannonf4ba4ec2013-06-15 14:25:04 -040051# - synopsis() cannot be prevented from clobbering existing
52# loaded modules.
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000053# - If the __file__ attribute on a module is a relative path and
54# the current directory is changed with os.chdir(), an incorrect
55# path will be displayed.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000056
Nick Coghlan7bb30b72010-12-03 09:29:11 +000057import builtins
Brett Cannond5e6f2e2013-06-11 17:09:36 -040058import importlib._bootstrap
Eric Snow32439d62015-05-02 19:15:18 -060059import importlib._bootstrap_external
Brett Cannoncb66eb02012-05-11 12:58:42 -040060import importlib.machinery
Brett Cannonf4ba4ec2013-06-15 14:25:04 -040061import importlib.util
Nick Coghlan7bb30b72010-12-03 09:29:11 +000062import inspect
Victor Stinnere6c910e2011-06-30 15:55:43 +020063import io
64import os
Nick Coghlan7bb30b72010-12-03 09:29:11 +000065import pkgutil
66import platform
67import re
Victor Stinnere6c910e2011-06-30 15:55:43 +020068import sys
Nick Coghlan7bb30b72010-12-03 09:29:11 +000069import time
Victor Stinnere6c910e2011-06-30 15:55:43 +020070import tokenize
Zachary Wareeb432142014-07-10 11:18:00 -050071import urllib.parse
Nick Coghlan7bb30b72010-12-03 09:29:11 +000072import warnings
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000073from collections import deque
Nick Coghlan7bb30b72010-12-03 09:29:11 +000074from reprlib import Repr
Victor Stinner7fa767e2014-03-20 09:16:38 +010075from traceback import format_exception_only
Nick Coghlan7bb30b72010-12-03 09:29:11 +000076
77
Ka-Ping Yeedd175342001-02-27 14:43:46 +000078# --------------------------------------------------------- common routines
79
Ka-Ping Yeedd175342001-02-27 14:43:46 +000080def pathdirs():
81 """Convert sys.path into a list of absolute, existing, unique paths."""
82 dirs = []
Ka-Ping Yee1d384632001-03-01 00:24:32 +000083 normdirs = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +000084 for dir in sys.path:
85 dir = os.path.abspath(dir or '.')
Ka-Ping Yee1d384632001-03-01 00:24:32 +000086 normdir = os.path.normcase(dir)
87 if normdir not in normdirs and os.path.isdir(dir):
Ka-Ping Yeedd175342001-02-27 14:43:46 +000088 dirs.append(dir)
Ka-Ping Yee1d384632001-03-01 00:24:32 +000089 normdirs.append(normdir)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000090 return dirs
91
92def getdoc(object):
93 """Get the doc string or comments for an object."""
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000094 result = inspect.getdoc(object) or inspect.getcomments(object)
Neal Norwitz9d72bb42007-04-17 08:48:32 +000095 return result and re.sub('^ *\n', '', result.rstrip()) or ''
Ka-Ping Yeedd175342001-02-27 14:43:46 +000096
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000097def splitdoc(doc):
98 """Split a doc string into a synopsis line (if any) and the rest."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +000099 lines = doc.strip().split('\n')
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000100 if len(lines) == 1:
101 return lines[0], ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000102 elif len(lines) >= 2 and not lines[1].rstrip():
103 return lines[0], '\n'.join(lines[2:])
104 return '', '\n'.join(lines)
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000105
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000106def classname(object, modname):
107 """Get a class name and qualify it with a module name if necessary."""
108 name = object.__name__
109 if object.__module__ != modname:
110 name = object.__module__ + '.' + name
111 return name
112
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000113def isdata(object):
Georg Brandl94432422005-07-22 21:52:25 +0000114 """Check if an object is of a type that probably means it's data."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000115 return not (inspect.ismodule(object) or inspect.isclass(object) or
116 inspect.isroutine(object) or inspect.isframe(object) or
117 inspect.istraceback(object) or inspect.iscode(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000118
119def replace(text, *pairs):
120 """Do a series of global replacements on a string."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000121 while pairs:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000122 text = pairs[1].join(text.split(pairs[0]))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000123 pairs = pairs[2:]
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000124 return text
125
126def cram(text, maxlen):
127 """Omit part of a string if needed to make it fit in a maximum length."""
128 if len(text) > maxlen:
Raymond Hettingerfca3bb62002-10-21 04:44:11 +0000129 pre = max(0, (maxlen-3)//2)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000130 post = max(0, maxlen-3-pre)
131 return text[:pre] + '...' + text[len(text)-post:]
132 return text
133
Brett Cannon84601f12004-06-19 01:22:48 +0000134_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000135def stripid(text):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000136 """Remove the hexadecimal id from a Python object representation."""
Brett Cannonc6c1f472004-06-19 01:02:51 +0000137 # The behaviour of %p is implementation-dependent in terms of case.
Ezio Melotti412c95a2010-02-16 23:31:04 +0000138 return _re_stripid.sub(r'\1', text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000139
Brett Cannonc6c1f472004-06-19 01:02:51 +0000140def _is_some_method(obj):
R David Murrayac0cea52013-03-19 02:47:44 -0400141 return (inspect.isfunction(obj) or
142 inspect.ismethod(obj) or
143 inspect.isbuiltin(obj) or
144 inspect.ismethoddescriptor(obj))
Tim Peters536d2262001-09-20 05:13:38 +0000145
Larry Hastings24a882b2014-02-20 23:34:46 -0800146def _is_bound_method(fn):
147 """
148 Returns True if fn is a bound method, regardless of whether
149 fn was implemented in Python or in C.
150 """
151 if inspect.ismethod(fn):
152 return True
153 if inspect.isbuiltin(fn):
154 self = getattr(fn, '__self__', None)
155 return not (inspect.ismodule(self) or (self is None))
156 return False
157
158
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000159def allmethods(cl):
160 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000161 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000162 methods[key] = 1
163 for base in cl.__bases__:
164 methods.update(allmethods(base)) # all your base are belong to us
165 for key in methods.keys():
166 methods[key] = getattr(cl, key)
167 return methods
168
Tim Petersfa26f7c2001-09-24 08:05:11 +0000169def _split_list(s, predicate):
170 """Split sequence s via predicate, and return pair ([true], [false]).
171
172 The return value is a 2-tuple of lists,
173 ([x for x in s if predicate(x)],
174 [x for x in s if not predicate(x)])
175 """
176
Tim Peters28355492001-09-23 21:29:55 +0000177 yes = []
178 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000179 for x in s:
180 if predicate(x):
181 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000182 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000183 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000184 return yes, no
185
Raymond Hettinger1103d052011-03-25 14:15:24 -0700186def visiblename(name, all=None, obj=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000187 """Decide whether to show documentation on a variable."""
Brett Cannond340b432012-08-06 17:19:22 -0400188 # Certain special names are redundant or internal.
Eric Snowb523f842013-11-22 09:05:39 -0700189 # XXX Remove __initializing__?
Brett Cannond340b432012-08-06 17:19:22 -0400190 if name in {'__author__', '__builtins__', '__cached__', '__credits__',
Eric Snowb523f842013-11-22 09:05:39 -0700191 '__date__', '__doc__', '__file__', '__spec__',
Brett Cannond340b432012-08-06 17:19:22 -0400192 '__loader__', '__module__', '__name__', '__package__',
193 '__path__', '__qualname__', '__slots__', '__version__'}:
Raymond Hettinger68272942011-03-18 02:22:15 -0700194 return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000195 # Private names are hidden, but special names are displayed.
196 if name.startswith('__') and name.endswith('__'): return 1
Raymond Hettinger1103d052011-03-25 14:15:24 -0700197 # Namedtuples have public fields and methods with a single leading underscore
198 if name.startswith('_') and hasattr(obj, '_fields'):
199 return True
Skip Montanaroa5616d22004-06-11 04:46:12 +0000200 if all is not None:
201 # only document that which the programmer exported in __all__
202 return name in all
203 else:
204 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000205
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000206def classify_class_attrs(object):
207 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000208 results = []
209 for (name, kind, cls, value) in inspect.classify_class_attrs(object):
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000210 if inspect.isdatadescriptor(value):
211 kind = 'data descriptor'
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000212 results.append((name, kind, cls, value))
213 return results
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000214
Raymond Hettinger95801bb2015-08-18 22:25:16 -0700215def sort_attributes(attrs, object):
216 'Sort the attrs list in-place by _fields and then alphabetically by name'
217 # This allows data descriptors to be ordered according
218 # to a _fields attribute if present.
219 fields = getattr(object, '_fields', [])
220 try:
221 field_order = {name : i-len(fields) for (i, name) in enumerate(fields)}
222 except TypeError:
223 field_order = {}
224 keyfunc = lambda attr: (field_order.get(attr[0], 0), attr[0])
225 attrs.sort(key=keyfunc)
226
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000227# ----------------------------------------------------- module manipulation
228
229def ispackage(path):
230 """Guess whether a path refers to a package directory."""
231 if os.path.isdir(path):
Brett Cannonf299abd2015-04-13 14:21:02 -0400232 for ext in ('.py', '.pyc'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000233 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000234 return True
235 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000236
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000237def source_synopsis(file):
238 line = file.readline()
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000239 while line[:1] == '#' or not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000240 line = file.readline()
241 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000242 line = line.strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000243 if line[:4] == 'r"""': line = line[1:]
244 if line[:3] == '"""':
245 line = line[3:]
246 if line[-1:] == '\\': line = line[:-1]
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000247 while not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000248 line = file.readline()
249 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000250 result = line.split('"""')[0].strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000251 else: result = None
252 return result
253
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000254def synopsis(filename, cache={}):
255 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000256 mtime = os.stat(filename).st_mtime
Charles-François Natali27c4e882011-07-27 19:40:02 +0200257 lastupdate, result = cache.get(filename, (None, None))
258 if lastupdate is None or lastupdate < mtime:
Eric Snowaed5b222014-01-04 20:38:11 -0700259 # Look for binary suffixes first, falling back to source.
260 if filename.endswith(tuple(importlib.machinery.BYTECODE_SUFFIXES)):
261 loader_cls = importlib.machinery.SourcelessFileLoader
262 elif filename.endswith(tuple(importlib.machinery.EXTENSION_SUFFIXES)):
263 loader_cls = importlib.machinery.ExtensionFileLoader
264 else:
265 loader_cls = None
266 # Now handle the choice.
267 if loader_cls is None:
268 # Must be a source file.
269 try:
270 file = tokenize.open(filename)
271 except OSError:
272 # module can't be opened, so skip it
273 return None
274 # text modules can be directly examined
275 with file:
276 result = source_synopsis(file)
277 else:
278 # Must be a binary module, which has to be imported.
279 loader = loader_cls('__temp__', filename)
Eric Snow3a62d142014-01-06 20:42:59 -0700280 # XXX We probably don't need to pass in the loader here.
281 spec = importlib.util.spec_from_file_location('__temp__', filename,
282 loader=loader)
Brett Cannoncb66eb02012-05-11 12:58:42 -0400283 try:
Brett Cannon2a17bde2014-05-30 14:55:29 -0400284 module = importlib._bootstrap._load(spec)
Brett Cannoncb66eb02012-05-11 12:58:42 -0400285 except:
286 return None
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000287 del sys.modules['__temp__']
Benjamin Peterson54237f92015-02-16 19:45:01 -0500288 result = module.__doc__.splitlines()[0] if module.__doc__ else None
Eric Snowaed5b222014-01-04 20:38:11 -0700289 # Cache the result.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000290 cache[filename] = (mtime, result)
291 return result
292
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000293class ErrorDuringImport(Exception):
294 """Errors that occurred while trying to import something to document it."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000295 def __init__(self, filename, exc_info):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000296 self.filename = filename
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000297 self.exc, self.value, self.tb = exc_info
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000298
299 def __str__(self):
Guido van Rossuma01a8b62007-05-27 09:20:14 +0000300 exc = self.exc.__name__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000301 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000302
303def importfile(path):
304 """Import a Python source file or compiled file given its path."""
Brett Cannonf4ba4ec2013-06-15 14:25:04 -0400305 magic = importlib.util.MAGIC_NUMBER
Victor Stinnere975af62011-07-04 02:08:50 +0200306 with open(path, 'rb') as file:
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400307 is_bytecode = magic == file.read(len(magic))
308 filename = os.path.basename(path)
309 name, ext = os.path.splitext(filename)
310 if is_bytecode:
Eric Snow32439d62015-05-02 19:15:18 -0600311 loader = importlib._bootstrap_external.SourcelessFileLoader(name, path)
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400312 else:
Eric Snow32439d62015-05-02 19:15:18 -0600313 loader = importlib._bootstrap_external.SourceFileLoader(name, path)
Eric Snow3a62d142014-01-06 20:42:59 -0700314 # XXX We probably don't need to pass in the loader here.
315 spec = importlib.util.spec_from_file_location(name, path, loader=loader)
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400316 try:
Brett Cannon2a17bde2014-05-30 14:55:29 -0400317 return importlib._bootstrap._load(spec)
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400318 except:
319 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000320
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000321def safeimport(path, forceload=0, cache={}):
322 """Import a module; handle errors; return None if the module isn't found.
323
324 If the module *is* found but an exception occurs, it's wrapped in an
325 ErrorDuringImport exception and reraised. Unlike __import__, if a
326 package path is specified, the module at the end of the path is returned,
327 not the package at the beginning. If the optional 'forceload' argument
328 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000329 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000330 # If forceload is 1 and the module has been previously loaded from
331 # disk, we always have to reload the module. Checking the file's
332 # mtime isn't good enough (e.g. the module could contain a class
333 # that inherits from another module that has changed).
334 if forceload and path in sys.modules:
335 if path not in sys.builtin_module_names:
Guido van Rossume7ba4952007-06-06 23:52:48 +0000336 # Remove the module from sys.modules and re-import to try
337 # and avoid problems with partially loaded modules.
338 # Also remove any submodules because they won't appear
339 # in the newly loaded module's namespace if they're already
340 # in sys.modules.
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000341 subs = [m for m in sys.modules if m.startswith(path + '.')]
342 for key in [path] + subs:
343 # Prevent garbage collection.
344 cache[key] = sys.modules[key]
345 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000346 module = __import__(path)
347 except:
348 # Did the error occur before or after the module was found?
349 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000350 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000351 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000352 raise ErrorDuringImport(sys.modules[path].__file__, info)
353 elif exc is SyntaxError:
354 # A SyntaxError occurred before we could execute the module.
355 raise ErrorDuringImport(value.filename, info)
Eric Snow46f97b82016-09-07 16:56:15 -0700356 elif issubclass(exc, ImportError) and value.name == path:
Brett Cannonfd074152012-04-14 14:10:13 -0400357 # No such module in the path.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000358 return None
359 else:
360 # Some other error occurred during the importing process.
361 raise ErrorDuringImport(path, sys.exc_info())
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000362 for part in path.split('.')[1:]:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000363 try: module = getattr(module, part)
364 except AttributeError: return None
365 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000366
367# ---------------------------------------------------- formatter base class
368
369class Doc:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000370
371 PYTHONDOCS = os.environ.get("PYTHONDOCS",
R David Murrayead9bfc2016-06-03 19:28:35 -0400372 "https://docs.python.org/%d.%d/library"
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000373 % sys.version_info[:2])
374
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000375 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000376 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000377 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000378 # 'try' clause is to attempt to handle the possibility that inspect
379 # identifies something in a way that pydoc itself has issues handling;
380 # think 'super' and how it is a descriptor (which raises the exception
381 # by lacking a __name__ attribute) and an instance.
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000382 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
383 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000384 try:
385 if inspect.ismodule(object): return self.docmodule(*args)
386 if inspect.isclass(object): return self.docclass(*args)
387 if inspect.isroutine(object): return self.docroutine(*args)
388 except AttributeError:
389 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000390 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000391 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000392
393 def fail(self, object, name=None, *args):
394 """Raise an exception for unimplemented types."""
395 message = "don't know how to document object%s of type %s" % (
396 name and ' ' + repr(name), type(object).__name__)
Collin Winterce36ad82007-08-30 01:19:48 +0000397 raise TypeError(message)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000398
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000399 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000400
R David Murrayead9bfc2016-06-03 19:28:35 -0400401 def getdocloc(self, object,
402 basedir=os.path.join(sys.base_exec_prefix, "lib",
403 "python%d.%d" % sys.version_info[:2])):
Skip Montanaro4997a692003-09-10 16:47:51 +0000404 """Return the location of module docs or None"""
405
406 try:
407 file = inspect.getabsfile(object)
408 except TypeError:
409 file = '(built-in)'
410
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000411 docloc = os.environ.get("PYTHONDOCS", self.PYTHONDOCS)
412
Martin Panter4f8aaf62016-06-12 04:24:06 +0000413 basedir = os.path.normcase(basedir)
Skip Montanaro4997a692003-09-10 16:47:51 +0000414 if (isinstance(object, type(os)) and
415 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
416 'marshal', 'posix', 'signal', 'sys',
Georg Brandl2067bfd2008-05-25 13:05:15 +0000417 '_thread', 'zipimport') or
Skip Montanaro4997a692003-09-10 16:47:51 +0000418 (file.startswith(basedir) and
Brian Curtin49c284c2010-03-31 03:19:28 +0000419 not file.startswith(os.path.join(basedir, 'site-packages')))) and
Brian Curtinedef05b2010-04-01 04:05:25 +0000420 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
Martin Panter4f8aaf62016-06-12 04:24:06 +0000421 if docloc.startswith(("http://", "https://")):
R David Murrayead9bfc2016-06-03 19:28:35 -0400422 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__.lower())
Skip Montanaro4997a692003-09-10 16:47:51 +0000423 else:
R David Murrayead9bfc2016-06-03 19:28:35 -0400424 docloc = os.path.join(docloc, object.__name__.lower() + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000425 else:
426 docloc = None
427 return docloc
428
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000429# -------------------------------------------- HTML documentation generator
430
431class HTMLRepr(Repr):
432 """Class for safely making an HTML representation of a Python object."""
433 def __init__(self):
434 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000435 self.maxlist = self.maxtuple = 20
436 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000437 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000438
439 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000440 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000441
442 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000443 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000444
445 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000446 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000447 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000448 if hasattr(self, methodname):
449 return getattr(self, methodname)(x, level)
450 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000451
452 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000453 test = cram(x, self.maxstring)
454 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000455 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000456 # Backslashes are only literal in the string and are never
457 # needed to make any special characters, so show a raw string.
458 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000459 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000460 r'<font color="#c040c0">\1</font>',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000461 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000462
Skip Montanarodf708782002-03-07 22:58:02 +0000463 repr_str = repr_string
464
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000465 def repr_instance(self, x, level):
466 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000467 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000468 except:
469 return self.escape('<%s instance>' % x.__class__.__name__)
470
471 repr_unicode = repr_string
472
473class HTMLDoc(Doc):
474 """Formatter class for HTML documentation."""
475
476 # ------------------------------------------- HTML formatting utilities
477
478 _repr_instance = HTMLRepr()
479 repr = _repr_instance.repr
480 escape = _repr_instance.escape
481
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000482 def page(self, title, contents):
483 """Format an HTML page."""
Georg Brandl388faac2009-04-10 08:31:48 +0000484 return '''\
Georg Brandle6066942009-04-10 08:28:28 +0000485<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000486<html><head><title>Python: %s</title>
Georg Brandl388faac2009-04-10 08:31:48 +0000487<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000488</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000489%s
490</body></html>''' % (title, contents)
491
492 def heading(self, title, fgcol, bgcol, extras=''):
493 """Format a page heading."""
494 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000495<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000496<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000497<td valign=bottom>&nbsp;<br>
498<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000499><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000500><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000501 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
502
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000503 def section(self, title, fgcol, bgcol, contents, width=6,
504 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000505 """Format a section with a heading."""
506 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000507 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000508 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000509<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000510<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000511<td colspan=3 valign=bottom>&nbsp;<br>
512<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000513 ''' % (bgcol, fgcol, title)
514 if prelude:
515 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000516<tr bgcolor="%s"><td rowspan=2>%s</td>
517<td colspan=2>%s</td></tr>
518<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
519 else:
520 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000521<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000522
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000523 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000524
525 def bigsection(self, title, *args):
526 """Format a section with a big heading."""
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000527 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000528 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000529
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000530 def preformat(self, text):
531 """Format literal preformatted text."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000532 text = self.escape(text.expandtabs())
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000533 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
534 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000535
536 def multicolumn(self, list, format, cols=4):
537 """Format a list of items into a multi-column list."""
538 result = ''
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000539 rows = (len(list)+cols-1)//cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000540 for col in range(cols):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000541 result = result + '<td width="%d%%" valign=top>' % (100//cols)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000542 for i in range(rows*col, rows*col+rows):
543 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000544 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000545 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000546 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000547
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000548 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000549
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000550 def namelink(self, name, *dicts):
551 """Make a link for an identifier, given name-to-URL mappings."""
552 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000553 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000554 return '<a href="%s">%s</a>' % (dict[name], name)
555 return name
556
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000557 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000558 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000559 name, module = object.__name__, sys.modules.get(object.__module__)
560 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000561 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000562 module.__name__, name, classname(object, modname))
563 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000564
565 def modulelink(self, object):
566 """Make a link for a module."""
567 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
568
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000569 def modpkglink(self, modpkginfo):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000570 """Make a link for a module or package to display in an index."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000571 name, path, ispackage, shadowed = modpkginfo
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000572 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000573 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000574 if path:
575 url = '%s.%s.html' % (path, name)
576 else:
577 url = '%s.html' % name
578 if ispackage:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000579 text = '<strong>%s</strong>&nbsp;(package)' % name
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000580 else:
581 text = name
582 return '<a href="%s">%s</a>' % (url, text)
583
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000584 def filelink(self, url, path):
585 """Make a link to source file."""
586 return '<a href="file:%s">%s</a>' % (url, path)
587
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000588 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
589 """Mark up some plain text, given a context of symbols to look for.
590 Each context dictionary maps object names to anchor names."""
591 escape = escape or self.escape
592 results = []
593 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000594 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
595 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000596 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000597 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000598 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000599 match = pattern.search(text, here)
600 if not match: break
601 start, end = match.span()
602 results.append(escape(text[here:start]))
603
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000604 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000605 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000606 url = escape(all).replace('"', '&quot;')
607 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000608 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000609 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
610 results.append('<a href="%s">%s</a>' % (url, escape(all)))
611 elif pep:
Christian Heimes2202f872008-02-06 14:31:34 +0000612 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000613 results.append('<a href="%s">%s</a>' % (url, escape(all)))
Benjamin Petersoned1160b2014-06-07 16:44:00 -0700614 elif selfdot:
615 # Create a link for methods like 'self.method(...)'
616 # and use <strong> for attributes like 'self.attr'
617 if text[end:end+1] == '(':
618 results.append('self.' + self.namelink(name, methods))
619 else:
620 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000621 elif text[end:end+1] == '(':
622 results.append(self.namelink(name, methods, funcs, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000623 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000624 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000625 here = end
626 results.append(escape(text[here:]))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000627 return ''.join(results)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000628
629 # ---------------------------------------------- type-specific routines
630
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000631 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000632 """Produce HTML for a class tree as given by inspect.getclasstree()."""
633 result = ''
634 for entry in tree:
635 if type(entry) is type(()):
636 c, bases = entry
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000637 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000638 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000639 if bases and bases != (parent,):
640 parents = []
641 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000642 parents.append(self.classlink(base, modname))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000643 result = result + '(' + ', '.join(parents) + ')'
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000644 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000645 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000646 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000647 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000648 return '<dl>\n%s</dl>\n' % result
649
Tim Peters8dd7ade2001-10-18 19:56:17 +0000650 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000651 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000652 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000653 try:
654 all = object.__all__
655 except AttributeError:
656 all = None
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000657 parts = name.split('.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000658 links = []
659 for i in range(len(parts)-1):
660 links.append(
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000661 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000662 ('.'.join(parts[:i+1]), parts[i]))
663 linkedname = '.'.join(links + parts[-1:])
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000664 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000665 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000666 path = inspect.getabsfile(object)
Zachary Wareeb432142014-07-10 11:18:00 -0500667 url = urllib.parse.quote(path)
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000668 filelink = self.filelink(url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000669 except TypeError:
670 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000671 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000672 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000673 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000674 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000675 version = version[11:-1].strip()
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000676 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000677 if hasattr(object, '__date__'):
678 info.append(self.escape(str(object.__date__)))
679 if info:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000680 head = head + ' (%s)' % ', '.join(info)
Skip Montanaro4997a692003-09-10 16:47:51 +0000681 docloc = self.getdocloc(object)
682 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000683 docloc = '<br><a href="%(docloc)s">Module Reference</a>' % locals()
Skip Montanaro4997a692003-09-10 16:47:51 +0000684 else:
685 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000686 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000687 head, '#ffffff', '#7799ee',
688 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000689
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000690 modules = inspect.getmembers(object, inspect.ismodule)
691
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000692 classes, cdict = [], {}
693 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000694 # if __all__ exists, believe it. Otherwise use old heuristic.
695 if (all is not None or
696 (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700697 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000698 classes.append((key, value))
699 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000700 for key, value in classes:
701 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000702 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000703 module = sys.modules.get(modname)
704 if modname != name and module and hasattr(module, key):
705 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000706 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000707 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000708 funcs, fdict = [], {}
709 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000710 # if __all__ exists, believe it. Otherwise use old heuristic.
711 if (all is not None or
712 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700713 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000714 funcs.append((key, value))
715 fdict[key] = '#-' + key
716 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000717 data = []
718 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700719 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000720 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000721
722 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
723 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000724 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000725
726 if hasattr(object, '__path__'):
727 modpkgs = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000728 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
729 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000730 modpkgs.sort()
731 contents = self.multicolumn(modpkgs, self.modpkglink)
732 result = result + self.bigsection(
733 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000734 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000735 contents = self.multicolumn(
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000736 modules, lambda t: self.modulelink(t[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000737 result = result + self.bigsection(
Christian Heimes7131fd92008-02-19 14:21:46 +0000738 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000739
740 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000741 classlist = [value for (key, value) in classes]
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000742 contents = [
743 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000744 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000745 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000746 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000747 'Classes', '#ffffff', '#ee77aa', ' '.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000748 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000749 contents = []
750 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000751 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000752 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000753 'Functions', '#ffffff', '#eeaa77', ' '.join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000754 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000755 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000756 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000757 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000758 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000759 'Data', '#ffffff', '#55aa55', '<br>\n'.join(contents))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000760 if hasattr(object, '__author__'):
761 contents = self.markup(str(object.__author__), self.preformat)
762 result = result + self.bigsection(
763 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000764 if hasattr(object, '__credits__'):
765 contents = self.markup(str(object.__credits__), self.preformat)
766 result = result + self.bigsection(
767 'Credits', '#ffffff', '#7799ee', contents)
768
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000769 return result
770
Tim Peters8dd7ade2001-10-18 19:56:17 +0000771 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
772 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000773 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000774 realname = object.__name__
775 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000776 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000777
Tim Petersb47879b2001-09-24 04:47:19 +0000778 contents = []
779 push = contents.append
780
Tim Petersfa26f7c2001-09-24 08:05:11 +0000781 # Cute little class to pump out a horizontal rule between sections.
782 class HorizontalRule:
783 def __init__(self):
784 self.needone = 0
785 def maybe(self):
786 if self.needone:
787 push('<hr>\n')
788 self.needone = 1
789 hr = HorizontalRule()
790
Tim Petersc86f6ca2001-09-26 21:31:51 +0000791 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000792 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000793 if len(mro) > 2:
794 hr.maybe()
795 push('<dl><dt>Method resolution order:</dt>\n')
796 for base in mro:
797 push('<dd>%s</dd>\n' % self.classlink(base,
798 object.__module__))
799 push('</dl>\n')
800
Tim Petersb47879b2001-09-24 04:47:19 +0000801 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000802 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000803 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000804 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000805 push(msg)
806 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100807 try:
808 value = getattr(object, name)
809 except Exception:
810 # Some descriptors may meet a failure in their __get__.
811 # (bug #1785)
812 push(self._docdescriptor(name, value, mod))
813 else:
814 push(self.document(value, name, mod,
815 funcs, classes, mdict, object))
Tim Petersb47879b2001-09-24 04:47:19 +0000816 push('\n')
817 return attrs
818
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000819 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000820 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000821 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000822 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000823 push(msg)
824 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000825 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000826 return attrs
827
Tim Petersfa26f7c2001-09-24 08:05:11 +0000828 def spilldata(msg, attrs, predicate):
829 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000830 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000831 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000832 push(msg)
833 for name, kind, homecls, value in ok:
834 base = self.docother(getattr(object, name), name, mod)
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200835 if callable(value) or inspect.isdatadescriptor(value):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000836 doc = getattr(value, "__doc__", None)
837 else:
838 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000839 if doc is None:
840 push('<dl><dt>%s</dl>\n' % base)
841 else:
842 doc = self.markup(getdoc(value), self.preformat,
843 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000844 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000845 push('<dl><dt>%s%s</dl>\n' % (base, doc))
846 push('\n')
847 return attrs
848
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000849 attrs = [(name, kind, cls, value)
850 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -0700851 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000852
Tim Petersb47879b2001-09-24 04:47:19 +0000853 mdict = {}
854 for key, kind, homecls, value in attrs:
855 mdict[key] = anchor = '#' + name + '-' + key
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100856 try:
857 value = getattr(object, name)
858 except Exception:
859 # Some descriptors may meet a failure in their __get__.
860 # (bug #1785)
861 pass
Tim Petersb47879b2001-09-24 04:47:19 +0000862 try:
863 # The value may not be hashable (e.g., a data attr with
864 # a dict or list value).
865 mdict[value] = anchor
866 except TypeError:
867 pass
868
Tim Petersfa26f7c2001-09-24 08:05:11 +0000869 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000870 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000871 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000872 else:
873 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000874 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
875
Georg Brandl1a3284e2007-12-02 09:40:06 +0000876 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000877 attrs = inherited
878 continue
879 elif thisclass is object:
880 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000881 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000882 tag = 'inherited from %s' % self.classlink(thisclass,
883 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000884 tag += ':<br>\n'
885
Raymond Hettinger95801bb2015-08-18 22:25:16 -0700886 sort_attributes(attrs, object)
Tim Petersb47879b2001-09-24 04:47:19 +0000887
888 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000889 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000890 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000891 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000892 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000893 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000894 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000895 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
896 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000897 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000898 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000899 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000900 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000901
902 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000903
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000904 if name == realname:
905 title = '<a name="%s">class <strong>%s</strong></a>' % (
906 name, realname)
907 else:
908 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
909 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000910 if bases:
911 parents = []
912 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000913 parents.append(self.classlink(base, object.__module__))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000914 title = title + '(%s)' % ', '.join(parents)
Serhiy Storchakaccb5f3c2017-01-23 12:37:00 +0200915
916 decl = ''
917 try:
918 signature = inspect.signature(object)
919 except (ValueError, TypeError):
920 signature = None
921 if signature:
922 argspec = str(signature)
Serhiy Storchaka213f2292017-01-23 14:02:35 +0200923 if argspec and argspec != '()':
Serhiy Storchakaccb5f3c2017-01-23 12:37:00 +0200924 decl = name + self.escape(argspec) + '\n\n'
925
926 doc = getdoc(object)
927 if decl:
928 doc = decl + (doc or '')
929 doc = self.markup(doc, self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000930 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000931
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000932 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000933
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000934 def formatvalue(self, object):
935 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000936 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000937
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000938 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000939 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000940 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000941 realname = object.__name__
942 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000943 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000944 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000945 skipdocs = 0
Larry Hastings24a882b2014-02-20 23:34:46 -0800946 if _is_bound_method(object):
Christian Heimesff737952007-11-27 10:40:20 +0000947 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000948 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000949 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000950 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000951 else:
Christian Heimesff737952007-11-27 10:40:20 +0000952 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000953 note = ' method of %s instance' % self.classlink(
Christian Heimesff737952007-11-27 10:40:20 +0000954 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000955 else:
956 note = ' unbound %s method' % self.classlink(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000957
958 if name == realname:
959 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
960 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000961 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000962 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000963 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000964 cl.__name__ + '-' + realname, realname)
965 skipdocs = 1
966 else:
967 reallink = realname
968 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
969 anchor, name, reallink)
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800970 argspec = None
Larry Hastings24a882b2014-02-20 23:34:46 -0800971 if inspect.isroutine(object):
Larry Hastings5c661892014-01-24 06:17:25 -0800972 try:
973 signature = inspect.signature(object)
974 except (ValueError, TypeError):
975 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800976 if signature:
977 argspec = str(signature)
978 if realname == '<lambda>':
979 title = '<strong>%s</strong> <em>lambda</em> ' % name
980 # XXX lambda's won't usually have func_annotations['return']
981 # since the syntax doesn't support but it is possible.
982 # So removing parentheses isn't truly safe.
983 argspec = argspec[1:-1] # remove parentheses
984 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +0000985 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000986
Serhiy Storchaka66dd4aa2014-11-17 23:48:02 +0200987 decl = title + self.escape(argspec) + (note and self.grey(
Tim Peters2306d242001-09-25 03:18:32 +0000988 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000989
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000990 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000991 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000992 else:
993 doc = self.markup(
994 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000995 doc = doc and '<dd><tt>%s</tt></dd>' % doc
996 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000997
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000998 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000999 results = []
1000 push = results.append
1001
1002 if name:
1003 push('<dl><dt><strong>%s</strong></dt>\n' % name)
1004 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001005 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001006 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001007 push('</dl>\n')
1008
1009 return ''.join(results)
1010
1011 def docproperty(self, object, name=None, mod=None, cl=None):
1012 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001013 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001014
Tim Peters8dd7ade2001-10-18 19:56:17 +00001015 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001016 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001017 lhs = name and '<strong>%s</strong> = ' % name or ''
1018 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001019
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001020 def docdata(self, object, name=None, mod=None, cl=None):
1021 """Produce html documentation for a data descriptor."""
1022 return self._docdescriptor(name, object, mod)
1023
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001024 def index(self, dir, shadowed=None):
1025 """Generate an HTML index for a directory of modules."""
1026 modpkgs = []
1027 if shadowed is None: shadowed = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001028 for importer, name, ispkg in pkgutil.iter_modules([dir]):
Victor Stinner4d652242011-04-12 23:41:50 +02001029 if any((0xD800 <= ord(ch) <= 0xDFFF) for ch in name):
1030 # ignore a module if its name contains a surrogate character
1031 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001032 modpkgs.append((name, '', ispkg, name in shadowed))
1033 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001034
1035 modpkgs.sort()
1036 contents = self.multicolumn(modpkgs, self.modpkglink)
1037 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
1038
1039# -------------------------------------------- text documentation generator
1040
1041class TextRepr(Repr):
1042 """Class for safely making a text representation of a Python object."""
1043 def __init__(self):
1044 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001045 self.maxlist = self.maxtuple = 20
1046 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001047 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001048
1049 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001050 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001051 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001052 if hasattr(self, methodname):
1053 return getattr(self, methodname)(x, level)
1054 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001055
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001056 def repr_string(self, x, level):
1057 test = cram(x, self.maxstring)
1058 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001059 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001060 # Backslashes are only literal in the string and are never
1061 # needed to make any special characters, so show a raw string.
1062 return 'r' + testrepr[0] + test + testrepr[0]
1063 return testrepr
1064
Skip Montanarodf708782002-03-07 22:58:02 +00001065 repr_str = repr_string
1066
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001067 def repr_instance(self, x, level):
1068 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001069 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001070 except:
1071 return '<%s instance>' % x.__class__.__name__
1072
1073class TextDoc(Doc):
1074 """Formatter class for text documentation."""
1075
1076 # ------------------------------------------- text formatting utilities
1077
1078 _repr_instance = TextRepr()
1079 repr = _repr_instance.repr
1080
1081 def bold(self, text):
1082 """Format a string in bold by overstriking."""
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001083 return ''.join(ch + '\b' + ch for ch in text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001084
1085 def indent(self, text, prefix=' '):
1086 """Indent text by prepending a given prefix to each line."""
1087 if not text: return ''
Collin Winter72e110c2007-07-17 00:27:30 +00001088 lines = [prefix + line for line in text.split('\n')]
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001089 if lines: lines[-1] = lines[-1].rstrip()
1090 return '\n'.join(lines)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001091
1092 def section(self, title, contents):
1093 """Format a section with a given heading."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001094 clean_contents = self.indent(contents).rstrip()
1095 return self.bold(title) + '\n' + clean_contents + '\n\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001096
1097 # ---------------------------------------------- type-specific routines
1098
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001099 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001100 """Render in text a class tree as returned by inspect.getclasstree()."""
1101 result = ''
1102 for entry in tree:
1103 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001104 c, bases = entry
1105 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001106 if bases and bases != (parent,):
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001107 parents = (classname(c, modname) for c in bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001108 result = result + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001109 result = result + '\n'
1110 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001111 result = result + self.formattree(
1112 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001113 return result
1114
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001115 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001116 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001117 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001118 synop, desc = splitdoc(getdoc(object))
1119 result = self.section('NAME', name + (synop and ' - ' + synop))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001120 all = getattr(object, '__all__', None)
Skip Montanaro4997a692003-09-10 16:47:51 +00001121 docloc = self.getdocloc(object)
1122 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001123 result = result + self.section('MODULE REFERENCE', docloc + """
1124
Éric Araujo647ef8c2011-09-11 00:43:20 +02001125The following documentation is automatically generated from the Python
1126source files. It may be incomplete, incorrect or include features that
1127are considered implementation detail and may vary between Python
1128implementations. When in doubt, consult the module reference at the
1129location listed above.
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001130""")
Skip Montanaro4997a692003-09-10 16:47:51 +00001131
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001132 if desc:
1133 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001134
1135 classes = []
1136 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001137 # if __all__ exists, believe it. Otherwise use old heuristic.
1138 if (all is not None
1139 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001140 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001141 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001142 funcs = []
1143 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001144 # if __all__ exists, believe it. Otherwise use old heuristic.
1145 if (all is not None or
1146 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001147 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001148 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001149 data = []
1150 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001151 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001152 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001153
Christian Heimes1af737c2008-01-23 08:24:23 +00001154 modpkgs = []
1155 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001156 if hasattr(object, '__path__'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001157 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Christian Heimes1af737c2008-01-23 08:24:23 +00001158 modpkgs_names.add(modname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001159 if ispkg:
1160 modpkgs.append(modname + ' (package)')
1161 else:
1162 modpkgs.append(modname)
1163
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001164 modpkgs.sort()
1165 result = result + self.section(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001166 'PACKAGE CONTENTS', '\n'.join(modpkgs))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001167
Christian Heimes1af737c2008-01-23 08:24:23 +00001168 # Detect submodules as sometimes created by C extensions
1169 submodules = []
1170 for key, value in inspect.getmembers(object, inspect.ismodule):
1171 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1172 submodules.append(key)
1173 if submodules:
1174 submodules.sort()
1175 result = result + self.section(
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001176 'SUBMODULES', '\n'.join(submodules))
Christian Heimes1af737c2008-01-23 08:24:23 +00001177
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001178 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001179 classlist = [value for key, value in classes]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001180 contents = [self.formattree(
1181 inspect.getclasstree(classlist, 1), name)]
1182 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001183 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001184 result = result + self.section('CLASSES', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001185
1186 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001187 contents = []
1188 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001189 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001190 result = result + self.section('FUNCTIONS', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001191
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001192 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001193 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001194 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001195 contents.append(self.docother(value, key, name, maxlen=70))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001196 result = result + self.section('DATA', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001197
1198 if hasattr(object, '__version__'):
1199 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001200 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001201 version = version[11:-1].strip()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001202 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001203 if hasattr(object, '__date__'):
1204 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001205 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001206 result = result + self.section('AUTHOR', str(object.__author__))
1207 if hasattr(object, '__credits__'):
1208 result = result + self.section('CREDITS', str(object.__credits__))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001209 try:
1210 file = inspect.getabsfile(object)
1211 except TypeError:
1212 file = '(built-in)'
1213 result = result + self.section('FILE', file)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001214 return result
1215
Georg Brandl9bd45f992010-12-03 09:58:38 +00001216 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001217 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001218 realname = object.__name__
1219 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001220 bases = object.__bases__
1221
Tim Petersc86f6ca2001-09-26 21:31:51 +00001222 def makename(c, m=object.__module__):
1223 return classname(c, m)
1224
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001225 if name == realname:
1226 title = 'class ' + self.bold(realname)
1227 else:
1228 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001229 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001230 parents = map(makename, bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001231 title = title + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001232
Serhiy Storchakaccb5f3c2017-01-23 12:37:00 +02001233 contents = []
Tim Peters28355492001-09-23 21:29:55 +00001234 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001235
Serhiy Storchakaccb5f3c2017-01-23 12:37:00 +02001236 try:
1237 signature = inspect.signature(object)
1238 except (ValueError, TypeError):
1239 signature = None
1240 if signature:
1241 argspec = str(signature)
Serhiy Storchaka213f2292017-01-23 14:02:35 +02001242 if argspec and argspec != '()':
Serhiy Storchakaccb5f3c2017-01-23 12:37:00 +02001243 push(name + argspec + '\n')
1244
1245 doc = getdoc(object)
1246 if doc:
1247 push(doc + '\n')
1248
Tim Petersc86f6ca2001-09-26 21:31:51 +00001249 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001250 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001251 if len(mro) > 2:
1252 push("Method resolution order:")
1253 for base in mro:
1254 push(' ' + makename(base))
1255 push('')
1256
Sanyam Khuranaa323cdc2018-10-21 00:22:02 -07001257 # List the built-in subclasses, if any:
1258 subclasses = sorted(
1259 (str(cls.__name__) for cls in object.__subclasses__()
1260 if not cls.__name__.startswith("_") and cls.__module__ == "builtins"),
1261 key=str.lower
1262 )
1263 no_of_subclasses = len(subclasses)
1264 MAX_SUBCLASSES_TO_DISPLAY = 4
1265 if subclasses:
1266 push("Built-in subclasses:")
1267 for subclassname in subclasses[:MAX_SUBCLASSES_TO_DISPLAY]:
1268 push(' ' + subclassname)
1269 if no_of_subclasses > MAX_SUBCLASSES_TO_DISPLAY:
1270 push(' ... and ' +
1271 str(no_of_subclasses - MAX_SUBCLASSES_TO_DISPLAY) +
1272 ' other subclasses')
1273 push('')
1274
Tim Petersf4aad8e2001-09-24 22:40:47 +00001275 # Cute little class to pump out a horizontal rule between sections.
1276 class HorizontalRule:
1277 def __init__(self):
1278 self.needone = 0
1279 def maybe(self):
1280 if self.needone:
1281 push('-' * 70)
1282 self.needone = 1
1283 hr = HorizontalRule()
1284
Tim Peters28355492001-09-23 21:29:55 +00001285 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001286 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001287 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001288 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001289 push(msg)
1290 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001291 try:
1292 value = getattr(object, name)
1293 except Exception:
1294 # Some descriptors may meet a failure in their __get__.
1295 # (bug #1785)
1296 push(self._docdescriptor(name, value, mod))
1297 else:
1298 push(self.document(value,
1299 name, mod, object))
Tim Peters28355492001-09-23 21:29:55 +00001300 return attrs
1301
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001302 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001303 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001304 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001305 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001306 push(msg)
1307 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001308 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001309 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001310
Tim Petersfa26f7c2001-09-24 08:05:11 +00001311 def spilldata(msg, attrs, predicate):
1312 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001313 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001314 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001315 push(msg)
1316 for name, kind, homecls, value in ok:
Florent Xicluna5d1155c2011-10-28 14:45:05 +02001317 if callable(value) or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001318 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001319 else:
1320 doc = None
Serhiy Storchaka056eb022014-02-19 23:05:12 +02001321 try:
1322 obj = getattr(object, name)
1323 except AttributeError:
1324 obj = homecls.__dict__[name]
1325 push(self.docother(obj, name, mod, maxlen=70, doc=doc) +
1326 '\n')
Tim Peters28355492001-09-23 21:29:55 +00001327 return attrs
1328
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001329 attrs = [(name, kind, cls, value)
1330 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -07001331 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001332
Tim Petersfa26f7c2001-09-24 08:05:11 +00001333 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001334 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001335 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001336 else:
1337 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001338 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1339
Georg Brandl1a3284e2007-12-02 09:40:06 +00001340 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001341 attrs = inherited
1342 continue
1343 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001344 tag = "defined here"
1345 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001346 tag = "inherited from %s" % classname(thisclass,
1347 object.__module__)
Raymond Hettinger95801bb2015-08-18 22:25:16 -07001348
1349 sort_attributes(attrs, object)
Tim Peters28355492001-09-23 21:29:55 +00001350
1351 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001352 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001353 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001354 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001355 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001356 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001357 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001358 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1359 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001360 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1361 lambda t: t[1] == 'data')
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001362
Tim Peters28355492001-09-23 21:29:55 +00001363 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001364 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001365
1366 contents = '\n'.join(contents)
1367 if not contents:
1368 return title + '\n'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001369 return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001370
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001371 def formatvalue(self, object):
1372 """Format an argument default value as text."""
1373 return '=' + self.repr(object)
1374
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001375 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001376 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001377 realname = object.__name__
1378 name = name or realname
1379 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001380 skipdocs = 0
Larry Hastings24a882b2014-02-20 23:34:46 -08001381 if _is_bound_method(object):
Christian Heimesff737952007-11-27 10:40:20 +00001382 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001383 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001384 if imclass is not cl:
1385 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001386 else:
Christian Heimesff737952007-11-27 10:40:20 +00001387 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001388 note = ' method of %s instance' % classname(
Christian Heimesff737952007-11-27 10:40:20 +00001389 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001390 else:
1391 note = ' unbound %s method' % classname(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001392
1393 if name == realname:
1394 title = self.bold(realname)
1395 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001396 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001397 cl.__dict__[realname] is object):
1398 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001399 title = self.bold(name) + ' = ' + realname
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001400 argspec = None
Larry Hastings5c661892014-01-24 06:17:25 -08001401
1402 if inspect.isroutine(object):
1403 try:
1404 signature = inspect.signature(object)
1405 except (ValueError, TypeError):
1406 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001407 if signature:
1408 argspec = str(signature)
1409 if realname == '<lambda>':
1410 title = self.bold(name) + ' lambda '
1411 # XXX lambda's won't usually have func_annotations['return']
1412 # since the syntax doesn't support but it is possible.
1413 # So removing parentheses isn't truly safe.
1414 argspec = argspec[1:-1] # remove parentheses
1415 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +00001416 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001417 decl = title + argspec + note
1418
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001419 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001420 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001421 else:
1422 doc = getdoc(object) or ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001423 return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001424
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001425 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001426 results = []
1427 push = results.append
1428
1429 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001430 push(self.bold(name))
1431 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001432 doc = getdoc(value) or ''
1433 if doc:
1434 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001435 push('\n')
1436 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001437
1438 def docproperty(self, object, name=None, mod=None, cl=None):
1439 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001440 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001441
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001442 def docdata(self, object, name=None, mod=None, cl=None):
1443 """Produce text documentation for a data descriptor."""
1444 return self._docdescriptor(name, object, mod)
1445
Georg Brandl8b813db2005-10-01 16:32:31 +00001446 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001447 """Produce text documentation for a data object."""
1448 repr = self.repr(object)
1449 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001450 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001451 chop = maxlen - len(line)
1452 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001453 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001454 if doc is not None:
1455 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001456 return line
1457
Georg Brandld80d5f42010-12-03 07:47:22 +00001458class _PlainTextDoc(TextDoc):
1459 """Subclass of TextDoc which overrides string styling"""
1460 def bold(self, text):
1461 return text
1462
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001463# --------------------------------------------------------- user interfaces
1464
1465def pager(text):
1466 """The first time this is called, determine what kind of pager to use."""
1467 global pager
1468 pager = getpager()
1469 pager(text)
1470
1471def getpager():
1472 """Decide what method to use for paging through text."""
Benjamin Peterson159824e2014-06-07 20:14:26 -07001473 if not hasattr(sys.stdin, "isatty"):
1474 return plainpager
Guido van Rossuma01a8b62007-05-27 09:20:14 +00001475 if not hasattr(sys.stdout, "isatty"):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001476 return plainpager
1477 if not sys.stdin.isatty() or not sys.stdout.isatty():
1478 return plainpager
doko@ubuntu.com96575452016-06-14 08:39:31 +02001479 use_pager = os.environ.get('MANPAGER') or os.environ.get('PAGER')
1480 if use_pager:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001481 if sys.platform == 'win32': # pipes completely broken in Windows
doko@ubuntu.comc8fd1922016-06-14 09:03:52 +02001482 return lambda text: tempfilepager(plain(text), use_pager)
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001483 elif os.environ.get('TERM') in ('dumb', 'emacs'):
doko@ubuntu.comc8fd1922016-06-14 09:03:52 +02001484 return lambda text: pipepager(plain(text), use_pager)
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001485 else:
doko@ubuntu.comc8fd1922016-06-14 09:03:52 +02001486 return lambda text: pipepager(text, use_pager)
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001487 if os.environ.get('TERM') in ('dumb', 'emacs'):
1488 return plainpager
Jesus Cea4791a242012-10-05 03:15:39 +02001489 if sys.platform == 'win32':
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001490 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001491 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001492 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001493
1494 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001495 (fd, filename) = tempfile.mkstemp()
1496 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001497 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001498 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001499 return lambda text: pipepager(text, 'more')
1500 else:
1501 return ttypager
1502 finally:
1503 os.unlink(filename)
1504
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001505def plain(text):
1506 """Remove boldface formatting from text."""
1507 return re.sub('.\b', '', text)
1508
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001509def pipepager(text, cmd):
1510 """Page through text by feeding it to another program."""
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001511 import subprocess
1512 proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001513 try:
R David Murray1058cda2015-03-29 15:15:40 -04001514 with io.TextIOWrapper(proc.stdin, errors='backslashreplace') as pipe:
R David Murraye7f5e142015-03-30 10:14:47 -04001515 try:
1516 pipe.write(text)
1517 except KeyboardInterrupt:
1518 # We've hereby abandoned whatever text hasn't been written,
1519 # but the pager is still in control of the terminal.
1520 pass
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001521 except OSError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001522 pass # Ignore broken pipes caused by quitting the pager program.
R David Murray1058cda2015-03-29 15:15:40 -04001523 while True:
1524 try:
1525 proc.wait()
1526 break
1527 except KeyboardInterrupt:
1528 # Ignore ctl-c like the pager itself does. Otherwise the pager is
1529 # left running and the terminal is in raw mode and unusable.
1530 pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001531
1532def tempfilepager(text, cmd):
1533 """Page through text by invoking a program on a temporary file."""
1534 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001535 filename = tempfile.mktemp()
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001536 with open(filename, 'w', errors='backslashreplace') as file:
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +01001537 file.write(text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001538 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001539 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001540 finally:
1541 os.unlink(filename)
1542
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001543def _escape_stdout(text):
1544 # Escape non-encodable characters to avoid encoding errors later
1545 encoding = getattr(sys.stdout, 'encoding', None) or 'utf-8'
1546 return text.encode(encoding, 'backslashreplace').decode(encoding)
1547
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001548def ttypager(text):
1549 """Page through text on a text terminal."""
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001550 lines = plain(_escape_stdout(text)).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001551 try:
1552 import tty
1553 fd = sys.stdin.fileno()
1554 old = tty.tcgetattr(fd)
1555 tty.setcbreak(fd)
1556 getchar = lambda: sys.stdin.read(1)
Serhiy Storchakaab5e9b92014-11-28 00:09:29 +02001557 except (ImportError, AttributeError, io.UnsupportedOperation):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001558 tty = None
1559 getchar = lambda: sys.stdin.readline()[:-1][:1]
1560
1561 try:
Serhiy Storchakaab5e9b92014-11-28 00:09:29 +02001562 try:
1563 h = int(os.environ.get('LINES', 0))
1564 except ValueError:
1565 h = 0
1566 if h <= 1:
1567 h = 25
1568 r = inc = h - 1
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001569 sys.stdout.write('\n'.join(lines[:inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001570 while lines[r:]:
1571 sys.stdout.write('-- more --')
1572 sys.stdout.flush()
1573 c = getchar()
1574
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001575 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001576 sys.stdout.write('\r \r')
1577 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001578 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001579 sys.stdout.write('\r \r' + lines[r] + '\n')
1580 r = r + 1
1581 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001582 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001583 r = r - inc - inc
1584 if r < 0: r = 0
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001585 sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001586 r = r + inc
1587
1588 finally:
1589 if tty:
1590 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1591
1592def plainpager(text):
1593 """Simply print unformatted text. This is the ultimate fallback."""
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001594 sys.stdout.write(plain(_escape_stdout(text)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001595
1596def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001597 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001598 if inspect.ismodule(thing):
1599 if thing.__name__ in sys.builtin_module_names:
1600 return 'built-in module ' + thing.__name__
1601 if hasattr(thing, '__path__'):
1602 return 'package ' + thing.__name__
1603 else:
1604 return 'module ' + thing.__name__
1605 if inspect.isbuiltin(thing):
1606 return 'built-in function ' + thing.__name__
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001607 if inspect.isgetsetdescriptor(thing):
1608 return 'getset descriptor %s.%s.%s' % (
1609 thing.__objclass__.__module__, thing.__objclass__.__name__,
1610 thing.__name__)
1611 if inspect.ismemberdescriptor(thing):
1612 return 'member descriptor %s.%s.%s' % (
1613 thing.__objclass__.__module__, thing.__objclass__.__name__,
1614 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001615 if inspect.isclass(thing):
1616 return 'class ' + thing.__name__
1617 if inspect.isfunction(thing):
1618 return 'function ' + thing.__name__
1619 if inspect.ismethod(thing):
1620 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001621 return type(thing).__name__
1622
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001623def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001624 """Locate an object by name or dotted path, importing as necessary."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001625 parts = [part for part in path.split('.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001626 module, n = None, 0
1627 while n < len(parts):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001628 nextmodule = safeimport('.'.join(parts[:n+1]), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001629 if nextmodule: module, n = nextmodule, n + 1
1630 else: break
1631 if module:
1632 object = module
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001633 else:
Éric Araujoe64e51b2011-07-29 17:03:55 +02001634 object = builtins
1635 for part in parts[n:]:
1636 try:
1637 object = getattr(object, part)
1638 except AttributeError:
1639 return None
1640 return object
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001641
1642# --------------------------------------- interactive interpreter interface
1643
1644text = TextDoc()
Georg Brandld80d5f42010-12-03 07:47:22 +00001645plaintext = _PlainTextDoc()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001646html = HTMLDoc()
1647
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001648def resolve(thing, forceload=0):
1649 """Given an object or a path to an object, get the object and its name."""
1650 if isinstance(thing, str):
1651 object = locate(thing, forceload)
Serhiy Storchakab6076fb2015-04-21 21:09:48 +03001652 if object is None:
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001653 raise ImportError('''\
1654No Python documentation found for %r.
1655Use help() to get the interactive help utility.
1656Use help(str) for help on the str class.''' % thing)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001657 return object, thing
1658 else:
R David Murrayc43125a2012-04-23 13:23:57 -04001659 name = getattr(thing, '__name__', None)
1660 return thing, name if isinstance(name, str) else None
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001661
Georg Brandld80d5f42010-12-03 07:47:22 +00001662def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
1663 renderer=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001664 """Render text documentation, given an object or a path to an object."""
Georg Brandld80d5f42010-12-03 07:47:22 +00001665 if renderer is None:
1666 renderer = text
Guido van Rossumd8faa362007-04-27 19:54:29 +00001667 object, name = resolve(thing, forceload)
1668 desc = describe(object)
1669 module = inspect.getmodule(object)
1670 if name and '.' in name:
1671 desc += ' in ' + name[:name.rfind('.')]
1672 elif module and module is not object:
1673 desc += ' in module ' + module.__name__
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001674
1675 if not (inspect.ismodule(object) or
Guido van Rossumd8faa362007-04-27 19:54:29 +00001676 inspect.isclass(object) or
1677 inspect.isroutine(object) or
1678 inspect.isgetsetdescriptor(object) or
1679 inspect.ismemberdescriptor(object) or
1680 isinstance(object, property)):
1681 # If the passed object is a piece of data or an instance,
1682 # document its available methods instead of its value.
1683 object = type(object)
1684 desc += ' object'
Georg Brandld80d5f42010-12-03 07:47:22 +00001685 return title % desc + '\n\n' + renderer.document(object, name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001686
Georg Brandld80d5f42010-12-03 07:47:22 +00001687def doc(thing, title='Python Library Documentation: %s', forceload=0,
1688 output=None):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001689 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001690 try:
Georg Brandld80d5f42010-12-03 07:47:22 +00001691 if output is None:
1692 pager(render_doc(thing, title, forceload))
1693 else:
1694 output.write(render_doc(thing, title, forceload, plaintext))
Guido van Rossumb940e112007-01-10 16:19:56 +00001695 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001696 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001697
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001698def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001699 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001700 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001701 object, name = resolve(thing, forceload)
1702 page = html.page(describe(object), html.document(object, name))
Serhiy Storchaka46ba6c82015-04-04 11:01:02 +03001703 with open(name + '.html', 'w', encoding='utf-8') as file:
1704 file.write(page)
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001705 print('wrote', name + '.html')
Guido van Rossumb940e112007-01-10 16:19:56 +00001706 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001707 print(value)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001708
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001709def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001710 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001711 if done is None: done = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001712 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1713 writedoc(modname)
1714 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001715
1716class Helper:
Georg Brandl6b38daa2008-06-01 21:05:17 +00001717
1718 # These dictionaries map a topic name to either an alias, or a tuple
1719 # (label, seealso-items). The "label" is the label of the corresponding
1720 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl5617db82009-04-27 16:28:57 +00001721 # in pydoc_data/topics.py.
Georg Brandl6b38daa2008-06-01 21:05:17 +00001722 #
1723 # CAUTION: if you change one of these dictionaries, be sure to adapt the
Jelle Zijlstraac317702017-10-05 20:24:46 -07001724 # list of needed labels in Doc/tools/extensions/pyspecific.py and
Georg Brandl5617db82009-04-27 16:28:57 +00001725 # regenerate the pydoc_data/topics.py file by running
Georg Brandl6b38daa2008-06-01 21:05:17 +00001726 # make pydoc-topics
1727 # in Doc/ and copying the output file into the Lib/ directory.
1728
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001729 keywords = {
Ezio Melottib185a042011-04-28 07:42:55 +03001730 'False': '',
1731 'None': '',
1732 'True': '',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001733 'and': 'BOOLEAN',
Guido van Rossumd8faa362007-04-27 19:54:29 +00001734 'as': 'with',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001735 'assert': ('assert', ''),
Jelle Zijlstraac317702017-10-05 20:24:46 -07001736 'async': ('async', ''),
1737 'await': ('await', ''),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001738 'break': ('break', 'while for'),
1739 'class': ('class', 'CLASSES SPECIALMETHODS'),
1740 'continue': ('continue', 'while for'),
1741 'def': ('function', ''),
1742 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001743 'elif': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001744 'else': ('else', 'while for'),
Georg Brandl0d855392008-08-30 19:53:05 +00001745 'except': 'try',
1746 'finally': 'try',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001747 'for': ('for', 'break continue while'),
Georg Brandl0d855392008-08-30 19:53:05 +00001748 'from': 'import',
Georg Brandl74abf6f2010-11-20 19:54:36 +00001749 'global': ('global', 'nonlocal NAMESPACES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001750 'if': ('if', 'TRUTHVALUE'),
1751 'import': ('import', 'MODULES'),
Georg Brandl395ed242009-09-04 08:07:32 +00001752 'in': ('in', 'SEQUENCEMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001753 'is': 'COMPARISON',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001754 'lambda': ('lambda', 'FUNCTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001755 'nonlocal': ('nonlocal', 'global NAMESPACES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001756 'not': 'BOOLEAN',
1757 'or': 'BOOLEAN',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001758 'pass': ('pass', ''),
1759 'raise': ('raise', 'EXCEPTIONS'),
1760 'return': ('return', 'FUNCTIONS'),
1761 'try': ('try', 'EXCEPTIONS'),
1762 'while': ('while', 'break continue if TRUTHVALUE'),
1763 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1764 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001765 }
Georg Brandldb7b6b92009-01-01 15:53:14 +00001766 # Either add symbols to this dictionary or to the symbols dictionary
1767 # directly: Whichever is easier. They are merged later.
Andrés Delfinob2043bb2018-05-05 13:07:32 -03001768 _strprefixes = [p + q for p in ('b', 'f', 'r', 'u') for q in ("'", '"')]
Georg Brandldb7b6b92009-01-01 15:53:14 +00001769 _symbols_inverse = {
Andrés Delfinob2043bb2018-05-05 13:07:32 -03001770 'STRINGS' : ("'", "'''", '"', '"""', *_strprefixes),
Georg Brandldb7b6b92009-01-01 15:53:14 +00001771 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1772 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1773 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1774 'UNARY' : ('-', '~'),
1775 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1776 '^=', '<<=', '>>=', '**=', '//='),
1777 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1778 'COMPLEX' : ('j', 'J')
1779 }
1780 symbols = {
1781 '%': 'OPERATORS FORMATTING',
1782 '**': 'POWER',
1783 ',': 'TUPLES LISTS FUNCTIONS',
1784 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1785 '...': 'ELLIPSIS',
1786 ':': 'SLICINGS DICTIONARYLITERALS',
1787 '@': 'def class',
1788 '\\': 'STRINGS',
1789 '_': 'PRIVATENAMES',
1790 '__': 'PRIVATENAMES SPECIALMETHODS',
1791 '`': 'BACKQUOTES',
1792 '(': 'TUPLES FUNCTIONS CALLS',
1793 ')': 'TUPLES FUNCTIONS CALLS',
1794 '[': 'LISTS SUBSCRIPTS SLICINGS',
1795 ']': 'LISTS SUBSCRIPTS SLICINGS'
1796 }
1797 for topic, symbols_ in _symbols_inverse.items():
1798 for symbol in symbols_:
1799 topics = symbols.get(symbol, topic)
1800 if topic not in topics:
1801 topics = topics + ' ' + topic
1802 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001803
1804 topics = {
Georg Brandl6b38daa2008-06-01 21:05:17 +00001805 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1806 'FUNCTIONS CLASSES MODULES FILES inspect'),
1807 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS '
1808 'FORMATTING TYPES'),
1809 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1810 'FORMATTING': ('formatstrings', 'OPERATORS'),
1811 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1812 'FORMATTING TYPES'),
1813 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1814 'INTEGER': ('integers', 'int range'),
1815 'FLOAT': ('floating', 'float math'),
1816 'COMPLEX': ('imaginary', 'complex cmath'),
1817 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING range LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001818 'MAPPINGS': 'DICTIONARIES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001819 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1820 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1821 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1822 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001823 'FRAMEOBJECTS': 'TYPES',
1824 'TRACEBACKS': 'TYPES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001825 'NONE': ('bltin-null-object', ''),
1826 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001827 'SPECIALATTRIBUTES': ('specialattrs', ''),
1828 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1829 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001830 'PACKAGES': 'import',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001831 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1832 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1833 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1834 'LISTS DICTIONARIES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001835 'OPERATORS': 'EXPRESSIONS',
1836 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001837 'OBJECTS': ('objects', 'TYPES'),
1838 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
Georg Brandl395ed242009-09-04 08:07:32 +00001839 'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS '
1840 'NUMBERMETHODS CLASSES'),
Mark Dickinsona56c4672009-01-27 18:17:45 +00001841 'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001842 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1843 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001844 'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS '
Georg Brandl6b38daa2008-06-01 21:05:17 +00001845 'SPECIALMETHODS'),
1846 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1847 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1848 'SPECIALMETHODS'),
1849 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001850 'NAMESPACES': ('naming', 'global nonlocal ASSIGNMENT DELETION DYNAMICFEATURES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001851 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001852 'SCOPING': 'NAMESPACES',
1853 'FRAMES': 'NAMESPACES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001854 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1855 'CONVERSIONS': ('conversions', ''),
1856 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1857 'SPECIALIDENTIFIERS': ('id-classes', ''),
1858 'PRIVATENAMES': ('atom-identifiers', ''),
1859 'LITERALS': ('atom-literals', 'STRINGS NUMBERS TUPLELITERALS '
1860 'LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001861 'TUPLES': 'SEQUENCES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001862 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1863 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1864 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1865 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1866 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1867 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001868 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'),
1869 'SLICINGS': ('slicings', 'SEQUENCEMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001870 'CALLS': ('calls', 'EXPRESSIONS'),
1871 'POWER': ('power', 'EXPRESSIONS'),
1872 'UNARY': ('unary', 'EXPRESSIONS'),
1873 'BINARY': ('binary', 'EXPRESSIONS'),
1874 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1875 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1876 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1877 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001878 'ASSERTION': 'assert',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001879 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1880 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001881 'DELETION': 'del',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001882 'RETURNING': 'return',
1883 'IMPORTING': 'import',
1884 'CONDITIONAL': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001885 'LOOPING': ('compound', 'for while break continue'),
1886 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1887 'DEBUGGING': ('debugger', 'pdb'),
1888 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001889 }
1890
Georg Brandl78aa3962010-07-31 21:51:48 +00001891 def __init__(self, input=None, output=None):
1892 self._input = input
1893 self._output = output
1894
Serhiy Storchakabdf6b912017-03-19 08:40:32 +02001895 @property
1896 def input(self):
1897 return self._input or sys.stdin
1898
1899 @property
1900 def output(self):
1901 return self._output or sys.stdout
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001902
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001903 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001904 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001905 self()
1906 return ''
Serhiy Storchaka465e60e2014-07-25 23:36:00 +03001907 return '<%s.%s instance>' % (self.__class__.__module__,
1908 self.__class__.__qualname__)
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001909
Alexander Belopolsky2e733c92010-07-04 17:00:20 +00001910 _GoInteractive = object()
1911 def __call__(self, request=_GoInteractive):
1912 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001913 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001914 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001915 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001916 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001917 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001918You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001919If you want to ask for help on a particular object directly from the
1920interpreter, you can type "help(object)". Executing "help('string')"
1921has the same effect as typing a particular string at the help> prompt.
1922''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001923
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001924 def interact(self):
1925 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001926 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001927 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001928 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001929 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001930 except (KeyboardInterrupt, EOFError):
1931 break
Andrés Delfinob2043bb2018-05-05 13:07:32 -03001932 request = request.strip()
1933
1934 # Make sure significant trailing quoting marks of literals don't
1935 # get deleted while cleaning input
1936 if (len(request) > 2 and request[0] == request[-1] in ("'", '"')
1937 and request[0] not in request[1:-1]):
1938 request = request[1:-1]
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001939 if request.lower() in ('q', 'quit'): break
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001940 if request == 'help':
1941 self.intro()
1942 else:
1943 self.help(request)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001944
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001945 def getline(self, prompt):
Guido van Rossum7c086c02008-01-02 03:52:38 +00001946 """Read one line, using input() when appropriate."""
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001947 if self.input is sys.stdin:
Guido van Rossum7c086c02008-01-02 03:52:38 +00001948 return input(prompt)
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001949 else:
1950 self.output.write(prompt)
1951 self.output.flush()
1952 return self.input.readline()
1953
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001954 def help(self, request):
1955 if type(request) is type(''):
R. David Murray1f1b9d32009-05-27 20:56:59 +00001956 request = request.strip()
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001957 if request == 'keywords': self.listkeywords()
Georg Brandldb7b6b92009-01-01 15:53:14 +00001958 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001959 elif request == 'topics': self.listtopics()
1960 elif request == 'modules': self.listmodules()
1961 elif request[:8] == 'modules ':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001962 self.listmodules(request.split()[1])
Georg Brandldb7b6b92009-01-01 15:53:14 +00001963 elif request in self.symbols: self.showsymbol(request)
Ezio Melottib185a042011-04-28 07:42:55 +03001964 elif request in ['True', 'False', 'None']:
1965 # special case these keywords since they are objects too
1966 doc(eval(request), 'Help on %s:')
Raymond Hettinger54f02222002-06-01 14:18:47 +00001967 elif request in self.keywords: self.showtopic(request)
1968 elif request in self.topics: self.showtopic(request)
Georg Brandld80d5f42010-12-03 07:47:22 +00001969 elif request: doc(request, 'Help on %s:', output=self._output)
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001970 else: doc(str, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001971 elif isinstance(request, Helper): self()
Georg Brandld80d5f42010-12-03 07:47:22 +00001972 else: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001973 self.output.write('\n')
1974
1975 def intro(self):
1976 self.output.write('''
Serhiy Storchaka885bdc42016-02-11 13:10:36 +02001977Welcome to Python {0}'s help utility!
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001978
1979If this is your first time using Python, you should definitely check out
oldke5681b92017-12-28 22:37:46 +08001980the tutorial on the Internet at https://docs.python.org/{0}/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001981
1982Enter the name of any module, keyword, or topic to get help on writing
1983Python programs and using Python modules. To quit this help utility and
1984return to the interpreter, just type "quit".
1985
Terry Jan Reedy34200572013-02-11 02:23:13 -05001986To get a list of available modules, keywords, symbols, or topics, type
1987"modules", "keywords", "symbols", or "topics". Each module also comes
1988with a one-line summary of what it does; to list the modules whose name
1989or summary contain a given string such as "spam", type "modules spam".
Serhiy Storchaka885bdc42016-02-11 13:10:36 +02001990'''.format('%d.%d' % sys.version_info[:2]))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001991
1992 def list(self, items, columns=4, width=80):
Guido van Rossum486364b2007-06-30 05:01:58 +00001993 items = list(sorted(items))
1994 colw = width // columns
1995 rows = (len(items) + columns - 1) // columns
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001996 for row in range(rows):
1997 for col in range(columns):
1998 i = col * rows + row
1999 if i < len(items):
2000 self.output.write(items[i])
2001 if col < columns - 1:
Guido van Rossum486364b2007-06-30 05:01:58 +00002002 self.output.write(' ' + ' ' * (colw - 1 - len(items[i])))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002003 self.output.write('\n')
2004
2005 def listkeywords(self):
2006 self.output.write('''
2007Here is a list of the Python keywords. Enter any keyword to get more help.
2008
2009''')
2010 self.list(self.keywords.keys())
2011
Georg Brandldb7b6b92009-01-01 15:53:14 +00002012 def listsymbols(self):
2013 self.output.write('''
2014Here is a list of the punctuation symbols which Python assigns special meaning
2015to. Enter any symbol to get more help.
2016
2017''')
2018 self.list(self.symbols.keys())
2019
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002020 def listtopics(self):
2021 self.output.write('''
2022Here is a list of available topics. Enter any topic name to get more help.
2023
2024''')
2025 self.list(self.topics.keys())
2026
Georg Brandldb7b6b92009-01-01 15:53:14 +00002027 def showtopic(self, topic, more_xrefs=''):
Georg Brandl6b38daa2008-06-01 21:05:17 +00002028 try:
Georg Brandl5617db82009-04-27 16:28:57 +00002029 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04002030 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002031 self.output.write('''
Georg Brandl6b38daa2008-06-01 21:05:17 +00002032Sorry, topic and keyword documentation is not available because the
Georg Brandl5617db82009-04-27 16:28:57 +00002033module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002034''')
2035 return
2036 target = self.topics.get(topic, self.keywords.get(topic))
2037 if not target:
2038 self.output.write('no documentation found for %s\n' % repr(topic))
2039 return
2040 if type(target) is type(''):
Georg Brandldb7b6b92009-01-01 15:53:14 +00002041 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002042
Georg Brandl6b38daa2008-06-01 21:05:17 +00002043 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002044 try:
Georg Brandl5617db82009-04-27 16:28:57 +00002045 doc = pydoc_data.topics.topics[label]
Georg Brandl6b38daa2008-06-01 21:05:17 +00002046 except KeyError:
2047 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002048 return
Berker Peksagd04f46c2018-07-23 08:37:47 +03002049 doc = doc.strip() + '\n'
Georg Brandldb7b6b92009-01-01 15:53:14 +00002050 if more_xrefs:
2051 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00002052 if xrefs:
Brett Cannon1448ecf2013-10-04 11:38:59 -04002053 import textwrap
2054 text = 'Related help topics: ' + ', '.join(xrefs.split()) + '\n'
2055 wrapped_text = textwrap.wrap(text, 72)
Berker Peksagd04f46c2018-07-23 08:37:47 +03002056 doc += '\n%s\n' % '\n'.join(wrapped_text)
2057 pager(doc)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002058
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002059 def _gettopic(self, topic, more_xrefs=''):
2060 """Return unbuffered tuple of (topic, xrefs).
2061
Georg Brandld2f38572011-01-30 08:37:19 +00002062 If an error occurs here, the exception is caught and displayed by
2063 the url handler.
2064
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002065 This function duplicates the showtopic method but returns its
2066 result directly so it can be formatted for display in an html page.
2067 """
2068 try:
2069 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04002070 except ImportError:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002071 return('''
2072Sorry, topic and keyword documentation is not available because the
2073module "pydoc_data.topics" could not be found.
2074''' , '')
2075 target = self.topics.get(topic, self.keywords.get(topic))
2076 if not target:
Georg Brandld2f38572011-01-30 08:37:19 +00002077 raise ValueError('could not find topic')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002078 if isinstance(target, str):
2079 return self._gettopic(target, more_xrefs)
2080 label, xrefs = target
Georg Brandld2f38572011-01-30 08:37:19 +00002081 doc = pydoc_data.topics.topics[label]
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002082 if more_xrefs:
2083 xrefs = (xrefs or '') + ' ' + more_xrefs
2084 return doc, xrefs
2085
Georg Brandldb7b6b92009-01-01 15:53:14 +00002086 def showsymbol(self, symbol):
2087 target = self.symbols[symbol]
2088 topic, _, xrefs = target.partition(' ')
2089 self.showtopic(topic, xrefs)
2090
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002091 def listmodules(self, key=''):
2092 if key:
2093 self.output.write('''
Terry Jan Reedy34200572013-02-11 02:23:13 -05002094Here is a list of modules whose name or summary contains '{}'.
2095If there are any, enter a module name to get more help.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002096
Terry Jan Reedy34200572013-02-11 02:23:13 -05002097'''.format(key))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002098 apropos(key)
2099 else:
2100 self.output.write('''
2101Please wait a moment while I gather a list of all available modules...
2102
2103''')
2104 modules = {}
2105 def callback(path, modname, desc, modules=modules):
2106 if modname and modname[-9:] == '.__init__':
2107 modname = modname[:-9] + ' (package)'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002108 if modname.find('.') < 0:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002109 modules[modname] = 1
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002110 def onerror(modname):
2111 callback(None, modname, None)
2112 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002113 self.list(modules.keys())
2114 self.output.write('''
2115Enter any module name to get more help. Or, type "modules spam" to search
Terry Jan Reedy34200572013-02-11 02:23:13 -05002116for modules whose name or summary contain the string "spam".
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002117''')
2118
Georg Brandl78aa3962010-07-31 21:51:48 +00002119help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002120
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002121class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002122 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002123
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002124 def run(self, callback, key=None, completer=None, onerror=None):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002125 if key: key = key.lower()
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002126 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002127 seen = {}
2128
2129 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002130 if modname != '__main__':
2131 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00002132 if key is None:
2133 callback(None, modname, '')
2134 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002135 name = __import__(modname).__doc__ or ''
2136 desc = name.split('\n')[0]
2137 name = modname + ' - ' + desc
2138 if name.lower().find(key) >= 0:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002139 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002140
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002141 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002142 if self.quit:
2143 break
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002144
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002145 if key is None:
2146 callback(None, modname, '')
2147 else:
Georg Brandl126c8792009-04-05 15:05:48 +00002148 try:
Eric Snow3a62d142014-01-06 20:42:59 -07002149 spec = pkgutil._get_spec(importer, modname)
Georg Brandl126c8792009-04-05 15:05:48 +00002150 except SyntaxError:
2151 # raised by tests for bad coding cookies or BOM
2152 continue
Eric Snow3a62d142014-01-06 20:42:59 -07002153 loader = spec.loader
Georg Brandl126c8792009-04-05 15:05:48 +00002154 if hasattr(loader, 'get_source'):
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002155 try:
2156 source = loader.get_source(modname)
Nick Coghlan2824cb52012-07-15 22:12:14 +10002157 except Exception:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002158 if onerror:
2159 onerror(modname)
2160 continue
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002161 desc = source_synopsis(io.StringIO(source)) or ''
Georg Brandl126c8792009-04-05 15:05:48 +00002162 if hasattr(loader, 'get_filename'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002163 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002164 else:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002165 path = None
2166 else:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002167 try:
Brett Cannon2a17bde2014-05-30 14:55:29 -04002168 module = importlib._bootstrap._load(spec)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002169 except ImportError:
2170 if onerror:
2171 onerror(modname)
2172 continue
Benjamin Peterson54237f92015-02-16 19:45:01 -05002173 desc = module.__doc__.splitlines()[0] if module.__doc__ else ''
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002174 path = getattr(module,'__file__',None)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002175 name = modname + ' - ' + desc
2176 if name.lower().find(key) >= 0:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002177 callback(path, modname, desc)
2178
2179 if completer:
2180 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002181
2182def apropos(key):
2183 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002184 def callback(path, modname, desc):
2185 if modname[-9:] == '.__init__':
2186 modname = modname[:-9] + ' (package)'
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002187 print(modname, desc and '- ' + desc)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002188 def onerror(modname):
2189 pass
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002190 with warnings.catch_warnings():
2191 warnings.filterwarnings('ignore') # ignore problems during import
2192 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002193
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002194# --------------------------------------- enhanced Web browser interface
2195
Feanil Patel6a396c92017-09-14 17:54:09 -04002196def _start_server(urlhandler, hostname, port):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002197 """Start an HTTP server thread on a specific port.
2198
2199 Start an HTML/text server thread, so HTML or text documents can be
2200 browsed dynamically and interactively with a Web browser. Example use:
2201
2202 >>> import time
2203 >>> import pydoc
2204
2205 Define a URL handler. To determine what the client is asking
2206 for, check the URL and content_type.
2207
2208 Then get or generate some text or HTML code and return it.
2209
2210 >>> def my_url_handler(url, content_type):
2211 ... text = 'the URL sent was: (%s, %s)' % (url, content_type)
2212 ... return text
2213
2214 Start server thread on port 0.
2215 If you use port 0, the server will pick a random port number.
2216 You can then use serverthread.port to get the port number.
2217
2218 >>> port = 0
2219 >>> serverthread = pydoc._start_server(my_url_handler, port)
2220
2221 Check that the server is really started. If it is, open browser
2222 and get first page. Use serverthread.url as the starting page.
2223
2224 >>> if serverthread.serving:
2225 ... import webbrowser
2226
2227 The next two lines are commented out so a browser doesn't open if
2228 doctest is run on this module.
2229
2230 #... webbrowser.open(serverthread.url)
2231 #True
2232
2233 Let the server do its thing. We just need to monitor its status.
2234 Use time.sleep so the loop doesn't hog the CPU.
2235
2236 >>> starttime = time.time()
2237 >>> timeout = 1 #seconds
2238
2239 This is a short timeout for testing purposes.
2240
2241 >>> while serverthread.serving:
2242 ... time.sleep(.01)
2243 ... if serverthread.serving and time.time() - starttime > timeout:
2244 ... serverthread.stop()
2245 ... break
2246
2247 Print any errors that may have occurred.
2248
2249 >>> print(serverthread.error)
2250 None
2251 """
2252 import http.server
2253 import email.message
2254 import select
2255 import threading
2256
2257 class DocHandler(http.server.BaseHTTPRequestHandler):
2258
2259 def do_GET(self):
2260 """Process a request from an HTML browser.
2261
2262 The URL received is in self.path.
2263 Get an HTML page from self.urlhandler and send it.
2264 """
2265 if self.path.endswith('.css'):
2266 content_type = 'text/css'
2267 else:
2268 content_type = 'text/html'
2269 self.send_response(200)
Georg Brandld2f38572011-01-30 08:37:19 +00002270 self.send_header('Content-Type', '%s; charset=UTF-8' % content_type)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002271 self.end_headers()
2272 self.wfile.write(self.urlhandler(
2273 self.path, content_type).encode('utf-8'))
2274
2275 def log_message(self, *args):
2276 # Don't log messages.
2277 pass
2278
2279 class DocServer(http.server.HTTPServer):
2280
Feanil Patel6a396c92017-09-14 17:54:09 -04002281 def __init__(self, host, port, callback):
2282 self.host = host
Senthil Kumaran2a42a0b2014-09-17 13:17:58 +08002283 self.address = (self.host, port)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002284 self.callback = callback
2285 self.base.__init__(self, self.address, self.handler)
2286 self.quit = False
2287
2288 def serve_until_quit(self):
2289 while not self.quit:
2290 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2291 if rd:
2292 self.handle_request()
Victor Stinnera3abd1d2011-01-03 16:12:39 +00002293 self.server_close()
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002294
2295 def server_activate(self):
2296 self.base.server_activate(self)
2297 if self.callback:
2298 self.callback(self)
2299
2300 class ServerThread(threading.Thread):
2301
Feanil Patel6a396c92017-09-14 17:54:09 -04002302 def __init__(self, urlhandler, host, port):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002303 self.urlhandler = urlhandler
Feanil Patel6a396c92017-09-14 17:54:09 -04002304 self.host = host
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002305 self.port = int(port)
2306 threading.Thread.__init__(self)
2307 self.serving = False
2308 self.error = None
2309
2310 def run(self):
2311 """Start the server."""
2312 try:
2313 DocServer.base = http.server.HTTPServer
2314 DocServer.handler = DocHandler
2315 DocHandler.MessageClass = email.message.Message
2316 DocHandler.urlhandler = staticmethod(self.urlhandler)
Feanil Patel6a396c92017-09-14 17:54:09 -04002317 docsvr = DocServer(self.host, self.port, self.ready)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002318 self.docserver = docsvr
2319 docsvr.serve_until_quit()
2320 except Exception as e:
2321 self.error = e
2322
2323 def ready(self, server):
2324 self.serving = True
2325 self.host = server.host
2326 self.port = server.server_port
2327 self.url = 'http://%s:%d/' % (self.host, self.port)
2328
2329 def stop(self):
2330 """Stop the server and this thread nicely"""
2331 self.docserver.quit = True
Victor Stinner4cab2cd2017-08-21 23:24:40 +02002332 self.join()
2333 # explicitly break a reference cycle: DocServer.callback
2334 # has indirectly a reference to ServerThread.
2335 self.docserver = None
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002336 self.serving = False
2337 self.url = None
2338
Feanil Patel6a396c92017-09-14 17:54:09 -04002339 thread = ServerThread(urlhandler, hostname, port)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002340 thread.start()
2341 # Wait until thread.serving is True to make sure we are
2342 # really up before returning.
2343 while not thread.error and not thread.serving:
2344 time.sleep(.01)
2345 return thread
2346
2347
2348def _url_handler(url, content_type="text/html"):
2349 """The pydoc url handler for use with the pydoc server.
2350
2351 If the content_type is 'text/css', the _pydoc.css style
2352 sheet is read and returned if it exits.
2353
2354 If the content_type is 'text/html', then the result of
2355 get_html_page(url) is returned.
2356 """
2357 class _HTMLDoc(HTMLDoc):
2358
2359 def page(self, title, contents):
2360 """Format an HTML page."""
2361 css_path = "pydoc_data/_pydoc.css"
2362 css_link = (
2363 '<link rel="stylesheet" type="text/css" href="%s">' %
2364 css_path)
2365 return '''\
2366<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Georg Brandld2f38572011-01-30 08:37:19 +00002367<html><head><title>Pydoc: %s</title>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002368<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Georg Brandld2f38572011-01-30 08:37:19 +00002369%s</head><body bgcolor="#f0f0f8">%s<div style="clear:both;padding-top:.5em;">%s</div>
2370</body></html>''' % (title, css_link, html_navbar(), contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002371
2372 def filelink(self, url, path):
2373 return '<a href="getfile?key=%s">%s</a>' % (url, path)
2374
2375
2376 html = _HTMLDoc()
2377
2378 def html_navbar():
Georg Brandld2f38572011-01-30 08:37:19 +00002379 version = html.escape("%s [%s, %s]" % (platform.python_version(),
2380 platform.python_build()[0],
2381 platform.python_compiler()))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002382 return """
2383 <div style='float:left'>
Georg Brandld2f38572011-01-30 08:37:19 +00002384 Python %s<br>%s
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002385 </div>
2386 <div style='float:right'>
2387 <div style='text-align:center'>
2388 <a href="index.html">Module Index</a>
2389 : <a href="topics.html">Topics</a>
2390 : <a href="keywords.html">Keywords</a>
2391 </div>
2392 <div>
Georg Brandld2f38572011-01-30 08:37:19 +00002393 <form action="get" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002394 <input type=text name=key size=15>
2395 <input type=submit value="Get">
Georg Brandld2f38572011-01-30 08:37:19 +00002396 </form>&nbsp;
2397 <form action="search" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002398 <input type=text name=key size=15>
2399 <input type=submit value="Search">
2400 </form>
2401 </div>
2402 </div>
Georg Brandld2f38572011-01-30 08:37:19 +00002403 """ % (version, html.escape(platform.platform(terse=True)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002404
2405 def html_index():
2406 """Module Index page."""
2407
2408 def bltinlink(name):
2409 return '<a href="%s.html">%s</a>' % (name, name)
2410
2411 heading = html.heading(
2412 '<big><big><strong>Index of Modules</strong></big></big>',
2413 '#ffffff', '#7799ee')
2414 names = [name for name in sys.builtin_module_names
2415 if name != '__main__']
2416 contents = html.multicolumn(names, bltinlink)
2417 contents = [heading, '<p>' + html.bigsection(
2418 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2419
2420 seen = {}
2421 for dir in sys.path:
2422 contents.append(html.index(dir, seen))
2423
2424 contents.append(
2425 '<p align=right><font color="#909090" face="helvetica,'
2426 'arial"><strong>pydoc</strong> by Ka-Ping Yee'
2427 '&lt;ping@lfw.org&gt;</font>')
Nick Coghlanecace282010-12-03 16:08:46 +00002428 return 'Index of Modules', ''.join(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002429
2430 def html_search(key):
2431 """Search results page."""
2432 # scan for modules
2433 search_result = []
2434
2435 def callback(path, modname, desc):
2436 if modname[-9:] == '.__init__':
2437 modname = modname[:-9] + ' (package)'
2438 search_result.append((modname, desc and '- ' + desc))
2439
2440 with warnings.catch_warnings():
2441 warnings.filterwarnings('ignore') # ignore problems during import
Martin Panter9ad0aae2015-11-06 00:27:14 +00002442 def onerror(modname):
2443 pass
2444 ModuleScanner().run(callback, key, onerror=onerror)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002445
2446 # format page
2447 def bltinlink(name):
2448 return '<a href="%s.html">%s</a>' % (name, name)
2449
2450 results = []
2451 heading = html.heading(
2452 '<big><big><strong>Search Results</strong></big></big>',
2453 '#ffffff', '#7799ee')
2454 for name, desc in search_result:
2455 results.append(bltinlink(name) + desc)
2456 contents = heading + html.bigsection(
2457 'key = %s' % key, '#ffffff', '#ee77aa', '<br>'.join(results))
Nick Coghlanecace282010-12-03 16:08:46 +00002458 return 'Search Results', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002459
2460 def html_getfile(path):
2461 """Get and display a source file listing safely."""
Zachary Wareeb432142014-07-10 11:18:00 -05002462 path = urllib.parse.unquote(path)
Victor Stinner91e08772011-07-05 14:30:41 +02002463 with tokenize.open(path) as fp:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002464 lines = html.escape(fp.read())
2465 body = '<pre>%s</pre>' % lines
2466 heading = html.heading(
2467 '<big><big><strong>File Listing</strong></big></big>',
2468 '#ffffff', '#7799ee')
2469 contents = heading + html.bigsection(
2470 'File: %s' % path, '#ffffff', '#ee77aa', body)
Nick Coghlanecace282010-12-03 16:08:46 +00002471 return 'getfile %s' % path, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002472
2473 def html_topics():
2474 """Index of topic texts available."""
2475
2476 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002477 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002478
2479 heading = html.heading(
2480 '<big><big><strong>INDEX</strong></big></big>',
2481 '#ffffff', '#7799ee')
2482 names = sorted(Helper.topics.keys())
2483
2484 contents = html.multicolumn(names, bltinlink)
2485 contents = heading + html.bigsection(
2486 'Topics', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002487 return 'Topics', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002488
2489 def html_keywords():
2490 """Index of keywords."""
2491 heading = html.heading(
2492 '<big><big><strong>INDEX</strong></big></big>',
2493 '#ffffff', '#7799ee')
2494 names = sorted(Helper.keywords.keys())
2495
2496 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002497 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002498
2499 contents = html.multicolumn(names, bltinlink)
2500 contents = heading + html.bigsection(
2501 'Keywords', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002502 return 'Keywords', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002503
2504 def html_topicpage(topic):
2505 """Topic or keyword help page."""
2506 buf = io.StringIO()
2507 htmlhelp = Helper(buf, buf)
2508 contents, xrefs = htmlhelp._gettopic(topic)
2509 if topic in htmlhelp.keywords:
2510 title = 'KEYWORD'
2511 else:
2512 title = 'TOPIC'
2513 heading = html.heading(
2514 '<big><big><strong>%s</strong></big></big>' % title,
2515 '#ffffff', '#7799ee')
Georg Brandld2f38572011-01-30 08:37:19 +00002516 contents = '<pre>%s</pre>' % html.markup(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002517 contents = html.bigsection(topic , '#ffffff','#ee77aa', contents)
Georg Brandld2f38572011-01-30 08:37:19 +00002518 if xrefs:
2519 xrefs = sorted(xrefs.split())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002520
Georg Brandld2f38572011-01-30 08:37:19 +00002521 def bltinlink(name):
2522 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002523
Georg Brandld2f38572011-01-30 08:37:19 +00002524 xrefs = html.multicolumn(xrefs, bltinlink)
2525 xrefs = html.section('Related help topics: ',
2526 '#ffffff', '#ee77aa', xrefs)
Nick Coghlanecace282010-12-03 16:08:46 +00002527 return ('%s %s' % (title, topic),
2528 ''.join((heading, contents, xrefs)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002529
Georg Brandld2f38572011-01-30 08:37:19 +00002530 def html_getobj(url):
2531 obj = locate(url, forceload=1)
2532 if obj is None and url != 'None':
2533 raise ValueError('could not find object')
2534 title = describe(obj)
2535 content = html.document(obj, url)
2536 return title, content
2537
2538 def html_error(url, exc):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002539 heading = html.heading(
2540 '<big><big><strong>Error</strong></big></big>',
Georg Brandld2f38572011-01-30 08:37:19 +00002541 '#ffffff', '#7799ee')
2542 contents = '<br>'.join(html.escape(line) for line in
2543 format_exception_only(type(exc), exc))
2544 contents = heading + html.bigsection(url, '#ffffff', '#bb0000',
2545 contents)
2546 return "Error - %s" % url, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002547
2548 def get_html_page(url):
2549 """Generate an HTML page for url."""
Georg Brandld2f38572011-01-30 08:37:19 +00002550 complete_url = url
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002551 if url.endswith('.html'):
2552 url = url[:-5]
Georg Brandld2f38572011-01-30 08:37:19 +00002553 try:
2554 if url in ("", "index"):
2555 title, content = html_index()
2556 elif url == "topics":
2557 title, content = html_topics()
2558 elif url == "keywords":
2559 title, content = html_keywords()
2560 elif '=' in url:
2561 op, _, url = url.partition('=')
2562 if op == "search?key":
2563 title, content = html_search(url)
2564 elif op == "getfile?key":
2565 title, content = html_getfile(url)
2566 elif op == "topic?key":
2567 # try topics first, then objects.
2568 try:
2569 title, content = html_topicpage(url)
2570 except ValueError:
2571 title, content = html_getobj(url)
2572 elif op == "get?key":
2573 # try objects first, then topics.
2574 if url in ("", "index"):
2575 title, content = html_index()
2576 else:
2577 try:
2578 title, content = html_getobj(url)
2579 except ValueError:
2580 title, content = html_topicpage(url)
2581 else:
2582 raise ValueError('bad pydoc url')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002583 else:
Georg Brandld2f38572011-01-30 08:37:19 +00002584 title, content = html_getobj(url)
2585 except Exception as exc:
2586 # Catch any errors and display them in an error page.
2587 title, content = html_error(complete_url, exc)
2588 return html.page(title, content)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002589
2590 if url.startswith('/'):
2591 url = url[1:]
2592 if content_type == 'text/css':
2593 path_here = os.path.dirname(os.path.realpath(__file__))
Georg Brandld2f38572011-01-30 08:37:19 +00002594 css_path = os.path.join(path_here, url)
2595 with open(css_path) as fp:
2596 return ''.join(fp.readlines())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002597 elif content_type == 'text/html':
2598 return get_html_page(url)
Georg Brandld2f38572011-01-30 08:37:19 +00002599 # Errors outside the url handler are caught by the server.
2600 raise TypeError('unknown content type %r for url %s' % (content_type, url))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002601
2602
Feanil Patel6a396c92017-09-14 17:54:09 -04002603def browse(port=0, *, open_browser=True, hostname='localhost'):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002604 """Start the enhanced pydoc Web server and open a Web browser.
2605
2606 Use port '0' to start the server on an arbitrary port.
2607 Set open_browser to False to suppress opening a browser.
2608 """
2609 import webbrowser
Feanil Patel6a396c92017-09-14 17:54:09 -04002610 serverthread = _start_server(_url_handler, hostname, port)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002611 if serverthread.error:
2612 print(serverthread.error)
2613 return
2614 if serverthread.serving:
2615 server_help_msg = 'Server commands: [b]rowser, [q]uit'
2616 if open_browser:
2617 webbrowser.open(serverthread.url)
2618 try:
2619 print('Server ready at', serverthread.url)
2620 print(server_help_msg)
2621 while serverthread.serving:
2622 cmd = input('server> ')
2623 cmd = cmd.lower()
2624 if cmd == 'q':
2625 break
2626 elif cmd == 'b':
2627 webbrowser.open(serverthread.url)
2628 else:
2629 print(server_help_msg)
2630 except (KeyboardInterrupt, EOFError):
2631 print()
2632 finally:
2633 if serverthread.serving:
2634 serverthread.stop()
2635 print('Server stopped')
2636
2637
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002638# -------------------------------------------------- command-line interface
2639
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002640def ispath(x):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002641 return isinstance(x, str) and x.find(os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002642
Nick Coghlan82a94812018-04-15 21:52:57 +10002643def _get_revised_path(given_path, argv0):
2644 """Ensures current directory is on returned path, and argv0 directory is not
2645
2646 Exception: argv0 dir is left alone if it's also pydoc's directory.
2647
2648 Returns a new path entry list, or None if no adjustment is needed.
2649 """
2650 # Scripts may get the current directory in their path by default if they're
2651 # run with the -m switch, or directly from the current directory.
2652 # The interactive prompt also allows imports from the current directory.
2653
2654 # Accordingly, if the current directory is already present, don't make
2655 # any changes to the given_path
2656 if '' in given_path or os.curdir in given_path or os.getcwd() in given_path:
2657 return None
2658
2659 # Otherwise, add the current directory to the given path, and remove the
2660 # script directory (as long as the latter isn't also pydoc's directory.
2661 stdlib_dir = os.path.dirname(__file__)
2662 script_dir = os.path.dirname(argv0)
2663 revised_path = given_path.copy()
2664 if script_dir in given_path and not os.path.samefile(script_dir, stdlib_dir):
2665 revised_path.remove(script_dir)
2666 revised_path.insert(0, os.getcwd())
2667 return revised_path
2668
2669
2670# Note: the tests only cover _get_revised_path, not _adjust_cli_path itself
2671def _adjust_cli_sys_path():
Nick Coghlan1a5c4bd2018-04-15 23:32:05 +10002672 """Ensures current directory is on sys.path, and __main__ directory is not.
Nick Coghlan82a94812018-04-15 21:52:57 +10002673
2674 Exception: __main__ dir is left alone if it's also pydoc's directory.
2675 """
2676 revised_path = _get_revised_path(sys.path, sys.argv[0])
2677 if revised_path is not None:
2678 sys.path[:] = revised_path
2679
2680
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002681def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002682 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002683 import getopt
Guido van Rossum756aa932007-04-07 03:04:01 +00002684 class BadUsage(Exception): pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002685
Nick Coghlan82a94812018-04-15 21:52:57 +10002686 _adjust_cli_sys_path()
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002687
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002688 try:
Feanil Patel6a396c92017-09-14 17:54:09 -04002689 opts, args = getopt.getopt(sys.argv[1:], 'bk:n:p:w')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002690 writing = False
2691 start_server = False
2692 open_browser = False
Feanil Patel6a396c92017-09-14 17:54:09 -04002693 port = 0
2694 hostname = 'localhost'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002695 for opt, val in opts:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002696 if opt == '-b':
2697 start_server = True
2698 open_browser = True
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002699 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002700 apropos(val)
2701 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002702 if opt == '-p':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002703 start_server = True
2704 port = val
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002705 if opt == '-w':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002706 writing = True
Feanil Patel6a396c92017-09-14 17:54:09 -04002707 if opt == '-n':
2708 start_server = True
2709 hostname = val
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002710
Benjamin Petersonb29614e2012-10-09 11:16:03 -04002711 if start_server:
Feanil Patel6a396c92017-09-14 17:54:09 -04002712 browse(port, hostname=hostname, open_browser=open_browser)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002713 return
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002714
2715 if not args: raise BadUsage
2716 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002717 if ispath(arg) and not os.path.exists(arg):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002718 print('file %r does not exist' % arg)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002719 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002720 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002721 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002722 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002723 if writing:
2724 if ispath(arg) and os.path.isdir(arg):
2725 writedocs(arg)
2726 else:
2727 writedoc(arg)
2728 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002729 help.help(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +00002730 except ErrorDuringImport as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002731 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002732
2733 except (getopt.error, BadUsage):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002734 cmd = os.path.splitext(os.path.basename(sys.argv[0]))[0]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002735 print("""pydoc - the Python documentation tool
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002736
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002737{cmd} <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002738 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002739 Python keyword, topic, function, module, or package, or a dotted
2740 reference to a class or function within a module or module in a
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002741 package. If <name> contains a '{sep}', it is used as the path to a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002742 Python source file to document. If name is 'keywords', 'topics',
2743 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002744
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002745{cmd} -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002746 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002747
Feanil Patel6a396c92017-09-14 17:54:09 -04002748{cmd} -n <hostname>
2749 Start an HTTP server with the given hostname (default: localhost).
2750
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002751{cmd} -p <port>
2752 Start an HTTP server on the given port on the local machine. Port
2753 number 0 can be used to get an arbitrary unused port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002754
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002755{cmd} -b
2756 Start an HTTP server on an arbitrary unused port and open a Web browser
Feanil Patel6a396c92017-09-14 17:54:09 -04002757 to interactively browse documentation. This option can be used in
2758 combination with -n and/or -p.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002759
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002760{cmd} -w <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002761 Write out the HTML documentation for a module to a file in the current
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002762 directory. If <name> contains a '{sep}', it is treated as a filename; if
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002763 it names a directory, documentation is written for all the contents.
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002764""".format(cmd=cmd, sep=os.sep))
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002765
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002766if __name__ == '__main__':
2767 cli()