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