blob: 006212b32e50598fa69c88c4299304d90697f334 [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
Georg Brandlc645c6a2012-06-24 17:24:26 +02004In the Python interpreter, do "from pydoc import help" to provide
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00005help. Calling help(thing) on a Python object documents the object.
6
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00007Or, at the shell command line outside of Python:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00008
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00009Run "pydoc <name>" to show documentation on something. <name> may be
10the name of a function, module, package, or a dotted reference to a
11class or function within a module or module in a package. If the
12argument contains a path segment delimiter (e.g. slash on Unix,
13backslash on Windows) it is treated as the path to a Python source file.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000014
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000015Run "pydoc -k <keyword>" to search for a keyword in the synopsis lines
16of all available modules.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000017
Nick Coghlan7bb30b72010-12-03 09:29:11 +000018Run "pydoc -p <port>" to start an HTTP server on the given port on the
19local machine. Port number 0 can be used to get an arbitrary unused port.
20
21Run "pydoc -b" to start an HTTP server on an arbitrary unused port and
22open a Web browser to interactively browse documentation. The -p option
23can be used with the -b option to explicitly specify the server port.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000024
Ka-Ping Yee37f7b382001-03-23 00:12:53 +000025Run "pydoc -w <name>" to write out the HTML documentation for a module
26to a file named "<name>.html".
Skip Montanaro4997a692003-09-10 16:47:51 +000027
28Module docs for core modules are assumed to be in
29
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000030 http://docs.python.org/X.Y/library/
Skip Montanaro4997a692003-09-10 16:47:51 +000031
32This can be overridden by setting the PYTHONDOCS environment variable
33to a different URL or to a local directory containing the Library
34Reference Manual pages.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000035"""
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000036__all__ = ['help']
Ka-Ping Yeedd175342001-02-27 14:43:46 +000037__author__ = "Ka-Ping Yee <ping@lfw.org>"
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000038__date__ = "26 February 2001"
Jeremy Hylton3e0055f2005-10-20 19:59:25 +000039
Martin v. Löwis6fe8f192004-11-14 10:21:04 +000040__credits__ = """Guido van Rossum, for an excellent programming language.
Ka-Ping Yee5e2b1732001-02-27 23:35:09 +000041Tommy Burnette, the original creator of manpy.
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +000042Paul Prescod, for all his work on onlinehelp.
43Richard Chamberlain, for the first implementation of textdoc.
Raymond Hettingered2dbe32005-01-01 07:51:01 +000044"""
Ka-Ping Yeedd175342001-02-27 14:43:46 +000045
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000046# Known bugs that can't be fixed here:
Brett Cannonf4ba4ec2013-06-15 14:25:04 -040047# - synopsis() cannot be prevented from clobbering existing
48# loaded modules.
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000049# - If the __file__ attribute on a module is a relative path and
50# the current directory is changed with os.chdir(), an incorrect
51# path will be displayed.
Ka-Ping Yee66efbc72001-03-01 13:55:20 +000052
Nick Coghlan7bb30b72010-12-03 09:29:11 +000053import builtins
Brett Cannond5e6f2e2013-06-11 17:09:36 -040054import importlib._bootstrap
Brett Cannoncb66eb02012-05-11 12:58:42 -040055import importlib.machinery
Brett Cannonf4ba4ec2013-06-15 14:25:04 -040056import importlib.util
Nick Coghlan7bb30b72010-12-03 09:29:11 +000057import inspect
Victor Stinnere6c910e2011-06-30 15:55:43 +020058import io
59import os
Nick Coghlan7bb30b72010-12-03 09:29:11 +000060import pkgutil
61import platform
62import re
Victor Stinnere6c910e2011-06-30 15:55:43 +020063import sys
Nick Coghlan7bb30b72010-12-03 09:29:11 +000064import time
Victor Stinnere6c910e2011-06-30 15:55:43 +020065import tokenize
Nick Coghlan7bb30b72010-12-03 09:29:11 +000066import warnings
Alexander Belopolskya47bbf52010-11-18 01:52:54 +000067from collections import deque
Nick Coghlan7bb30b72010-12-03 09:29:11 +000068from reprlib import Repr
Victor Stinner7fa767e2014-03-20 09:16:38 +010069from traceback import format_exception_only
Nick Coghlan7bb30b72010-12-03 09:29:11 +000070
71
Ka-Ping Yeedd175342001-02-27 14:43:46 +000072# --------------------------------------------------------- common routines
73
Ka-Ping Yeedd175342001-02-27 14:43:46 +000074def pathdirs():
75 """Convert sys.path into a list of absolute, existing, unique paths."""
76 dirs = []
Ka-Ping Yee1d384632001-03-01 00:24:32 +000077 normdirs = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +000078 for dir in sys.path:
79 dir = os.path.abspath(dir or '.')
Ka-Ping Yee1d384632001-03-01 00:24:32 +000080 normdir = os.path.normcase(dir)
81 if normdir not in normdirs and os.path.isdir(dir):
Ka-Ping Yeedd175342001-02-27 14:43:46 +000082 dirs.append(dir)
Ka-Ping Yee1d384632001-03-01 00:24:32 +000083 normdirs.append(normdir)
Ka-Ping Yeedd175342001-02-27 14:43:46 +000084 return dirs
85
86def getdoc(object):
87 """Get the doc string or comments for an object."""
Ka-Ping Yee3bda8792001-03-23 13:17:50 +000088 result = inspect.getdoc(object) or inspect.getcomments(object)
Neal Norwitz9d72bb42007-04-17 08:48:32 +000089 return result and re.sub('^ *\n', '', result.rstrip()) or ''
Ka-Ping Yeedd175342001-02-27 14:43:46 +000090
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000091def splitdoc(doc):
92 """Split a doc string into a synopsis line (if any) and the rest."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +000093 lines = doc.strip().split('\n')
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000094 if len(lines) == 1:
95 return lines[0], ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +000096 elif len(lines) >= 2 and not lines[1].rstrip():
97 return lines[0], '\n'.join(lines[2:])
98 return '', '\n'.join(lines)
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +000099
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000100def classname(object, modname):
101 """Get a class name and qualify it with a module name if necessary."""
102 name = object.__name__
103 if object.__module__ != modname:
104 name = object.__module__ + '.' + name
105 return name
106
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000107def isdata(object):
Georg Brandl94432422005-07-22 21:52:25 +0000108 """Check if an object is of a type that probably means it's data."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000109 return not (inspect.ismodule(object) or inspect.isclass(object) or
110 inspect.isroutine(object) or inspect.isframe(object) or
111 inspect.istraceback(object) or inspect.iscode(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000112
113def replace(text, *pairs):
114 """Do a series of global replacements on a string."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000115 while pairs:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000116 text = pairs[1].join(text.split(pairs[0]))
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000117 pairs = pairs[2:]
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000118 return text
119
120def cram(text, maxlen):
121 """Omit part of a string if needed to make it fit in a maximum length."""
122 if len(text) > maxlen:
Raymond Hettingerfca3bb62002-10-21 04:44:11 +0000123 pre = max(0, (maxlen-3)//2)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000124 post = max(0, maxlen-3-pre)
125 return text[:pre] + '...' + text[len(text)-post:]
126 return text
127
Brett Cannon84601f12004-06-19 01:22:48 +0000128_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000129def stripid(text):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000130 """Remove the hexadecimal id from a Python object representation."""
Brett Cannonc6c1f472004-06-19 01:02:51 +0000131 # The behaviour of %p is implementation-dependent in terms of case.
Ezio Melotti412c95a2010-02-16 23:31:04 +0000132 return _re_stripid.sub(r'\1', text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000133
Brett Cannonc6c1f472004-06-19 01:02:51 +0000134def _is_some_method(obj):
R David Murrayac0cea52013-03-19 02:47:44 -0400135 return (inspect.isfunction(obj) or
136 inspect.ismethod(obj) or
137 inspect.isbuiltin(obj) or
138 inspect.ismethoddescriptor(obj))
Tim Peters536d2262001-09-20 05:13:38 +0000139
Larry Hastings24a882b2014-02-20 23:34:46 -0800140def _is_bound_method(fn):
141 """
142 Returns True if fn is a bound method, regardless of whether
143 fn was implemented in Python or in C.
144 """
145 if inspect.ismethod(fn):
146 return True
147 if inspect.isbuiltin(fn):
148 self = getattr(fn, '__self__', None)
149 return not (inspect.ismodule(self) or (self is None))
150 return False
151
152
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000153def allmethods(cl):
154 methods = {}
Tim Peters536d2262001-09-20 05:13:38 +0000155 for key, value in inspect.getmembers(cl, _is_some_method):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000156 methods[key] = 1
157 for base in cl.__bases__:
158 methods.update(allmethods(base)) # all your base are belong to us
159 for key in methods.keys():
160 methods[key] = getattr(cl, key)
161 return methods
162
Tim Petersfa26f7c2001-09-24 08:05:11 +0000163def _split_list(s, predicate):
164 """Split sequence s via predicate, and return pair ([true], [false]).
165
166 The return value is a 2-tuple of lists,
167 ([x for x in s if predicate(x)],
168 [x for x in s if not predicate(x)])
169 """
170
Tim Peters28355492001-09-23 21:29:55 +0000171 yes = []
172 no = []
Tim Petersfa26f7c2001-09-24 08:05:11 +0000173 for x in s:
174 if predicate(x):
175 yes.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000176 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000177 no.append(x)
Tim Peters28355492001-09-23 21:29:55 +0000178 return yes, no
179
Raymond Hettinger1103d052011-03-25 14:15:24 -0700180def visiblename(name, all=None, obj=None):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000181 """Decide whether to show documentation on a variable."""
Brett Cannond340b432012-08-06 17:19:22 -0400182 # Certain special names are redundant or internal.
Eric Snowb523f842013-11-22 09:05:39 -0700183 # XXX Remove __initializing__?
Brett Cannond340b432012-08-06 17:19:22 -0400184 if name in {'__author__', '__builtins__', '__cached__', '__credits__',
Eric Snowb523f842013-11-22 09:05:39 -0700185 '__date__', '__doc__', '__file__', '__spec__',
Brett Cannond340b432012-08-06 17:19:22 -0400186 '__loader__', '__module__', '__name__', '__package__',
187 '__path__', '__qualname__', '__slots__', '__version__'}:
Raymond Hettinger68272942011-03-18 02:22:15 -0700188 return 0
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000189 # Private names are hidden, but special names are displayed.
190 if name.startswith('__') and name.endswith('__'): return 1
Raymond Hettinger1103d052011-03-25 14:15:24 -0700191 # Namedtuples have public fields and methods with a single leading underscore
192 if name.startswith('_') and hasattr(obj, '_fields'):
193 return True
Skip Montanaroa5616d22004-06-11 04:46:12 +0000194 if all is not None:
195 # only document that which the programmer exported in __all__
196 return name in all
197 else:
198 return not name.startswith('_')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000199
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000200def classify_class_attrs(object):
201 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000202 results = []
203 for (name, kind, cls, value) in inspect.classify_class_attrs(object):
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000204 if inspect.isdatadescriptor(value):
205 kind = 'data descriptor'
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000206 results.append((name, kind, cls, value))
207 return results
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000208
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000209# ----------------------------------------------------- module manipulation
210
211def ispackage(path):
212 """Guess whether a path refers to a package directory."""
213 if os.path.isdir(path):
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000214 for ext in ('.py', '.pyc', '.pyo'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000215 if os.path.isfile(os.path.join(path, '__init__' + ext)):
Tim Petersbc0e9102002-04-04 22:55:58 +0000216 return True
217 return False
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000218
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000219def source_synopsis(file):
220 line = file.readline()
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000221 while line[:1] == '#' or not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000222 line = file.readline()
223 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000224 line = line.strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000225 if line[:4] == 'r"""': line = line[1:]
226 if line[:3] == '"""':
227 line = line[3:]
228 if line[-1:] == '\\': line = line[:-1]
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000229 while not line.strip():
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000230 line = file.readline()
231 if not line: break
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000232 result = line.split('"""')[0].strip()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000233 else: result = None
234 return result
235
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000236def synopsis(filename, cache={}):
237 """Get the one-line summary out of a module file."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000238 mtime = os.stat(filename).st_mtime
Charles-François Natali27c4e882011-07-27 19:40:02 +0200239 lastupdate, result = cache.get(filename, (None, None))
240 if lastupdate is None or lastupdate < mtime:
Eric Snowaed5b222014-01-04 20:38:11 -0700241 # Look for binary suffixes first, falling back to source.
242 if filename.endswith(tuple(importlib.machinery.BYTECODE_SUFFIXES)):
243 loader_cls = importlib.machinery.SourcelessFileLoader
244 elif filename.endswith(tuple(importlib.machinery.EXTENSION_SUFFIXES)):
245 loader_cls = importlib.machinery.ExtensionFileLoader
246 else:
247 loader_cls = None
248 # Now handle the choice.
249 if loader_cls is None:
250 # Must be a source file.
251 try:
252 file = tokenize.open(filename)
253 except OSError:
254 # module can't be opened, so skip it
255 return None
256 # text modules can be directly examined
257 with file:
258 result = source_synopsis(file)
259 else:
260 # Must be a binary module, which has to be imported.
261 loader = loader_cls('__temp__', filename)
Eric Snow3a62d142014-01-06 20:42:59 -0700262 # XXX We probably don't need to pass in the loader here.
263 spec = importlib.util.spec_from_file_location('__temp__', filename,
264 loader=loader)
265 _spec = importlib._bootstrap._SpecMethods(spec)
Brett Cannoncb66eb02012-05-11 12:58:42 -0400266 try:
Eric Snow3a62d142014-01-06 20:42:59 -0700267 module = _spec.load()
Brett Cannoncb66eb02012-05-11 12:58:42 -0400268 except:
269 return None
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000270 del sys.modules['__temp__']
Eric Snowaed5b222014-01-04 20:38:11 -0700271 result = (module.__doc__ or '').splitlines()[0]
272 # Cache the result.
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000273 cache[filename] = (mtime, result)
274 return result
275
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000276class ErrorDuringImport(Exception):
277 """Errors that occurred while trying to import something to document it."""
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000278 def __init__(self, filename, exc_info):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000279 self.filename = filename
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000280 self.exc, self.value, self.tb = exc_info
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000281
282 def __str__(self):
Guido van Rossuma01a8b62007-05-27 09:20:14 +0000283 exc = self.exc.__name__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000284 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000285
286def importfile(path):
287 """Import a Python source file or compiled file given its path."""
Brett Cannonf4ba4ec2013-06-15 14:25:04 -0400288 magic = importlib.util.MAGIC_NUMBER
Victor Stinnere975af62011-07-04 02:08:50 +0200289 with open(path, 'rb') as file:
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400290 is_bytecode = magic == file.read(len(magic))
291 filename = os.path.basename(path)
292 name, ext = os.path.splitext(filename)
293 if is_bytecode:
294 loader = importlib._bootstrap.SourcelessFileLoader(name, path)
295 else:
296 loader = importlib._bootstrap.SourceFileLoader(name, path)
Eric Snow3a62d142014-01-06 20:42:59 -0700297 # XXX We probably don't need to pass in the loader here.
298 spec = importlib.util.spec_from_file_location(name, path, loader=loader)
299 _spec = importlib._bootstrap._SpecMethods(spec)
Brett Cannond5e6f2e2013-06-11 17:09:36 -0400300 try:
Eric Snow3a62d142014-01-06 20:42:59 -0700301 return _spec.load()
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)))
597 elif text[end:end+1] == '(':
598 results.append(self.namelink(name, methods, funcs, classes))
599 elif selfdot:
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000600 results.append('self.<strong>%s</strong>' % name)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000601 else:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000602 results.append(self.namelink(name, classes))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000603 here = end
604 results.append(escape(text[here:]))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000605 return ''.join(results)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000606
607 # ---------------------------------------------- type-specific routines
608
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000609 def formattree(self, tree, modname, parent=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000610 """Produce HTML for a class tree as given by inspect.getclasstree()."""
611 result = ''
612 for entry in tree:
613 if type(entry) is type(()):
614 c, bases = entry
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000615 result = result + '<dt><font face="helvetica, arial">'
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000616 result = result + self.classlink(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000617 if bases and bases != (parent,):
618 parents = []
619 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000620 parents.append(self.classlink(base, modname))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000621 result = result + '(' + ', '.join(parents) + ')'
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000622 result = result + '\n</font></dt>'
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000623 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000624 result = result + '<dd>\n%s</dd>\n' % self.formattree(
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000625 entry, modname, c)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000626 return '<dl>\n%s</dl>\n' % result
627
Tim Peters8dd7ade2001-10-18 19:56:17 +0000628 def docmodule(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000629 """Produce HTML documentation for a module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000630 name = object.__name__ # ignore the passed-in name
Skip Montanaroa5616d22004-06-11 04:46:12 +0000631 try:
632 all = object.__all__
633 except AttributeError:
634 all = None
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000635 parts = name.split('.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000636 links = []
637 for i in range(len(parts)-1):
638 links.append(
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000639 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000640 ('.'.join(parts[:i+1]), parts[i]))
641 linkedname = '.'.join(links + parts[-1:])
Raymond Hettinger95f285c2009-02-24 23:41:47 +0000642 head = '<big><big><strong>%s</strong></big></big>' % linkedname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000643 try:
Ka-Ping Yee239432a2001-03-02 02:45:08 +0000644 path = inspect.getabsfile(object)
Ka-Ping Yee6191a232001-04-13 15:00:27 +0000645 url = path
646 if sys.platform == 'win32':
647 import nturl2path
648 url = nturl2path.pathname2url(path)
Nick Coghlan7bb30b72010-12-03 09:29:11 +0000649 filelink = self.filelink(url, path)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000650 except TypeError:
651 filelink = '(built-in)'
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000652 info = []
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000653 if hasattr(object, '__version__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000654 version = str(object.__version__)
Ka-Ping Yee40c49912001-02-27 22:46:01 +0000655 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000656 version = version[11:-1].strip()
Ka-Ping Yee1d384632001-03-01 00:24:32 +0000657 info.append('version %s' % self.escape(version))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000658 if hasattr(object, '__date__'):
659 info.append(self.escape(str(object.__date__)))
660 if info:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000661 head = head + ' (%s)' % ', '.join(info)
Skip Montanaro4997a692003-09-10 16:47:51 +0000662 docloc = self.getdocloc(object)
663 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +0000664 docloc = '<br><a href="%(docloc)s">Module Reference</a>' % locals()
Skip Montanaro4997a692003-09-10 16:47:51 +0000665 else:
666 docloc = ''
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000667 result = self.heading(
Skip Montanaro4997a692003-09-10 16:47:51 +0000668 head, '#ffffff', '#7799ee',
669 '<a href=".">index</a><br>' + filelink + docloc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000670
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000671 modules = inspect.getmembers(object, inspect.ismodule)
672
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000673 classes, cdict = [], {}
674 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000675 # if __all__ exists, believe it. Otherwise use old heuristic.
676 if (all is not None or
677 (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700678 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000679 classes.append((key, value))
680 cdict[key] = cdict[value] = '#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000681 for key, value in classes:
682 for base in value.__bases__:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000683 key, modname = base.__name__, base.__module__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000684 module = sys.modules.get(modname)
685 if modname != name and module and hasattr(module, key):
686 if getattr(module, key) is base:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000687 if not key in cdict:
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000688 cdict[key] = cdict[base] = modname + '.html#' + key
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000689 funcs, fdict = [], {}
690 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +0000691 # if __all__ exists, believe it. Otherwise use old heuristic.
692 if (all is not None or
693 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700694 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000695 funcs.append((key, value))
696 fdict[key] = '#-' + key
697 if inspect.isfunction(value): fdict[value] = fdict[key]
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000698 data = []
699 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -0700700 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000701 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000702
703 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
704 doc = doc and '<tt>%s</tt>' % doc
Tim Peters2306d242001-09-25 03:18:32 +0000705 result = result + '<p>%s</p>\n' % doc
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000706
707 if hasattr(object, '__path__'):
708 modpkgs = []
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000709 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
710 modpkgs.append((modname, name, ispkg, 0))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000711 modpkgs.sort()
712 contents = self.multicolumn(modpkgs, self.modpkglink)
713 result = result + self.bigsection(
714 'Package Contents', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000715 elif modules:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000716 contents = self.multicolumn(
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000717 modules, lambda t: self.modulelink(t[1]))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000718 result = result + self.bigsection(
Christian Heimes7131fd92008-02-19 14:21:46 +0000719 'Modules', '#ffffff', '#aa55cc', contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000720
721 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000722 classlist = [value for (key, value) in classes]
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000723 contents = [
724 self.formattree(inspect.getclasstree(classlist, 1), name)]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000725 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000726 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000727 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000728 'Classes', '#ffffff', '#ee77aa', ' '.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000729 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000730 contents = []
731 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000732 contents.append(self.document(value, key, name, fdict, cdict))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000733 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000734 'Functions', '#ffffff', '#eeaa77', ' '.join(contents))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000735 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000736 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +0000737 for key, value in data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000738 contents.append(self.document(value, key))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000739 result = result + self.bigsection(
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000740 'Data', '#ffffff', '#55aa55', '<br>\n'.join(contents))
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000741 if hasattr(object, '__author__'):
742 contents = self.markup(str(object.__author__), self.preformat)
743 result = result + self.bigsection(
744 'Author', '#ffffff', '#7799ee', contents)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +0000745 if hasattr(object, '__credits__'):
746 contents = self.markup(str(object.__credits__), self.preformat)
747 result = result + self.bigsection(
748 'Credits', '#ffffff', '#7799ee', contents)
749
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000750 return result
751
Tim Peters8dd7ade2001-10-18 19:56:17 +0000752 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
753 *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000754 """Produce HTML documentation for a class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000755 realname = object.__name__
756 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000757 bases = object.__bases__
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000758
Tim Petersb47879b2001-09-24 04:47:19 +0000759 contents = []
760 push = contents.append
761
Tim Petersfa26f7c2001-09-24 08:05:11 +0000762 # Cute little class to pump out a horizontal rule between sections.
763 class HorizontalRule:
764 def __init__(self):
765 self.needone = 0
766 def maybe(self):
767 if self.needone:
768 push('<hr>\n')
769 self.needone = 1
770 hr = HorizontalRule()
771
Tim Petersc86f6ca2001-09-26 21:31:51 +0000772 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000773 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +0000774 if len(mro) > 2:
775 hr.maybe()
776 push('<dl><dt>Method resolution order:</dt>\n')
777 for base in mro:
778 push('<dd>%s</dd>\n' % self.classlink(base,
779 object.__module__))
780 push('</dl>\n')
781
Tim Petersb47879b2001-09-24 04:47:19 +0000782 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000783 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000784 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000785 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000786 push(msg)
787 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100788 try:
789 value = getattr(object, name)
790 except Exception:
791 # Some descriptors may meet a failure in their __get__.
792 # (bug #1785)
793 push(self._docdescriptor(name, value, mod))
794 else:
795 push(self.document(value, name, mod,
796 funcs, classes, mdict, object))
Tim Petersb47879b2001-09-24 04:47:19 +0000797 push('\n')
798 return attrs
799
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000800 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +0000801 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000802 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000803 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000804 push(msg)
805 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000806 push(self._docdescriptor(name, value, mod))
Tim Petersb47879b2001-09-24 04:47:19 +0000807 return attrs
808
Tim Petersfa26f7c2001-09-24 08:05:11 +0000809 def spilldata(msg, attrs, predicate):
810 ok, attrs = _split_list(attrs, predicate)
Tim Petersb47879b2001-09-24 04:47:19 +0000811 if ok:
Tim Petersfa26f7c2001-09-24 08:05:11 +0000812 hr.maybe()
Tim Petersb47879b2001-09-24 04:47:19 +0000813 push(msg)
814 for name, kind, homecls, value in ok:
815 base = self.docother(getattr(object, name), name, mod)
Florent Xicluna5d1155c2011-10-28 14:45:05 +0200816 if callable(value) or inspect.isdatadescriptor(value):
Guido van Rossum5e355b22002-05-21 20:56:15 +0000817 doc = getattr(value, "__doc__", None)
818 else:
819 doc = None
Tim Petersb47879b2001-09-24 04:47:19 +0000820 if doc is None:
821 push('<dl><dt>%s</dl>\n' % base)
822 else:
823 doc = self.markup(getdoc(value), self.preformat,
824 funcs, classes, mdict)
Tim Peters2306d242001-09-25 03:18:32 +0000825 doc = '<dd><tt>%s</tt>' % doc
Tim Petersb47879b2001-09-24 04:47:19 +0000826 push('<dl><dt>%s%s</dl>\n' % (base, doc))
827 push('\n')
828 return attrs
829
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000830 attrs = [(name, kind, cls, value)
831 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -0700832 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000833
Tim Petersb47879b2001-09-24 04:47:19 +0000834 mdict = {}
835 for key, kind, homecls, value in attrs:
836 mdict[key] = anchor = '#' + name + '-' + key
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100837 try:
838 value = getattr(object, name)
839 except Exception:
840 # Some descriptors may meet a failure in their __get__.
841 # (bug #1785)
842 pass
Tim Petersb47879b2001-09-24 04:47:19 +0000843 try:
844 # The value may not be hashable (e.g., a data attr with
845 # a dict or list value).
846 mdict[value] = anchor
847 except TypeError:
848 pass
849
Tim Petersfa26f7c2001-09-24 08:05:11 +0000850 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +0000851 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +0000852 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +0000853 else:
854 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +0000855 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
856
Georg Brandl1a3284e2007-12-02 09:40:06 +0000857 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000858 attrs = inherited
859 continue
860 elif thisclass is object:
861 tag = 'defined here'
Tim Petersb47879b2001-09-24 04:47:19 +0000862 else:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000863 tag = 'inherited from %s' % self.classlink(thisclass,
864 object.__module__)
Tim Petersb47879b2001-09-24 04:47:19 +0000865 tag += ':<br>\n'
866
867 # Sort attrs by name.
Raymond Hettingerd4cb56d2008-01-30 02:55:10 +0000868 attrs.sort(key=lambda t: t[0])
Tim Petersb47879b2001-09-24 04:47:19 +0000869
870 # Pump out the attrs, segregated by kind.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000871 attrs = spill('Methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000872 lambda t: t[1] == 'method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000873 attrs = spill('Class methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000874 lambda t: t[1] == 'class method')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000875 attrs = spill('Static methods %s' % tag, attrs,
Tim Petersb47879b2001-09-24 04:47:19 +0000876 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000877 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
878 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000879 attrs = spilldata('Data and other attributes %s' % tag, attrs,
Tim Petersfa26f7c2001-09-24 08:05:11 +0000880 lambda t: t[1] == 'data')
Tim Petersb47879b2001-09-24 04:47:19 +0000881 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +0000882 attrs = inherited
Tim Petersb47879b2001-09-24 04:47:19 +0000883
884 contents = ''.join(contents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000885
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000886 if name == realname:
887 title = '<a name="%s">class <strong>%s</strong></a>' % (
888 name, realname)
889 else:
890 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
891 name, name, realname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000892 if bases:
893 parents = []
894 for base in bases:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000895 parents.append(self.classlink(base, object.__module__))
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000896 title = title + '(%s)' % ', '.join(parents)
Tim Peters2306d242001-09-25 03:18:32 +0000897 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000898 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
Tim Petersc86f6ca2001-09-26 21:31:51 +0000899
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +0000900 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000901
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000902 def formatvalue(self, object):
903 """Format an argument default value as text."""
Tim Peters2306d242001-09-25 03:18:32 +0000904 return self.grey('=' + self.repr(object))
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000905
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000906 def docroutine(self, object, name=None, mod=None,
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000907 funcs={}, classes={}, methods={}, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000908 """Produce HTML documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000909 realname = object.__name__
910 name = name or realname
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000911 anchor = (cl and cl.__name__ or '') + '-' + name
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000912 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000913 skipdocs = 0
Larry Hastings24a882b2014-02-20 23:34:46 -0800914 if _is_bound_method(object):
Christian Heimesff737952007-11-27 10:40:20 +0000915 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000916 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000917 if imclass is not cl:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000918 note = ' from ' + self.classlink(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000919 else:
Christian Heimesff737952007-11-27 10:40:20 +0000920 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000921 note = ' method of %s instance' % self.classlink(
Christian Heimesff737952007-11-27 10:40:20 +0000922 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +0000923 else:
924 note = ' unbound %s method' % self.classlink(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000925
926 if name == realname:
927 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
928 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000929 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000930 cl.__dict__[realname] is object):
Ka-Ping Yeee280c062001-03-23 14:05:53 +0000931 reallink = '<a href="#%s">%s</a>' % (
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000932 cl.__name__ + '-' + realname, realname)
933 skipdocs = 1
934 else:
935 reallink = realname
936 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
937 anchor, name, reallink)
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800938 argspec = None
Larry Hastings24a882b2014-02-20 23:34:46 -0800939 if inspect.isroutine(object):
Larry Hastings5c661892014-01-24 06:17:25 -0800940 try:
941 signature = inspect.signature(object)
942 except (ValueError, TypeError):
943 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -0800944 if signature:
945 argspec = str(signature)
946 if realname == '<lambda>':
947 title = '<strong>%s</strong> <em>lambda</em> ' % name
948 # XXX lambda's won't usually have func_annotations['return']
949 # since the syntax doesn't support but it is possible.
950 # So removing parentheses isn't truly safe.
951 argspec = argspec[1:-1] # remove parentheses
952 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +0000953 argspec = '(...)'
Ka-Ping Yee66efbc72001-03-01 13:55:20 +0000954
Tim Peters2306d242001-09-25 03:18:32 +0000955 decl = title + argspec + (note and self.grey(
956 '<font face="helvetica, arial">%s</font>' % note))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000957
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000958 if skipdocs:
Tim Peters2306d242001-09-25 03:18:32 +0000959 return '<dl><dt>%s</dt></dl>\n' % decl
Ka-Ping Yee3bda8792001-03-23 13:17:50 +0000960 else:
961 doc = self.markup(
962 getdoc(object), self.preformat, funcs, classes, methods)
Tim Peters2306d242001-09-25 03:18:32 +0000963 doc = doc and '<dd><tt>%s</tt></dd>' % doc
964 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000965
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000966 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000967 results = []
968 push = results.append
969
970 if name:
971 push('<dl><dt><strong>%s</strong></dt>\n' % name)
972 if value.__doc__ is not None:
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +0000973 doc = self.markup(getdoc(value), self.preformat)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000974 push('<dd><tt>%s</tt></dd>\n' % doc)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000975 push('</dl>\n')
976
977 return ''.join(results)
978
979 def docproperty(self, object, name=None, mod=None, cl=None):
980 """Produce html documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +0000981 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +0000982
Tim Peters8dd7ade2001-10-18 19:56:17 +0000983 def docother(self, object, name=None, mod=None, *ignored):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +0000984 """Produce HTML documentation for a data object."""
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +0000985 lhs = name and '<strong>%s</strong> = ' % name or ''
986 return lhs + self.repr(object)
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000987
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000988 def docdata(self, object, name=None, mod=None, cl=None):
989 """Produce html documentation for a data descriptor."""
990 return self._docdescriptor(name, object, mod)
991
Ka-Ping Yeedd175342001-02-27 14:43:46 +0000992 def index(self, dir, shadowed=None):
993 """Generate an HTML index for a directory of modules."""
994 modpkgs = []
995 if shadowed is None: shadowed = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000996 for importer, name, ispkg in pkgutil.iter_modules([dir]):
Victor Stinner4d652242011-04-12 23:41:50 +0200997 if any((0xD800 <= ord(ch) <= 0xDFFF) for ch in name):
998 # ignore a module if its name contains a surrogate character
999 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001000 modpkgs.append((name, '', ispkg, name in shadowed))
1001 shadowed[name] = 1
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001002
1003 modpkgs.sort()
1004 contents = self.multicolumn(modpkgs, self.modpkglink)
1005 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
1006
1007# -------------------------------------------- text documentation generator
1008
1009class TextRepr(Repr):
1010 """Class for safely making a text representation of a Python object."""
1011 def __init__(self):
1012 Repr.__init__(self)
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001013 self.maxlist = self.maxtuple = 20
1014 self.maxdict = 10
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001015 self.maxstring = self.maxother = 100
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001016
1017 def repr1(self, x, level):
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001018 if hasattr(type(x), '__name__'):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001019 methodname = 'repr_' + '_'.join(type(x).__name__.split())
Skip Montanaro0fe8fce2003-06-27 15:45:41 +00001020 if hasattr(self, methodname):
1021 return getattr(self, methodname)(x, level)
1022 return cram(stripid(repr(x)), self.maxother)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001023
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001024 def repr_string(self, x, level):
1025 test = cram(x, self.maxstring)
1026 testrepr = repr(test)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001027 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
Ka-Ping Yeea2fe1032001-03-02 01:19:14 +00001028 # Backslashes are only literal in the string and are never
1029 # needed to make any special characters, so show a raw string.
1030 return 'r' + testrepr[0] + test + testrepr[0]
1031 return testrepr
1032
Skip Montanarodf708782002-03-07 22:58:02 +00001033 repr_str = repr_string
1034
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001035 def repr_instance(self, x, level):
1036 try:
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001037 return cram(stripid(repr(x)), self.maxstring)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001038 except:
1039 return '<%s instance>' % x.__class__.__name__
1040
1041class TextDoc(Doc):
1042 """Formatter class for text documentation."""
1043
1044 # ------------------------------------------- text formatting utilities
1045
1046 _repr_instance = TextRepr()
1047 repr = _repr_instance.repr
1048
1049 def bold(self, text):
1050 """Format a string in bold by overstriking."""
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001051 return ''.join(ch + '\b' + ch for ch in text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001052
1053 def indent(self, text, prefix=' '):
1054 """Indent text by prepending a given prefix to each line."""
1055 if not text: return ''
Collin Winter72e110c2007-07-17 00:27:30 +00001056 lines = [prefix + line for line in text.split('\n')]
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001057 if lines: lines[-1] = lines[-1].rstrip()
1058 return '\n'.join(lines)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001059
1060 def section(self, title, contents):
1061 """Format a section with a given heading."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001062 clean_contents = self.indent(contents).rstrip()
1063 return self.bold(title) + '\n' + clean_contents + '\n\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001064
1065 # ---------------------------------------------- type-specific routines
1066
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001067 def formattree(self, tree, modname, parent=None, prefix=''):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001068 """Render in text a class tree as returned by inspect.getclasstree()."""
1069 result = ''
1070 for entry in tree:
1071 if type(entry) is type(()):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001072 c, bases = entry
1073 result = result + prefix + classname(c, modname)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001074 if bases and bases != (parent,):
Georg Brandlcbd2ab12010-12-04 10:39:14 +00001075 parents = (classname(c, modname) for c in bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001076 result = result + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001077 result = result + '\n'
1078 elif type(entry) is type([]):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001079 result = result + self.formattree(
1080 entry, modname, c, prefix + ' ')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001081 return result
1082
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001083 def docmodule(self, object, name=None, mod=None):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001084 """Produce text documentation for a given module object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001085 name = object.__name__ # ignore the passed-in name
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001086 synop, desc = splitdoc(getdoc(object))
1087 result = self.section('NAME', name + (synop and ' - ' + synop))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001088 all = getattr(object, '__all__', None)
Skip Montanaro4997a692003-09-10 16:47:51 +00001089 docloc = self.getdocloc(object)
1090 if docloc is not None:
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001091 result = result + self.section('MODULE REFERENCE', docloc + """
1092
Éric Araujo647ef8c2011-09-11 00:43:20 +02001093The following documentation is automatically generated from the Python
1094source files. It may be incomplete, incorrect or include features that
1095are considered implementation detail and may vary between Python
1096implementations. When in doubt, consult the module reference at the
1097location listed above.
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001098""")
Skip Montanaro4997a692003-09-10 16:47:51 +00001099
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001100 if desc:
1101 result = result + self.section('DESCRIPTION', desc)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001102
1103 classes = []
1104 for key, value in inspect.getmembers(object, inspect.isclass):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001105 # if __all__ exists, believe it. Otherwise use old heuristic.
1106 if (all is not None
1107 or (inspect.getmodule(value) or object) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001108 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001109 classes.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001110 funcs = []
1111 for key, value in inspect.getmembers(object, inspect.isroutine):
Johannes Gijsbers4c11f602004-08-30 14:13:04 +00001112 # if __all__ exists, believe it. Otherwise use old heuristic.
1113 if (all is not None or
1114 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001115 if visiblename(key, all, object):
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001116 funcs.append((key, value))
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001117 data = []
1118 for key, value in inspect.getmembers(object, isdata):
Raymond Hettinger1103d052011-03-25 14:15:24 -07001119 if visiblename(key, all, object):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001120 data.append((key, value))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001121
Christian Heimes1af737c2008-01-23 08:24:23 +00001122 modpkgs = []
1123 modpkgs_names = set()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001124 if hasattr(object, '__path__'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001125 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
Christian Heimes1af737c2008-01-23 08:24:23 +00001126 modpkgs_names.add(modname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001127 if ispkg:
1128 modpkgs.append(modname + ' (package)')
1129 else:
1130 modpkgs.append(modname)
1131
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001132 modpkgs.sort()
1133 result = result + self.section(
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001134 'PACKAGE CONTENTS', '\n'.join(modpkgs))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001135
Christian Heimes1af737c2008-01-23 08:24:23 +00001136 # Detect submodules as sometimes created by C extensions
1137 submodules = []
1138 for key, value in inspect.getmembers(object, inspect.ismodule):
1139 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1140 submodules.append(key)
1141 if submodules:
1142 submodules.sort()
1143 result = result + self.section(
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001144 'SUBMODULES', '\n'.join(submodules))
Christian Heimes1af737c2008-01-23 08:24:23 +00001145
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001146 if classes:
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001147 classlist = [value for key, value in classes]
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001148 contents = [self.formattree(
1149 inspect.getclasstree(classlist, 1), name)]
1150 for key, value in classes:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001151 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001152 result = result + self.section('CLASSES', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001153
1154 if funcs:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001155 contents = []
1156 for key, value in funcs:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001157 contents.append(self.document(value, key, name))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001158 result = result + self.section('FUNCTIONS', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001159
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001160 if data:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001161 contents = []
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001162 for key, value in data:
Georg Brandl8b813db2005-10-01 16:32:31 +00001163 contents.append(self.docother(value, key, name, maxlen=70))
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001164 result = result + self.section('DATA', '\n'.join(contents))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001165
1166 if hasattr(object, '__version__'):
1167 version = str(object.__version__)
Ka-Ping Yee1d384632001-03-01 00:24:32 +00001168 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001169 version = version[11:-1].strip()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001170 result = result + self.section('VERSION', version)
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001171 if hasattr(object, '__date__'):
1172 result = result + self.section('DATE', str(object.__date__))
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001173 if hasattr(object, '__author__'):
Ka-Ping Yee6f3f9a42001-02-27 22:42:36 +00001174 result = result + self.section('AUTHOR', str(object.__author__))
1175 if hasattr(object, '__credits__'):
1176 result = result + self.section('CREDITS', str(object.__credits__))
Alexander Belopolskya47bbf52010-11-18 01:52:54 +00001177 try:
1178 file = inspect.getabsfile(object)
1179 except TypeError:
1180 file = '(built-in)'
1181 result = result + self.section('FILE', file)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001182 return result
1183
Georg Brandl9bd45f992010-12-03 09:58:38 +00001184 def docclass(self, object, name=None, mod=None, *ignored):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001185 """Produce text documentation for a given class object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001186 realname = object.__name__
1187 name = name or realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001188 bases = object.__bases__
1189
Tim Petersc86f6ca2001-09-26 21:31:51 +00001190 def makename(c, m=object.__module__):
1191 return classname(c, m)
1192
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001193 if name == realname:
1194 title = 'class ' + self.bold(realname)
1195 else:
1196 title = self.bold(name) + ' = class ' + realname
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001197 if bases:
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001198 parents = map(makename, bases)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001199 title = title + '(%s)' % ', '.join(parents)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001200
1201 doc = getdoc(object)
Tim Peters28355492001-09-23 21:29:55 +00001202 contents = doc and [doc + '\n'] or []
1203 push = contents.append
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001204
Tim Petersc86f6ca2001-09-26 21:31:51 +00001205 # List the mro, if non-trivial.
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001206 mro = deque(inspect.getmro(object))
Tim Petersc86f6ca2001-09-26 21:31:51 +00001207 if len(mro) > 2:
1208 push("Method resolution order:")
1209 for base in mro:
1210 push(' ' + makename(base))
1211 push('')
1212
Tim Petersf4aad8e2001-09-24 22:40:47 +00001213 # Cute little class to pump out a horizontal rule between sections.
1214 class HorizontalRule:
1215 def __init__(self):
1216 self.needone = 0
1217 def maybe(self):
1218 if self.needone:
1219 push('-' * 70)
1220 self.needone = 1
1221 hr = HorizontalRule()
1222
Tim Peters28355492001-09-23 21:29:55 +00001223 def spill(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001224 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001225 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001226 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001227 push(msg)
1228 for name, kind, homecls, value in ok:
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001229 try:
1230 value = getattr(object, name)
1231 except Exception:
1232 # Some descriptors may meet a failure in their __get__.
1233 # (bug #1785)
1234 push(self._docdescriptor(name, value, mod))
1235 else:
1236 push(self.document(value,
1237 name, mod, object))
Tim Peters28355492001-09-23 21:29:55 +00001238 return attrs
1239
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001240 def spilldescriptors(msg, attrs, predicate):
Tim Petersfa26f7c2001-09-24 08:05:11 +00001241 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001242 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001243 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001244 push(msg)
1245 for name, kind, homecls, value in ok:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001246 push(self._docdescriptor(name, value, mod))
Tim Peters28355492001-09-23 21:29:55 +00001247 return attrs
Tim Petersb47879b2001-09-24 04:47:19 +00001248
Tim Petersfa26f7c2001-09-24 08:05:11 +00001249 def spilldata(msg, attrs, predicate):
1250 ok, attrs = _split_list(attrs, predicate)
Tim Peters28355492001-09-23 21:29:55 +00001251 if ok:
Tim Petersf4aad8e2001-09-24 22:40:47 +00001252 hr.maybe()
Tim Peters28355492001-09-23 21:29:55 +00001253 push(msg)
1254 for name, kind, homecls, value in ok:
Florent Xicluna5d1155c2011-10-28 14:45:05 +02001255 if callable(value) or inspect.isdatadescriptor(value):
Ka-Ping Yeebba6acc2005-02-19 22:58:26 +00001256 doc = getdoc(value)
Guido van Rossum5e355b22002-05-21 20:56:15 +00001257 else:
1258 doc = None
Serhiy Storchaka056eb022014-02-19 23:05:12 +02001259 try:
1260 obj = getattr(object, name)
1261 except AttributeError:
1262 obj = homecls.__dict__[name]
1263 push(self.docother(obj, name, mod, maxlen=70, doc=doc) +
1264 '\n')
Tim Peters28355492001-09-23 21:29:55 +00001265 return attrs
1266
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001267 attrs = [(name, kind, cls, value)
1268 for name, kind, cls, value in classify_class_attrs(object)
Raymond Hettinger1103d052011-03-25 14:15:24 -07001269 if visiblename(name, obj=object)]
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001270
Tim Petersfa26f7c2001-09-24 08:05:11 +00001271 while attrs:
Tim Peters351e3622001-09-27 03:29:51 +00001272 if mro:
Raymond Hettinger756b3f32004-01-29 06:37:52 +00001273 thisclass = mro.popleft()
Tim Peters351e3622001-09-27 03:29:51 +00001274 else:
1275 thisclass = attrs[0][2]
Tim Petersfa26f7c2001-09-24 08:05:11 +00001276 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1277
Georg Brandl1a3284e2007-12-02 09:40:06 +00001278 if thisclass is builtins.object:
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001279 attrs = inherited
1280 continue
1281 elif thisclass is object:
Tim Peters28355492001-09-23 21:29:55 +00001282 tag = "defined here"
1283 else:
Tim Petersfa26f7c2001-09-24 08:05:11 +00001284 tag = "inherited from %s" % classname(thisclass,
1285 object.__module__)
Tim Peters28355492001-09-23 21:29:55 +00001286 # Sort attrs by name.
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001287 attrs.sort()
Tim Peters28355492001-09-23 21:29:55 +00001288
1289 # Pump out the attrs, segregated by kind.
Tim Petersf4aad8e2001-09-24 22:40:47 +00001290 attrs = spill("Methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001291 lambda t: t[1] == 'method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001292 attrs = spill("Class methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001293 lambda t: t[1] == 'class method')
Tim Petersf4aad8e2001-09-24 22:40:47 +00001294 attrs = spill("Static methods %s:\n" % tag, attrs,
Tim Peters28355492001-09-23 21:29:55 +00001295 lambda t: t[1] == 'static method')
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001296 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1297 lambda t: t[1] == 'data descriptor')
Ka-Ping Yeed9e213e2003-03-28 16:35:51 +00001298 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1299 lambda t: t[1] == 'data')
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001300
Tim Peters28355492001-09-23 21:29:55 +00001301 assert attrs == []
Tim Peters351e3622001-09-27 03:29:51 +00001302 attrs = inherited
Tim Peters28355492001-09-23 21:29:55 +00001303
1304 contents = '\n'.join(contents)
1305 if not contents:
1306 return title + '\n'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001307 return title + '\n' + self.indent(contents.rstrip(), ' | ') + '\n'
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001308
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001309 def formatvalue(self, object):
1310 """Format an argument default value as text."""
1311 return '=' + self.repr(object)
1312
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001313 def docroutine(self, object, name=None, mod=None, cl=None):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00001314 """Produce text documentation for a function or method object."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001315 realname = object.__name__
1316 name = name or realname
1317 note = ''
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001318 skipdocs = 0
Larry Hastings24a882b2014-02-20 23:34:46 -08001319 if _is_bound_method(object):
Christian Heimesff737952007-11-27 10:40:20 +00001320 imclass = object.__self__.__class__
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001321 if cl:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001322 if imclass is not cl:
1323 note = ' from ' + classname(imclass, mod)
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001324 else:
Christian Heimesff737952007-11-27 10:40:20 +00001325 if object.__self__ is not None:
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001326 note = ' method of %s instance' % classname(
Christian Heimesff737952007-11-27 10:40:20 +00001327 object.__self__.__class__, mod)
Ka-Ping Yeeb7a48302001-04-12 20:39:14 +00001328 else:
1329 note = ' unbound %s method' % classname(imclass,mod)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001330
1331 if name == realname:
1332 title = self.bold(realname)
1333 else:
Raymond Hettinger54f02222002-06-01 14:18:47 +00001334 if (cl and realname in cl.__dict__ and
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001335 cl.__dict__[realname] is object):
1336 skipdocs = 1
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001337 title = self.bold(name) + ' = ' + realname
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001338 argspec = None
Larry Hastings5c661892014-01-24 06:17:25 -08001339
1340 if inspect.isroutine(object):
1341 try:
1342 signature = inspect.signature(object)
1343 except (ValueError, TypeError):
1344 signature = None
Larry Hastings44e2eaa2013-11-23 15:37:55 -08001345 if signature:
1346 argspec = str(signature)
1347 if realname == '<lambda>':
1348 title = self.bold(name) + ' lambda '
1349 # XXX lambda's won't usually have func_annotations['return']
1350 # since the syntax doesn't support but it is possible.
1351 # So removing parentheses isn't truly safe.
1352 argspec = argspec[1:-1] # remove parentheses
1353 if not argspec:
Tim Peters4bcfa312001-09-20 06:08:24 +00001354 argspec = '(...)'
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001355 decl = title + argspec + note
1356
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001357 if skipdocs:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001358 return decl + '\n'
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001359 else:
1360 doc = getdoc(object) or ''
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001361 return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001362
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001363 def _docdescriptor(self, name, value, mod):
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001364 results = []
1365 push = results.append
1366
1367 if name:
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001368 push(self.bold(name))
1369 push('\n')
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001370 doc = getdoc(value) or ''
1371 if doc:
1372 push(self.indent(doc))
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001373 push('\n')
1374 return ''.join(results)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001375
1376 def docproperty(self, object, name=None, mod=None, cl=None):
1377 """Produce text documentation for a property."""
Johannes Gijsbers9ddb3002005-01-08 20:16:43 +00001378 return self._docdescriptor(name, object, mod)
Johannes Gijsbers8de645a2004-11-07 19:16:05 +00001379
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001380 def docdata(self, object, name=None, mod=None, cl=None):
1381 """Produce text documentation for a data descriptor."""
1382 return self._docdescriptor(name, object, mod)
1383
Georg Brandl8b813db2005-10-01 16:32:31 +00001384 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001385 """Produce text documentation for a data object."""
1386 repr = self.repr(object)
1387 if maxlen:
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001388 line = (name and name + ' = ' or '') + repr
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001389 chop = maxlen - len(line)
1390 if chop < 0: repr = repr[:chop] + '...'
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001391 line = (name and self.bold(name) + ' = ' or '') + repr
Tim Peters28355492001-09-23 21:29:55 +00001392 if doc is not None:
1393 line += '\n' + self.indent(str(doc))
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001394 return line
1395
Georg Brandld80d5f42010-12-03 07:47:22 +00001396class _PlainTextDoc(TextDoc):
1397 """Subclass of TextDoc which overrides string styling"""
1398 def bold(self, text):
1399 return text
1400
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001401# --------------------------------------------------------- user interfaces
1402
1403def pager(text):
1404 """The first time this is called, determine what kind of pager to use."""
1405 global pager
1406 pager = getpager()
1407 pager(text)
1408
1409def getpager():
1410 """Decide what method to use for paging through text."""
Guido van Rossuma01a8b62007-05-27 09:20:14 +00001411 if not hasattr(sys.stdout, "isatty"):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001412 return plainpager
1413 if not sys.stdin.isatty() or not sys.stdout.isatty():
1414 return plainpager
Raymond Hettinger54f02222002-06-01 14:18:47 +00001415 if 'PAGER' in os.environ:
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001416 if sys.platform == 'win32': # pipes completely broken in Windows
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001417 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001418 elif os.environ.get('TERM') in ('dumb', 'emacs'):
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001419 return lambda text: pipepager(plain(text), os.environ['PAGER'])
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00001420 else:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001421 return lambda text: pipepager(text, os.environ['PAGER'])
Ka-Ping Yeea487e4e2005-11-05 04:49:18 +00001422 if os.environ.get('TERM') in ('dumb', 'emacs'):
1423 return plainpager
Jesus Cea4791a242012-10-05 03:15:39 +02001424 if sys.platform == 'win32':
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001425 return lambda text: tempfilepager(plain(text), 'more <')
Skip Montanarod404bee2002-09-26 21:44:57 +00001426 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001427 return lambda text: pipepager(text, 'less')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001428
1429 import tempfile
Guido van Rossum3b0a3292002-08-09 16:38:32 +00001430 (fd, filename) = tempfile.mkstemp()
1431 os.close(fd)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001432 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001433 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001434 return lambda text: pipepager(text, 'more')
1435 else:
1436 return ttypager
1437 finally:
1438 os.unlink(filename)
1439
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001440def plain(text):
1441 """Remove boldface formatting from text."""
1442 return re.sub('.\b', '', text)
1443
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001444def pipepager(text, cmd):
1445 """Page through text by feeding it to another program."""
1446 pipe = os.popen(cmd, 'w')
1447 try:
1448 pipe.write(text)
1449 pipe.close()
Andrew Svetlovf7a17b42012-12-25 16:47:37 +02001450 except OSError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001451 pass # Ignore broken pipes caused by quitting the pager program.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001452
1453def tempfilepager(text, cmd):
1454 """Page through text by invoking a program on a temporary file."""
1455 import tempfile
Tim Peters550e4e52003-02-07 01:53:46 +00001456 filename = tempfile.mktemp()
Giampaolo Rodola'2f50aaf2013-02-12 02:04:27 +01001457 with open(filename, 'w') as file:
1458 file.write(text)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001459 try:
Georg Brandl3dbca812008-07-23 16:10:53 +00001460 os.system(cmd + ' "' + filename + '"')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001461 finally:
1462 os.unlink(filename)
1463
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001464def ttypager(text):
1465 """Page through text on a text terminal."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001466 lines = plain(text).split('\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001467 try:
1468 import tty
1469 fd = sys.stdin.fileno()
1470 old = tty.tcgetattr(fd)
1471 tty.setcbreak(fd)
1472 getchar = lambda: sys.stdin.read(1)
Ka-Ping Yee457aab22001-02-27 23:36:29 +00001473 except (ImportError, AttributeError):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001474 tty = None
1475 getchar = lambda: sys.stdin.readline()[:-1][:1]
1476
1477 try:
1478 r = inc = os.environ.get('LINES', 25) - 1
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001479 sys.stdout.write('\n'.join(lines[:inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001480 while lines[r:]:
1481 sys.stdout.write('-- more --')
1482 sys.stdout.flush()
1483 c = getchar()
1484
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001485 if c in ('q', 'Q'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001486 sys.stdout.write('\r \r')
1487 break
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001488 elif c in ('\r', '\n'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001489 sys.stdout.write('\r \r' + lines[r] + '\n')
1490 r = r + 1
1491 continue
Raymond Hettingerdbecd932005-02-06 06:57:08 +00001492 if c in ('b', 'B', '\x1b'):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001493 r = r - inc - inc
1494 if r < 0: r = 0
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001495 sys.stdout.write('\n' + '\n'.join(lines[r:r+inc]) + '\n')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001496 r = r + inc
1497
1498 finally:
1499 if tty:
1500 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1501
1502def plainpager(text):
1503 """Simply print unformatted text. This is the ultimate fallback."""
1504 sys.stdout.write(plain(text))
1505
1506def describe(thing):
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00001507 """Produce a short description of the given thing."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001508 if inspect.ismodule(thing):
1509 if thing.__name__ in sys.builtin_module_names:
1510 return 'built-in module ' + thing.__name__
1511 if hasattr(thing, '__path__'):
1512 return 'package ' + thing.__name__
1513 else:
1514 return 'module ' + thing.__name__
1515 if inspect.isbuiltin(thing):
1516 return 'built-in function ' + thing.__name__
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001517 if inspect.isgetsetdescriptor(thing):
1518 return 'getset descriptor %s.%s.%s' % (
1519 thing.__objclass__.__module__, thing.__objclass__.__name__,
1520 thing.__name__)
1521 if inspect.ismemberdescriptor(thing):
1522 return 'member descriptor %s.%s.%s' % (
1523 thing.__objclass__.__module__, thing.__objclass__.__name__,
1524 thing.__name__)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001525 if inspect.isclass(thing):
1526 return 'class ' + thing.__name__
1527 if inspect.isfunction(thing):
1528 return 'function ' + thing.__name__
1529 if inspect.ismethod(thing):
1530 return 'method ' + thing.__name__
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001531 return type(thing).__name__
1532
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001533def locate(path, forceload=0):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001534 """Locate an object by name or dotted path, importing as necessary."""
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001535 parts = [part for part in path.split('.') if part]
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001536 module, n = None, 0
1537 while n < len(parts):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001538 nextmodule = safeimport('.'.join(parts[:n+1]), forceload)
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001539 if nextmodule: module, n = nextmodule, n + 1
1540 else: break
1541 if module:
1542 object = module
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001543 else:
Éric Araujoe64e51b2011-07-29 17:03:55 +02001544 object = builtins
1545 for part in parts[n:]:
1546 try:
1547 object = getattr(object, part)
1548 except AttributeError:
1549 return None
1550 return object
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001551
1552# --------------------------------------- interactive interpreter interface
1553
1554text = TextDoc()
Georg Brandld80d5f42010-12-03 07:47:22 +00001555plaintext = _PlainTextDoc()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001556html = HTMLDoc()
1557
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001558def resolve(thing, forceload=0):
1559 """Given an object or a path to an object, get the object and its name."""
1560 if isinstance(thing, str):
1561 object = locate(thing, forceload)
1562 if not object:
Collin Winterce36ad82007-08-30 01:19:48 +00001563 raise ImportError('no Python documentation found for %r' % thing)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001564 return object, thing
1565 else:
R David Murrayc43125a2012-04-23 13:23:57 -04001566 name = getattr(thing, '__name__', None)
1567 return thing, name if isinstance(name, str) else None
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001568
Georg Brandld80d5f42010-12-03 07:47:22 +00001569def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
1570 renderer=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +00001571 """Render text documentation, given an object or a path to an object."""
Georg Brandld80d5f42010-12-03 07:47:22 +00001572 if renderer is None:
1573 renderer = text
Guido van Rossumd8faa362007-04-27 19:54:29 +00001574 object, name = resolve(thing, forceload)
1575 desc = describe(object)
1576 module = inspect.getmodule(object)
1577 if name and '.' in name:
1578 desc += ' in ' + name[:name.rfind('.')]
1579 elif module and module is not object:
1580 desc += ' in module ' + module.__name__
Amaury Forgeot d'Arc768db922008-04-24 21:00:04 +00001581
1582 if not (inspect.ismodule(object) or
Guido van Rossumd8faa362007-04-27 19:54:29 +00001583 inspect.isclass(object) or
1584 inspect.isroutine(object) or
1585 inspect.isgetsetdescriptor(object) or
1586 inspect.ismemberdescriptor(object) or
1587 isinstance(object, property)):
1588 # If the passed object is a piece of data or an instance,
1589 # document its available methods instead of its value.
1590 object = type(object)
1591 desc += ' object'
Georg Brandld80d5f42010-12-03 07:47:22 +00001592 return title % desc + '\n\n' + renderer.document(object, name)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001593
Georg Brandld80d5f42010-12-03 07:47:22 +00001594def doc(thing, title='Python Library Documentation: %s', forceload=0,
1595 output=None):
Ka-Ping Yee9aa0d902001-04-12 10:50:23 +00001596 """Display text documentation, given an object or a path to an object."""
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001597 try:
Georg Brandld80d5f42010-12-03 07:47:22 +00001598 if output is None:
1599 pager(render_doc(thing, title, forceload))
1600 else:
1601 output.write(render_doc(thing, title, forceload, plaintext))
Guido van Rossumb940e112007-01-10 16:19:56 +00001602 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001603 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001604
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001605def writedoc(thing, forceload=0):
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001606 """Write HTML documentation to a file in the current directory."""
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001607 try:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001608 object, name = resolve(thing, forceload)
1609 page = html.page(describe(object), html.document(object, name))
Georg Brandl388faac2009-04-10 08:31:48 +00001610 file = open(name + '.html', 'w', encoding='utf-8')
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00001611 file.write(page)
1612 file.close()
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001613 print('wrote', name + '.html')
Guido van Rossumb940e112007-01-10 16:19:56 +00001614 except (ImportError, ErrorDuringImport) as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001615 print(value)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001616
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001617def writedocs(dir, pkgpath='', done=None):
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00001618 """Write out HTML documentation for all modules in a directory tree."""
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001619 if done is None: done = {}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001620 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1621 writedoc(modname)
1622 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001623
1624class Helper:
Georg Brandl6b38daa2008-06-01 21:05:17 +00001625
1626 # These dictionaries map a topic name to either an alias, or a tuple
1627 # (label, seealso-items). The "label" is the label of the corresponding
1628 # section in the .rst file under Doc/ and an index into the dictionary
Georg Brandl5617db82009-04-27 16:28:57 +00001629 # in pydoc_data/topics.py.
Georg Brandl6b38daa2008-06-01 21:05:17 +00001630 #
1631 # CAUTION: if you change one of these dictionaries, be sure to adapt the
1632 # list of needed labels in Doc/tools/sphinxext/pyspecific.py and
Georg Brandl5617db82009-04-27 16:28:57 +00001633 # regenerate the pydoc_data/topics.py file by running
Georg Brandl6b38daa2008-06-01 21:05:17 +00001634 # make pydoc-topics
1635 # in Doc/ and copying the output file into the Lib/ directory.
1636
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001637 keywords = {
Ezio Melottib185a042011-04-28 07:42:55 +03001638 'False': '',
1639 'None': '',
1640 'True': '',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001641 'and': 'BOOLEAN',
Guido van Rossumd8faa362007-04-27 19:54:29 +00001642 'as': 'with',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001643 'assert': ('assert', ''),
1644 'break': ('break', 'while for'),
1645 'class': ('class', 'CLASSES SPECIALMETHODS'),
1646 'continue': ('continue', 'while for'),
1647 'def': ('function', ''),
1648 'del': ('del', 'BASICMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001649 'elif': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001650 'else': ('else', 'while for'),
Georg Brandl0d855392008-08-30 19:53:05 +00001651 'except': 'try',
1652 'finally': 'try',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001653 'for': ('for', 'break continue while'),
Georg Brandl0d855392008-08-30 19:53:05 +00001654 'from': 'import',
Georg Brandl74abf6f2010-11-20 19:54:36 +00001655 'global': ('global', 'nonlocal NAMESPACES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001656 'if': ('if', 'TRUTHVALUE'),
1657 'import': ('import', 'MODULES'),
Georg Brandl395ed242009-09-04 08:07:32 +00001658 'in': ('in', 'SEQUENCEMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001659 'is': 'COMPARISON',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001660 'lambda': ('lambda', 'FUNCTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001661 'nonlocal': ('nonlocal', 'global NAMESPACES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001662 'not': 'BOOLEAN',
1663 'or': 'BOOLEAN',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001664 'pass': ('pass', ''),
1665 'raise': ('raise', 'EXCEPTIONS'),
1666 'return': ('return', 'FUNCTIONS'),
1667 'try': ('try', 'EXCEPTIONS'),
1668 'while': ('while', 'break continue if TRUTHVALUE'),
1669 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1670 'yield': ('yield', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001671 }
Georg Brandldb7b6b92009-01-01 15:53:14 +00001672 # Either add symbols to this dictionary or to the symbols dictionary
1673 # directly: Whichever is easier. They are merged later.
1674 _symbols_inverse = {
1675 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'),
1676 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1677 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1678 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1679 'UNARY' : ('-', '~'),
1680 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1681 '^=', '<<=', '>>=', '**=', '//='),
1682 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1683 'COMPLEX' : ('j', 'J')
1684 }
1685 symbols = {
1686 '%': 'OPERATORS FORMATTING',
1687 '**': 'POWER',
1688 ',': 'TUPLES LISTS FUNCTIONS',
1689 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1690 '...': 'ELLIPSIS',
1691 ':': 'SLICINGS DICTIONARYLITERALS',
1692 '@': 'def class',
1693 '\\': 'STRINGS',
1694 '_': 'PRIVATENAMES',
1695 '__': 'PRIVATENAMES SPECIALMETHODS',
1696 '`': 'BACKQUOTES',
1697 '(': 'TUPLES FUNCTIONS CALLS',
1698 ')': 'TUPLES FUNCTIONS CALLS',
1699 '[': 'LISTS SUBSCRIPTS SLICINGS',
1700 ']': 'LISTS SUBSCRIPTS SLICINGS'
1701 }
1702 for topic, symbols_ in _symbols_inverse.items():
1703 for symbol in symbols_:
1704 topics = symbols.get(symbol, topic)
1705 if topic not in topics:
1706 topics = topics + ' ' + topic
1707 symbols[symbol] = topics
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001708
1709 topics = {
Georg Brandl6b38daa2008-06-01 21:05:17 +00001710 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1711 'FUNCTIONS CLASSES MODULES FILES inspect'),
1712 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS '
1713 'FORMATTING TYPES'),
1714 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1715 'FORMATTING': ('formatstrings', 'OPERATORS'),
1716 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1717 'FORMATTING TYPES'),
1718 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1719 'INTEGER': ('integers', 'int range'),
1720 'FLOAT': ('floating', 'float math'),
1721 'COMPLEX': ('imaginary', 'complex cmath'),
1722 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING range LISTS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001723 'MAPPINGS': 'DICTIONARIES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001724 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1725 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1726 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1727 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001728 'FRAMEOBJECTS': 'TYPES',
1729 'TRACEBACKS': 'TYPES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001730 'NONE': ('bltin-null-object', ''),
1731 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
1732 'FILES': ('bltin-file-objects', ''),
1733 'SPECIALATTRIBUTES': ('specialattrs', ''),
1734 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1735 'MODULES': ('typesmodules', 'import'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001736 'PACKAGES': 'import',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001737 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1738 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1739 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1740 'LISTS DICTIONARIES'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001741 'OPERATORS': 'EXPRESSIONS',
1742 'PRECEDENCE': 'EXPRESSIONS',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001743 'OBJECTS': ('objects', 'TYPES'),
1744 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
Georg Brandl395ed242009-09-04 08:07:32 +00001745 'CALLABLEMETHODS SEQUENCEMETHODS MAPPINGMETHODS '
1746 'NUMBERMETHODS CLASSES'),
Mark Dickinsona56c4672009-01-27 18:17:45 +00001747 'BASICMETHODS': ('customization', 'hash repr str SPECIALMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001748 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1749 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001750 'SEQUENCEMETHODS': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS '
Georg Brandl6b38daa2008-06-01 21:05:17 +00001751 'SPECIALMETHODS'),
1752 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1753 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1754 'SPECIALMETHODS'),
1755 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
Georg Brandl74abf6f2010-11-20 19:54:36 +00001756 'NAMESPACES': ('naming', 'global nonlocal ASSIGNMENT DELETION DYNAMICFEATURES'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001757 'DYNAMICFEATURES': ('dynamic-features', ''),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001758 'SCOPING': 'NAMESPACES',
1759 'FRAMES': 'NAMESPACES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001760 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1761 'CONVERSIONS': ('conversions', ''),
1762 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1763 'SPECIALIDENTIFIERS': ('id-classes', ''),
1764 'PRIVATENAMES': ('atom-identifiers', ''),
1765 'LITERALS': ('atom-literals', 'STRINGS NUMBERS TUPLELITERALS '
1766 'LISTLITERALS DICTIONARYLITERALS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001767 'TUPLES': 'SEQUENCES',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001768 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1769 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1770 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1771 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1772 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1773 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
Georg Brandl395ed242009-09-04 08:07:32 +00001774 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS'),
1775 'SLICINGS': ('slicings', 'SEQUENCEMETHODS'),
Georg Brandl6b38daa2008-06-01 21:05:17 +00001776 'CALLS': ('calls', 'EXPRESSIONS'),
1777 'POWER': ('power', 'EXPRESSIONS'),
1778 'UNARY': ('unary', 'EXPRESSIONS'),
1779 'BINARY': ('binary', 'EXPRESSIONS'),
1780 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1781 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1782 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1783 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001784 'ASSERTION': 'assert',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001785 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1786 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001787 'DELETION': 'del',
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001788 'RETURNING': 'return',
1789 'IMPORTING': 'import',
1790 'CONDITIONAL': 'if',
Georg Brandl6b38daa2008-06-01 21:05:17 +00001791 'LOOPING': ('compound', 'for while break continue'),
1792 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1793 'DEBUGGING': ('debugger', 'pdb'),
1794 'CONTEXTMANAGERS': ('context-managers', 'with'),
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001795 }
1796
Georg Brandl78aa3962010-07-31 21:51:48 +00001797 def __init__(self, input=None, output=None):
1798 self._input = input
1799 self._output = output
1800
Georg Brandl76ae3972010-08-01 06:32:55 +00001801 input = property(lambda self: self._input or sys.stdin)
1802 output = property(lambda self: self._output or sys.stdout)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001803
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001804 def __repr__(self):
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001805 if inspect.stack()[1][3] == '?':
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001806 self()
1807 return ''
Ka-Ping Yee9bc576b2001-04-13 13:57:31 +00001808 return '<pydoc.Helper instance>'
Ka-Ping Yee79c009d2001-04-13 10:53:25 +00001809
Alexander Belopolsky2e733c92010-07-04 17:00:20 +00001810 _GoInteractive = object()
1811 def __call__(self, request=_GoInteractive):
1812 if request is not self._GoInteractive:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001813 self.help(request)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001814 else:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001815 self.intro()
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001816 self.interact()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001817 self.output.write('''
Fred Drakee61967f2001-05-10 18:41:02 +00001818You are now leaving help and returning to the Python interpreter.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001819If you want to ask for help on a particular object directly from the
1820interpreter, you can type "help(object)". Executing "help('string')"
1821has the same effect as typing a particular string at the help> prompt.
1822''')
Ka-Ping Yeedd175342001-02-27 14:43:46 +00001823
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001824 def interact(self):
1825 self.output.write('\n')
Guido van Rossum8ca162f2002-04-07 06:36:23 +00001826 while True:
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001827 try:
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001828 request = self.getline('help> ')
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001829 if not request: break
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001830 except (KeyboardInterrupt, EOFError):
1831 break
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001832 request = replace(request, '"', '', "'", '').strip()
1833 if request.lower() in ('q', 'quit'): break
Ka-Ping Yeedec96e92001-04-13 09:55:49 +00001834 self.help(request)
1835
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001836 def getline(self, prompt):
Guido van Rossum7c086c02008-01-02 03:52:38 +00001837 """Read one line, using input() when appropriate."""
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001838 if self.input is sys.stdin:
Guido van Rossum7c086c02008-01-02 03:52:38 +00001839 return input(prompt)
Johannes Gijsberse7691d32004-08-17 13:21:53 +00001840 else:
1841 self.output.write(prompt)
1842 self.output.flush()
1843 return self.input.readline()
1844
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001845 def help(self, request):
1846 if type(request) is type(''):
R. David Murray1f1b9d32009-05-27 20:56:59 +00001847 request = request.strip()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001848 if request == 'help': self.intro()
1849 elif request == 'keywords': self.listkeywords()
Georg Brandldb7b6b92009-01-01 15:53:14 +00001850 elif request == 'symbols': self.listsymbols()
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001851 elif request == 'topics': self.listtopics()
1852 elif request == 'modules': self.listmodules()
1853 elif request[:8] == 'modules ':
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001854 self.listmodules(request.split()[1])
Georg Brandldb7b6b92009-01-01 15:53:14 +00001855 elif request in self.symbols: self.showsymbol(request)
Ezio Melottib185a042011-04-28 07:42:55 +03001856 elif request in ['True', 'False', 'None']:
1857 # special case these keywords since they are objects too
1858 doc(eval(request), 'Help on %s:')
Raymond Hettinger54f02222002-06-01 14:18:47 +00001859 elif request in self.keywords: self.showtopic(request)
1860 elif request in self.topics: self.showtopic(request)
Georg Brandld80d5f42010-12-03 07:47:22 +00001861 elif request: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001862 elif isinstance(request, Helper): self()
Georg Brandld80d5f42010-12-03 07:47:22 +00001863 else: doc(request, 'Help on %s:', output=self._output)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001864 self.output.write('\n')
1865
1866 def intro(self):
1867 self.output.write('''
Georg Brandlc645c6a2012-06-24 17:24:26 +02001868Welcome to Python %s! This is the interactive help utility.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001869
1870If this is your first time using Python, you should definitely check out
R David Murrayde0f6292012-03-31 12:06:35 -04001871the tutorial on the Internet at http://docs.python.org/%s/tutorial/.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001872
1873Enter the name of any module, keyword, or topic to get help on writing
1874Python programs and using Python modules. To quit this help utility and
1875return to the interpreter, just type "quit".
1876
Terry Jan Reedy34200572013-02-11 02:23:13 -05001877To get a list of available modules, keywords, symbols, or topics, type
1878"modules", "keywords", "symbols", or "topics". Each module also comes
1879with a one-line summary of what it does; to list the modules whose name
1880or summary contain a given string such as "spam", type "modules spam".
R David Murrayde0f6292012-03-31 12:06:35 -04001881''' % tuple([sys.version[:3]]*2))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001882
1883 def list(self, items, columns=4, width=80):
Guido van Rossum486364b2007-06-30 05:01:58 +00001884 items = list(sorted(items))
1885 colw = width // columns
1886 rows = (len(items) + columns - 1) // columns
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001887 for row in range(rows):
1888 for col in range(columns):
1889 i = col * rows + row
1890 if i < len(items):
1891 self.output.write(items[i])
1892 if col < columns - 1:
Guido van Rossum486364b2007-06-30 05:01:58 +00001893 self.output.write(' ' + ' ' * (colw - 1 - len(items[i])))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001894 self.output.write('\n')
1895
1896 def listkeywords(self):
1897 self.output.write('''
1898Here is a list of the Python keywords. Enter any keyword to get more help.
1899
1900''')
1901 self.list(self.keywords.keys())
1902
Georg Brandldb7b6b92009-01-01 15:53:14 +00001903 def listsymbols(self):
1904 self.output.write('''
1905Here is a list of the punctuation symbols which Python assigns special meaning
1906to. Enter any symbol to get more help.
1907
1908''')
1909 self.list(self.symbols.keys())
1910
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001911 def listtopics(self):
1912 self.output.write('''
1913Here is a list of available topics. Enter any topic name to get more help.
1914
1915''')
1916 self.list(self.topics.keys())
1917
Georg Brandldb7b6b92009-01-01 15:53:14 +00001918 def showtopic(self, topic, more_xrefs=''):
Georg Brandl6b38daa2008-06-01 21:05:17 +00001919 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001920 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04001921 except ImportError:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001922 self.output.write('''
Georg Brandl6b38daa2008-06-01 21:05:17 +00001923Sorry, topic and keyword documentation is not available because the
Georg Brandl5617db82009-04-27 16:28:57 +00001924module "pydoc_data.topics" could not be found.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001925''')
1926 return
1927 target = self.topics.get(topic, self.keywords.get(topic))
1928 if not target:
1929 self.output.write('no documentation found for %s\n' % repr(topic))
1930 return
1931 if type(target) is type(''):
Georg Brandldb7b6b92009-01-01 15:53:14 +00001932 return self.showtopic(target, more_xrefs)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001933
Georg Brandl6b38daa2008-06-01 21:05:17 +00001934 label, xrefs = target
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001935 try:
Georg Brandl5617db82009-04-27 16:28:57 +00001936 doc = pydoc_data.topics.topics[label]
Georg Brandl6b38daa2008-06-01 21:05:17 +00001937 except KeyError:
1938 self.output.write('no documentation found for %s\n' % repr(topic))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001939 return
Georg Brandl6b38daa2008-06-01 21:05:17 +00001940 pager(doc.strip() + '\n')
Georg Brandldb7b6b92009-01-01 15:53:14 +00001941 if more_xrefs:
1942 xrefs = (xrefs or '') + ' ' + more_xrefs
Ka-Ping Yeeda793892001-04-13 11:02:51 +00001943 if xrefs:
Brett Cannon1448ecf2013-10-04 11:38:59 -04001944 import textwrap
1945 text = 'Related help topics: ' + ', '.join(xrefs.split()) + '\n'
1946 wrapped_text = textwrap.wrap(text, 72)
1947 self.output.write('\n%s\n' % ''.join(wrapped_text))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001948
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001949 def _gettopic(self, topic, more_xrefs=''):
1950 """Return unbuffered tuple of (topic, xrefs).
1951
Georg Brandld2f38572011-01-30 08:37:19 +00001952 If an error occurs here, the exception is caught and displayed by
1953 the url handler.
1954
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001955 This function duplicates the showtopic method but returns its
1956 result directly so it can be formatted for display in an html page.
1957 """
1958 try:
1959 import pydoc_data.topics
Brett Cannoncd171c82013-07-04 17:43:24 -04001960 except ImportError:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001961 return('''
1962Sorry, topic and keyword documentation is not available because the
1963module "pydoc_data.topics" could not be found.
1964''' , '')
1965 target = self.topics.get(topic, self.keywords.get(topic))
1966 if not target:
Georg Brandld2f38572011-01-30 08:37:19 +00001967 raise ValueError('could not find topic')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001968 if isinstance(target, str):
1969 return self._gettopic(target, more_xrefs)
1970 label, xrefs = target
Georg Brandld2f38572011-01-30 08:37:19 +00001971 doc = pydoc_data.topics.topics[label]
Nick Coghlan7bb30b72010-12-03 09:29:11 +00001972 if more_xrefs:
1973 xrefs = (xrefs or '') + ' ' + more_xrefs
1974 return doc, xrefs
1975
Georg Brandldb7b6b92009-01-01 15:53:14 +00001976 def showsymbol(self, symbol):
1977 target = self.symbols[symbol]
1978 topic, _, xrefs = target.partition(' ')
1979 self.showtopic(topic, xrefs)
1980
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001981 def listmodules(self, key=''):
1982 if key:
1983 self.output.write('''
Terry Jan Reedy34200572013-02-11 02:23:13 -05001984Here is a list of modules whose name or summary contains '{}'.
1985If there are any, enter a module name to get more help.
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001986
Terry Jan Reedy34200572013-02-11 02:23:13 -05001987'''.format(key))
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001988 apropos(key)
1989 else:
1990 self.output.write('''
1991Please wait a moment while I gather a list of all available modules...
1992
1993''')
1994 modules = {}
1995 def callback(path, modname, desc, modules=modules):
1996 if modname and modname[-9:] == '.__init__':
1997 modname = modname[:-9] + ' (package)'
Neal Norwitz9d72bb42007-04-17 08:48:32 +00001998 if modname.find('.') < 0:
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00001999 modules[modname] = 1
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002000 def onerror(modname):
2001 callback(None, modname, None)
2002 ModuleScanner().run(callback, onerror=onerror)
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002003 self.list(modules.keys())
2004 self.output.write('''
2005Enter any module name to get more help. Or, type "modules spam" to search
Terry Jan Reedy34200572013-02-11 02:23:13 -05002006for modules whose name or summary contain the string "spam".
Ka-Ping Yee35cf0a32001-04-12 19:53:52 +00002007''')
2008
Georg Brandl78aa3962010-07-31 21:51:48 +00002009help = Helper()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002010
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002011class ModuleScanner:
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002012 """An interruptible scanner that searches module synopses."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002013
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002014 def run(self, callback, key=None, completer=None, onerror=None):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002015 if key: key = key.lower()
Guido van Rossum8ca162f2002-04-07 06:36:23 +00002016 self.quit = False
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002017 seen = {}
2018
2019 for modname in sys.builtin_module_names:
Ka-Ping Yee239432a2001-03-02 02:45:08 +00002020 if modname != '__main__':
2021 seen[modname] = 1
Ka-Ping Yee66246962001-04-12 11:59:50 +00002022 if key is None:
2023 callback(None, modname, '')
2024 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002025 name = __import__(modname).__doc__ or ''
2026 desc = name.split('\n')[0]
2027 name = modname + ' - ' + desc
2028 if name.lower().find(key) >= 0:
Ka-Ping Yee66246962001-04-12 11:59:50 +00002029 callback(None, modname, desc)
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002030
Christian Heimesd32ed6f2008-01-14 18:49:24 +00002031 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002032 if self.quit:
2033 break
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002034
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002035 if key is None:
2036 callback(None, modname, '')
2037 else:
Georg Brandl126c8792009-04-05 15:05:48 +00002038 try:
Eric Snow3a62d142014-01-06 20:42:59 -07002039 spec = pkgutil._get_spec(importer, modname)
Georg Brandl126c8792009-04-05 15:05:48 +00002040 except SyntaxError:
2041 # raised by tests for bad coding cookies or BOM
2042 continue
Eric Snow3a62d142014-01-06 20:42:59 -07002043 loader = spec.loader
Georg Brandl126c8792009-04-05 15:05:48 +00002044 if hasattr(loader, 'get_source'):
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002045 try:
2046 source = loader.get_source(modname)
Nick Coghlan2824cb52012-07-15 22:12:14 +10002047 except Exception:
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002048 if onerror:
2049 onerror(modname)
2050 continue
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002051 desc = source_synopsis(io.StringIO(source)) or ''
Georg Brandl126c8792009-04-05 15:05:48 +00002052 if hasattr(loader, 'get_filename'):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002053 path = loader.get_filename(modname)
Ka-Ping Yee66246962001-04-12 11:59:50 +00002054 else:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002055 path = None
2056 else:
Eric Snow3a62d142014-01-06 20:42:59 -07002057 _spec = importlib._bootstrap._SpecMethods(spec)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002058 try:
Eric Snow3a62d142014-01-06 20:42:59 -07002059 module = _spec.load()
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002060 except ImportError:
2061 if onerror:
2062 onerror(modname)
2063 continue
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002064 desc = (module.__doc__ or '').splitlines()[0]
2065 path = getattr(module,'__file__',None)
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002066 name = modname + ' - ' + desc
2067 if name.lower().find(key) >= 0:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002068 callback(path, modname, desc)
2069
2070 if completer:
2071 completer()
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002072
2073def apropos(key):
2074 """Print all the one-line module summaries that contain a substring."""
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002075 def callback(path, modname, desc):
2076 if modname[-9:] == '.__init__':
2077 modname = modname[:-9] + ' (package)'
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002078 print(modname, desc and '- ' + desc)
Amaury Forgeot d'Arc9196dc62008-06-19 20:54:32 +00002079 def onerror(modname):
2080 pass
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002081 with warnings.catch_warnings():
2082 warnings.filterwarnings('ignore') # ignore problems during import
2083 ModuleScanner().run(callback, key, onerror=onerror)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002084
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002085# --------------------------------------- enhanced Web browser interface
2086
2087def _start_server(urlhandler, port):
2088 """Start an HTTP server thread on a specific port.
2089
2090 Start an HTML/text server thread, so HTML or text documents can be
2091 browsed dynamically and interactively with a Web browser. Example use:
2092
2093 >>> import time
2094 >>> import pydoc
2095
2096 Define a URL handler. To determine what the client is asking
2097 for, check the URL and content_type.
2098
2099 Then get or generate some text or HTML code and return it.
2100
2101 >>> def my_url_handler(url, content_type):
2102 ... text = 'the URL sent was: (%s, %s)' % (url, content_type)
2103 ... return text
2104
2105 Start server thread on port 0.
2106 If you use port 0, the server will pick a random port number.
2107 You can then use serverthread.port to get the port number.
2108
2109 >>> port = 0
2110 >>> serverthread = pydoc._start_server(my_url_handler, port)
2111
2112 Check that the server is really started. If it is, open browser
2113 and get first page. Use serverthread.url as the starting page.
2114
2115 >>> if serverthread.serving:
2116 ... import webbrowser
2117
2118 The next two lines are commented out so a browser doesn't open if
2119 doctest is run on this module.
2120
2121 #... webbrowser.open(serverthread.url)
2122 #True
2123
2124 Let the server do its thing. We just need to monitor its status.
2125 Use time.sleep so the loop doesn't hog the CPU.
2126
2127 >>> starttime = time.time()
2128 >>> timeout = 1 #seconds
2129
2130 This is a short timeout for testing purposes.
2131
2132 >>> while serverthread.serving:
2133 ... time.sleep(.01)
2134 ... if serverthread.serving and time.time() - starttime > timeout:
2135 ... serverthread.stop()
2136 ... break
2137
2138 Print any errors that may have occurred.
2139
2140 >>> print(serverthread.error)
2141 None
2142 """
2143 import http.server
2144 import email.message
2145 import select
2146 import threading
2147
2148 class DocHandler(http.server.BaseHTTPRequestHandler):
2149
2150 def do_GET(self):
2151 """Process a request from an HTML browser.
2152
2153 The URL received is in self.path.
2154 Get an HTML page from self.urlhandler and send it.
2155 """
2156 if self.path.endswith('.css'):
2157 content_type = 'text/css'
2158 else:
2159 content_type = 'text/html'
2160 self.send_response(200)
Georg Brandld2f38572011-01-30 08:37:19 +00002161 self.send_header('Content-Type', '%s; charset=UTF-8' % content_type)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002162 self.end_headers()
2163 self.wfile.write(self.urlhandler(
2164 self.path, content_type).encode('utf-8'))
2165
2166 def log_message(self, *args):
2167 # Don't log messages.
2168 pass
2169
2170 class DocServer(http.server.HTTPServer):
2171
2172 def __init__(self, port, callback):
2173 self.host = (sys.platform == 'mac') and '127.0.0.1' or 'localhost'
2174 self.address = ('', port)
2175 self.callback = callback
2176 self.base.__init__(self, self.address, self.handler)
2177 self.quit = False
2178
2179 def serve_until_quit(self):
2180 while not self.quit:
2181 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2182 if rd:
2183 self.handle_request()
Victor Stinnera3abd1d2011-01-03 16:12:39 +00002184 self.server_close()
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002185
2186 def server_activate(self):
2187 self.base.server_activate(self)
2188 if self.callback:
2189 self.callback(self)
2190
2191 class ServerThread(threading.Thread):
2192
2193 def __init__(self, urlhandler, port):
2194 self.urlhandler = urlhandler
2195 self.port = int(port)
2196 threading.Thread.__init__(self)
2197 self.serving = False
2198 self.error = None
2199
2200 def run(self):
2201 """Start the server."""
2202 try:
2203 DocServer.base = http.server.HTTPServer
2204 DocServer.handler = DocHandler
2205 DocHandler.MessageClass = email.message.Message
2206 DocHandler.urlhandler = staticmethod(self.urlhandler)
2207 docsvr = DocServer(self.port, self.ready)
2208 self.docserver = docsvr
2209 docsvr.serve_until_quit()
2210 except Exception as e:
2211 self.error = e
2212
2213 def ready(self, server):
2214 self.serving = True
2215 self.host = server.host
2216 self.port = server.server_port
2217 self.url = 'http://%s:%d/' % (self.host, self.port)
2218
2219 def stop(self):
2220 """Stop the server and this thread nicely"""
2221 self.docserver.quit = True
2222 self.serving = False
2223 self.url = None
2224
2225 thread = ServerThread(urlhandler, port)
2226 thread.start()
2227 # Wait until thread.serving is True to make sure we are
2228 # really up before returning.
2229 while not thread.error and not thread.serving:
2230 time.sleep(.01)
2231 return thread
2232
2233
2234def _url_handler(url, content_type="text/html"):
2235 """The pydoc url handler for use with the pydoc server.
2236
2237 If the content_type is 'text/css', the _pydoc.css style
2238 sheet is read and returned if it exits.
2239
2240 If the content_type is 'text/html', then the result of
2241 get_html_page(url) is returned.
2242 """
2243 class _HTMLDoc(HTMLDoc):
2244
2245 def page(self, title, contents):
2246 """Format an HTML page."""
2247 css_path = "pydoc_data/_pydoc.css"
2248 css_link = (
2249 '<link rel="stylesheet" type="text/css" href="%s">' %
2250 css_path)
2251 return '''\
2252<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Georg Brandld2f38572011-01-30 08:37:19 +00002253<html><head><title>Pydoc: %s</title>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002254<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Georg Brandld2f38572011-01-30 08:37:19 +00002255%s</head><body bgcolor="#f0f0f8">%s<div style="clear:both;padding-top:.5em;">%s</div>
2256</body></html>''' % (title, css_link, html_navbar(), contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002257
2258 def filelink(self, url, path):
2259 return '<a href="getfile?key=%s">%s</a>' % (url, path)
2260
2261
2262 html = _HTMLDoc()
2263
2264 def html_navbar():
Georg Brandld2f38572011-01-30 08:37:19 +00002265 version = html.escape("%s [%s, %s]" % (platform.python_version(),
2266 platform.python_build()[0],
2267 platform.python_compiler()))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002268 return """
2269 <div style='float:left'>
Georg Brandld2f38572011-01-30 08:37:19 +00002270 Python %s<br>%s
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002271 </div>
2272 <div style='float:right'>
2273 <div style='text-align:center'>
2274 <a href="index.html">Module Index</a>
2275 : <a href="topics.html">Topics</a>
2276 : <a href="keywords.html">Keywords</a>
2277 </div>
2278 <div>
Georg Brandld2f38572011-01-30 08:37:19 +00002279 <form action="get" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002280 <input type=text name=key size=15>
2281 <input type=submit value="Get">
Georg Brandld2f38572011-01-30 08:37:19 +00002282 </form>&nbsp;
2283 <form action="search" style='display:inline;'>
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002284 <input type=text name=key size=15>
2285 <input type=submit value="Search">
2286 </form>
2287 </div>
2288 </div>
Georg Brandld2f38572011-01-30 08:37:19 +00002289 """ % (version, html.escape(platform.platform(terse=True)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002290
2291 def html_index():
2292 """Module Index page."""
2293
2294 def bltinlink(name):
2295 return '<a href="%s.html">%s</a>' % (name, name)
2296
2297 heading = html.heading(
2298 '<big><big><strong>Index of Modules</strong></big></big>',
2299 '#ffffff', '#7799ee')
2300 names = [name for name in sys.builtin_module_names
2301 if name != '__main__']
2302 contents = html.multicolumn(names, bltinlink)
2303 contents = [heading, '<p>' + html.bigsection(
2304 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2305
2306 seen = {}
2307 for dir in sys.path:
2308 contents.append(html.index(dir, seen))
2309
2310 contents.append(
2311 '<p align=right><font color="#909090" face="helvetica,'
2312 'arial"><strong>pydoc</strong> by Ka-Ping Yee'
2313 '&lt;ping@lfw.org&gt;</font>')
Nick Coghlanecace282010-12-03 16:08:46 +00002314 return 'Index of Modules', ''.join(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002315
2316 def html_search(key):
2317 """Search results page."""
2318 # scan for modules
2319 search_result = []
2320
2321 def callback(path, modname, desc):
2322 if modname[-9:] == '.__init__':
2323 modname = modname[:-9] + ' (package)'
2324 search_result.append((modname, desc and '- ' + desc))
2325
2326 with warnings.catch_warnings():
2327 warnings.filterwarnings('ignore') # ignore problems during import
2328 ModuleScanner().run(callback, key)
2329
2330 # format page
2331 def bltinlink(name):
2332 return '<a href="%s.html">%s</a>' % (name, name)
2333
2334 results = []
2335 heading = html.heading(
2336 '<big><big><strong>Search Results</strong></big></big>',
2337 '#ffffff', '#7799ee')
2338 for name, desc in search_result:
2339 results.append(bltinlink(name) + desc)
2340 contents = heading + html.bigsection(
2341 'key = %s' % key, '#ffffff', '#ee77aa', '<br>'.join(results))
Nick Coghlanecace282010-12-03 16:08:46 +00002342 return 'Search Results', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002343
2344 def html_getfile(path):
2345 """Get and display a source file listing safely."""
Nick Coghlanecace282010-12-03 16:08:46 +00002346 path = path.replace('%20', ' ')
Victor Stinner91e08772011-07-05 14:30:41 +02002347 with tokenize.open(path) as fp:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002348 lines = html.escape(fp.read())
2349 body = '<pre>%s</pre>' % lines
2350 heading = html.heading(
2351 '<big><big><strong>File Listing</strong></big></big>',
2352 '#ffffff', '#7799ee')
2353 contents = heading + html.bigsection(
2354 'File: %s' % path, '#ffffff', '#ee77aa', body)
Nick Coghlanecace282010-12-03 16:08:46 +00002355 return 'getfile %s' % path, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002356
2357 def html_topics():
2358 """Index of topic texts available."""
2359
2360 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002361 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002362
2363 heading = html.heading(
2364 '<big><big><strong>INDEX</strong></big></big>',
2365 '#ffffff', '#7799ee')
2366 names = sorted(Helper.topics.keys())
2367
2368 contents = html.multicolumn(names, bltinlink)
2369 contents = heading + html.bigsection(
2370 'Topics', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002371 return 'Topics', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002372
2373 def html_keywords():
2374 """Index of keywords."""
2375 heading = html.heading(
2376 '<big><big><strong>INDEX</strong></big></big>',
2377 '#ffffff', '#7799ee')
2378 names = sorted(Helper.keywords.keys())
2379
2380 def bltinlink(name):
Georg Brandld2f38572011-01-30 08:37:19 +00002381 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002382
2383 contents = html.multicolumn(names, bltinlink)
2384 contents = heading + html.bigsection(
2385 'Keywords', '#ffffff', '#ee77aa', contents)
Nick Coghlanecace282010-12-03 16:08:46 +00002386 return 'Keywords', contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002387
2388 def html_topicpage(topic):
2389 """Topic or keyword help page."""
2390 buf = io.StringIO()
2391 htmlhelp = Helper(buf, buf)
2392 contents, xrefs = htmlhelp._gettopic(topic)
2393 if topic in htmlhelp.keywords:
2394 title = 'KEYWORD'
2395 else:
2396 title = 'TOPIC'
2397 heading = html.heading(
2398 '<big><big><strong>%s</strong></big></big>' % title,
2399 '#ffffff', '#7799ee')
Georg Brandld2f38572011-01-30 08:37:19 +00002400 contents = '<pre>%s</pre>' % html.markup(contents)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002401 contents = html.bigsection(topic , '#ffffff','#ee77aa', contents)
Georg Brandld2f38572011-01-30 08:37:19 +00002402 if xrefs:
2403 xrefs = sorted(xrefs.split())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002404
Georg Brandld2f38572011-01-30 08:37:19 +00002405 def bltinlink(name):
2406 return '<a href="topic?key=%s">%s</a>' % (name, name)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002407
Georg Brandld2f38572011-01-30 08:37:19 +00002408 xrefs = html.multicolumn(xrefs, bltinlink)
2409 xrefs = html.section('Related help topics: ',
2410 '#ffffff', '#ee77aa', xrefs)
Nick Coghlanecace282010-12-03 16:08:46 +00002411 return ('%s %s' % (title, topic),
2412 ''.join((heading, contents, xrefs)))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002413
Georg Brandld2f38572011-01-30 08:37:19 +00002414 def html_getobj(url):
2415 obj = locate(url, forceload=1)
2416 if obj is None and url != 'None':
2417 raise ValueError('could not find object')
2418 title = describe(obj)
2419 content = html.document(obj, url)
2420 return title, content
2421
2422 def html_error(url, exc):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002423 heading = html.heading(
2424 '<big><big><strong>Error</strong></big></big>',
Georg Brandld2f38572011-01-30 08:37:19 +00002425 '#ffffff', '#7799ee')
2426 contents = '<br>'.join(html.escape(line) for line in
2427 format_exception_only(type(exc), exc))
2428 contents = heading + html.bigsection(url, '#ffffff', '#bb0000',
2429 contents)
2430 return "Error - %s" % url, contents
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002431
2432 def get_html_page(url):
2433 """Generate an HTML page for url."""
Georg Brandld2f38572011-01-30 08:37:19 +00002434 complete_url = url
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002435 if url.endswith('.html'):
2436 url = url[:-5]
Georg Brandld2f38572011-01-30 08:37:19 +00002437 try:
2438 if url in ("", "index"):
2439 title, content = html_index()
2440 elif url == "topics":
2441 title, content = html_topics()
2442 elif url == "keywords":
2443 title, content = html_keywords()
2444 elif '=' in url:
2445 op, _, url = url.partition('=')
2446 if op == "search?key":
2447 title, content = html_search(url)
2448 elif op == "getfile?key":
2449 title, content = html_getfile(url)
2450 elif op == "topic?key":
2451 # try topics first, then objects.
2452 try:
2453 title, content = html_topicpage(url)
2454 except ValueError:
2455 title, content = html_getobj(url)
2456 elif op == "get?key":
2457 # try objects first, then topics.
2458 if url in ("", "index"):
2459 title, content = html_index()
2460 else:
2461 try:
2462 title, content = html_getobj(url)
2463 except ValueError:
2464 title, content = html_topicpage(url)
2465 else:
2466 raise ValueError('bad pydoc url')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002467 else:
Georg Brandld2f38572011-01-30 08:37:19 +00002468 title, content = html_getobj(url)
2469 except Exception as exc:
2470 # Catch any errors and display them in an error page.
2471 title, content = html_error(complete_url, exc)
2472 return html.page(title, content)
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002473
2474 if url.startswith('/'):
2475 url = url[1:]
2476 if content_type == 'text/css':
2477 path_here = os.path.dirname(os.path.realpath(__file__))
Georg Brandld2f38572011-01-30 08:37:19 +00002478 css_path = os.path.join(path_here, url)
2479 with open(css_path) as fp:
2480 return ''.join(fp.readlines())
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002481 elif content_type == 'text/html':
2482 return get_html_page(url)
Georg Brandld2f38572011-01-30 08:37:19 +00002483 # Errors outside the url handler are caught by the server.
2484 raise TypeError('unknown content type %r for url %s' % (content_type, url))
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002485
2486
2487def browse(port=0, *, open_browser=True):
2488 """Start the enhanced pydoc Web server and open a Web browser.
2489
2490 Use port '0' to start the server on an arbitrary port.
2491 Set open_browser to False to suppress opening a browser.
2492 """
2493 import webbrowser
2494 serverthread = _start_server(_url_handler, port)
2495 if serverthread.error:
2496 print(serverthread.error)
2497 return
2498 if serverthread.serving:
2499 server_help_msg = 'Server commands: [b]rowser, [q]uit'
2500 if open_browser:
2501 webbrowser.open(serverthread.url)
2502 try:
2503 print('Server ready at', serverthread.url)
2504 print(server_help_msg)
2505 while serverthread.serving:
2506 cmd = input('server> ')
2507 cmd = cmd.lower()
2508 if cmd == 'q':
2509 break
2510 elif cmd == 'b':
2511 webbrowser.open(serverthread.url)
2512 else:
2513 print(server_help_msg)
2514 except (KeyboardInterrupt, EOFError):
2515 print()
2516 finally:
2517 if serverthread.serving:
2518 serverthread.stop()
2519 print('Server stopped')
2520
2521
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002522# -------------------------------------------------- command-line interface
2523
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002524def ispath(x):
Neal Norwitz9d72bb42007-04-17 08:48:32 +00002525 return isinstance(x, str) and x.find(os.sep) >= 0
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002526
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002527def cli():
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002528 """Command-line interface (looks at sys.argv to decide what to do)."""
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002529 import getopt
Guido van Rossum756aa932007-04-07 03:04:01 +00002530 class BadUsage(Exception): pass
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002531
Nick Coghlan106274b2009-11-15 23:04:33 +00002532 # Scripts don't get the current directory in their path by default
2533 # unless they are run with the '-m' switch
2534 if '' not in sys.path:
2535 scriptdir = os.path.dirname(sys.argv[0])
2536 if scriptdir in sys.path:
2537 sys.path.remove(scriptdir)
2538 sys.path.insert(0, '.')
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002539
Ka-Ping Yee3bda8792001-03-23 13:17:50 +00002540 try:
Victor Stinner383c3fc2011-05-25 01:35:05 +02002541 opts, args = getopt.getopt(sys.argv[1:], 'bk:p:w')
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002542 writing = False
2543 start_server = False
2544 open_browser = False
2545 port = None
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002546 for opt, val in opts:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002547 if opt == '-b':
2548 start_server = True
2549 open_browser = True
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002550 if opt == '-k':
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002551 apropos(val)
2552 return
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002553 if opt == '-p':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002554 start_server = True
2555 port = val
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002556 if opt == '-w':
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002557 writing = True
2558
Benjamin Petersonb29614e2012-10-09 11:16:03 -04002559 if start_server:
2560 if port is None:
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002561 port = 0
2562 browse(port, open_browser=open_browser)
2563 return
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002564
2565 if not args: raise BadUsage
2566 for arg in args:
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002567 if ispath(arg) and not os.path.exists(arg):
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002568 print('file %r does not exist' % arg)
Ka-Ping Yee45daeb02002-08-11 15:11:33 +00002569 break
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002570 try:
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002571 if ispath(arg) and os.path.isfile(arg):
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002572 arg = importfile(arg)
Ka-Ping Yee37f7b382001-03-23 00:12:53 +00002573 if writing:
2574 if ispath(arg) and os.path.isdir(arg):
2575 writedocs(arg)
2576 else:
2577 writedoc(arg)
2578 else:
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002579 help.help(arg)
Guido van Rossumb940e112007-01-10 16:19:56 +00002580 except ErrorDuringImport as value:
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002581 print(value)
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002582
2583 except (getopt.error, BadUsage):
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002584 cmd = os.path.splitext(os.path.basename(sys.argv[0]))[0]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00002585 print("""pydoc - the Python documentation tool
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002586
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002587{cmd} <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002588 Show text documentation on something. <name> may be the name of a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002589 Python keyword, topic, function, module, or package, or a dotted
2590 reference to a class or function within a module or module in a
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002591 package. If <name> contains a '{sep}', it is used as the path to a
Martin v. Löwisb8c084e2003-06-14 09:03:46 +00002592 Python source file to document. If name is 'keywords', 'topics',
2593 or 'modules', a listing of these things is displayed.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002594
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002595{cmd} -k <keyword>
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002596 Search for a keyword in the synopsis lines of all available modules.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002597
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002598{cmd} -p <port>
2599 Start an HTTP server on the given port on the local machine. Port
2600 number 0 can be used to get an arbitrary unused port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002601
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002602{cmd} -b
2603 Start an HTTP server on an arbitrary unused port and open a Web browser
2604 to interactively browse documentation. The -p option can be used with
2605 the -b option to explicitly specify the server port.
Ka-Ping Yeedd175342001-02-27 14:43:46 +00002606
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002607{cmd} -w <name> ...
Ka-Ping Yee66efbc72001-03-01 13:55:20 +00002608 Write out the HTML documentation for a module to a file in the current
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002609 directory. If <name> contains a '{sep}', it is treated as a filename; if
Ka-Ping Yee5a804ed2001-04-10 11:46:02 +00002610 it names a directory, documentation is written for all the contents.
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002611""".format(cmd=cmd, sep=os.sep))
Ka-Ping Yee1d384632001-03-01 00:24:32 +00002612
Nick Coghlan7bb30b72010-12-03 09:29:11 +00002613if __name__ == '__main__':
2614 cli()