]> git.proxmox.com Git - mirror_edk2.git/blob - AppPkg/Applications/Python/Python-2.7.10/PyMod-2.7.10/Lib/pydoc.py
AppPkg/.../Python-2.7.10: AppPkg.dsc, pyconfig.h, PyMod-2.7.10
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.10 / PyMod-2.7.10 / Lib / pydoc.py
1 #!/usr/bin/env python
2 # -*- coding: latin-1 -*-
3
4 # Module 'pydoc' -- Generate Python documentation in HTML or text for interactive use.
5 #
6 # Copyright (c) 2015, Daryl McDaniel. All rights reserved.<BR>
7 # Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
8 # This program and the accompanying materials are licensed and made available under
9 # the terms and conditions of the BSD License that accompanies this distribution.
10 # The full text of the license may be found at
11 # http://opensource.org/licenses/bsd-license.
12 #
13 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15
16 """Generate Python documentation in HTML or text for interactive use.
17
18 In the Python interpreter, do "from pydoc import help" to provide online
19 help. Calling help(thing) on a Python object documents the object.
20
21 Or, at the shell command line outside of Python:
22
23 Run "pydoc <name>" to show documentation on something. <name> may be
24 the name of a function, module, package, or a dotted reference to a
25 class or function within a module or module in a package. If the
26 argument contains a path segment delimiter (e.g. slash on Unix,
27 backslash on Windows) it is treated as the path to a Python source file.
28
29 Run "pydoc -k <keyword>" to search for a keyword in the synopsis lines
30 of all available modules.
31
32 Run "pydoc -p <port>" to start an HTTP server on a given port on the
33 local machine to generate documentation web pages. Port number 0 can be
34 used to get an arbitrary unused port.
35
36 For platforms without a command line, "pydoc -g" starts the HTTP server
37 and also pops up a little window for controlling it.
38
39 Run "pydoc -w <name>" to write out the HTML documentation for a module
40 to a file named "<name>.html".
41
42 Module docs for core modules are assumed to be in
43
44 http://docs.python.org/library/
45
46 This can be overridden by setting the PYTHONDOCS environment variable
47 to a different URL or to a local directory containing the Library
48 Reference Manual pages.
49 """
50
51 __author__ = "Ka-Ping Yee <ping@lfw.org>"
52 __date__ = "26 February 2001"
53
54 __version__ = "$Revision: 88564 $"
55 __credits__ = """Guido van Rossum, for an excellent programming language.
56 Tommy Burnette, the original creator of manpy.
57 Paul Prescod, for all his work on onlinehelp.
58 Richard Chamberlain, for the first implementation of textdoc.
59 """
60
61 # Known bugs that can't be fixed here:
62 # - imp.load_module() cannot be prevented from clobbering existing
63 # loaded modules, so calling synopsis() on a binary module file
64 # changes the contents of any existing module with the same name.
65 # - If the __file__ attribute on a module is a relative path and
66 # the current directory is changed with os.chdir(), an incorrect
67 # path will be displayed.
68
69 import sys, imp, os, re, types, inspect, __builtin__, pkgutil, warnings
70 from repr import Repr
71 from string import expandtabs, find, join, lower, split, strip, rfind, rstrip
72 from traceback import extract_tb
73 try:
74 from collections import deque
75 except ImportError:
76 # Python 2.3 compatibility
77 class deque(list):
78 def popleft(self):
79 return self.pop(0)
80
81 # --------------------------------------------------------- common routines
82
83 def pathdirs():
84 """Convert sys.path into a list of absolute, existing, unique paths."""
85 dirs = []
86 normdirs = []
87 for dir in sys.path:
88 dir = os.path.abspath(dir or '.')
89 normdir = os.path.normcase(dir)
90 if normdir not in normdirs and os.path.isdir(dir):
91 dirs.append(dir)
92 normdirs.append(normdir)
93 return dirs
94
95 def getdoc(object):
96 """Get the doc string or comments for an object."""
97 result = inspect.getdoc(object) or inspect.getcomments(object)
98 result = _encode(result)
99 return result and re.sub('^ *\n', '', rstrip(result)) or ''
100
101 def splitdoc(doc):
102 """Split a doc string into a synopsis line (if any) and the rest."""
103 lines = split(strip(doc), '\n')
104 if len(lines) == 1:
105 return lines[0], ''
106 elif len(lines) >= 2 and not rstrip(lines[1]):
107 return lines[0], join(lines[2:], '\n')
108 return '', join(lines, '\n')
109
110 def classname(object, modname):
111 """Get a class name and qualify it with a module name if necessary."""
112 name = object.__name__
113 if object.__module__ != modname:
114 name = object.__module__ + '.' + name
115 return name
116
117 def isdata(object):
118 """Check if an object is of a type that probably means it's data."""
119 return not (inspect.ismodule(object) or inspect.isclass(object) or
120 inspect.isroutine(object) or inspect.isframe(object) or
121 inspect.istraceback(object) or inspect.iscode(object))
122
123 def replace(text, *pairs):
124 """Do a series of global replacements on a string."""
125 while pairs:
126 text = join(split(text, pairs[0]), pairs[1])
127 pairs = pairs[2:]
128 return text
129
130 def cram(text, maxlen):
131 """Omit part of a string if needed to make it fit in a maximum length."""
132 if len(text) > maxlen:
133 pre = max(0, (maxlen-3)//2)
134 post = max(0, maxlen-3-pre)
135 return text[:pre] + '...' + text[len(text)-post:]
136 return text
137
138 _re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
139 def stripid(text):
140 """Remove the hexadecimal id from a Python object representation."""
141 # The behaviour of %p is implementation-dependent in terms of case.
142 return _re_stripid.sub(r'\1', text)
143
144 def _is_some_method(obj):
145 return inspect.ismethod(obj) or inspect.ismethoddescriptor(obj)
146
147 def allmethods(cl):
148 methods = {}
149 for key, value in inspect.getmembers(cl, _is_some_method):
150 methods[key] = 1
151 for base in cl.__bases__:
152 methods.update(allmethods(base)) # all your base are belong to us
153 for key in methods.keys():
154 methods[key] = getattr(cl, key)
155 return methods
156
157 def _split_list(s, predicate):
158 """Split sequence s via predicate, and return pair ([true], [false]).
159
160 The return value is a 2-tuple of lists,
161 ([x for x in s if predicate(x)],
162 [x for x in s if not predicate(x)])
163 """
164
165 yes = []
166 no = []
167 for x in s:
168 if predicate(x):
169 yes.append(x)
170 else:
171 no.append(x)
172 return yes, no
173
174 def visiblename(name, all=None, obj=None):
175 """Decide whether to show documentation on a variable."""
176 # Certain special names are redundant.
177 _hidden_names = ('__builtins__', '__doc__', '__file__', '__path__',
178 '__module__', '__name__', '__slots__', '__package__')
179 if name in _hidden_names: return 0
180 # Private names are hidden, but special names are displayed.
181 if name.startswith('__') and name.endswith('__'): return 1
182 # Namedtuples have public fields and methods with a single leading underscore
183 if name.startswith('_') and hasattr(obj, '_fields'):
184 return 1
185 if all is not None:
186 # only document that which the programmer exported in __all__
187 return name in all
188 else:
189 return not name.startswith('_')
190
191 def classify_class_attrs(object):
192 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
193 def fixup(data):
194 name, kind, cls, value = data
195 if inspect.isdatadescriptor(value):
196 kind = 'data descriptor'
197 return name, kind, cls, value
198 return map(fixup, inspect.classify_class_attrs(object))
199
200 # ----------------------------------------------------- Unicode support helpers
201
202 try:
203 _unicode = unicode
204 except NameError:
205 # If Python is built without Unicode support, the unicode type
206 # will not exist. Fake one that nothing will match, and make
207 # the _encode function that do nothing.
208 class _unicode(object):
209 pass
210 _encoding = 'ascii'
211 def _encode(text, encoding='ascii'):
212 return text
213 else:
214 import locale
215 _encoding = locale.getpreferredencoding()
216
217 def _encode(text, encoding=None):
218 if isinstance(text, unicode):
219 return text.encode(encoding or _encoding, 'xmlcharrefreplace')
220 else:
221 return text
222
223 def _binstr(obj):
224 # Ensure that we have an encoded (binary) string representation of obj,
225 # even if it is a unicode string.
226 if isinstance(obj, _unicode):
227 return obj.encode(_encoding, 'xmlcharrefreplace')
228 return str(obj)
229
230 # ----------------------------------------------------- module manipulation
231
232 def ispackage(path):
233 """Guess whether a path refers to a package directory."""
234 if os.path.isdir(path):
235 for ext in ('.py', '.pyc', '.pyo'):
236 if os.path.isfile(os.path.join(path, '__init__' + ext)):
237 return True
238 return False
239
240 def source_synopsis(file):
241 line = file.readline()
242 while line[:1] == '#' or not strip(line):
243 line = file.readline()
244 if not line: break
245 line = strip(line)
246 if line[:4] == 'r"""': line = line[1:]
247 if line[:3] == '"""':
248 line = line[3:]
249 if line[-1:] == '\\': line = line[:-1]
250 while not strip(line):
251 line = file.readline()
252 if not line: break
253 result = strip(split(line, '"""')[0])
254 else: result = None
255 return result
256
257 def synopsis(filename, cache={}):
258 """Get the one-line summary out of a module file."""
259 mtime = os.stat(filename).st_mtime
260 lastupdate, result = cache.get(filename, (None, None))
261 if lastupdate is None or lastupdate < mtime:
262 info = inspect.getmoduleinfo(filename)
263 try:
264 file = open(filename)
265 except IOError:
266 # module can't be opened, so skip it
267 return None
268 if info and 'b' in info[2]: # binary modules have to be imported
269 try: module = imp.load_module('__temp__', file, filename, info[1:])
270 except: return None
271 result = module.__doc__.splitlines()[0] if module.__doc__ else None
272 del sys.modules['__temp__']
273 else: # text modules can be directly examined
274 result = source_synopsis(file)
275 file.close()
276 cache[filename] = (mtime, result)
277 return result
278
279 class ErrorDuringImport(Exception):
280 """Errors that occurred while trying to import something to document it."""
281 def __init__(self, filename, exc_info):
282 exc, value, tb = exc_info
283 self.filename = filename
284 self.exc = exc
285 self.value = value
286 self.tb = tb
287
288 def __str__(self):
289 exc = self.exc
290 if type(exc) is types.ClassType:
291 exc = exc.__name__
292 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
293
294 def importfile(path):
295 """Import a Python source file or compiled file given its path."""
296 magic = imp.get_magic()
297 file = open(path, 'r')
298 if file.read(len(magic)) == magic:
299 kind = imp.PY_COMPILED
300 else:
301 kind = imp.PY_SOURCE
302 file.close()
303 filename = os.path.basename(path)
304 name, ext = os.path.splitext(filename)
305 file = open(path, 'r')
306 try:
307 module = imp.load_module(name, file, path, (ext, 'r', kind))
308 except:
309 raise ErrorDuringImport(path, sys.exc_info())
310 file.close()
311 return module
312
313 def safeimport(path, forceload=0, cache={}):
314 """Import a module; handle errors; return None if the module isn't found.
315
316 If the module *is* found but an exception occurs, it's wrapped in an
317 ErrorDuringImport exception and reraised. Unlike __import__, if a
318 package path is specified, the module at the end of the path is returned,
319 not the package at the beginning. If the optional 'forceload' argument
320 is 1, we reload the module from disk (unless it's a dynamic extension)."""
321 try:
322 # If forceload is 1 and the module has been previously loaded from
323 # disk, we always have to reload the module. Checking the file's
324 # mtime isn't good enough (e.g. the module could contain a class
325 # that inherits from another module that has changed).
326 if forceload and path in sys.modules:
327 if path not in sys.builtin_module_names:
328 # Avoid simply calling reload() because it leaves names in
329 # the currently loaded module lying around if they're not
330 # defined in the new source file. Instead, remove the
331 # module from sys.modules and re-import. Also remove any
332 # submodules because they won't appear in the newly loaded
333 # module's namespace if they're already in sys.modules.
334 subs = [m for m in sys.modules if m.startswith(path + '.')]
335 for key in [path] + subs:
336 # Prevent garbage collection.
337 cache[key] = sys.modules[key]
338 del sys.modules[key]
339 module = __import__(path)
340 except:
341 # Did the error occur before or after the module was found?
342 (exc, value, tb) = info = sys.exc_info()
343 if path in sys.modules:
344 # An error occurred while executing the imported module.
345 raise ErrorDuringImport(sys.modules[path].__file__, info)
346 elif exc is SyntaxError:
347 # A SyntaxError occurred before we could execute the module.
348 raise ErrorDuringImport(value.filename, info)
349 elif exc is ImportError and extract_tb(tb)[-1][2]=='safeimport':
350 # The import error occurred directly in this function,
351 # which means there is no such module in the path.
352 return None
353 else:
354 # Some other error occurred during the importing process.
355 raise ErrorDuringImport(path, sys.exc_info())
356 for part in split(path, '.')[1:]:
357 try: module = getattr(module, part)
358 except AttributeError: return None
359 return module
360
361 # ---------------------------------------------------- formatter base class
362
363 class Doc:
364 def document(self, object, name=None, *args):
365 """Generate documentation for an object."""
366 args = (object, name) + args
367 # 'try' clause is to attempt to handle the possibility that inspect
368 # identifies something in a way that pydoc itself has issues handling;
369 # think 'super' and how it is a descriptor (which raises the exception
370 # by lacking a __name__ attribute) and an instance.
371 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
372 if inspect.ismemberdescriptor(object): return self.docdata(*args)
373 try:
374 if inspect.ismodule(object): return self.docmodule(*args)
375 if inspect.isclass(object): return self.docclass(*args)
376 if inspect.isroutine(object): return self.docroutine(*args)
377 except AttributeError:
378 pass
379 if isinstance(object, property): return self.docproperty(*args)
380 return self.docother(*args)
381
382 def fail(self, object, name=None, *args):
383 """Raise an exception for unimplemented types."""
384 message = "don't know how to document object%s of type %s" % (
385 name and ' ' + repr(name), type(object).__name__)
386 raise TypeError, message
387
388 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
389
390 def getdocloc(self, object):
391 """Return the location of module docs or None"""
392
393 try:
394 file = inspect.getabsfile(object)
395 except TypeError:
396 file = '(built-in)'
397
398 docloc = os.environ.get("PYTHONDOCS",
399 "http://docs.python.org/library")
400 basedir = os.path.join(sys.exec_prefix, "lib",
401 "python"+sys.version[0:3])
402 if (isinstance(object, type(os)) and
403 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
404 'marshal', 'posix', 'signal', 'sys',
405 'thread', 'zipimport') or
406 (file.startswith(basedir) and
407 not file.startswith(os.path.join(basedir, 'site-packages')))) and
408 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
409 if docloc.startswith("http://"):
410 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
411 else:
412 docloc = os.path.join(docloc, object.__name__ + ".html")
413 else:
414 docloc = None
415 return docloc
416
417 # -------------------------------------------- HTML documentation generator
418
419 class HTMLRepr(Repr):
420 """Class for safely making an HTML representation of a Python object."""
421 def __init__(self):
422 Repr.__init__(self)
423 self.maxlist = self.maxtuple = 20
424 self.maxdict = 10
425 self.maxstring = self.maxother = 100
426
427 def escape(self, text):
428 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
429
430 def repr(self, object):
431 return Repr.repr(self, object)
432
433 def repr1(self, x, level):
434 if hasattr(type(x), '__name__'):
435 methodname = 'repr_' + join(split(type(x).__name__), '_')
436 if hasattr(self, methodname):
437 return getattr(self, methodname)(x, level)
438 return self.escape(cram(stripid(repr(x)), self.maxother))
439
440 def repr_string(self, x, level):
441 test = cram(x, self.maxstring)
442 testrepr = repr(test)
443 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
444 # Backslashes are only literal in the string and are never
445 # needed to make any special characters, so show a raw string.
446 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
447 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
448 r'<font color="#c040c0">\1</font>',
449 self.escape(testrepr))
450
451 repr_str = repr_string
452
453 def repr_instance(self, x, level):
454 try:
455 return self.escape(cram(stripid(repr(x)), self.maxstring))
456 except:
457 return self.escape('<%s instance>' % x.__class__.__name__)
458
459 repr_unicode = repr_string
460
461 class HTMLDoc(Doc):
462 """Formatter class for HTML documentation."""
463
464 # ------------------------------------------- HTML formatting utilities
465
466 _repr_instance = HTMLRepr()
467 repr = _repr_instance.repr
468 escape = _repr_instance.escape
469
470 def page(self, title, contents):
471 """Format an HTML page."""
472 return _encode('''
473 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
474 <html><head><title>Python: %s</title>
475 <meta charset="utf-8">
476 </head><body bgcolor="#f0f0f8">
477 %s
478 </body></html>''' % (title, contents), 'ascii')
479
480 def heading(self, title, fgcol, bgcol, extras=''):
481 """Format a page heading."""
482 return '''
483 <table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
484 <tr bgcolor="%s">
485 <td valign=bottom>&nbsp;<br>
486 <font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
487 ><td align=right valign=bottom
488 ><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
489 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
490
491 def section(self, title, fgcol, bgcol, contents, width=6,
492 prelude='', marginalia=None, gap='&nbsp;'):
493 """Format a section with a heading."""
494 if marginalia is None:
495 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
496 result = '''<p>
497 <table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
498 <tr bgcolor="%s">
499 <td colspan=3 valign=bottom>&nbsp;<br>
500 <font color="%s" face="helvetica, arial">%s</font></td></tr>
501 ''' % (bgcol, fgcol, title)
502 if prelude:
503 result = result + '''
504 <tr bgcolor="%s"><td rowspan=2>%s</td>
505 <td colspan=2>%s</td></tr>
506 <tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
507 else:
508 result = result + '''
509 <tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
510
511 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
512
513 def bigsection(self, title, *args):
514 """Format a section with a big heading."""
515 title = '<big><strong>%s</strong></big>' % title
516 return self.section(title, *args)
517
518 def preformat(self, text):
519 """Format literal preformatted text."""
520 text = self.escape(expandtabs(text))
521 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
522 ' ', '&nbsp;', '\n', '<br>\n')
523
524 def multicolumn(self, list, format, cols=4):
525 """Format a list of items into a multi-column list."""
526 result = ''
527 rows = (len(list)+cols-1)//cols
528 for col in range(cols):
529 result = result + '<td width="%d%%" valign=top>' % (100//cols)
530 for i in range(rows*col, rows*col+rows):
531 if i < len(list):
532 result = result + format(list[i]) + '<br>\n'
533 result = result + '</td>'
534 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
535
536 def grey(self, text): return '<font color="#909090">%s</font>' % text
537
538 def namelink(self, name, *dicts):
539 """Make a link for an identifier, given name-to-URL mappings."""
540 for dict in dicts:
541 if name in dict:
542 return '<a href="%s">%s</a>' % (dict[name], name)
543 return name
544
545 def classlink(self, object, modname):
546 """Make a link for a class."""
547 name, module = object.__name__, sys.modules.get(object.__module__)
548 if hasattr(module, name) and getattr(module, name) is object:
549 return '<a href="%s.html#%s">%s</a>' % (
550 module.__name__, name, classname(object, modname))
551 return classname(object, modname)
552
553 def modulelink(self, object):
554 """Make a link for a module."""
555 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
556
557 def modpkglink(self, data):
558 """Make a link for a module or package to display in an index."""
559 name, path, ispackage, shadowed = data
560 if shadowed:
561 return self.grey(name)
562 if path:
563 url = '%s.%s.html' % (path, name)
564 else:
565 url = '%s.html' % name
566 if ispackage:
567 text = '<strong>%s</strong>&nbsp;(package)' % name
568 else:
569 text = name
570 return '<a href="%s">%s</a>' % (url, text)
571
572 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
573 """Mark up some plain text, given a context of symbols to look for.
574 Each context dictionary maps object names to anchor names."""
575 escape = escape or self.escape
576 results = []
577 here = 0
578 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
579 r'RFC[- ]?(\d+)|'
580 r'PEP[- ]?(\d+)|'
581 r'(self\.)?(\w+))')
582 while True:
583 match = pattern.search(text, here)
584 if not match: break
585 start, end = match.span()
586 results.append(escape(text[here:start]))
587
588 all, scheme, rfc, pep, selfdot, name = match.groups()
589 if scheme:
590 url = escape(all).replace('"', '&quot;')
591 results.append('<a href="%s">%s</a>' % (url, url))
592 elif rfc:
593 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
594 results.append('<a href="%s">%s</a>' % (url, escape(all)))
595 elif pep:
596 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
597 results.append('<a href="%s">%s</a>' % (url, escape(all)))
598 elif selfdot:
599 # Create a link for methods like 'self.method(...)'
600 # and use <strong> for attributes like 'self.attr'
601 if text[end:end+1] == '(':
602 results.append('self.' + self.namelink(name, methods))
603 else:
604 results.append('self.<strong>%s</strong>' % name)
605 elif text[end:end+1] == '(':
606 results.append(self.namelink(name, methods, funcs, classes))
607 else:
608 results.append(self.namelink(name, classes))
609 here = end
610 results.append(escape(text[here:]))
611 return join(results, '')
612
613 # ---------------------------------------------- type-specific routines
614
615 def formattree(self, tree, modname, parent=None):
616 """Produce HTML for a class tree as given by inspect.getclasstree()."""
617 result = ''
618 for entry in tree:
619 if type(entry) is type(()):
620 c, bases = entry
621 result = result + '<dt><font face="helvetica, arial">'
622 result = result + self.classlink(c, modname)
623 if bases and bases != (parent,):
624 parents = []
625 for base in bases:
626 parents.append(self.classlink(base, modname))
627 result = result + '(' + join(parents, ', ') + ')'
628 result = result + '\n</font></dt>'
629 elif type(entry) is type([]):
630 result = result + '<dd>\n%s</dd>\n' % self.formattree(
631 entry, modname, c)
632 return '<dl>\n%s</dl>\n' % result
633
634 def docmodule(self, object, name=None, mod=None, *ignored):
635 """Produce HTML documentation for a module object."""
636 name = object.__name__ # ignore the passed-in name
637 try:
638 all = object.__all__
639 except AttributeError:
640 all = None
641 parts = split(name, '.')
642 links = []
643 for i in range(len(parts)-1):
644 links.append(
645 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
646 (join(parts[:i+1], '.'), parts[i]))
647 linkedname = join(links + parts[-1:], '.')
648 head = '<big><big><strong>%s</strong></big></big>' % linkedname
649 try:
650 path = inspect.getabsfile(object)
651 url = path
652 if sys.platform == 'win32':
653 import nturl2path
654 url = nturl2path.pathname2url(path)
655 filelink = '<a href="file:%s">%s</a>' % (url, path)
656 except TypeError:
657 filelink = '(built-in)'
658 info = []
659 if hasattr(object, '__version__'):
660 version = _binstr(object.__version__)
661 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
662 version = strip(version[11:-1])
663 info.append('version %s' % self.escape(version))
664 if hasattr(object, '__date__'):
665 info.append(self.escape(_binstr(object.__date__)))
666 if info:
667 head = head + ' (%s)' % join(info, ', ')
668 docloc = self.getdocloc(object)
669 if docloc is not None:
670 docloc = '<br><a href="%(docloc)s">Module Docs</a>' % locals()
671 else:
672 docloc = ''
673 result = self.heading(
674 head, '#ffffff', '#7799ee',
675 '<a href=".">index</a><br>' + filelink + docloc)
676
677 modules = inspect.getmembers(object, inspect.ismodule)
678
679 classes, cdict = [], {}
680 for key, value in inspect.getmembers(object, inspect.isclass):
681 # if __all__ exists, believe it. Otherwise use old heuristic.
682 if (all is not None or
683 (inspect.getmodule(value) or object) is object):
684 if visiblename(key, all, object):
685 classes.append((key, value))
686 cdict[key] = cdict[value] = '#' + key
687 for key, value in classes:
688 for base in value.__bases__:
689 key, modname = base.__name__, base.__module__
690 module = sys.modules.get(modname)
691 if modname != name and module and hasattr(module, key):
692 if getattr(module, key) is base:
693 if not key in cdict:
694 cdict[key] = cdict[base] = modname + '.html#' + key
695 funcs, fdict = [], {}
696 for key, value in inspect.getmembers(object, inspect.isroutine):
697 # if __all__ exists, believe it. Otherwise use old heuristic.
698 if (all is not None or
699 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
700 if visiblename(key, all, object):
701 funcs.append((key, value))
702 fdict[key] = '#-' + key
703 if inspect.isfunction(value): fdict[value] = fdict[key]
704 data = []
705 for key, value in inspect.getmembers(object, isdata):
706 if visiblename(key, all, object):
707 data.append((key, value))
708
709 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
710 doc = doc and '<tt>%s</tt>' % doc
711 result = result + '<p>%s</p>\n' % doc
712
713 if hasattr(object, '__path__'):
714 modpkgs = []
715 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
716 modpkgs.append((modname, name, ispkg, 0))
717 modpkgs.sort()
718 contents = self.multicolumn(modpkgs, self.modpkglink)
719 result = result + self.bigsection(
720 'Package Contents', '#ffffff', '#aa55cc', contents)
721 elif modules:
722 contents = self.multicolumn(
723 modules, lambda key_value, s=self: s.modulelink(key_value[1]))
724 result = result + self.bigsection(
725 'Modules', '#ffffff', '#aa55cc', contents)
726
727 if classes:
728 classlist = map(lambda key_value: key_value[1], classes)
729 contents = [
730 self.formattree(inspect.getclasstree(classlist, 1), name)]
731 for key, value in classes:
732 contents.append(self.document(value, key, name, fdict, cdict))
733 result = result + self.bigsection(
734 'Classes', '#ffffff', '#ee77aa', join(contents))
735 if funcs:
736 contents = []
737 for key, value in funcs:
738 contents.append(self.document(value, key, name, fdict, cdict))
739 result = result + self.bigsection(
740 'Functions', '#ffffff', '#eeaa77', join(contents))
741 if data:
742 contents = []
743 for key, value in data:
744 contents.append(self.document(value, key))
745 result = result + self.bigsection(
746 'Data', '#ffffff', '#55aa55', join(contents, '<br>\n'))
747 if hasattr(object, '__author__'):
748 contents = self.markup(_binstr(object.__author__), self.preformat)
749 result = result + self.bigsection(
750 'Author', '#ffffff', '#7799ee', contents)
751 if hasattr(object, '__credits__'):
752 contents = self.markup(_binstr(object.__credits__), self.preformat)
753 result = result + self.bigsection(
754 'Credits', '#ffffff', '#7799ee', contents)
755
756 return result
757
758 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
759 *ignored):
760 """Produce HTML documentation for a class object."""
761 realname = object.__name__
762 name = name or realname
763 bases = object.__bases__
764
765 contents = []
766 push = contents.append
767
768 # Cute little class to pump out a horizontal rule between sections.
769 class HorizontalRule:
770 def __init__(self):
771 self.needone = 0
772 def maybe(self):
773 if self.needone:
774 push('<hr>\n')
775 self.needone = 1
776 hr = HorizontalRule()
777
778 # List the mro, if non-trivial.
779 mro = deque(inspect.getmro(object))
780 if len(mro) > 2:
781 hr.maybe()
782 push('<dl><dt>Method resolution order:</dt>\n')
783 for base in mro:
784 push('<dd>%s</dd>\n' % self.classlink(base,
785 object.__module__))
786 push('</dl>\n')
787
788 def spill(msg, attrs, predicate):
789 ok, attrs = _split_list(attrs, predicate)
790 if ok:
791 hr.maybe()
792 push(msg)
793 for name, kind, homecls, value in ok:
794 try:
795 value = getattr(object, name)
796 except Exception:
797 # Some descriptors may meet a failure in their __get__.
798 # (bug #1785)
799 push(self._docdescriptor(name, value, mod))
800 else:
801 push(self.document(value, name, mod,
802 funcs, classes, mdict, object))
803 push('\n')
804 return attrs
805
806 def spilldescriptors(msg, attrs, predicate):
807 ok, attrs = _split_list(attrs, predicate)
808 if ok:
809 hr.maybe()
810 push(msg)
811 for name, kind, homecls, value in ok:
812 push(self._docdescriptor(name, value, mod))
813 return attrs
814
815 def spilldata(msg, attrs, predicate):
816 ok, attrs = _split_list(attrs, predicate)
817 if ok:
818 hr.maybe()
819 push(msg)
820 for name, kind, homecls, value in ok:
821 base = self.docother(getattr(object, name), name, mod)
822 if (hasattr(value, '__call__') or
823 inspect.isdatadescriptor(value)):
824 doc = getattr(value, "__doc__", None)
825 else:
826 doc = None
827 if doc is None:
828 push('<dl><dt>%s</dl>\n' % base)
829 else:
830 doc = self.markup(getdoc(value), self.preformat,
831 funcs, classes, mdict)
832 doc = '<dd><tt>%s</tt>' % doc
833 push('<dl><dt>%s%s</dl>\n' % (base, doc))
834 push('\n')
835 return attrs
836
837 attrs = filter(lambda data: visiblename(data[0], obj=object),
838 classify_class_attrs(object))
839 mdict = {}
840 for key, kind, homecls, value in attrs:
841 mdict[key] = anchor = '#' + name + '-' + key
842 try:
843 value = getattr(object, name)
844 except Exception:
845 # Some descriptors may meet a failure in their __get__.
846 # (bug #1785)
847 pass
848 try:
849 # The value may not be hashable (e.g., a data attr with
850 # a dict or list value).
851 mdict[value] = anchor
852 except TypeError:
853 pass
854
855 while attrs:
856 if mro:
857 thisclass = mro.popleft()
858 else:
859 thisclass = attrs[0][2]
860 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
861
862 if thisclass is __builtin__.object:
863 attrs = inherited
864 continue
865 elif thisclass is object:
866 tag = 'defined here'
867 else:
868 tag = 'inherited from %s' % self.classlink(thisclass,
869 object.__module__)
870 tag += ':<br>\n'
871
872 # Sort attrs by name.
873 try:
874 attrs.sort(key=lambda t: t[0])
875 except TypeError:
876 attrs.sort(lambda t1, t2: cmp(t1[0], t2[0])) # 2.3 compat
877
878 # Pump out the attrs, segregated by kind.
879 attrs = spill('Methods %s' % tag, attrs,
880 lambda t: t[1] == 'method')
881 attrs = spill('Class methods %s' % tag, attrs,
882 lambda t: t[1] == 'class method')
883 attrs = spill('Static methods %s' % tag, attrs,
884 lambda t: t[1] == 'static method')
885 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
886 lambda t: t[1] == 'data descriptor')
887 attrs = spilldata('Data and other attributes %s' % tag, attrs,
888 lambda t: t[1] == 'data')
889 assert attrs == []
890 attrs = inherited
891
892 contents = ''.join(contents)
893
894 if name == realname:
895 title = '<a name="%s">class <strong>%s</strong></a>' % (
896 name, realname)
897 else:
898 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
899 name, name, realname)
900 if bases:
901 parents = []
902 for base in bases:
903 parents.append(self.classlink(base, object.__module__))
904 title = title + '(%s)' % join(parents, ', ')
905 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
906 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
907
908 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
909
910 def formatvalue(self, object):
911 """Format an argument default value as text."""
912 return self.grey('=' + self.repr(object))
913
914 def docroutine(self, object, name=None, mod=None,
915 funcs={}, classes={}, methods={}, cl=None):
916 """Produce HTML documentation for a function or method object."""
917 realname = object.__name__
918 name = name or realname
919 anchor = (cl and cl.__name__ or '') + '-' + name
920 note = ''
921 skipdocs = 0
922 if inspect.ismethod(object):
923 imclass = object.im_class
924 if cl:
925 if imclass is not cl:
926 note = ' from ' + self.classlink(imclass, mod)
927 else:
928 if object.im_self is not None:
929 note = ' method of %s instance' % self.classlink(
930 object.im_self.__class__, mod)
931 else:
932 note = ' unbound %s method' % self.classlink(imclass,mod)
933 object = object.im_func
934
935 if name == realname:
936 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
937 else:
938 if (cl and realname in cl.__dict__ and
939 cl.__dict__[realname] is object):
940 reallink = '<a href="#%s">%s</a>' % (
941 cl.__name__ + '-' + realname, realname)
942 skipdocs = 1
943 else:
944 reallink = realname
945 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
946 anchor, name, reallink)
947 if inspect.isfunction(object):
948 args, varargs, varkw, defaults = inspect.getargspec(object)
949 argspec = inspect.formatargspec(
950 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
951 if realname == '<lambda>':
952 title = '<strong>%s</strong> <em>lambda</em> ' % name
953 argspec = argspec[1:-1] # remove parentheses
954 else:
955 argspec = '(...)'
956
957 decl = title + argspec + (note and self.grey(
958 '<font face="helvetica, arial">%s</font>' % note))
959
960 if skipdocs:
961 return '<dl><dt>%s</dt></dl>\n' % decl
962 else:
963 doc = self.markup(
964 getdoc(object), self.preformat, funcs, classes, methods)
965 doc = doc and '<dd><tt>%s</tt></dd>' % doc
966 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
967
968 def _docdescriptor(self, name, value, mod):
969 results = []
970 push = results.append
971
972 if name:
973 push('<dl><dt><strong>%s</strong></dt>\n' % name)
974 if value.__doc__ is not None:
975 doc = self.markup(getdoc(value), self.preformat)
976 push('<dd><tt>%s</tt></dd>\n' % doc)
977 push('</dl>\n')
978
979 return ''.join(results)
980
981 def docproperty(self, object, name=None, mod=None, cl=None):
982 """Produce html documentation for a property."""
983 return self._docdescriptor(name, object, mod)
984
985 def docother(self, object, name=None, mod=None, *ignored):
986 """Produce HTML documentation for a data object."""
987 lhs = name and '<strong>%s</strong> = ' % name or ''
988 return lhs + self.repr(object)
989
990 def docdata(self, object, name=None, mod=None, cl=None):
991 """Produce html documentation for a data descriptor."""
992 return self._docdescriptor(name, object, mod)
993
994 def index(self, dir, shadowed=None):
995 """Generate an HTML index for a directory of modules."""
996 modpkgs = []
997 if shadowed is None: shadowed = {}
998 for importer, name, ispkg in pkgutil.iter_modules([dir]):
999 modpkgs.append((name, '', ispkg, name in shadowed))
1000 shadowed[name] = 1
1001
1002 modpkgs.sort()
1003 contents = self.multicolumn(modpkgs, self.modpkglink)
1004 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
1005
1006 # -------------------------------------------- text documentation generator
1007
1008 class TextRepr(Repr):
1009 """Class for safely making a text representation of a Python object."""
1010 def __init__(self):
1011 Repr.__init__(self)
1012 self.maxlist = self.maxtuple = 20
1013 self.maxdict = 10
1014 self.maxstring = self.maxother = 100
1015
1016 def repr1(self, x, level):
1017 if hasattr(type(x), '__name__'):
1018 methodname = 'repr_' + join(split(type(x).__name__), '_')
1019 if hasattr(self, methodname):
1020 return getattr(self, methodname)(x, level)
1021 return cram(stripid(repr(x)), self.maxother)
1022
1023 def repr_string(self, x, level):
1024 test = cram(x, self.maxstring)
1025 testrepr = repr(test)
1026 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
1027 # Backslashes are only literal in the string and are never
1028 # needed to make any special characters, so show a raw string.
1029 return 'r' + testrepr[0] + test + testrepr[0]
1030 return testrepr
1031
1032 repr_str = repr_string
1033
1034 def repr_instance(self, x, level):
1035 try:
1036 return cram(stripid(repr(x)), self.maxstring)
1037 except:
1038 return '<%s instance>' % x.__class__.__name__
1039
1040 class TextDoc(Doc):
1041 """Formatter class for text documentation."""
1042
1043 # ------------------------------------------- text formatting utilities
1044
1045 _repr_instance = TextRepr()
1046 repr = _repr_instance.repr
1047
1048 def bold(self, text):
1049 """Format a string in bold by overstriking."""
1050 return join(map(lambda ch: ch + '\b' + ch, text), '')
1051
1052 def indent(self, text, prefix=' '):
1053 """Indent text by prepending a given prefix to each line."""
1054 if not text: return ''
1055 lines = split(text, '\n')
1056 lines = map(lambda line, prefix=prefix: prefix + line, lines)
1057 if lines: lines[-1] = rstrip(lines[-1])
1058 return join(lines, '\n')
1059
1060 def section(self, title, contents):
1061 """Format a section with a given heading."""
1062 return self.bold(title) + '\n' + rstrip(self.indent(contents)) + '\n\n'
1063
1064 # ---------------------------------------------- type-specific routines
1065
1066 def formattree(self, tree, modname, parent=None, prefix=''):
1067 """Render in text a class tree as returned by inspect.getclasstree()."""
1068 result = ''
1069 for entry in tree:
1070 if type(entry) is type(()):
1071 c, bases = entry
1072 result = result + prefix + classname(c, modname)
1073 if bases and bases != (parent,):
1074 parents = map(lambda c, m=modname: classname(c, m), bases)
1075 result = result + '(%s)' % join(parents, ', ')
1076 result = result + '\n'
1077 elif type(entry) is type([]):
1078 result = result + self.formattree(
1079 entry, modname, c, prefix + ' ')
1080 return result
1081
1082 def docmodule(self, object, name=None, mod=None):
1083 """Produce text documentation for a given module object."""
1084 name = object.__name__ # ignore the passed-in name
1085 synop, desc = splitdoc(getdoc(object))
1086 result = self.section('NAME', name + (synop and ' - ' + synop))
1087
1088 try:
1089 all = object.__all__
1090 except AttributeError:
1091 all = None
1092
1093 try:
1094 file = inspect.getabsfile(object)
1095 except TypeError:
1096 file = '(built-in)'
1097 result = result + self.section('FILE', file)
1098
1099 docloc = self.getdocloc(object)
1100 if docloc is not None:
1101 result = result + self.section('MODULE DOCS', docloc)
1102
1103 if desc:
1104 result = result + self.section('DESCRIPTION', desc)
1105
1106 classes = []
1107 for key, value in inspect.getmembers(object, inspect.isclass):
1108 # if __all__ exists, believe it. Otherwise use old heuristic.
1109 if (all is not None
1110 or (inspect.getmodule(value) or object) is object):
1111 if visiblename(key, all, object):
1112 classes.append((key, value))
1113 funcs = []
1114 for key, value in inspect.getmembers(object, inspect.isroutine):
1115 # if __all__ exists, believe it. Otherwise use old heuristic.
1116 if (all is not None or
1117 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
1118 if visiblename(key, all, object):
1119 funcs.append((key, value))
1120 data = []
1121 for key, value in inspect.getmembers(object, isdata):
1122 if visiblename(key, all, object):
1123 data.append((key, value))
1124
1125 modpkgs = []
1126 modpkgs_names = set()
1127 if hasattr(object, '__path__'):
1128 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
1129 modpkgs_names.add(modname)
1130 if ispkg:
1131 modpkgs.append(modname + ' (package)')
1132 else:
1133 modpkgs.append(modname)
1134
1135 modpkgs.sort()
1136 result = result + self.section(
1137 'PACKAGE CONTENTS', join(modpkgs, '\n'))
1138
1139 # Detect submodules as sometimes created by C extensions
1140 submodules = []
1141 for key, value in inspect.getmembers(object, inspect.ismodule):
1142 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1143 submodules.append(key)
1144 if submodules:
1145 submodules.sort()
1146 result = result + self.section(
1147 'SUBMODULES', join(submodules, '\n'))
1148
1149 if classes:
1150 classlist = map(lambda key_value: key_value[1], classes)
1151 contents = [self.formattree(
1152 inspect.getclasstree(classlist, 1), name)]
1153 for key, value in classes:
1154 contents.append(self.document(value, key, name))
1155 result = result + self.section('CLASSES', join(contents, '\n'))
1156
1157 if funcs:
1158 contents = []
1159 for key, value in funcs:
1160 contents.append(self.document(value, key, name))
1161 result = result + self.section('FUNCTIONS', join(contents, '\n'))
1162
1163 if data:
1164 contents = []
1165 for key, value in data:
1166 contents.append(self.docother(value, key, name, maxlen=70))
1167 result = result + self.section('DATA', join(contents, '\n'))
1168
1169 if hasattr(object, '__version__'):
1170 version = _binstr(object.__version__)
1171 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
1172 version = strip(version[11:-1])
1173 result = result + self.section('VERSION', version)
1174 if hasattr(object, '__date__'):
1175 result = result + self.section('DATE', _binstr(object.__date__))
1176 if hasattr(object, '__author__'):
1177 result = result + self.section('AUTHOR', _binstr(object.__author__))
1178 if hasattr(object, '__credits__'):
1179 result = result + self.section('CREDITS', _binstr(object.__credits__))
1180 return result
1181
1182 def docclass(self, object, name=None, mod=None, *ignored):
1183 """Produce text documentation for a given class object."""
1184 realname = object.__name__
1185 name = name or realname
1186 bases = object.__bases__
1187
1188 def makename(c, m=object.__module__):
1189 return classname(c, m)
1190
1191 if name == realname:
1192 title = 'class ' + self.bold(realname)
1193 else:
1194 title = self.bold(name) + ' = class ' + realname
1195 if bases:
1196 parents = map(makename, bases)
1197 title = title + '(%s)' % join(parents, ', ')
1198
1199 doc = getdoc(object)
1200 contents = doc and [doc + '\n'] or []
1201 push = contents.append
1202
1203 # List the mro, if non-trivial.
1204 mro = deque(inspect.getmro(object))
1205 if len(mro) > 2:
1206 push("Method resolution order:")
1207 for base in mro:
1208 push(' ' + makename(base))
1209 push('')
1210
1211 # Cute little class to pump out a horizontal rule between sections.
1212 class HorizontalRule:
1213 def __init__(self):
1214 self.needone = 0
1215 def maybe(self):
1216 if self.needone:
1217 push('-' * 70)
1218 self.needone = 1
1219 hr = HorizontalRule()
1220
1221 def spill(msg, attrs, predicate):
1222 ok, attrs = _split_list(attrs, predicate)
1223 if ok:
1224 hr.maybe()
1225 push(msg)
1226 for name, kind, homecls, value in ok:
1227 try:
1228 value = getattr(object, name)
1229 except Exception:
1230 # Some descriptors may meet a failure in their __get__.
1231 # (bug #1785)
1232 push(self._docdescriptor(name, value, mod))
1233 else:
1234 push(self.document(value,
1235 name, mod, object))
1236 return attrs
1237
1238 def spilldescriptors(msg, attrs, predicate):
1239 ok, attrs = _split_list(attrs, predicate)
1240 if ok:
1241 hr.maybe()
1242 push(msg)
1243 for name, kind, homecls, value in ok:
1244 push(self._docdescriptor(name, value, mod))
1245 return attrs
1246
1247 def spilldata(msg, attrs, predicate):
1248 ok, attrs = _split_list(attrs, predicate)
1249 if ok:
1250 hr.maybe()
1251 push(msg)
1252 for name, kind, homecls, value in ok:
1253 if (hasattr(value, '__call__') or
1254 inspect.isdatadescriptor(value)):
1255 doc = getdoc(value)
1256 else:
1257 doc = None
1258 push(self.docother(getattr(object, name),
1259 name, mod, maxlen=70, doc=doc) + '\n')
1260 return attrs
1261
1262 attrs = filter(lambda data: visiblename(data[0], obj=object),
1263 classify_class_attrs(object))
1264 while attrs:
1265 if mro:
1266 thisclass = mro.popleft()
1267 else:
1268 thisclass = attrs[0][2]
1269 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1270
1271 if thisclass is __builtin__.object:
1272 attrs = inherited
1273 continue
1274 elif thisclass is object:
1275 tag = "defined here"
1276 else:
1277 tag = "inherited from %s" % classname(thisclass,
1278 object.__module__)
1279
1280 # Sort attrs by name.
1281 attrs.sort()
1282
1283 # Pump out the attrs, segregated by kind.
1284 attrs = spill("Methods %s:\n" % tag, attrs,
1285 lambda t: t[1] == 'method')
1286 attrs = spill("Class methods %s:\n" % tag, attrs,
1287 lambda t: t[1] == 'class method')
1288 attrs = spill("Static methods %s:\n" % tag, attrs,
1289 lambda t: t[1] == 'static method')
1290 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1291 lambda t: t[1] == 'data descriptor')
1292 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1293 lambda t: t[1] == 'data')
1294 assert attrs == []
1295 attrs = inherited
1296
1297 contents = '\n'.join(contents)
1298 if not contents:
1299 return title + '\n'
1300 return title + '\n' + self.indent(rstrip(contents), ' | ') + '\n'
1301
1302 def formatvalue(self, object):
1303 """Format an argument default value as text."""
1304 return '=' + self.repr(object)
1305
1306 def docroutine(self, object, name=None, mod=None, cl=None):
1307 """Produce text documentation for a function or method object."""
1308 realname = object.__name__
1309 name = name or realname
1310 note = ''
1311 skipdocs = 0
1312 if inspect.ismethod(object):
1313 imclass = object.im_class
1314 if cl:
1315 if imclass is not cl:
1316 note = ' from ' + classname(imclass, mod)
1317 else:
1318 if object.im_self is not None:
1319 note = ' method of %s instance' % classname(
1320 object.im_self.__class__, mod)
1321 else:
1322 note = ' unbound %s method' % classname(imclass,mod)
1323 object = object.im_func
1324
1325 if name == realname:
1326 title = self.bold(realname)
1327 else:
1328 if (cl and realname in cl.__dict__ and
1329 cl.__dict__[realname] is object):
1330 skipdocs = 1
1331 title = self.bold(name) + ' = ' + realname
1332 if inspect.isfunction(object):
1333 args, varargs, varkw, defaults = inspect.getargspec(object)
1334 argspec = inspect.formatargspec(
1335 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
1336 if realname == '<lambda>':
1337 title = self.bold(name) + ' lambda '
1338 argspec = argspec[1:-1] # remove parentheses
1339 else:
1340 argspec = '(...)'
1341 decl = title + argspec + note
1342
1343 if skipdocs:
1344 return decl + '\n'
1345 else:
1346 doc = getdoc(object) or ''
1347 return decl + '\n' + (doc and rstrip(self.indent(doc)) + '\n')
1348
1349 def _docdescriptor(self, name, value, mod):
1350 results = []
1351 push = results.append
1352
1353 if name:
1354 push(self.bold(name))
1355 push('\n')
1356 doc = getdoc(value) or ''
1357 if doc:
1358 push(self.indent(doc))
1359 push('\n')
1360 return ''.join(results)
1361
1362 def docproperty(self, object, name=None, mod=None, cl=None):
1363 """Produce text documentation for a property."""
1364 return self._docdescriptor(name, object, mod)
1365
1366 def docdata(self, object, name=None, mod=None, cl=None):
1367 """Produce text documentation for a data descriptor."""
1368 return self._docdescriptor(name, object, mod)
1369
1370 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
1371 """Produce text documentation for a data object."""
1372 repr = self.repr(object)
1373 if maxlen:
1374 line = (name and name + ' = ' or '') + repr
1375 chop = maxlen - len(line)
1376 if chop < 0: repr = repr[:chop] + '...'
1377 line = (name and self.bold(name) + ' = ' or '') + repr
1378 if doc is not None:
1379 line += '\n' + self.indent(str(doc))
1380 return line
1381
1382 # --------------------------------------------------------- user interfaces
1383
1384 def pager(text):
1385 """The first time this is called, determine what kind of pager to use."""
1386 global pager
1387 pager = getpager()
1388 pager(text)
1389
1390 def getpager():
1391 """Decide what method to use for paging through text."""
1392 if type(sys.stdout) is not types.FileType:
1393 return plainpager
1394 if not hasattr(sys.stdin, "isatty"):
1395 return plainpager
1396 if not sys.stdin.isatty() or not sys.stdout.isatty():
1397 return plainpager
1398 if 'PAGER' in os.environ:
1399 if sys.platform == 'win32': # pipes completely broken in Windows
1400 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
1401 elif sys.platform == 'uefi':
1402 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
1403 elif os.environ.get('TERM') in ('dumb', 'emacs'):
1404 return lambda text: pipepager(plain(text), os.environ['PAGER'])
1405 else:
1406 return lambda text: pipepager(text, os.environ['PAGER'])
1407 if os.environ.get('TERM') in ('dumb', 'emacs'):
1408 return plainpager
1409 if sys.platform == 'uefi':
1410 return plainpager
1411 if sys.platform == 'win32' or sys.platform.startswith('os2'):
1412 return lambda text: tempfilepager(plain(text), 'more <')
1413 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
1414 return lambda text: pipepager(text, 'less')
1415
1416 import tempfile
1417 (fd, filename) = tempfile.mkstemp()
1418 os.close(fd)
1419 try:
1420 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
1421 return lambda text: pipepager(text, 'more')
1422 else:
1423 return ttypager
1424 finally:
1425 os.unlink(filename)
1426
1427 def plain(text):
1428 """Remove boldface formatting from text."""
1429 return re.sub('.\b', '', text)
1430
1431 def pipepager(text, cmd):
1432 """Page through text by feeding it to another program."""
1433 pipe = os.popen(cmd, 'w')
1434 try:
1435 pipe.write(_encode(text))
1436 pipe.close()
1437 except IOError:
1438 pass # Ignore broken pipes caused by quitting the pager program.
1439
1440 def tempfilepager(text, cmd):
1441 """Page through text by invoking a program on a temporary file."""
1442 import tempfile
1443 filename = tempfile.mktemp()
1444 file = open(filename, 'w')
1445 file.write(_encode(text))
1446 file.close()
1447 try:
1448 os.system(cmd + ' "' + filename + '"')
1449 finally:
1450 os.unlink(filename)
1451
1452 def ttypager(text):
1453 """Page through text on a text terminal."""
1454 lines = plain(_encode(plain(text), getattr(sys.stdout, 'encoding', _encoding))).split('\n')
1455 try:
1456 import tty
1457 fd = sys.stdin.fileno()
1458 old = tty.tcgetattr(fd)
1459 tty.setcbreak(fd)
1460 getchar = lambda: sys.stdin.read(1)
1461 except (ImportError, AttributeError):
1462 tty = None
1463 getchar = lambda: sys.stdin.readline()[:-1][:1]
1464
1465 try:
1466 try:
1467 h = int(os.environ.get('LINES', 0))
1468 except ValueError:
1469 h = 0
1470 if h <= 1:
1471 h = 25
1472 r = inc = h - 1
1473 sys.stdout.write(join(lines[:inc], '\n') + '\n')
1474 while lines[r:]:
1475 sys.stdout.write('-- more --')
1476 sys.stdout.flush()
1477 c = getchar()
1478
1479 if c in ('q', 'Q'):
1480 sys.stdout.write('\r \r')
1481 break
1482 elif c in ('\r', '\n'):
1483 sys.stdout.write('\r \r' + lines[r] + '\n')
1484 r = r + 1
1485 continue
1486 if c in ('b', 'B', '\x1b'):
1487 r = r - inc - inc
1488 if r < 0: r = 0
1489 sys.stdout.write('\n' + join(lines[r:r+inc], '\n') + '\n')
1490 r = r + inc
1491
1492 finally:
1493 if tty:
1494 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1495
1496 def plainpager(text):
1497 """Simply print unformatted text. This is the ultimate fallback."""
1498 sys.stdout.write(_encode(plain(text), getattr(sys.stdout, 'encoding', _encoding)))
1499
1500 def describe(thing):
1501 """Produce a short description of the given thing."""
1502 if inspect.ismodule(thing):
1503 if thing.__name__ in sys.builtin_module_names:
1504 return 'built-in module ' + thing.__name__
1505 if hasattr(thing, '__path__'):
1506 return 'package ' + thing.__name__
1507 else:
1508 return 'module ' + thing.__name__
1509 if inspect.isbuiltin(thing):
1510 return 'built-in function ' + thing.__name__
1511 if inspect.isgetsetdescriptor(thing):
1512 return 'getset descriptor %s.%s.%s' % (
1513 thing.__objclass__.__module__, thing.__objclass__.__name__,
1514 thing.__name__)
1515 if inspect.ismemberdescriptor(thing):
1516 return 'member descriptor %s.%s.%s' % (
1517 thing.__objclass__.__module__, thing.__objclass__.__name__,
1518 thing.__name__)
1519 if inspect.isclass(thing):
1520 return 'class ' + thing.__name__
1521 if inspect.isfunction(thing):
1522 return 'function ' + thing.__name__
1523 if inspect.ismethod(thing):
1524 return 'method ' + thing.__name__
1525 if type(thing) is types.InstanceType:
1526 return 'instance of ' + thing.__class__.__name__
1527 return type(thing).__name__
1528
1529 def locate(path, forceload=0):
1530 """Locate an object by name or dotted path, importing as necessary."""
1531 parts = [part for part in split(path, '.') if part]
1532 module, n = None, 0
1533 while n < len(parts):
1534 nextmodule = safeimport(join(parts[:n+1], '.'), forceload)
1535 if nextmodule: module, n = nextmodule, n + 1
1536 else: break
1537 if module:
1538 object = module
1539 else:
1540 object = __builtin__
1541 for part in parts[n:]:
1542 try:
1543 object = getattr(object, part)
1544 except AttributeError:
1545 return None
1546 return object
1547
1548 # --------------------------------------- interactive interpreter interface
1549
1550 text = TextDoc()
1551 html = HTMLDoc()
1552
1553 class _OldStyleClass: pass
1554 _OLD_INSTANCE_TYPE = type(_OldStyleClass())
1555
1556 def resolve(thing, forceload=0):
1557 """Given an object or a path to an object, get the object and its name."""
1558 if isinstance(thing, str):
1559 object = locate(thing, forceload)
1560 if object is None:
1561 raise ImportError, 'no Python documentation found for %r' % thing
1562 return object, thing
1563 else:
1564 name = getattr(thing, '__name__', None)
1565 return thing, name if isinstance(name, str) else None
1566
1567 def render_doc(thing, title='Python Library Documentation: %s', forceload=0):
1568 """Render text documentation, given an object or a path to an object."""
1569 object, name = resolve(thing, forceload)
1570 desc = describe(object)
1571 module = inspect.getmodule(object)
1572 if name and '.' in name:
1573 desc += ' in ' + name[:name.rfind('.')]
1574 elif module and module is not object:
1575 desc += ' in module ' + module.__name__
1576 if type(object) is _OLD_INSTANCE_TYPE:
1577 # If the passed object is an instance of an old-style class,
1578 # document its available methods instead of its value.
1579 object = object.__class__
1580 elif not (inspect.ismodule(object) or
1581 inspect.isclass(object) or
1582 inspect.isroutine(object) or
1583 inspect.isgetsetdescriptor(object) or
1584 inspect.ismemberdescriptor(object) or
1585 isinstance(object, property)):
1586 # If the passed object is a piece of data or an instance,
1587 # document its available methods instead of its value.
1588 object = type(object)
1589 desc += ' object'
1590 return title % desc + '\n\n' + text.document(object, name)
1591
1592 def doc(thing, title='Python Library Documentation: %s', forceload=0):
1593 """Display text documentation, given an object or a path to an object."""
1594 try:
1595 pager(render_doc(thing, title, forceload))
1596 except (ImportError, ErrorDuringImport), value:
1597 print value
1598
1599 def writedoc(thing, forceload=0):
1600 """Write HTML documentation to a file in the current directory."""
1601 try:
1602 object, name = resolve(thing, forceload)
1603 page = html.page(describe(object), html.document(object, name))
1604 file = open(name + '.html', 'w')
1605 file.write(page)
1606 file.close()
1607 print 'wrote', name + '.html'
1608 except (ImportError, ErrorDuringImport), value:
1609 print value
1610
1611 def writedocs(dir, pkgpath='', done=None):
1612 """Write out HTML documentation for all modules in a directory tree."""
1613 if done is None: done = {}
1614 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1615 writedoc(modname)
1616 return
1617
1618 class Helper:
1619
1620 # These dictionaries map a topic name to either an alias, or a tuple
1621 # (label, seealso-items). The "label" is the label of the corresponding
1622 # section in the .rst file under Doc/ and an index into the dictionary
1623 # in pydoc_data/topics.py.
1624 #
1625 # CAUTION: if you change one of these dictionaries, be sure to adapt the
1626 # list of needed labels in Doc/tools/pyspecific.py and
1627 # regenerate the pydoc_data/topics.py file by running
1628 # make pydoc-topics
1629 # in Doc/ and copying the output file into the Lib/ directory.
1630
1631 keywords = {
1632 'and': 'BOOLEAN',
1633 'as': 'with',
1634 'assert': ('assert', ''),
1635 'break': ('break', 'while for'),
1636 'class': ('class', 'CLASSES SPECIALMETHODS'),
1637 'continue': ('continue', 'while for'),
1638 'def': ('function', ''),
1639 'del': ('del', 'BASICMETHODS'),
1640 'elif': 'if',
1641 'else': ('else', 'while for'),
1642 'except': 'try',
1643 'exec': ('exec', ''),
1644 'finally': 'try',
1645 'for': ('for', 'break continue while'),
1646 'from': 'import',
1647 'global': ('global', 'NAMESPACES'),
1648 'if': ('if', 'TRUTHVALUE'),
1649 'import': ('import', 'MODULES'),
1650 'in': ('in', 'SEQUENCEMETHODS2'),
1651 'is': 'COMPARISON',
1652 'lambda': ('lambda', 'FUNCTIONS'),
1653 'not': 'BOOLEAN',
1654 'or': 'BOOLEAN',
1655 'pass': ('pass', ''),
1656 'print': ('print', ''),
1657 'raise': ('raise', 'EXCEPTIONS'),
1658 'return': ('return', 'FUNCTIONS'),
1659 'try': ('try', 'EXCEPTIONS'),
1660 'while': ('while', 'break continue if TRUTHVALUE'),
1661 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1662 'yield': ('yield', ''),
1663 }
1664 # Either add symbols to this dictionary or to the symbols dictionary
1665 # directly: Whichever is easier. They are merged later.
1666 _symbols_inverse = {
1667 'STRINGS' : ("'", "'''", "r'", "u'", '"""', '"', 'r"', 'u"'),
1668 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1669 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1670 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1671 'UNARY' : ('-', '~'),
1672 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1673 '^=', '<<=', '>>=', '**=', '//='),
1674 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1675 'COMPLEX' : ('j', 'J')
1676 }
1677 symbols = {
1678 '%': 'OPERATORS FORMATTING',
1679 '**': 'POWER',
1680 ',': 'TUPLES LISTS FUNCTIONS',
1681 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1682 '...': 'ELLIPSIS',
1683 ':': 'SLICINGS DICTIONARYLITERALS',
1684 '@': 'def class',
1685 '\\': 'STRINGS',
1686 '_': 'PRIVATENAMES',
1687 '__': 'PRIVATENAMES SPECIALMETHODS',
1688 '`': 'BACKQUOTES',
1689 '(': 'TUPLES FUNCTIONS CALLS',
1690 ')': 'TUPLES FUNCTIONS CALLS',
1691 '[': 'LISTS SUBSCRIPTS SLICINGS',
1692 ']': 'LISTS SUBSCRIPTS SLICINGS'
1693 }
1694 for topic, symbols_ in _symbols_inverse.iteritems():
1695 for symbol in symbols_:
1696 topics = symbols.get(symbol, topic)
1697 if topic not in topics:
1698 topics = topics + ' ' + topic
1699 symbols[symbol] = topics
1700
1701 topics = {
1702 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1703 'FUNCTIONS CLASSES MODULES FILES inspect'),
1704 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS FORMATTING '
1705 'TYPES'),
1706 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1707 'FORMATTING': ('formatstrings', 'OPERATORS'),
1708 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1709 'FORMATTING TYPES'),
1710 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1711 'INTEGER': ('integers', 'int range'),
1712 'FLOAT': ('floating', 'float math'),
1713 'COMPLEX': ('imaginary', 'complex cmath'),
1714 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING xrange LISTS'),
1715 'MAPPINGS': 'DICTIONARIES',
1716 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1717 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1718 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1719 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
1720 'FRAMEOBJECTS': 'TYPES',
1721 'TRACEBACKS': 'TYPES',
1722 'NONE': ('bltin-null-object', ''),
1723 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
1724 'FILES': ('bltin-file-objects', ''),
1725 'SPECIALATTRIBUTES': ('specialattrs', ''),
1726 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1727 'MODULES': ('typesmodules', 'import'),
1728 'PACKAGES': 'import',
1729 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1730 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1731 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1732 'LISTS DICTIONARIES BACKQUOTES'),
1733 'OPERATORS': 'EXPRESSIONS',
1734 'PRECEDENCE': 'EXPRESSIONS',
1735 'OBJECTS': ('objects', 'TYPES'),
1736 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
1737 'CALLABLEMETHODS SEQUENCEMETHODS1 MAPPINGMETHODS '
1738 'SEQUENCEMETHODS2 NUMBERMETHODS CLASSES'),
1739 'BASICMETHODS': ('customization', 'cmp hash repr str SPECIALMETHODS'),
1740 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1741 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
1742 'SEQUENCEMETHODS1': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS2 '
1743 'SPECIALMETHODS'),
1744 'SEQUENCEMETHODS2': ('sequence-methods', 'SEQUENCES SEQUENCEMETHODS1 '
1745 'SPECIALMETHODS'),
1746 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1747 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1748 'SPECIALMETHODS'),
1749 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
1750 'NAMESPACES': ('naming', 'global ASSIGNMENT DELETION DYNAMICFEATURES'),
1751 'DYNAMICFEATURES': ('dynamic-features', ''),
1752 'SCOPING': 'NAMESPACES',
1753 'FRAMES': 'NAMESPACES',
1754 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1755 'COERCIONS': ('coercion-rules','CONVERSIONS'),
1756 'CONVERSIONS': ('conversions', 'COERCIONS'),
1757 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1758 'SPECIALIDENTIFIERS': ('id-classes', ''),
1759 'PRIVATENAMES': ('atom-identifiers', ''),
1760 'LITERALS': ('atom-literals', 'STRINGS BACKQUOTES NUMBERS '
1761 'TUPLELITERALS LISTLITERALS DICTIONARYLITERALS'),
1762 'TUPLES': 'SEQUENCES',
1763 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1764 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1765 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1766 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1767 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1768 'BACKQUOTES': ('string-conversions', 'repr str STRINGS LITERALS'),
1769 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr '
1770 'ATTRIBUTEMETHODS'),
1771 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS1'),
1772 'SLICINGS': ('slicings', 'SEQUENCEMETHODS2'),
1773 'CALLS': ('calls', 'EXPRESSIONS'),
1774 'POWER': ('power', 'EXPRESSIONS'),
1775 'UNARY': ('unary', 'EXPRESSIONS'),
1776 'BINARY': ('binary', 'EXPRESSIONS'),
1777 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1778 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1779 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1780 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
1781 'ASSERTION': 'assert',
1782 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1783 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
1784 'DELETION': 'del',
1785 'PRINTING': 'print',
1786 'RETURNING': 'return',
1787 'IMPORTING': 'import',
1788 'CONDITIONAL': 'if',
1789 'LOOPING': ('compound', 'for while break continue'),
1790 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1791 'DEBUGGING': ('debugger', 'pdb'),
1792 'CONTEXTMANAGERS': ('context-managers', 'with'),
1793 }
1794
1795 def __init__(self, input=None, output=None):
1796 self._input = input
1797 self._output = output
1798
1799 input = property(lambda self: self._input or sys.stdin)
1800 output = property(lambda self: self._output or sys.stdout)
1801
1802 def __repr__(self):
1803 if inspect.stack()[1][3] == '?':
1804 self()
1805 return ''
1806 return '<pydoc.Helper instance>'
1807
1808 _GoInteractive = object()
1809 def __call__(self, request=_GoInteractive):
1810 if request is not self._GoInteractive:
1811 self.help(request)
1812 else:
1813 self.intro()
1814 self.interact()
1815 self.output.write('''
1816 You are now leaving help and returning to the Python interpreter.
1817 If you want to ask for help on a particular object directly from the
1818 interpreter, you can type "help(object)". Executing "help('string')"
1819 has the same effect as typing a particular string at the help> prompt.
1820 ''')
1821
1822 def interact(self):
1823 self.output.write('\n')
1824 while True:
1825 try:
1826 request = self.getline('help> ')
1827 if not request: break
1828 except (KeyboardInterrupt, EOFError):
1829 break
1830 request = strip(replace(request, '"', '', "'", ''))
1831 if lower(request) in ('q', 'quit'): break
1832 self.help(request)
1833
1834 def getline(self, prompt):
1835 """Read one line, using raw_input when available."""
1836 if self.input is sys.stdin:
1837 return raw_input(prompt)
1838 else:
1839 self.output.write(prompt)
1840 self.output.flush()
1841 return self.input.readline()
1842
1843 def help(self, request):
1844 if type(request) is type(''):
1845 request = request.strip()
1846 if request == 'help': self.intro()
1847 elif request == 'keywords': self.listkeywords()
1848 elif request == 'symbols': self.listsymbols()
1849 elif request == 'topics': self.listtopics()
1850 elif request == 'modules': self.listmodules()
1851 elif request[:8] == 'modules ':
1852 self.listmodules(split(request)[1])
1853 elif request in self.symbols: self.showsymbol(request)
1854 elif request in self.keywords: self.showtopic(request)
1855 elif request in self.topics: self.showtopic(request)
1856 elif request: doc(request, 'Help on %s:')
1857 elif isinstance(request, Helper): self()
1858 else: doc(request, 'Help on %s:')
1859 self.output.write('\n')
1860
1861 def intro(self):
1862 self.output.write('''
1863 Welcome to Python %s! This is the online help utility.
1864
1865 If this is your first time using Python, you should definitely check out
1866 the tutorial on the Internet at http://docs.python.org/%s/tutorial/.
1867
1868 Enter the name of any module, keyword, or topic to get help on writing
1869 Python programs and using Python modules. To quit this help utility and
1870 return to the interpreter, just type "quit".
1871
1872 To get a list of available modules, keywords, or topics, type "modules",
1873 "keywords", or "topics". Each module also comes with a one-line summary
1874 of what it does; to list the modules whose summaries contain a given word
1875 such as "spam", type "modules spam".
1876 ''' % tuple([sys.version[:3]]*2))
1877
1878 def list(self, items, columns=4, width=80):
1879 items = items[:]
1880 items.sort()
1881 colw = width / columns
1882 rows = (len(items) + columns - 1) / columns
1883 for row in range(rows):
1884 for col in range(columns):
1885 i = col * rows + row
1886 if i < len(items):
1887 self.output.write(items[i])
1888 if col < columns - 1:
1889 self.output.write(' ' + ' ' * (colw-1 - len(items[i])))
1890 self.output.write('\n')
1891
1892 def listkeywords(self):
1893 self.output.write('''
1894 Here is a list of the Python keywords. Enter any keyword to get more help.
1895
1896 ''')
1897 self.list(self.keywords.keys())
1898
1899 def listsymbols(self):
1900 self.output.write('''
1901 Here is a list of the punctuation symbols which Python assigns special meaning
1902 to. Enter any symbol to get more help.
1903
1904 ''')
1905 self.list(self.symbols.keys())
1906
1907 def listtopics(self):
1908 self.output.write('''
1909 Here is a list of available topics. Enter any topic name to get more help.
1910
1911 ''')
1912 self.list(self.topics.keys())
1913
1914 def showtopic(self, topic, more_xrefs=''):
1915 try:
1916 import pydoc_data.topics
1917 except ImportError:
1918 self.output.write('''
1919 Sorry, topic and keyword documentation is not available because the
1920 module "pydoc_data.topics" could not be found.
1921 ''')
1922 return
1923 target = self.topics.get(topic, self.keywords.get(topic))
1924 if not target:
1925 self.output.write('no documentation found for %s\n' % repr(topic))
1926 return
1927 if type(target) is type(''):
1928 return self.showtopic(target, more_xrefs)
1929
1930 label, xrefs = target
1931 try:
1932 doc = pydoc_data.topics.topics[label]
1933 except KeyError:
1934 self.output.write('no documentation found for %s\n' % repr(topic))
1935 return
1936 pager(strip(doc) + '\n')
1937 if more_xrefs:
1938 xrefs = (xrefs or '') + ' ' + more_xrefs
1939 if xrefs:
1940 import StringIO, formatter
1941 buffer = StringIO.StringIO()
1942 formatter.DumbWriter(buffer).send_flowing_data(
1943 'Related help topics: ' + join(split(xrefs), ', ') + '\n')
1944 self.output.write('\n%s\n' % buffer.getvalue())
1945
1946 def showsymbol(self, symbol):
1947 target = self.symbols[symbol]
1948 topic, _, xrefs = target.partition(' ')
1949 self.showtopic(topic, xrefs)
1950
1951 def listmodules(self, key=''):
1952 if key:
1953 self.output.write('''
1954 Here is a list of matching modules. Enter any module name to get more help.
1955
1956 ''')
1957 apropos(key)
1958 else:
1959 self.output.write('''
1960 Please wait a moment while I gather a list of all available modules...
1961
1962 ''')
1963 modules = {}
1964 def callback(path, modname, desc, modules=modules):
1965 if modname and modname[-9:] == '.__init__':
1966 modname = modname[:-9] + ' (package)'
1967 if find(modname, '.') < 0:
1968 modules[modname] = 1
1969 def onerror(modname):
1970 callback(None, modname, None)
1971 ModuleScanner().run(callback, onerror=onerror)
1972 self.list(modules.keys())
1973 self.output.write('''
1974 Enter any module name to get more help. Or, type "modules spam" to search
1975 for modules whose descriptions contain the word "spam".
1976 ''')
1977
1978 help = Helper()
1979
1980 class Scanner:
1981 """A generic tree iterator."""
1982 def __init__(self, roots, children, descendp):
1983 self.roots = roots[:]
1984 self.state = []
1985 self.children = children
1986 self.descendp = descendp
1987
1988 def next(self):
1989 if not self.state:
1990 if not self.roots:
1991 return None
1992 root = self.roots.pop(0)
1993 self.state = [(root, self.children(root))]
1994 node, children = self.state[-1]
1995 if not children:
1996 self.state.pop()
1997 return self.next()
1998 child = children.pop(0)
1999 if self.descendp(child):
2000 self.state.append((child, self.children(child)))
2001 return child
2002
2003
2004 class ModuleScanner:
2005 """An interruptible scanner that searches module synopses."""
2006
2007 def run(self, callback, key=None, completer=None, onerror=None):
2008 if key: key = lower(key)
2009 self.quit = False
2010 seen = {}
2011
2012 for modname in sys.builtin_module_names:
2013 if modname != '__main__':
2014 seen[modname] = 1
2015 if key is None:
2016 callback(None, modname, '')
2017 else:
2018 desc = split(__import__(modname).__doc__ or '', '\n')[0]
2019 if find(lower(modname + ' - ' + desc), key) >= 0:
2020 callback(None, modname, desc)
2021
2022 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
2023 if self.quit:
2024 break
2025 if key is None:
2026 callback(None, modname, '')
2027 else:
2028 loader = importer.find_module(modname)
2029 if hasattr(loader,'get_source'):
2030 import StringIO
2031 desc = source_synopsis(
2032 StringIO.StringIO(loader.get_source(modname))
2033 ) or ''
2034 if hasattr(loader,'get_filename'):
2035 path = loader.get_filename(modname)
2036 else:
2037 path = None
2038 else:
2039 module = loader.load_module(modname)
2040 desc = module.__doc__.splitlines()[0] if module.__doc__ else ''
2041 path = getattr(module,'__file__',None)
2042 if find(lower(modname + ' - ' + desc), key) >= 0:
2043 callback(path, modname, desc)
2044
2045 if completer:
2046 completer()
2047
2048 def apropos(key):
2049 """Print all the one-line module summaries that contain a substring."""
2050 def callback(path, modname, desc):
2051 if modname[-9:] == '.__init__':
2052 modname = modname[:-9] + ' (package)'
2053 print modname, desc and '- ' + desc
2054 def onerror(modname):
2055 pass
2056 with warnings.catch_warnings():
2057 warnings.filterwarnings('ignore') # ignore problems during import
2058 ModuleScanner().run(callback, key, onerror=onerror)
2059
2060 # --------------------------------------------------- web browser interface
2061
2062 def serve(port, callback=None, completer=None):
2063 import BaseHTTPServer, mimetools, select
2064
2065 # Patch up mimetools.Message so it doesn't break if rfc822 is reloaded.
2066 class Message(mimetools.Message):
2067 def __init__(self, fp, seekable=1):
2068 Message = self.__class__
2069 Message.__bases__[0].__bases__[0].__init__(self, fp, seekable)
2070 self.encodingheader = self.getheader('content-transfer-encoding')
2071 self.typeheader = self.getheader('content-type')
2072 self.parsetype()
2073 self.parseplist()
2074
2075 class DocHandler(BaseHTTPServer.BaseHTTPRequestHandler):
2076 def send_document(self, title, contents):
2077 try:
2078 self.send_response(200)
2079 self.send_header('Content-Type', 'text/html')
2080 self.end_headers()
2081 self.wfile.write(html.page(title, contents))
2082 except IOError: pass
2083
2084 def do_GET(self):
2085 path = self.path
2086 if path[-5:] == '.html': path = path[:-5]
2087 if path[:1] == '/': path = path[1:]
2088 if path and path != '.':
2089 try:
2090 obj = locate(path, forceload=1)
2091 except ErrorDuringImport, value:
2092 self.send_document(path, html.escape(str(value)))
2093 return
2094 if obj:
2095 self.send_document(describe(obj), html.document(obj, path))
2096 else:
2097 self.send_document(path,
2098 'no Python documentation found for %s' % repr(path))
2099 else:
2100 heading = html.heading(
2101 '<big><big><strong>Python: Index of Modules</strong></big></big>',
2102 '#ffffff', '#7799ee')
2103 def bltinlink(name):
2104 return '<a href="%s.html">%s</a>' % (name, name)
2105 names = filter(lambda x: x != '__main__',
2106 sys.builtin_module_names)
2107 contents = html.multicolumn(names, bltinlink)
2108 indices = ['<p>' + html.bigsection(
2109 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2110
2111 seen = {}
2112 for dir in sys.path:
2113 indices.append(html.index(dir, seen))
2114 contents = heading + join(indices) + '''<p align=right>
2115 <font color="#909090" face="helvetica, arial"><strong>
2116 pydoc</strong> by Ka-Ping Yee &lt;ping@lfw.org&gt;</font>'''
2117 self.send_document('Index of Modules', contents)
2118
2119 def log_message(self, *args): pass
2120
2121 class DocServer(BaseHTTPServer.HTTPServer):
2122 def __init__(self, port, callback):
2123 host = 'localhost'
2124 self.address = (host, port)
2125 self.callback = callback
2126 self.base.__init__(self, self.address, self.handler)
2127
2128 def serve_until_quit(self):
2129 import select
2130 self.quit = False
2131 while not self.quit:
2132 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2133 if rd: self.handle_request()
2134
2135 def server_activate(self):
2136 self.base.server_activate(self)
2137 self.url = 'http://%s:%d/' % (self.address[0], self.server_port)
2138 if self.callback: self.callback(self)
2139
2140 DocServer.base = BaseHTTPServer.HTTPServer
2141 DocServer.handler = DocHandler
2142 DocHandler.MessageClass = Message
2143 try:
2144 try:
2145 DocServer(port, callback).serve_until_quit()
2146 except (KeyboardInterrupt, select.error):
2147 pass
2148 finally:
2149 if completer: completer()
2150
2151 # ----------------------------------------------------- graphical interface
2152
2153 def gui():
2154 """Graphical interface (starts web server and pops up a control window)."""
2155 class GUI:
2156 def __init__(self, window, port=7464):
2157 self.window = window
2158 self.server = None
2159 self.scanner = None
2160
2161 import Tkinter
2162 self.server_frm = Tkinter.Frame(window)
2163 self.title_lbl = Tkinter.Label(self.server_frm,
2164 text='Starting server...\n ')
2165 self.open_btn = Tkinter.Button(self.server_frm,
2166 text='open browser', command=self.open, state='disabled')
2167 self.quit_btn = Tkinter.Button(self.server_frm,
2168 text='quit serving', command=self.quit, state='disabled')
2169
2170 self.search_frm = Tkinter.Frame(window)
2171 self.search_lbl = Tkinter.Label(self.search_frm, text='Search for')
2172 self.search_ent = Tkinter.Entry(self.search_frm)
2173 self.search_ent.bind('<Return>', self.search)
2174 self.stop_btn = Tkinter.Button(self.search_frm,
2175 text='stop', pady=0, command=self.stop, state='disabled')
2176 if sys.platform == 'win32':
2177 # Trying to hide and show this button crashes under Windows.
2178 self.stop_btn.pack(side='right')
2179
2180 self.window.title('pydoc')
2181 self.window.protocol('WM_DELETE_WINDOW', self.quit)
2182 self.title_lbl.pack(side='top', fill='x')
2183 self.open_btn.pack(side='left', fill='x', expand=1)
2184 self.quit_btn.pack(side='right', fill='x', expand=1)
2185 self.server_frm.pack(side='top', fill='x')
2186
2187 self.search_lbl.pack(side='left')
2188 self.search_ent.pack(side='right', fill='x', expand=1)
2189 self.search_frm.pack(side='top', fill='x')
2190 self.search_ent.focus_set()
2191
2192 font = ('helvetica', sys.platform == 'win32' and 8 or 10)
2193 self.result_lst = Tkinter.Listbox(window, font=font, height=6)
2194 self.result_lst.bind('<Button-1>', self.select)
2195 self.result_lst.bind('<Double-Button-1>', self.goto)
2196 self.result_scr = Tkinter.Scrollbar(window,
2197 orient='vertical', command=self.result_lst.yview)
2198 self.result_lst.config(yscrollcommand=self.result_scr.set)
2199
2200 self.result_frm = Tkinter.Frame(window)
2201 self.goto_btn = Tkinter.Button(self.result_frm,
2202 text='go to selected', command=self.goto)
2203 self.hide_btn = Tkinter.Button(self.result_frm,
2204 text='hide results', command=self.hide)
2205 self.goto_btn.pack(side='left', fill='x', expand=1)
2206 self.hide_btn.pack(side='right', fill='x', expand=1)
2207
2208 self.window.update()
2209 self.minwidth = self.window.winfo_width()
2210 self.minheight = self.window.winfo_height()
2211 self.bigminheight = (self.server_frm.winfo_reqheight() +
2212 self.search_frm.winfo_reqheight() +
2213 self.result_lst.winfo_reqheight() +
2214 self.result_frm.winfo_reqheight())
2215 self.bigwidth, self.bigheight = self.minwidth, self.bigminheight
2216 self.expanded = 0
2217 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2218 self.window.wm_minsize(self.minwidth, self.minheight)
2219 self.window.tk.willdispatch()
2220
2221 import threading
2222 threading.Thread(
2223 target=serve, args=(port, self.ready, self.quit)).start()
2224
2225 def ready(self, server):
2226 self.server = server
2227 self.title_lbl.config(
2228 text='Python documentation server at\n' + server.url)
2229 self.open_btn.config(state='normal')
2230 self.quit_btn.config(state='normal')
2231
2232 def open(self, event=None, url=None):
2233 url = url or self.server.url
2234 try:
2235 import webbrowser
2236 webbrowser.open(url)
2237 except ImportError: # pre-webbrowser.py compatibility
2238 if sys.platform == 'win32':
2239 os.system('start "%s"' % url)
2240 else:
2241 rc = os.system('netscape -remote "openURL(%s)" &' % url)
2242 if rc: os.system('netscape "%s" &' % url)
2243
2244 def quit(self, event=None):
2245 if self.server:
2246 self.server.quit = 1
2247 self.window.quit()
2248
2249 def search(self, event=None):
2250 key = self.search_ent.get()
2251 self.stop_btn.pack(side='right')
2252 self.stop_btn.config(state='normal')
2253 self.search_lbl.config(text='Searching for "%s"...' % key)
2254 self.search_ent.forget()
2255 self.search_lbl.pack(side='left')
2256 self.result_lst.delete(0, 'end')
2257 self.goto_btn.config(state='disabled')
2258 self.expand()
2259
2260 import threading
2261 if self.scanner:
2262 self.scanner.quit = 1
2263 self.scanner = ModuleScanner()
2264 threading.Thread(target=self.scanner.run,
2265 args=(self.update, key, self.done)).start()
2266
2267 def update(self, path, modname, desc):
2268 if modname[-9:] == '.__init__':
2269 modname = modname[:-9] + ' (package)'
2270 self.result_lst.insert('end',
2271 modname + ' - ' + (desc or '(no description)'))
2272
2273 def stop(self, event=None):
2274 if self.scanner:
2275 self.scanner.quit = 1
2276 self.scanner = None
2277
2278 def done(self):
2279 self.scanner = None
2280 self.search_lbl.config(text='Search for')
2281 self.search_lbl.pack(side='left')
2282 self.search_ent.pack(side='right', fill='x', expand=1)
2283 if sys.platform != 'win32': self.stop_btn.forget()
2284 self.stop_btn.config(state='disabled')
2285
2286 def select(self, event=None):
2287 self.goto_btn.config(state='normal')
2288
2289 def goto(self, event=None):
2290 selection = self.result_lst.curselection()
2291 if selection:
2292 modname = split(self.result_lst.get(selection[0]))[0]
2293 self.open(url=self.server.url + modname + '.html')
2294
2295 def collapse(self):
2296 if not self.expanded: return
2297 self.result_frm.forget()
2298 self.result_scr.forget()
2299 self.result_lst.forget()
2300 self.bigwidth = self.window.winfo_width()
2301 self.bigheight = self.window.winfo_height()
2302 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2303 self.window.wm_minsize(self.minwidth, self.minheight)
2304 self.expanded = 0
2305
2306 def expand(self):
2307 if self.expanded: return
2308 self.result_frm.pack(side='bottom', fill='x')
2309 self.result_scr.pack(side='right', fill='y')
2310 self.result_lst.pack(side='top', fill='both', expand=1)
2311 self.window.wm_geometry('%dx%d' % (self.bigwidth, self.bigheight))
2312 self.window.wm_minsize(self.minwidth, self.bigminheight)
2313 self.expanded = 1
2314
2315 def hide(self, event=None):
2316 self.stop()
2317 self.collapse()
2318
2319 import Tkinter
2320 try:
2321 root = Tkinter.Tk()
2322 # Tk will crash if pythonw.exe has an XP .manifest
2323 # file and the root has is not destroyed explicitly.
2324 # If the problem is ever fixed in Tk, the explicit
2325 # destroy can go.
2326 try:
2327 gui = GUI(root)
2328 root.mainloop()
2329 finally:
2330 root.destroy()
2331 except KeyboardInterrupt:
2332 pass
2333
2334 # -------------------------------------------------- command-line interface
2335
2336 def ispath(x):
2337 return isinstance(x, str) and find(x, os.sep) >= 0
2338
2339 def cli():
2340 """Command-line interface (looks at sys.argv to decide what to do)."""
2341 import getopt
2342 class BadUsage: pass
2343
2344 # Scripts don't get the current directory in their path by default
2345 # unless they are run with the '-m' switch
2346 if '' not in sys.path:
2347 scriptdir = os.path.dirname(sys.argv[0])
2348 if scriptdir in sys.path:
2349 sys.path.remove(scriptdir)
2350 sys.path.insert(0, '.')
2351
2352 try:
2353 opts, args = getopt.getopt(sys.argv[1:], 'gk:p:w')
2354 writing = 0
2355
2356 for opt, val in opts:
2357 if opt == '-g':
2358 gui()
2359 return
2360 if opt == '-k':
2361 apropos(val)
2362 return
2363 if opt == '-p':
2364 try:
2365 port = int(val)
2366 except ValueError:
2367 raise BadUsage
2368 def ready(server):
2369 print 'pydoc server ready at %s' % server.url
2370 def stopped():
2371 print 'pydoc server stopped'
2372 serve(port, ready, stopped)
2373 return
2374 if opt == '-w':
2375 writing = 1
2376
2377 if not args: raise BadUsage
2378 for arg in args:
2379 if ispath(arg) and not os.path.exists(arg):
2380 print 'file %r does not exist' % arg
2381 break
2382 try:
2383 if ispath(arg) and os.path.isfile(arg):
2384 arg = importfile(arg)
2385 if writing:
2386 if ispath(arg) and os.path.isdir(arg):
2387 writedocs(arg)
2388 else:
2389 writedoc(arg)
2390 else:
2391 help.help(arg)
2392 except ErrorDuringImport, value:
2393 print value
2394
2395 except (getopt.error, BadUsage):
2396 cmd = os.path.basename(sys.argv[0])
2397 print """pydoc - the Python documentation tool
2398
2399 %s <name> ...
2400 Show text documentation on something. <name> may be the name of a
2401 Python keyword, topic, function, module, or package, or a dotted
2402 reference to a class or function within a module or module in a
2403 package. If <name> contains a '%s', it is used as the path to a
2404 Python source file to document. If name is 'keywords', 'topics',
2405 or 'modules', a listing of these things is displayed.
2406
2407 %s -k <keyword>
2408 Search for a keyword in the synopsis lines of all available modules.
2409
2410 %s -p <port>
2411 Start an HTTP server on the given port on the local machine. Port
2412 number 0 can be used to get an arbitrary unused port.
2413
2414 %s -g
2415 Pop up a graphical interface for finding and serving documentation.
2416
2417 %s -w <name> ...
2418 Write out the HTML documentation for a module to a file in the current
2419 directory. If <name> contains a '%s', it is treated as a filename; if
2420 it names a directory, documentation is written for all the contents.
2421 """ % (cmd, os.sep, cmd, cmd, cmd, cmd, os.sep)
2422
2423 if __name__ == '__main__': cli()