13b553e0ab2146ef2055c969a1893b453b2023cf4darylm#!/usr/bin/env python
23b553e0ab2146ef2055c969a1893b453b2023cf4darylm# -*- coding: latin-1 -*-
33b553e0ab2146ef2055c969a1893b453b2023cf4darylm"""Generate Python documentation in HTML or text for interactive use.
43b553e0ab2146ef2055c969a1893b453b2023cf4darylm
53b553e0ab2146ef2055c969a1893b453b2023cf4darylmIn the Python interpreter, do "from pydoc import help" to provide online
63b553e0ab2146ef2055c969a1893b453b2023cf4darylmhelp.  Calling help(thing) on a Python object documents the object.
73b553e0ab2146ef2055c969a1893b453b2023cf4darylm
83b553e0ab2146ef2055c969a1893b453b2023cf4darylmOr, at the shell command line outside of Python:
93b553e0ab2146ef2055c969a1893b453b2023cf4darylm
103b553e0ab2146ef2055c969a1893b453b2023cf4darylmRun "pydoc <name>" to show documentation on something.  <name> may be
113b553e0ab2146ef2055c969a1893b453b2023cf4darylmthe name of a function, module, package, or a dotted reference to a
123b553e0ab2146ef2055c969a1893b453b2023cf4darylmclass or function within a module or module in a package.  If the
133b553e0ab2146ef2055c969a1893b453b2023cf4darylmargument contains a path segment delimiter (e.g. slash on Unix,
143b553e0ab2146ef2055c969a1893b453b2023cf4darylmbackslash on Windows) it is treated as the path to a Python source file.
153b553e0ab2146ef2055c969a1893b453b2023cf4darylm
163b553e0ab2146ef2055c969a1893b453b2023cf4darylmRun "pydoc -k <keyword>" to search for a keyword in the synopsis lines
173b553e0ab2146ef2055c969a1893b453b2023cf4darylmof all available modules.
183b553e0ab2146ef2055c969a1893b453b2023cf4darylm
193b553e0ab2146ef2055c969a1893b453b2023cf4darylmRun "pydoc -p <port>" to start an HTTP server on a given port on the
203b553e0ab2146ef2055c969a1893b453b2023cf4darylmlocal machine to generate documentation web pages.
213b553e0ab2146ef2055c969a1893b453b2023cf4darylm
223b553e0ab2146ef2055c969a1893b453b2023cf4darylmFor platforms without a command line, "pydoc -g" starts the HTTP server
233b553e0ab2146ef2055c969a1893b453b2023cf4darylmand also pops up a little window for controlling it.
243b553e0ab2146ef2055c969a1893b453b2023cf4darylm
253b553e0ab2146ef2055c969a1893b453b2023cf4darylmRun "pydoc -w <name>" to write out the HTML documentation for a module
263b553e0ab2146ef2055c969a1893b453b2023cf4darylmto a file named "<name>.html".
273b553e0ab2146ef2055c969a1893b453b2023cf4darylm
283b553e0ab2146ef2055c969a1893b453b2023cf4darylmModule docs for core modules are assumed to be in
293b553e0ab2146ef2055c969a1893b453b2023cf4darylm
303b553e0ab2146ef2055c969a1893b453b2023cf4darylm    http://docs.python.org/library/
313b553e0ab2146ef2055c969a1893b453b2023cf4darylm
323b553e0ab2146ef2055c969a1893b453b2023cf4darylmThis can be overridden by setting the PYTHONDOCS environment variable
333b553e0ab2146ef2055c969a1893b453b2023cf4darylmto a different URL or to a local directory containing the Library
343b553e0ab2146ef2055c969a1893b453b2023cf4darylmReference Manual pages.
353b553e0ab2146ef2055c969a1893b453b2023cf4darylm"""
363b553e0ab2146ef2055c969a1893b453b2023cf4darylm
373b553e0ab2146ef2055c969a1893b453b2023cf4darylm__author__ = "Ka-Ping Yee <ping@lfw.org>"
383b553e0ab2146ef2055c969a1893b453b2023cf4darylm__date__ = "26 February 2001"
393b553e0ab2146ef2055c969a1893b453b2023cf4darylm
403b553e0ab2146ef2055c969a1893b453b2023cf4darylm__version__ = "$Revision$"
413b553e0ab2146ef2055c969a1893b453b2023cf4darylm__credits__ = """Guido van Rossum, for an excellent programming language.
423b553e0ab2146ef2055c969a1893b453b2023cf4darylmTommy Burnette, the original creator of manpy.
433b553e0ab2146ef2055c969a1893b453b2023cf4darylmPaul Prescod, for all his work on onlinehelp.
443b553e0ab2146ef2055c969a1893b453b2023cf4darylmRichard Chamberlain, for the first implementation of textdoc.
453b553e0ab2146ef2055c969a1893b453b2023cf4darylm"""
463b553e0ab2146ef2055c969a1893b453b2023cf4darylm
473b553e0ab2146ef2055c969a1893b453b2023cf4darylm# Known bugs that can't be fixed here:
483b553e0ab2146ef2055c969a1893b453b2023cf4darylm#   - imp.load_module() cannot be prevented from clobbering existing
493b553e0ab2146ef2055c969a1893b453b2023cf4darylm#     loaded modules, so calling synopsis() on a binary module file
503b553e0ab2146ef2055c969a1893b453b2023cf4darylm#     changes the contents of any existing module with the same name.
513b553e0ab2146ef2055c969a1893b453b2023cf4darylm#   - If the __file__ attribute on a module is a relative path and
523b553e0ab2146ef2055c969a1893b453b2023cf4darylm#     the current directory is changed with os.chdir(), an incorrect
533b553e0ab2146ef2055c969a1893b453b2023cf4darylm#     path will be displayed.
543b553e0ab2146ef2055c969a1893b453b2023cf4darylm
553b553e0ab2146ef2055c969a1893b453b2023cf4darylmimport sys, imp, os, re, types, inspect, __builtin__, pkgutil
563b553e0ab2146ef2055c969a1893b453b2023cf4darylmfrom repr import Repr
573b553e0ab2146ef2055c969a1893b453b2023cf4darylmfrom string import expandtabs, find, join, lower, split, strip, rfind, rstrip
583b553e0ab2146ef2055c969a1893b453b2023cf4darylmfrom traceback import extract_tb
593b553e0ab2146ef2055c969a1893b453b2023cf4darylmtry:
603b553e0ab2146ef2055c969a1893b453b2023cf4darylm    from collections import deque
613b553e0ab2146ef2055c969a1893b453b2023cf4darylmexcept ImportError:
623b553e0ab2146ef2055c969a1893b453b2023cf4darylm    # Python 2.3 compatibility
633b553e0ab2146ef2055c969a1893b453b2023cf4darylm    class deque(list):
643b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def popleft(self):
653b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return self.pop(0)
663b553e0ab2146ef2055c969a1893b453b2023cf4darylm
673b553e0ab2146ef2055c969a1893b453b2023cf4darylm# --------------------------------------------------------- common routines
683b553e0ab2146ef2055c969a1893b453b2023cf4darylm
693b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef pathdirs():
703b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Convert sys.path into a list of absolute, existing, unique paths."""
713b553e0ab2146ef2055c969a1893b453b2023cf4darylm    dirs = []
723b553e0ab2146ef2055c969a1893b453b2023cf4darylm    normdirs = []
733b553e0ab2146ef2055c969a1893b453b2023cf4darylm    for dir in sys.path:
743b553e0ab2146ef2055c969a1893b453b2023cf4darylm        dir = os.path.abspath(dir or '.')
753b553e0ab2146ef2055c969a1893b453b2023cf4darylm        normdir = os.path.normcase(dir)
763b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if normdir not in normdirs and os.path.isdir(dir):
773b553e0ab2146ef2055c969a1893b453b2023cf4darylm            dirs.append(dir)
783b553e0ab2146ef2055c969a1893b453b2023cf4darylm            normdirs.append(normdir)
793b553e0ab2146ef2055c969a1893b453b2023cf4darylm    return dirs
803b553e0ab2146ef2055c969a1893b453b2023cf4darylm
813b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef getdoc(object):
823b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Get the doc string or comments for an object."""
833b553e0ab2146ef2055c969a1893b453b2023cf4darylm    result = inspect.getdoc(object) or inspect.getcomments(object)
843b553e0ab2146ef2055c969a1893b453b2023cf4darylm    return result and re.sub('^ *\n', '', rstrip(result)) or ''
853b553e0ab2146ef2055c969a1893b453b2023cf4darylm
863b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef splitdoc(doc):
873b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Split a doc string into a synopsis line (if any) and the rest."""
883b553e0ab2146ef2055c969a1893b453b2023cf4darylm    lines = split(strip(doc), '\n')
893b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if len(lines) == 1:
903b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return lines[0], ''
913b553e0ab2146ef2055c969a1893b453b2023cf4darylm    elif len(lines) >= 2 and not rstrip(lines[1]):
923b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return lines[0], join(lines[2:], '\n')
933b553e0ab2146ef2055c969a1893b453b2023cf4darylm    return '', join(lines, '\n')
943b553e0ab2146ef2055c969a1893b453b2023cf4darylm
953b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef classname(object, modname):
963b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Get a class name and qualify it with a module name if necessary."""
973b553e0ab2146ef2055c969a1893b453b2023cf4darylm    name = object.__name__
983b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if object.__module__ != modname:
993b553e0ab2146ef2055c969a1893b453b2023cf4darylm        name = object.__module__ + '.' + name
1003b553e0ab2146ef2055c969a1893b453b2023cf4darylm    return name
1013b553e0ab2146ef2055c969a1893b453b2023cf4darylm
1023b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef isdata(object):
1033b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Check if an object is of a type that probably means it's data."""
1043b553e0ab2146ef2055c969a1893b453b2023cf4darylm    return not (inspect.ismodule(object) or inspect.isclass(object) or
1053b553e0ab2146ef2055c969a1893b453b2023cf4darylm                inspect.isroutine(object) or inspect.isframe(object) or
1063b553e0ab2146ef2055c969a1893b453b2023cf4darylm                inspect.istraceback(object) or inspect.iscode(object))
1073b553e0ab2146ef2055c969a1893b453b2023cf4darylm
1083b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef replace(text, *pairs):
1093b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Do a series of global replacements on a string."""
1103b553e0ab2146ef2055c969a1893b453b2023cf4darylm    while pairs:
1113b553e0ab2146ef2055c969a1893b453b2023cf4darylm        text = join(split(text, pairs[0]), pairs[1])
1123b553e0ab2146ef2055c969a1893b453b2023cf4darylm        pairs = pairs[2:]
1133b553e0ab2146ef2055c969a1893b453b2023cf4darylm    return text
1143b553e0ab2146ef2055c969a1893b453b2023cf4darylm
1153b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef cram(text, maxlen):
1163b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Omit part of a string if needed to make it fit in a maximum length."""
1173b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if len(text) > maxlen:
1183b553e0ab2146ef2055c969a1893b453b2023cf4darylm        pre = max(0, (maxlen-3)//2)
1193b553e0ab2146ef2055c969a1893b453b2023cf4darylm        post = max(0, maxlen-3-pre)
1203b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return text[:pre] + '...' + text[len(text)-post:]
1213b553e0ab2146ef2055c969a1893b453b2023cf4darylm    return text
1223b553e0ab2146ef2055c969a1893b453b2023cf4darylm
1233b553e0ab2146ef2055c969a1893b453b2023cf4darylm_re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
1243b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef stripid(text):
1253b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Remove the hexadecimal id from a Python object representation."""
1263b553e0ab2146ef2055c969a1893b453b2023cf4darylm    # The behaviour of %p is implementation-dependent in terms of case.
1273b553e0ab2146ef2055c969a1893b453b2023cf4darylm    return _re_stripid.sub(r'\1', text)
1283b553e0ab2146ef2055c969a1893b453b2023cf4darylm
1293b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef _is_some_method(obj):
1303b553e0ab2146ef2055c969a1893b453b2023cf4darylm    return inspect.ismethod(obj) or inspect.ismethoddescriptor(obj)
1313b553e0ab2146ef2055c969a1893b453b2023cf4darylm
1323b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef allmethods(cl):
1333b553e0ab2146ef2055c969a1893b453b2023cf4darylm    methods = {}
1343b553e0ab2146ef2055c969a1893b453b2023cf4darylm    for key, value in inspect.getmembers(cl, _is_some_method):
1353b553e0ab2146ef2055c969a1893b453b2023cf4darylm        methods[key] = 1
1363b553e0ab2146ef2055c969a1893b453b2023cf4darylm    for base in cl.__bases__:
1373b553e0ab2146ef2055c969a1893b453b2023cf4darylm        methods.update(allmethods(base)) # all your base are belong to us
1383b553e0ab2146ef2055c969a1893b453b2023cf4darylm    for key in methods.keys():
1393b553e0ab2146ef2055c969a1893b453b2023cf4darylm        methods[key] = getattr(cl, key)
1403b553e0ab2146ef2055c969a1893b453b2023cf4darylm    return methods
1413b553e0ab2146ef2055c969a1893b453b2023cf4darylm
1423b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef _split_list(s, predicate):
1433b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Split sequence s via predicate, and return pair ([true], [false]).
1443b553e0ab2146ef2055c969a1893b453b2023cf4darylm
1453b553e0ab2146ef2055c969a1893b453b2023cf4darylm    The return value is a 2-tuple of lists,
1463b553e0ab2146ef2055c969a1893b453b2023cf4darylm        ([x for x in s if predicate(x)],
1473b553e0ab2146ef2055c969a1893b453b2023cf4darylm         [x for x in s if not predicate(x)])
1483b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """
1493b553e0ab2146ef2055c969a1893b453b2023cf4darylm
1503b553e0ab2146ef2055c969a1893b453b2023cf4darylm    yes = []
1513b553e0ab2146ef2055c969a1893b453b2023cf4darylm    no = []
1523b553e0ab2146ef2055c969a1893b453b2023cf4darylm    for x in s:
1533b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if predicate(x):
1543b553e0ab2146ef2055c969a1893b453b2023cf4darylm            yes.append(x)
1553b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else:
1563b553e0ab2146ef2055c969a1893b453b2023cf4darylm            no.append(x)
1573b553e0ab2146ef2055c969a1893b453b2023cf4darylm    return yes, no
1583b553e0ab2146ef2055c969a1893b453b2023cf4darylm
1593b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef visiblename(name, all=None, obj=None):
1603b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Decide whether to show documentation on a variable."""
1613b553e0ab2146ef2055c969a1893b453b2023cf4darylm    # Certain special names are redundant.
1623b553e0ab2146ef2055c969a1893b453b2023cf4darylm    _hidden_names = ('__builtins__', '__doc__', '__file__', '__path__',
1633b553e0ab2146ef2055c969a1893b453b2023cf4darylm                     '__module__', '__name__', '__slots__', '__package__')
1643b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if name in _hidden_names: return 0
1653b553e0ab2146ef2055c969a1893b453b2023cf4darylm    # Private names are hidden, but special names are displayed.
1663b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if name.startswith('__') and name.endswith('__'): return 1
1673b553e0ab2146ef2055c969a1893b453b2023cf4darylm    # Namedtuples have public fields and methods with a single leading underscore
1683b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if name.startswith('_') and hasattr(obj, '_fields'):
1693b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return 1
1703b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if all is not None:
1713b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # only document that which the programmer exported in __all__
1723b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return name in all
1733b553e0ab2146ef2055c969a1893b453b2023cf4darylm    else:
1743b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return not name.startswith('_')
1753b553e0ab2146ef2055c969a1893b453b2023cf4darylm
1763b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef classify_class_attrs(object):
1773b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
1783b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def fixup(data):
1793b553e0ab2146ef2055c969a1893b453b2023cf4darylm        name, kind, cls, value = data
1803b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if inspect.isdatadescriptor(value):
1813b553e0ab2146ef2055c969a1893b453b2023cf4darylm            kind = 'data descriptor'
1823b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return name, kind, cls, value
1833b553e0ab2146ef2055c969a1893b453b2023cf4darylm    return map(fixup, inspect.classify_class_attrs(object))
1843b553e0ab2146ef2055c969a1893b453b2023cf4darylm
1853b553e0ab2146ef2055c969a1893b453b2023cf4darylm# ----------------------------------------------------- module manipulation
1863b553e0ab2146ef2055c969a1893b453b2023cf4darylm
1873b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef ispackage(path):
1883b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Guess whether a path refers to a package directory."""
1893b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if os.path.isdir(path):
1903b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for ext in ('.py', '.pyc', '.pyo'):
1913b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if os.path.isfile(os.path.join(path, '__init__' + ext)):
1923b553e0ab2146ef2055c969a1893b453b2023cf4darylm                return True
1933b553e0ab2146ef2055c969a1893b453b2023cf4darylm    return False
1943b553e0ab2146ef2055c969a1893b453b2023cf4darylm
1953b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef source_synopsis(file):
1963b553e0ab2146ef2055c969a1893b453b2023cf4darylm    line = file.readline()
1973b553e0ab2146ef2055c969a1893b453b2023cf4darylm    while line[:1] == '#' or not strip(line):
1983b553e0ab2146ef2055c969a1893b453b2023cf4darylm        line = file.readline()
1993b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if not line: break
2003b553e0ab2146ef2055c969a1893b453b2023cf4darylm    line = strip(line)
2013b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if line[:4] == 'r"""': line = line[1:]
2023b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if line[:3] == '"""':
2033b553e0ab2146ef2055c969a1893b453b2023cf4darylm        line = line[3:]
2043b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if line[-1:] == '\\': line = line[:-1]
2053b553e0ab2146ef2055c969a1893b453b2023cf4darylm        while not strip(line):
2063b553e0ab2146ef2055c969a1893b453b2023cf4darylm            line = file.readline()
2073b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if not line: break
2083b553e0ab2146ef2055c969a1893b453b2023cf4darylm        result = strip(split(line, '"""')[0])
2093b553e0ab2146ef2055c969a1893b453b2023cf4darylm    else: result = None
2103b553e0ab2146ef2055c969a1893b453b2023cf4darylm    return result
2113b553e0ab2146ef2055c969a1893b453b2023cf4darylm
2123b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef synopsis(filename, cache={}):
2133b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Get the one-line summary out of a module file."""
2143b553e0ab2146ef2055c969a1893b453b2023cf4darylm    mtime = os.stat(filename).st_mtime
2153b553e0ab2146ef2055c969a1893b453b2023cf4darylm    lastupdate, result = cache.get(filename, (0, None))
2163b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if lastupdate < mtime:
2173b553e0ab2146ef2055c969a1893b453b2023cf4darylm        info = inspect.getmoduleinfo(filename)
2183b553e0ab2146ef2055c969a1893b453b2023cf4darylm        try:
2193b553e0ab2146ef2055c969a1893b453b2023cf4darylm            file = open(filename)
2203b553e0ab2146ef2055c969a1893b453b2023cf4darylm        except IOError:
2213b553e0ab2146ef2055c969a1893b453b2023cf4darylm            # module can't be opened, so skip it
2223b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return None
2233b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if info and 'b' in info[2]: # binary modules have to be imported
2243b553e0ab2146ef2055c969a1893b453b2023cf4darylm            try: module = imp.load_module('__temp__', file, filename, info[1:])
2253b553e0ab2146ef2055c969a1893b453b2023cf4darylm            except: return None
2263b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = (module.__doc__ or '').splitlines()[0]
2273b553e0ab2146ef2055c969a1893b453b2023cf4darylm            del sys.modules['__temp__']
2283b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else: # text modules can be directly examined
2293b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = source_synopsis(file)
2303b553e0ab2146ef2055c969a1893b453b2023cf4darylm            file.close()
2313b553e0ab2146ef2055c969a1893b453b2023cf4darylm        cache[filename] = (mtime, result)
2323b553e0ab2146ef2055c969a1893b453b2023cf4darylm    return result
2333b553e0ab2146ef2055c969a1893b453b2023cf4darylm
2343b553e0ab2146ef2055c969a1893b453b2023cf4darylmclass ErrorDuringImport(Exception):
2353b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Errors that occurred while trying to import something to document it."""
2363b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def __init__(self, filename, exc_info):
2373b553e0ab2146ef2055c969a1893b453b2023cf4darylm        exc, value, tb = exc_info
2383b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.filename = filename
2393b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.exc = exc
2403b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.value = value
2413b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.tb = tb
2423b553e0ab2146ef2055c969a1893b453b2023cf4darylm
2433b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def __str__(self):
2443b553e0ab2146ef2055c969a1893b453b2023cf4darylm        exc = self.exc
2453b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if type(exc) is types.ClassType:
2463b553e0ab2146ef2055c969a1893b453b2023cf4darylm            exc = exc.__name__
2473b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
2483b553e0ab2146ef2055c969a1893b453b2023cf4darylm
2493b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef importfile(path):
2503b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Import a Python source file or compiled file given its path."""
2513b553e0ab2146ef2055c969a1893b453b2023cf4darylm    magic = imp.get_magic()
2523b553e0ab2146ef2055c969a1893b453b2023cf4darylm    file = open(path, 'r')
2533b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if file.read(len(magic)) == magic:
2543b553e0ab2146ef2055c969a1893b453b2023cf4darylm        kind = imp.PY_COMPILED
2553b553e0ab2146ef2055c969a1893b453b2023cf4darylm    else:
2563b553e0ab2146ef2055c969a1893b453b2023cf4darylm        kind = imp.PY_SOURCE
2573b553e0ab2146ef2055c969a1893b453b2023cf4darylm    file.close()
2583b553e0ab2146ef2055c969a1893b453b2023cf4darylm    filename = os.path.basename(path)
2593b553e0ab2146ef2055c969a1893b453b2023cf4darylm    name, ext = os.path.splitext(filename)
2603b553e0ab2146ef2055c969a1893b453b2023cf4darylm    file = open(path, 'r')
2613b553e0ab2146ef2055c969a1893b453b2023cf4darylm    try:
2623b553e0ab2146ef2055c969a1893b453b2023cf4darylm        module = imp.load_module(name, file, path, (ext, 'r', kind))
2633b553e0ab2146ef2055c969a1893b453b2023cf4darylm    except:
2643b553e0ab2146ef2055c969a1893b453b2023cf4darylm        raise ErrorDuringImport(path, sys.exc_info())
2653b553e0ab2146ef2055c969a1893b453b2023cf4darylm    file.close()
2663b553e0ab2146ef2055c969a1893b453b2023cf4darylm    return module
2673b553e0ab2146ef2055c969a1893b453b2023cf4darylm
2683b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef safeimport(path, forceload=0, cache={}):
2693b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Import a module; handle errors; return None if the module isn't found.
2703b553e0ab2146ef2055c969a1893b453b2023cf4darylm
2713b553e0ab2146ef2055c969a1893b453b2023cf4darylm    If the module *is* found but an exception occurs, it's wrapped in an
2723b553e0ab2146ef2055c969a1893b453b2023cf4darylm    ErrorDuringImport exception and reraised.  Unlike __import__, if a
2733b553e0ab2146ef2055c969a1893b453b2023cf4darylm    package path is specified, the module at the end of the path is returned,
2743b553e0ab2146ef2055c969a1893b453b2023cf4darylm    not the package at the beginning.  If the optional 'forceload' argument
2753b553e0ab2146ef2055c969a1893b453b2023cf4darylm    is 1, we reload the module from disk (unless it's a dynamic extension)."""
2763b553e0ab2146ef2055c969a1893b453b2023cf4darylm    try:
2773b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # If forceload is 1 and the module has been previously loaded from
2783b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # disk, we always have to reload the module.  Checking the file's
2793b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # mtime isn't good enough (e.g. the module could contain a class
2803b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # that inherits from another module that has changed).
2813b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if forceload and path in sys.modules:
2823b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if path not in sys.builtin_module_names:
2833b553e0ab2146ef2055c969a1893b453b2023cf4darylm                # Avoid simply calling reload() because it leaves names in
2843b553e0ab2146ef2055c969a1893b453b2023cf4darylm                # the currently loaded module lying around if they're not
2853b553e0ab2146ef2055c969a1893b453b2023cf4darylm                # defined in the new source file.  Instead, remove the
2863b553e0ab2146ef2055c969a1893b453b2023cf4darylm                # module from sys.modules and re-import.  Also remove any
2873b553e0ab2146ef2055c969a1893b453b2023cf4darylm                # submodules because they won't appear in the newly loaded
2883b553e0ab2146ef2055c969a1893b453b2023cf4darylm                # module's namespace if they're already in sys.modules.
2893b553e0ab2146ef2055c969a1893b453b2023cf4darylm                subs = [m for m in sys.modules if m.startswith(path + '.')]
2903b553e0ab2146ef2055c969a1893b453b2023cf4darylm                for key in [path] + subs:
2913b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    # Prevent garbage collection.
2923b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    cache[key] = sys.modules[key]
2933b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    del sys.modules[key]
2943b553e0ab2146ef2055c969a1893b453b2023cf4darylm        module = __import__(path)
2953b553e0ab2146ef2055c969a1893b453b2023cf4darylm    except:
2963b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # Did the error occur before or after the module was found?
2973b553e0ab2146ef2055c969a1893b453b2023cf4darylm        (exc, value, tb) = info = sys.exc_info()
2983b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if path in sys.modules:
2993b553e0ab2146ef2055c969a1893b453b2023cf4darylm            # An error occurred while executing the imported module.
3003b553e0ab2146ef2055c969a1893b453b2023cf4darylm            raise ErrorDuringImport(sys.modules[path].__file__, info)
3013b553e0ab2146ef2055c969a1893b453b2023cf4darylm        elif exc is SyntaxError:
3023b553e0ab2146ef2055c969a1893b453b2023cf4darylm            # A SyntaxError occurred before we could execute the module.
3033b553e0ab2146ef2055c969a1893b453b2023cf4darylm            raise ErrorDuringImport(value.filename, info)
3043b553e0ab2146ef2055c969a1893b453b2023cf4darylm        elif exc is ImportError and extract_tb(tb)[-1][2]=='safeimport':
3053b553e0ab2146ef2055c969a1893b453b2023cf4darylm            # The import error occurred directly in this function,
3063b553e0ab2146ef2055c969a1893b453b2023cf4darylm            # which means there is no such module in the path.
3073b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return None
3083b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else:
3093b553e0ab2146ef2055c969a1893b453b2023cf4darylm            # Some other error occurred during the importing process.
3103b553e0ab2146ef2055c969a1893b453b2023cf4darylm            raise ErrorDuringImport(path, sys.exc_info())
3113b553e0ab2146ef2055c969a1893b453b2023cf4darylm    for part in split(path, '.')[1:]:
3123b553e0ab2146ef2055c969a1893b453b2023cf4darylm        try: module = getattr(module, part)
3133b553e0ab2146ef2055c969a1893b453b2023cf4darylm        except AttributeError: return None
3143b553e0ab2146ef2055c969a1893b453b2023cf4darylm    return module
3153b553e0ab2146ef2055c969a1893b453b2023cf4darylm
3163b553e0ab2146ef2055c969a1893b453b2023cf4darylm# ---------------------------------------------------- formatter base class
3173b553e0ab2146ef2055c969a1893b453b2023cf4darylm
3183b553e0ab2146ef2055c969a1893b453b2023cf4darylmclass Doc:
3193b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def document(self, object, name=None, *args):
3203b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Generate documentation for an object."""
3213b553e0ab2146ef2055c969a1893b453b2023cf4darylm        args = (object, name) + args
3223b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # 'try' clause is to attempt to handle the possibility that inspect
3233b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # identifies something in a way that pydoc itself has issues handling;
3243b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # think 'super' and how it is a descriptor (which raises the exception
3253b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # by lacking a __name__ attribute) and an instance.
3263b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if inspect.isgetsetdescriptor(object): return self.docdata(*args)
3273b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if inspect.ismemberdescriptor(object): return self.docdata(*args)
3283b553e0ab2146ef2055c969a1893b453b2023cf4darylm        try:
3293b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if inspect.ismodule(object): return self.docmodule(*args)
3303b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if inspect.isclass(object): return self.docclass(*args)
3313b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if inspect.isroutine(object): return self.docroutine(*args)
3323b553e0ab2146ef2055c969a1893b453b2023cf4darylm        except AttributeError:
3333b553e0ab2146ef2055c969a1893b453b2023cf4darylm            pass
3343b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if isinstance(object, property): return self.docproperty(*args)
3353b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return self.docother(*args)
3363b553e0ab2146ef2055c969a1893b453b2023cf4darylm
3373b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def fail(self, object, name=None, *args):
3383b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Raise an exception for unimplemented types."""
3393b553e0ab2146ef2055c969a1893b453b2023cf4darylm        message = "don't know how to document object%s of type %s" % (
3403b553e0ab2146ef2055c969a1893b453b2023cf4darylm            name and ' ' + repr(name), type(object).__name__)
3413b553e0ab2146ef2055c969a1893b453b2023cf4darylm        raise TypeError, message
3423b553e0ab2146ef2055c969a1893b453b2023cf4darylm
3433b553e0ab2146ef2055c969a1893b453b2023cf4darylm    docmodule = docclass = docroutine = docother = docproperty = docdata = fail
3443b553e0ab2146ef2055c969a1893b453b2023cf4darylm
3453b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def getdocloc(self, object):
3463b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Return the location of module docs or None"""
3473b553e0ab2146ef2055c969a1893b453b2023cf4darylm
3483b553e0ab2146ef2055c969a1893b453b2023cf4darylm        try:
3493b553e0ab2146ef2055c969a1893b453b2023cf4darylm            file = inspect.getabsfile(object)
3503b553e0ab2146ef2055c969a1893b453b2023cf4darylm        except TypeError:
3513b553e0ab2146ef2055c969a1893b453b2023cf4darylm            file = '(built-in)'
3523b553e0ab2146ef2055c969a1893b453b2023cf4darylm
3533b553e0ab2146ef2055c969a1893b453b2023cf4darylm        docloc = os.environ.get("PYTHONDOCS",
3543b553e0ab2146ef2055c969a1893b453b2023cf4darylm                                "http://docs.python.org/library")
3553b553e0ab2146ef2055c969a1893b453b2023cf4darylm        basedir = os.path.join(sys.exec_prefix, "lib",
3563b553e0ab2146ef2055c969a1893b453b2023cf4darylm                               "python"+sys.version[0:3])
3573b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if (isinstance(object, type(os)) and
3583b553e0ab2146ef2055c969a1893b453b2023cf4darylm            (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
3593b553e0ab2146ef2055c969a1893b453b2023cf4darylm                                 'marshal', 'posix', 'signal', 'sys',
3603b553e0ab2146ef2055c969a1893b453b2023cf4darylm                                 'thread', 'zipimport') or
3613b553e0ab2146ef2055c969a1893b453b2023cf4darylm             (file.startswith(basedir) and
3623b553e0ab2146ef2055c969a1893b453b2023cf4darylm              not file.startswith(os.path.join(basedir, 'site-packages')))) and
3633b553e0ab2146ef2055c969a1893b453b2023cf4darylm            object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
3643b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if docloc.startswith("http://"):
3653b553e0ab2146ef2055c969a1893b453b2023cf4darylm                docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
3663b553e0ab2146ef2055c969a1893b453b2023cf4darylm            else:
3673b553e0ab2146ef2055c969a1893b453b2023cf4darylm                docloc = os.path.join(docloc, object.__name__ + ".html")
3683b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else:
3693b553e0ab2146ef2055c969a1893b453b2023cf4darylm            docloc = None
3703b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return docloc
3713b553e0ab2146ef2055c969a1893b453b2023cf4darylm
3723b553e0ab2146ef2055c969a1893b453b2023cf4darylm# -------------------------------------------- HTML documentation generator
3733b553e0ab2146ef2055c969a1893b453b2023cf4darylm
3743b553e0ab2146ef2055c969a1893b453b2023cf4darylmclass HTMLRepr(Repr):
3753b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Class for safely making an HTML representation of a Python object."""
3763b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def __init__(self):
3773b553e0ab2146ef2055c969a1893b453b2023cf4darylm        Repr.__init__(self)
3783b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.maxlist = self.maxtuple = 20
3793b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.maxdict = 10
3803b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.maxstring = self.maxother = 100
3813b553e0ab2146ef2055c969a1893b453b2023cf4darylm
3823b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def escape(self, text):
3833b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
3843b553e0ab2146ef2055c969a1893b453b2023cf4darylm
3853b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def repr(self, object):
3863b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return Repr.repr(self, object)
3873b553e0ab2146ef2055c969a1893b453b2023cf4darylm
3883b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def repr1(self, x, level):
3893b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if hasattr(type(x), '__name__'):
3903b553e0ab2146ef2055c969a1893b453b2023cf4darylm            methodname = 'repr_' + join(split(type(x).__name__), '_')
3913b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if hasattr(self, methodname):
3923b553e0ab2146ef2055c969a1893b453b2023cf4darylm                return getattr(self, methodname)(x, level)
3933b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return self.escape(cram(stripid(repr(x)), self.maxother))
3943b553e0ab2146ef2055c969a1893b453b2023cf4darylm
3953b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def repr_string(self, x, level):
3963b553e0ab2146ef2055c969a1893b453b2023cf4darylm        test = cram(x, self.maxstring)
3973b553e0ab2146ef2055c969a1893b453b2023cf4darylm        testrepr = repr(test)
3983b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
3993b553e0ab2146ef2055c969a1893b453b2023cf4darylm            # Backslashes are only literal in the string and are never
4003b553e0ab2146ef2055c969a1893b453b2023cf4darylm            # needed to make any special characters, so show a raw string.
4013b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
4023b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
4033b553e0ab2146ef2055c969a1893b453b2023cf4darylm                      r'<font color="#c040c0">\1</font>',
4043b553e0ab2146ef2055c969a1893b453b2023cf4darylm                      self.escape(testrepr))
4053b553e0ab2146ef2055c969a1893b453b2023cf4darylm
4063b553e0ab2146ef2055c969a1893b453b2023cf4darylm    repr_str = repr_string
4073b553e0ab2146ef2055c969a1893b453b2023cf4darylm
4083b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def repr_instance(self, x, level):
4093b553e0ab2146ef2055c969a1893b453b2023cf4darylm        try:
4103b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return self.escape(cram(stripid(repr(x)), self.maxstring))
4113b553e0ab2146ef2055c969a1893b453b2023cf4darylm        except:
4123b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return self.escape('<%s instance>' % x.__class__.__name__)
4133b553e0ab2146ef2055c969a1893b453b2023cf4darylm
4143b553e0ab2146ef2055c969a1893b453b2023cf4darylm    repr_unicode = repr_string
4153b553e0ab2146ef2055c969a1893b453b2023cf4darylm
4163b553e0ab2146ef2055c969a1893b453b2023cf4darylmclass HTMLDoc(Doc):
4173b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Formatter class for HTML documentation."""
4183b553e0ab2146ef2055c969a1893b453b2023cf4darylm
4193b553e0ab2146ef2055c969a1893b453b2023cf4darylm    # ------------------------------------------- HTML formatting utilities
4203b553e0ab2146ef2055c969a1893b453b2023cf4darylm
4213b553e0ab2146ef2055c969a1893b453b2023cf4darylm    _repr_instance = HTMLRepr()
4223b553e0ab2146ef2055c969a1893b453b2023cf4darylm    repr = _repr_instance.repr
4233b553e0ab2146ef2055c969a1893b453b2023cf4darylm    escape = _repr_instance.escape
4243b553e0ab2146ef2055c969a1893b453b2023cf4darylm
4253b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def page(self, title, contents):
4263b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Format an HTML page."""
4273b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return '''
4283b553e0ab2146ef2055c969a1893b453b2023cf4darylm<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
4293b553e0ab2146ef2055c969a1893b453b2023cf4darylm<html><head><title>Python: %s</title>
4303b553e0ab2146ef2055c969a1893b453b2023cf4darylm</head><body bgcolor="#f0f0f8">
4313b553e0ab2146ef2055c969a1893b453b2023cf4darylm%s
4323b553e0ab2146ef2055c969a1893b453b2023cf4darylm</body></html>''' % (title, contents)
4333b553e0ab2146ef2055c969a1893b453b2023cf4darylm
4343b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def heading(self, title, fgcol, bgcol, extras=''):
4353b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Format a page heading."""
4363b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return '''
4373b553e0ab2146ef2055c969a1893b453b2023cf4darylm<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
4383b553e0ab2146ef2055c969a1893b453b2023cf4darylm<tr bgcolor="%s">
4393b553e0ab2146ef2055c969a1893b453b2023cf4darylm<td valign=bottom>&nbsp;<br>
4403b553e0ab2146ef2055c969a1893b453b2023cf4darylm<font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
4413b553e0ab2146ef2055c969a1893b453b2023cf4darylm><td align=right valign=bottom
4423b553e0ab2146ef2055c969a1893b453b2023cf4darylm><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
4433b553e0ab2146ef2055c969a1893b453b2023cf4darylm    ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
4443b553e0ab2146ef2055c969a1893b453b2023cf4darylm
4453b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def section(self, title, fgcol, bgcol, contents, width=6,
4463b553e0ab2146ef2055c969a1893b453b2023cf4darylm                prelude='', marginalia=None, gap='&nbsp;'):
4473b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Format a section with a heading."""
4483b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if marginalia is None:
4493b553e0ab2146ef2055c969a1893b453b2023cf4darylm            marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
4503b553e0ab2146ef2055c969a1893b453b2023cf4darylm        result = '''<p>
4513b553e0ab2146ef2055c969a1893b453b2023cf4darylm<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
4523b553e0ab2146ef2055c969a1893b453b2023cf4darylm<tr bgcolor="%s">
4533b553e0ab2146ef2055c969a1893b453b2023cf4darylm<td colspan=3 valign=bottom>&nbsp;<br>
4543b553e0ab2146ef2055c969a1893b453b2023cf4darylm<font color="%s" face="helvetica, arial">%s</font></td></tr>
4553b553e0ab2146ef2055c969a1893b453b2023cf4darylm    ''' % (bgcol, fgcol, title)
4563b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if prelude:
4573b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = result + '''
4583b553e0ab2146ef2055c969a1893b453b2023cf4darylm<tr bgcolor="%s"><td rowspan=2>%s</td>
4593b553e0ab2146ef2055c969a1893b453b2023cf4darylm<td colspan=2>%s</td></tr>
4603b553e0ab2146ef2055c969a1893b453b2023cf4darylm<tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
4613b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else:
4623b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = result + '''
4633b553e0ab2146ef2055c969a1893b453b2023cf4darylm<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
4643b553e0ab2146ef2055c969a1893b453b2023cf4darylm
4653b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return result + '\n<td width="100%%">%s</td></tr></table>' % contents
4663b553e0ab2146ef2055c969a1893b453b2023cf4darylm
4673b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def bigsection(self, title, *args):
4683b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Format a section with a big heading."""
4693b553e0ab2146ef2055c969a1893b453b2023cf4darylm        title = '<big><strong>%s</strong></big>' % title
4703b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return self.section(title, *args)
4713b553e0ab2146ef2055c969a1893b453b2023cf4darylm
4723b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def preformat(self, text):
4733b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Format literal preformatted text."""
4743b553e0ab2146ef2055c969a1893b453b2023cf4darylm        text = self.escape(expandtabs(text))
4753b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
4763b553e0ab2146ef2055c969a1893b453b2023cf4darylm                             ' ', '&nbsp;', '\n', '<br>\n')
4773b553e0ab2146ef2055c969a1893b453b2023cf4darylm
4783b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def multicolumn(self, list, format, cols=4):
4793b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Format a list of items into a multi-column list."""
4803b553e0ab2146ef2055c969a1893b453b2023cf4darylm        result = ''
4813b553e0ab2146ef2055c969a1893b453b2023cf4darylm        rows = (len(list)+cols-1)//cols
4823b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for col in range(cols):
4833b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = result + '<td width="%d%%" valign=top>' % (100//cols)
4843b553e0ab2146ef2055c969a1893b453b2023cf4darylm            for i in range(rows*col, rows*col+rows):
4853b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if i < len(list):
4863b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    result = result + format(list[i]) + '<br>\n'
4873b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = result + '</td>'
4883b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
4893b553e0ab2146ef2055c969a1893b453b2023cf4darylm
4903b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def grey(self, text): return '<font color="#909090">%s</font>' % text
4913b553e0ab2146ef2055c969a1893b453b2023cf4darylm
4923b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def namelink(self, name, *dicts):
4933b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Make a link for an identifier, given name-to-URL mappings."""
4943b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for dict in dicts:
4953b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if name in dict:
4963b553e0ab2146ef2055c969a1893b453b2023cf4darylm                return '<a href="%s">%s</a>' % (dict[name], name)
4973b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return name
4983b553e0ab2146ef2055c969a1893b453b2023cf4darylm
4993b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def classlink(self, object, modname):
5003b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Make a link for a class."""
5013b553e0ab2146ef2055c969a1893b453b2023cf4darylm        name, module = object.__name__, sys.modules.get(object.__module__)
5023b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if hasattr(module, name) and getattr(module, name) is object:
5033b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return '<a href="%s.html#%s">%s</a>' % (
5043b553e0ab2146ef2055c969a1893b453b2023cf4darylm                module.__name__, name, classname(object, modname))
5053b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return classname(object, modname)
5063b553e0ab2146ef2055c969a1893b453b2023cf4darylm
5073b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def modulelink(self, object):
5083b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Make a link for a module."""
5093b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
5103b553e0ab2146ef2055c969a1893b453b2023cf4darylm
5113b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def modpkglink(self, data):
5123b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Make a link for a module or package to display in an index."""
5133b553e0ab2146ef2055c969a1893b453b2023cf4darylm        name, path, ispackage, shadowed = data
5143b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if shadowed:
5153b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return self.grey(name)
5163b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if path:
5173b553e0ab2146ef2055c969a1893b453b2023cf4darylm            url = '%s.%s.html' % (path, name)
5183b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else:
5193b553e0ab2146ef2055c969a1893b453b2023cf4darylm            url = '%s.html' % name
5203b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if ispackage:
5213b553e0ab2146ef2055c969a1893b453b2023cf4darylm            text = '<strong>%s</strong>&nbsp;(package)' % name
5223b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else:
5233b553e0ab2146ef2055c969a1893b453b2023cf4darylm            text = name
5243b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return '<a href="%s">%s</a>' % (url, text)
5253b553e0ab2146ef2055c969a1893b453b2023cf4darylm
5263b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
5273b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Mark up some plain text, given a context of symbols to look for.
5283b553e0ab2146ef2055c969a1893b453b2023cf4darylm        Each context dictionary maps object names to anchor names."""
5293b553e0ab2146ef2055c969a1893b453b2023cf4darylm        escape = escape or self.escape
5303b553e0ab2146ef2055c969a1893b453b2023cf4darylm        results = []
5313b553e0ab2146ef2055c969a1893b453b2023cf4darylm        here = 0
5323b553e0ab2146ef2055c969a1893b453b2023cf4darylm        pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
5333b553e0ab2146ef2055c969a1893b453b2023cf4darylm                                r'RFC[- ]?(\d+)|'
5343b553e0ab2146ef2055c969a1893b453b2023cf4darylm                                r'PEP[- ]?(\d+)|'
5353b553e0ab2146ef2055c969a1893b453b2023cf4darylm                                r'(self\.)?(\w+))')
5363b553e0ab2146ef2055c969a1893b453b2023cf4darylm        while True:
5373b553e0ab2146ef2055c969a1893b453b2023cf4darylm            match = pattern.search(text, here)
5383b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if not match: break
5393b553e0ab2146ef2055c969a1893b453b2023cf4darylm            start, end = match.span()
5403b553e0ab2146ef2055c969a1893b453b2023cf4darylm            results.append(escape(text[here:start]))
5413b553e0ab2146ef2055c969a1893b453b2023cf4darylm
5423b553e0ab2146ef2055c969a1893b453b2023cf4darylm            all, scheme, rfc, pep, selfdot, name = match.groups()
5433b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if scheme:
5443b553e0ab2146ef2055c969a1893b453b2023cf4darylm                url = escape(all).replace('"', '&quot;')
5453b553e0ab2146ef2055c969a1893b453b2023cf4darylm                results.append('<a href="%s">%s</a>' % (url, url))
5463b553e0ab2146ef2055c969a1893b453b2023cf4darylm            elif rfc:
5473b553e0ab2146ef2055c969a1893b453b2023cf4darylm                url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
5483b553e0ab2146ef2055c969a1893b453b2023cf4darylm                results.append('<a href="%s">%s</a>' % (url, escape(all)))
5493b553e0ab2146ef2055c969a1893b453b2023cf4darylm            elif pep:
5503b553e0ab2146ef2055c969a1893b453b2023cf4darylm                url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
5513b553e0ab2146ef2055c969a1893b453b2023cf4darylm                results.append('<a href="%s">%s</a>' % (url, escape(all)))
5523b553e0ab2146ef2055c969a1893b453b2023cf4darylm            elif text[end:end+1] == '(':
5533b553e0ab2146ef2055c969a1893b453b2023cf4darylm                results.append(self.namelink(name, methods, funcs, classes))
5543b553e0ab2146ef2055c969a1893b453b2023cf4darylm            elif selfdot:
5553b553e0ab2146ef2055c969a1893b453b2023cf4darylm                results.append('self.<strong>%s</strong>' % name)
5563b553e0ab2146ef2055c969a1893b453b2023cf4darylm            else:
5573b553e0ab2146ef2055c969a1893b453b2023cf4darylm                results.append(self.namelink(name, classes))
5583b553e0ab2146ef2055c969a1893b453b2023cf4darylm            here = end
5593b553e0ab2146ef2055c969a1893b453b2023cf4darylm        results.append(escape(text[here:]))
5603b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return join(results, '')
5613b553e0ab2146ef2055c969a1893b453b2023cf4darylm
5623b553e0ab2146ef2055c969a1893b453b2023cf4darylm    # ---------------------------------------------- type-specific routines
5633b553e0ab2146ef2055c969a1893b453b2023cf4darylm
5643b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def formattree(self, tree, modname, parent=None):
5653b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Produce HTML for a class tree as given by inspect.getclasstree()."""
5663b553e0ab2146ef2055c969a1893b453b2023cf4darylm        result = ''
5673b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for entry in tree:
5683b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if type(entry) is type(()):
5693b553e0ab2146ef2055c969a1893b453b2023cf4darylm                c, bases = entry
5703b553e0ab2146ef2055c969a1893b453b2023cf4darylm                result = result + '<dt><font face="helvetica, arial">'
5713b553e0ab2146ef2055c969a1893b453b2023cf4darylm                result = result + self.classlink(c, modname)
5723b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if bases and bases != (parent,):
5733b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    parents = []
5743b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    for base in bases:
5753b553e0ab2146ef2055c969a1893b453b2023cf4darylm                        parents.append(self.classlink(base, modname))
5763b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    result = result + '(' + join(parents, ', ') + ')'
5773b553e0ab2146ef2055c969a1893b453b2023cf4darylm                result = result + '\n</font></dt>'
5783b553e0ab2146ef2055c969a1893b453b2023cf4darylm            elif type(entry) is type([]):
5793b553e0ab2146ef2055c969a1893b453b2023cf4darylm                result = result + '<dd>\n%s</dd>\n' % self.formattree(
5803b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    entry, modname, c)
5813b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return '<dl>\n%s</dl>\n' % result
5823b553e0ab2146ef2055c969a1893b453b2023cf4darylm
5833b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def docmodule(self, object, name=None, mod=None, *ignored):
5843b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Produce HTML documentation for a module object."""
5853b553e0ab2146ef2055c969a1893b453b2023cf4darylm        name = object.__name__ # ignore the passed-in name
5863b553e0ab2146ef2055c969a1893b453b2023cf4darylm        try:
5873b553e0ab2146ef2055c969a1893b453b2023cf4darylm            all = object.__all__
5883b553e0ab2146ef2055c969a1893b453b2023cf4darylm        except AttributeError:
5893b553e0ab2146ef2055c969a1893b453b2023cf4darylm            all = None
5903b553e0ab2146ef2055c969a1893b453b2023cf4darylm        parts = split(name, '.')
5913b553e0ab2146ef2055c969a1893b453b2023cf4darylm        links = []
5923b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for i in range(len(parts)-1):
5933b553e0ab2146ef2055c969a1893b453b2023cf4darylm            links.append(
5943b553e0ab2146ef2055c969a1893b453b2023cf4darylm                '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
5953b553e0ab2146ef2055c969a1893b453b2023cf4darylm                (join(parts[:i+1], '.'), parts[i]))
5963b553e0ab2146ef2055c969a1893b453b2023cf4darylm        linkedname = join(links + parts[-1:], '.')
5973b553e0ab2146ef2055c969a1893b453b2023cf4darylm        head = '<big><big><strong>%s</strong></big></big>' % linkedname
5983b553e0ab2146ef2055c969a1893b453b2023cf4darylm        try:
5993b553e0ab2146ef2055c969a1893b453b2023cf4darylm            path = inspect.getabsfile(object)
6003b553e0ab2146ef2055c969a1893b453b2023cf4darylm            url = path
6013b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if sys.platform == 'win32':
6023b553e0ab2146ef2055c969a1893b453b2023cf4darylm                import nturl2path
6033b553e0ab2146ef2055c969a1893b453b2023cf4darylm                url = nturl2path.pathname2url(path)
6043b553e0ab2146ef2055c969a1893b453b2023cf4darylm            filelink = '<a href="file:%s">%s</a>' % (url, path)
6053b553e0ab2146ef2055c969a1893b453b2023cf4darylm        except TypeError:
6063b553e0ab2146ef2055c969a1893b453b2023cf4darylm            filelink = '(built-in)'
6073b553e0ab2146ef2055c969a1893b453b2023cf4darylm        info = []
6083b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if hasattr(object, '__version__'):
6093b553e0ab2146ef2055c969a1893b453b2023cf4darylm            version = str(object.__version__)
6103b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
6113b553e0ab2146ef2055c969a1893b453b2023cf4darylm                version = strip(version[11:-1])
6123b553e0ab2146ef2055c969a1893b453b2023cf4darylm            info.append('version %s' % self.escape(version))
6133b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if hasattr(object, '__date__'):
6143b553e0ab2146ef2055c969a1893b453b2023cf4darylm            info.append(self.escape(str(object.__date__)))
6153b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if info:
6163b553e0ab2146ef2055c969a1893b453b2023cf4darylm            head = head + ' (%s)' % join(info, ', ')
6173b553e0ab2146ef2055c969a1893b453b2023cf4darylm        docloc = self.getdocloc(object)
6183b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if docloc is not None:
6193b553e0ab2146ef2055c969a1893b453b2023cf4darylm            docloc = '<br><a href="%(docloc)s">Module Docs</a>' % locals()
6203b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else:
6213b553e0ab2146ef2055c969a1893b453b2023cf4darylm            docloc = ''
6223b553e0ab2146ef2055c969a1893b453b2023cf4darylm        result = self.heading(
6233b553e0ab2146ef2055c969a1893b453b2023cf4darylm            head, '#ffffff', '#7799ee',
6243b553e0ab2146ef2055c969a1893b453b2023cf4darylm            '<a href=".">index</a><br>' + filelink + docloc)
6253b553e0ab2146ef2055c969a1893b453b2023cf4darylm
6263b553e0ab2146ef2055c969a1893b453b2023cf4darylm        modules = inspect.getmembers(object, inspect.ismodule)
6273b553e0ab2146ef2055c969a1893b453b2023cf4darylm
6283b553e0ab2146ef2055c969a1893b453b2023cf4darylm        classes, cdict = [], {}
6293b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for key, value in inspect.getmembers(object, inspect.isclass):
6303b553e0ab2146ef2055c969a1893b453b2023cf4darylm            # if __all__ exists, believe it.  Otherwise use old heuristic.
6313b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if (all is not None or
6323b553e0ab2146ef2055c969a1893b453b2023cf4darylm                (inspect.getmodule(value) or object) is object):
6333b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if visiblename(key, all, object):
6343b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    classes.append((key, value))
6353b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    cdict[key] = cdict[value] = '#' + key
6363b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for key, value in classes:
6373b553e0ab2146ef2055c969a1893b453b2023cf4darylm            for base in value.__bases__:
6383b553e0ab2146ef2055c969a1893b453b2023cf4darylm                key, modname = base.__name__, base.__module__
6393b553e0ab2146ef2055c969a1893b453b2023cf4darylm                module = sys.modules.get(modname)
6403b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if modname != name and module and hasattr(module, key):
6413b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    if getattr(module, key) is base:
6423b553e0ab2146ef2055c969a1893b453b2023cf4darylm                        if not key in cdict:
6433b553e0ab2146ef2055c969a1893b453b2023cf4darylm                            cdict[key] = cdict[base] = modname + '.html#' + key
6443b553e0ab2146ef2055c969a1893b453b2023cf4darylm        funcs, fdict = [], {}
6453b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for key, value in inspect.getmembers(object, inspect.isroutine):
6463b553e0ab2146ef2055c969a1893b453b2023cf4darylm            # if __all__ exists, believe it.  Otherwise use old heuristic.
6473b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if (all is not None or
6483b553e0ab2146ef2055c969a1893b453b2023cf4darylm                inspect.isbuiltin(value) or inspect.getmodule(value) is object):
6493b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if visiblename(key, all, object):
6503b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    funcs.append((key, value))
6513b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    fdict[key] = '#-' + key
6523b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    if inspect.isfunction(value): fdict[value] = fdict[key]
6533b553e0ab2146ef2055c969a1893b453b2023cf4darylm        data = []
6543b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for key, value in inspect.getmembers(object, isdata):
6553b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if visiblename(key, all, object):
6563b553e0ab2146ef2055c969a1893b453b2023cf4darylm                data.append((key, value))
6573b553e0ab2146ef2055c969a1893b453b2023cf4darylm
6583b553e0ab2146ef2055c969a1893b453b2023cf4darylm        doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
6593b553e0ab2146ef2055c969a1893b453b2023cf4darylm        doc = doc and '<tt>%s</tt>' % doc
6603b553e0ab2146ef2055c969a1893b453b2023cf4darylm        result = result + '<p>%s</p>\n' % doc
6613b553e0ab2146ef2055c969a1893b453b2023cf4darylm
6623b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if hasattr(object, '__path__'):
6633b553e0ab2146ef2055c969a1893b453b2023cf4darylm            modpkgs = []
6643b553e0ab2146ef2055c969a1893b453b2023cf4darylm            for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
6653b553e0ab2146ef2055c969a1893b453b2023cf4darylm                modpkgs.append((modname, name, ispkg, 0))
6663b553e0ab2146ef2055c969a1893b453b2023cf4darylm            modpkgs.sort()
6673b553e0ab2146ef2055c969a1893b453b2023cf4darylm            contents = self.multicolumn(modpkgs, self.modpkglink)
6683b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = result + self.bigsection(
6693b553e0ab2146ef2055c969a1893b453b2023cf4darylm                'Package Contents', '#ffffff', '#aa55cc', contents)
6703b553e0ab2146ef2055c969a1893b453b2023cf4darylm        elif modules:
6713b553e0ab2146ef2055c969a1893b453b2023cf4darylm            contents = self.multicolumn(
6723b553e0ab2146ef2055c969a1893b453b2023cf4darylm                modules, lambda key_value, s=self: s.modulelink(key_value[1]))
6733b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = result + self.bigsection(
6743b553e0ab2146ef2055c969a1893b453b2023cf4darylm                'Modules', '#ffffff', '#aa55cc', contents)
6753b553e0ab2146ef2055c969a1893b453b2023cf4darylm
6763b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if classes:
6773b553e0ab2146ef2055c969a1893b453b2023cf4darylm            classlist = map(lambda key_value: key_value[1], classes)
6783b553e0ab2146ef2055c969a1893b453b2023cf4darylm            contents = [
6793b553e0ab2146ef2055c969a1893b453b2023cf4darylm                self.formattree(inspect.getclasstree(classlist, 1), name)]
6803b553e0ab2146ef2055c969a1893b453b2023cf4darylm            for key, value in classes:
6813b553e0ab2146ef2055c969a1893b453b2023cf4darylm                contents.append(self.document(value, key, name, fdict, cdict))
6823b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = result + self.bigsection(
6833b553e0ab2146ef2055c969a1893b453b2023cf4darylm                'Classes', '#ffffff', '#ee77aa', join(contents))
6843b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if funcs:
6853b553e0ab2146ef2055c969a1893b453b2023cf4darylm            contents = []
6863b553e0ab2146ef2055c969a1893b453b2023cf4darylm            for key, value in funcs:
6873b553e0ab2146ef2055c969a1893b453b2023cf4darylm                contents.append(self.document(value, key, name, fdict, cdict))
6883b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = result + self.bigsection(
6893b553e0ab2146ef2055c969a1893b453b2023cf4darylm                'Functions', '#ffffff', '#eeaa77', join(contents))
6903b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if data:
6913b553e0ab2146ef2055c969a1893b453b2023cf4darylm            contents = []
6923b553e0ab2146ef2055c969a1893b453b2023cf4darylm            for key, value in data:
6933b553e0ab2146ef2055c969a1893b453b2023cf4darylm                contents.append(self.document(value, key))
6943b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = result + self.bigsection(
6953b553e0ab2146ef2055c969a1893b453b2023cf4darylm                'Data', '#ffffff', '#55aa55', join(contents, '<br>\n'))
6963b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if hasattr(object, '__author__'):
6973b553e0ab2146ef2055c969a1893b453b2023cf4darylm            contents = self.markup(str(object.__author__), self.preformat)
6983b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = result + self.bigsection(
6993b553e0ab2146ef2055c969a1893b453b2023cf4darylm                'Author', '#ffffff', '#7799ee', contents)
7003b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if hasattr(object, '__credits__'):
7013b553e0ab2146ef2055c969a1893b453b2023cf4darylm            contents = self.markup(str(object.__credits__), self.preformat)
7023b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = result + self.bigsection(
7033b553e0ab2146ef2055c969a1893b453b2023cf4darylm                'Credits', '#ffffff', '#7799ee', contents)
7043b553e0ab2146ef2055c969a1893b453b2023cf4darylm
7053b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return result
7063b553e0ab2146ef2055c969a1893b453b2023cf4darylm
7073b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def docclass(self, object, name=None, mod=None, funcs={}, classes={},
7083b553e0ab2146ef2055c969a1893b453b2023cf4darylm                 *ignored):
7093b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Produce HTML documentation for a class object."""
7103b553e0ab2146ef2055c969a1893b453b2023cf4darylm        realname = object.__name__
7113b553e0ab2146ef2055c969a1893b453b2023cf4darylm        name = name or realname
7123b553e0ab2146ef2055c969a1893b453b2023cf4darylm        bases = object.__bases__
7133b553e0ab2146ef2055c969a1893b453b2023cf4darylm
7143b553e0ab2146ef2055c969a1893b453b2023cf4darylm        contents = []
7153b553e0ab2146ef2055c969a1893b453b2023cf4darylm        push = contents.append
7163b553e0ab2146ef2055c969a1893b453b2023cf4darylm
7173b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # Cute little class to pump out a horizontal rule between sections.
7183b553e0ab2146ef2055c969a1893b453b2023cf4darylm        class HorizontalRule:
7193b553e0ab2146ef2055c969a1893b453b2023cf4darylm            def __init__(self):
7203b553e0ab2146ef2055c969a1893b453b2023cf4darylm                self.needone = 0
7213b553e0ab2146ef2055c969a1893b453b2023cf4darylm            def maybe(self):
7223b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if self.needone:
7233b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    push('<hr>\n')
7243b553e0ab2146ef2055c969a1893b453b2023cf4darylm                self.needone = 1
7253b553e0ab2146ef2055c969a1893b453b2023cf4darylm        hr = HorizontalRule()
7263b553e0ab2146ef2055c969a1893b453b2023cf4darylm
7273b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # List the mro, if non-trivial.
7283b553e0ab2146ef2055c969a1893b453b2023cf4darylm        mro = deque(inspect.getmro(object))
7293b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if len(mro) > 2:
7303b553e0ab2146ef2055c969a1893b453b2023cf4darylm            hr.maybe()
7313b553e0ab2146ef2055c969a1893b453b2023cf4darylm            push('<dl><dt>Method resolution order:</dt>\n')
7323b553e0ab2146ef2055c969a1893b453b2023cf4darylm            for base in mro:
7333b553e0ab2146ef2055c969a1893b453b2023cf4darylm                push('<dd>%s</dd>\n' % self.classlink(base,
7343b553e0ab2146ef2055c969a1893b453b2023cf4darylm                                                      object.__module__))
7353b553e0ab2146ef2055c969a1893b453b2023cf4darylm            push('</dl>\n')
7363b553e0ab2146ef2055c969a1893b453b2023cf4darylm
7373b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def spill(msg, attrs, predicate):
7383b553e0ab2146ef2055c969a1893b453b2023cf4darylm            ok, attrs = _split_list(attrs, predicate)
7393b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if ok:
7403b553e0ab2146ef2055c969a1893b453b2023cf4darylm                hr.maybe()
7413b553e0ab2146ef2055c969a1893b453b2023cf4darylm                push(msg)
7423b553e0ab2146ef2055c969a1893b453b2023cf4darylm                for name, kind, homecls, value in ok:
7433b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    push(self.document(getattr(object, name), name, mod,
7443b553e0ab2146ef2055c969a1893b453b2023cf4darylm                                       funcs, classes, mdict, object))
7453b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    push('\n')
7463b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return attrs
7473b553e0ab2146ef2055c969a1893b453b2023cf4darylm
7483b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def spilldescriptors(msg, attrs, predicate):
7493b553e0ab2146ef2055c969a1893b453b2023cf4darylm            ok, attrs = _split_list(attrs, predicate)
7503b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if ok:
7513b553e0ab2146ef2055c969a1893b453b2023cf4darylm                hr.maybe()
7523b553e0ab2146ef2055c969a1893b453b2023cf4darylm                push(msg)
7533b553e0ab2146ef2055c969a1893b453b2023cf4darylm                for name, kind, homecls, value in ok:
7543b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    push(self._docdescriptor(name, value, mod))
7553b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return attrs
7563b553e0ab2146ef2055c969a1893b453b2023cf4darylm
7573b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def spilldata(msg, attrs, predicate):
7583b553e0ab2146ef2055c969a1893b453b2023cf4darylm            ok, attrs = _split_list(attrs, predicate)
7593b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if ok:
7603b553e0ab2146ef2055c969a1893b453b2023cf4darylm                hr.maybe()
7613b553e0ab2146ef2055c969a1893b453b2023cf4darylm                push(msg)
7623b553e0ab2146ef2055c969a1893b453b2023cf4darylm                for name, kind, homecls, value in ok:
7633b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    base = self.docother(getattr(object, name), name, mod)
7643b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    if (hasattr(value, '__call__') or
7653b553e0ab2146ef2055c969a1893b453b2023cf4darylm                            inspect.isdatadescriptor(value)):
7663b553e0ab2146ef2055c969a1893b453b2023cf4darylm                        doc = getattr(value, "__doc__", None)
7673b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    else:
7683b553e0ab2146ef2055c969a1893b453b2023cf4darylm                        doc = None
7693b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    if doc is None:
7703b553e0ab2146ef2055c969a1893b453b2023cf4darylm                        push('<dl><dt>%s</dl>\n' % base)
7713b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    else:
7723b553e0ab2146ef2055c969a1893b453b2023cf4darylm                        doc = self.markup(getdoc(value), self.preformat,
7733b553e0ab2146ef2055c969a1893b453b2023cf4darylm                                          funcs, classes, mdict)
7743b553e0ab2146ef2055c969a1893b453b2023cf4darylm                        doc = '<dd><tt>%s</tt>' % doc
7753b553e0ab2146ef2055c969a1893b453b2023cf4darylm                        push('<dl><dt>%s%s</dl>\n' % (base, doc))
7763b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    push('\n')
7773b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return attrs
7783b553e0ab2146ef2055c969a1893b453b2023cf4darylm
7793b553e0ab2146ef2055c969a1893b453b2023cf4darylm        attrs = filter(lambda data: visiblename(data[0], obj=object),
7803b553e0ab2146ef2055c969a1893b453b2023cf4darylm                       classify_class_attrs(object))
7813b553e0ab2146ef2055c969a1893b453b2023cf4darylm        mdict = {}
7823b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for key, kind, homecls, value in attrs:
7833b553e0ab2146ef2055c969a1893b453b2023cf4darylm            mdict[key] = anchor = '#' + name + '-' + key
7843b553e0ab2146ef2055c969a1893b453b2023cf4darylm            value = getattr(object, key)
7853b553e0ab2146ef2055c969a1893b453b2023cf4darylm            try:
7863b553e0ab2146ef2055c969a1893b453b2023cf4darylm                # The value may not be hashable (e.g., a data attr with
7873b553e0ab2146ef2055c969a1893b453b2023cf4darylm                # a dict or list value).
7883b553e0ab2146ef2055c969a1893b453b2023cf4darylm                mdict[value] = anchor
7893b553e0ab2146ef2055c969a1893b453b2023cf4darylm            except TypeError:
7903b553e0ab2146ef2055c969a1893b453b2023cf4darylm                pass
7913b553e0ab2146ef2055c969a1893b453b2023cf4darylm
7923b553e0ab2146ef2055c969a1893b453b2023cf4darylm        while attrs:
7933b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if mro:
7943b553e0ab2146ef2055c969a1893b453b2023cf4darylm                thisclass = mro.popleft()
7953b553e0ab2146ef2055c969a1893b453b2023cf4darylm            else:
7963b553e0ab2146ef2055c969a1893b453b2023cf4darylm                thisclass = attrs[0][2]
7973b553e0ab2146ef2055c969a1893b453b2023cf4darylm            attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
7983b553e0ab2146ef2055c969a1893b453b2023cf4darylm
7993b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if thisclass is __builtin__.object:
8003b553e0ab2146ef2055c969a1893b453b2023cf4darylm                attrs = inherited
8013b553e0ab2146ef2055c969a1893b453b2023cf4darylm                continue
8023b553e0ab2146ef2055c969a1893b453b2023cf4darylm            elif thisclass is object:
8033b553e0ab2146ef2055c969a1893b453b2023cf4darylm                tag = 'defined here'
8043b553e0ab2146ef2055c969a1893b453b2023cf4darylm            else:
8053b553e0ab2146ef2055c969a1893b453b2023cf4darylm                tag = 'inherited from %s' % self.classlink(thisclass,
8063b553e0ab2146ef2055c969a1893b453b2023cf4darylm                                                           object.__module__)
8073b553e0ab2146ef2055c969a1893b453b2023cf4darylm            tag += ':<br>\n'
8083b553e0ab2146ef2055c969a1893b453b2023cf4darylm
8093b553e0ab2146ef2055c969a1893b453b2023cf4darylm            # Sort attrs by name.
8103b553e0ab2146ef2055c969a1893b453b2023cf4darylm            try:
8113b553e0ab2146ef2055c969a1893b453b2023cf4darylm                attrs.sort(key=lambda t: t[0])
8123b553e0ab2146ef2055c969a1893b453b2023cf4darylm            except TypeError:
8133b553e0ab2146ef2055c969a1893b453b2023cf4darylm                attrs.sort(lambda t1, t2: cmp(t1[0], t2[0]))    # 2.3 compat
8143b553e0ab2146ef2055c969a1893b453b2023cf4darylm
8153b553e0ab2146ef2055c969a1893b453b2023cf4darylm            # Pump out the attrs, segregated by kind.
8163b553e0ab2146ef2055c969a1893b453b2023cf4darylm            attrs = spill('Methods %s' % tag, attrs,
8173b553e0ab2146ef2055c969a1893b453b2023cf4darylm                          lambda t: t[1] == 'method')
8183b553e0ab2146ef2055c969a1893b453b2023cf4darylm            attrs = spill('Class methods %s' % tag, attrs,
8193b553e0ab2146ef2055c969a1893b453b2023cf4darylm                          lambda t: t[1] == 'class method')
8203b553e0ab2146ef2055c969a1893b453b2023cf4darylm            attrs = spill('Static methods %s' % tag, attrs,
8213b553e0ab2146ef2055c969a1893b453b2023cf4darylm                          lambda t: t[1] == 'static method')
8223b553e0ab2146ef2055c969a1893b453b2023cf4darylm            attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
8233b553e0ab2146ef2055c969a1893b453b2023cf4darylm                                     lambda t: t[1] == 'data descriptor')
8243b553e0ab2146ef2055c969a1893b453b2023cf4darylm            attrs = spilldata('Data and other attributes %s' % tag, attrs,
8253b553e0ab2146ef2055c969a1893b453b2023cf4darylm                              lambda t: t[1] == 'data')
8263b553e0ab2146ef2055c969a1893b453b2023cf4darylm            assert attrs == []
8273b553e0ab2146ef2055c969a1893b453b2023cf4darylm            attrs = inherited
8283b553e0ab2146ef2055c969a1893b453b2023cf4darylm
8293b553e0ab2146ef2055c969a1893b453b2023cf4darylm        contents = ''.join(contents)
8303b553e0ab2146ef2055c969a1893b453b2023cf4darylm
8313b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if name == realname:
8323b553e0ab2146ef2055c969a1893b453b2023cf4darylm            title = '<a name="%s">class <strong>%s</strong></a>' % (
8333b553e0ab2146ef2055c969a1893b453b2023cf4darylm                name, realname)
8343b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else:
8353b553e0ab2146ef2055c969a1893b453b2023cf4darylm            title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
8363b553e0ab2146ef2055c969a1893b453b2023cf4darylm                name, name, realname)
8373b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if bases:
8383b553e0ab2146ef2055c969a1893b453b2023cf4darylm            parents = []
8393b553e0ab2146ef2055c969a1893b453b2023cf4darylm            for base in bases:
8403b553e0ab2146ef2055c969a1893b453b2023cf4darylm                parents.append(self.classlink(base, object.__module__))
8413b553e0ab2146ef2055c969a1893b453b2023cf4darylm            title = title + '(%s)' % join(parents, ', ')
8423b553e0ab2146ef2055c969a1893b453b2023cf4darylm        doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
8433b553e0ab2146ef2055c969a1893b453b2023cf4darylm        doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
8443b553e0ab2146ef2055c969a1893b453b2023cf4darylm
8453b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
8463b553e0ab2146ef2055c969a1893b453b2023cf4darylm
8473b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def formatvalue(self, object):
8483b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Format an argument default value as text."""
8493b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return self.grey('=' + self.repr(object))
8503b553e0ab2146ef2055c969a1893b453b2023cf4darylm
8513b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def docroutine(self, object, name=None, mod=None,
8523b553e0ab2146ef2055c969a1893b453b2023cf4darylm                   funcs={}, classes={}, methods={}, cl=None):
8533b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Produce HTML documentation for a function or method object."""
8543b553e0ab2146ef2055c969a1893b453b2023cf4darylm        realname = object.__name__
8553b553e0ab2146ef2055c969a1893b453b2023cf4darylm        name = name or realname
8563b553e0ab2146ef2055c969a1893b453b2023cf4darylm        anchor = (cl and cl.__name__ or '') + '-' + name
8573b553e0ab2146ef2055c969a1893b453b2023cf4darylm        note = ''
8583b553e0ab2146ef2055c969a1893b453b2023cf4darylm        skipdocs = 0
8593b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if inspect.ismethod(object):
8603b553e0ab2146ef2055c969a1893b453b2023cf4darylm            imclass = object.im_class
8613b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if cl:
8623b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if imclass is not cl:
8633b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    note = ' from ' + self.classlink(imclass, mod)
8643b553e0ab2146ef2055c969a1893b453b2023cf4darylm            else:
8653b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if object.im_self is not None:
8663b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    note = ' method of %s instance' % self.classlink(
8673b553e0ab2146ef2055c969a1893b453b2023cf4darylm                        object.im_self.__class__, mod)
8683b553e0ab2146ef2055c969a1893b453b2023cf4darylm                else:
8693b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    note = ' unbound %s method' % self.classlink(imclass,mod)
8703b553e0ab2146ef2055c969a1893b453b2023cf4darylm            object = object.im_func
8713b553e0ab2146ef2055c969a1893b453b2023cf4darylm
8723b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if name == realname:
8733b553e0ab2146ef2055c969a1893b453b2023cf4darylm            title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
8743b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else:
8753b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if (cl and realname in cl.__dict__ and
8763b553e0ab2146ef2055c969a1893b453b2023cf4darylm                cl.__dict__[realname] is object):
8773b553e0ab2146ef2055c969a1893b453b2023cf4darylm                reallink = '<a href="#%s">%s</a>' % (
8783b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    cl.__name__ + '-' + realname, realname)
8793b553e0ab2146ef2055c969a1893b453b2023cf4darylm                skipdocs = 1
8803b553e0ab2146ef2055c969a1893b453b2023cf4darylm            else:
8813b553e0ab2146ef2055c969a1893b453b2023cf4darylm                reallink = realname
8823b553e0ab2146ef2055c969a1893b453b2023cf4darylm            title = '<a name="%s"><strong>%s</strong></a> = %s' % (
8833b553e0ab2146ef2055c969a1893b453b2023cf4darylm                anchor, name, reallink)
8843b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if inspect.isfunction(object):
8853b553e0ab2146ef2055c969a1893b453b2023cf4darylm            args, varargs, varkw, defaults = inspect.getargspec(object)
8863b553e0ab2146ef2055c969a1893b453b2023cf4darylm            argspec = inspect.formatargspec(
8873b553e0ab2146ef2055c969a1893b453b2023cf4darylm                args, varargs, varkw, defaults, formatvalue=self.formatvalue)
8883b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if realname == '<lambda>':
8893b553e0ab2146ef2055c969a1893b453b2023cf4darylm                title = '<strong>%s</strong> <em>lambda</em> ' % name
8903b553e0ab2146ef2055c969a1893b453b2023cf4darylm                argspec = argspec[1:-1] # remove parentheses
8913b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else:
8923b553e0ab2146ef2055c969a1893b453b2023cf4darylm            argspec = '(...)'
8933b553e0ab2146ef2055c969a1893b453b2023cf4darylm
8943b553e0ab2146ef2055c969a1893b453b2023cf4darylm        decl = title + argspec + (note and self.grey(
8953b553e0ab2146ef2055c969a1893b453b2023cf4darylm               '<font face="helvetica, arial">%s</font>' % note))
8963b553e0ab2146ef2055c969a1893b453b2023cf4darylm
8973b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if skipdocs:
8983b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return '<dl><dt>%s</dt></dl>\n' % decl
8993b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else:
9003b553e0ab2146ef2055c969a1893b453b2023cf4darylm            doc = self.markup(
9013b553e0ab2146ef2055c969a1893b453b2023cf4darylm                getdoc(object), self.preformat, funcs, classes, methods)
9023b553e0ab2146ef2055c969a1893b453b2023cf4darylm            doc = doc and '<dd><tt>%s</tt></dd>' % doc
9033b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
9043b553e0ab2146ef2055c969a1893b453b2023cf4darylm
9053b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def _docdescriptor(self, name, value, mod):
9063b553e0ab2146ef2055c969a1893b453b2023cf4darylm        results = []
9073b553e0ab2146ef2055c969a1893b453b2023cf4darylm        push = results.append
9083b553e0ab2146ef2055c969a1893b453b2023cf4darylm
9093b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if name:
9103b553e0ab2146ef2055c969a1893b453b2023cf4darylm            push('<dl><dt><strong>%s</strong></dt>\n' % name)
9113b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if value.__doc__ is not None:
9123b553e0ab2146ef2055c969a1893b453b2023cf4darylm            doc = self.markup(getdoc(value), self.preformat)
9133b553e0ab2146ef2055c969a1893b453b2023cf4darylm            push('<dd><tt>%s</tt></dd>\n' % doc)
9143b553e0ab2146ef2055c969a1893b453b2023cf4darylm        push('</dl>\n')
9153b553e0ab2146ef2055c969a1893b453b2023cf4darylm
9163b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return ''.join(results)
9173b553e0ab2146ef2055c969a1893b453b2023cf4darylm
9183b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def docproperty(self, object, name=None, mod=None, cl=None):
9193b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Produce html documentation for a property."""
9203b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return self._docdescriptor(name, object, mod)
9213b553e0ab2146ef2055c969a1893b453b2023cf4darylm
9223b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def docother(self, object, name=None, mod=None, *ignored):
9233b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Produce HTML documentation for a data object."""
9243b553e0ab2146ef2055c969a1893b453b2023cf4darylm        lhs = name and '<strong>%s</strong> = ' % name or ''
9253b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return lhs + self.repr(object)
9263b553e0ab2146ef2055c969a1893b453b2023cf4darylm
9273b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def docdata(self, object, name=None, mod=None, cl=None):
9283b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Produce html documentation for a data descriptor."""
9293b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return self._docdescriptor(name, object, mod)
9303b553e0ab2146ef2055c969a1893b453b2023cf4darylm
9313b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def index(self, dir, shadowed=None):
9323b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Generate an HTML index for a directory of modules."""
9333b553e0ab2146ef2055c969a1893b453b2023cf4darylm        modpkgs = []
9343b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if shadowed is None: shadowed = {}
9353b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for importer, name, ispkg in pkgutil.iter_modules([dir]):
9363b553e0ab2146ef2055c969a1893b453b2023cf4darylm            modpkgs.append((name, '', ispkg, name in shadowed))
9373b553e0ab2146ef2055c969a1893b453b2023cf4darylm            shadowed[name] = 1
9383b553e0ab2146ef2055c969a1893b453b2023cf4darylm
9393b553e0ab2146ef2055c969a1893b453b2023cf4darylm        modpkgs.sort()
9403b553e0ab2146ef2055c969a1893b453b2023cf4darylm        contents = self.multicolumn(modpkgs, self.modpkglink)
9413b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
9423b553e0ab2146ef2055c969a1893b453b2023cf4darylm
9433b553e0ab2146ef2055c969a1893b453b2023cf4darylm# -------------------------------------------- text documentation generator
9443b553e0ab2146ef2055c969a1893b453b2023cf4darylm
9453b553e0ab2146ef2055c969a1893b453b2023cf4darylmclass TextRepr(Repr):
9463b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Class for safely making a text representation of a Python object."""
9473b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def __init__(self):
9483b553e0ab2146ef2055c969a1893b453b2023cf4darylm        Repr.__init__(self)
9493b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.maxlist = self.maxtuple = 20
9503b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.maxdict = 10
9513b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.maxstring = self.maxother = 100
9523b553e0ab2146ef2055c969a1893b453b2023cf4darylm
9533b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def repr1(self, x, level):
9543b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if hasattr(type(x), '__name__'):
9553b553e0ab2146ef2055c969a1893b453b2023cf4darylm            methodname = 'repr_' + join(split(type(x).__name__), '_')
9563b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if hasattr(self, methodname):
9573b553e0ab2146ef2055c969a1893b453b2023cf4darylm                return getattr(self, methodname)(x, level)
9583b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return cram(stripid(repr(x)), self.maxother)
9593b553e0ab2146ef2055c969a1893b453b2023cf4darylm
9603b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def repr_string(self, x, level):
9613b553e0ab2146ef2055c969a1893b453b2023cf4darylm        test = cram(x, self.maxstring)
9623b553e0ab2146ef2055c969a1893b453b2023cf4darylm        testrepr = repr(test)
9633b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
9643b553e0ab2146ef2055c969a1893b453b2023cf4darylm            # Backslashes are only literal in the string and are never
9653b553e0ab2146ef2055c969a1893b453b2023cf4darylm            # needed to make any special characters, so show a raw string.
9663b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return 'r' + testrepr[0] + test + testrepr[0]
9673b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return testrepr
9683b553e0ab2146ef2055c969a1893b453b2023cf4darylm
9693b553e0ab2146ef2055c969a1893b453b2023cf4darylm    repr_str = repr_string
9703b553e0ab2146ef2055c969a1893b453b2023cf4darylm
9713b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def repr_instance(self, x, level):
9723b553e0ab2146ef2055c969a1893b453b2023cf4darylm        try:
9733b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return cram(stripid(repr(x)), self.maxstring)
9743b553e0ab2146ef2055c969a1893b453b2023cf4darylm        except:
9753b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return '<%s instance>' % x.__class__.__name__
9763b553e0ab2146ef2055c969a1893b453b2023cf4darylm
9773b553e0ab2146ef2055c969a1893b453b2023cf4darylmclass TextDoc(Doc):
9783b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Formatter class for text documentation."""
9793b553e0ab2146ef2055c969a1893b453b2023cf4darylm
9803b553e0ab2146ef2055c969a1893b453b2023cf4darylm    # ------------------------------------------- text formatting utilities
9813b553e0ab2146ef2055c969a1893b453b2023cf4darylm
9823b553e0ab2146ef2055c969a1893b453b2023cf4darylm    _repr_instance = TextRepr()
9833b553e0ab2146ef2055c969a1893b453b2023cf4darylm    repr = _repr_instance.repr
9843b553e0ab2146ef2055c969a1893b453b2023cf4darylm
9853b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def bold(self, text):
9863b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Format a string in bold by overstriking."""
9873b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return join(map(lambda ch: ch + '\b' + ch, text), '')
9883b553e0ab2146ef2055c969a1893b453b2023cf4darylm
9893b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def indent(self, text, prefix='    '):
9903b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Indent text by prepending a given prefix to each line."""
9913b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if not text: return ''
9923b553e0ab2146ef2055c969a1893b453b2023cf4darylm        lines = split(text, '\n')
9933b553e0ab2146ef2055c969a1893b453b2023cf4darylm        lines = map(lambda line, prefix=prefix: prefix + line, lines)
9943b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if lines: lines[-1] = rstrip(lines[-1])
9953b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return join(lines, '\n')
9963b553e0ab2146ef2055c969a1893b453b2023cf4darylm
9973b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def section(self, title, contents):
9983b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Format a section with a given heading."""
9993b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return self.bold(title) + '\n' + rstrip(self.indent(contents)) + '\n\n'
10003b553e0ab2146ef2055c969a1893b453b2023cf4darylm
10013b553e0ab2146ef2055c969a1893b453b2023cf4darylm    # ---------------------------------------------- type-specific routines
10023b553e0ab2146ef2055c969a1893b453b2023cf4darylm
10033b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def formattree(self, tree, modname, parent=None, prefix=''):
10043b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Render in text a class tree as returned by inspect.getclasstree()."""
10053b553e0ab2146ef2055c969a1893b453b2023cf4darylm        result = ''
10063b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for entry in tree:
10073b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if type(entry) is type(()):
10083b553e0ab2146ef2055c969a1893b453b2023cf4darylm                c, bases = entry
10093b553e0ab2146ef2055c969a1893b453b2023cf4darylm                result = result + prefix + classname(c, modname)
10103b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if bases and bases != (parent,):
10113b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    parents = map(lambda c, m=modname: classname(c, m), bases)
10123b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    result = result + '(%s)' % join(parents, ', ')
10133b553e0ab2146ef2055c969a1893b453b2023cf4darylm                result = result + '\n'
10143b553e0ab2146ef2055c969a1893b453b2023cf4darylm            elif type(entry) is type([]):
10153b553e0ab2146ef2055c969a1893b453b2023cf4darylm                result = result + self.formattree(
10163b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    entry, modname, c, prefix + '    ')
10173b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return result
10183b553e0ab2146ef2055c969a1893b453b2023cf4darylm
10193b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def docmodule(self, object, name=None, mod=None):
10203b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Produce text documentation for a given module object."""
10213b553e0ab2146ef2055c969a1893b453b2023cf4darylm        name = object.__name__ # ignore the passed-in name
10223b553e0ab2146ef2055c969a1893b453b2023cf4darylm        synop, desc = splitdoc(getdoc(object))
10233b553e0ab2146ef2055c969a1893b453b2023cf4darylm        result = self.section('NAME', name + (synop and ' - ' + synop))
10243b553e0ab2146ef2055c969a1893b453b2023cf4darylm
10253b553e0ab2146ef2055c969a1893b453b2023cf4darylm        try:
10263b553e0ab2146ef2055c969a1893b453b2023cf4darylm            all = object.__all__
10273b553e0ab2146ef2055c969a1893b453b2023cf4darylm        except AttributeError:
10283b553e0ab2146ef2055c969a1893b453b2023cf4darylm            all = None
10293b553e0ab2146ef2055c969a1893b453b2023cf4darylm
10303b553e0ab2146ef2055c969a1893b453b2023cf4darylm        try:
10313b553e0ab2146ef2055c969a1893b453b2023cf4darylm            file = inspect.getabsfile(object)
10323b553e0ab2146ef2055c969a1893b453b2023cf4darylm        except TypeError:
10333b553e0ab2146ef2055c969a1893b453b2023cf4darylm            file = '(built-in)'
10343b553e0ab2146ef2055c969a1893b453b2023cf4darylm        result = result + self.section('FILE', file)
10353b553e0ab2146ef2055c969a1893b453b2023cf4darylm
10363b553e0ab2146ef2055c969a1893b453b2023cf4darylm        docloc = self.getdocloc(object)
10373b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if docloc is not None:
10383b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = result + self.section('MODULE DOCS', docloc)
10393b553e0ab2146ef2055c969a1893b453b2023cf4darylm
10403b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if desc:
10413b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = result + self.section('DESCRIPTION', desc)
10423b553e0ab2146ef2055c969a1893b453b2023cf4darylm
10433b553e0ab2146ef2055c969a1893b453b2023cf4darylm        classes = []
10443b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for key, value in inspect.getmembers(object, inspect.isclass):
10453b553e0ab2146ef2055c969a1893b453b2023cf4darylm            # if __all__ exists, believe it.  Otherwise use old heuristic.
10463b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if (all is not None
10473b553e0ab2146ef2055c969a1893b453b2023cf4darylm                or (inspect.getmodule(value) or object) is object):
10483b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if visiblename(key, all, object):
10493b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    classes.append((key, value))
10503b553e0ab2146ef2055c969a1893b453b2023cf4darylm        funcs = []
10513b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for key, value in inspect.getmembers(object, inspect.isroutine):
10523b553e0ab2146ef2055c969a1893b453b2023cf4darylm            # if __all__ exists, believe it.  Otherwise use old heuristic.
10533b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if (all is not None or
10543b553e0ab2146ef2055c969a1893b453b2023cf4darylm                inspect.isbuiltin(value) or inspect.getmodule(value) is object):
10553b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if visiblename(key, all, object):
10563b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    funcs.append((key, value))
10573b553e0ab2146ef2055c969a1893b453b2023cf4darylm        data = []
10583b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for key, value in inspect.getmembers(object, isdata):
10593b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if visiblename(key, all, object):
10603b553e0ab2146ef2055c969a1893b453b2023cf4darylm                data.append((key, value))
10613b553e0ab2146ef2055c969a1893b453b2023cf4darylm
10623b553e0ab2146ef2055c969a1893b453b2023cf4darylm        modpkgs = []
10633b553e0ab2146ef2055c969a1893b453b2023cf4darylm        modpkgs_names = set()
10643b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if hasattr(object, '__path__'):
10653b553e0ab2146ef2055c969a1893b453b2023cf4darylm            for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
10663b553e0ab2146ef2055c969a1893b453b2023cf4darylm                modpkgs_names.add(modname)
10673b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if ispkg:
10683b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    modpkgs.append(modname + ' (package)')
10693b553e0ab2146ef2055c969a1893b453b2023cf4darylm                else:
10703b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    modpkgs.append(modname)
10713b553e0ab2146ef2055c969a1893b453b2023cf4darylm
10723b553e0ab2146ef2055c969a1893b453b2023cf4darylm            modpkgs.sort()
10733b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = result + self.section(
10743b553e0ab2146ef2055c969a1893b453b2023cf4darylm                'PACKAGE CONTENTS', join(modpkgs, '\n'))
10753b553e0ab2146ef2055c969a1893b453b2023cf4darylm
10763b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # Detect submodules as sometimes created by C extensions
10773b553e0ab2146ef2055c969a1893b453b2023cf4darylm        submodules = []
10783b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for key, value in inspect.getmembers(object, inspect.ismodule):
10793b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if value.__name__.startswith(name + '.') and key not in modpkgs_names:
10803b553e0ab2146ef2055c969a1893b453b2023cf4darylm                submodules.append(key)
10813b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if submodules:
10823b553e0ab2146ef2055c969a1893b453b2023cf4darylm            submodules.sort()
10833b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = result + self.section(
10843b553e0ab2146ef2055c969a1893b453b2023cf4darylm                'SUBMODULES', join(submodules, '\n'))
10853b553e0ab2146ef2055c969a1893b453b2023cf4darylm
10863b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if classes:
10873b553e0ab2146ef2055c969a1893b453b2023cf4darylm            classlist = map(lambda key_value: key_value[1], classes)
10883b553e0ab2146ef2055c969a1893b453b2023cf4darylm            contents = [self.formattree(
10893b553e0ab2146ef2055c969a1893b453b2023cf4darylm                inspect.getclasstree(classlist, 1), name)]
10903b553e0ab2146ef2055c969a1893b453b2023cf4darylm            for key, value in classes:
10913b553e0ab2146ef2055c969a1893b453b2023cf4darylm                contents.append(self.document(value, key, name))
10923b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = result + self.section('CLASSES', join(contents, '\n'))
10933b553e0ab2146ef2055c969a1893b453b2023cf4darylm
10943b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if funcs:
10953b553e0ab2146ef2055c969a1893b453b2023cf4darylm            contents = []
10963b553e0ab2146ef2055c969a1893b453b2023cf4darylm            for key, value in funcs:
10973b553e0ab2146ef2055c969a1893b453b2023cf4darylm                contents.append(self.document(value, key, name))
10983b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = result + self.section('FUNCTIONS', join(contents, '\n'))
10993b553e0ab2146ef2055c969a1893b453b2023cf4darylm
11003b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if data:
11013b553e0ab2146ef2055c969a1893b453b2023cf4darylm            contents = []
11023b553e0ab2146ef2055c969a1893b453b2023cf4darylm            for key, value in data:
11033b553e0ab2146ef2055c969a1893b453b2023cf4darylm                contents.append(self.docother(value, key, name, maxlen=70))
11043b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = result + self.section('DATA', join(contents, '\n'))
11053b553e0ab2146ef2055c969a1893b453b2023cf4darylm
11063b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if hasattr(object, '__version__'):
11073b553e0ab2146ef2055c969a1893b453b2023cf4darylm            version = str(object.__version__)
11083b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
11093b553e0ab2146ef2055c969a1893b453b2023cf4darylm                version = strip(version[11:-1])
11103b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = result + self.section('VERSION', version)
11113b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if hasattr(object, '__date__'):
11123b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = result + self.section('DATE', str(object.__date__))
11133b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if hasattr(object, '__author__'):
11143b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = result + self.section('AUTHOR', str(object.__author__))
11153b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if hasattr(object, '__credits__'):
11163b553e0ab2146ef2055c969a1893b453b2023cf4darylm            result = result + self.section('CREDITS', str(object.__credits__))
11173b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return result
11183b553e0ab2146ef2055c969a1893b453b2023cf4darylm
11193b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def docclass(self, object, name=None, mod=None, *ignored):
11203b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Produce text documentation for a given class object."""
11213b553e0ab2146ef2055c969a1893b453b2023cf4darylm        realname = object.__name__
11223b553e0ab2146ef2055c969a1893b453b2023cf4darylm        name = name or realname
11233b553e0ab2146ef2055c969a1893b453b2023cf4darylm        bases = object.__bases__
11243b553e0ab2146ef2055c969a1893b453b2023cf4darylm
11253b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def makename(c, m=object.__module__):
11263b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return classname(c, m)
11273b553e0ab2146ef2055c969a1893b453b2023cf4darylm
11283b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if name == realname:
11293b553e0ab2146ef2055c969a1893b453b2023cf4darylm            title = 'class ' + self.bold(realname)
11303b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else:
11313b553e0ab2146ef2055c969a1893b453b2023cf4darylm            title = self.bold(name) + ' = class ' + realname
11323b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if bases:
11333b553e0ab2146ef2055c969a1893b453b2023cf4darylm            parents = map(makename, bases)
11343b553e0ab2146ef2055c969a1893b453b2023cf4darylm            title = title + '(%s)' % join(parents, ', ')
11353b553e0ab2146ef2055c969a1893b453b2023cf4darylm
11363b553e0ab2146ef2055c969a1893b453b2023cf4darylm        doc = getdoc(object)
11373b553e0ab2146ef2055c969a1893b453b2023cf4darylm        contents = doc and [doc + '\n'] or []
11383b553e0ab2146ef2055c969a1893b453b2023cf4darylm        push = contents.append
11393b553e0ab2146ef2055c969a1893b453b2023cf4darylm
11403b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # List the mro, if non-trivial.
11413b553e0ab2146ef2055c969a1893b453b2023cf4darylm        mro = deque(inspect.getmro(object))
11423b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if len(mro) > 2:
11433b553e0ab2146ef2055c969a1893b453b2023cf4darylm            push("Method resolution order:")
11443b553e0ab2146ef2055c969a1893b453b2023cf4darylm            for base in mro:
11453b553e0ab2146ef2055c969a1893b453b2023cf4darylm                push('    ' + makename(base))
11463b553e0ab2146ef2055c969a1893b453b2023cf4darylm            push('')
11473b553e0ab2146ef2055c969a1893b453b2023cf4darylm
11483b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # Cute little class to pump out a horizontal rule between sections.
11493b553e0ab2146ef2055c969a1893b453b2023cf4darylm        class HorizontalRule:
11503b553e0ab2146ef2055c969a1893b453b2023cf4darylm            def __init__(self):
11513b553e0ab2146ef2055c969a1893b453b2023cf4darylm                self.needone = 0
11523b553e0ab2146ef2055c969a1893b453b2023cf4darylm            def maybe(self):
11533b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if self.needone:
11543b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    push('-' * 70)
11553b553e0ab2146ef2055c969a1893b453b2023cf4darylm                self.needone = 1
11563b553e0ab2146ef2055c969a1893b453b2023cf4darylm        hr = HorizontalRule()
11573b553e0ab2146ef2055c969a1893b453b2023cf4darylm
11583b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def spill(msg, attrs, predicate):
11593b553e0ab2146ef2055c969a1893b453b2023cf4darylm            ok, attrs = _split_list(attrs, predicate)
11603b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if ok:
11613b553e0ab2146ef2055c969a1893b453b2023cf4darylm                hr.maybe()
11623b553e0ab2146ef2055c969a1893b453b2023cf4darylm                push(msg)
11633b553e0ab2146ef2055c969a1893b453b2023cf4darylm                for name, kind, homecls, value in ok:
11643b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    push(self.document(getattr(object, name),
11653b553e0ab2146ef2055c969a1893b453b2023cf4darylm                                       name, mod, object))
11663b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return attrs
11673b553e0ab2146ef2055c969a1893b453b2023cf4darylm
11683b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def spilldescriptors(msg, attrs, predicate):
11693b553e0ab2146ef2055c969a1893b453b2023cf4darylm            ok, attrs = _split_list(attrs, predicate)
11703b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if ok:
11713b553e0ab2146ef2055c969a1893b453b2023cf4darylm                hr.maybe()
11723b553e0ab2146ef2055c969a1893b453b2023cf4darylm                push(msg)
11733b553e0ab2146ef2055c969a1893b453b2023cf4darylm                for name, kind, homecls, value in ok:
11743b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    push(self._docdescriptor(name, value, mod))
11753b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return attrs
11763b553e0ab2146ef2055c969a1893b453b2023cf4darylm
11773b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def spilldata(msg, attrs, predicate):
11783b553e0ab2146ef2055c969a1893b453b2023cf4darylm            ok, attrs = _split_list(attrs, predicate)
11793b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if ok:
11803b553e0ab2146ef2055c969a1893b453b2023cf4darylm                hr.maybe()
11813b553e0ab2146ef2055c969a1893b453b2023cf4darylm                push(msg)
11823b553e0ab2146ef2055c969a1893b453b2023cf4darylm                for name, kind, homecls, value in ok:
11833b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    if (hasattr(value, '__call__') or
11843b553e0ab2146ef2055c969a1893b453b2023cf4darylm                            inspect.isdatadescriptor(value)):
11853b553e0ab2146ef2055c969a1893b453b2023cf4darylm                        doc = getdoc(value)
11863b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    else:
11873b553e0ab2146ef2055c969a1893b453b2023cf4darylm                        doc = None
11883b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    push(self.docother(getattr(object, name),
11893b553e0ab2146ef2055c969a1893b453b2023cf4darylm                                       name, mod, maxlen=70, doc=doc) + '\n')
11903b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return attrs
11913b553e0ab2146ef2055c969a1893b453b2023cf4darylm
11923b553e0ab2146ef2055c969a1893b453b2023cf4darylm        attrs = filter(lambda data: visiblename(data[0], obj=object),
11933b553e0ab2146ef2055c969a1893b453b2023cf4darylm                       classify_class_attrs(object))
11943b553e0ab2146ef2055c969a1893b453b2023cf4darylm        while attrs:
11953b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if mro:
11963b553e0ab2146ef2055c969a1893b453b2023cf4darylm                thisclass = mro.popleft()
11973b553e0ab2146ef2055c969a1893b453b2023cf4darylm            else:
11983b553e0ab2146ef2055c969a1893b453b2023cf4darylm                thisclass = attrs[0][2]
11993b553e0ab2146ef2055c969a1893b453b2023cf4darylm            attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
12003b553e0ab2146ef2055c969a1893b453b2023cf4darylm
12013b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if thisclass is __builtin__.object:
12023b553e0ab2146ef2055c969a1893b453b2023cf4darylm                attrs = inherited
12033b553e0ab2146ef2055c969a1893b453b2023cf4darylm                continue
12043b553e0ab2146ef2055c969a1893b453b2023cf4darylm            elif thisclass is object:
12053b553e0ab2146ef2055c969a1893b453b2023cf4darylm                tag = "defined here"
12063b553e0ab2146ef2055c969a1893b453b2023cf4darylm            else:
12073b553e0ab2146ef2055c969a1893b453b2023cf4darylm                tag = "inherited from %s" % classname(thisclass,
12083b553e0ab2146ef2055c969a1893b453b2023cf4darylm                                                      object.__module__)
12093b553e0ab2146ef2055c969a1893b453b2023cf4darylm
12103b553e0ab2146ef2055c969a1893b453b2023cf4darylm            # Sort attrs by name.
12113b553e0ab2146ef2055c969a1893b453b2023cf4darylm            attrs.sort()
12123b553e0ab2146ef2055c969a1893b453b2023cf4darylm
12133b553e0ab2146ef2055c969a1893b453b2023cf4darylm            # Pump out the attrs, segregated by kind.
12143b553e0ab2146ef2055c969a1893b453b2023cf4darylm            attrs = spill("Methods %s:\n" % tag, attrs,
12153b553e0ab2146ef2055c969a1893b453b2023cf4darylm                          lambda t: t[1] == 'method')
12163b553e0ab2146ef2055c969a1893b453b2023cf4darylm            attrs = spill("Class methods %s:\n" % tag, attrs,
12173b553e0ab2146ef2055c969a1893b453b2023cf4darylm                          lambda t: t[1] == 'class method')
12183b553e0ab2146ef2055c969a1893b453b2023cf4darylm            attrs = spill("Static methods %s:\n" % tag, attrs,
12193b553e0ab2146ef2055c969a1893b453b2023cf4darylm                          lambda t: t[1] == 'static method')
12203b553e0ab2146ef2055c969a1893b453b2023cf4darylm            attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
12213b553e0ab2146ef2055c969a1893b453b2023cf4darylm                                     lambda t: t[1] == 'data descriptor')
12223b553e0ab2146ef2055c969a1893b453b2023cf4darylm            attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
12233b553e0ab2146ef2055c969a1893b453b2023cf4darylm                              lambda t: t[1] == 'data')
12243b553e0ab2146ef2055c969a1893b453b2023cf4darylm            assert attrs == []
12253b553e0ab2146ef2055c969a1893b453b2023cf4darylm            attrs = inherited
12263b553e0ab2146ef2055c969a1893b453b2023cf4darylm
12273b553e0ab2146ef2055c969a1893b453b2023cf4darylm        contents = '\n'.join(contents)
12283b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if not contents:
12293b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return title + '\n'
12303b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return title + '\n' + self.indent(rstrip(contents), ' |  ') + '\n'
12313b553e0ab2146ef2055c969a1893b453b2023cf4darylm
12323b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def formatvalue(self, object):
12333b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Format an argument default value as text."""
12343b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return '=' + self.repr(object)
12353b553e0ab2146ef2055c969a1893b453b2023cf4darylm
12363b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def docroutine(self, object, name=None, mod=None, cl=None):
12373b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Produce text documentation for a function or method object."""
12383b553e0ab2146ef2055c969a1893b453b2023cf4darylm        realname = object.__name__
12393b553e0ab2146ef2055c969a1893b453b2023cf4darylm        name = name or realname
12403b553e0ab2146ef2055c969a1893b453b2023cf4darylm        note = ''
12413b553e0ab2146ef2055c969a1893b453b2023cf4darylm        skipdocs = 0
12423b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if inspect.ismethod(object):
12433b553e0ab2146ef2055c969a1893b453b2023cf4darylm            imclass = object.im_class
12443b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if cl:
12453b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if imclass is not cl:
12463b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    note = ' from ' + classname(imclass, mod)
12473b553e0ab2146ef2055c969a1893b453b2023cf4darylm            else:
12483b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if object.im_self is not None:
12493b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    note = ' method of %s instance' % classname(
12503b553e0ab2146ef2055c969a1893b453b2023cf4darylm                        object.im_self.__class__, mod)
12513b553e0ab2146ef2055c969a1893b453b2023cf4darylm                else:
12523b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    note = ' unbound %s method' % classname(imclass,mod)
12533b553e0ab2146ef2055c969a1893b453b2023cf4darylm            object = object.im_func
12543b553e0ab2146ef2055c969a1893b453b2023cf4darylm
12553b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if name == realname:
12563b553e0ab2146ef2055c969a1893b453b2023cf4darylm            title = self.bold(realname)
12573b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else:
12583b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if (cl and realname in cl.__dict__ and
12593b553e0ab2146ef2055c969a1893b453b2023cf4darylm                cl.__dict__[realname] is object):
12603b553e0ab2146ef2055c969a1893b453b2023cf4darylm                skipdocs = 1
12613b553e0ab2146ef2055c969a1893b453b2023cf4darylm            title = self.bold(name) + ' = ' + realname
12623b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if inspect.isfunction(object):
12633b553e0ab2146ef2055c969a1893b453b2023cf4darylm            args, varargs, varkw, defaults = inspect.getargspec(object)
12643b553e0ab2146ef2055c969a1893b453b2023cf4darylm            argspec = inspect.formatargspec(
12653b553e0ab2146ef2055c969a1893b453b2023cf4darylm                args, varargs, varkw, defaults, formatvalue=self.formatvalue)
12663b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if realname == '<lambda>':
12673b553e0ab2146ef2055c969a1893b453b2023cf4darylm                title = self.bold(name) + ' lambda '
12683b553e0ab2146ef2055c969a1893b453b2023cf4darylm                argspec = argspec[1:-1] # remove parentheses
12693b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else:
12703b553e0ab2146ef2055c969a1893b453b2023cf4darylm            argspec = '(...)'
12713b553e0ab2146ef2055c969a1893b453b2023cf4darylm        decl = title + argspec + note
12723b553e0ab2146ef2055c969a1893b453b2023cf4darylm
12733b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if skipdocs:
12743b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return decl + '\n'
12753b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else:
12763b553e0ab2146ef2055c969a1893b453b2023cf4darylm            doc = getdoc(object) or ''
12773b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return decl + '\n' + (doc and rstrip(self.indent(doc)) + '\n')
12783b553e0ab2146ef2055c969a1893b453b2023cf4darylm
12793b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def _docdescriptor(self, name, value, mod):
12803b553e0ab2146ef2055c969a1893b453b2023cf4darylm        results = []
12813b553e0ab2146ef2055c969a1893b453b2023cf4darylm        push = results.append
12823b553e0ab2146ef2055c969a1893b453b2023cf4darylm
12833b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if name:
12843b553e0ab2146ef2055c969a1893b453b2023cf4darylm            push(self.bold(name))
12853b553e0ab2146ef2055c969a1893b453b2023cf4darylm            push('\n')
12863b553e0ab2146ef2055c969a1893b453b2023cf4darylm        doc = getdoc(value) or ''
12873b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if doc:
12883b553e0ab2146ef2055c969a1893b453b2023cf4darylm            push(self.indent(doc))
12893b553e0ab2146ef2055c969a1893b453b2023cf4darylm            push('\n')
12903b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return ''.join(results)
12913b553e0ab2146ef2055c969a1893b453b2023cf4darylm
12923b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def docproperty(self, object, name=None, mod=None, cl=None):
12933b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Produce text documentation for a property."""
12943b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return self._docdescriptor(name, object, mod)
12953b553e0ab2146ef2055c969a1893b453b2023cf4darylm
12963b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def docdata(self, object, name=None, mod=None, cl=None):
12973b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Produce text documentation for a data descriptor."""
12983b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return self._docdescriptor(name, object, mod)
12993b553e0ab2146ef2055c969a1893b453b2023cf4darylm
13003b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
13013b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Produce text documentation for a data object."""
13023b553e0ab2146ef2055c969a1893b453b2023cf4darylm        repr = self.repr(object)
13033b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if maxlen:
13043b553e0ab2146ef2055c969a1893b453b2023cf4darylm            line = (name and name + ' = ' or '') + repr
13053b553e0ab2146ef2055c969a1893b453b2023cf4darylm            chop = maxlen - len(line)
13063b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if chop < 0: repr = repr[:chop] + '...'
13073b553e0ab2146ef2055c969a1893b453b2023cf4darylm        line = (name and self.bold(name) + ' = ' or '') + repr
13083b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if doc is not None:
13093b553e0ab2146ef2055c969a1893b453b2023cf4darylm            line += '\n' + self.indent(str(doc))
13103b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return line
13113b553e0ab2146ef2055c969a1893b453b2023cf4darylm
13123b553e0ab2146ef2055c969a1893b453b2023cf4darylm# --------------------------------------------------------- user interfaces
13133b553e0ab2146ef2055c969a1893b453b2023cf4darylm
13143b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef pager(text):
13153b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """The first time this is called, determine what kind of pager to use."""
13163b553e0ab2146ef2055c969a1893b453b2023cf4darylm    global pager
13173b553e0ab2146ef2055c969a1893b453b2023cf4darylm    pager = getpager()
13183b553e0ab2146ef2055c969a1893b453b2023cf4darylm    pager(text)
13193b553e0ab2146ef2055c969a1893b453b2023cf4darylm
13203b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef getpager():
13213b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Decide what method to use for paging through text."""
13223b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if type(sys.stdout) is not types.FileType:
13233b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return plainpager
13243b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if not sys.stdin.isatty() or not sys.stdout.isatty():
13253b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return plainpager
13263b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if 'PAGER' in os.environ:
13273b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if sys.platform == 'win32': # pipes completely broken in Windows
13283b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
13293b553e0ab2146ef2055c969a1893b453b2023cf4darylm        elif sys.platform == 'uefi':
13303b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
13313b553e0ab2146ef2055c969a1893b453b2023cf4darylm        elif os.environ.get('TERM') in ('dumb', 'emacs'):
13323b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return lambda text: pipepager(plain(text), os.environ['PAGER'])
13333b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else:
13343b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return lambda text: pipepager(text, os.environ['PAGER'])
13353b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if os.environ.get('TERM') in ('dumb', 'emacs'):
13363b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return plainpager
13373b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if sys.platform == 'uefi':
13383b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return plainpager
13393b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if sys.platform == 'win32' or sys.platform.startswith('os2'):
13403b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return lambda text: tempfilepager(plain(text), 'more <')
13413b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
13423b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return lambda text: pipepager(text, 'less')
13433b553e0ab2146ef2055c969a1893b453b2023cf4darylm
13443b553e0ab2146ef2055c969a1893b453b2023cf4darylm    import tempfile
13453b553e0ab2146ef2055c969a1893b453b2023cf4darylm    (fd, filename) = tempfile.mkstemp()
13463b553e0ab2146ef2055c969a1893b453b2023cf4darylm    os.close(fd)
13473b553e0ab2146ef2055c969a1893b453b2023cf4darylm    try:
13483b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
13493b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return lambda text: pipepager(text, 'more')
13503b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else:
13513b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return ttypager
13523b553e0ab2146ef2055c969a1893b453b2023cf4darylm    finally:
13533b553e0ab2146ef2055c969a1893b453b2023cf4darylm        os.unlink(filename)
13543b553e0ab2146ef2055c969a1893b453b2023cf4darylm
13553b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef plain(text):
13563b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Remove boldface formatting from text."""
13573b553e0ab2146ef2055c969a1893b453b2023cf4darylm    return re.sub('.\b', '', text)
13583b553e0ab2146ef2055c969a1893b453b2023cf4darylm
13593b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef pipepager(text, cmd):
13603b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Page through text by feeding it to another program."""
13613b553e0ab2146ef2055c969a1893b453b2023cf4darylm    pipe = os.popen(cmd, 'w')
13623b553e0ab2146ef2055c969a1893b453b2023cf4darylm    try:
13633b553e0ab2146ef2055c969a1893b453b2023cf4darylm        pipe.write(text)
13643b553e0ab2146ef2055c969a1893b453b2023cf4darylm        pipe.close()
13653b553e0ab2146ef2055c969a1893b453b2023cf4darylm    except IOError:
13663b553e0ab2146ef2055c969a1893b453b2023cf4darylm        pass # Ignore broken pipes caused by quitting the pager program.
13673b553e0ab2146ef2055c969a1893b453b2023cf4darylm
13683b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef tempfilepager(text, cmd):
13693b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Page through text by invoking a program on a temporary file."""
13703b553e0ab2146ef2055c969a1893b453b2023cf4darylm    import tempfile
13713b553e0ab2146ef2055c969a1893b453b2023cf4darylm    filename = tempfile.mktemp()
13723b553e0ab2146ef2055c969a1893b453b2023cf4darylm    file = open(filename, 'w')
13733b553e0ab2146ef2055c969a1893b453b2023cf4darylm    file.write(text)
13743b553e0ab2146ef2055c969a1893b453b2023cf4darylm    file.close()
13753b553e0ab2146ef2055c969a1893b453b2023cf4darylm    try:
13763b553e0ab2146ef2055c969a1893b453b2023cf4darylm        os.system(cmd + ' "' + filename + '"')
13773b553e0ab2146ef2055c969a1893b453b2023cf4darylm    finally:
13783b553e0ab2146ef2055c969a1893b453b2023cf4darylm        os.unlink(filename)
13793b553e0ab2146ef2055c969a1893b453b2023cf4darylm
13803b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef ttypager(text):
13813b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Page through text on a text terminal."""
13823b553e0ab2146ef2055c969a1893b453b2023cf4darylm    lines = split(plain(text), '\n')
13833b553e0ab2146ef2055c969a1893b453b2023cf4darylm    try:
13843b553e0ab2146ef2055c969a1893b453b2023cf4darylm        import tty
13853b553e0ab2146ef2055c969a1893b453b2023cf4darylm        fd = sys.stdin.fileno()
13863b553e0ab2146ef2055c969a1893b453b2023cf4darylm        old = tty.tcgetattr(fd)
13873b553e0ab2146ef2055c969a1893b453b2023cf4darylm        tty.setcbreak(fd)
13883b553e0ab2146ef2055c969a1893b453b2023cf4darylm        getchar = lambda: sys.stdin.read(1)
13893b553e0ab2146ef2055c969a1893b453b2023cf4darylm    except (ImportError, AttributeError):
13903b553e0ab2146ef2055c969a1893b453b2023cf4darylm        tty = None
13913b553e0ab2146ef2055c969a1893b453b2023cf4darylm        getchar = lambda: sys.stdin.readline()[:-1][:1]
13923b553e0ab2146ef2055c969a1893b453b2023cf4darylm
13933b553e0ab2146ef2055c969a1893b453b2023cf4darylm    try:
13943b553e0ab2146ef2055c969a1893b453b2023cf4darylm        r = inc = os.environ.get('LINES', 25) - 1
13953b553e0ab2146ef2055c969a1893b453b2023cf4darylm        sys.stdout.write(join(lines[:inc], '\n') + '\n')
13963b553e0ab2146ef2055c969a1893b453b2023cf4darylm        while lines[r:]:
13973b553e0ab2146ef2055c969a1893b453b2023cf4darylm            sys.stdout.write('-- more --')
13983b553e0ab2146ef2055c969a1893b453b2023cf4darylm            sys.stdout.flush()
13993b553e0ab2146ef2055c969a1893b453b2023cf4darylm            c = getchar()
14003b553e0ab2146ef2055c969a1893b453b2023cf4darylm
14013b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if c in ('q', 'Q'):
14023b553e0ab2146ef2055c969a1893b453b2023cf4darylm                sys.stdout.write('\r          \r')
14033b553e0ab2146ef2055c969a1893b453b2023cf4darylm                break
14043b553e0ab2146ef2055c969a1893b453b2023cf4darylm            elif c in ('\r', '\n'):
14053b553e0ab2146ef2055c969a1893b453b2023cf4darylm                sys.stdout.write('\r          \r' + lines[r] + '\n')
14063b553e0ab2146ef2055c969a1893b453b2023cf4darylm                r = r + 1
14073b553e0ab2146ef2055c969a1893b453b2023cf4darylm                continue
14083b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if c in ('b', 'B', '\x1b'):
14093b553e0ab2146ef2055c969a1893b453b2023cf4darylm                r = r - inc - inc
14103b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if r < 0: r = 0
14113b553e0ab2146ef2055c969a1893b453b2023cf4darylm            sys.stdout.write('\n' + join(lines[r:r+inc], '\n') + '\n')
14123b553e0ab2146ef2055c969a1893b453b2023cf4darylm            r = r + inc
14133b553e0ab2146ef2055c969a1893b453b2023cf4darylm
14143b553e0ab2146ef2055c969a1893b453b2023cf4darylm    finally:
14153b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if tty:
14163b553e0ab2146ef2055c969a1893b453b2023cf4darylm            tty.tcsetattr(fd, tty.TCSAFLUSH, old)
14173b553e0ab2146ef2055c969a1893b453b2023cf4darylm
14183b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef plainpager(text):
14193b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Simply print unformatted text.  This is the ultimate fallback."""
14203b553e0ab2146ef2055c969a1893b453b2023cf4darylm    sys.stdout.write(plain(text))
14213b553e0ab2146ef2055c969a1893b453b2023cf4darylm
14223b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef describe(thing):
14233b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Produce a short description of the given thing."""
14243b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if inspect.ismodule(thing):
14253b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if thing.__name__ in sys.builtin_module_names:
14263b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return 'built-in module ' + thing.__name__
14273b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if hasattr(thing, '__path__'):
14283b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return 'package ' + thing.__name__
14293b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else:
14303b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return 'module ' + thing.__name__
14313b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if inspect.isbuiltin(thing):
14323b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return 'built-in function ' + thing.__name__
14333b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if inspect.isgetsetdescriptor(thing):
14343b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return 'getset descriptor %s.%s.%s' % (
14353b553e0ab2146ef2055c969a1893b453b2023cf4darylm            thing.__objclass__.__module__, thing.__objclass__.__name__,
14363b553e0ab2146ef2055c969a1893b453b2023cf4darylm            thing.__name__)
14373b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if inspect.ismemberdescriptor(thing):
14383b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return 'member descriptor %s.%s.%s' % (
14393b553e0ab2146ef2055c969a1893b453b2023cf4darylm            thing.__objclass__.__module__, thing.__objclass__.__name__,
14403b553e0ab2146ef2055c969a1893b453b2023cf4darylm            thing.__name__)
14413b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if inspect.isclass(thing):
14423b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return 'class ' + thing.__name__
14433b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if inspect.isfunction(thing):
14443b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return 'function ' + thing.__name__
14453b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if inspect.ismethod(thing):
14463b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return 'method ' + thing.__name__
14473b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if type(thing) is types.InstanceType:
14483b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return 'instance of ' + thing.__class__.__name__
14493b553e0ab2146ef2055c969a1893b453b2023cf4darylm    return type(thing).__name__
14503b553e0ab2146ef2055c969a1893b453b2023cf4darylm
14513b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef locate(path, forceload=0):
14523b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Locate an object by name or dotted path, importing as necessary."""
14533b553e0ab2146ef2055c969a1893b453b2023cf4darylm    parts = [part for part in split(path, '.') if part]
14543b553e0ab2146ef2055c969a1893b453b2023cf4darylm    module, n = None, 0
14553b553e0ab2146ef2055c969a1893b453b2023cf4darylm    while n < len(parts):
14563b553e0ab2146ef2055c969a1893b453b2023cf4darylm        nextmodule = safeimport(join(parts[:n+1], '.'), forceload)
14573b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if nextmodule: module, n = nextmodule, n + 1
14583b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else: break
14593b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if module:
14603b553e0ab2146ef2055c969a1893b453b2023cf4darylm        object = module
14613b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for part in parts[n:]:
14623b553e0ab2146ef2055c969a1893b453b2023cf4darylm            try: object = getattr(object, part)
14633b553e0ab2146ef2055c969a1893b453b2023cf4darylm            except AttributeError: return None
14643b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return object
14653b553e0ab2146ef2055c969a1893b453b2023cf4darylm    else:
14663b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if hasattr(__builtin__, path):
14673b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return getattr(__builtin__, path)
14683b553e0ab2146ef2055c969a1893b453b2023cf4darylm
14693b553e0ab2146ef2055c969a1893b453b2023cf4darylm# --------------------------------------- interactive interpreter interface
14703b553e0ab2146ef2055c969a1893b453b2023cf4darylm
14713b553e0ab2146ef2055c969a1893b453b2023cf4darylmtext = TextDoc()
14723b553e0ab2146ef2055c969a1893b453b2023cf4darylmhtml = HTMLDoc()
14733b553e0ab2146ef2055c969a1893b453b2023cf4darylm
14743b553e0ab2146ef2055c969a1893b453b2023cf4darylmclass _OldStyleClass: pass
14753b553e0ab2146ef2055c969a1893b453b2023cf4darylm_OLD_INSTANCE_TYPE = type(_OldStyleClass())
14763b553e0ab2146ef2055c969a1893b453b2023cf4darylm
14773b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef resolve(thing, forceload=0):
14783b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Given an object or a path to an object, get the object and its name."""
14793b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if isinstance(thing, str):
14803b553e0ab2146ef2055c969a1893b453b2023cf4darylm        object = locate(thing, forceload)
14813b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if not object:
14823b553e0ab2146ef2055c969a1893b453b2023cf4darylm            raise ImportError, 'no Python documentation found for %r' % thing
14833b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return object, thing
14843b553e0ab2146ef2055c969a1893b453b2023cf4darylm    else:
14853b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return thing, getattr(thing, '__name__', None)
14863b553e0ab2146ef2055c969a1893b453b2023cf4darylm
14873b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef render_doc(thing, title='Python Library Documentation: %s', forceload=0):
14883b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Render text documentation, given an object or a path to an object."""
14893b553e0ab2146ef2055c969a1893b453b2023cf4darylm    object, name = resolve(thing, forceload)
14903b553e0ab2146ef2055c969a1893b453b2023cf4darylm    desc = describe(object)
14913b553e0ab2146ef2055c969a1893b453b2023cf4darylm    module = inspect.getmodule(object)
14923b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if name and '.' in name:
14933b553e0ab2146ef2055c969a1893b453b2023cf4darylm        desc += ' in ' + name[:name.rfind('.')]
14943b553e0ab2146ef2055c969a1893b453b2023cf4darylm    elif module and module is not object:
14953b553e0ab2146ef2055c969a1893b453b2023cf4darylm        desc += ' in module ' + module.__name__
14963b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if type(object) is _OLD_INSTANCE_TYPE:
14973b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # If the passed object is an instance of an old-style class,
14983b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # document its available methods instead of its value.
14993b553e0ab2146ef2055c969a1893b453b2023cf4darylm        object = object.__class__
15003b553e0ab2146ef2055c969a1893b453b2023cf4darylm    elif not (inspect.ismodule(object) or
15013b553e0ab2146ef2055c969a1893b453b2023cf4darylm              inspect.isclass(object) or
15023b553e0ab2146ef2055c969a1893b453b2023cf4darylm              inspect.isroutine(object) or
15033b553e0ab2146ef2055c969a1893b453b2023cf4darylm              inspect.isgetsetdescriptor(object) or
15043b553e0ab2146ef2055c969a1893b453b2023cf4darylm              inspect.ismemberdescriptor(object) or
15053b553e0ab2146ef2055c969a1893b453b2023cf4darylm              isinstance(object, property)):
15063b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # If the passed object is a piece of data or an instance,
15073b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # document its available methods instead of its value.
15083b553e0ab2146ef2055c969a1893b453b2023cf4darylm        object = type(object)
15093b553e0ab2146ef2055c969a1893b453b2023cf4darylm        desc += ' object'
15103b553e0ab2146ef2055c969a1893b453b2023cf4darylm    return title % desc + '\n\n' + text.document(object, name)
15113b553e0ab2146ef2055c969a1893b453b2023cf4darylm
15123b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef doc(thing, title='Python Library Documentation: %s', forceload=0):
15133b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Display text documentation, given an object or a path to an object."""
15143b553e0ab2146ef2055c969a1893b453b2023cf4darylm    try:
15153b553e0ab2146ef2055c969a1893b453b2023cf4darylm        pager(render_doc(thing, title, forceload))
15163b553e0ab2146ef2055c969a1893b453b2023cf4darylm    except (ImportError, ErrorDuringImport), value:
15173b553e0ab2146ef2055c969a1893b453b2023cf4darylm        print value
15183b553e0ab2146ef2055c969a1893b453b2023cf4darylm
15193b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef writedoc(thing, forceload=0):
15203b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Write HTML documentation to a file in the current directory."""
15213b553e0ab2146ef2055c969a1893b453b2023cf4darylm    try:
15223b553e0ab2146ef2055c969a1893b453b2023cf4darylm        object, name = resolve(thing, forceload)
15233b553e0ab2146ef2055c969a1893b453b2023cf4darylm        page = html.page(describe(object), html.document(object, name))
15243b553e0ab2146ef2055c969a1893b453b2023cf4darylm        file = open(name + '.html', 'w')
15253b553e0ab2146ef2055c969a1893b453b2023cf4darylm        file.write(page)
15263b553e0ab2146ef2055c969a1893b453b2023cf4darylm        file.close()
15273b553e0ab2146ef2055c969a1893b453b2023cf4darylm        print 'wrote', name + '.html'
15283b553e0ab2146ef2055c969a1893b453b2023cf4darylm    except (ImportError, ErrorDuringImport), value:
15293b553e0ab2146ef2055c969a1893b453b2023cf4darylm        print value
15303b553e0ab2146ef2055c969a1893b453b2023cf4darylm
15313b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef writedocs(dir, pkgpath='', done=None):
15323b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Write out HTML documentation for all modules in a directory tree."""
15333b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if done is None: done = {}
15343b553e0ab2146ef2055c969a1893b453b2023cf4darylm    for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
15353b553e0ab2146ef2055c969a1893b453b2023cf4darylm        writedoc(modname)
15363b553e0ab2146ef2055c969a1893b453b2023cf4darylm    return
15373b553e0ab2146ef2055c969a1893b453b2023cf4darylm
15383b553e0ab2146ef2055c969a1893b453b2023cf4darylmclass Helper:
15393b553e0ab2146ef2055c969a1893b453b2023cf4darylm
15403b553e0ab2146ef2055c969a1893b453b2023cf4darylm    # These dictionaries map a topic name to either an alias, or a tuple
15413b553e0ab2146ef2055c969a1893b453b2023cf4darylm    # (label, seealso-items).  The "label" is the label of the corresponding
15423b553e0ab2146ef2055c969a1893b453b2023cf4darylm    # section in the .rst file under Doc/ and an index into the dictionary
15433b553e0ab2146ef2055c969a1893b453b2023cf4darylm    # in pydoc_data/topics.py.
15443b553e0ab2146ef2055c969a1893b453b2023cf4darylm    #
15453b553e0ab2146ef2055c969a1893b453b2023cf4darylm    # CAUTION: if you change one of these dictionaries, be sure to adapt the
15463b553e0ab2146ef2055c969a1893b453b2023cf4darylm    #          list of needed labels in Doc/tools/sphinxext/pyspecific.py and
15473b553e0ab2146ef2055c969a1893b453b2023cf4darylm    #          regenerate the pydoc_data/topics.py file by running
15483b553e0ab2146ef2055c969a1893b453b2023cf4darylm    #              make pydoc-topics
15493b553e0ab2146ef2055c969a1893b453b2023cf4darylm    #          in Doc/ and copying the output file into the Lib/ directory.
15503b553e0ab2146ef2055c969a1893b453b2023cf4darylm
15513b553e0ab2146ef2055c969a1893b453b2023cf4darylm    keywords = {
15523b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'and': 'BOOLEAN',
15533b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'as': 'with',
15543b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'assert': ('assert', ''),
15553b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'break': ('break', 'while for'),
15563b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'class': ('class', 'CLASSES SPECIALMETHODS'),
15573b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'continue': ('continue', 'while for'),
15583b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'def': ('function', ''),
15593b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'del': ('del', 'BASICMETHODS'),
15603b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'elif': 'if',
15613b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'else': ('else', 'while for'),
15623b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'except': 'try',
15633b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'exec': ('exec', ''),
15643b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'finally': 'try',
15653b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'for': ('for', 'break continue while'),
15663b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'from': 'import',
15673b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'global': ('global', 'NAMESPACES'),
15683b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'if': ('if', 'TRUTHVALUE'),
15693b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'import': ('import', 'MODULES'),
15703b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'in': ('in', 'SEQUENCEMETHODS2'),
15713b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'is': 'COMPARISON',
15723b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'lambda': ('lambda', 'FUNCTIONS'),
15733b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'not': 'BOOLEAN',
15743b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'or': 'BOOLEAN',
15753b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'pass': ('pass', ''),
15763b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'print': ('print', ''),
15773b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'raise': ('raise', 'EXCEPTIONS'),
15783b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'return': ('return', 'FUNCTIONS'),
15793b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'try': ('try', 'EXCEPTIONS'),
15803b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'while': ('while', 'break continue if TRUTHVALUE'),
15813b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
15823b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'yield': ('yield', ''),
15833b553e0ab2146ef2055c969a1893b453b2023cf4darylm    }
15843b553e0ab2146ef2055c969a1893b453b2023cf4darylm    # Either add symbols to this dictionary or to the symbols dictionary
15853b553e0ab2146ef2055c969a1893b453b2023cf4darylm    # directly: Whichever is easier. They are merged later.
15863b553e0ab2146ef2055c969a1893b453b2023cf4darylm    _symbols_inverse = {
15873b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'STRINGS' : ("'", "'''", "r'", "u'", '"""', '"', 'r"', 'u"'),
15883b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
15893b553e0ab2146ef2055c969a1893b453b2023cf4darylm                       '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
15903b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
15913b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'UNARY' : ('-', '~'),
15923b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
15933b553e0ab2146ef2055c969a1893b453b2023cf4darylm                                '^=', '<<=', '>>=', '**=', '//='),
15943b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
15953b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'COMPLEX' : ('j', 'J')
15963b553e0ab2146ef2055c969a1893b453b2023cf4darylm    }
15973b553e0ab2146ef2055c969a1893b453b2023cf4darylm    symbols = {
15983b553e0ab2146ef2055c969a1893b453b2023cf4darylm        '%': 'OPERATORS FORMATTING',
15993b553e0ab2146ef2055c969a1893b453b2023cf4darylm        '**': 'POWER',
16003b553e0ab2146ef2055c969a1893b453b2023cf4darylm        ',': 'TUPLES LISTS FUNCTIONS',
16013b553e0ab2146ef2055c969a1893b453b2023cf4darylm        '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
16023b553e0ab2146ef2055c969a1893b453b2023cf4darylm        '...': 'ELLIPSIS',
16033b553e0ab2146ef2055c969a1893b453b2023cf4darylm        ':': 'SLICINGS DICTIONARYLITERALS',
16043b553e0ab2146ef2055c969a1893b453b2023cf4darylm        '@': 'def class',
16053b553e0ab2146ef2055c969a1893b453b2023cf4darylm        '\\': 'STRINGS',
16063b553e0ab2146ef2055c969a1893b453b2023cf4darylm        '_': 'PRIVATENAMES',
16073b553e0ab2146ef2055c969a1893b453b2023cf4darylm        '__': 'PRIVATENAMES SPECIALMETHODS',
16083b553e0ab2146ef2055c969a1893b453b2023cf4darylm        '`': 'BACKQUOTES',
16093b553e0ab2146ef2055c969a1893b453b2023cf4darylm        '(': 'TUPLES FUNCTIONS CALLS',
16103b553e0ab2146ef2055c969a1893b453b2023cf4darylm        ')': 'TUPLES FUNCTIONS CALLS',
16113b553e0ab2146ef2055c969a1893b453b2023cf4darylm        '[': 'LISTS SUBSCRIPTS SLICINGS',
16123b553e0ab2146ef2055c969a1893b453b2023cf4darylm        ']': 'LISTS SUBSCRIPTS SLICINGS'
16133b553e0ab2146ef2055c969a1893b453b2023cf4darylm    }
16143b553e0ab2146ef2055c969a1893b453b2023cf4darylm    for topic, symbols_ in _symbols_inverse.iteritems():
16153b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for symbol in symbols_:
16163b553e0ab2146ef2055c969a1893b453b2023cf4darylm            topics = symbols.get(symbol, topic)
16173b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if topic not in topics:
16183b553e0ab2146ef2055c969a1893b453b2023cf4darylm                topics = topics + ' ' + topic
16193b553e0ab2146ef2055c969a1893b453b2023cf4darylm            symbols[symbol] = topics
16203b553e0ab2146ef2055c969a1893b453b2023cf4darylm
16213b553e0ab2146ef2055c969a1893b453b2023cf4darylm    topics = {
16223b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
16233b553e0ab2146ef2055c969a1893b453b2023cf4darylm                  'FUNCTIONS CLASSES MODULES FILES inspect'),
16243b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS FORMATTING '
16253b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    'TYPES'),
16263b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
16273b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'FORMATTING': ('formatstrings', 'OPERATORS'),
16283b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
16293b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    'FORMATTING TYPES'),
16303b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
16313b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'INTEGER': ('integers', 'int range'),
16323b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'FLOAT': ('floating', 'float math'),
16333b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'COMPLEX': ('imaginary', 'complex cmath'),
16343b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING xrange LISTS'),
16353b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'MAPPINGS': 'DICTIONARIES',
16363b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'FUNCTIONS': ('typesfunctions', 'def TYPES'),
16373b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
16383b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
16393b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
16403b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'FRAMEOBJECTS': 'TYPES',
16413b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'TRACEBACKS': 'TYPES',
16423b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'NONE': ('bltin-null-object', ''),
16433b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
16443b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'FILES': ('bltin-file-objects', ''),
16453b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'SPECIALATTRIBUTES': ('specialattrs', ''),
16463b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
16473b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'MODULES': ('typesmodules', 'import'),
16483b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'PACKAGES': 'import',
16493b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
16503b553e0ab2146ef2055c969a1893b453b2023cf4darylm                        'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
16513b553e0ab2146ef2055c969a1893b453b2023cf4darylm                        'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
16523b553e0ab2146ef2055c969a1893b453b2023cf4darylm                        'LISTS DICTIONARIES BACKQUOTES'),
16533b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'OPERATORS': 'EXPRESSIONS',
16543b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'PRECEDENCE': 'EXPRESSIONS',
16553b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'OBJECTS': ('objects', 'TYPES'),
16563b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
16573b553e0ab2146ef2055c969a1893b453b2023cf4darylm                           'CALLABLEMETHODS SEQUENCEMETHODS1 MAPPINGMETHODS '
16583b553e0ab2146ef2055c969a1893b453b2023cf4darylm                           'SEQUENCEMETHODS2 NUMBERMETHODS CLASSES'),
16593b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'BASICMETHODS': ('customization', 'cmp hash repr str SPECIALMETHODS'),
16603b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
16613b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
16623b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'SEQUENCEMETHODS1': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS2 '
16633b553e0ab2146ef2055c969a1893b453b2023cf4darylm                             'SPECIALMETHODS'),
16643b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'SEQUENCEMETHODS2': ('sequence-methods', 'SEQUENCES SEQUENCEMETHODS1 '
16653b553e0ab2146ef2055c969a1893b453b2023cf4darylm                             'SPECIALMETHODS'),
16663b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
16673b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
16683b553e0ab2146ef2055c969a1893b453b2023cf4darylm                          'SPECIALMETHODS'),
16693b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
16703b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'NAMESPACES': ('naming', 'global ASSIGNMENT DELETION DYNAMICFEATURES'),
16713b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'DYNAMICFEATURES': ('dynamic-features', ''),
16723b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'SCOPING': 'NAMESPACES',
16733b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'FRAMES': 'NAMESPACES',
16743b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'EXCEPTIONS': ('exceptions', 'try except finally raise'),
16753b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'COERCIONS': ('coercion-rules','CONVERSIONS'),
16763b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'CONVERSIONS': ('conversions', 'COERCIONS'),
16773b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
16783b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'SPECIALIDENTIFIERS': ('id-classes', ''),
16793b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'PRIVATENAMES': ('atom-identifiers', ''),
16803b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'LITERALS': ('atom-literals', 'STRINGS BACKQUOTES NUMBERS '
16813b553e0ab2146ef2055c969a1893b453b2023cf4darylm                     'TUPLELITERALS LISTLITERALS DICTIONARYLITERALS'),
16823b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'TUPLES': 'SEQUENCES',
16833b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
16843b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
16853b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'LISTLITERALS': ('lists', 'LISTS LITERALS'),
16863b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
16873b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
16883b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'BACKQUOTES': ('string-conversions', 'repr str STRINGS LITERALS'),
16893b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr '
16903b553e0ab2146ef2055c969a1893b453b2023cf4darylm                       'ATTRIBUTEMETHODS'),
16913b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS1'),
16923b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'SLICINGS': ('slicings', 'SEQUENCEMETHODS2'),
16933b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'CALLS': ('calls', 'EXPRESSIONS'),
16943b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'POWER': ('power', 'EXPRESSIONS'),
16953b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'UNARY': ('unary', 'EXPRESSIONS'),
16963b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'BINARY': ('binary', 'EXPRESSIONS'),
16973b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'SHIFTING': ('shifting', 'EXPRESSIONS'),
16983b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'BITWISE': ('bitwise', 'EXPRESSIONS'),
16993b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
17003b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
17013b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'ASSERTION': 'assert',
17023b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
17033b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
17043b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'DELETION': 'del',
17053b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'PRINTING': 'print',
17063b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'RETURNING': 'return',
17073b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'IMPORTING': 'import',
17083b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'CONDITIONAL': 'if',
17093b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'LOOPING': ('compound', 'for while break continue'),
17103b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
17113b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'DEBUGGING': ('debugger', 'pdb'),
17123b553e0ab2146ef2055c969a1893b453b2023cf4darylm        'CONTEXTMANAGERS': ('context-managers', 'with'),
17133b553e0ab2146ef2055c969a1893b453b2023cf4darylm    }
17143b553e0ab2146ef2055c969a1893b453b2023cf4darylm
17153b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def __init__(self, input=None, output=None):
17163b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self._input = input
17173b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self._output = output
17183b553e0ab2146ef2055c969a1893b453b2023cf4darylm
17193b553e0ab2146ef2055c969a1893b453b2023cf4darylm    input  = property(lambda self: self._input or sys.stdin)
17203b553e0ab2146ef2055c969a1893b453b2023cf4darylm    output = property(lambda self: self._output or sys.stdout)
17213b553e0ab2146ef2055c969a1893b453b2023cf4darylm
17223b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def __repr__(self):
17233b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if inspect.stack()[1][3] == '?':
17243b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self()
17253b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return ''
17263b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return '<pydoc.Helper instance>'
17273b553e0ab2146ef2055c969a1893b453b2023cf4darylm
17283b553e0ab2146ef2055c969a1893b453b2023cf4darylm    _GoInteractive = object()
17293b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def __call__(self, request=_GoInteractive):
17303b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if request is not self._GoInteractive:
17313b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.help(request)
17323b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else:
17333b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.intro()
17343b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.interact()
17353b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.output.write('''
17363b553e0ab2146ef2055c969a1893b453b2023cf4darylmYou are now leaving help and returning to the Python interpreter.
17373b553e0ab2146ef2055c969a1893b453b2023cf4darylmIf you want to ask for help on a particular object directly from the
17383b553e0ab2146ef2055c969a1893b453b2023cf4darylminterpreter, you can type "help(object)".  Executing "help('string')"
17393b553e0ab2146ef2055c969a1893b453b2023cf4darylmhas the same effect as typing a particular string at the help> prompt.
17403b553e0ab2146ef2055c969a1893b453b2023cf4darylm''')
17413b553e0ab2146ef2055c969a1893b453b2023cf4darylm
17423b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def interact(self):
17433b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.output.write('\n')
17443b553e0ab2146ef2055c969a1893b453b2023cf4darylm        while True:
17453b553e0ab2146ef2055c969a1893b453b2023cf4darylm            try:
17463b553e0ab2146ef2055c969a1893b453b2023cf4darylm                request = self.getline('help> ')
17473b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if not request: break
17483b553e0ab2146ef2055c969a1893b453b2023cf4darylm            except (KeyboardInterrupt, EOFError):
17493b553e0ab2146ef2055c969a1893b453b2023cf4darylm                break
17503b553e0ab2146ef2055c969a1893b453b2023cf4darylm            request = strip(replace(request, '"', '', "'", ''))
17513b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if lower(request) in ('q', 'quit'): break
17523b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.help(request)
17533b553e0ab2146ef2055c969a1893b453b2023cf4darylm
17543b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def getline(self, prompt):
17553b553e0ab2146ef2055c969a1893b453b2023cf4darylm        """Read one line, using raw_input when available."""
17563b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if self.input is sys.stdin:
17573b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return raw_input(prompt)
17583b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else:
17593b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.output.write(prompt)
17603b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.output.flush()
17613b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return self.input.readline()
17623b553e0ab2146ef2055c969a1893b453b2023cf4darylm
17633b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def help(self, request):
17643b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if type(request) is type(''):
17653b553e0ab2146ef2055c969a1893b453b2023cf4darylm            request = request.strip()
17663b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if request == 'help': self.intro()
17673b553e0ab2146ef2055c969a1893b453b2023cf4darylm            elif request == 'keywords': self.listkeywords()
17683b553e0ab2146ef2055c969a1893b453b2023cf4darylm            elif request == 'symbols': self.listsymbols()
17693b553e0ab2146ef2055c969a1893b453b2023cf4darylm            elif request == 'topics': self.listtopics()
17703b553e0ab2146ef2055c969a1893b453b2023cf4darylm            elif request == 'modules': self.listmodules()
17713b553e0ab2146ef2055c969a1893b453b2023cf4darylm            elif request[:8] == 'modules ':
17723b553e0ab2146ef2055c969a1893b453b2023cf4darylm                self.listmodules(split(request)[1])
17733b553e0ab2146ef2055c969a1893b453b2023cf4darylm            elif request in self.symbols: self.showsymbol(request)
17743b553e0ab2146ef2055c969a1893b453b2023cf4darylm            elif request in self.keywords: self.showtopic(request)
17753b553e0ab2146ef2055c969a1893b453b2023cf4darylm            elif request in self.topics: self.showtopic(request)
17763b553e0ab2146ef2055c969a1893b453b2023cf4darylm            elif request: doc(request, 'Help on %s:')
17773b553e0ab2146ef2055c969a1893b453b2023cf4darylm        elif isinstance(request, Helper): self()
17783b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else: doc(request, 'Help on %s:')
17793b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.output.write('\n')
17803b553e0ab2146ef2055c969a1893b453b2023cf4darylm
17813b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def intro(self):
17823b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.output.write('''
17833b553e0ab2146ef2055c969a1893b453b2023cf4darylmWelcome to Python %s!  This is the online help utility.
17843b553e0ab2146ef2055c969a1893b453b2023cf4darylm
17853b553e0ab2146ef2055c969a1893b453b2023cf4darylmIf this is your first time using Python, you should definitely check out
17863b553e0ab2146ef2055c969a1893b453b2023cf4darylmthe tutorial on the Internet at http://docs.python.org/tutorial/.
17873b553e0ab2146ef2055c969a1893b453b2023cf4darylm
17883b553e0ab2146ef2055c969a1893b453b2023cf4darylmEnter the name of any module, keyword, or topic to get help on writing
17893b553e0ab2146ef2055c969a1893b453b2023cf4darylmPython programs and using Python modules.  To quit this help utility and
17903b553e0ab2146ef2055c969a1893b453b2023cf4darylmreturn to the interpreter, just type "quit".
17913b553e0ab2146ef2055c969a1893b453b2023cf4darylm
17923b553e0ab2146ef2055c969a1893b453b2023cf4darylmTo get a list of available modules, keywords, or topics, type "modules",
17933b553e0ab2146ef2055c969a1893b453b2023cf4darylm"keywords", or "topics".  Each module also comes with a one-line summary
17943b553e0ab2146ef2055c969a1893b453b2023cf4darylmof what it does; to list the modules whose summaries contain a given word
17953b553e0ab2146ef2055c969a1893b453b2023cf4darylmsuch as "spam", type "modules spam".
17963b553e0ab2146ef2055c969a1893b453b2023cf4darylm''' % sys.version[:3])
17973b553e0ab2146ef2055c969a1893b453b2023cf4darylm
17983b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def list(self, items, columns=4, width=80):
17993b553e0ab2146ef2055c969a1893b453b2023cf4darylm        items = items[:]
18003b553e0ab2146ef2055c969a1893b453b2023cf4darylm        items.sort()
18013b553e0ab2146ef2055c969a1893b453b2023cf4darylm        colw = width / columns
18023b553e0ab2146ef2055c969a1893b453b2023cf4darylm        rows = (len(items) + columns - 1) / columns
18033b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for row in range(rows):
18043b553e0ab2146ef2055c969a1893b453b2023cf4darylm            for col in range(columns):
18053b553e0ab2146ef2055c969a1893b453b2023cf4darylm                i = col * rows + row
18063b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if i < len(items):
18073b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    self.output.write(items[i])
18083b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    if col < columns - 1:
18093b553e0ab2146ef2055c969a1893b453b2023cf4darylm                        self.output.write(' ' + ' ' * (colw-1 - len(items[i])))
18103b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.output.write('\n')
18113b553e0ab2146ef2055c969a1893b453b2023cf4darylm
18123b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def listkeywords(self):
18133b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.output.write('''
18143b553e0ab2146ef2055c969a1893b453b2023cf4darylmHere is a list of the Python keywords.  Enter any keyword to get more help.
18153b553e0ab2146ef2055c969a1893b453b2023cf4darylm
18163b553e0ab2146ef2055c969a1893b453b2023cf4darylm''')
18173b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.list(self.keywords.keys())
18183b553e0ab2146ef2055c969a1893b453b2023cf4darylm
18193b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def listsymbols(self):
18203b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.output.write('''
18213b553e0ab2146ef2055c969a1893b453b2023cf4darylmHere is a list of the punctuation symbols which Python assigns special meaning
18223b553e0ab2146ef2055c969a1893b453b2023cf4darylmto. Enter any symbol to get more help.
18233b553e0ab2146ef2055c969a1893b453b2023cf4darylm
18243b553e0ab2146ef2055c969a1893b453b2023cf4darylm''')
18253b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.list(self.symbols.keys())
18263b553e0ab2146ef2055c969a1893b453b2023cf4darylm
18273b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def listtopics(self):
18283b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.output.write('''
18293b553e0ab2146ef2055c969a1893b453b2023cf4darylmHere is a list of available topics.  Enter any topic name to get more help.
18303b553e0ab2146ef2055c969a1893b453b2023cf4darylm
18313b553e0ab2146ef2055c969a1893b453b2023cf4darylm''')
18323b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.list(self.topics.keys())
18333b553e0ab2146ef2055c969a1893b453b2023cf4darylm
18343b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def showtopic(self, topic, more_xrefs=''):
18353b553e0ab2146ef2055c969a1893b453b2023cf4darylm        try:
18363b553e0ab2146ef2055c969a1893b453b2023cf4darylm            import pydoc_data.topics
18373b553e0ab2146ef2055c969a1893b453b2023cf4darylm        except ImportError:
18383b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.output.write('''
18393b553e0ab2146ef2055c969a1893b453b2023cf4darylmSorry, topic and keyword documentation is not available because the
18403b553e0ab2146ef2055c969a1893b453b2023cf4darylmmodule "pydoc_data.topics" could not be found.
18413b553e0ab2146ef2055c969a1893b453b2023cf4darylm''')
18423b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return
18433b553e0ab2146ef2055c969a1893b453b2023cf4darylm        target = self.topics.get(topic, self.keywords.get(topic))
18443b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if not target:
18453b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.output.write('no documentation found for %s\n' % repr(topic))
18463b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return
18473b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if type(target) is type(''):
18483b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return self.showtopic(target, more_xrefs)
18493b553e0ab2146ef2055c969a1893b453b2023cf4darylm
18503b553e0ab2146ef2055c969a1893b453b2023cf4darylm        label, xrefs = target
18513b553e0ab2146ef2055c969a1893b453b2023cf4darylm        try:
18523b553e0ab2146ef2055c969a1893b453b2023cf4darylm            doc = pydoc_data.topics.topics[label]
18533b553e0ab2146ef2055c969a1893b453b2023cf4darylm        except KeyError:
18543b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.output.write('no documentation found for %s\n' % repr(topic))
18553b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return
18563b553e0ab2146ef2055c969a1893b453b2023cf4darylm        pager(strip(doc) + '\n')
18573b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if more_xrefs:
18583b553e0ab2146ef2055c969a1893b453b2023cf4darylm            xrefs = (xrefs or '') + ' ' + more_xrefs
18593b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if xrefs:
18603b553e0ab2146ef2055c969a1893b453b2023cf4darylm            import StringIO, formatter
18613b553e0ab2146ef2055c969a1893b453b2023cf4darylm            buffer = StringIO.StringIO()
18623b553e0ab2146ef2055c969a1893b453b2023cf4darylm            formatter.DumbWriter(buffer).send_flowing_data(
18633b553e0ab2146ef2055c969a1893b453b2023cf4darylm                'Related help topics: ' + join(split(xrefs), ', ') + '\n')
18643b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.output.write('\n%s\n' % buffer.getvalue())
18653b553e0ab2146ef2055c969a1893b453b2023cf4darylm
18663b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def showsymbol(self, symbol):
18673b553e0ab2146ef2055c969a1893b453b2023cf4darylm        target = self.symbols[symbol]
18683b553e0ab2146ef2055c969a1893b453b2023cf4darylm        topic, _, xrefs = target.partition(' ')
18693b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.showtopic(topic, xrefs)
18703b553e0ab2146ef2055c969a1893b453b2023cf4darylm
18713b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def listmodules(self, key=''):
18723b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if key:
18733b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.output.write('''
18743b553e0ab2146ef2055c969a1893b453b2023cf4darylmHere is a list of matching modules.  Enter any module name to get more help.
18753b553e0ab2146ef2055c969a1893b453b2023cf4darylm
18763b553e0ab2146ef2055c969a1893b453b2023cf4darylm''')
18773b553e0ab2146ef2055c969a1893b453b2023cf4darylm            apropos(key)
18783b553e0ab2146ef2055c969a1893b453b2023cf4darylm        else:
18793b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.output.write('''
18803b553e0ab2146ef2055c969a1893b453b2023cf4darylmPlease wait a moment while I gather a list of all available modules...
18813b553e0ab2146ef2055c969a1893b453b2023cf4darylm
18823b553e0ab2146ef2055c969a1893b453b2023cf4darylm''')
18833b553e0ab2146ef2055c969a1893b453b2023cf4darylm            modules = {}
18843b553e0ab2146ef2055c969a1893b453b2023cf4darylm            def callback(path, modname, desc, modules=modules):
18853b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if modname and modname[-9:] == '.__init__':
18863b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    modname = modname[:-9] + ' (package)'
18873b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if find(modname, '.') < 0:
18883b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    modules[modname] = 1
18893b553e0ab2146ef2055c969a1893b453b2023cf4darylm            def onerror(modname):
18903b553e0ab2146ef2055c969a1893b453b2023cf4darylm                callback(None, modname, None)
18913b553e0ab2146ef2055c969a1893b453b2023cf4darylm            ModuleScanner().run(callback, onerror=onerror)
18923b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.list(modules.keys())
18933b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.output.write('''
18943b553e0ab2146ef2055c969a1893b453b2023cf4darylmEnter any module name to get more help.  Or, type "modules spam" to search
18953b553e0ab2146ef2055c969a1893b453b2023cf4darylmfor modules whose descriptions contain the word "spam".
18963b553e0ab2146ef2055c969a1893b453b2023cf4darylm''')
18973b553e0ab2146ef2055c969a1893b453b2023cf4darylm
18983b553e0ab2146ef2055c969a1893b453b2023cf4darylmhelp = Helper()
18993b553e0ab2146ef2055c969a1893b453b2023cf4darylm
19003b553e0ab2146ef2055c969a1893b453b2023cf4darylmclass Scanner:
19013b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """A generic tree iterator."""
19023b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def __init__(self, roots, children, descendp):
19033b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.roots = roots[:]
19043b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.state = []
19053b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.children = children
19063b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.descendp = descendp
19073b553e0ab2146ef2055c969a1893b453b2023cf4darylm
19083b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def next(self):
19093b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if not self.state:
19103b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if not self.roots:
19113b553e0ab2146ef2055c969a1893b453b2023cf4darylm                return None
19123b553e0ab2146ef2055c969a1893b453b2023cf4darylm            root = self.roots.pop(0)
19133b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.state = [(root, self.children(root))]
19143b553e0ab2146ef2055c969a1893b453b2023cf4darylm        node, children = self.state[-1]
19153b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if not children:
19163b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.state.pop()
19173b553e0ab2146ef2055c969a1893b453b2023cf4darylm            return self.next()
19183b553e0ab2146ef2055c969a1893b453b2023cf4darylm        child = children.pop(0)
19193b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if self.descendp(child):
19203b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.state.append((child, self.children(child)))
19213b553e0ab2146ef2055c969a1893b453b2023cf4darylm        return child
19223b553e0ab2146ef2055c969a1893b453b2023cf4darylm
19233b553e0ab2146ef2055c969a1893b453b2023cf4darylm
19243b553e0ab2146ef2055c969a1893b453b2023cf4darylmclass ModuleScanner:
19253b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """An interruptible scanner that searches module synopses."""
19263b553e0ab2146ef2055c969a1893b453b2023cf4darylm
19273b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def run(self, callback, key=None, completer=None, onerror=None):
19283b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if key: key = lower(key)
19293b553e0ab2146ef2055c969a1893b453b2023cf4darylm        self.quit = False
19303b553e0ab2146ef2055c969a1893b453b2023cf4darylm        seen = {}
19313b553e0ab2146ef2055c969a1893b453b2023cf4darylm
19323b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for modname in sys.builtin_module_names:
19333b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if modname != '__main__':
19343b553e0ab2146ef2055c969a1893b453b2023cf4darylm                seen[modname] = 1
19353b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if key is None:
19363b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    callback(None, modname, '')
19373b553e0ab2146ef2055c969a1893b453b2023cf4darylm                else:
19383b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    desc = split(__import__(modname).__doc__ or '', '\n')[0]
19393b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    if find(lower(modname + ' - ' + desc), key) >= 0:
19403b553e0ab2146ef2055c969a1893b453b2023cf4darylm                        callback(None, modname, desc)
19413b553e0ab2146ef2055c969a1893b453b2023cf4darylm
19423b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
19433b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if self.quit:
19443b553e0ab2146ef2055c969a1893b453b2023cf4darylm                break
19453b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if key is None:
19463b553e0ab2146ef2055c969a1893b453b2023cf4darylm                callback(None, modname, '')
19473b553e0ab2146ef2055c969a1893b453b2023cf4darylm            else:
19483b553e0ab2146ef2055c969a1893b453b2023cf4darylm                loader = importer.find_module(modname)
19493b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if hasattr(loader,'get_source'):
19503b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    import StringIO
19513b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    desc = source_synopsis(
19523b553e0ab2146ef2055c969a1893b453b2023cf4darylm                        StringIO.StringIO(loader.get_source(modname))
19533b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    ) or ''
19543b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    if hasattr(loader,'get_filename'):
19553b553e0ab2146ef2055c969a1893b453b2023cf4darylm                        path = loader.get_filename(modname)
19563b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    else:
19573b553e0ab2146ef2055c969a1893b453b2023cf4darylm                        path = None
19583b553e0ab2146ef2055c969a1893b453b2023cf4darylm                else:
19593b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    module = loader.load_module(modname)
19603b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    desc = (module.__doc__ or '').splitlines()[0]
19613b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    path = getattr(module,'__file__',None)
19623b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if find(lower(modname + ' - ' + desc), key) >= 0:
19633b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    callback(path, modname, desc)
19643b553e0ab2146ef2055c969a1893b453b2023cf4darylm
19653b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if completer:
19663b553e0ab2146ef2055c969a1893b453b2023cf4darylm            completer()
19673b553e0ab2146ef2055c969a1893b453b2023cf4darylm
19683b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef apropos(key):
19693b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Print all the one-line module summaries that contain a substring."""
19703b553e0ab2146ef2055c969a1893b453b2023cf4darylm    def callback(path, modname, desc):
19713b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if modname[-9:] == '.__init__':
19723b553e0ab2146ef2055c969a1893b453b2023cf4darylm            modname = modname[:-9] + ' (package)'
19733b553e0ab2146ef2055c969a1893b453b2023cf4darylm        print modname, desc and '- ' + desc
19743b553e0ab2146ef2055c969a1893b453b2023cf4darylm    try: import warnings
19753b553e0ab2146ef2055c969a1893b453b2023cf4darylm    except ImportError: pass
19763b553e0ab2146ef2055c969a1893b453b2023cf4darylm    else: warnings.filterwarnings('ignore') # ignore problems during import
19773b553e0ab2146ef2055c969a1893b453b2023cf4darylm    ModuleScanner().run(callback, key)
19783b553e0ab2146ef2055c969a1893b453b2023cf4darylm
19793b553e0ab2146ef2055c969a1893b453b2023cf4darylm# --------------------------------------------------- web browser interface
19803b553e0ab2146ef2055c969a1893b453b2023cf4darylm
19813b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef serve(port, callback=None, completer=None):
19823b553e0ab2146ef2055c969a1893b453b2023cf4darylm    import BaseHTTPServer, mimetools, select
19833b553e0ab2146ef2055c969a1893b453b2023cf4darylm
19843b553e0ab2146ef2055c969a1893b453b2023cf4darylm    # Patch up mimetools.Message so it doesn't break if rfc822 is reloaded.
19853b553e0ab2146ef2055c969a1893b453b2023cf4darylm    class Message(mimetools.Message):
19863b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def __init__(self, fp, seekable=1):
19873b553e0ab2146ef2055c969a1893b453b2023cf4darylm            Message = self.__class__
19883b553e0ab2146ef2055c969a1893b453b2023cf4darylm            Message.__bases__[0].__bases__[0].__init__(self, fp, seekable)
19893b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.encodingheader = self.getheader('content-transfer-encoding')
19903b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.typeheader = self.getheader('content-type')
19913b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.parsetype()
19923b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.parseplist()
19933b553e0ab2146ef2055c969a1893b453b2023cf4darylm
19943b553e0ab2146ef2055c969a1893b453b2023cf4darylm    class DocHandler(BaseHTTPServer.BaseHTTPRequestHandler):
19953b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def send_document(self, title, contents):
19963b553e0ab2146ef2055c969a1893b453b2023cf4darylm            try:
19973b553e0ab2146ef2055c969a1893b453b2023cf4darylm                self.send_response(200)
19983b553e0ab2146ef2055c969a1893b453b2023cf4darylm                self.send_header('Content-Type', 'text/html')
19993b553e0ab2146ef2055c969a1893b453b2023cf4darylm                self.end_headers()
20003b553e0ab2146ef2055c969a1893b453b2023cf4darylm                self.wfile.write(html.page(title, contents))
20013b553e0ab2146ef2055c969a1893b453b2023cf4darylm            except IOError: pass
20023b553e0ab2146ef2055c969a1893b453b2023cf4darylm
20033b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def do_GET(self):
20043b553e0ab2146ef2055c969a1893b453b2023cf4darylm            path = self.path
20053b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if path[-5:] == '.html': path = path[:-5]
20063b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if path[:1] == '/': path = path[1:]
20073b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if path and path != '.':
20083b553e0ab2146ef2055c969a1893b453b2023cf4darylm                try:
20093b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    obj = locate(path, forceload=1)
20103b553e0ab2146ef2055c969a1893b453b2023cf4darylm                except ErrorDuringImport, value:
20113b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    self.send_document(path, html.escape(str(value)))
20123b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    return
20133b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if obj:
20143b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    self.send_document(describe(obj), html.document(obj, path))
20153b553e0ab2146ef2055c969a1893b453b2023cf4darylm                else:
20163b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    self.send_document(path,
20173b553e0ab2146ef2055c969a1893b453b2023cf4darylm'no Python documentation found for %s' % repr(path))
20183b553e0ab2146ef2055c969a1893b453b2023cf4darylm            else:
20193b553e0ab2146ef2055c969a1893b453b2023cf4darylm                heading = html.heading(
20203b553e0ab2146ef2055c969a1893b453b2023cf4darylm'<big><big><strong>Python: Index of Modules</strong></big></big>',
20213b553e0ab2146ef2055c969a1893b453b2023cf4darylm'#ffffff', '#7799ee')
20223b553e0ab2146ef2055c969a1893b453b2023cf4darylm                def bltinlink(name):
20233b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    return '<a href="%s.html">%s</a>' % (name, name)
20243b553e0ab2146ef2055c969a1893b453b2023cf4darylm                names = filter(lambda x: x != '__main__',
20253b553e0ab2146ef2055c969a1893b453b2023cf4darylm                               sys.builtin_module_names)
20263b553e0ab2146ef2055c969a1893b453b2023cf4darylm                contents = html.multicolumn(names, bltinlink)
20273b553e0ab2146ef2055c969a1893b453b2023cf4darylm                indices = ['<p>' + html.bigsection(
20283b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    'Built-in Modules', '#ffffff', '#ee77aa', contents)]
20293b553e0ab2146ef2055c969a1893b453b2023cf4darylm
20303b553e0ab2146ef2055c969a1893b453b2023cf4darylm                seen = {}
20313b553e0ab2146ef2055c969a1893b453b2023cf4darylm                for dir in sys.path:
20323b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    indices.append(html.index(dir, seen))
20333b553e0ab2146ef2055c969a1893b453b2023cf4darylm                contents = heading + join(indices) + '''<p align=right>
20343b553e0ab2146ef2055c969a1893b453b2023cf4darylm<font color="#909090" face="helvetica, arial"><strong>
20353b553e0ab2146ef2055c969a1893b453b2023cf4darylmpydoc</strong> by Ka-Ping Yee &lt;ping@lfw.org&gt;</font>'''
20363b553e0ab2146ef2055c969a1893b453b2023cf4darylm                self.send_document('Index of Modules', contents)
20373b553e0ab2146ef2055c969a1893b453b2023cf4darylm
20383b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def log_message(self, *args): pass
20393b553e0ab2146ef2055c969a1893b453b2023cf4darylm
20403b553e0ab2146ef2055c969a1893b453b2023cf4darylm    class DocServer(BaseHTTPServer.HTTPServer):
20413b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def __init__(self, port, callback):
20423b553e0ab2146ef2055c969a1893b453b2023cf4darylm            host = 'localhost'
20433b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.address = (host, port)
20443b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.url = 'http://%s:%d/' % (host, port)
20453b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.callback = callback
20463b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.base.__init__(self, self.address, self.handler)
20473b553e0ab2146ef2055c969a1893b453b2023cf4darylm
20483b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def serve_until_quit(self):
20493b553e0ab2146ef2055c969a1893b453b2023cf4darylm            import select
20503b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.quit = False
20513b553e0ab2146ef2055c969a1893b453b2023cf4darylm            while not self.quit:
20523b553e0ab2146ef2055c969a1893b453b2023cf4darylm                rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
20533b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if rd: self.handle_request()
20543b553e0ab2146ef2055c969a1893b453b2023cf4darylm
20553b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def server_activate(self):
20563b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.base.server_activate(self)
20573b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if self.callback: self.callback(self)
20583b553e0ab2146ef2055c969a1893b453b2023cf4darylm
20593b553e0ab2146ef2055c969a1893b453b2023cf4darylm    DocServer.base = BaseHTTPServer.HTTPServer
20603b553e0ab2146ef2055c969a1893b453b2023cf4darylm    DocServer.handler = DocHandler
20613b553e0ab2146ef2055c969a1893b453b2023cf4darylm    DocHandler.MessageClass = Message
20623b553e0ab2146ef2055c969a1893b453b2023cf4darylm    try:
20633b553e0ab2146ef2055c969a1893b453b2023cf4darylm        try:
20643b553e0ab2146ef2055c969a1893b453b2023cf4darylm            DocServer(port, callback).serve_until_quit()
20653b553e0ab2146ef2055c969a1893b453b2023cf4darylm        except (KeyboardInterrupt, select.error):
20663b553e0ab2146ef2055c969a1893b453b2023cf4darylm            pass
20673b553e0ab2146ef2055c969a1893b453b2023cf4darylm    finally:
20683b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if completer: completer()
20693b553e0ab2146ef2055c969a1893b453b2023cf4darylm
20703b553e0ab2146ef2055c969a1893b453b2023cf4darylm# ----------------------------------------------------- graphical interface
20713b553e0ab2146ef2055c969a1893b453b2023cf4darylm
20723b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef gui():
20733b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Graphical interface (starts web server and pops up a control window)."""
20743b553e0ab2146ef2055c969a1893b453b2023cf4darylm    class GUI:
20753b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def __init__(self, window, port=7464):
20763b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.window = window
20773b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.server = None
20783b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.scanner = None
20793b553e0ab2146ef2055c969a1893b453b2023cf4darylm
20803b553e0ab2146ef2055c969a1893b453b2023cf4darylm            import Tkinter
20813b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.server_frm = Tkinter.Frame(window)
20823b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.title_lbl = Tkinter.Label(self.server_frm,
20833b553e0ab2146ef2055c969a1893b453b2023cf4darylm                text='Starting server...\n ')
20843b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.open_btn = Tkinter.Button(self.server_frm,
20853b553e0ab2146ef2055c969a1893b453b2023cf4darylm                text='open browser', command=self.open, state='disabled')
20863b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.quit_btn = Tkinter.Button(self.server_frm,
20873b553e0ab2146ef2055c969a1893b453b2023cf4darylm                text='quit serving', command=self.quit, state='disabled')
20883b553e0ab2146ef2055c969a1893b453b2023cf4darylm
20893b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.search_frm = Tkinter.Frame(window)
20903b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.search_lbl = Tkinter.Label(self.search_frm, text='Search for')
20913b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.search_ent = Tkinter.Entry(self.search_frm)
20923b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.search_ent.bind('<Return>', self.search)
20933b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.stop_btn = Tkinter.Button(self.search_frm,
20943b553e0ab2146ef2055c969a1893b453b2023cf4darylm                text='stop', pady=0, command=self.stop, state='disabled')
20953b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if sys.platform == 'win32':
20963b553e0ab2146ef2055c969a1893b453b2023cf4darylm                # Trying to hide and show this button crashes under Windows.
20973b553e0ab2146ef2055c969a1893b453b2023cf4darylm                self.stop_btn.pack(side='right')
20983b553e0ab2146ef2055c969a1893b453b2023cf4darylm
20993b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.window.title('pydoc')
21003b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.window.protocol('WM_DELETE_WINDOW', self.quit)
21013b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.title_lbl.pack(side='top', fill='x')
21023b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.open_btn.pack(side='left', fill='x', expand=1)
21033b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.quit_btn.pack(side='right', fill='x', expand=1)
21043b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.server_frm.pack(side='top', fill='x')
21053b553e0ab2146ef2055c969a1893b453b2023cf4darylm
21063b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.search_lbl.pack(side='left')
21073b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.search_ent.pack(side='right', fill='x', expand=1)
21083b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.search_frm.pack(side='top', fill='x')
21093b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.search_ent.focus_set()
21103b553e0ab2146ef2055c969a1893b453b2023cf4darylm
21113b553e0ab2146ef2055c969a1893b453b2023cf4darylm            font = ('helvetica', sys.platform == 'win32' and 8 or 10)
21123b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.result_lst = Tkinter.Listbox(window, font=font, height=6)
21133b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.result_lst.bind('<Button-1>', self.select)
21143b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.result_lst.bind('<Double-Button-1>', self.goto)
21153b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.result_scr = Tkinter.Scrollbar(window,
21163b553e0ab2146ef2055c969a1893b453b2023cf4darylm                orient='vertical', command=self.result_lst.yview)
21173b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.result_lst.config(yscrollcommand=self.result_scr.set)
21183b553e0ab2146ef2055c969a1893b453b2023cf4darylm
21193b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.result_frm = Tkinter.Frame(window)
21203b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.goto_btn = Tkinter.Button(self.result_frm,
21213b553e0ab2146ef2055c969a1893b453b2023cf4darylm                text='go to selected', command=self.goto)
21223b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.hide_btn = Tkinter.Button(self.result_frm,
21233b553e0ab2146ef2055c969a1893b453b2023cf4darylm                text='hide results', command=self.hide)
21243b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.goto_btn.pack(side='left', fill='x', expand=1)
21253b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.hide_btn.pack(side='right', fill='x', expand=1)
21263b553e0ab2146ef2055c969a1893b453b2023cf4darylm
21273b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.window.update()
21283b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.minwidth = self.window.winfo_width()
21293b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.minheight = self.window.winfo_height()
21303b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.bigminheight = (self.server_frm.winfo_reqheight() +
21313b553e0ab2146ef2055c969a1893b453b2023cf4darylm                                 self.search_frm.winfo_reqheight() +
21323b553e0ab2146ef2055c969a1893b453b2023cf4darylm                                 self.result_lst.winfo_reqheight() +
21333b553e0ab2146ef2055c969a1893b453b2023cf4darylm                                 self.result_frm.winfo_reqheight())
21343b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.bigwidth, self.bigheight = self.minwidth, self.bigminheight
21353b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.expanded = 0
21363b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
21373b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.window.wm_minsize(self.minwidth, self.minheight)
21383b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.window.tk.willdispatch()
21393b553e0ab2146ef2055c969a1893b453b2023cf4darylm
21403b553e0ab2146ef2055c969a1893b453b2023cf4darylm            import threading
21413b553e0ab2146ef2055c969a1893b453b2023cf4darylm            threading.Thread(
21423b553e0ab2146ef2055c969a1893b453b2023cf4darylm                target=serve, args=(port, self.ready, self.quit)).start()
21433b553e0ab2146ef2055c969a1893b453b2023cf4darylm
21443b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def ready(self, server):
21453b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.server = server
21463b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.title_lbl.config(
21473b553e0ab2146ef2055c969a1893b453b2023cf4darylm                text='Python documentation server at\n' + server.url)
21483b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.open_btn.config(state='normal')
21493b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.quit_btn.config(state='normal')
21503b553e0ab2146ef2055c969a1893b453b2023cf4darylm
21513b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def open(self, event=None, url=None):
21523b553e0ab2146ef2055c969a1893b453b2023cf4darylm            url = url or self.server.url
21533b553e0ab2146ef2055c969a1893b453b2023cf4darylm            try:
21543b553e0ab2146ef2055c969a1893b453b2023cf4darylm                import webbrowser
21553b553e0ab2146ef2055c969a1893b453b2023cf4darylm                webbrowser.open(url)
21563b553e0ab2146ef2055c969a1893b453b2023cf4darylm            except ImportError: # pre-webbrowser.py compatibility
21573b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if sys.platform == 'win32':
21583b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    os.system('start "%s"' % url)
21593b553e0ab2146ef2055c969a1893b453b2023cf4darylm                else:
21603b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    rc = os.system('netscape -remote "openURL(%s)" &' % url)
21613b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    if rc: os.system('netscape "%s" &' % url)
21623b553e0ab2146ef2055c969a1893b453b2023cf4darylm
21633b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def quit(self, event=None):
21643b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if self.server:
21653b553e0ab2146ef2055c969a1893b453b2023cf4darylm                self.server.quit = 1
21663b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.window.quit()
21673b553e0ab2146ef2055c969a1893b453b2023cf4darylm
21683b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def search(self, event=None):
21693b553e0ab2146ef2055c969a1893b453b2023cf4darylm            key = self.search_ent.get()
21703b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.stop_btn.pack(side='right')
21713b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.stop_btn.config(state='normal')
21723b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.search_lbl.config(text='Searching for "%s"...' % key)
21733b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.search_ent.forget()
21743b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.search_lbl.pack(side='left')
21753b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.result_lst.delete(0, 'end')
21763b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.goto_btn.config(state='disabled')
21773b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.expand()
21783b553e0ab2146ef2055c969a1893b453b2023cf4darylm
21793b553e0ab2146ef2055c969a1893b453b2023cf4darylm            import threading
21803b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if self.scanner:
21813b553e0ab2146ef2055c969a1893b453b2023cf4darylm                self.scanner.quit = 1
21823b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.scanner = ModuleScanner()
21833b553e0ab2146ef2055c969a1893b453b2023cf4darylm            threading.Thread(target=self.scanner.run,
21843b553e0ab2146ef2055c969a1893b453b2023cf4darylm                             args=(self.update, key, self.done)).start()
21853b553e0ab2146ef2055c969a1893b453b2023cf4darylm
21863b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def update(self, path, modname, desc):
21873b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if modname[-9:] == '.__init__':
21883b553e0ab2146ef2055c969a1893b453b2023cf4darylm                modname = modname[:-9] + ' (package)'
21893b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.result_lst.insert('end',
21903b553e0ab2146ef2055c969a1893b453b2023cf4darylm                modname + ' - ' + (desc or '(no description)'))
21913b553e0ab2146ef2055c969a1893b453b2023cf4darylm
21923b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def stop(self, event=None):
21933b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if self.scanner:
21943b553e0ab2146ef2055c969a1893b453b2023cf4darylm                self.scanner.quit = 1
21953b553e0ab2146ef2055c969a1893b453b2023cf4darylm                self.scanner = None
21963b553e0ab2146ef2055c969a1893b453b2023cf4darylm
21973b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def done(self):
21983b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.scanner = None
21993b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.search_lbl.config(text='Search for')
22003b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.search_lbl.pack(side='left')
22013b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.search_ent.pack(side='right', fill='x', expand=1)
22023b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if sys.platform != 'win32': self.stop_btn.forget()
22033b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.stop_btn.config(state='disabled')
22043b553e0ab2146ef2055c969a1893b453b2023cf4darylm
22053b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def select(self, event=None):
22063b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.goto_btn.config(state='normal')
22073b553e0ab2146ef2055c969a1893b453b2023cf4darylm
22083b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def goto(self, event=None):
22093b553e0ab2146ef2055c969a1893b453b2023cf4darylm            selection = self.result_lst.curselection()
22103b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if selection:
22113b553e0ab2146ef2055c969a1893b453b2023cf4darylm                modname = split(self.result_lst.get(selection[0]))[0]
22123b553e0ab2146ef2055c969a1893b453b2023cf4darylm                self.open(url=self.server.url + modname + '.html')
22133b553e0ab2146ef2055c969a1893b453b2023cf4darylm
22143b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def collapse(self):
22153b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if not self.expanded: return
22163b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.result_frm.forget()
22173b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.result_scr.forget()
22183b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.result_lst.forget()
22193b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.bigwidth = self.window.winfo_width()
22203b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.bigheight = self.window.winfo_height()
22213b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
22223b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.window.wm_minsize(self.minwidth, self.minheight)
22233b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.expanded = 0
22243b553e0ab2146ef2055c969a1893b453b2023cf4darylm
22253b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def expand(self):
22263b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if self.expanded: return
22273b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.result_frm.pack(side='bottom', fill='x')
22283b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.result_scr.pack(side='right', fill='y')
22293b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.result_lst.pack(side='top', fill='both', expand=1)
22303b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.window.wm_geometry('%dx%d' % (self.bigwidth, self.bigheight))
22313b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.window.wm_minsize(self.minwidth, self.bigminheight)
22323b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.expanded = 1
22333b553e0ab2146ef2055c969a1893b453b2023cf4darylm
22343b553e0ab2146ef2055c969a1893b453b2023cf4darylm        def hide(self, event=None):
22353b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.stop()
22363b553e0ab2146ef2055c969a1893b453b2023cf4darylm            self.collapse()
22373b553e0ab2146ef2055c969a1893b453b2023cf4darylm
22383b553e0ab2146ef2055c969a1893b453b2023cf4darylm    import Tkinter
22393b553e0ab2146ef2055c969a1893b453b2023cf4darylm    try:
22403b553e0ab2146ef2055c969a1893b453b2023cf4darylm        root = Tkinter.Tk()
22413b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # Tk will crash if pythonw.exe has an XP .manifest
22423b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # file and the root has is not destroyed explicitly.
22433b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # If the problem is ever fixed in Tk, the explicit
22443b553e0ab2146ef2055c969a1893b453b2023cf4darylm        # destroy can go.
22453b553e0ab2146ef2055c969a1893b453b2023cf4darylm        try:
22463b553e0ab2146ef2055c969a1893b453b2023cf4darylm            gui = GUI(root)
22473b553e0ab2146ef2055c969a1893b453b2023cf4darylm            root.mainloop()
22483b553e0ab2146ef2055c969a1893b453b2023cf4darylm        finally:
22493b553e0ab2146ef2055c969a1893b453b2023cf4darylm            root.destroy()
22503b553e0ab2146ef2055c969a1893b453b2023cf4darylm    except KeyboardInterrupt:
22513b553e0ab2146ef2055c969a1893b453b2023cf4darylm        pass
22523b553e0ab2146ef2055c969a1893b453b2023cf4darylm
22533b553e0ab2146ef2055c969a1893b453b2023cf4darylm# -------------------------------------------------- command-line interface
22543b553e0ab2146ef2055c969a1893b453b2023cf4darylm
22553b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef ispath(x):
22563b553e0ab2146ef2055c969a1893b453b2023cf4darylm    return isinstance(x, str) and find(x, os.sep) >= 0
22573b553e0ab2146ef2055c969a1893b453b2023cf4darylm
22583b553e0ab2146ef2055c969a1893b453b2023cf4darylmdef cli():
22593b553e0ab2146ef2055c969a1893b453b2023cf4darylm    """Command-line interface (looks at sys.argv to decide what to do)."""
22603b553e0ab2146ef2055c969a1893b453b2023cf4darylm    import getopt
22613b553e0ab2146ef2055c969a1893b453b2023cf4darylm    class BadUsage: pass
22623b553e0ab2146ef2055c969a1893b453b2023cf4darylm
22633b553e0ab2146ef2055c969a1893b453b2023cf4darylm    # Scripts don't get the current directory in their path by default
22643b553e0ab2146ef2055c969a1893b453b2023cf4darylm    # unless they are run with the '-m' switch
22653b553e0ab2146ef2055c969a1893b453b2023cf4darylm    if '' not in sys.path:
22663b553e0ab2146ef2055c969a1893b453b2023cf4darylm        scriptdir = os.path.dirname(sys.argv[0])
22673b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if scriptdir in sys.path:
22683b553e0ab2146ef2055c969a1893b453b2023cf4darylm            sys.path.remove(scriptdir)
22693b553e0ab2146ef2055c969a1893b453b2023cf4darylm        sys.path.insert(0, '.')
22703b553e0ab2146ef2055c969a1893b453b2023cf4darylm
22713b553e0ab2146ef2055c969a1893b453b2023cf4darylm    try:
22723b553e0ab2146ef2055c969a1893b453b2023cf4darylm        opts, args = getopt.getopt(sys.argv[1:], 'gk:p:w')
22733b553e0ab2146ef2055c969a1893b453b2023cf4darylm        writing = 0
22743b553e0ab2146ef2055c969a1893b453b2023cf4darylm
22753b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for opt, val in opts:
22763b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if opt == '-g':
22773b553e0ab2146ef2055c969a1893b453b2023cf4darylm                gui()
22783b553e0ab2146ef2055c969a1893b453b2023cf4darylm                return
22793b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if opt == '-k':
22803b553e0ab2146ef2055c969a1893b453b2023cf4darylm                apropos(val)
22813b553e0ab2146ef2055c969a1893b453b2023cf4darylm                return
22823b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if opt == '-p':
22833b553e0ab2146ef2055c969a1893b453b2023cf4darylm                try:
22843b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    port = int(val)
22853b553e0ab2146ef2055c969a1893b453b2023cf4darylm                except ValueError:
22863b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    raise BadUsage
22873b553e0ab2146ef2055c969a1893b453b2023cf4darylm                def ready(server):
22883b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    print 'pydoc server ready at %s' % server.url
22893b553e0ab2146ef2055c969a1893b453b2023cf4darylm                def stopped():
22903b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    print 'pydoc server stopped'
22913b553e0ab2146ef2055c969a1893b453b2023cf4darylm                serve(port, ready, stopped)
22923b553e0ab2146ef2055c969a1893b453b2023cf4darylm                return
22933b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if opt == '-w':
22943b553e0ab2146ef2055c969a1893b453b2023cf4darylm                writing = 1
22953b553e0ab2146ef2055c969a1893b453b2023cf4darylm
22963b553e0ab2146ef2055c969a1893b453b2023cf4darylm        if not args: raise BadUsage
22973b553e0ab2146ef2055c969a1893b453b2023cf4darylm        for arg in args:
22983b553e0ab2146ef2055c969a1893b453b2023cf4darylm            if ispath(arg) and not os.path.exists(arg):
22993b553e0ab2146ef2055c969a1893b453b2023cf4darylm                print 'file %r does not exist' % arg
23003b553e0ab2146ef2055c969a1893b453b2023cf4darylm                break
23013b553e0ab2146ef2055c969a1893b453b2023cf4darylm            try:
23023b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if ispath(arg) and os.path.isfile(arg):
23033b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    arg = importfile(arg)
23043b553e0ab2146ef2055c969a1893b453b2023cf4darylm                if writing:
23053b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    if ispath(arg) and os.path.isdir(arg):
23063b553e0ab2146ef2055c969a1893b453b2023cf4darylm                        writedocs(arg)
23073b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    else:
23083b553e0ab2146ef2055c969a1893b453b2023cf4darylm                        writedoc(arg)
23093b553e0ab2146ef2055c969a1893b453b2023cf4darylm                else:
23103b553e0ab2146ef2055c969a1893b453b2023cf4darylm                    help.help(arg)
23113b553e0ab2146ef2055c969a1893b453b2023cf4darylm            except ErrorDuringImport, value:
23123b553e0ab2146ef2055c969a1893b453b2023cf4darylm                print value
23133b553e0ab2146ef2055c969a1893b453b2023cf4darylm
23143b553e0ab2146ef2055c969a1893b453b2023cf4darylm    except (getopt.error, BadUsage):
23153b553e0ab2146ef2055c969a1893b453b2023cf4darylm        cmd = os.path.basename(sys.argv[0])
23163b553e0ab2146ef2055c969a1893b453b2023cf4darylm        print """pydoc - the Python documentation tool
23173b553e0ab2146ef2055c969a1893b453b2023cf4darylm
23183b553e0ab2146ef2055c969a1893b453b2023cf4darylm%s <name> ...
23193b553e0ab2146ef2055c969a1893b453b2023cf4darylm    Show text documentation on something.  <name> may be the name of a
23203b553e0ab2146ef2055c969a1893b453b2023cf4darylm    Python keyword, topic, function, module, or package, or a dotted
23213b553e0ab2146ef2055c969a1893b453b2023cf4darylm    reference to a class or function within a module or module in a
23223b553e0ab2146ef2055c969a1893b453b2023cf4darylm    package.  If <name> contains a '%s', it is used as the path to a
23233b553e0ab2146ef2055c969a1893b453b2023cf4darylm    Python source file to document. If name is 'keywords', 'topics',
23243b553e0ab2146ef2055c969a1893b453b2023cf4darylm    or 'modules', a listing of these things is displayed.
23253b553e0ab2146ef2055c969a1893b453b2023cf4darylm
23263b553e0ab2146ef2055c969a1893b453b2023cf4darylm%s -k <keyword>
23273b553e0ab2146ef2055c969a1893b453b2023cf4darylm    Search for a keyword in the synopsis lines of all available modules.
23283b553e0ab2146ef2055c969a1893b453b2023cf4darylm
23293b553e0ab2146ef2055c969a1893b453b2023cf4darylm%s -p <port>
23303b553e0ab2146ef2055c969a1893b453b2023cf4darylm    Start an HTTP server on the given port on the local machine.
23313b553e0ab2146ef2055c969a1893b453b2023cf4darylm
23323b553e0ab2146ef2055c969a1893b453b2023cf4darylm%s -g
23333b553e0ab2146ef2055c969a1893b453b2023cf4darylm    Pop up a graphical interface for finding and serving documentation.
23343b553e0ab2146ef2055c969a1893b453b2023cf4darylm
23353b553e0ab2146ef2055c969a1893b453b2023cf4darylm%s -w <name> ...
23363b553e0ab2146ef2055c969a1893b453b2023cf4darylm    Write out the HTML documentation for a module to a file in the current
23373b553e0ab2146ef2055c969a1893b453b2023cf4darylm    directory.  If <name> contains a '%s', it is treated as a filename; if
23383b553e0ab2146ef2055c969a1893b453b2023cf4darylm    it names a directory, documentation is written for all the contents.
23393b553e0ab2146ef2055c969a1893b453b2023cf4darylm""" % (cmd, os.sep, cmd, cmd, cmd, cmd, os.sep)
23403b553e0ab2146ef2055c969a1893b453b2023cf4darylm
23413b553e0ab2146ef2055c969a1893b453b2023cf4darylmif __name__ == '__main__': cli()
2342