2 # -*- coding: latin-1 -*-
3 """Generate Python documentation in HTML or text for interactive use.
5 In the Python interpreter, do "from pydoc import help" to provide online
6 help. Calling help(thing) on a Python object documents the object.
8 Or, at the shell command line outside of Python:
10 Run "pydoc <name>" to show documentation on something. <name> may be
11 the name of a function, module, package, or a dotted reference to a
12 class or function within a module or module in a package. If the
13 argument contains a path segment delimiter (e.g. slash on Unix,
14 backslash on Windows) it is treated as the path to a Python source file.
16 Run "pydoc -k <keyword>" to search for a keyword in the synopsis lines
17 of all available modules.
19 Run "pydoc -p <port>" to start an HTTP server on a given port on the
20 local machine to generate documentation web pages.
22 For platforms without a command line, "pydoc -g" starts the HTTP server
23 and also pops up a little window for controlling it.
25 Run "pydoc -w <name>" to write out the HTML documentation for a module
26 to a file named "<name>.html".
28 Module docs for core modules are assumed to be in
30 http://docs.python.org/library/
32 This can be overridden by setting the PYTHONDOCS environment variable
33 to a different URL or to a local directory containing the Library
34 Reference Manual pages.
37 __author__ = "Ka-Ping Yee <ping@lfw.org>"
38 __date__ = "26 February 2001"
40 __version__ = "$Revision: 88564 $"
41 __credits__ = """Guido van Rossum, for an excellent programming language.
42 Tommy Burnette, the original creator of manpy.
43 Paul Prescod, for all his work on onlinehelp.
44 Richard Chamberlain, for the first implementation of textdoc.
47 # Known bugs that can't be fixed here:
48 # - imp.load_module() cannot be prevented from clobbering existing
49 # loaded modules, so calling synopsis() on a binary module file
50 # changes the contents of any existing module with the same name.
51 # - If the __file__ attribute on a module is a relative path and
52 # the current directory is changed with os.chdir(), an incorrect
53 # path will be displayed.
55 import sys, imp, os, re, types, inspect, __builtin__, pkgutil, warnings
57 from string import expandtabs, find, join, lower, split, strip, rfind, rstrip
58 from traceback import extract_tb
60 from collections import deque
62 # Python 2.3 compatibility
67 # --------------------------------------------------------- common routines
70 """Convert sys.path into a list of absolute, existing, unique paths."""
74 dir = os.path.abspath(dir or '.')
75 normdir = os.path.normcase(dir)
76 if normdir not in normdirs and os.path.isdir(dir):
78 normdirs.append(normdir)
82 """Get the doc string or comments for an object."""
83 result = inspect.getdoc(object) or inspect.getcomments(object)
84 return result and re.sub('^ *\n', '', rstrip(result)) or ''
87 """Split a doc string into a synopsis line (if any) and the rest."""
88 lines = split(strip(doc), '\n')
91 elif len(lines) >= 2 and not rstrip(lines[1]):
92 return lines[0], join(lines[2:], '\n')
93 return '', join(lines, '\n')
95 def classname(object, modname):
96 """Get a class name and qualify it with a module name if necessary."""
97 name = object.__name__
98 if object.__module__ != modname:
99 name = object.__module__ + '.' + name
103 """Check if an object is of a type that probably means it's data."""
104 return not (inspect.ismodule(object) or inspect.isclass(object) or
105 inspect.isroutine(object) or inspect.isframe(object) or
106 inspect.istraceback(object) or inspect.iscode(object))
108 def replace(text, *pairs):
109 """Do a series of global replacements on a string."""
111 text = join(split(text, pairs[0]), pairs[1])
115 def cram(text, maxlen):
116 """Omit part of a string if needed to make it fit in a maximum length."""
117 if len(text) > maxlen:
118 pre = max(0, (maxlen-3)//2)
119 post = max(0, maxlen-3-pre)
120 return text[:pre] + '...' + text[len(text)-post:]
123 _re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
125 """Remove the hexadecimal id from a Python object representation."""
126 # The behaviour of %p is implementation-dependent in terms of case.
127 return _re_stripid.sub(r'\1', text)
129 def _is_some_method(obj):
130 return inspect.ismethod(obj) or inspect.ismethoddescriptor(obj)
134 for key, value in inspect.getmembers(cl, _is_some_method):
136 for base in cl.__bases__:
137 methods.update(allmethods(base)) # all your base are belong to us
138 for key in methods.keys():
139 methods[key] = getattr(cl, key)
142 def _split_list(s, predicate):
143 """Split sequence s via predicate, and return pair ([true], [false]).
145 The return value is a 2-tuple of lists,
146 ([x for x in s if predicate(x)],
147 [x for x in s if not predicate(x)])
159 def visiblename(name, all=None, obj=None):
160 """Decide whether to show documentation on a variable."""
161 # Certain special names are redundant.
162 _hidden_names = ('__builtins__', '__doc__', '__file__', '__path__',
163 '__module__', '__name__', '__slots__', '__package__')
164 if name in _hidden_names: return 0
165 # Private names are hidden, but special names are displayed.
166 if name.startswith('__') and name.endswith('__'): return 1
167 # Namedtuples have public fields and methods with a single leading underscore
168 if name.startswith('_') and hasattr(obj, '_fields'):
171 # only document that which the programmer exported in __all__
174 return not name.startswith('_')
176 def classify_class_attrs(object):
177 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
179 name, kind, cls, value = data
180 if inspect.isdatadescriptor(value):
181 kind = 'data descriptor'
182 return name, kind, cls, value
183 return map(fixup, inspect.classify_class_attrs(object))
185 # ----------------------------------------------------- module manipulation
188 """Guess whether a path refers to a package directory."""
189 if os.path.isdir(path):
190 for ext in ('.py', '.pyc', '.pyo'):
191 if os.path.isfile(os.path.join(path, '__init__' + ext)):
195 def source_synopsis(file):
196 line = file.readline()
197 while line[:1] == '#' or not strip(line):
198 line = file.readline()
201 if line[:4] == 'r"""': line = line[1:]
202 if line[:3] == '"""':
204 if line[-1:] == '\\': line = line[:-1]
205 while not strip(line):
206 line = file.readline()
208 result = strip(split(line, '"""')[0])
212 def synopsis(filename, cache={}):
213 """Get the one-line summary out of a module file."""
214 mtime = os.stat(filename).st_mtime
215 lastupdate, result = cache.get(filename, (None, None))
216 if lastupdate is None or lastupdate < mtime:
217 info = inspect.getmoduleinfo(filename)
219 file = open(filename)
221 # module can't be opened, so skip it
223 if info and 'b' in info[2]: # binary modules have to be imported
224 try: module = imp.load_module('__temp__', file, filename, info[1:])
226 result = (module.__doc__ or '').splitlines()[0]
227 del sys.modules['__temp__']
228 else: # text modules can be directly examined
229 result = source_synopsis(file)
231 cache[filename] = (mtime, result)
234 class ErrorDuringImport(Exception):
235 """Errors that occurred while trying to import something to document it."""
236 def __init__(self, filename, exc_info):
237 exc, value, tb = exc_info
238 self.filename = filename
245 if type(exc) is types.ClassType:
247 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
249 def importfile(path):
250 """Import a Python source file or compiled file given its path."""
251 magic = imp.get_magic()
252 file = open(path, 'r')
253 if file.read(len(magic)) == magic:
254 kind = imp.PY_COMPILED
258 filename = os.path.basename(path)
259 name, ext = os.path.splitext(filename)
260 file = open(path, 'r')
262 module = imp.load_module(name, file, path, (ext, 'r', kind))
264 raise ErrorDuringImport(path, sys.exc_info())
268 def safeimport(path, forceload=0, cache={}):
269 """Import a module; handle errors; return None if the module isn't found.
271 If the module *is* found but an exception occurs, it's wrapped in an
272 ErrorDuringImport exception and reraised. Unlike __import__, if a
273 package path is specified, the module at the end of the path is returned,
274 not the package at the beginning. If the optional 'forceload' argument
275 is 1, we reload the module from disk (unless it's a dynamic extension)."""
277 # If forceload is 1 and the module has been previously loaded from
278 # disk, we always have to reload the module. Checking the file's
279 # mtime isn't good enough (e.g. the module could contain a class
280 # that inherits from another module that has changed).
281 if forceload and path in sys.modules:
282 if path not in sys.builtin_module_names:
283 # Avoid simply calling reload() because it leaves names in
284 # the currently loaded module lying around if they're not
285 # defined in the new source file. Instead, remove the
286 # module from sys.modules and re-import. Also remove any
287 # submodules because they won't appear in the newly loaded
288 # module's namespace if they're already in sys.modules.
289 subs = [m for m in sys.modules if m.startswith(path + '.')]
290 for key in [path] + subs:
291 # Prevent garbage collection.
292 cache[key] = sys.modules[key]
294 module = __import__(path)
296 # Did the error occur before or after the module was found?
297 (exc, value, tb) = info = sys.exc_info()
298 if path in sys.modules:
299 # An error occurred while executing the imported module.
300 raise ErrorDuringImport(sys.modules[path].__file__, info)
301 elif exc is SyntaxError:
302 # A SyntaxError occurred before we could execute the module.
303 raise ErrorDuringImport(value.filename, info)
304 elif exc is ImportError and extract_tb(tb)[-1][2]=='safeimport':
305 # The import error occurred directly in this function,
306 # which means there is no such module in the path.
309 # Some other error occurred during the importing process.
310 raise ErrorDuringImport(path, sys.exc_info())
311 for part in split(path, '.')[1:]:
312 try: module = getattr(module, part)
313 except AttributeError: return None
316 # ---------------------------------------------------- formatter base class
319 def document(self, object, name=None, *args):
320 """Generate documentation for an object."""
321 args = (object, name) + args
322 # 'try' clause is to attempt to handle the possibility that inspect
323 # identifies something in a way that pydoc itself has issues handling;
324 # think 'super' and how it is a descriptor (which raises the exception
325 # by lacking a __name__ attribute) and an instance.
326 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
327 if inspect.ismemberdescriptor(object): return self.docdata(*args)
329 if inspect.ismodule(object): return self.docmodule(*args)
330 if inspect.isclass(object): return self.docclass(*args)
331 if inspect.isroutine(object): return self.docroutine(*args)
332 except AttributeError:
334 if isinstance(object, property): return self.docproperty(*args)
335 return self.docother(*args)
337 def fail(self, object, name=None, *args):
338 """Raise an exception for unimplemented types."""
339 message = "don't know how to document object%s of type %s" % (
340 name and ' ' + repr(name), type(object).__name__)
341 raise TypeError, message
343 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
345 def getdocloc(self, object):
346 """Return the location of module docs or None"""
349 file = inspect.getabsfile(object)
353 docloc = os.environ.get("PYTHONDOCS",
354 "http://docs.python.org/library")
355 basedir = os.path.join(sys.exec_prefix, "lib",
356 "python"+sys.version[0:3])
357 if (isinstance(object, type(os)) and
358 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
359 'marshal', 'posix', 'signal', 'sys',
360 'thread', 'zipimport') or
361 (file.startswith(basedir) and
362 not file.startswith(os.path.join(basedir, 'site-packages')))) and
363 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
364 if docloc.startswith("http://"):
365 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
367 docloc = os.path.join(docloc, object.__name__ + ".html")
372 # -------------------------------------------- HTML documentation generator
374 class HTMLRepr(Repr):
375 """Class for safely making an HTML representation of a Python object."""
378 self.maxlist = self.maxtuple = 20
380 self.maxstring = self.maxother = 100
382 def escape(self, text):
383 return replace(text, '&', '&', '<', '<', '>', '>')
385 def repr(self, object):
386 return Repr.repr(self, object)
388 def repr1(self, x, level):
389 if hasattr(type(x), '__name__'):
390 methodname = 'repr_' + join(split(type(x).__name__), '_')
391 if hasattr(self, methodname):
392 return getattr(self, methodname)(x, level)
393 return self.escape(cram(stripid(repr(x)), self.maxother))
395 def repr_string(self, x, level):
396 test = cram(x, self.maxstring)
397 testrepr = repr(test)
398 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
399 # Backslashes are only literal in the string and are never
400 # needed to make any special characters, so show a raw string.
401 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
402 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
403 r'<font color="#c040c0">\1</font>',
404 self.escape(testrepr))
406 repr_str = repr_string
408 def repr_instance(self, x, level):
410 return self.escape(cram(stripid(repr(x)), self.maxstring))
412 return self.escape('<%s instance>' % x.__class__.__name__)
414 repr_unicode = repr_string
417 """Formatter class for HTML documentation."""
419 # ------------------------------------------- HTML formatting utilities
421 _repr_instance = HTMLRepr()
422 repr = _repr_instance.repr
423 escape = _repr_instance.escape
425 def page(self, title, contents):
426 """Format an HTML page."""
428 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
429 <html><head><title>Python: %s</title>
430 </head><body bgcolor="#f0f0f8">
432 </body></html>''' % (title, contents)
434 def heading(self, title, fgcol, bgcol, extras=''):
435 """Format a page heading."""
437 <table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
439 <td valign=bottom> <br>
440 <font color="%s" face="helvetica, arial"> <br>%s</font></td
441 ><td align=right valign=bottom
442 ><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
443 ''' % (bgcol, fgcol, title, fgcol, extras or ' ')
445 def section(self, title, fgcol, bgcol, contents, width=6,
446 prelude='', marginalia=None, gap=' '):
447 """Format a section with a heading."""
448 if marginalia is None:
449 marginalia = '<tt>' + ' ' * width + '</tt>'
451 <table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
453 <td colspan=3 valign=bottom> <br>
454 <font color="%s" face="helvetica, arial">%s</font></td></tr>
455 ''' % (bgcol, fgcol, title)
457 result = result + '''
458 <tr bgcolor="%s"><td rowspan=2>%s</td>
459 <td colspan=2>%s</td></tr>
460 <tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
462 result = result + '''
463 <tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
465 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
467 def bigsection(self, title, *args):
468 """Format a section with a big heading."""
469 title = '<big><strong>%s</strong></big>' % title
470 return self.section(title, *args)
472 def preformat(self, text):
473 """Format literal preformatted text."""
474 text = self.escape(expandtabs(text))
475 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
476 ' ', ' ', '\n', '<br>\n')
478 def multicolumn(self, list, format, cols=4):
479 """Format a list of items into a multi-column list."""
481 rows = (len(list)+cols-1)//cols
482 for col in range(cols):
483 result = result + '<td width="%d%%" valign=top>' % (100//cols)
484 for i in range(rows*col, rows*col+rows):
486 result = result + format(list[i]) + '<br>\n'
487 result = result + '</td>'
488 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
490 def grey(self, text): return '<font color="#909090">%s</font>' % text
492 def namelink(self, name, *dicts):
493 """Make a link for an identifier, given name-to-URL mappings."""
496 return '<a href="%s">%s</a>' % (dict[name], name)
499 def classlink(self, object, modname):
500 """Make a link for a class."""
501 name, module = object.__name__, sys.modules.get(object.__module__)
502 if hasattr(module, name) and getattr(module, name) is object:
503 return '<a href="%s.html#%s">%s</a>' % (
504 module.__name__, name, classname(object, modname))
505 return classname(object, modname)
507 def modulelink(self, object):
508 """Make a link for a module."""
509 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
511 def modpkglink(self, data):
512 """Make a link for a module or package to display in an index."""
513 name, path, ispackage, shadowed = data
515 return self.grey(name)
517 url = '%s.%s.html' % (path, name)
519 url = '%s.html' % name
521 text = '<strong>%s</strong> (package)' % name
524 return '<a href="%s">%s</a>' % (url, text)
526 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
527 """Mark up some plain text, given a context of symbols to look for.
528 Each context dictionary maps object names to anchor names."""
529 escape = escape or self.escape
532 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
537 match = pattern.search(text, here)
539 start, end = match.span()
540 results.append(escape(text[here:start]))
542 all, scheme, rfc, pep, selfdot, name = match.groups()
544 url = escape(all).replace('"', '"')
545 results.append('<a href="%s">%s</a>' % (url, url))
547 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
548 results.append('<a href="%s">%s</a>' % (url, escape(all)))
550 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
551 results.append('<a href="%s">%s</a>' % (url, escape(all)))
552 elif text[end:end+1] == '(':
553 results.append(self.namelink(name, methods, funcs, classes))
555 results.append('self.<strong>%s</strong>' % name)
557 results.append(self.namelink(name, classes))
559 results.append(escape(text[here:]))
560 return join(results, '')
562 # ---------------------------------------------- type-specific routines
564 def formattree(self, tree, modname, parent=None):
565 """Produce HTML for a class tree as given by inspect.getclasstree()."""
568 if type(entry) is type(()):
570 result = result + '<dt><font face="helvetica, arial">'
571 result = result + self.classlink(c, modname)
572 if bases and bases != (parent,):
575 parents.append(self.classlink(base, modname))
576 result = result + '(' + join(parents, ', ') + ')'
577 result = result + '\n</font></dt>'
578 elif type(entry) is type([]):
579 result = result + '<dd>\n%s</dd>\n' % self.formattree(
581 return '<dl>\n%s</dl>\n' % result
583 def docmodule(self, object, name=None, mod=None, *ignored):
584 """Produce HTML documentation for a module object."""
585 name = object.__name__ # ignore the passed-in name
588 except AttributeError:
590 parts = split(name, '.')
592 for i in range(len(parts)-1):
594 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
595 (join(parts[:i+1], '.'), parts[i]))
596 linkedname = join(links + parts[-1:], '.')
597 head = '<big><big><strong>%s</strong></big></big>' % linkedname
599 path = inspect.getabsfile(object)
601 if sys.platform == 'win32':
603 url = nturl2path.pathname2url(path)
604 filelink = '<a href="file:%s">%s</a>' % (url, path)
606 filelink = '(built-in)'
608 if hasattr(object, '__version__'):
609 version = str(object.__version__)
610 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
611 version = strip(version[11:-1])
612 info.append('version %s' % self.escape(version))
613 if hasattr(object, '__date__'):
614 info.append(self.escape(str(object.__date__)))
616 head = head + ' (%s)' % join(info, ', ')
617 docloc = self.getdocloc(object)
618 if docloc is not None:
619 docloc = '<br><a href="%(docloc)s">Module Docs</a>' % locals()
622 result = self.heading(
623 head, '#ffffff', '#7799ee',
624 '<a href=".">index</a><br>' + filelink + docloc)
626 modules = inspect.getmembers(object, inspect.ismodule)
628 classes, cdict = [], {}
629 for key, value in inspect.getmembers(object, inspect.isclass):
630 # if __all__ exists, believe it. Otherwise use old heuristic.
631 if (all is not None or
632 (inspect.getmodule(value) or object) is object):
633 if visiblename(key, all, object):
634 classes.append((key, value))
635 cdict[key] = cdict[value] = '#' + key
636 for key, value in classes:
637 for base in value.__bases__:
638 key, modname = base.__name__, base.__module__
639 module = sys.modules.get(modname)
640 if modname != name and module and hasattr(module, key):
641 if getattr(module, key) is base:
643 cdict[key] = cdict[base] = modname + '.html#' + key
644 funcs, fdict = [], {}
645 for key, value in inspect.getmembers(object, inspect.isroutine):
646 # if __all__ exists, believe it. Otherwise use old heuristic.
647 if (all is not None or
648 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
649 if visiblename(key, all, object):
650 funcs.append((key, value))
651 fdict[key] = '#-' + key
652 if inspect.isfunction(value): fdict[value] = fdict[key]
654 for key, value in inspect.getmembers(object, isdata):
655 if visiblename(key, all, object):
656 data.append((key, value))
658 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
659 doc = doc and '<tt>%s</tt>' % doc
660 result = result + '<p>%s</p>\n' % doc
662 if hasattr(object, '__path__'):
664 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
665 modpkgs.append((modname, name, ispkg, 0))
667 contents = self.multicolumn(modpkgs, self.modpkglink)
668 result = result + self.bigsection(
669 'Package Contents', '#ffffff', '#aa55cc', contents)
671 contents = self.multicolumn(
672 modules, lambda key_value, s=self: s.modulelink(key_value[1]))
673 result = result + self.bigsection(
674 'Modules', '#ffffff', '#aa55cc', contents)
677 classlist = map(lambda key_value: key_value[1], classes)
679 self.formattree(inspect.getclasstree(classlist, 1), name)]
680 for key, value in classes:
681 contents.append(self.document(value, key, name, fdict, cdict))
682 result = result + self.bigsection(
683 'Classes', '#ffffff', '#ee77aa', join(contents))
686 for key, value in funcs:
687 contents.append(self.document(value, key, name, fdict, cdict))
688 result = result + self.bigsection(
689 'Functions', '#ffffff', '#eeaa77', join(contents))
692 for key, value in data:
693 contents.append(self.document(value, key))
694 result = result + self.bigsection(
695 'Data', '#ffffff', '#55aa55', join(contents, '<br>\n'))
696 if hasattr(object, '__author__'):
697 contents = self.markup(str(object.__author__), self.preformat)
698 result = result + self.bigsection(
699 'Author', '#ffffff', '#7799ee', contents)
700 if hasattr(object, '__credits__'):
701 contents = self.markup(str(object.__credits__), self.preformat)
702 result = result + self.bigsection(
703 'Credits', '#ffffff', '#7799ee', contents)
707 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
709 """Produce HTML documentation for a class object."""
710 realname = object.__name__
711 name = name or realname
712 bases = object.__bases__
715 push = contents.append
717 # Cute little class to pump out a horizontal rule between sections.
718 class HorizontalRule:
725 hr = HorizontalRule()
727 # List the mro, if non-trivial.
728 mro = deque(inspect.getmro(object))
731 push('<dl><dt>Method resolution order:</dt>\n')
733 push('<dd>%s</dd>\n' % self.classlink(base,
737 def spill(msg, attrs, predicate):
738 ok, attrs = _split_list(attrs, predicate)
742 for name, kind, homecls, value in ok:
744 value = getattr(object, name)
746 # Some descriptors may meet a failure in their __get__.
748 push(self._docdescriptor(name, value, mod))
750 push(self.document(value, name, mod,
751 funcs, classes, mdict, object))
755 def spilldescriptors(msg, attrs, predicate):
756 ok, attrs = _split_list(attrs, predicate)
760 for name, kind, homecls, value in ok:
761 push(self._docdescriptor(name, value, mod))
764 def spilldata(msg, attrs, predicate):
765 ok, attrs = _split_list(attrs, predicate)
769 for name, kind, homecls, value in ok:
770 base = self.docother(getattr(object, name), name, mod)
771 if (hasattr(value, '__call__') or
772 inspect.isdatadescriptor(value)):
773 doc = getattr(value, "__doc__", None)
777 push('<dl><dt>%s</dl>\n' % base)
779 doc = self.markup(getdoc(value), self.preformat,
780 funcs, classes, mdict)
781 doc = '<dd><tt>%s</tt>' % doc
782 push('<dl><dt>%s%s</dl>\n' % (base, doc))
786 attrs = filter(lambda data: visiblename(data[0], obj=object),
787 classify_class_attrs(object))
789 for key, kind, homecls, value in attrs:
790 mdict[key] = anchor = '#' + name + '-' + key
792 value = getattr(object, name)
794 # Some descriptors may meet a failure in their __get__.
798 # The value may not be hashable (e.g., a data attr with
799 # a dict or list value).
800 mdict[value] = anchor
806 thisclass = mro.popleft()
808 thisclass = attrs[0][2]
809 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
811 if thisclass is __builtin__.object:
814 elif thisclass is object:
817 tag = 'inherited from %s' % self.classlink(thisclass,
821 # Sort attrs by name.
823 attrs.sort(key=lambda t: t[0])
825 attrs.sort(lambda t1, t2: cmp(t1[0], t2[0])) # 2.3 compat
827 # Pump out the attrs, segregated by kind.
828 attrs = spill('Methods %s' % tag, attrs,
829 lambda t: t[1] == 'method')
830 attrs = spill('Class methods %s' % tag, attrs,
831 lambda t: t[1] == 'class method')
832 attrs = spill('Static methods %s' % tag, attrs,
833 lambda t: t[1] == 'static method')
834 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
835 lambda t: t[1] == 'data descriptor')
836 attrs = spilldata('Data and other attributes %s' % tag, attrs,
837 lambda t: t[1] == 'data')
841 contents = ''.join(contents)
844 title = '<a name="%s">class <strong>%s</strong></a>' % (
847 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
848 name, name, realname)
852 parents.append(self.classlink(base, object.__module__))
853 title = title + '(%s)' % join(parents, ', ')
854 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
855 doc = doc and '<tt>%s<br> </tt>' % doc
857 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
859 def formatvalue(self, object):
860 """Format an argument default value as text."""
861 return self.grey('=' + self.repr(object))
863 def docroutine(self, object, name=None, mod=None,
864 funcs={}, classes={}, methods={}, cl=None):
865 """Produce HTML documentation for a function or method object."""
866 realname = object.__name__
867 name = name or realname
868 anchor = (cl and cl.__name__ or '') + '-' + name
871 if inspect.ismethod(object):
872 imclass = object.im_class
874 if imclass is not cl:
875 note = ' from ' + self.classlink(imclass, mod)
877 if object.im_self is not None:
878 note = ' method of %s instance' % self.classlink(
879 object.im_self.__class__, mod)
881 note = ' unbound %s method' % self.classlink(imclass,mod)
882 object = object.im_func
885 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
887 if (cl and realname in cl.__dict__ and
888 cl.__dict__[realname] is object):
889 reallink = '<a href="#%s">%s</a>' % (
890 cl.__name__ + '-' + realname, realname)
894 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
895 anchor, name, reallink)
896 if inspect.isfunction(object):
897 args, varargs, varkw, defaults = inspect.getargspec(object)
898 argspec = inspect.formatargspec(
899 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
900 if realname == '<lambda>':
901 title = '<strong>%s</strong> <em>lambda</em> ' % name
902 argspec = argspec[1:-1] # remove parentheses
906 decl = title + argspec + (note and self.grey(
907 '<font face="helvetica, arial">%s</font>' % note))
910 return '<dl><dt>%s</dt></dl>\n' % decl
913 getdoc(object), self.preformat, funcs, classes, methods)
914 doc = doc and '<dd><tt>%s</tt></dd>' % doc
915 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
917 def _docdescriptor(self, name, value, mod):
919 push = results.append
922 push('<dl><dt><strong>%s</strong></dt>\n' % name)
923 if value.__doc__ is not None:
924 doc = self.markup(getdoc(value), self.preformat)
925 push('<dd><tt>%s</tt></dd>\n' % doc)
928 return ''.join(results)
930 def docproperty(self, object, name=None, mod=None, cl=None):
931 """Produce html documentation for a property."""
932 return self._docdescriptor(name, object, mod)
934 def docother(self, object, name=None, mod=None, *ignored):
935 """Produce HTML documentation for a data object."""
936 lhs = name and '<strong>%s</strong> = ' % name or ''
937 return lhs + self.repr(object)
939 def docdata(self, object, name=None, mod=None, cl=None):
940 """Produce html documentation for a data descriptor."""
941 return self._docdescriptor(name, object, mod)
943 def index(self, dir, shadowed=None):
944 """Generate an HTML index for a directory of modules."""
946 if shadowed is None: shadowed = {}
947 for importer, name, ispkg in pkgutil.iter_modules([dir]):
948 modpkgs.append((name, '', ispkg, name in shadowed))
952 contents = self.multicolumn(modpkgs, self.modpkglink)
953 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
955 # -------------------------------------------- text documentation generator
957 class TextRepr(Repr):
958 """Class for safely making a text representation of a Python object."""
961 self.maxlist = self.maxtuple = 20
963 self.maxstring = self.maxother = 100
965 def repr1(self, x, level):
966 if hasattr(type(x), '__name__'):
967 methodname = 'repr_' + join(split(type(x).__name__), '_')
968 if hasattr(self, methodname):
969 return getattr(self, methodname)(x, level)
970 return cram(stripid(repr(x)), self.maxother)
972 def repr_string(self, x, level):
973 test = cram(x, self.maxstring)
974 testrepr = repr(test)
975 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
976 # Backslashes are only literal in the string and are never
977 # needed to make any special characters, so show a raw string.
978 return 'r' + testrepr[0] + test + testrepr[0]
981 repr_str = repr_string
983 def repr_instance(self, x, level):
985 return cram(stripid(repr(x)), self.maxstring)
987 return '<%s instance>' % x.__class__.__name__
990 """Formatter class for text documentation."""
992 # ------------------------------------------- text formatting utilities
994 _repr_instance = TextRepr()
995 repr = _repr_instance.repr
997 def bold(self, text):
998 """Format a string in bold by overstriking."""
999 return join(map(lambda ch: ch + '\b' + ch, text), '')
1001 def indent(self, text, prefix=' '):
1002 """Indent text by prepending a given prefix to each line."""
1003 if not text: return ''
1004 lines = split(text, '\n')
1005 lines = map(lambda line, prefix=prefix: prefix + line, lines)
1006 if lines: lines[-1] = rstrip(lines[-1])
1007 return join(lines, '\n')
1009 def section(self, title, contents):
1010 """Format a section with a given heading."""
1011 return self.bold(title) + '\n' + rstrip(self.indent(contents)) + '\n\n'
1013 # ---------------------------------------------- type-specific routines
1015 def formattree(self, tree, modname, parent=None, prefix=''):
1016 """Render in text a class tree as returned by inspect.getclasstree()."""
1019 if type(entry) is type(()):
1021 result = result + prefix + classname(c, modname)
1022 if bases and bases != (parent,):
1023 parents = map(lambda c, m=modname: classname(c, m), bases)
1024 result = result + '(%s)' % join(parents, ', ')
1025 result = result + '\n'
1026 elif type(entry) is type([]):
1027 result = result + self.formattree(
1028 entry, modname, c, prefix + ' ')
1031 def docmodule(self, object, name=None, mod=None):
1032 """Produce text documentation for a given module object."""
1033 name = object.__name__ # ignore the passed-in name
1034 synop, desc = splitdoc(getdoc(object))
1035 result = self.section('NAME', name + (synop and ' - ' + synop))
1038 all = object.__all__
1039 except AttributeError:
1043 file = inspect.getabsfile(object)
1046 result = result + self.section('FILE', file)
1048 docloc = self.getdocloc(object)
1049 if docloc is not None:
1050 result = result + self.section('MODULE DOCS', docloc)
1053 result = result + self.section('DESCRIPTION', desc)
1056 for key, value in inspect.getmembers(object, inspect.isclass):
1057 # if __all__ exists, believe it. Otherwise use old heuristic.
1059 or (inspect.getmodule(value) or object) is object):
1060 if visiblename(key, all, object):
1061 classes.append((key, value))
1063 for key, value in inspect.getmembers(object, inspect.isroutine):
1064 # if __all__ exists, believe it. Otherwise use old heuristic.
1065 if (all is not None or
1066 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
1067 if visiblename(key, all, object):
1068 funcs.append((key, value))
1070 for key, value in inspect.getmembers(object, isdata):
1071 if visiblename(key, all, object):
1072 data.append((key, value))
1075 modpkgs_names = set()
1076 if hasattr(object, '__path__'):
1077 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
1078 modpkgs_names.add(modname)
1080 modpkgs.append(modname + ' (package)')
1082 modpkgs.append(modname)
1085 result = result + self.section(
1086 'PACKAGE CONTENTS', join(modpkgs, '\n'))
1088 # Detect submodules as sometimes created by C extensions
1090 for key, value in inspect.getmembers(object, inspect.ismodule):
1091 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1092 submodules.append(key)
1095 result = result + self.section(
1096 'SUBMODULES', join(submodules, '\n'))
1099 classlist = map(lambda key_value: key_value[1], classes)
1100 contents = [self.formattree(
1101 inspect.getclasstree(classlist, 1), name)]
1102 for key, value in classes:
1103 contents.append(self.document(value, key, name))
1104 result = result + self.section('CLASSES', join(contents, '\n'))
1108 for key, value in funcs:
1109 contents.append(self.document(value, key, name))
1110 result = result + self.section('FUNCTIONS', join(contents, '\n'))
1114 for key, value in data:
1115 contents.append(self.docother(value, key, name, maxlen=70))
1116 result = result + self.section('DATA', join(contents, '\n'))
1118 if hasattr(object, '__version__'):
1119 version = str(object.__version__)
1120 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
1121 version = strip(version[11:-1])
1122 result = result + self.section('VERSION', version)
1123 if hasattr(object, '__date__'):
1124 result = result + self.section('DATE', str(object.__date__))
1125 if hasattr(object, '__author__'):
1126 result = result + self.section('AUTHOR', str(object.__author__))
1127 if hasattr(object, '__credits__'):
1128 result = result + self.section('CREDITS', str(object.__credits__))
1131 def docclass(self, object, name=None, mod=None, *ignored):
1132 """Produce text documentation for a given class object."""
1133 realname = object.__name__
1134 name = name or realname
1135 bases = object.__bases__
1137 def makename(c, m=object.__module__):
1138 return classname(c, m)
1140 if name == realname:
1141 title = 'class ' + self.bold(realname)
1143 title = self.bold(name) + ' = class ' + realname
1145 parents = map(makename, bases)
1146 title = title + '(%s)' % join(parents, ', ')
1148 doc = getdoc(object)
1149 contents = doc and [doc + '\n'] or []
1150 push = contents.append
1152 # List the mro, if non-trivial.
1153 mro = deque(inspect.getmro(object))
1155 push("Method resolution order:")
1157 push(' ' + makename(base))
1160 # Cute little class to pump out a horizontal rule between sections.
1161 class HorizontalRule:
1168 hr = HorizontalRule()
1170 def spill(msg, attrs, predicate):
1171 ok, attrs = _split_list(attrs, predicate)
1175 for name, kind, homecls, value in ok:
1177 value = getattr(object, name)
1179 # Some descriptors may meet a failure in their __get__.
1181 push(self._docdescriptor(name, value, mod))
1183 push(self.document(value,
1187 def spilldescriptors(msg, attrs, predicate):
1188 ok, attrs = _split_list(attrs, predicate)
1192 for name, kind, homecls, value in ok:
1193 push(self._docdescriptor(name, value, mod))
1196 def spilldata(msg, attrs, predicate):
1197 ok, attrs = _split_list(attrs, predicate)
1201 for name, kind, homecls, value in ok:
1202 if (hasattr(value, '__call__') or
1203 inspect.isdatadescriptor(value)):
1207 push(self.docother(getattr(object, name),
1208 name, mod, maxlen=70, doc=doc) + '\n')
1211 attrs = filter(lambda data: visiblename(data[0], obj=object),
1212 classify_class_attrs(object))
1215 thisclass = mro.popleft()
1217 thisclass = attrs[0][2]
1218 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1220 if thisclass is __builtin__.object:
1223 elif thisclass is object:
1224 tag = "defined here"
1226 tag = "inherited from %s" % classname(thisclass,
1229 # Sort attrs by name.
1232 # Pump out the attrs, segregated by kind.
1233 attrs = spill("Methods %s:\n" % tag, attrs,
1234 lambda t: t[1] == 'method')
1235 attrs = spill("Class methods %s:\n" % tag, attrs,
1236 lambda t: t[1] == 'class method')
1237 attrs = spill("Static methods %s:\n" % tag, attrs,
1238 lambda t: t[1] == 'static method')
1239 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1240 lambda t: t[1] == 'data descriptor')
1241 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1242 lambda t: t[1] == 'data')
1246 contents = '\n'.join(contents)
1249 return title + '\n' + self.indent(rstrip(contents), ' | ') + '\n'
1251 def formatvalue(self, object):
1252 """Format an argument default value as text."""
1253 return '=' + self.repr(object)
1255 def docroutine(self, object, name=None, mod=None, cl=None):
1256 """Produce text documentation for a function or method object."""
1257 realname = object.__name__
1258 name = name or realname
1261 if inspect.ismethod(object):
1262 imclass = object.im_class
1264 if imclass is not cl:
1265 note = ' from ' + classname(imclass, mod)
1267 if object.im_self is not None:
1268 note = ' method of %s instance' % classname(
1269 object.im_self.__class__, mod)
1271 note = ' unbound %s method' % classname(imclass,mod)
1272 object = object.im_func
1274 if name == realname:
1275 title = self.bold(realname)
1277 if (cl and realname in cl.__dict__ and
1278 cl.__dict__[realname] is object):
1280 title = self.bold(name) + ' = ' + realname
1281 if inspect.isfunction(object):
1282 args, varargs, varkw, defaults = inspect.getargspec(object)
1283 argspec = inspect.formatargspec(
1284 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
1285 if realname == '<lambda>':
1286 title = self.bold(name) + ' lambda '
1287 argspec = argspec[1:-1] # remove parentheses
1290 decl = title + argspec + note
1295 doc = getdoc(object) or ''
1296 return decl + '\n' + (doc and rstrip(self.indent(doc)) + '\n')
1298 def _docdescriptor(self, name, value, mod):
1300 push = results.append
1303 push(self.bold(name))
1305 doc = getdoc(value) or ''
1307 push(self.indent(doc))
1309 return ''.join(results)
1311 def docproperty(self, object, name=None, mod=None, cl=None):
1312 """Produce text documentation for a property."""
1313 return self._docdescriptor(name, object, mod)
1315 def docdata(self, object, name=None, mod=None, cl=None):
1316 """Produce text documentation for a data descriptor."""
1317 return self._docdescriptor(name, object, mod)
1319 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
1320 """Produce text documentation for a data object."""
1321 repr = self.repr(object)
1323 line = (name and name + ' = ' or '') + repr
1324 chop = maxlen - len(line)
1325 if chop < 0: repr = repr[:chop] + '...'
1326 line = (name and self.bold(name) + ' = ' or '') + repr
1328 line += '\n' + self.indent(str(doc))
1331 # --------------------------------------------------------- user interfaces
1334 """The first time this is called, determine what kind of pager to use."""
1340 """Decide what method to use for paging through text."""
1341 if type(sys.stdout) is not types.FileType:
1343 if not sys.stdin.isatty() or not sys.stdout.isatty():
1345 if 'PAGER' in os.environ:
1346 if sys.platform == 'win32': # pipes completely broken in Windows
1347 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
1348 elif os.environ.get('TERM') in ('dumb', 'emacs'):
1349 return lambda text: pipepager(plain(text), os.environ['PAGER'])
1351 return lambda text: pipepager(text, os.environ['PAGER'])
1352 if os.environ.get('TERM') in ('dumb', 'emacs'):
1354 if sys.platform == 'win32' or sys.platform.startswith('os2'):
1355 return lambda text: tempfilepager(plain(text), 'more <')
1356 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
1357 return lambda text: pipepager(text, 'less')
1360 (fd, filename) = tempfile.mkstemp()
1363 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
1364 return lambda text: pipepager(text, 'more')
1371 """Remove boldface formatting from text."""
1372 return re.sub('.\b', '', text)
1374 def pipepager(text, cmd):
1375 """Page through text by feeding it to another program."""
1376 pipe = os.popen(cmd, 'w')
1381 pass # Ignore broken pipes caused by quitting the pager program.
1383 def tempfilepager(text, cmd):
1384 """Page through text by invoking a program on a temporary file."""
1386 filename = tempfile.mktemp()
1387 file = open(filename, 'w')
1391 os.system(cmd + ' "' + filename + '"')
1396 """Page through text on a text terminal."""
1397 lines = split(plain(text), '\n')
1400 fd = sys.stdin.fileno()
1401 old = tty.tcgetattr(fd)
1403 getchar = lambda: sys.stdin.read(1)
1404 except (ImportError, AttributeError):
1406 getchar = lambda: sys.stdin.readline()[:-1][:1]
1409 r = inc = os.environ.get('LINES', 25) - 1
1410 sys.stdout.write(join(lines[:inc], '\n') + '\n')
1412 sys.stdout.write('-- more --')
1417 sys.stdout.write('\r \r')
1419 elif c in ('\r', '\n'):
1420 sys.stdout.write('\r \r' + lines[r] + '\n')
1423 if c in ('b', 'B', '\x1b'):
1426 sys.stdout.write('\n' + join(lines[r:r+inc], '\n') + '\n')
1431 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1433 def plainpager(text):
1434 """Simply print unformatted text. This is the ultimate fallback."""
1435 sys.stdout.write(plain(text))
1437 def describe(thing):
1438 """Produce a short description of the given thing."""
1439 if inspect.ismodule(thing):
1440 if thing.__name__ in sys.builtin_module_names:
1441 return 'built-in module ' + thing.__name__
1442 if hasattr(thing, '__path__'):
1443 return 'package ' + thing.__name__
1445 return 'module ' + thing.__name__
1446 if inspect.isbuiltin(thing):
1447 return 'built-in function ' + thing.__name__
1448 if inspect.isgetsetdescriptor(thing):
1449 return 'getset descriptor %s.%s.%s' % (
1450 thing.__objclass__.__module__, thing.__objclass__.__name__,
1452 if inspect.ismemberdescriptor(thing):
1453 return 'member descriptor %s.%s.%s' % (
1454 thing.__objclass__.__module__, thing.__objclass__.__name__,
1456 if inspect.isclass(thing):
1457 return 'class ' + thing.__name__
1458 if inspect.isfunction(thing):
1459 return 'function ' + thing.__name__
1460 if inspect.ismethod(thing):
1461 return 'method ' + thing.__name__
1462 if type(thing) is types.InstanceType:
1463 return 'instance of ' + thing.__class__.__name__
1464 return type(thing).__name__
1466 def locate(path, forceload=0):
1467 """Locate an object by name or dotted path, importing as necessary."""
1468 parts = [part for part in split(path, '.') if part]
1470 while n < len(parts):
1471 nextmodule = safeimport(join(parts[:n+1], '.'), forceload)
1472 if nextmodule: module, n = nextmodule, n + 1
1477 object = __builtin__
1478 for part in parts[n:]:
1480 object = getattr(object, part)
1481 except AttributeError:
1485 # --------------------------------------- interactive interpreter interface
1490 class _OldStyleClass: pass
1491 _OLD_INSTANCE_TYPE = type(_OldStyleClass())
1493 def resolve(thing, forceload=0):
1494 """Given an object or a path to an object, get the object and its name."""
1495 if isinstance(thing, str):
1496 object = locate(thing, forceload)
1498 raise ImportError, 'no Python documentation found for %r' % thing
1499 return object, thing
1501 return thing, getattr(thing, '__name__', None)
1503 def render_doc(thing, title='Python Library Documentation: %s', forceload=0):
1504 """Render text documentation, given an object or a path to an object."""
1505 object, name = resolve(thing, forceload)
1506 desc = describe(object)
1507 module = inspect.getmodule(object)
1508 if name and '.' in name:
1509 desc += ' in ' + name[:name.rfind('.')]
1510 elif module and module is not object:
1511 desc += ' in module ' + module.__name__
1512 if type(object) is _OLD_INSTANCE_TYPE:
1513 # If the passed object is an instance of an old-style class,
1514 # document its available methods instead of its value.
1515 object = object.__class__
1516 elif not (inspect.ismodule(object) or
1517 inspect.isclass(object) or
1518 inspect.isroutine(object) or
1519 inspect.isgetsetdescriptor(object) or
1520 inspect.ismemberdescriptor(object) or
1521 isinstance(object, property)):
1522 # If the passed object is a piece of data or an instance,
1523 # document its available methods instead of its value.
1524 object = type(object)
1526 return title % desc + '\n\n' + text.document(object, name)
1528 def doc(thing, title='Python Library Documentation: %s', forceload=0):
1529 """Display text documentation, given an object or a path to an object."""
1531 pager(render_doc(thing, title, forceload))
1532 except (ImportError, ErrorDuringImport), value:
1535 def writedoc(thing, forceload=0):
1536 """Write HTML documentation to a file in the current directory."""
1538 object, name = resolve(thing, forceload)
1539 page = html.page(describe(object), html.document(object, name))
1540 file = open(name + '.html', 'w')
1543 print 'wrote', name + '.html'
1544 except (ImportError, ErrorDuringImport), value:
1547 def writedocs(dir, pkgpath='', done=None):
1548 """Write out HTML documentation for all modules in a directory tree."""
1549 if done is None: done = {}
1550 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1556 # These dictionaries map a topic name to either an alias, or a tuple
1557 # (label, seealso-items). The "label" is the label of the corresponding
1558 # section in the .rst file under Doc/ and an index into the dictionary
1559 # in pydoc_data/topics.py.
1561 # CAUTION: if you change one of these dictionaries, be sure to adapt the
1562 # list of needed labels in Doc/tools/sphinxext/pyspecific.py and
1563 # regenerate the pydoc_data/topics.py file by running
1565 # in Doc/ and copying the output file into the Lib/ directory.
1570 'assert': ('assert', ''),
1571 'break': ('break', 'while for'),
1572 'class': ('class', 'CLASSES SPECIALMETHODS'),
1573 'continue': ('continue', 'while for'),
1574 'def': ('function', ''),
1575 'del': ('del', 'BASICMETHODS'),
1577 'else': ('else', 'while for'),
1579 'exec': ('exec', ''),
1581 'for': ('for', 'break continue while'),
1583 'global': ('global', 'NAMESPACES'),
1584 'if': ('if', 'TRUTHVALUE'),
1585 'import': ('import', 'MODULES'),
1586 'in': ('in', 'SEQUENCEMETHODS2'),
1588 'lambda': ('lambda', 'FUNCTIONS'),
1591 'pass': ('pass', ''),
1592 'print': ('print', ''),
1593 'raise': ('raise', 'EXCEPTIONS'),
1594 'return': ('return', 'FUNCTIONS'),
1595 'try': ('try', 'EXCEPTIONS'),
1596 'while': ('while', 'break continue if TRUTHVALUE'),
1597 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1598 'yield': ('yield', ''),
1600 # Either add symbols to this dictionary or to the symbols dictionary
1601 # directly: Whichever is easier. They are merged later.
1602 _symbols_inverse = {
1603 'STRINGS' : ("'", "'''", "r'", "u'", '"""', '"', 'r"', 'u"'),
1604 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1605 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1606 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1607 'UNARY' : ('-', '~'),
1608 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1609 '^=', '<<=', '>>=', '**=', '//='),
1610 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1611 'COMPLEX' : ('j', 'J')
1614 '%': 'OPERATORS FORMATTING',
1616 ',': 'TUPLES LISTS FUNCTIONS',
1617 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1619 ':': 'SLICINGS DICTIONARYLITERALS',
1622 '_': 'PRIVATENAMES',
1623 '__': 'PRIVATENAMES SPECIALMETHODS',
1625 '(': 'TUPLES FUNCTIONS CALLS',
1626 ')': 'TUPLES FUNCTIONS CALLS',
1627 '[': 'LISTS SUBSCRIPTS SLICINGS',
1628 ']': 'LISTS SUBSCRIPTS SLICINGS'
1630 for topic, symbols_ in _symbols_inverse.iteritems():
1631 for symbol in symbols_:
1632 topics = symbols.get(symbol, topic)
1633 if topic not in topics:
1634 topics = topics + ' ' + topic
1635 symbols[symbol] = topics
1638 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1639 'FUNCTIONS CLASSES MODULES FILES inspect'),
1640 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS FORMATTING '
1642 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1643 'FORMATTING': ('formatstrings', 'OPERATORS'),
1644 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1645 'FORMATTING TYPES'),
1646 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1647 'INTEGER': ('integers', 'int range'),
1648 'FLOAT': ('floating', 'float math'),
1649 'COMPLEX': ('imaginary', 'complex cmath'),
1650 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING xrange LISTS'),
1651 'MAPPINGS': 'DICTIONARIES',
1652 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1653 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1654 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1655 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
1656 'FRAMEOBJECTS': 'TYPES',
1657 'TRACEBACKS': 'TYPES',
1658 'NONE': ('bltin-null-object', ''),
1659 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
1660 'FILES': ('bltin-file-objects', ''),
1661 'SPECIALATTRIBUTES': ('specialattrs', ''),
1662 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1663 'MODULES': ('typesmodules', 'import'),
1664 'PACKAGES': 'import',
1665 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1666 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1667 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1668 'LISTS DICTIONARIES BACKQUOTES'),
1669 'OPERATORS': 'EXPRESSIONS',
1670 'PRECEDENCE': 'EXPRESSIONS',
1671 'OBJECTS': ('objects', 'TYPES'),
1672 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
1673 'CALLABLEMETHODS SEQUENCEMETHODS1 MAPPINGMETHODS '
1674 'SEQUENCEMETHODS2 NUMBERMETHODS CLASSES'),
1675 'BASICMETHODS': ('customization', 'cmp hash repr str SPECIALMETHODS'),
1676 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1677 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
1678 'SEQUENCEMETHODS1': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS2 '
1680 'SEQUENCEMETHODS2': ('sequence-methods', 'SEQUENCES SEQUENCEMETHODS1 '
1682 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1683 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1685 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
1686 'NAMESPACES': ('naming', 'global ASSIGNMENT DELETION DYNAMICFEATURES'),
1687 'DYNAMICFEATURES': ('dynamic-features', ''),
1688 'SCOPING': 'NAMESPACES',
1689 'FRAMES': 'NAMESPACES',
1690 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1691 'COERCIONS': ('coercion-rules','CONVERSIONS'),
1692 'CONVERSIONS': ('conversions', 'COERCIONS'),
1693 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1694 'SPECIALIDENTIFIERS': ('id-classes', ''),
1695 'PRIVATENAMES': ('atom-identifiers', ''),
1696 'LITERALS': ('atom-literals', 'STRINGS BACKQUOTES NUMBERS '
1697 'TUPLELITERALS LISTLITERALS DICTIONARYLITERALS'),
1698 'TUPLES': 'SEQUENCES',
1699 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1700 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1701 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1702 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1703 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1704 'BACKQUOTES': ('string-conversions', 'repr str STRINGS LITERALS'),
1705 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr '
1706 'ATTRIBUTEMETHODS'),
1707 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS1'),
1708 'SLICINGS': ('slicings', 'SEQUENCEMETHODS2'),
1709 'CALLS': ('calls', 'EXPRESSIONS'),
1710 'POWER': ('power', 'EXPRESSIONS'),
1711 'UNARY': ('unary', 'EXPRESSIONS'),
1712 'BINARY': ('binary', 'EXPRESSIONS'),
1713 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1714 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1715 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1716 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
1717 'ASSERTION': 'assert',
1718 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1719 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
1721 'PRINTING': 'print',
1722 'RETURNING': 'return',
1723 'IMPORTING': 'import',
1724 'CONDITIONAL': 'if',
1725 'LOOPING': ('compound', 'for while break continue'),
1726 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1727 'DEBUGGING': ('debugger', 'pdb'),
1728 'CONTEXTMANAGERS': ('context-managers', 'with'),
1731 def __init__(self, input=None, output=None):
1733 self._output = output
1735 input = property(lambda self: self._input or sys.stdin)
1736 output = property(lambda self: self._output or sys.stdout)
1739 if inspect.stack()[1][3] == '?':
1742 return '<pydoc.Helper instance>'
1744 _GoInteractive = object()
1745 def __call__(self, request=_GoInteractive):
1746 if request is not self._GoInteractive:
1751 self.output.write('''
1752 You are now leaving help and returning to the Python interpreter.
1753 If you want to ask for help on a particular object directly from the
1754 interpreter, you can type "help(object)". Executing "help('string')"
1755 has the same effect as typing a particular string at the help> prompt.
1759 self.output.write('\n')
1762 request = self.getline('help> ')
1763 if not request: break
1764 except (KeyboardInterrupt, EOFError):
1766 request = strip(replace(request, '"', '', "'", ''))
1767 if lower(request) in ('q', 'quit'): break
1770 def getline(self, prompt):
1771 """Read one line, using raw_input when available."""
1772 if self.input is sys.stdin:
1773 return raw_input(prompt)
1775 self.output.write(prompt)
1777 return self.input.readline()
1779 def help(self, request):
1780 if type(request) is type(''):
1781 request = request.strip()
1782 if request == 'help': self.intro()
1783 elif request == 'keywords': self.listkeywords()
1784 elif request == 'symbols': self.listsymbols()
1785 elif request == 'topics': self.listtopics()
1786 elif request == 'modules': self.listmodules()
1787 elif request[:8] == 'modules ':
1788 self.listmodules(split(request)[1])
1789 elif request in self.symbols: self.showsymbol(request)
1790 elif request in self.keywords: self.showtopic(request)
1791 elif request in self.topics: self.showtopic(request)
1792 elif request: doc(request, 'Help on %s:')
1793 elif isinstance(request, Helper): self()
1794 else: doc(request, 'Help on %s:')
1795 self.output.write('\n')
1798 self.output.write('''
1799 Welcome to Python %s! This is the online help utility.
1801 If this is your first time using Python, you should definitely check out
1802 the tutorial on the Internet at http://docs.python.org/tutorial/.
1804 Enter the name of any module, keyword, or topic to get help on writing
1805 Python programs and using Python modules. To quit this help utility and
1806 return to the interpreter, just type "quit".
1808 To get a list of available modules, keywords, or topics, type "modules",
1809 "keywords", or "topics". Each module also comes with a one-line summary
1810 of what it does; to list the modules whose summaries contain a given word
1811 such as "spam", type "modules spam".
1812 ''' % sys.version[:3])
1814 def list(self, items, columns=4, width=80):
1817 colw = width / columns
1818 rows = (len(items) + columns - 1) / columns
1819 for row in range(rows):
1820 for col in range(columns):
1821 i = col * rows + row
1823 self.output.write(items[i])
1824 if col < columns - 1:
1825 self.output.write(' ' + ' ' * (colw-1 - len(items[i])))
1826 self.output.write('\n')
1828 def listkeywords(self):
1829 self.output.write('''
1830 Here is a list of the Python keywords. Enter any keyword to get more help.
1833 self.list(self.keywords.keys())
1835 def listsymbols(self):
1836 self.output.write('''
1837 Here is a list of the punctuation symbols which Python assigns special meaning
1838 to. Enter any symbol to get more help.
1841 self.list(self.symbols.keys())
1843 def listtopics(self):
1844 self.output.write('''
1845 Here is a list of available topics. Enter any topic name to get more help.
1848 self.list(self.topics.keys())
1850 def showtopic(self, topic, more_xrefs=''):
1852 import pydoc_data.topics
1854 self.output.write('''
1855 Sorry, topic and keyword documentation is not available because the
1856 module "pydoc_data.topics" could not be found.
1859 target = self.topics.get(topic, self.keywords.get(topic))
1861 self.output.write('no documentation found for %s\n' % repr(topic))
1863 if type(target) is type(''):
1864 return self.showtopic(target, more_xrefs)
1866 label, xrefs = target
1868 doc = pydoc_data.topics.topics[label]
1870 self.output.write('no documentation found for %s\n' % repr(topic))
1872 pager(strip(doc) + '\n')
1874 xrefs = (xrefs or '') + ' ' + more_xrefs
1876 import StringIO, formatter
1877 buffer = StringIO.StringIO()
1878 formatter.DumbWriter(buffer).send_flowing_data(
1879 'Related help topics: ' + join(split(xrefs), ', ') + '\n')
1880 self.output.write('\n%s\n' % buffer.getvalue())
1882 def showsymbol(self, symbol):
1883 target = self.symbols[symbol]
1884 topic, _, xrefs = target.partition(' ')
1885 self.showtopic(topic, xrefs)
1887 def listmodules(self, key=''):
1889 self.output.write('''
1890 Here is a list of matching modules. Enter any module name to get more help.
1895 self.output.write('''
1896 Please wait a moment while I gather a list of all available modules...
1900 def callback(path, modname, desc, modules=modules):
1901 if modname and modname[-9:] == '.__init__':
1902 modname = modname[:-9] + ' (package)'
1903 if find(modname, '.') < 0:
1904 modules[modname] = 1
1905 def onerror(modname):
1906 callback(None, modname, None)
1907 ModuleScanner().run(callback, onerror=onerror)
1908 self.list(modules.keys())
1909 self.output.write('''
1910 Enter any module name to get more help. Or, type "modules spam" to search
1911 for modules whose descriptions contain the word "spam".
1917 """A generic tree iterator."""
1918 def __init__(self, roots, children, descendp):
1919 self.roots = roots[:]
1921 self.children = children
1922 self.descendp = descendp
1928 root = self.roots.pop(0)
1929 self.state = [(root, self.children(root))]
1930 node, children = self.state[-1]
1934 child = children.pop(0)
1935 if self.descendp(child):
1936 self.state.append((child, self.children(child)))
1940 class ModuleScanner:
1941 """An interruptible scanner that searches module synopses."""
1943 def run(self, callback, key=None, completer=None, onerror=None):
1944 if key: key = lower(key)
1948 for modname in sys.builtin_module_names:
1949 if modname != '__main__':
1952 callback(None, modname, '')
1954 desc = split(__import__(modname).__doc__ or '', '\n')[0]
1955 if find(lower(modname + ' - ' + desc), key) >= 0:
1956 callback(None, modname, desc)
1958 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
1962 callback(None, modname, '')
1964 loader = importer.find_module(modname)
1965 if hasattr(loader,'get_source'):
1967 desc = source_synopsis(
1968 StringIO.StringIO(loader.get_source(modname))
1970 if hasattr(loader,'get_filename'):
1971 path = loader.get_filename(modname)
1975 module = loader.load_module(modname)
1976 desc = (module.__doc__ or '').splitlines()[0]
1977 path = getattr(module,'__file__',None)
1978 if find(lower(modname + ' - ' + desc), key) >= 0:
1979 callback(path, modname, desc)
1985 """Print all the one-line module summaries that contain a substring."""
1986 def callback(path, modname, desc):
1987 if modname[-9:] == '.__init__':
1988 modname = modname[:-9] + ' (package)'
1989 print modname, desc and '- ' + desc
1990 def onerror(modname):
1992 with warnings.catch_warnings():
1993 warnings.filterwarnings('ignore') # ignore problems during import
1994 ModuleScanner().run(callback, key, onerror=onerror)
1996 # --------------------------------------------------- web browser interface
1998 def serve(port, callback=None, completer=None):
1999 import BaseHTTPServer, mimetools, select
2001 # Patch up mimetools.Message so it doesn't break if rfc822 is reloaded.
2002 class Message(mimetools.Message):
2003 def __init__(self, fp, seekable=1):
2004 Message = self.__class__
2005 Message.__bases__[0].__bases__[0].__init__(self, fp, seekable)
2006 self.encodingheader = self.getheader('content-transfer-encoding')
2007 self.typeheader = self.getheader('content-type')
2011 class DocHandler(BaseHTTPServer.BaseHTTPRequestHandler):
2012 def send_document(self, title, contents):
2014 self.send_response(200)
2015 self.send_header('Content-Type', 'text/html')
2017 self.wfile.write(html.page(title, contents))
2018 except IOError: pass
2022 if path[-5:] == '.html': path = path[:-5]
2023 if path[:1] == '/': path = path[1:]
2024 if path and path != '.':
2026 obj = locate(path, forceload=1)
2027 except ErrorDuringImport, value:
2028 self.send_document(path, html.escape(str(value)))
2031 self.send_document(describe(obj), html.document(obj, path))
2033 self.send_document(path,
2034 'no Python documentation found for %s' % repr(path))
2036 heading = html.heading(
2037 '<big><big><strong>Python: Index of Modules</strong></big></big>',
2038 '#ffffff', '#7799ee')
2039 def bltinlink(name):
2040 return '<a href="%s.html">%s</a>' % (name, name)
2041 names = filter(lambda x: x != '__main__',
2042 sys.builtin_module_names)
2043 contents = html.multicolumn(names, bltinlink)
2044 indices = ['<p>' + html.bigsection(
2045 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2048 for dir in sys.path:
2049 indices.append(html.index(dir, seen))
2050 contents = heading + join(indices) + '''<p align=right>
2051 <font color="#909090" face="helvetica, arial"><strong>
2052 pydoc</strong> by Ka-Ping Yee <ping@lfw.org></font>'''
2053 self.send_document('Index of Modules', contents)
2055 def log_message(self, *args): pass
2057 class DocServer(BaseHTTPServer.HTTPServer):
2058 def __init__(self, port, callback):
2060 self.address = (host, port)
2061 self.url = 'http://%s:%d/' % (host, port)
2062 self.callback = callback
2063 self.base.__init__(self, self.address, self.handler)
2065 def serve_until_quit(self):
2068 while not self.quit:
2069 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2070 if rd: self.handle_request()
2072 def server_activate(self):
2073 self.base.server_activate(self)
2074 if self.callback: self.callback(self)
2076 DocServer.base = BaseHTTPServer.HTTPServer
2077 DocServer.handler = DocHandler
2078 DocHandler.MessageClass = Message
2081 DocServer(port, callback).serve_until_quit()
2082 except (KeyboardInterrupt, select.error):
2085 if completer: completer()
2087 # ----------------------------------------------------- graphical interface
2090 """Graphical interface (starts web server and pops up a control window)."""
2092 def __init__(self, window, port=7464):
2093 self.window = window
2098 self.server_frm = Tkinter.Frame(window)
2099 self.title_lbl = Tkinter.Label(self.server_frm,
2100 text='Starting server...\n ')
2101 self.open_btn = Tkinter.Button(self.server_frm,
2102 text='open browser', command=self.open, state='disabled')
2103 self.quit_btn = Tkinter.Button(self.server_frm,
2104 text='quit serving', command=self.quit, state='disabled')
2106 self.search_frm = Tkinter.Frame(window)
2107 self.search_lbl = Tkinter.Label(self.search_frm, text='Search for')
2108 self.search_ent = Tkinter.Entry(self.search_frm)
2109 self.search_ent.bind('<Return>', self.search)
2110 self.stop_btn = Tkinter.Button(self.search_frm,
2111 text='stop', pady=0, command=self.stop, state='disabled')
2112 if sys.platform == 'win32':
2113 # Trying to hide and show this button crashes under Windows.
2114 self.stop_btn.pack(side='right')
2116 self.window.title('pydoc')
2117 self.window.protocol('WM_DELETE_WINDOW', self.quit)
2118 self.title_lbl.pack(side='top', fill='x')
2119 self.open_btn.pack(side='left', fill='x', expand=1)
2120 self.quit_btn.pack(side='right', fill='x', expand=1)
2121 self.server_frm.pack(side='top', fill='x')
2123 self.search_lbl.pack(side='left')
2124 self.search_ent.pack(side='right', fill='x', expand=1)
2125 self.search_frm.pack(side='top', fill='x')
2126 self.search_ent.focus_set()
2128 font = ('helvetica', sys.platform == 'win32' and 8 or 10)
2129 self.result_lst = Tkinter.Listbox(window, font=font, height=6)
2130 self.result_lst.bind('<Button-1>', self.select)
2131 self.result_lst.bind('<Double-Button-1>', self.goto)
2132 self.result_scr = Tkinter.Scrollbar(window,
2133 orient='vertical', command=self.result_lst.yview)
2134 self.result_lst.config(yscrollcommand=self.result_scr.set)
2136 self.result_frm = Tkinter.Frame(window)
2137 self.goto_btn = Tkinter.Button(self.result_frm,
2138 text='go to selected', command=self.goto)
2139 self.hide_btn = Tkinter.Button(self.result_frm,
2140 text='hide results', command=self.hide)
2141 self.goto_btn.pack(side='left', fill='x', expand=1)
2142 self.hide_btn.pack(side='right', fill='x', expand=1)
2144 self.window.update()
2145 self.minwidth = self.window.winfo_width()
2146 self.minheight = self.window.winfo_height()
2147 self.bigminheight = (self.server_frm.winfo_reqheight() +
2148 self.search_frm.winfo_reqheight() +
2149 self.result_lst.winfo_reqheight() +
2150 self.result_frm.winfo_reqheight())
2151 self.bigwidth, self.bigheight = self.minwidth, self.bigminheight
2153 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2154 self.window.wm_minsize(self.minwidth, self.minheight)
2155 self.window.tk.willdispatch()
2159 target=serve, args=(port, self.ready, self.quit)).start()
2161 def ready(self, server):
2162 self.server = server
2163 self.title_lbl.config(
2164 text='Python documentation server at\n' + server.url)
2165 self.open_btn.config(state='normal')
2166 self.quit_btn.config(state='normal')
2168 def open(self, event=None, url=None):
2169 url = url or self.server.url
2172 webbrowser.open(url)
2173 except ImportError: # pre-webbrowser.py compatibility
2174 if sys.platform == 'win32':
2175 os.system('start "%s"' % url)
2177 rc = os.system('netscape -remote "openURL(%s)" &' % url)
2178 if rc: os.system('netscape "%s" &' % url)
2180 def quit(self, event=None):
2182 self.server.quit = 1
2185 def search(self, event=None):
2186 key = self.search_ent.get()
2187 self.stop_btn.pack(side='right')
2188 self.stop_btn.config(state='normal')
2189 self.search_lbl.config(text='Searching for "%s"...' % key)
2190 self.search_ent.forget()
2191 self.search_lbl.pack(side='left')
2192 self.result_lst.delete(0, 'end')
2193 self.goto_btn.config(state='disabled')
2198 self.scanner.quit = 1
2199 self.scanner = ModuleScanner()
2200 threading.Thread(target=self.scanner.run,
2201 args=(self.update, key, self.done)).start()
2203 def update(self, path, modname, desc):
2204 if modname[-9:] == '.__init__':
2205 modname = modname[:-9] + ' (package)'
2206 self.result_lst.insert('end',
2207 modname + ' - ' + (desc or '(no description)'))
2209 def stop(self, event=None):
2211 self.scanner.quit = 1
2216 self.search_lbl.config(text='Search for')
2217 self.search_lbl.pack(side='left')
2218 self.search_ent.pack(side='right', fill='x', expand=1)
2219 if sys.platform != 'win32': self.stop_btn.forget()
2220 self.stop_btn.config(state='disabled')
2222 def select(self, event=None):
2223 self.goto_btn.config(state='normal')
2225 def goto(self, event=None):
2226 selection = self.result_lst.curselection()
2228 modname = split(self.result_lst.get(selection[0]))[0]
2229 self.open(url=self.server.url + modname + '.html')
2232 if not self.expanded: return
2233 self.result_frm.forget()
2234 self.result_scr.forget()
2235 self.result_lst.forget()
2236 self.bigwidth = self.window.winfo_width()
2237 self.bigheight = self.window.winfo_height()
2238 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2239 self.window.wm_minsize(self.minwidth, self.minheight)
2243 if self.expanded: return
2244 self.result_frm.pack(side='bottom', fill='x')
2245 self.result_scr.pack(side='right', fill='y')
2246 self.result_lst.pack(side='top', fill='both', expand=1)
2247 self.window.wm_geometry('%dx%d' % (self.bigwidth, self.bigheight))
2248 self.window.wm_minsize(self.minwidth, self.bigminheight)
2251 def hide(self, event=None):
2258 # Tk will crash if pythonw.exe has an XP .manifest
2259 # file and the root has is not destroyed explicitly.
2260 # If the problem is ever fixed in Tk, the explicit
2267 except KeyboardInterrupt:
2270 # -------------------------------------------------- command-line interface
2273 return isinstance(x, str) and find(x, os.sep) >= 0
2276 """Command-line interface (looks at sys.argv to decide what to do)."""
2278 class BadUsage: pass
2280 # Scripts don't get the current directory in their path by default
2281 # unless they are run with the '-m' switch
2282 if '' not in sys.path:
2283 scriptdir = os.path.dirname(sys.argv[0])
2284 if scriptdir in sys.path:
2285 sys.path.remove(scriptdir)
2286 sys.path.insert(0, '.')
2289 opts, args = getopt.getopt(sys.argv[1:], 'gk:p:w')
2292 for opt, val in opts:
2305 print 'pydoc server ready at %s' % server.url
2307 print 'pydoc server stopped'
2308 serve(port, ready, stopped)
2313 if not args: raise BadUsage
2315 if ispath(arg) and not os.path.exists(arg):
2316 print 'file %r does not exist' % arg
2319 if ispath(arg) and os.path.isfile(arg):
2320 arg = importfile(arg)
2322 if ispath(arg) and os.path.isdir(arg):
2328 except ErrorDuringImport, value:
2331 except (getopt.error, BadUsage):
2332 cmd = os.path.basename(sys.argv[0])
2333 print """pydoc - the Python documentation tool
2336 Show text documentation on something. <name> may be the name of a
2337 Python keyword, topic, function, module, or package, or a dotted
2338 reference to a class or function within a module or module in a
2339 package. If <name> contains a '%s', it is used as the path to a
2340 Python source file to document. If name is 'keywords', 'topics',
2341 or 'modules', a listing of these things is displayed.
2344 Search for a keyword in the synopsis lines of all available modules.
2347 Start an HTTP server on the given port on the local machine.
2350 Pop up a graphical interface for finding and serving documentation.
2353 Write out the HTML documentation for a module to a file in the current
2354 directory. If <name> contains a '%s', it is treated as a filename; if
2355 it names a directory, documentation is written for all the contents.
2356 """ % (cmd, os.sep, cmd, cmd, cmd, cmd, os.sep)
2358 if __name__ == '__main__': cli()