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