blob: d77ed002ecbb871fc679c76a37a17ec172b747b4 [file] [log] [blame]
Benjamin Peterson90f5ba52010-03-11 22:53:45 +00001#!/usr/bin/env python3
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002"""Generate Python documentation in HTML or text for interactive use.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00003
R David Murray3d050dd2014-04-19 12:59:30 -04004At the Python interactive prompt, calling help(thing) on a Python object
5documents the object, and calling help() starts up an interactive
6help session.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00007
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00008Or, at the shell command line outside of Python:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00009
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000010Run "pydoc <name>" to show documentation on something. <name> may be
11the name of a function, module, package, or a dotted reference to a
12class or function within a module or module in a package. If the
13argument contains a path segment delimiter (e.g. slash on Unix,
14backslash on Windows) it is treated as the path to a Python source file.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000015
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000016Run "pydoc -k <keyword>" to search for a keyword in the synopsis lines
17of all available modules.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000018
Nick Coghlan7bb30b72010-12-03 09:29:11 +000019Run "pydoc -p <port>" to start an HTTP server on the given port on the
20local machine. Port number 0 can be used to get an arbitrary unused port.
21
22Run "pydoc -b" to start an HTTP server on an arbitrary unused port and
23open a Web browser to interactively browse documentation. The -p option
24can be used with the -b option to explicitly specify the server port.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000025
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000026Run "pydoc -w <name>" to write out the HTML documentation for a module
27to a file named "<name>.html".
Skip Montanaro4997a692003-09-10 16:47:51 +000028
29Module docs for core modules are assumed to be in
30
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000031 http://docs.python.org/X.Y/library/
Skip Montanaro4997a692003-09-10 16:47:51 +000032
33This can be overridden by setting the PYTHONDOCS environment variable
34to a different URL or to a local directory containing the Library
35Reference Manual pages.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000036"""
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000037__all__ = ['help']
Ka-Ping Yeedd175342001-02-27 14:43:46 +000038__author__ = "Ka-Ping Yee <ping@lfw.org>"
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000039__date__ = "26 February 2001"
Jeremy Hylton3e0055f2005-10-20 19:59:25 +000040
Martin v. Löwis6fe8f192004-11-14 10:21:04 +000041__credits__ = """Guido van Rossum, for an excellent programming language.
Ka-Ping Yee5e2b1732001-02-27 23:35:09 +000042Tommy Burnette, the original creator of manpy.
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000043Paul Prescod, for all his work on onlinehelp.
44Richard Chamberlain, for the first implementation of textdoc.
Raymond Hettingered2dbe32005-01-01 07:51:01 +000045"""
Ka-Ping Yeedd175342001-02-27 14:43:46 +000046
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000047# Known bugs that can't be fixed here:
Brett Cannonf4ba4ec2013-06-15 14:25:04 -040048# - synopsis() cannot be prevented from clobbering existing
49# loaded modules.
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000050# - If the __file__ attribute on a module is a relative path and
51# the current directory is changed with os.chdir(), an incorrect
52# path will be displayed.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000053
Nick Coghlan7bb30b72010-12-03 09:29:11 +000054import builtins
Brett Cannond5e6f2e2013-06-11 17:09:36 -040055import importlib._bootstrap
Brett Cannoncb66eb02012-05-11 12:58:42 -040056import importlib.machinery
Brett Cannonf4ba4ec2013-06-15 14:25:04 -040057import importlib.util
Nick Coghlan7bb30b72010-12-03 09:29:11 +000058import inspect
Victor Stinnere6c910e2011-06-30 15:55:43 +020059import io
60import os
Nick Coghlan7bb30b72010-12-03 09:29:11 +000061import pkgutil
62import platform
63import re
Victor Stinnere6c910e2011-06-30 15:55:43 +020064import sys
Nick Coghlan7bb30b72010-12-03 09:29:11 +000065import time
Victor Stinnere6c910e2011-06-30 15:55:43 +020066import tokenize
Zachary Wareeb432142014-07-10 11:18:00 -050067import urllib.parse
Nick Coghlan7bb30b72010-12-03 09:29:11 +000068import warnings
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000069from collections import deque
Nick Coghlan7bb30b72010-12-03 09:29:11 +000070from reprlib import Repr
Victor Stinner7fa767e2014-03-20 09:16:38 +010071from traceback import format_exception_only
Nick Coghlan7bb30b72010-12-03 09:29:11 +000072
73
Ka-Ping Yeedd175342001-02-27 14:43:46 +000074# --------------------------------------------------------- common routines
75
Ka-Ping Yeedd175342001-02-27 14:43:46 +000076def pathdirs():
77 """Convert sys.path into a list of absolute, existing, unique paths."""
78 dirs = []
Ka-Ping Yee1d384632001-03-01 00:24:32 +000079 normdirs = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +000080 for dir in sys.path:
81 dir = os.path.abspath(dir or '.')
Ka-Ping Yee1d384632001-03-01 00:24:32 +000082 normdir = os.path.normcase(dir)
83 if normdir not in normdirs and os.path.isdir(dir):
Ka-Ping Yeedd175342001-02-27 14:43:46 +000084 dirs.append(dir)
Ka-Ping Yee1d384632001-03-01 00:24:32 +000085 normdirs.append(normdir)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000086 return dirs
87
88def getdoc(object):
89 """Get the doc string or comments for an object."""
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000090 result = inspect.getdoc(object) or inspect.getcomments(object)
Neal Norwitz9d72bb42007-04-17 08:48:32 +000091 return result and re.sub('^ *\n', '', result.rstrip()) or ''
Ka-Ping Yeedd175342001-02-27 14:43:46 +000092
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000093def splitdoc(doc):
94 """Split a doc string into a synopsis line (if any) and the rest."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +000095 lines = doc.strip().split('\n')
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000096 if len(lines) == 1:
97 return lines[0], ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +000098 elif len(lines) >= 2 and not lines[1].rstrip():
99 return lines[0], '\n'.join(lines[2:])
100 return '', '\n'.join(lines)
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000101
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000102def classname(object, modname):
103 """Get a class name and qualify it with a module name if necessary."""
104 name = object.__name__
105 if object.__module__ != modname:
106 name = object.__module__ + '.' + name
107 return name
108
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000109def isdata(object):
Georg Brandl94432422005-07-22 21:52:25 +0000110 """Check if an object is of a type that probably means it's data."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000111 return not (inspect.ismodule(object) or inspect.isclass(object) or
112 inspect.isroutine(object) or inspect.isframe(object) or
113 inspect.istraceback(object) or inspect.iscode(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000114
115def replace(text, *pairs):
116 """Do a series of global replacements on a string."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000117 while pairs:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000118 text = pairs[1].join(text.split(pairs[0]))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000119 pairs = pairs[2:]
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000120 return text
121
122def cram(text, maxlen):
123 """Omit part of a string if needed to make it fit in a maximum length."""
124 if len(text) > maxlen:
Raymond Hettingerfca3bb62002-10-21 04:44:11 +0000125 pre = max(0, (maxlen-3)//2)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000126 post = max(0, maxlen-3-pre)
127 return text[:pre] + '...' + text[len(text)-post:]
128 return text
129
Brett Cannon84601f12004-06-19 01:22:48 +0000130_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000131def stripid(text):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000132 """Remove the hexadecimal id from a Python object representation."""
Brett Cannonc6c1f472004-06-19 01:02:51 +0000133 # The behaviour of %p is implementation-dependent in terms of case.
Ezio Melotti412c95a2010-02-16 23:31:04 +0000134 return _re_stripid.sub(r'\1', text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000135
Brett Cannonc6c1f472004-06-19 01:02:51 +0000136def _is_some_method(obj):
R David Murrayac0cea52013-03-19 02:47:44 -0400137 return (inspect.isfunction(obj) or
138 inspect.ismethod(obj) or
139 inspect.isbuiltin(obj) or
140 inspect.ismethoddescriptor(obj))
Tim Peters536d2262001-09-20 05:13:38 +0000141
Larry Hastings24a882b2014-02-20 23:34:46 -0800142def _is_bound_method(fn):
143 """
144 Returns True if fn is a bound method, regardless of whether
145 fn was implemented in Python or in C.
146 """
147 if inspect.ismethod(fn):
148 return True
149 if inspect.isbuiltin(fn):
150 self = getattr(fn, '__self__', None)
151 return not (inspect.ismodule(self) or (self is None))
152 return False
153
154
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000155def allmethods(cl):
156 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000157 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000158 methods[key] = 1
159 for base in cl.__bases__:
160 methods.update(allmethods(base)) # all your base are belong to us
161 for key in methods.keys():
162 methods[key] = getattr(cl, key)
163 return methods
164
Tim Petersfa26f7c2001-09-24 08:05:11 +0000165def _split_list(s, predicate):
166 """Split sequence s via predicate, and return pair ([true], [false]).
167
168 The return value is a 2-tuple of lists,
169 ([x for x in s if predicate(x)],
170 [x for x in s if not predicate(x)])
171 """
172
Tim Peters28355492001-09-23 21:29:55 +0000173 yes = []
174 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000175 for x in s:
176 if predicate(x):
177 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000178 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000179 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000180 return yes, no
181
Raymond Hettinger1103d052011-03-25 14:15:24 -0700182def visiblename(name, all=None, obj=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000183 """Decide whether to show documentation on a variable."""
Brett Cannond340b432012-08-06 17:19:22 -0400184 # Certain special names are redundant or internal.
Eric Snowb523f842013-11-22 09:05:39 -0700185 # XXX Remove __initializing__?
Brett Cannond340b432012-08-06 17:19:22 -0400186 if name in {'__author__', '__builtins__', '__cached__', '__credits__',
Eric Snowb523f842013-11-22 09:05:39 -0700187 '__date__', '__doc__', '__file__', '__spec__',
Brett Cannond340b432012-08-06 17:19:22 -0400188 '__loader__', '__module__', '__name__', '__package__',
189 '__path__', '__qualname__', '__slots__', '__version__'}:
Raymond Hettinger68272942011-03-18 02:22:15 -0700190 return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000191 # Private names are hidden, but special names are displayed.
192 if name.startswith('__') and name.endswith('__'): return 1
Raymond Hettinger1103d052011-03-25 14:15:24 -0700193 # Namedtuples have public fields and methods with a single leading underscore
194 if name.startswith('_') and hasattr(obj, '_fields'):
195 return True
Skip Montanaroa5616d22004-06-11 04:46:12 +0000196 if all is not None:
197 # only document that which the programmer exported in __all__
198 return name in all
199 else:
200 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000201
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000202def classify_class_attrs(object):
203 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000204 results = []
205 for (name, kind, cls, value) in inspect.classify_class_attrs(object):
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000206 if inspect.isdatadescriptor(value):
207 kind = 'data descriptor'
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000208 results.append((name, kind, cls, value))
209 return results
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000210
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000211# ----------------------------------------------------- module manipulation
212
213def ispackage(path):
214 """Guess whether a path refers to a package directory."""
215 if os.path.isdir(path):
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000216 for ext in ('.py', '.pyc', '.pyo'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000217 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000218 return True
219 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000220
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000221def source_synopsis(file):
222 line = file.readline()
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000223 while line[:1] == '#' or not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000224 line = file.readline()
225 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000226 line = line.strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000227 if line[:4] == 'r"""': line = line[1:]
228 if line[:3] == '"""':
229 line = line[3:]
230 if line[-1:] == '\\': line = line[:-1]
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000231 while not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000232 line = file.readline()
233 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000234 result = line.split('"""')[0].strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000235 else: result = None
236 return result
237
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000238def synopsis(filename, cache={}):
239 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000240 mtime = os.stat(filename).st_mtime
Charles-François Natali27c4e882011-07-27 19:40:02 +0200241 lastupdate, result = cache.get(filename, (None, None))
242 if lastupdate is None or lastupdate < mtime:
Eric Snowaed5b222014-01-04 20:38:11 -0700243 # Look for binary suffixes first, falling back to source.
244 if filename.endswith(tuple(importlib.machinery.BYTECODE_SUFFIXES)):
245 loader_cls = importlib.machinery.SourcelessFileLoader
246 elif filename.endswith(tuple(importlib.machinery.EXTENSION_SUFFIXES)):
247 loader_cls = importlib.machinery.ExtensionFileLoader
248 else:
249 loader_cls = None
250 # Now handle the choice.
251 if loader_cls is None:
252 # Must be a source file.
253 try:
254 file = tokenize.open(filename)
255 except OSError:
256 # module can't be opened, so skip it
257 return None
258 # text modules can be directly examined
259 with file:
260 result = source_synopsis(file)
261 else:
262 # Must be a binary module, which has to be imported.
263 loader = loader_cls('__temp__', filename)
Eric Snow3a62d142014-01-06 20:42:59 -0700264 # XXX We probably don't need to pass in the loader here.
265 spec = importlib.util.spec_from_file_location('__temp__', filename,
266 loader=loader)
Brett Cannoncb66eb02012-05-11 12:58:42 -0400267 try:
Brett Cannon2a17bde2014-05-30 14:55:29 -0400268 module = importlib._bootstrap._load(spec)
Brett Cannoncb66eb02012-05-11 12:58:42 -0400269 except:
270 return None
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000271 del sys.modules['__temp__']
Benjamin Peterson54237f92015-02-16 19:45:01 -0500272 result = module.__doc__.splitlines()[0] if module.__doc__ else None
Eric Snowaed5b222014-01-04 20:38:11 -0700273 # Cache the result.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000274 cache[filename] = (mtime, result)
275 return result
276
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000277class ErrorDuringImport(Exception):
278 """Errors that occurred while trying to import something to document it."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000279 def __init__(self, filename, exc_info):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000280 self.filename = filename
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000281 self.exc, self.value, self.tb = exc_info
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000282
283 def __str__(self):
Guido van Rossuma01a8b62007-05-27 09:20:14 +0000284 exc = self.exc.__name__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000285 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000286
287def importfile(path):
288 """Import a Python source file or compiled file given its path."""
Brett Cannonf4ba4ec2013-06-15 14:25:04 -0400289 magic = importlib.util.MAGIC_NUMBER
Victor Stinnere975af62011-07-04 02:08:50 +0200290 with open(path, 'rb') as file:
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400291 is_bytecode = magic == file.read(len(magic))
292 filename = os.path.basename(path)
293 name, ext = os.path.splitext(filename)
294 if is_bytecode:
295 loader = importlib._bootstrap.SourcelessFileLoader(name, path)
296 else:
297 loader = importlib._bootstrap.SourceFileLoader(name, path)
Eric Snow3a62d142014-01-06 20:42:59 -0700298 # XXX We probably don't need to pass in the loader here.
299 spec = importlib.util.spec_from_file_location(name, path, loader=loader)
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400300 try:
Brett Cannon2a17bde2014-05-30 14:55:29 -0400301 return importlib._bootstrap._load(spec)
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400302 except:
303 raise ErrorDuringImport(path, sys.exc_info())
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000304
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000305def safeimport(path, forceload=0, cache={}):
306 """Import a module; handle errors; return None if the module isn't found.
307
308 If the module *is* found but an exception occurs, it's wrapped in an
309 ErrorDuringImport exception and reraised. Unlike __import__, if a
310 package path is specified, the module at the end of the path is returned,
311 not the package at the beginning. If the optional 'forceload' argument
312 is 1, we reload the module from disk (unless it's a dynamic extension)."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000313 try:
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000314 # If forceload is 1 and the module has been previously loaded from
315 # disk, we always have to reload the module. Checking the file's
316 # mtime isn't good enough (e.g. the module could contain a class
317 # that inherits from another module that has changed).
318 if forceload and path in sys.modules:
319 if path not in sys.builtin_module_names:
Guido van Rossume7ba4952007-06-06 23:52:48 +0000320 # Remove the module from sys.modules and re-import to try
321 # and avoid problems with partially loaded modules.
322 # Also remove any submodules because they won't appear
323 # in the newly loaded module's namespace if they're already
324 # in sys.modules.
Ka-Ping Yee9a2dcf82005-11-05 05:04:41 +0000325 subs = [m for m in sys.modules if m.startswith(path + '.')]
326 for key in [path] + subs:
327 # Prevent garbage collection.
328 cache[key] = sys.modules[key]
329 del sys.modules[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000330 module = __import__(path)
331 except:
332 # Did the error occur before or after the module was found?
333 (exc, value, tb) = info = sys.exc_info()
Raymond Hettinger54f02222002-06-01 14:18:47 +0000334 if path in sys.modules:
Fred Drakedb390c12005-10-28 14:39:47 +0000335 # An error occurred while executing the imported module.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000336 raise ErrorDuringImport(sys.modules[path].__file__, info)
337 elif exc is SyntaxError:
338 # A SyntaxError occurred before we could execute the module.
339 raise ErrorDuringImport(value.filename, info)
Brett Cannon679ecb52013-07-04 17:51:50 -0400340 elif exc is ImportError and value.name == path:
Brett Cannonfd074152012-04-14 14:10:13 -0400341 # No such module in the path.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000342 return None
343 else:
344 # Some other error occurred during the importing process.
345 raise ErrorDuringImport(path, sys.exc_info())
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000346 for part in path.split('.')[1:]:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000347 try: module = getattr(module, part)
348 except AttributeError: return None
349 return module
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000350
351# ---------------------------------------------------- formatter base class
352
353class Doc:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000354
355 PYTHONDOCS = os.environ.get("PYTHONDOCS",
356 "http://docs.python.org/%d.%d/library"
357 % sys.version_info[:2])
358
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000359 def document(self, object, name=None, *args):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000360 """Generate documentation for an object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000361 args = (object, name) + args
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000362 # 'try' clause is to attempt to handle the possibility that inspect
363 # identifies something in a way that pydoc itself has issues handling;
364 # think 'super' and how it is a descriptor (which raises the exception
365 # by lacking a __name__ attribute) and an instance.
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000366 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
367 if inspect.ismemberdescriptor(object): return self.docdata(*args)
Brett Cannon28a4f0f2003-06-11 23:38:55 +0000368 try:
369 if inspect.ismodule(object): return self.docmodule(*args)
370 if inspect.isclass(object): return self.docclass(*args)
371 if inspect.isroutine(object): return self.docroutine(*args)
372 except AttributeError:
373 pass
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000374 if isinstance(object, property): return self.docproperty(*args)
Guido van Rossum68468eb2003-02-27 20:14:51 +0000375 return self.docother(*args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000376
377 def fail(self, object, name=None, *args):
378 """Raise an exception for unimplemented types."""
379 message = "don't know how to document object%s of type %s" % (
380 name and ' ' + repr(name), type(object).__name__)
Collin Winterce36ad82007-08-30 01:19:48 +0000381 raise TypeError(message)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000382
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000383 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000384
Skip Montanaro4997a692003-09-10 16:47:51 +0000385 def getdocloc(self, object):
386 """Return the location of module docs or None"""
387
388 try:
389 file = inspect.getabsfile(object)
390 except TypeError:
391 file = '(built-in)'
392
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000393 docloc = os.environ.get("PYTHONDOCS", self.PYTHONDOCS)
394
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100395 basedir = os.path.join(sys.base_exec_prefix, "lib",
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000396 "python%d.%d" % sys.version_info[:2])
Skip Montanaro4997a692003-09-10 16:47:51 +0000397 if (isinstance(object, type(os)) and
398 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
399 'marshal', 'posix', 'signal', 'sys',
Georg Brandl2067bfd2008-05-25 13:05:15 +0000400 '_thread', 'zipimport') or
Skip Montanaro4997a692003-09-10 16:47:51 +0000401 (file.startswith(basedir) and
Brian Curtin49c284c2010-03-31 03:19:28 +0000402 not file.startswith(os.path.join(basedir, 'site-packages')))) and
Brian Curtinedef05b2010-04-01 04:05:25 +0000403 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
Skip Montanaro4997a692003-09-10 16:47:51 +0000404 if docloc.startswith("http://"):
Georg Brandl86def6c2008-01-21 20:36:10 +0000405 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
Skip Montanaro4997a692003-09-10 16:47:51 +0000406 else:
Georg Brandl86def6c2008-01-21 20:36:10 +0000407 docloc = os.path.join(docloc, object.__name__ + ".html")
Skip Montanaro4997a692003-09-10 16:47:51 +0000408 else:
409 docloc = None
410 return docloc
411
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000412# -------------------------------------------- HTML documentation generator
413
414class HTMLRepr(Repr):
415 """Class for safely making an HTML representation of a Python object."""
416 def __init__(self):
417 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000418 self.maxlist = self.maxtuple = 20
419 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000420 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000421
422 def escape(self, text):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000423 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000424
425 def repr(self, object):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000426 return Repr.repr(self, object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000427
428 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000429 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000430 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +0000431 if hasattr(self, methodname):
432 return getattr(self, methodname)(x, level)
433 return self.escape(cram(stripid(repr(x)), self.maxother))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000434
435 def repr_string(self, x, level):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000436 test = cram(x, self.maxstring)
437 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000438 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000439 # Backslashes are only literal in the string and are never
440 # needed to make any special characters, so show a raw string.
441 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000442 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000443 r'<font color="#c040c0">\1</font>',
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +0000444 self.escape(testrepr))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000445
Skip Montanarodf708782002-03-07 22:58:02 +0000446 repr_str = repr_string
447
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000448 def repr_instance(self, x, level):
449 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000450 return self.escape(cram(stripid(repr(x)), self.maxstring))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000451 except:
452 return self.escape('<%s instance>' % x.__class__.__name__)
453
454 repr_unicode = repr_string
455
456class HTMLDoc(Doc):
457 """Formatter class for HTML documentation."""
458
459 # ------------------------------------------- HTML formatting utilities
460
461 _repr_instance = HTMLRepr()
462 repr = _repr_instance.repr
463 escape = _repr_instance.escape
464
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000465 def page(self, title, contents):
466 """Format an HTML page."""
Georg Brandl388faac2009-04-10 08:31:48 +0000467 return '''\
Georg Brandle6066942009-04-10 08:28:28 +0000468<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000469<html><head><title>Python: %s</title>
Georg Brandl388faac2009-04-10 08:31:48 +0000470<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000471</head><body bgcolor="#f0f0f8">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000472%s
473</body></html>''' % (title, contents)
474
475 def heading(self, title, fgcol, bgcol, extras=''):
476 """Format a page heading."""
477 return '''
Tim Peters59ed4482001-10-31 04:20:26 +0000478<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000479<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000480<td valign=bottom>&nbsp;<br>
481<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000482><td align=right valign=bottom
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000483><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000484 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
485
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000486 def section(self, title, fgcol, bgcol, contents, width=6,
487 prelude='', marginalia=None, gap='&nbsp;'):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000488 """Format a section with a heading."""
489 if marginalia is None:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000490 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000491 result = '''<p>
Tim Peters59ed4482001-10-31 04:20:26 +0000492<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000493<tr bgcolor="%s">
Tim Peters2306d242001-09-25 03:18:32 +0000494<td colspan=3 valign=bottom>&nbsp;<br>
495<font color="%s" face="helvetica, arial">%s</font></td></tr>
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000496 ''' % (bgcol, fgcol, title)
497 if prelude:
498 result = result + '''
Ka-Ping Yee987ec902001-03-23 13:35:45 +0000499<tr bgcolor="%s"><td rowspan=2>%s</td>
500<td colspan=2>%s</td></tr>
501<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
502 else:
503 result = result + '''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000504<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000505
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +0000506 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000507
508 def bigsection(self, title, *args):
509 """Format a section with a big heading."""
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000510 title = '<big><strong>%s</strong></big>' % title
Guido van Rossum68468eb2003-02-27 20:14:51 +0000511 return self.section(title, *args)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000512
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000513 def preformat(self, text):
514 """Format literal preformatted text."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000515 text = self.escape(text.expandtabs())
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000516 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
517 ' ', '&nbsp;', '\n', '<br>\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000518
519 def multicolumn(self, list, format, cols=4):
520 """Format a list of items into a multi-column list."""
521 result = ''
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000522 rows = (len(list)+cols-1)//cols
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000523 for col in range(cols):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000524 result = result + '<td width="%d%%" valign=top>' % (100//cols)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000525 for i in range(rows*col, rows*col+rows):
526 if i < len(list):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000527 result = result + format(list[i]) + '<br>\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000528 result = result + '</td>'
Tim Peters59ed4482001-10-31 04:20:26 +0000529 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000530
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000531 def grey(self, text): return '<font color="#909090">%s</font>' % text
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000532
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000533 def namelink(self, name, *dicts):
534 """Make a link for an identifier, given name-to-URL mappings."""
535 for dict in dicts:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000536 if name in dict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000537 return '<a href="%s">%s</a>' % (dict[name], name)
538 return name
539
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000540 def classlink(self, object, modname):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000541 """Make a link for a class."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000542 name, module = object.__name__, sys.modules.get(object.__module__)
543 if hasattr(module, name) and getattr(module, name) is object:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000544 return '<a href="%s.html#%s">%s</a>' % (
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000545 module.__name__, name, classname(object, modname))
546 return classname(object, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000547
548 def modulelink(self, object):
549 """Make a link for a module."""
550 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
551
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000552 def modpkglink(self, modpkginfo):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000553 """Make a link for a module or package to display in an index."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000554 name, path, ispackage, shadowed = modpkginfo
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000555 if shadowed:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000556 return self.grey(name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000557 if path:
558 url = '%s.%s.html' % (path, name)
559 else:
560 url = '%s.html' % name
561 if ispackage:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000562 text = '<strong>%s</strong>&nbsp;(package)' % name
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000563 else:
564 text = name
565 return '<a href="%s">%s</a>' % (url, text)
566
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000567 def filelink(self, url, path):
568 """Make a link to source file."""
569 return '<a href="file:%s">%s</a>' % (url, path)
570
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000571 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
572 """Mark up some plain text, given a context of symbols to look for.
573 Each context dictionary maps object names to anchor names."""
574 escape = escape or self.escape
575 results = []
576 here = 0
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000577 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
578 r'RFC[- ]?(\d+)|'
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000579 r'PEP[- ]?(\d+)|'
Neil Schemenauerd69711c2002-03-24 23:02:07 +0000580 r'(self\.)?(\w+))')
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000581 while True:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000582 match = pattern.search(text, here)
583 if not match: break
584 start, end = match.span()
585 results.append(escape(text[here:start]))
586
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000587 all, scheme, rfc, pep, selfdot, name = match.groups()
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000588 if scheme:
Neil Schemenauercddc1a02002-03-24 23:11:21 +0000589 url = escape(all).replace('"', '&quot;')
590 results.append('<a href="%s">%s</a>' % (url, url))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000591 elif rfc:
Ka-Ping Yeef78a81b2001-03-27 08:13:42 +0000592 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
593 results.append('<a href="%s">%s</a>' % (url, escape(all)))
594 elif pep:
Christian Heimes2202f872008-02-06 14:31:34 +0000595 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000596 results.append('<a href="%s">%s</a>' % (url, escape(all)))
Benjamin Petersoned1160b2014-06-07 16:44:00 -0700597 elif selfdot:
598 # Create a link for methods like 'self.method(...)'
599 # and use <strong> for attributes like 'self.attr'
600 if text[end:end+1] == '(':
601 results.append('self.' + self.namelink(name, methods))
602 else:
603 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000604 elif text[end:end+1] == '(':
605 results.append(self.namelink(name, methods, funcs, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000606 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000607 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000608 here = end
609 results.append(escape(text[here:]))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000610 return ''.join(results)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000611
612 # ---------------------------------------------- type-specific routines
613
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000614 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000615 """Produce HTML for a class tree as given by inspect.getclasstree()."""
616 result = ''
617 for entry in tree:
618 if type(entry) is type(()):
619 c, bases = entry
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000620 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000621 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000622 if bases and bases != (parent,):
623 parents = []
624 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000625 parents.append(self.classlink(base, modname))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000626 result = result + '(' + ', '.join(parents) + ')'
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000627 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000628 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000629 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000630 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000631 return '<dl>\n%s</dl>\n' % result
632
Tim Peters8dd7ade2001-10-18 19:56:17 +0000633 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000634 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000635 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000636 try:
637 all = object.__all__
638 except AttributeError:
639 all = None
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000640 parts = name.split('.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000641 links = []
642 for i in range(len(parts)-1):
643 links.append(
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000644 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000645 ('.'.join(parts[:i+1]), parts[i]))
646 linkedname = '.'.join(links + parts[-1:])
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000647 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000648 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000649 path = inspect.getabsfile(object)
Zachary Wareeb432142014-07-10 11:18:00 -0500650 url = urllib.parse.quote(path)
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000651 filelink = self.filelink(url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000652 except TypeError:
653 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000654 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000655 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000656 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000657 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000658 version = version[11:-1].strip()
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000659 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000660 if hasattr(object, '__date__'):
661 info.append(self.escape(str(object.__date__)))
662 if info:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000663 head = head + ' (%s)' % ', '.join(info)
Skip Montanaro4997a692003-09-10 16:47:51 +0000664 docloc = self.getdocloc(object)
665 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000666 docloc = '<br><a href="%(docloc)s">Module Reference</a>' % locals()
Skip Montanaro4997a692003-09-10 16:47:51 +0000667 else:
668 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000669 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000670 head, '#ffffff', '#7799ee',
671 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000672
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000673 modules = inspect.getmembers(object, inspect.ismodule)
674
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000675 classes, cdict = [], {}
676 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000677 # if __all__ exists, believe it. Otherwise use old heuristic.
678 if (all is not None or
679 (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700680 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000681 classes.append((key, value))
682 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000683 for key, value in classes:
684 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000685 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000686 module = sys.modules.get(modname)
687 if modname != name and module and hasattr(module, key):
688 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000689 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000690 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000691 funcs, fdict = [], {}
692 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000693 # if __all__ exists, believe it. Otherwise use old heuristic.
694 if (all is not None or
695 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700696 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000697 funcs.append((key, value))
698 fdict[key] = '#-' + key
699 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000700 data = []
701 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700702 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000703 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000704
705 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
706 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000707 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000708
709 if hasattr(object, '__path__'):
710 modpkgs = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000711 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
712 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000713 modpkgs.sort()
714 contents = self.multicolumn(modpkgs, self.modpkglink)
715 result = result + self.bigsection(
716 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000717 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000718 contents = self.multicolumn(
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000719 modules, lambda t: self.modulelink(t[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000720 result = result + self.bigsection(
Christian Heimes7131fd92008-02-19 14:21:46 +0000721 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000722
723 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000724 classlist = [value for (key, value) in classes]
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000725 contents = [
726 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000727 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000728 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000729 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000730 'Classes', '#ffffff', '#ee77aa', ' '.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000731 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000732 contents = []
733 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000734 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000735 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000736 'Functions', '#ffffff', '#eeaa77', ' '.join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000737 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000738 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000739 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000740 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000741 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000742 'Data', '#ffffff', '#55aa55', '<br>\n'.join(contents))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000743 if hasattr(object, '__author__'):
744 contents = self.markup(str(object.__author__), self.preformat)
745 result = result + self.bigsection(
746 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000747 if hasattr(object, '__credits__'):
748 contents = self.markup(str(object.__credits__), self.preformat)
749 result = result + self.bigsection(
750 'Credits', '#ffffff', '#7799ee', contents)
751
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000752 return result
753
Tim Peters8dd7ade2001-10-18 19:56:17 +0000754 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
755 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000756 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000757 realname = object.__name__
758 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000759 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000760
Tim Petersb47879b2001-09-24 04:47:19 +0000761 contents = []
762 push = contents.append
763
Tim Petersfa26f7c2001-09-24 08:05:11 +0000764 # Cute little class to pump out a horizontal rule between sections.
765 class HorizontalRule:
766 def __init__(self):
767 self.needone = 0
768 def maybe(self):
769 if self.needone:
770 push('<hr>\n')
771 self.needone = 1
772 hr = HorizontalRule()
773
Tim Petersc86f6ca2001-09-26 21:31:51 +0000774 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000775 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000776 if len(mro) > 2:
777 hr.maybe()
778 push('<dl><dt>Method resolution order:</dt>\n')
779 for base in mro:
780 push('<dd>%s</dd>\n' % self.classlink(base,
781 object.__module__))
782 push('</dl>\n')
783
Tim Petersb47879b2001-09-24 04:47:19 +0000784 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000785 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000786 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000787 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000788 push(msg)
789 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100790 try:
791 value = getattr(object, name)
792 except Exception:
793 # Some descriptors may meet a failure in their __get__.
794 # (bug #1785)
795 push(self._docdescriptor(name, value, mod))
796 else:
797 push(self.document(value, name, mod,
798 funcs, classes, mdict, object))
Tim Petersb47879b2001-09-24 04:47:19 +0000799 push('\n')
800 return attrs
801
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000802 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000803 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000804 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000805 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000806 push(msg)
807 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000808 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000809 return attrs
810
Tim Petersfa26f7c2001-09-24 08:05:11 +0000811 def spilldata(msg, attrs, predicate):
812 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000813 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000814 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000815 push(msg)
816 for name, kind, homecls, value in ok:
817 base = self.docother(getattr(object, name), name, mod)
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200818 if callable(value) or inspect.isdatadescriptor(value):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000819 doc = getattr(value, "__doc__", None)
820 else:
821 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000822 if doc is None:
823 push('<dl><dt>%s</dl>\n' % base)
824 else:
825 doc = self.markup(getdoc(value), self.preformat,
826 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000827 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000828 push('<dl><dt>%s%s</dl>\n' % (base, doc))
829 push('\n')
830 return attrs
831
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000832 attrs = [(name, kind, cls, value)
833 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -0700834 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000835
Tim Petersb47879b2001-09-24 04:47:19 +0000836 mdict = {}
837 for key, kind, homecls, value in attrs:
838 mdict[key] = anchor = '#' + name + '-' + key
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100839 try:
840 value = getattr(object, name)
841 except Exception:
842 # Some descriptors may meet a failure in their __get__.
843 # (bug #1785)
844 pass
Tim Petersb47879b2001-09-24 04:47:19 +0000845 try:
846 # The value may not be hashable (e.g., a data attr with
847 # a dict or list value).
848 mdict[value] = anchor
849 except TypeError:
850 pass
851
Tim Petersfa26f7c2001-09-24 08:05:11 +0000852 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000853 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000854 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000855 else:
856 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000857 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
858
Georg Brandl1a3284e2007-12-02 09:40:06 +0000859 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000860 attrs = inherited
861 continue
862 elif thisclass is object:
863 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000864 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000865 tag = 'inherited from %s' % self.classlink(thisclass,
866 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000867 tag += ':<br>\n'
868
869 # Sort attrs by name.
Raymond Hettingerd4cb56d2008-01-30 02:55:10 +0000870 attrs.sort(key=lambda t: t[0])
Tim Petersb47879b2001-09-24 04:47:19 +0000871
872 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000873 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000874 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000875 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000876 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000877 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000878 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000879 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
880 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000881 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000882 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000883 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000884 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000885
886 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000887
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000888 if name == realname:
889 title = '<a name="%s">class <strong>%s</strong></a>' % (
890 name, realname)
891 else:
892 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
893 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000894 if bases:
895 parents = []
896 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000897 parents.append(self.classlink(base, object.__module__))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000898 title = title + '(%s)' % ', '.join(parents)
Tim Peters2306d242001-09-25 03:18:32 +0000899 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000900 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000901
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000902 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000903
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000904 def formatvalue(self, object):
905 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000906 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000907
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000908 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000909 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000910 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000911 realname = object.__name__
912 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000913 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000914 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000915 skipdocs = 0
Larry Hastings24a882b2014-02-20 23:34:46 -0800916 if _is_bound_method(object):
Christian Heimesff737952007-11-27 10:40:20 +0000917 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000918 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000919 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000920 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000921 else:
Christian Heimesff737952007-11-27 10:40:20 +0000922 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000923 note = ' method of %s instance' % self.classlink(
Christian Heimesff737952007-11-27 10:40:20 +0000924 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000925 else:
926 note = ' unbound %s method' % self.classlink(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000927
928 if name == realname:
929 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
930 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000931 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000932 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000933 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000934 cl.__name__ + '-' + realname, realname)
935 skipdocs = 1
936 else:
937 reallink = realname
938 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
939 anchor, name, reallink)
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800940 argspec = None
Larry Hastings24a882b2014-02-20 23:34:46 -0800941 if inspect.isroutine(object):
Larry Hastings5c661892014-01-24 06:17:25 -0800942 try:
943 signature = inspect.signature(object)
944 except (ValueError, TypeError):
945 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800946 if signature:
947 argspec = str(signature)
948 if realname == '<lambda>':
949 title = '<strong>%s</strong> <em>lambda</em> ' % name
950 # XXX lambda's won't usually have func_annotations['return']
951 # since the syntax doesn't support but it is possible.
952 # So removing parentheses isn't truly safe.
953 argspec = argspec[1:-1] # remove parentheses
954 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +0000955 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000956
Serhiy Storchaka66dd4aa2014-11-17 23:48:02 +0200957 decl = title + self.escape(argspec) + (note and self.grey(
Tim Peters2306d242001-09-25 03:18:32 +0000958 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000959
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000960 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000961 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000962 else:
963 doc = self.markup(
964 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000965 doc = doc and '<dd><tt>%s</tt></dd>' % doc
966 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000967
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000968 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000969 results = []
970 push = results.append
971
972 if name:
973 push('<dl><dt><strong>%s</strong></dt>\n' % name)
974 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000975 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000976 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000977 push('</dl>\n')
978
979 return ''.join(results)
980
981 def docproperty(self, object, name=None, mod=None, cl=None):
982 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000983 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000984
Tim Peters8dd7ade2001-10-18 19:56:17 +0000985 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000986 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000987 lhs = name and '<strong>%s</strong> = ' % name or ''
988 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000989
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000990 def docdata(self, object, name=None, mod=None, cl=None):
991 """Produce html documentation for a data descriptor."""
992 return self._docdescriptor(name, object, mod)
993
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000994 def index(self, dir, shadowed=None):
995 """Generate an HTML index for a directory of modules."""
996 modpkgs = []
997 if shadowed is None: shadowed = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000998 for importer, name, ispkg in pkgutil.iter_modules([dir]):
Victor Stinner4d652242011-04-12 23:41:50 +0200999 if any((0xD800 <= ord(ch) <= 0xDFFF) for ch in name):
1000 # ignore a module if its name contains a surrogate character
1001 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001002 modpkgs.append((name, '', ispkg, name in shadowed))
1003 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001004
1005 modpkgs.sort()
1006 contents = self.multicolumn(modpkgs, self.modpkglink)
1007 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
1008
1009# -------------------------------------------- text documentation generator
1010
1011class TextRepr(Repr):
1012 """Class for safely making a text representation of a Python object."""
1013 def __init__(self):
1014 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001015 self.maxlist = self.maxtuple = 20
1016 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001017 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001018
1019 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001020 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001021 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001022 if hasattr(self, methodname):
1023 return getattr(self, methodname)(x, level)
1024 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001025
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001026 def repr_string(self, x, level):
1027 test = cram(x, self.maxstring)
1028 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001029 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001030 # Backslashes are only literal in the string and are never
1031 # needed to make any special characters, so show a raw string.
1032 return 'r' + testrepr[0] + test + testrepr[0]
1033 return testrepr
1034
Skip Montanarodf708782002-03-07 22:58:02 +00001035 repr_str = repr_string
1036
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001037 def repr_instance(self, x, level):
1038 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001039 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001040 except:
1041 return '<%s instance>' % x.__class__.__name__
1042
1043class TextDoc(Doc):
1044 """Formatter class for text documentation."""
1045
1046 # ------------------------------------------- text formatting utilities
1047
1048 _repr_instance = TextRepr()
1049 repr = _repr_instance.repr
1050
1051 def bold(self, text):
1052 """Format a string in bold by overstriking."""
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001053 return ''.join(ch + '\b' + ch for ch in text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001054
1055 def indent(self, text, prefix=' '):
1056 """Indent text by prepending a given prefix to each line."""
1057 if not text: return ''
Collin Winter72e110c2007-07-17 00:27:30 +00001058 lines = [prefix + line for line in text.split('\n')]
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001059 if lines: lines[-1] = lines[-1].rstrip()
1060 return '\n'.join(lines)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001061
1062 def section(self, title, contents):
1063 """Format a section with a given heading."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001064 clean_contents = self.indent(contents).rstrip()
1065 return self.bold(title) + '\n' + clean_contents + '\n\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001066
1067 # ---------------------------------------------- type-specific routines
1068
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001069 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001070 """Render in text a class tree as returned by inspect.getclasstree()."""
1071 result = ''
1072 for entry in tree:
1073 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001074 c, bases = entry
1075 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001076 if bases and bases != (parent,):
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001077 parents = (classname(c, modname) for c in bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001078 result = result + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001079 result = result + '\n'
1080 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001081 result = result + self.formattree(
1082 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001083 return result
1084
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001085 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001086 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001087 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001088 synop, desc = splitdoc(getdoc(object))
1089 result = self.section('NAME', name + (synop and ' - ' + synop))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001090 all = getattr(object, '__all__', None)
Skip Montanaro4997a692003-09-10 16:47:51 +00001091 docloc = self.getdocloc(object)
1092 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001093 result = result + self.section('MODULE REFERENCE', docloc + """
1094
Éric Araujo647ef8c2011-09-11 00:43:20 +02001095The following documentation is automatically generated from the Python
1096source files. It may be incomplete, incorrect or include features that
1097are considered implementation detail and may vary between Python
1098implementations. When in doubt, consult the module reference at the
1099location listed above.
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001100""")
Skip Montanaro4997a692003-09-10 16:47:51 +00001101
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001102 if desc:
1103 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001104
1105 classes = []
1106 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001107 # if __all__ exists, believe it. Otherwise use old heuristic.
1108 if (all is not None
1109 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001110 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001111 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001112 funcs = []
1113 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001114 # if __all__ exists, believe it. Otherwise use old heuristic.
1115 if (all is not None or
1116 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001117 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001118 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001119 data = []
1120 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001121 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001122 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001123
Christian Heimes1af737c2008-01-23 08:24:23 +00001124 modpkgs = []
1125 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001126 if hasattr(object, '__path__'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001127 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Christian Heimes1af737c2008-01-23 08:24:23 +00001128 modpkgs_names.add(modname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001129 if ispkg:
1130 modpkgs.append(modname + ' (package)')
1131 else:
1132 modpkgs.append(modname)
1133
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001134 modpkgs.sort()
1135 result = result + self.section(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001136 'PACKAGE CONTENTS', '\n'.join(modpkgs))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001137
Christian Heimes1af737c2008-01-23 08:24:23 +00001138 # Detect submodules as sometimes created by C extensions
1139 submodules = []
1140 for key, value in inspect.getmembers(object, inspect.ismodule):
1141 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1142 submodules.append(key)
1143 if submodules:
1144 submodules.sort()
1145 result = result + self.section(
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001146 'SUBMODULES', '\n'.join(submodules))
Christian Heimes1af737c2008-01-23 08:24:23 +00001147
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001148 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001149 classlist = [value for key, value in classes]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001150 contents = [self.formattree(
1151 inspect.getclasstree(classlist, 1), name)]
1152 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001153 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001154 result = result + self.section('CLASSES', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001155
1156 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001157 contents = []
1158 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001159 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001160 result = result + self.section('FUNCTIONS', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001161
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001162 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001163 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001164 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001165 contents.append(self.docother(value, key, name, maxlen=70))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001166 result = result + self.section('DATA', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001167
1168 if hasattr(object, '__version__'):
1169 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001170 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001171 version = version[11:-1].strip()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001172 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001173 if hasattr(object, '__date__'):
1174 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001175 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001176 result = result + self.section('AUTHOR', str(object.__author__))
1177 if hasattr(object, '__credits__'):
1178 result = result + self.section('CREDITS', str(object.__credits__))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001179 try:
1180 file = inspect.getabsfile(object)
1181 except TypeError:
1182 file = '(built-in)'
1183 result = result + self.section('FILE', file)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001184 return result
1185
Georg Brandl9bd45f992010-12-03 09:58:38 +00001186 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001187 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001188 realname = object.__name__
1189 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001190 bases = object.__bases__
1191
Tim Petersc86f6ca2001-09-26 21:31:51 +00001192 def makename(c, m=object.__module__):
1193 return classname(c, m)
1194
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001195 if name == realname:
1196 title = 'class ' + self.bold(realname)
1197 else:
1198 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001199 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001200 parents = map(makename, bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001201 title = title + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001202
1203 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001204 contents = doc and [doc + '\n'] or []
1205 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001206
Tim Petersc86f6ca2001-09-26 21:31:51 +00001207 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001208 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001209 if len(mro) > 2:
1210 push("Method resolution order:")
1211 for base in mro:
1212 push(' ' + makename(base))
1213 push('')
1214
Tim Petersf4aad8e2001-09-24 22:40:47 +00001215 # Cute little class to pump out a horizontal rule between sections.
1216 class HorizontalRule:
1217 def __init__(self):
1218 self.needone = 0
1219 def maybe(self):
1220 if self.needone:
1221 push('-' * 70)
1222 self.needone = 1
1223 hr = HorizontalRule()
1224
Tim Peters28355492001-09-23 21:29:55 +00001225 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001226 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001227 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001228 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001229 push(msg)
1230 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001231 try:
1232 value = getattr(object, name)
1233 except Exception:
1234 # Some descriptors may meet a failure in their __get__.
1235 # (bug #1785)
1236 push(self._docdescriptor(name, value, mod))
1237 else:
1238 push(self.document(value,
1239 name, mod, object))
Tim Peters28355492001-09-23 21:29:55 +00001240 return attrs
1241
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001242 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001243 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001244 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001245 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001246 push(msg)
1247 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001248 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001249 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001250
Tim Petersfa26f7c2001-09-24 08:05:11 +00001251 def spilldata(msg, attrs, predicate):
1252 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001253 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001254 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001255 push(msg)
1256 for name, kind, homecls, value in ok:
Florent Xicluna5d1155c2011-10-28 14:45:05 +02001257 if callable(value) or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001258 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001259 else:
1260 doc = None
Serhiy Storchaka056eb022014-02-19 23:05:12 +02001261 try:
1262 obj = getattr(object, name)
1263 except AttributeError:
1264 obj = homecls.__dict__[name]
1265 push(self.docother(obj, name, mod, maxlen=70, doc=doc) +
1266 '\n')
Tim Peters28355492001-09-23 21:29:55 +00001267 return attrs
1268
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001269 attrs = [(name, kind, cls, value)
1270 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -07001271 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001272
Tim Petersfa26f7c2001-09-24 08:05:11 +00001273 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001274 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001275 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001276 else:
1277 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001278 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1279
Georg Brandl1a3284e2007-12-02 09:40:06 +00001280 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001281 attrs = inherited
1282 continue
1283 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001284 tag = "defined here"
1285 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001286 tag = "inherited from %s" % classname(thisclass,
1287 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001288 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001289 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001290
1291 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001292 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001293 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001294 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001295 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001296 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001297 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001298 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1299 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001300 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1301 lambda t: t[1] == 'data')
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001302
Tim Peters28355492001-09-23 21:29:55 +00001303 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001304 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001305
1306 contents = '\n'.join(contents)
1307 if not contents:
1308 return title + '\n'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001309 return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001310
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001311 def formatvalue(self, object):
1312 """Format an argument default value as text."""
1313 return '=' + self.repr(object)
1314
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001315 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001316 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001317 realname = object.__name__
1318 name = name or realname
1319 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001320 skipdocs = 0
Larry Hastings24a882b2014-02-20 23:34:46 -08001321 if _is_bound_method(object):
Christian Heimesff737952007-11-27 10:40:20 +00001322 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001323 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001324 if imclass is not cl:
1325 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001326 else:
Christian Heimesff737952007-11-27 10:40:20 +00001327 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001328 note = ' method of %s instance' % classname(
Christian Heimesff737952007-11-27 10:40:20 +00001329 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001330 else:
1331 note = ' unbound %s method' % classname(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001332
1333 if name == realname:
1334 title = self.bold(realname)
1335 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001336 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001337 cl.__dict__[realname] is object):
1338 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001339 title = self.bold(name) + ' = ' + realname
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001340 argspec = None
Larry Hastings5c661892014-01-24 06:17:25 -08001341
1342 if inspect.isroutine(object):
1343 try:
1344 signature = inspect.signature(object)
1345 except (ValueError, TypeError):
1346 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001347 if signature:
1348 argspec = str(signature)
1349 if realname == '<lambda>':
1350 title = self.bold(name) + ' lambda '
1351 # XXX lambda's won't usually have func_annotations['return']
1352 # since the syntax doesn't support but it is possible.
1353 # So removing parentheses isn't truly safe.
1354 argspec = argspec[1:-1] # remove parentheses
1355 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +00001356 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001357 decl = title + argspec + note
1358
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001359 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001360 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001361 else:
1362 doc = getdoc(object) or ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001363 return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001364
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001365 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001366 results = []
1367 push = results.append
1368
1369 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001370 push(self.bold(name))
1371 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001372 doc = getdoc(value) or ''
1373 if doc:
1374 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001375 push('\n')
1376 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001377
1378 def docproperty(self, object, name=None, mod=None, cl=None):
1379 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001380 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001381
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001382 def docdata(self, object, name=None, mod=None, cl=None):
1383 """Produce text documentation for a data descriptor."""
1384 return self._docdescriptor(name, object, mod)
1385
Georg Brandl8b813db2005-10-01 16:32:31 +00001386 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001387 """Produce text documentation for a data object."""
1388 repr = self.repr(object)
1389 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001390 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001391 chop = maxlen - len(line)
1392 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001393 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001394 if doc is not None:
1395 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001396 return line
1397
Georg Brandld80d5f42010-12-03 07:47:22 +00001398class _PlainTextDoc(TextDoc):
1399 """Subclass of TextDoc which overrides string styling"""
1400 def bold(self, text):
1401 return text
1402
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001403# --------------------------------------------------------- user interfaces
1404
1405def pager(text):
1406 """The first time this is called, determine what kind of pager to use."""
1407 global pager
1408 pager = getpager()
1409 pager(text)
1410
1411def getpager():
1412 """Decide what method to use for paging through text."""
Benjamin Peterson159824e2014-06-07 20:14:26 -07001413 if not hasattr(sys.stdin, "isatty"):
1414 return plainpager
Guido van Rossuma01a8b62007-05-27 09:20:14 +00001415 if not hasattr(sys.stdout, "isatty"):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001416 return plainpager
1417 if not sys.stdin.isatty() or not sys.stdout.isatty():
1418 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001419 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001420 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001421 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001422 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001423 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001424 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001425 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001426 if os.environ.get('TERM') in ('dumb', 'emacs'):
1427 return plainpager
Jesus Cea4791a242012-10-05 03:15:39 +02001428 if sys.platform == 'win32':
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001429 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001430 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001431 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001432
1433 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001434 (fd, filename) = tempfile.mkstemp()
1435 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001436 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001437 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001438 return lambda text: pipepager(text, 'more')
1439 else:
1440 return ttypager
1441 finally:
1442 os.unlink(filename)
1443
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001444def plain(text):
1445 """Remove boldface formatting from text."""
1446 return re.sub('.\b', '', text)
1447
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001448def pipepager(text, cmd):
1449 """Page through text by feeding it to another program."""
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001450 import subprocess
1451 proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001452 try:
R David Murray1058cda2015-03-29 15:15:40 -04001453 with io.TextIOWrapper(proc.stdin, errors='backslashreplace') as pipe:
R David Murraye7f5e142015-03-30 10:14:47 -04001454 try:
1455 pipe.write(text)
1456 except KeyboardInterrupt:
1457 # We've hereby abandoned whatever text hasn't been written,
1458 # but the pager is still in control of the terminal.
1459 pass
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001460 except OSError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001461 pass # Ignore broken pipes caused by quitting the pager program.
R David Murray1058cda2015-03-29 15:15:40 -04001462 while True:
1463 try:
1464 proc.wait()
1465 break
1466 except KeyboardInterrupt:
1467 # Ignore ctl-c like the pager itself does. Otherwise the pager is
1468 # left running and the terminal is in raw mode and unusable.
1469 pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001470
1471def tempfilepager(text, cmd):
1472 """Page through text by invoking a program on a temporary file."""
1473 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001474 filename = tempfile.mktemp()
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001475 with open(filename, 'w', errors='backslashreplace') as file:
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +01001476 file.write(text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001477 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001478 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001479 finally:
1480 os.unlink(filename)
1481
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001482def _escape_stdout(text):
1483 # Escape non-encodable characters to avoid encoding errors later
1484 encoding = getattr(sys.stdout, 'encoding', None) or 'utf-8'
1485 return text.encode(encoding, 'backslashreplace').decode(encoding)
1486
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001487def ttypager(text):
1488 """Page through text on a text terminal."""
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001489 lines = plain(_escape_stdout(text)).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001490 try:
1491 import tty
1492 fd = sys.stdin.fileno()
1493 old = tty.tcgetattr(fd)
1494 tty.setcbreak(fd)
1495 getchar = lambda: sys.stdin.read(1)
Serhiy Storchakaab5e9b92014-11-28 00:09:29 +02001496 except (ImportError, AttributeError, io.UnsupportedOperation):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001497 tty = None
1498 getchar = lambda: sys.stdin.readline()[:-1][:1]
1499
1500 try:
Serhiy Storchakaab5e9b92014-11-28 00:09:29 +02001501 try:
1502 h = int(os.environ.get('LINES', 0))
1503 except ValueError:
1504 h = 0
1505 if h <= 1:
1506 h = 25
1507 r = inc = h - 1
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001508 sys.stdout.write('\n'.join(lines[:inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001509 while lines[r:]:
1510 sys.stdout.write('-- more --')
1511 sys.stdout.flush()
1512 c = getchar()
1513
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001514 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001515 sys.stdout.write('\r \r')
1516 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001517 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001518 sys.stdout.write('\r \r' + lines[r] + '\n')
1519 r = r + 1
1520 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001521 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001522 r = r - inc - inc
1523 if r < 0: r = 0
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001524 sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001525 r = r + inc
1526
1527 finally:
1528 if tty:
1529 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1530
1531def plainpager(text):
1532 """Simply print unformatted text. This is the ultimate fallback."""
Serhiy Storchaka5e3d7a42015-02-20 23:46:06 +02001533 sys.stdout.write(plain(_escape_stdout(text)))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001534
1535def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001536 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001537 if inspect.ismodule(thing):
1538 if thing.__name__ in sys.builtin_module_names:
1539 return 'built-in module ' + thing.__name__
1540 if hasattr(thing, '__path__'):
1541 return 'package ' + thing.__name__
1542 else:
1543 return 'module ' + thing.__name__
1544 if inspect.isbuiltin(thing):
1545 return 'built-in function ' + thing.__name__
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001546 if inspect.isgetsetdescriptor(thing):
1547 return 'getset descriptor %s.%s.%s' % (
1548 thing.__objclass__.__module__, thing.__objclass__.__name__,
1549 thing.__name__)
1550 if inspect.ismemberdescriptor(thing):
1551 return 'member descriptor %s.%s.%s' % (
1552 thing.__objclass__.__module__, thing.__objclass__.__name__,
1553 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001554 if inspect.isclass(thing):
1555 return 'class ' + thing.__name__
1556 if inspect.isfunction(thing):
1557 return 'function ' + thing.__name__
1558 if inspect.ismethod(thing):
1559 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001560 return type(thing).__name__
1561
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001562def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001563 """Locate an object by name or dotted path, importing as necessary."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001564 parts = [part for part in path.split('.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001565 module, n = None, 0
1566 while n < len(parts):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001567 nextmodule = safeimport('.'.join(parts[:n+1]), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001568 if nextmodule: module, n = nextmodule, n + 1
1569 else: break
1570 if module:
1571 object = module
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001572 else:
Éric Araujoe64e51b2011-07-29 17:03:55 +02001573 object = builtins
1574 for part in parts[n:]:
1575 try:
1576 object = getattr(object, part)
1577 except AttributeError:
1578 return None
1579 return object
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001580
1581# --------------------------------------- interactive interpreter interface
1582
1583text = TextDoc()
Georg Brandld80d5f42010-12-03 07:47:22 +00001584plaintext = _PlainTextDoc()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001585html = HTMLDoc()
1586
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001587def resolve(thing, forceload=0):
1588 """Given an object or a path to an object, get the object and its name."""
1589 if isinstance(thing, str):
1590 object = locate(thing, forceload)
1591 if not object:
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001592 raise ImportError('''\
1593No Python documentation found for %r.
1594Use help() to get the interactive help utility.
1595Use help(str) for help on the str class.''' % thing)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001596 return object, thing
1597 else:
R David Murrayc43125a2012-04-23 13:23:57 -04001598 name = getattr(thing, '__name__', None)
1599 return thing, name if isinstance(name, str) else None
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001600
Georg Brandld80d5f42010-12-03 07:47:22 +00001601def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
1602 renderer=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001603 """Render text documentation, given an object or a path to an object."""
Georg Brandld80d5f42010-12-03 07:47:22 +00001604 if renderer is None:
1605 renderer = text
Guido van Rossumd8faa362007-04-27 19:54:29 +00001606 object, name = resolve(thing, forceload)
1607 desc = describe(object)
1608 module = inspect.getmodule(object)
1609 if name and '.' in name:
1610 desc += ' in ' + name[:name.rfind('.')]
1611 elif module and module is not object:
1612 desc += ' in module ' + module.__name__
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001613
1614 if not (inspect.ismodule(object) or
Guido van Rossumd8faa362007-04-27 19:54:29 +00001615 inspect.isclass(object) or
1616 inspect.isroutine(object) or
1617 inspect.isgetsetdescriptor(object) or
1618 inspect.ismemberdescriptor(object) or
1619 isinstance(object, property)):
1620 # If the passed object is a piece of data or an instance,
1621 # document its available methods instead of its value.
1622 object = type(object)
1623 desc += ' object'
Georg Brandld80d5f42010-12-03 07:47:22 +00001624 return title % desc + '\n\n' + renderer.document(object, name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001625
Georg Brandld80d5f42010-12-03 07:47:22 +00001626def doc(thing, title='Python Library Documentation: %s', forceload=0,
1627 output=None):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001628 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001629 try:
Georg Brandld80d5f42010-12-03 07:47:22 +00001630 if output is None:
1631 pager(render_doc(thing, title, forceload))
1632 else:
1633 output.write(render_doc(thing, title, forceload, plaintext))
Guido van Rossumb940e112007-01-10 16:19:56 +00001634 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001635 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001636
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001637def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001638 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001639 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001640 object, name = resolve(thing, forceload)
1641 page = html.page(describe(object), html.document(object, name))
Serhiy Storchaka46ba6c82015-04-04 11:01:02 +03001642 with open(name + '.html', 'w', encoding='utf-8') as file:
1643 file.write(page)
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001644 print('wrote', name + '.html')
Guido van Rossumb940e112007-01-10 16:19:56 +00001645 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001646 print(value)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001647
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001648def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001649 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001650 if done is None: done = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001651 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1652 writedoc(modname)
1653 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001654
1655class Helper:
Georg Brandl6b38daa2008-06-01 21:05:17 +00001656
1657 # These dictionaries map a topic name to either an alias, or a tuple
1658 # (label, seealso-items). The "label" is the label of the corresponding
1659 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl5617db82009-04-27 16:28:57 +00001660 # in pydoc_data/topics.py.
Georg Brandl6b38daa2008-06-01 21:05:17 +00001661 #
1662 # CAUTION: if you change one of these dictionaries, be sure to adapt the
Georg Brandl61bd1dc2014-09-30 22:56:38 +02001663 # list of needed labels in Doc/tools/pyspecific.py and
Georg Brandl5617db82009-04-27 16:28:57 +00001664 # regenerate the pydoc_data/topics.py file by running
Georg Brandl6b38daa2008-06-01 21:05:17 +00001665 # make pydoc-topics
1666 # in Doc/ and copying the output file into the Lib/ directory.
1667
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001668 keywords = {
Ezio Melottib185a042011-04-28 07:42:55 +03001669 'False': '',
1670 'None': '',
1671 'True': '',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001672 'and': 'BOOLEAN',
Guido van Rossumd8faa362007-04-27 19:54:29 +00001673 'as': 'with',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001674 'assert': ('assert', ''),
1675 'break': ('break', 'while for'),
1676 'class': ('class', 'CLASSES SPECIALMETHODS'),
1677 'continue': ('continue', 'while for'),
1678 'def': ('function', ''),
1679 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001680 'elif': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001681 'else': ('else', 'while for'),
Georg Brandl0d855392008-08-30 19:53:05 +00001682 'except': 'try',
1683 'finally': 'try',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001684 'for': ('for', 'break continue while'),
Georg Brandl0d855392008-08-30 19:53:05 +00001685 'from': 'import',
Georg Brandl74abf6f2010-11-20 19:54:36 +00001686 'global': ('global', 'nonlocal NAMESPACES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001687 'if': ('if', 'TRUTHVALUE'),
1688 'import': ('import', 'MODULES'),
Georg Brandl395ed242009-09-04 08:07:32 +00001689 'in': ('in', 'SEQUENCEMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001690 'is': 'COMPARISON',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001691 'lambda': ('lambda', 'FUNCTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001692 'nonlocal': ('nonlocal', 'global NAMESPACES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001693 'not': 'BOOLEAN',
1694 'or': 'BOOLEAN',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001695 'pass': ('pass', ''),
1696 'raise': ('raise', 'EXCEPTIONS'),
1697 'return': ('return', 'FUNCTIONS'),
1698 'try': ('try', 'EXCEPTIONS'),
1699 'while': ('while', 'break continue if TRUTHVALUE'),
1700 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1701 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001702 }
Georg Brandldb7b6b92009-01-01 15:53:14 +00001703 # Either add symbols to this dictionary or to the symbols dictionary
1704 # directly: Whichever is easier. They are merged later.
1705 _symbols_inverse = {
1706 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'),
1707 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1708 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1709 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1710 'UNARY' : ('-', '~'),
1711 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1712 '^=', '<<=', '>>=', '**=', '//='),
1713 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1714 'COMPLEX' : ('j', 'J')
1715 }
1716 symbols = {
1717 '%': 'OPERATORS FORMATTING',
1718 '**': 'POWER',
1719 ',': 'TUPLES LISTS FUNCTIONS',
1720 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1721 '...': 'ELLIPSIS',
1722 ':': 'SLICINGS DICTIONARYLITERALS',
1723 '@': 'def class',
1724 '\\': 'STRINGS',
1725 '_': 'PRIVATENAMES',
1726 '__': 'PRIVATENAMES SPECIALMETHODS',
1727 '`': 'BACKQUOTES',
1728 '(': 'TUPLES FUNCTIONS CALLS',
1729 ')': 'TUPLES FUNCTIONS CALLS',
1730 '[': 'LISTS SUBSCRIPTS SLICINGS',
1731 ']': 'LISTS SUBSCRIPTS SLICINGS'
1732 }
1733 for topic, symbols_ in _symbols_inverse.items():
1734 for symbol in symbols_:
1735 topics = symbols.get(symbol, topic)
1736 if topic not in topics:
1737 topics = topics + ' ' + topic
1738 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001739
1740 topics = {
Georg Brandl6b38daa2008-06-01 21:05:17 +00001741 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1742 'FUNCTIONS CLASSES MODULES FILES inspect'),
1743 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS '
1744 'FORMATTING TYPES'),
1745 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1746 'FORMATTING': ('formatstrings', 'OPERATORS'),
1747 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1748 'FORMATTING TYPES'),
1749 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1750 'INTEGER': ('integers', 'int range'),
1751 'FLOAT': ('floating', 'float math'),
1752 'COMPLEX': ('imaginary', 'complex cmath'),
1753 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING range LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001754 'MAPPINGS': 'DICTIONARIES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001755 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1756 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1757 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1758 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001759 'FRAMEOBJECTS': 'TYPES',
1760 'TRACEBACKS': 'TYPES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001761 'NONE': ('bltin-null-object', ''),
1762 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001763 'SPECIALATTRIBUTES': ('specialattrs', ''),
1764 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1765 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001766 'PACKAGES': 'import',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001767 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1768 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1769 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1770 'LISTS DICTIONARIES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001771 'OPERATORS': 'EXPRESSIONS',
1772 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001773 'OBJECTS': ('objects', 'TYPES'),
1774 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
Georg Brandl395ed242009-09-04 08:07:32 +00001775 'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS '
1776 'NUMBERMETHODS CLASSES'),
Mark Dickinsona56c4672009-01-27 18:17:45 +00001777 'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001778 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1779 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001780 'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS '
Georg Brandl6b38daa2008-06-01 21:05:17 +00001781 'SPECIALMETHODS'),
1782 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1783 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1784 'SPECIALMETHODS'),
1785 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001786 'NAMESPACES': ('naming', 'global nonlocal ASSIGNMENT DELETION DYNAMICFEATURES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001787 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001788 'SCOPING': 'NAMESPACES',
1789 'FRAMES': 'NAMESPACES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001790 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1791 'CONVERSIONS': ('conversions', ''),
1792 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1793 'SPECIALIDENTIFIERS': ('id-classes', ''),
1794 'PRIVATENAMES': ('atom-identifiers', ''),
1795 'LITERALS': ('atom-literals', 'STRINGS NUMBERS TUPLELITERALS '
1796 'LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001797 'TUPLES': 'SEQUENCES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001798 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1799 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1800 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1801 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1802 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1803 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001804 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'),
1805 'SLICINGS': ('slicings', 'SEQUENCEMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001806 'CALLS': ('calls', 'EXPRESSIONS'),
1807 'POWER': ('power', 'EXPRESSIONS'),
1808 'UNARY': ('unary', 'EXPRESSIONS'),
1809 'BINARY': ('binary', 'EXPRESSIONS'),
1810 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1811 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1812 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1813 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001814 'ASSERTION': 'assert',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001815 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1816 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001817 'DELETION': 'del',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001818 'RETURNING': 'return',
1819 'IMPORTING': 'import',
1820 'CONDITIONAL': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001821 'LOOPING': ('compound', 'for while break continue'),
1822 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1823 'DEBUGGING': ('debugger', 'pdb'),
1824 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001825 }
1826
Georg Brandl78aa3962010-07-31 21:51:48 +00001827 def __init__(self, input=None, output=None):
1828 self._input = input
1829 self._output = output
1830
Georg Brandl76ae3972010-08-01 06:32:55 +00001831 input = property(lambda self: self._input or sys.stdin)
1832 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001833
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001834 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001835 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001836 self()
1837 return ''
Serhiy Storchaka465e60e2014-07-25 23:36:00 +03001838 return '<%s.%s instance>' % (self.__class__.__module__,
1839 self.__class__.__qualname__)
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001840
Alexander Belopolsky2e733c92010-07-04 17:00:20 +00001841 _GoInteractive = object()
1842 def __call__(self, request=_GoInteractive):
1843 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001844 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001845 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001846 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001847 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001848 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001849You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001850If you want to ask for help on a particular object directly from the
1851interpreter, you can type "help(object)". Executing "help('string')"
1852has the same effect as typing a particular string at the help> prompt.
1853''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001854
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001855 def interact(self):
1856 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001857 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001858 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001859 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001860 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001861 except (KeyboardInterrupt, EOFError):
1862 break
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001863 request = replace(request, '"', '', "'", '').strip()
1864 if request.lower() in ('q', 'quit'): break
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001865 if request == 'help':
1866 self.intro()
1867 else:
1868 self.help(request)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001869
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001870 def getline(self, prompt):
Guido van Rossum7c086c02008-01-02 03:52:38 +00001871 """Read one line, using input() when appropriate."""
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001872 if self.input is sys.stdin:
Guido van Rossum7c086c02008-01-02 03:52:38 +00001873 return input(prompt)
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001874 else:
1875 self.output.write(prompt)
1876 self.output.flush()
1877 return self.input.readline()
1878
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001879 def help(self, request):
1880 if type(request) is type(''):
R. David Murray1f1b9d32009-05-27 20:56:59 +00001881 request = request.strip()
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001882 if request == 'keywords': self.listkeywords()
Georg Brandldb7b6b92009-01-01 15:53:14 +00001883 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001884 elif request == 'topics': self.listtopics()
1885 elif request == 'modules': self.listmodules()
1886 elif request[:8] == 'modules ':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001887 self.listmodules(request.split()[1])
Georg Brandldb7b6b92009-01-01 15:53:14 +00001888 elif request in self.symbols: self.showsymbol(request)
Ezio Melottib185a042011-04-28 07:42:55 +03001889 elif request in ['True', 'False', 'None']:
1890 # special case these keywords since they are objects too
1891 doc(eval(request), 'Help on %s:')
Raymond Hettinger54f02222002-06-01 14:18:47 +00001892 elif request in self.keywords: self.showtopic(request)
1893 elif request in self.topics: self.showtopic(request)
Georg Brandld80d5f42010-12-03 07:47:22 +00001894 elif request: doc(request, 'Help on %s:', output=self._output)
Serhiy Storchaka1c205512015-03-01 00:42:54 +02001895 else: doc(str, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001896 elif isinstance(request, Helper): self()
Georg Brandld80d5f42010-12-03 07:47:22 +00001897 else: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001898 self.output.write('\n')
1899
1900 def intro(self):
1901 self.output.write('''
R David Murray3d050dd2014-04-19 12:59:30 -04001902Welcome to Python %s's help utility!
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001903
1904If this is your first time using Python, you should definitely check out
R David Murrayde0f6292012-03-31 12:06:35 -04001905the tutorial on the Internet at http://docs.python.org/%s/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001906
1907Enter the name of any module, keyword, or topic to get help on writing
1908Python programs and using Python modules. To quit this help utility and
1909return to the interpreter, just type "quit".
1910
Terry Jan Reedy34200572013-02-11 02:23:13 -05001911To get a list of available modules, keywords, symbols, or topics, type
1912"modules", "keywords", "symbols", or "topics". Each module also comes
1913with a one-line summary of what it does; to list the modules whose name
1914or summary contain a given string such as "spam", type "modules spam".
R David Murrayde0f6292012-03-31 12:06:35 -04001915''' % tuple([sys.version[:3]]*2))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001916
1917 def list(self, items, columns=4, width=80):
Guido van Rossum486364b2007-06-30 05:01:58 +00001918 items = list(sorted(items))
1919 colw = width // columns
1920 rows = (len(items) + columns - 1) // columns
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001921 for row in range(rows):
1922 for col in range(columns):
1923 i = col * rows + row
1924 if i < len(items):
1925 self.output.write(items[i])
1926 if col < columns - 1:
Guido van Rossum486364b2007-06-30 05:01:58 +00001927 self.output.write(' ' + ' ' * (colw - 1 - len(items[i])))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001928 self.output.write('\n')
1929
1930 def listkeywords(self):
1931 self.output.write('''
1932Here is a list of the Python keywords. Enter any keyword to get more help.
1933
1934''')
1935 self.list(self.keywords.keys())
1936
Georg Brandldb7b6b92009-01-01 15:53:14 +00001937 def listsymbols(self):
1938 self.output.write('''
1939Here is a list of the punctuation symbols which Python assigns special meaning
1940to. Enter any symbol to get more help.
1941
1942''')
1943 self.list(self.symbols.keys())
1944
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001945 def listtopics(self):
1946 self.output.write('''
1947Here is a list of available topics. Enter any topic name to get more help.
1948
1949''')
1950 self.list(self.topics.keys())
1951
Georg Brandldb7b6b92009-01-01 15:53:14 +00001952 def showtopic(self, topic, more_xrefs=''):
Georg Brandl6b38daa2008-06-01 21:05:17 +00001953 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001954 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04001955 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001956 self.output.write('''
Georg Brandl6b38daa2008-06-01 21:05:17 +00001957Sorry, topic and keyword documentation is not available because the
Georg Brandl5617db82009-04-27 16:28:57 +00001958module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001959''')
1960 return
1961 target = self.topics.get(topic, self.keywords.get(topic))
1962 if not target:
1963 self.output.write('no documentation found for %s\n' % repr(topic))
1964 return
1965 if type(target) is type(''):
Georg Brandldb7b6b92009-01-01 15:53:14 +00001966 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001967
Georg Brandl6b38daa2008-06-01 21:05:17 +00001968 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001969 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001970 doc = pydoc_data.topics.topics[label]
Georg Brandl6b38daa2008-06-01 21:05:17 +00001971 except KeyError:
1972 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001973 return
Georg Brandl6b38daa2008-06-01 21:05:17 +00001974 pager(doc.strip() + '\n')
Georg Brandldb7b6b92009-01-01 15:53:14 +00001975 if more_xrefs:
1976 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001977 if xrefs:
Brett Cannon1448ecf2013-10-04 11:38:59 -04001978 import textwrap
1979 text = 'Related help topics: ' + ', '.join(xrefs.split()) + '\n'
1980 wrapped_text = textwrap.wrap(text, 72)
1981 self.output.write('\n%s\n' % ''.join(wrapped_text))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001982
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001983 def _gettopic(self, topic, more_xrefs=''):
1984 """Return unbuffered tuple of (topic, xrefs).
1985
Georg Brandld2f38572011-01-30 08:37:19 +00001986 If an error occurs here, the exception is caught and displayed by
1987 the url handler.
1988
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001989 This function duplicates the showtopic method but returns its
1990 result directly so it can be formatted for display in an html page.
1991 """
1992 try:
1993 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04001994 except ImportError:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001995 return('''
1996Sorry, topic and keyword documentation is not available because the
1997module "pydoc_data.topics" could not be found.
1998''' , '')
1999 target = self.topics.get(topic, self.keywords.get(topic))
2000 if not target:
Georg Brandld2f38572011-01-30 08:37:19 +00002001 raise ValueError('could not find topic')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002002 if isinstance(target, str):
2003 return self._gettopic(target, more_xrefs)
2004 label, xrefs = target
Georg Brandld2f38572011-01-30 08:37:19 +00002005 doc = pydoc_data.topics.topics[label]
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002006 if more_xrefs:
2007 xrefs = (xrefs or '') + ' ' + more_xrefs
2008 return doc, xrefs
2009
Georg Brandldb7b6b92009-01-01 15:53:14 +00002010 def showsymbol(self, symbol):
2011 target = self.symbols[symbol]
2012 topic, _, xrefs = target.partition(' ')
2013 self.showtopic(topic, xrefs)
2014
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002015 def listmodules(self, key=''):
2016 if key:
2017 self.output.write('''
Terry Jan Reedy34200572013-02-11 02:23:13 -05002018Here is a list of modules whose name or summary contains '{}'.
2019If there are any, enter a module name to get more help.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002020
Terry Jan Reedy34200572013-02-11 02:23:13 -05002021'''.format(key))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002022 apropos(key)
2023 else:
2024 self.output.write('''
2025Please wait a moment while I gather a list of all available modules...
2026
2027''')
2028 modules = {}
2029 def callback(path, modname, desc, modules=modules):
2030 if modname and modname[-9:] == '.__init__':
2031 modname = modname[:-9] + ' (package)'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002032 if modname.find('.') < 0:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002033 modules[modname] = 1
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002034 def onerror(modname):
2035 callback(None, modname, None)
2036 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002037 self.list(modules.keys())
2038 self.output.write('''
2039Enter any module name to get more help. Or, type "modules spam" to search
Terry Jan Reedy34200572013-02-11 02:23:13 -05002040for modules whose name or summary contain the string "spam".
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002041''')
2042
Georg Brandl78aa3962010-07-31 21:51:48 +00002043help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002044
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002045class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002046 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002047
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002048 def run(self, callback, key=None, completer=None, onerror=None):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002049 if key: key = key.lower()
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002050 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002051 seen = {}
2052
2053 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002054 if modname != '__main__':
2055 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00002056 if key is None:
2057 callback(None, modname, '')
2058 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002059 name = __import__(modname).__doc__ or ''
2060 desc = name.split('\n')[0]
2061 name = modname + ' - ' + desc
2062 if name.lower().find(key) >= 0:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002063 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002064
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002065 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002066 if self.quit:
2067 break
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002068
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002069 if key is None:
2070 callback(None, modname, '')
2071 else:
Georg Brandl126c8792009-04-05 15:05:48 +00002072 try:
Eric Snow3a62d142014-01-06 20:42:59 -07002073 spec = pkgutil._get_spec(importer, modname)
Georg Brandl126c8792009-04-05 15:05:48 +00002074 except SyntaxError:
2075 # raised by tests for bad coding cookies or BOM
2076 continue
Eric Snow3a62d142014-01-06 20:42:59 -07002077 loader = spec.loader
Georg Brandl126c8792009-04-05 15:05:48 +00002078 if hasattr(loader, 'get_source'):
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002079 try:
2080 source = loader.get_source(modname)
Nick Coghlan2824cb52012-07-15 22:12:14 +10002081 except Exception:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002082 if onerror:
2083 onerror(modname)
2084 continue
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002085 desc = source_synopsis(io.StringIO(source)) or ''
Georg Brandl126c8792009-04-05 15:05:48 +00002086 if hasattr(loader, 'get_filename'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002087 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002088 else:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002089 path = None
2090 else:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002091 try:
Brett Cannon2a17bde2014-05-30 14:55:29 -04002092 module = importlib._bootstrap._load(spec)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002093 except ImportError:
2094 if onerror:
2095 onerror(modname)
2096 continue
Benjamin Peterson54237f92015-02-16 19:45:01 -05002097 desc = module.__doc__.splitlines()[0] if module.__doc__ else ''
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002098 path = getattr(module,'__file__',None)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002099 name = modname + ' - ' + desc
2100 if name.lower().find(key) >= 0:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002101 callback(path, modname, desc)
2102
2103 if completer:
2104 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002105
2106def apropos(key):
2107 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002108 def callback(path, modname, desc):
2109 if modname[-9:] == '.__init__':
2110 modname = modname[:-9] + ' (package)'
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002111 print(modname, desc and '- ' + desc)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002112 def onerror(modname):
2113 pass
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002114 with warnings.catch_warnings():
2115 warnings.filterwarnings('ignore') # ignore problems during import
2116 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002117
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002118# --------------------------------------- enhanced Web browser interface
2119
2120def _start_server(urlhandler, port):
2121 """Start an HTTP server thread on a specific port.
2122
2123 Start an HTML/text server thread, so HTML or text documents can be
2124 browsed dynamically and interactively with a Web browser. Example use:
2125
2126 >>> import time
2127 >>> import pydoc
2128
2129 Define a URL handler. To determine what the client is asking
2130 for, check the URL and content_type.
2131
2132 Then get or generate some text or HTML code and return it.
2133
2134 >>> def my_url_handler(url, content_type):
2135 ... text = 'the URL sent was: (%s, %s)' % (url, content_type)
2136 ... return text
2137
2138 Start server thread on port 0.
2139 If you use port 0, the server will pick a random port number.
2140 You can then use serverthread.port to get the port number.
2141
2142 >>> port = 0
2143 >>> serverthread = pydoc._start_server(my_url_handler, port)
2144
2145 Check that the server is really started. If it is, open browser
2146 and get first page. Use serverthread.url as the starting page.
2147
2148 >>> if serverthread.serving:
2149 ... import webbrowser
2150
2151 The next two lines are commented out so a browser doesn't open if
2152 doctest is run on this module.
2153
2154 #... webbrowser.open(serverthread.url)
2155 #True
2156
2157 Let the server do its thing. We just need to monitor its status.
2158 Use time.sleep so the loop doesn't hog the CPU.
2159
2160 >>> starttime = time.time()
2161 >>> timeout = 1 #seconds
2162
2163 This is a short timeout for testing purposes.
2164
2165 >>> while serverthread.serving:
2166 ... time.sleep(.01)
2167 ... if serverthread.serving and time.time() - starttime > timeout:
2168 ... serverthread.stop()
2169 ... break
2170
2171 Print any errors that may have occurred.
2172
2173 >>> print(serverthread.error)
2174 None
2175 """
2176 import http.server
2177 import email.message
2178 import select
2179 import threading
2180
2181 class DocHandler(http.server.BaseHTTPRequestHandler):
2182
2183 def do_GET(self):
2184 """Process a request from an HTML browser.
2185
2186 The URL received is in self.path.
2187 Get an HTML page from self.urlhandler and send it.
2188 """
2189 if self.path.endswith('.css'):
2190 content_type = 'text/css'
2191 else:
2192 content_type = 'text/html'
2193 self.send_response(200)
Georg Brandld2f38572011-01-30 08:37:19 +00002194 self.send_header('Content-Type', '%s; charset=UTF-8' % content_type)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002195 self.end_headers()
2196 self.wfile.write(self.urlhandler(
2197 self.path, content_type).encode('utf-8'))
2198
2199 def log_message(self, *args):
2200 # Don't log messages.
2201 pass
2202
2203 class DocServer(http.server.HTTPServer):
2204
2205 def __init__(self, port, callback):
Senthil Kumaran2a42a0b2014-09-17 13:17:58 +08002206 self.host = 'localhost'
2207 self.address = (self.host, port)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002208 self.callback = callback
2209 self.base.__init__(self, self.address, self.handler)
2210 self.quit = False
2211
2212 def serve_until_quit(self):
2213 while not self.quit:
2214 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2215 if rd:
2216 self.handle_request()
Victor Stinnera3abd1d2011-01-03 16:12:39 +00002217 self.server_close()
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002218
2219 def server_activate(self):
2220 self.base.server_activate(self)
2221 if self.callback:
2222 self.callback(self)
2223
2224 class ServerThread(threading.Thread):
2225
2226 def __init__(self, urlhandler, port):
2227 self.urlhandler = urlhandler
2228 self.port = int(port)
2229 threading.Thread.__init__(self)
2230 self.serving = False
2231 self.error = None
2232
2233 def run(self):
2234 """Start the server."""
2235 try:
2236 DocServer.base = http.server.HTTPServer
2237 DocServer.handler = DocHandler
2238 DocHandler.MessageClass = email.message.Message
2239 DocHandler.urlhandler = staticmethod(self.urlhandler)
2240 docsvr = DocServer(self.port, self.ready)
2241 self.docserver = docsvr
2242 docsvr.serve_until_quit()
2243 except Exception as e:
2244 self.error = e
2245
2246 def ready(self, server):
2247 self.serving = True
2248 self.host = server.host
2249 self.port = server.server_port
2250 self.url = 'http://%s:%d/' % (self.host, self.port)
2251
2252 def stop(self):
2253 """Stop the server and this thread nicely"""
2254 self.docserver.quit = True
2255 self.serving = False
2256 self.url = None
2257
2258 thread = ServerThread(urlhandler, port)
2259 thread.start()
2260 # Wait until thread.serving is True to make sure we are
2261 # really up before returning.
2262 while not thread.error and not thread.serving:
2263 time.sleep(.01)
2264 return thread
2265
2266
2267def _url_handler(url, content_type="text/html"):
2268 """The pydoc url handler for use with the pydoc server.
2269
2270 If the content_type is 'text/css', the _pydoc.css style
2271 sheet is read and returned if it exits.
2272
2273 If the content_type is 'text/html', then the result of
2274 get_html_page(url) is returned.
2275 """
2276 class _HTMLDoc(HTMLDoc):
2277
2278 def page(self, title, contents):
2279 """Format an HTML page."""
2280 css_path = "pydoc_data/_pydoc.css"
2281 css_link = (
2282 '<link rel="stylesheet" type="text/css" href="%s">' %
2283 css_path)
2284 return '''\
2285<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Georg Brandld2f38572011-01-30 08:37:19 +00002286<html><head><title>Pydoc: %s</title>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002287<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Georg Brandld2f38572011-01-30 08:37:19 +00002288%s</head><body bgcolor="#f0f0f8">%s<div style="clear:both;padding-top:.5em;">%s</div>
2289</body></html>''' % (title, css_link, html_navbar(), contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002290
2291 def filelink(self, url, path):
2292 return '<a href="getfile?key=%s">%s</a>' % (url, path)
2293
2294
2295 html = _HTMLDoc()
2296
2297 def html_navbar():
Georg Brandld2f38572011-01-30 08:37:19 +00002298 version = html.escape("%s [%s, %s]" % (platform.python_version(),
2299 platform.python_build()[0],
2300 platform.python_compiler()))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002301 return """
2302 <div style='float:left'>
Georg Brandld2f38572011-01-30 08:37:19 +00002303 Python %s<br>%s
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002304 </div>
2305 <div style='float:right'>
2306 <div style='text-align:center'>
2307 <a href="index.html">Module Index</a>
2308 : <a href="topics.html">Topics</a>
2309 : <a href="keywords.html">Keywords</a>
2310 </div>
2311 <div>
Georg Brandld2f38572011-01-30 08:37:19 +00002312 <form action="get" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002313 <input type=text name=key size=15>
2314 <input type=submit value="Get">
Georg Brandld2f38572011-01-30 08:37:19 +00002315 </form>&nbsp;
2316 <form action="search" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002317 <input type=text name=key size=15>
2318 <input type=submit value="Search">
2319 </form>
2320 </div>
2321 </div>
Georg Brandld2f38572011-01-30 08:37:19 +00002322 """ % (version, html.escape(platform.platform(terse=True)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002323
2324 def html_index():
2325 """Module Index page."""
2326
2327 def bltinlink(name):
2328 return '<a href="%s.html">%s</a>' % (name, name)
2329
2330 heading = html.heading(
2331 '<big><big><strong>Index of Modules</strong></big></big>',
2332 '#ffffff', '#7799ee')
2333 names = [name for name in sys.builtin_module_names
2334 if name != '__main__']
2335 contents = html.multicolumn(names, bltinlink)
2336 contents = [heading, '<p>' + html.bigsection(
2337 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2338
2339 seen = {}
2340 for dir in sys.path:
2341 contents.append(html.index(dir, seen))
2342
2343 contents.append(
2344 '<p align=right><font color="#909090" face="helvetica,'
2345 'arial"><strong>pydoc</strong> by Ka-Ping Yee'
2346 '&lt;ping@lfw.org&gt;</font>')
Nick Coghlanecace282010-12-03 16:08:46 +00002347 return 'Index of Modules', ''.join(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002348
2349 def html_search(key):
2350 """Search results page."""
2351 # scan for modules
2352 search_result = []
2353
2354 def callback(path, modname, desc):
2355 if modname[-9:] == '.__init__':
2356 modname = modname[:-9] + ' (package)'
2357 search_result.append((modname, desc and '- ' + desc))
2358
2359 with warnings.catch_warnings():
2360 warnings.filterwarnings('ignore') # ignore problems during import
2361 ModuleScanner().run(callback, key)
2362
2363 # format page
2364 def bltinlink(name):
2365 return '<a href="%s.html">%s</a>' % (name, name)
2366
2367 results = []
2368 heading = html.heading(
2369 '<big><big><strong>Search Results</strong></big></big>',
2370 '#ffffff', '#7799ee')
2371 for name, desc in search_result:
2372 results.append(bltinlink(name) + desc)
2373 contents = heading + html.bigsection(
2374 'key = %s' % key, '#ffffff', '#ee77aa', '<br>'.join(results))
Nick Coghlanecace282010-12-03 16:08:46 +00002375 return 'Search Results', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002376
2377 def html_getfile(path):
2378 """Get and display a source file listing safely."""
Zachary Wareeb432142014-07-10 11:18:00 -05002379 path = urllib.parse.unquote(path)
Victor Stinner91e08772011-07-05 14:30:41 +02002380 with tokenize.open(path) as fp:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002381 lines = html.escape(fp.read())
2382 body = '<pre>%s</pre>' % lines
2383 heading = html.heading(
2384 '<big><big><strong>File Listing</strong></big></big>',
2385 '#ffffff', '#7799ee')
2386 contents = heading + html.bigsection(
2387 'File: %s' % path, '#ffffff', '#ee77aa', body)
Nick Coghlanecace282010-12-03 16:08:46 +00002388 return 'getfile %s' % path, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002389
2390 def html_topics():
2391 """Index of topic texts available."""
2392
2393 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002394 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002395
2396 heading = html.heading(
2397 '<big><big><strong>INDEX</strong></big></big>',
2398 '#ffffff', '#7799ee')
2399 names = sorted(Helper.topics.keys())
2400
2401 contents = html.multicolumn(names, bltinlink)
2402 contents = heading + html.bigsection(
2403 'Topics', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002404 return 'Topics', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002405
2406 def html_keywords():
2407 """Index of keywords."""
2408 heading = html.heading(
2409 '<big><big><strong>INDEX</strong></big></big>',
2410 '#ffffff', '#7799ee')
2411 names = sorted(Helper.keywords.keys())
2412
2413 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002414 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002415
2416 contents = html.multicolumn(names, bltinlink)
2417 contents = heading + html.bigsection(
2418 'Keywords', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002419 return 'Keywords', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002420
2421 def html_topicpage(topic):
2422 """Topic or keyword help page."""
2423 buf = io.StringIO()
2424 htmlhelp = Helper(buf, buf)
2425 contents, xrefs = htmlhelp._gettopic(topic)
2426 if topic in htmlhelp.keywords:
2427 title = 'KEYWORD'
2428 else:
2429 title = 'TOPIC'
2430 heading = html.heading(
2431 '<big><big><strong>%s</strong></big></big>' % title,
2432 '#ffffff', '#7799ee')
Georg Brandld2f38572011-01-30 08:37:19 +00002433 contents = '<pre>%s</pre>' % html.markup(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002434 contents = html.bigsection(topic , '#ffffff','#ee77aa', contents)
Georg Brandld2f38572011-01-30 08:37:19 +00002435 if xrefs:
2436 xrefs = sorted(xrefs.split())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002437
Georg Brandld2f38572011-01-30 08:37:19 +00002438 def bltinlink(name):
2439 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002440
Georg Brandld2f38572011-01-30 08:37:19 +00002441 xrefs = html.multicolumn(xrefs, bltinlink)
2442 xrefs = html.section('Related help topics: ',
2443 '#ffffff', '#ee77aa', xrefs)
Nick Coghlanecace282010-12-03 16:08:46 +00002444 return ('%s %s' % (title, topic),
2445 ''.join((heading, contents, xrefs)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002446
Georg Brandld2f38572011-01-30 08:37:19 +00002447 def html_getobj(url):
2448 obj = locate(url, forceload=1)
2449 if obj is None and url != 'None':
2450 raise ValueError('could not find object')
2451 title = describe(obj)
2452 content = html.document(obj, url)
2453 return title, content
2454
2455 def html_error(url, exc):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002456 heading = html.heading(
2457 '<big><big><strong>Error</strong></big></big>',
Georg Brandld2f38572011-01-30 08:37:19 +00002458 '#ffffff', '#7799ee')
2459 contents = '<br>'.join(html.escape(line) for line in
2460 format_exception_only(type(exc), exc))
2461 contents = heading + html.bigsection(url, '#ffffff', '#bb0000',
2462 contents)
2463 return "Error - %s" % url, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002464
2465 def get_html_page(url):
2466 """Generate an HTML page for url."""
Georg Brandld2f38572011-01-30 08:37:19 +00002467 complete_url = url
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002468 if url.endswith('.html'):
2469 url = url[:-5]
Georg Brandld2f38572011-01-30 08:37:19 +00002470 try:
2471 if url in ("", "index"):
2472 title, content = html_index()
2473 elif url == "topics":
2474 title, content = html_topics()
2475 elif url == "keywords":
2476 title, content = html_keywords()
2477 elif '=' in url:
2478 op, _, url = url.partition('=')
2479 if op == "search?key":
2480 title, content = html_search(url)
2481 elif op == "getfile?key":
2482 title, content = html_getfile(url)
2483 elif op == "topic?key":
2484 # try topics first, then objects.
2485 try:
2486 title, content = html_topicpage(url)
2487 except ValueError:
2488 title, content = html_getobj(url)
2489 elif op == "get?key":
2490 # try objects first, then topics.
2491 if url in ("", "index"):
2492 title, content = html_index()
2493 else:
2494 try:
2495 title, content = html_getobj(url)
2496 except ValueError:
2497 title, content = html_topicpage(url)
2498 else:
2499 raise ValueError('bad pydoc url')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002500 else:
Georg Brandld2f38572011-01-30 08:37:19 +00002501 title, content = html_getobj(url)
2502 except Exception as exc:
2503 # Catch any errors and display them in an error page.
2504 title, content = html_error(complete_url, exc)
2505 return html.page(title, content)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002506
2507 if url.startswith('/'):
2508 url = url[1:]
2509 if content_type == 'text/css':
2510 path_here = os.path.dirname(os.path.realpath(__file__))
Georg Brandld2f38572011-01-30 08:37:19 +00002511 css_path = os.path.join(path_here, url)
2512 with open(css_path) as fp:
2513 return ''.join(fp.readlines())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002514 elif content_type == 'text/html':
2515 return get_html_page(url)
Georg Brandld2f38572011-01-30 08:37:19 +00002516 # Errors outside the url handler are caught by the server.
2517 raise TypeError('unknown content type %r for url %s' % (content_type, url))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002518
2519
2520def browse(port=0, *, open_browser=True):
2521 """Start the enhanced pydoc Web server and open a Web browser.
2522
2523 Use port '0' to start the server on an arbitrary port.
2524 Set open_browser to False to suppress opening a browser.
2525 """
2526 import webbrowser
2527 serverthread = _start_server(_url_handler, port)
2528 if serverthread.error:
2529 print(serverthread.error)
2530 return
2531 if serverthread.serving:
2532 server_help_msg = 'Server commands: [b]rowser, [q]uit'
2533 if open_browser:
2534 webbrowser.open(serverthread.url)
2535 try:
2536 print('Server ready at', serverthread.url)
2537 print(server_help_msg)
2538 while serverthread.serving:
2539 cmd = input('server> ')
2540 cmd = cmd.lower()
2541 if cmd == 'q':
2542 break
2543 elif cmd == 'b':
2544 webbrowser.open(serverthread.url)
2545 else:
2546 print(server_help_msg)
2547 except (KeyboardInterrupt, EOFError):
2548 print()
2549 finally:
2550 if serverthread.serving:
2551 serverthread.stop()
2552 print('Server stopped')
2553
2554
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002555# -------------------------------------------------- command-line interface
2556
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002557def ispath(x):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002558 return isinstance(x, str) and x.find(os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002559
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002560def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002561 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002562 import getopt
Guido van Rossum756aa932007-04-07 03:04:01 +00002563 class BadUsage(Exception): pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002564
Nick Coghlan106274b2009-11-15 23:04:33 +00002565 # Scripts don't get the current directory in their path by default
2566 # unless they are run with the '-m' switch
2567 if '' not in sys.path:
2568 scriptdir = os.path.dirname(sys.argv[0])
2569 if scriptdir in sys.path:
2570 sys.path.remove(scriptdir)
2571 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002572
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002573 try:
Victor Stinner383c3fc2011-05-25 01:35:05 +02002574 opts, args = getopt.getopt(sys.argv[1:], 'bk:p:w')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002575 writing = False
2576 start_server = False
2577 open_browser = False
2578 port = None
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002579 for opt, val in opts:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002580 if opt == '-b':
2581 start_server = True
2582 open_browser = True
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002583 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002584 apropos(val)
2585 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002586 if opt == '-p':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002587 start_server = True
2588 port = val
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002589 if opt == '-w':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002590 writing = True
2591
Benjamin Petersonb29614e2012-10-09 11:16:03 -04002592 if start_server:
2593 if port is None:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002594 port = 0
2595 browse(port, open_browser=open_browser)
2596 return
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002597
2598 if not args: raise BadUsage
2599 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002600 if ispath(arg) and not os.path.exists(arg):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002601 print('file %r does not exist' % arg)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002602 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002603 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002604 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002605 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002606 if writing:
2607 if ispath(arg) and os.path.isdir(arg):
2608 writedocs(arg)
2609 else:
2610 writedoc(arg)
2611 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002612 help.help(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +00002613 except ErrorDuringImport as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002614 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002615
2616 except (getopt.error, BadUsage):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002617 cmd = os.path.splitext(os.path.basename(sys.argv[0]))[0]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002618 print("""pydoc - the Python documentation tool
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002619
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002620{cmd} <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002621 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002622 Python keyword, topic, function, module, or package, or a dotted
2623 reference to a class or function within a module or module in a
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002624 package. If <name> contains a '{sep}', it is used as the path to a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002625 Python source file to document. If name is 'keywords', 'topics',
2626 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002627
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002628{cmd} -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002629 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002630
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002631{cmd} -p <port>
2632 Start an HTTP server on the given port on the local machine. Port
2633 number 0 can be used to get an arbitrary unused port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002634
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002635{cmd} -b
2636 Start an HTTP server on an arbitrary unused port and open a Web browser
2637 to interactively browse documentation. The -p option can be used with
2638 the -b option to explicitly specify the server port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002639
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002640{cmd} -w <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002641 Write out the HTML documentation for a module to a file in the current
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002642 directory. If <name> contains a '{sep}', it is treated as a filename; if
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002643 it names a directory, documentation is written for all the contents.
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002644""".format(cmd=cmd, sep=os.sep))
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002645
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002646if __name__ == '__main__':
2647 cli()