2 """Generate Python documentation in HTML or text for interactive use.
4 In the Python interpreter, do "from pydoc import help" to provide online
5 help. Calling help(thing) on a Python object documents the object.
7 Or, at the shell command line outside of Python:
9 Run "pydoc <name>" to show documentation on something. <name> may be
10 the name of a function, module, package, or a dotted reference to a
11 class or function within a module or module in a package. If the
12 argument contains a path segment delimiter (e.g. slash on Unix,
13 backslash on Windows) it is treated as the path to a Python source file.
15 Run "pydoc -k <keyword>" to search for a keyword in the synopsis lines
16 of all available modules.
18 Run "pydoc -p <port>" to start an HTTP server on a given port on the
19 local machine to generate documentation web pages.
21 For platforms without a command line, "pydoc -g" starts the HTTP server
22 and also pops up a little window for controlling it.
24 Run "pydoc -w <name>" to write out the HTML documentation for a module
25 to a file named "<name>.html".
28 __author__
= "Ka-Ping Yee <ping@lfw.org>"
29 __date__
= "26 February 2001"
30 __version__
= "$Revision$"
31 __credits__
= """Guido van Rossum, for an excellent programming language.
32 Tommy Burnette, the original creator of manpy.
33 Paul Prescod, for all his work on onlinehelp.
34 Richard Chamberlain, for the first implementation of textdoc.
36 Mynd you, møøse bites Kan be pretty nasti..."""
38 # Known bugs that can't be fixed here:
39 # - imp.load_module() cannot be prevented from clobbering existing
40 # loaded modules, so calling synopsis() on a binary module file
41 # changes the contents of any existing module with the same name.
42 # - If the __file__ attribute on a module is a relative path and
43 # the current directory is changed with os.chdir(), an incorrect
44 # path will be displayed.
46 import sys
, imp
, os
, stat
, re
, types
, inspect
48 from string
import expandtabs
, find
, join
, lower
, split
, strip
, rfind
, rstrip
50 # --------------------------------------------------------- common routines
53 """Convert sys.path into a list of absolute, existing, unique paths."""
57 dir = os
.path
.abspath(dir or '.')
58 normdir
= os
.path
.normcase(dir)
59 if normdir
not in normdirs
and os
.path
.isdir(dir):
61 normdirs
.append(normdir
)
65 """Get the doc string or comments for an object."""
66 result
= inspect
.getdoc(object) or inspect
.getcomments(object)
67 return result
and re
.sub('^ *\n', '', rstrip(result
)) or ''
70 """Split a doc string into a synopsis line (if any) and the rest."""
71 lines
= split(strip(doc
), '\n')
74 elif len(lines
) >= 2 and not rstrip(lines
[1]):
75 return lines
[0], join(lines
[2:], '\n')
76 return '', join(lines
, '\n')
78 def classname(object, modname
):
79 """Get a class name and qualify it with a module name if necessary."""
80 name
= object.__name
__
81 if object.__module
__ != modname
:
82 name
= object.__module
__ + '.' + name
86 """Check if an object is of a type that probably means it's data."""
87 return not (inspect
.ismodule(object) or inspect
.isclass(object) or
88 inspect
.isroutine(object) or inspect
.isframe(object) or
89 inspect
.istraceback(object) or inspect
.iscode(object))
91 def replace(text
, *pairs
):
92 """Do a series of global replacements on a string."""
94 text
= join(split(text
, pairs
[0]), pairs
[1])
98 def cram(text
, maxlen
):
99 """Omit part of a string if needed to make it fit in a maximum length."""
100 if len(text
) > maxlen
:
101 pre
= max(0, (maxlen
-3)/2)
102 post
= max(0, maxlen
-3-pre
)
103 return text
[:pre
] + '...' + text
[len(text
)-post
:]
107 """Remove the hexadecimal id from a Python object representation."""
108 # The behaviour of %p is implementation-dependent; we check two cases.
109 for pattern
in [' at 0x[0-9a-f]{6,}>$', ' at [0-9A-F]{8,}>$']:
110 if re
.search(pattern
, repr(Exception)):
111 return re
.sub(pattern
, '>', text
)
114 def _is_some_method(object):
115 return inspect
.ismethod(object) or inspect
.ismethoddescriptor(object)
119 for key
, value
in inspect
.getmembers(cl
, _is_some_method
):
121 for base
in cl
.__bases
__:
122 methods
.update(allmethods(base
)) # all your base are belong to us
123 for key
in methods
.keys():
124 methods
[key
] = getattr(cl
, key
)
127 def _split_list(s
, predicate
):
128 """Split sequence s via predicate, and return pair ([true], [false]).
130 The return value is a 2-tuple of lists,
131 ([x for x in s if predicate(x)],
132 [x for x in s if not predicate(x)])
144 # ----------------------------------------------------- module manipulation
147 """Guess whether a path refers to a package directory."""
148 if os
.path
.isdir(path
):
149 for ext
in ['.py', '.pyc', '.pyo']:
150 if os
.path
.isfile(os
.path
.join(path
, '__init__' + ext
)):
153 def synopsis(filename
, cache
={}):
154 """Get the one-line summary out of a module file."""
155 mtime
= os
.stat(filename
)[stat
.ST_MTIME
]
156 lastupdate
, result
= cache
.get(filename
, (0, None))
157 if lastupdate
< mtime
:
158 info
= inspect
.getmoduleinfo(filename
)
159 file = open(filename
)
160 if info
and 'b' in info
[2]: # binary modules have to be imported
161 try: module
= imp
.load_module('__temp__', file, filename
, info
[1:])
163 result
= split(module
.__doc
__ or '', '\n')[0]
164 del sys
.modules
['__temp__']
165 else: # text modules can be directly examined
166 line
= file.readline()
167 while line
[:1] == '#' or not strip(line
):
168 line
= file.readline()
171 if line
[:4] == 'r"""': line
= line
[1:]
172 if line
[:3] == '"""':
174 if line
[-1:] == '\\': line
= line
[:-1]
175 while not strip(line
):
176 line
= file.readline()
178 result
= strip(split(line
, '"""')[0])
181 cache
[filename
] = (mtime
, result
)
184 class ErrorDuringImport(Exception):
185 """Errors that occurred while trying to import something to document it."""
186 def __init__(self
, filename
, (exc
, value
, tb
)):
187 self
.filename
= filename
194 if type(exc
) is types
.ClassType
:
196 return 'problem in %s - %s: %s' % (self
.filename
, exc
, self
.value
)
198 def importfile(path
):
199 """Import a Python source file or compiled file given its path."""
200 magic
= imp
.get_magic()
201 file = open(path
, 'r')
202 if file.read(len(magic
)) == magic
:
203 kind
= imp
.PY_COMPILED
207 filename
= os
.path
.basename(path
)
208 name
, ext
= os
.path
.splitext(filename
)
209 file = open(path
, 'r')
211 module
= imp
.load_module(name
, file, path
, (ext
, 'r', kind
))
213 raise ErrorDuringImport(path
, sys
.exc_info())
217 def safeimport(path
, forceload
=0, cache
={}):
218 """Import a module; handle errors; return None if the module isn't found.
220 If the module *is* found but an exception occurs, it's wrapped in an
221 ErrorDuringImport exception and reraised. Unlike __import__, if a
222 package path is specified, the module at the end of the path is returned,
223 not the package at the beginning. If the optional 'forceload' argument
224 is 1, we reload the module from disk (unless it's a dynamic extension)."""
225 if forceload
and sys
.modules
.has_key(path
):
226 # This is the only way to be sure. Checking the mtime of the file
227 # isn't good enough (e.g. what if the module contains a class that
228 # inherits from another module that has changed?).
229 if path
not in sys
.builtin_module_names
:
230 # Python never loads a dynamic extension a second time from the
231 # same path, even if the file is changed or missing. Deleting
232 # the entry in sys.modules doesn't help for dynamic extensions,
233 # so we're not even going to try to keep them up to date.
234 info
= inspect
.getmoduleinfo(sys
.modules
[path
].__file
__)
235 if info
[3] != imp
.C_EXTENSION
:
236 cache
[path
] = sys
.modules
[path
] # prevent module from clearing
237 del sys
.modules
[path
]
239 module
= __import__(path
)
241 # Did the error occur before or after the module was found?
242 (exc
, value
, tb
) = info
= sys
.exc_info()
243 if sys
.modules
.has_key(path
):
244 # An error occured while executing the imported module.
245 raise ErrorDuringImport(sys
.modules
[path
].__file
__, info
)
246 elif exc
is SyntaxError:
247 # A SyntaxError occurred before we could execute the module.
248 raise ErrorDuringImport(value
.filename
, info
)
249 elif exc
is ImportError and \
250 split(lower(str(value
)))[:2] == ['no', 'module']:
251 # The module was not found.
254 # Some other error occurred during the importing process.
255 raise ErrorDuringImport(path
, sys
.exc_info())
256 for part
in split(path
, '.')[1:]:
257 try: module
= getattr(module
, part
)
258 except AttributeError: return None
261 # ---------------------------------------------------- formatter base class
264 def document(self
, object, name
=None, *args
):
265 """Generate documentation for an object."""
266 args
= (object, name
) + args
267 if inspect
.ismodule(object): return apply(self
.docmodule
, args
)
268 if inspect
.isclass(object): return apply(self
.docclass
, args
)
269 if inspect
.isroutine(object): return apply(self
.docroutine
, args
)
270 return apply(self
.docother
, args
)
272 def fail(self
, object, name
=None, *args
):
273 """Raise an exception for unimplemented types."""
274 message
= "don't know how to document object%s of type %s" % (
275 name
and ' ' + repr(name
), type(object).__name
__)
276 raise TypeError, message
278 docmodule
= docclass
= docroutine
= docother
= fail
280 # -------------------------------------------- HTML documentation generator
282 class HTMLRepr(Repr
):
283 """Class for safely making an HTML representation of a Python object."""
286 self
.maxlist
= self
.maxtuple
= 20
288 self
.maxstring
= self
.maxother
= 100
290 def escape(self
, text
):
291 return replace(text
, '&', '&', '<', '<', '>', '>')
293 def repr(self
, object):
294 return Repr
.repr(self
, object)
296 def repr1(self
, x
, level
):
297 methodname
= 'repr_' + join(split(type(x
).__name
__), '_')
298 if hasattr(self
, methodname
):
299 return getattr(self
, methodname
)(x
, level
)
301 return self
.escape(cram(stripid(repr(x
)), self
.maxother
))
303 def repr_string(self
, x
, level
):
304 test
= cram(x
, self
.maxstring
)
305 testrepr
= repr(test
)
306 if '\\' in test
and '\\' not in replace(testrepr
, r
'\\', ''):
307 # Backslashes are only literal in the string and are never
308 # needed to make any special characters, so show a raw string.
309 return 'r' + testrepr
[0] + self
.escape(test
) + testrepr
[0]
310 return re
.sub(r
'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
311 r'<font color="#c040c0">\1</font>',
312 self
.escape(testrepr
))
314 def repr_instance(self
, x
, level
):
316 return self
.escape(cram(stripid(repr(x
)), self
.maxstring
))
318 return self
.escape('<%s instance>' % x
.__class
__.__name
__)
320 repr_unicode
= repr_string
323 """Formatter class for HTML documentation."""
325 # ------------------------------------------- HTML formatting utilities
327 _repr_instance
= HTMLRepr()
328 repr = _repr_instance
.repr
329 escape
= _repr_instance
.escape
331 def page(self
, title
, contents
):
332 """Format an HTML page."""
334 <!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">
335 <html><head><title>Python: %s</title>
336 <style type="text/css"><!--
337 TT { font-family: lucidatypewriter, lucida console, courier }
338 --></style></head><body bgcolor="#f0f0f8">
340 </body></html>''' % (title
, contents
)
342 def heading(self
, title
, fgcol
, bgcol
, extras
=''):
343 """Format a page heading."""
345 <table width="100%%" cellspacing=0 cellpadding=2 border=0>
347 <td valign=bottom> <br>
348 <font color="%s" face="helvetica, arial"> <br>%s</font></td
349 ><td align=right valign=bottom
350 ><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
351 ''' % (bgcol
, fgcol
, title
, fgcol
, extras
or ' ')
353 def section(self
, title
, fgcol
, bgcol
, contents
, width
=10,
354 prelude
='', marginalia
=None, gap
=' '):
355 """Format a section with a heading."""
356 if marginalia
is None:
357 marginalia
= '<tt>' + ' ' * width
+ '</tt>'
359 <p><table width="100%%" cellspacing=0 cellpadding=2 border=0>
361 <td colspan=3 valign=bottom> <br>
362 <font color="%s" face="helvetica, arial">%s</font></td></tr>
363 ''' % (bgcol
, fgcol
, title
)
365 result
= result
+ '''
366 <tr bgcolor="%s"><td rowspan=2>%s</td>
367 <td colspan=2>%s</td></tr>
368 <tr><td>%s</td>''' % (bgcol
, marginalia
, prelude
, gap
)
370 result
= result
+ '''
371 <tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol
, marginalia
, gap
)
373 return result
+ '\n<td width="100%%">%s</td></tr></table>' % contents
375 def bigsection(self
, title
, *args
):
376 """Format a section with a big heading."""
377 title
= '<big><strong>%s</strong></big>' % title
378 return apply(self
.section
, (title
,) + args
)
380 def preformat(self
, text
):
381 """Format literal preformatted text."""
382 text
= self
.escape(expandtabs(text
))
383 return replace(text
, '\n\n', '\n \n', '\n\n', '\n \n',
384 ' ', ' ', '\n', '<br>\n')
386 def multicolumn(self
, list, format
, cols
=4):
387 """Format a list of items into a multi-column list."""
389 rows
= (len(list)+cols
-1)/cols
390 for col
in range(cols
):
391 result
= result
+ '<td width="%d%%" valign=top>' % (100/cols
)
392 for i
in range(rows
*col
, rows
*col
+rows
):
394 result
= result
+ format(list[i
]) + '<br>\n'
395 result
= result
+ '</td>'
396 return '<table width="100%%"><tr>%s</tr></table>' % result
398 def grey(self
, text
): return '<font color="#909090">%s</font>' % text
400 def namelink(self
, name
, *dicts
):
401 """Make a link for an identifier, given name-to-URL mappings."""
403 if dict.has_key(name
):
404 return '<a href="%s">%s</a>' % (dict[name
], name
)
407 def classlink(self
, object, modname
):
408 """Make a link for a class."""
409 name
, module
= object.__name
__, sys
.modules
.get(object.__module
__)
410 if hasattr(module
, name
) and getattr(module
, name
) is object:
411 return '<a href="%s.html#%s">%s</a>' % (
412 module
.__name
__, name
, classname(object, modname
))
413 return classname(object, modname
)
415 def modulelink(self
, object):
416 """Make a link for a module."""
417 return '<a href="%s.html">%s</a>' % (object.__name
__, object.__name
__)
419 def modpkglink(self
, (name
, path
, ispackage
, shadowed
)):
420 """Make a link for a module or package to display in an index."""
422 return self
.grey(name
)
424 url
= '%s.%s.html' % (path
, name
)
426 url
= '%s.html' % name
428 text
= '<strong>%s</strong> (package)' % name
431 return '<a href="%s">%s</a>' % (url
, text
)
433 def markup(self
, text
, escape
=None, funcs
={}, classes
={}, methods
={}):
434 """Mark up some plain text, given a context of symbols to look for.
435 Each context dictionary maps object names to anchor names."""
436 escape
= escape
or self
.escape
439 pattern
= re
.compile(r
'\b((http|ftp)://\S+[\w/]|'
442 r
'(self\.)?(\w+))\b')
444 match
= pattern
.search(text
, here
)
446 start
, end
= match
.span()
447 results
.append(escape(text
[here
:start
]))
449 all
, scheme
, rfc
, pep
, selfdot
, name
= match
.groups()
451 results
.append('<a href="%s">%s</a>' % (all
, escape(all
)))
453 url
= 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc
)
454 results
.append('<a href="%s">%s</a>' % (url
, escape(all
)))
456 url
= 'http://www.python.org/peps/pep-%04d.html' % int(pep
)
457 results
.append('<a href="%s">%s</a>' % (url
, escape(all
)))
458 elif text
[end
:end
+1] == '(':
459 results
.append(self
.namelink(name
, methods
, funcs
, classes
))
461 results
.append('self.<strong>%s</strong>' % name
)
463 results
.append(self
.namelink(name
, classes
))
465 results
.append(escape(text
[here
:]))
466 return join(results
, '')
468 # ---------------------------------------------- type-specific routines
470 def formattree(self
, tree
, modname
, parent
=None):
471 """Produce HTML for a class tree as given by inspect.getclasstree()."""
474 if type(entry
) is type(()):
476 result
= result
+ '<dt><font face="helvetica, arial">'
477 result
= result
+ self
.classlink(c
, modname
)
478 if bases
and bases
!= (parent
,):
481 parents
.append(self
.classlink(base
, modname
))
482 result
= result
+ '(' + join(parents
, ', ') + ')'
483 result
= result
+ '\n</font></dt>'
484 elif type(entry
) is type([]):
485 result
= result
+ '<dd>\n%s</dd>\n' % self
.formattree(
487 return '<dl>\n%s</dl>\n' % result
489 def docmodule(self
, object, name
=None, mod
=None):
490 """Produce HTML documentation for a module object."""
491 name
= object.__name
__ # ignore the passed-in name
492 parts
= split(name
, '.')
494 for i
in range(len(parts
)-1):
496 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
497 (join(parts
[:i
+1], '.'), parts
[i
]))
498 linkedname
= join(links
+ parts
[-1:], '.')
499 head
= '<big><big><strong>%s</strong></big></big>' % linkedname
501 path
= inspect
.getabsfile(object)
503 if sys
.platform
== 'win32':
505 url
= nturl2path
.pathname2url(path
)
506 filelink
= '<a href="file:%s">%s</a>' % (url
, path
)
508 filelink
= '(built-in)'
510 if hasattr(object, '__version__'):
511 version
= str(object.__version
__)
512 if version
[:11] == '$' + 'Revision: ' and version
[-1:] == '$':
513 version
= strip(version
[11:-1])
514 info
.append('version %s' % self
.escape(version
))
515 if hasattr(object, '__date__'):
516 info
.append(self
.escape(str(object.__date
__)))
518 head
= head
+ ' (%s)' % join(info
, ', ')
519 result
= self
.heading(
520 head
, '#ffffff', '#7799ee', '<a href=".">index</a><br>' + filelink
)
522 modules
= inspect
.getmembers(object, inspect
.ismodule
)
524 classes
, cdict
= [], {}
525 for key
, value
in inspect
.getmembers(object, inspect
.isclass
):
526 if (inspect
.getmodule(value
) or object) is object:
527 classes
.append((key
, value
))
528 cdict
[key
] = cdict
[value
] = '#' + key
529 for key
, value
in classes
:
530 for base
in value
.__bases
__:
531 key
, modname
= base
.__name
__, base
.__module
__
532 module
= sys
.modules
.get(modname
)
533 if modname
!= name
and module
and hasattr(module
, key
):
534 if getattr(module
, key
) is base
:
535 if not cdict
.has_key(key
):
536 cdict
[key
] = cdict
[base
] = modname
+ '.html#' + key
537 funcs
, fdict
= [], {}
538 for key
, value
in inspect
.getmembers(object, inspect
.isroutine
):
539 if inspect
.isbuiltin(value
) or inspect
.getmodule(value
) is object:
540 funcs
.append((key
, value
))
541 fdict
[key
] = '#-' + key
542 if inspect
.isfunction(value
): fdict
[value
] = fdict
[key
]
544 for key
, value
in inspect
.getmembers(object, isdata
):
545 if key
not in ['__builtins__', '__doc__']:
546 data
.append((key
, value
))
548 doc
= self
.markup(getdoc(object), self
.preformat
, fdict
, cdict
)
549 doc
= doc
and '<tt>%s</tt>' % doc
550 result
= result
+ '<p>%s</p>\n' % doc
552 if hasattr(object, '__path__'):
555 for file in os
.listdir(object.__path
__[0]):
556 path
= os
.path
.join(object.__path
__[0], file)
557 modname
= inspect
.getmodulename(file)
558 if modname
and modname
not in modnames
:
559 modpkgs
.append((modname
, name
, 0, 0))
560 modnames
.append(modname
)
561 elif ispackage(path
):
562 modpkgs
.append((file, name
, 1, 0))
564 contents
= self
.multicolumn(modpkgs
, self
.modpkglink
)
565 result
= result
+ self
.bigsection(
566 'Package Contents', '#ffffff', '#aa55cc', contents
)
568 contents
= self
.multicolumn(
569 modules
, lambda (key
, value
), s
=self
: s
.modulelink(value
))
570 result
= result
+ self
.bigsection(
571 'Modules', '#fffff', '#aa55cc', contents
)
574 classlist
= map(lambda (key
, value
): value
, classes
)
576 self
.formattree(inspect
.getclasstree(classlist
, 1), name
)]
577 for key
, value
in classes
:
578 contents
.append(self
.document(value
, key
, name
, fdict
, cdict
))
579 result
= result
+ self
.bigsection(
580 'Classes', '#ffffff', '#ee77aa', join(contents
))
583 for key
, value
in funcs
:
584 contents
.append(self
.document(value
, key
, name
, fdict
, cdict
))
585 result
= result
+ self
.bigsection(
586 'Functions', '#ffffff', '#eeaa77', join(contents
))
589 for key
, value
in data
:
590 contents
.append(self
.document(value
, key
))
591 result
= result
+ self
.bigsection(
592 'Data', '#ffffff', '#55aa55', join(contents
, '<br>\n'))
593 if hasattr(object, '__author__'):
594 contents
= self
.markup(str(object.__author
__), self
.preformat
)
595 result
= result
+ self
.bigsection(
596 'Author', '#ffffff', '#7799ee', contents
)
597 if hasattr(object, '__credits__'):
598 contents
= self
.markup(str(object.__credits
__), self
.preformat
)
599 result
= result
+ self
.bigsection(
600 'Credits', '#ffffff', '#7799ee', contents
)
604 def docclass(self
, object, name
=None, mod
=None, funcs
={}, classes
={}):
605 """Produce HTML documentation for a class object."""
606 realname
= object.__name
__
607 name
= name
or realname
608 bases
= object.__bases
__
611 push
= contents
.append
613 # Cute little class to pump out a horizontal rule between sections.
614 class HorizontalRule
:
621 hr
= HorizontalRule()
623 # List the mro, if non-trivial.
624 mro
= list(inspect
.getmro(object))
627 push('<dl><dt>Method resolution order:</dt>\n')
629 push('<dd>%s</dd>\n' % self
.classlink(base
,
633 def spill(msg
, attrs
, predicate
):
634 ok
, attrs
= _split_list(attrs
, predicate
)
638 for name
, kind
, homecls
, value
in ok
:
639 push(self
.document(getattr(object, name
), name
, mod
,
640 funcs
, classes
, mdict
, object))
644 def spillproperties(msg
, attrs
, predicate
):
645 ok
, attrs
= _split_list(attrs
, predicate
)
649 for name
, kind
, homecls
, value
in ok
:
650 push('<dl><dt><strong>%s</strong></dt>\n' % name
)
651 if value
.__doc
__ is not None:
652 doc
= self
.markup(value
.__doc
__, self
.preformat
,
653 funcs
, classes
, mdict
)
654 push('<dd><tt>%s</tt></dd>\n' % doc
)
655 for attr
, tag
in [("fget", " getter"),
657 ("fdel", " deleter")]:
658 func
= getattr(value
, attr
)
660 base
= self
.document(func
, name
+ tag
, mod
,
661 funcs
, classes
, mdict
, object)
662 push('<dd>%s</dd>\n' % base
)
666 def spilldata(msg
, attrs
, predicate
):
667 ok
, attrs
= _split_list(attrs
, predicate
)
671 for name
, kind
, homecls
, value
in ok
:
672 base
= self
.docother(getattr(object, name
), name
, mod
)
673 doc
= getattr(value
, "__doc__", None)
675 push('<dl><dt>%s</dl>\n' % base
)
677 doc
= self
.markup(getdoc(value
), self
.preformat
,
678 funcs
, classes
, mdict
)
679 doc
= '<dd><tt>%s</tt>' % doc
680 push('<dl><dt>%s%s</dl>\n' % (base
, doc
))
684 attrs
= inspect
.classify_class_attrs(object)
686 for key
, kind
, homecls
, value
in attrs
:
687 mdict
[key
] = anchor
= '#' + name
+ '-' + key
688 value
= getattr(object, key
)
690 # The value may not be hashable (e.g., a data attr with
691 # a dict or list value).
692 mdict
[value
] = anchor
698 thisclass
= mro
.pop(0)
700 thisclass
= attrs
[0][2]
701 attrs
, inherited
= _split_list(attrs
, lambda t
: t
[2] is thisclass
)
703 if thisclass
is object:
706 tag
= "inherited from %s" % self
.classlink(thisclass
,
710 # Sort attrs by name.
711 attrs
.sort(lambda t1
, t2
: cmp(t1
[0], t2
[0]))
713 # Pump out the attrs, segregated by kind.
714 attrs
= spill("Methods %s" % tag
, attrs
,
715 lambda t
: t
[1] == 'method')
716 attrs
= spill("Class methods %s" % tag
, attrs
,
717 lambda t
: t
[1] == 'class method')
718 attrs
= spill("Static methods %s" % tag
, attrs
,
719 lambda t
: t
[1] == 'static method')
720 attrs
= spillproperties("Properties %s" % tag
, attrs
,
721 lambda t
: t
[1] == 'property')
722 attrs
= spilldata("Data and non-method functions %s" % tag
, attrs
,
723 lambda t
: t
[1] == 'data')
727 contents
= ''.join(contents
)
730 title
= '<a name="%s">class <strong>%s</strong></a>' % (
733 title
= '<strong>%s</strong> = <a name="%s">class %s</a>' % (
734 name
, name
, realname
)
738 parents
.append(self
.classlink(base
, object.__module
__))
739 title
= title
+ '(%s)' % join(parents
, ', ')
740 doc
= self
.markup(getdoc(object), self
.preformat
, funcs
, classes
, mdict
)
741 doc
= doc
and '<tt>%s<br> </tt>' % doc
or ' '
743 return self
.section(title
, '#000000', '#ffc8d8', contents
, 5, doc
)
745 def formatvalue(self
, object):
746 """Format an argument default value as text."""
747 return self
.grey('=' + self
.repr(object))
749 def docroutine(self
, object, name
=None, mod
=None,
750 funcs
={}, classes
={}, methods
={}, cl
=None):
751 """Produce HTML documentation for a function or method object."""
752 realname
= object.__name
__
753 name
= name
or realname
754 anchor
= (cl
and cl
.__name
__ or '') + '-' + name
757 if inspect
.ismethod(object):
758 imclass
= object.im_class
760 if imclass
is not cl
:
761 note
= ' from ' + self
.classlink(imclass
, mod
)
764 note
= ' method of %s instance' % self
.classlink(
765 object.im_self
.__class
__, mod
)
767 note
= ' unbound %s method' % self
.classlink(imclass
,mod
)
768 object = object.im_func
771 title
= '<a name="%s"><strong>%s</strong></a>' % (anchor
, realname
)
773 if (cl
and cl
.__dict
__.has_key(realname
) and
774 cl
.__dict
__[realname
] is object):
775 reallink
= '<a href="#%s">%s</a>' % (
776 cl
.__name
__ + '-' + realname
, realname
)
780 title
= '<a name="%s"><strong>%s</strong></a> = %s' % (
781 anchor
, name
, reallink
)
782 if inspect
.isfunction(object):
783 args
, varargs
, varkw
, defaults
= inspect
.getargspec(object)
784 argspec
= inspect
.formatargspec(
785 args
, varargs
, varkw
, defaults
, formatvalue
=self
.formatvalue
)
786 if realname
== '<lambda>':
787 decl
= '<em>lambda</em>'
788 argspec
= argspec
[1:-1] # remove parentheses
792 decl
= title
+ argspec
+ (note
and self
.grey(
793 '<font face="helvetica, arial">%s</font>' % note
))
796 return '<dl><dt>%s</dt></dl>\n' % decl
799 getdoc(object), self
.preformat
, funcs
, classes
, methods
)
800 doc
= doc
and '<dd><tt>%s</tt></dd>' % doc
801 return '<dl><dt>%s</dt>%s</dl>\n' % (decl
, doc
)
803 def docother(self
, object, name
=None, mod
=None):
804 """Produce HTML documentation for a data object."""
805 lhs
= name
and '<strong>%s</strong> = ' % name
or ''
806 return lhs
+ self
.repr(object)
808 def index(self
, dir, shadowed
=None):
809 """Generate an HTML index for a directory of modules."""
811 if shadowed
is None: shadowed
= {}
813 files
= os
.listdir(dir)
815 def found(name
, ispackage
,
816 modpkgs
=modpkgs
, shadowed
=shadowed
, seen
=seen
):
817 if not seen
.has_key(name
):
818 modpkgs
.append((name
, '', ispackage
, shadowed
.has_key(name
)))
822 # Package spam/__init__.py takes precedence over module spam.py.
824 path
= os
.path
.join(dir, file)
825 if ispackage(path
): found(file, 1)
827 path
= os
.path
.join(dir, file)
828 if os
.path
.isfile(path
):
829 modname
= inspect
.getmodulename(file)
830 if modname
: found(modname
, 0)
833 contents
= self
.multicolumn(modpkgs
, self
.modpkglink
)
834 return self
.bigsection(dir, '#ffffff', '#ee77aa', contents
)
836 # -------------------------------------------- text documentation generator
838 class TextRepr(Repr
):
839 """Class for safely making a text representation of a Python object."""
842 self
.maxlist
= self
.maxtuple
= 20
844 self
.maxstring
= self
.maxother
= 100
846 def repr1(self
, x
, level
):
847 methodname
= 'repr_' + join(split(type(x
).__name
__), '_')
848 if hasattr(self
, methodname
):
849 return getattr(self
, methodname
)(x
, level
)
851 return cram(stripid(repr(x
)), self
.maxother
)
853 def repr_string(self
, x
, level
):
854 test
= cram(x
, self
.maxstring
)
855 testrepr
= repr(test
)
856 if '\\' in test
and '\\' not in replace(testrepr
, r
'\\', ''):
857 # Backslashes are only literal in the string and are never
858 # needed to make any special characters, so show a raw string.
859 return 'r' + testrepr
[0] + test
+ testrepr
[0]
862 def repr_instance(self
, x
, level
):
864 return cram(stripid(repr(x
)), self
.maxstring
)
866 return '<%s instance>' % x
.__class
__.__name
__
869 """Formatter class for text documentation."""
871 # ------------------------------------------- text formatting utilities
873 _repr_instance
= TextRepr()
874 repr = _repr_instance
.repr
876 def bold(self
, text
):
877 """Format a string in bold by overstriking."""
878 return join(map(lambda ch
: ch
+ '\b' + ch
, text
), '')
880 def indent(self
, text
, prefix
=' '):
881 """Indent text by prepending a given prefix to each line."""
882 if not text
: return ''
883 lines
= split(text
, '\n')
884 lines
= map(lambda line
, prefix
=prefix
: prefix
+ line
, lines
)
885 if lines
: lines
[-1] = rstrip(lines
[-1])
886 return join(lines
, '\n')
888 def section(self
, title
, contents
):
889 """Format a section with a given heading."""
890 return self
.bold(title
) + '\n' + rstrip(self
.indent(contents
)) + '\n\n'
892 # ---------------------------------------------- type-specific routines
894 def formattree(self
, tree
, modname
, parent
=None, prefix
=''):
895 """Render in text a class tree as returned by inspect.getclasstree()."""
898 if type(entry
) is type(()):
900 result
= result
+ prefix
+ classname(c
, modname
)
901 if bases
and bases
!= (parent
,):
902 parents
= map(lambda c
, m
=modname
: classname(c
, m
), bases
)
903 result
= result
+ '(%s)' % join(parents
, ', ')
904 result
= result
+ '\n'
905 elif type(entry
) is type([]):
906 result
= result
+ self
.formattree(
907 entry
, modname
, c
, prefix
+ ' ')
910 def docmodule(self
, object, name
=None, mod
=None):
911 """Produce text documentation for a given module object."""
912 name
= object.__name
__ # ignore the passed-in name
913 synop
, desc
= splitdoc(getdoc(object))
914 result
= self
.section('NAME', name
+ (synop
and ' - ' + synop
))
917 file = inspect
.getabsfile(object)
920 result
= result
+ self
.section('FILE', file)
922 result
= result
+ self
.section('DESCRIPTION', desc
)
925 for key
, value
in inspect
.getmembers(object, inspect
.isclass
):
926 if (inspect
.getmodule(value
) or object) is object:
927 classes
.append((key
, value
))
929 for key
, value
in inspect
.getmembers(object, inspect
.isroutine
):
930 if inspect
.isbuiltin(value
) or inspect
.getmodule(value
) is object:
931 funcs
.append((key
, value
))
933 for key
, value
in inspect
.getmembers(object, isdata
):
934 if key
not in ['__builtins__', '__doc__']:
935 data
.append((key
, value
))
937 if hasattr(object, '__path__'):
939 for file in os
.listdir(object.__path
__[0]):
940 path
= os
.path
.join(object.__path
__[0], file)
941 modname
= inspect
.getmodulename(file)
942 if modname
and modname
not in modpkgs
:
943 modpkgs
.append(modname
)
944 elif ispackage(path
):
945 modpkgs
.append(file + ' (package)')
947 result
= result
+ self
.section(
948 'PACKAGE CONTENTS', join(modpkgs
, '\n'))
951 classlist
= map(lambda (key
, value
): value
, classes
)
952 contents
= [self
.formattree(
953 inspect
.getclasstree(classlist
, 1), name
)]
954 for key
, value
in classes
:
955 contents
.append(self
.document(value
, key
, name
))
956 result
= result
+ self
.section('CLASSES', join(contents
, '\n'))
960 for key
, value
in funcs
:
961 contents
.append(self
.document(value
, key
, name
))
962 result
= result
+ self
.section('FUNCTIONS', join(contents
, '\n'))
966 for key
, value
in data
:
967 contents
.append(self
.docother(value
, key
, name
, 70))
968 result
= result
+ self
.section('DATA', join(contents
, '\n'))
970 if hasattr(object, '__version__'):
971 version
= str(object.__version
__)
972 if version
[:11] == '$' + 'Revision: ' and version
[-1:] == '$':
973 version
= strip(version
[11:-1])
974 result
= result
+ self
.section('VERSION', version
)
975 if hasattr(object, '__date__'):
976 result
= result
+ self
.section('DATE', str(object.__date
__))
977 if hasattr(object, '__author__'):
978 result
= result
+ self
.section('AUTHOR', str(object.__author
__))
979 if hasattr(object, '__credits__'):
980 result
= result
+ self
.section('CREDITS', str(object.__credits
__))
983 def docclass(self
, object, name
=None, mod
=None):
984 """Produce text documentation for a given class object."""
985 realname
= object.__name
__
986 name
= name
or realname
987 bases
= object.__bases
__
989 def makename(c
, m
=object.__module
__):
990 return classname(c
, m
)
993 title
= 'class ' + self
.bold(realname
)
995 title
= self
.bold(name
) + ' = class ' + realname
997 parents
= map(makename
, bases
)
998 title
= title
+ '(%s)' % join(parents
, ', ')
1000 doc
= getdoc(object)
1001 contents
= doc
and [doc
+ '\n'] or []
1002 push
= contents
.append
1004 # List the mro, if non-trivial.
1005 mro
= list(inspect
.getmro(object))
1007 push("Method resolution order:")
1009 push(' ' + makename(base
))
1012 # Cute little class to pump out a horizontal rule between sections.
1013 class HorizontalRule
:
1020 hr
= HorizontalRule()
1022 def spill(msg
, attrs
, predicate
):
1023 ok
, attrs
= _split_list(attrs
, predicate
)
1027 for name
, kind
, homecls
, value
in ok
:
1028 push(self
.document(getattr(object, name
),
1032 def spillproperties(msg
, attrs
, predicate
):
1033 ok
, attrs
= _split_list(attrs
, predicate
)
1037 for name
, kind
, homecls
, value
in ok
:
1039 need_blank_after_doc
= 0
1040 doc
= getdoc(value
) or ''
1042 push(self
.indent(doc
))
1043 need_blank_after_doc
= 1
1044 for attr
, tag
in [("fget", " getter"),
1045 ("fset", " setter"),
1046 ("fdel", " deleter")]:
1047 func
= getattr(value
, attr
)
1048 if func
is not None:
1049 if need_blank_after_doc
:
1051 need_blank_after_doc
= 0
1052 base
= self
.docother(func
, name
+ tag
, mod
, 70)
1053 push(self
.indent(base
))
1057 def spilldata(msg
, attrs
, predicate
):
1058 ok
, attrs
= _split_list(attrs
, predicate
)
1062 for name
, kind
, homecls
, value
in ok
:
1063 doc
= getattr(value
, "__doc__", None)
1064 push(self
.docother(getattr(object, name
),
1065 name
, mod
, 70, doc
) + '\n')
1068 attrs
= inspect
.classify_class_attrs(object)
1071 thisclass
= mro
.pop(0)
1073 thisclass
= attrs
[0][2]
1074 attrs
, inherited
= _split_list(attrs
, lambda t
: t
[2] is thisclass
)
1076 if thisclass
is object:
1077 tag
= "defined here"
1079 tag
= "inherited from %s" % classname(thisclass
,
1082 # Sort attrs by name.
1083 attrs
.sort(lambda t1
, t2
: cmp(t1
[0], t2
[0]))
1085 # Pump out the attrs, segregated by kind.
1086 attrs
= spill("Methods %s:\n" % tag
, attrs
,
1087 lambda t
: t
[1] == 'method')
1088 attrs
= spill("Class methods %s:\n" % tag
, attrs
,
1089 lambda t
: t
[1] == 'class method')
1090 attrs
= spill("Static methods %s:\n" % tag
, attrs
,
1091 lambda t
: t
[1] == 'static method')
1092 attrs
= spillproperties("Properties %s:\n" % tag
, attrs
,
1093 lambda t
: t
[1] == 'property')
1094 attrs
= spilldata("Data and non-method functions %s:\n" % tag
,
1095 attrs
, lambda t
: t
[1] == 'data')
1099 contents
= '\n'.join(contents
)
1102 return title
+ '\n' + self
.indent(rstrip(contents
), ' | ') + '\n'
1104 def formatvalue(self
, object):
1105 """Format an argument default value as text."""
1106 return '=' + self
.repr(object)
1108 def docroutine(self
, object, name
=None, mod
=None, cl
=None):
1109 """Produce text documentation for a function or method object."""
1110 realname
= object.__name
__
1111 name
= name
or realname
1114 if inspect
.ismethod(object):
1115 imclass
= object.im_class
1117 if imclass
is not cl
:
1118 note
= ' from ' + classname(imclass
, mod
)
1121 note
= ' method of %s instance' % classname(
1122 object.im_self
.__class
__, mod
)
1124 note
= ' unbound %s method' % classname(imclass
,mod
)
1125 object = object.im_func
1127 if name
== realname
:
1128 title
= self
.bold(realname
)
1130 if (cl
and cl
.__dict
__.has_key(realname
) and
1131 cl
.__dict
__[realname
] is object):
1133 title
= self
.bold(name
) + ' = ' + realname
1134 if inspect
.isfunction(object):
1135 args
, varargs
, varkw
, defaults
= inspect
.getargspec(object)
1136 argspec
= inspect
.formatargspec(
1137 args
, varargs
, varkw
, defaults
, formatvalue
=self
.formatvalue
)
1138 if realname
== '<lambda>':
1140 argspec
= argspec
[1:-1] # remove parentheses
1143 decl
= title
+ argspec
+ note
1148 doc
= getdoc(object) or ''
1149 return decl
+ '\n' + (doc
and rstrip(self
.indent(doc
)) + '\n')
1151 def docother(self
, object, name
=None, mod
=None, maxlen
=None, doc
=None):
1152 """Produce text documentation for a data object."""
1153 repr = self
.repr(object)
1155 line
= (name
and name
+ ' = ' or '') + repr
1156 chop
= maxlen
- len(line
)
1157 if chop
< 0: repr = repr[:chop
] + '...'
1158 line
= (name
and self
.bold(name
) + ' = ' or '') + repr
1160 line
+= '\n' + self
.indent(str(doc
))
1163 # --------------------------------------------------------- user interfaces
1166 """The first time this is called, determine what kind of pager to use."""
1172 """Decide what method to use for paging through text."""
1173 if type(sys
.stdout
) is not types
.FileType
:
1175 if not sys
.stdin
.isatty() or not sys
.stdout
.isatty():
1177 if os
.environ
.get('TERM') in ['dumb', 'emacs']:
1179 if os
.environ
.has_key('PAGER'):
1180 if sys
.platform
== 'win32': # pipes completely broken in Windows
1181 return lambda text
: tempfilepager(plain(text
), os
.environ
['PAGER'])
1182 elif os
.environ
.get('TERM') in ['dumb', 'emacs']:
1183 return lambda text
: pipepager(plain(text
), os
.environ
['PAGER'])
1185 return lambda text
: pipepager(text
, os
.environ
['PAGER'])
1186 if sys
.platform
== 'win32':
1187 return lambda text
: tempfilepager(plain(text
), 'more <')
1188 if hasattr(os
, 'system') and os
.system('less 2>/dev/null') == 0:
1189 return lambda text
: pipepager(text
, 'less')
1192 filename
= tempfile
.mktemp()
1193 open(filename
, 'w').close()
1195 if hasattr(os
, 'system') and os
.system('more %s' % filename
) == 0:
1196 return lambda text
: pipepager(text
, 'more')
1203 """Remove boldface formatting from text."""
1204 return re
.sub('.\b', '', text
)
1206 def pipepager(text
, cmd
):
1207 """Page through text by feeding it to another program."""
1208 pipe
= os
.popen(cmd
, 'w')
1213 pass # Ignore broken pipes caused by quitting the pager program.
1215 def tempfilepager(text
, cmd
):
1216 """Page through text by invoking a program on a temporary file."""
1218 filename
= tempfile
.mktemp()
1219 file = open(filename
, 'w')
1223 os
.system(cmd
+ ' ' + filename
)
1228 """Page through text on a text terminal."""
1229 lines
= split(plain(text
), '\n')
1232 fd
= sys
.stdin
.fileno()
1233 old
= tty
.tcgetattr(fd
)
1235 getchar
= lambda: sys
.stdin
.read(1)
1236 except (ImportError, AttributeError):
1238 getchar
= lambda: sys
.stdin
.readline()[:-1][:1]
1241 r
= inc
= os
.environ
.get('LINES', 25) - 1
1242 sys
.stdout
.write(join(lines
[:inc
], '\n') + '\n')
1244 sys
.stdout
.write('-- more --')
1249 sys
.stdout
.write('\r \r')
1251 elif c
in ['\r', '\n']:
1252 sys
.stdout
.write('\r \r' + lines
[r
] + '\n')
1255 if c
in ['b', 'B', '\x1b']:
1258 sys
.stdout
.write('\n' + join(lines
[r
:r
+inc
], '\n') + '\n')
1263 tty
.tcsetattr(fd
, tty
.TCSAFLUSH
, old
)
1265 def plainpager(text
):
1266 """Simply print unformatted text. This is the ultimate fallback."""
1267 sys
.stdout
.write(plain(text
))
1269 def describe(thing
):
1270 """Produce a short description of the given thing."""
1271 if inspect
.ismodule(thing
):
1272 if thing
.__name
__ in sys
.builtin_module_names
:
1273 return 'built-in module ' + thing
.__name
__
1274 if hasattr(thing
, '__path__'):
1275 return 'package ' + thing
.__name
__
1277 return 'module ' + thing
.__name
__
1278 if inspect
.isbuiltin(thing
):
1279 return 'built-in function ' + thing
.__name
__
1280 if inspect
.isclass(thing
):
1281 return 'class ' + thing
.__name
__
1282 if inspect
.isfunction(thing
):
1283 return 'function ' + thing
.__name
__
1284 if inspect
.ismethod(thing
):
1285 return 'method ' + thing
.__name
__
1286 if type(thing
) is types
.InstanceType
:
1287 return 'instance of ' + thing
.__class
__.__name
__
1288 return type(thing
).__name
__
1290 def locate(path
, forceload
=0):
1291 """Locate an object by name or dotted path, importing as necessary."""
1292 parts
= split(path
, '.')
1294 while n
< len(parts
):
1295 nextmodule
= safeimport(join(parts
[:n
+1], '.'), forceload
)
1296 if nextmodule
: module
, n
= nextmodule
, n
+ 1
1300 for part
in parts
[n
:]:
1301 try: object = getattr(object, part
)
1302 except AttributeError: return None
1306 if hasattr(__builtin__
, path
):
1307 return getattr(__builtin__
, path
)
1309 # --------------------------------------- interactive interpreter interface
1314 def doc(thing
, title
='Python Library Documentation: %s', forceload
=0):
1315 """Display text documentation, given an object or a path to an object."""
1316 suffix
, name
= '', None
1317 if type(thing
) is type(''):
1319 object = locate(thing
, forceload
)
1320 except ErrorDuringImport
, value
:
1324 print 'no Python documentation found for %s' % repr(thing
)
1326 parts
= split(thing
, '.')
1327 if len(parts
) > 1: suffix
= ' in ' + join(parts
[:-1], '.')
1331 desc
= describe(thing
)
1332 module
= inspect
.getmodule(thing
)
1333 if not suffix
and module
and module
is not thing
:
1334 suffix
= ' in module ' + module
.__name
__
1335 pager(title
% (desc
+ suffix
) + '\n\n' + text
.document(thing
, name
))
1337 def writedoc(key
, forceload
=0):
1338 """Write HTML documentation to a file in the current directory."""
1340 object = locate(key
, forceload
)
1341 except ErrorDuringImport
, value
:
1345 page
= html
.page(describe(object),
1346 html
.document(object, object.__name
__))
1347 file = open(key
+ '.html', 'w')
1350 print 'wrote', key
+ '.html'
1352 print 'no Python documentation found for %s' % repr(key
)
1354 def writedocs(dir, pkgpath
='', done
=None):
1355 """Write out HTML documentation for all modules in a directory tree."""
1356 if done
is None: done
= {}
1357 for file in os
.listdir(dir):
1358 path
= os
.path
.join(dir, file)
1360 writedocs(path
, pkgpath
+ file + '.', done
)
1361 elif os
.path
.isfile(path
):
1362 modname
= inspect
.getmodulename(path
)
1364 modname
= pkgpath
+ modname
1365 if not done
.has_key(modname
):
1372 'assert': ('ref/assert', ''),
1373 'break': ('ref/break', 'while for'),
1374 'class': ('ref/class', 'CLASSES SPECIALMETHODS'),
1375 'continue': ('ref/continue', 'while for'),
1376 'def': ('ref/function', ''),
1377 'del': ('ref/del', 'BASICMETHODS'),
1379 'else': ('ref/if', 'while for'),
1381 'exec': ('ref/exec', ''),
1383 'for': ('ref/for', 'break continue while'),
1385 'global': ('ref/global', 'NAMESPACES'),
1386 'if': ('ref/if', 'TRUTHVALUE'),
1387 'import': ('ref/import', 'MODULES'),
1388 'in': ('ref/comparisons', 'SEQUENCEMETHODS2'),
1390 'lambda': ('ref/lambda', 'FUNCTIONS'),
1394 'print': ('ref/print', ''),
1395 'raise': ('ref/raise', 'EXCEPTIONS'),
1396 'return': ('ref/return', 'FUNCTIONS'),
1397 'try': ('ref/try', 'EXCEPTIONS'),
1398 'while': ('ref/while', 'break continue if TRUTHVALUE'),
1402 'TYPES': ('ref/types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS FUNCTIONS CLASSES MODULES FILES inspect'),
1403 'STRINGS': ('ref/strings', 'str UNICODE SEQUENCES STRINGMETHODS FORMATTING TYPES'),
1404 'STRINGMETHODS': ('lib/string-methods', 'STRINGS FORMATTING'),
1405 'FORMATTING': ('lib/typesseq-strings', 'OPERATORS'),
1406 'UNICODE': ('ref/unicode', 'encodings unicode TYPES STRING'),
1407 'NUMBERS': ('ref/numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1408 'INTEGER': ('ref/integers', 'int range'),
1409 'FLOAT': ('ref/floating', 'float math'),
1410 'COMPLEX': ('ref/imaginary', 'complex cmath'),
1411 'SEQUENCES': ('lib/typesseq', 'STRINGMETHODS FORMATTING xrange LISTS'),
1412 'MAPPINGS': 'DICTIONARIES',
1413 'FUNCTIONS': ('lib/typesfunctions', 'def TYPES'),
1414 'METHODS': ('lib/typesmethods', 'class def CLASSES TYPES'),
1415 'CODEOBJECTS': ('lib/bltin-code-objects', 'compile FUNCTIONS TYPES'),
1416 'TYPEOBJECTS': ('lib/bltin-type-objects', 'types TYPES'),
1417 'FRAMEOBJECTS': 'TYPES',
1418 'TRACEBACKS': 'TYPES',
1419 'NONE': ('lib/bltin-null-object', ''),
1420 'ELLIPSIS': ('lib/bltin-ellipsis-object', 'SLICINGS'),
1421 'FILES': ('lib/bltin-file-objects', ''),
1422 'SPECIALATTRIBUTES': ('lib/specialattrs', ''),
1423 'CLASSES': ('ref/types', 'class SPECIALMETHODS PRIVATENAMES'),
1424 'MODULES': ('lib/typesmodules', 'import'),
1425 'PACKAGES': 'import',
1426 'EXPRESSIONS': ('ref/summary', 'lambda or and not in is BOOLEAN COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES LISTS DICTIONARIES BACKQUOTES'),
1427 'OPERATORS': 'EXPRESSIONS',
1428 'PRECEDENCE': 'EXPRESSIONS',
1429 'OBJECTS': ('ref/objects', 'TYPES'),
1430 'SPECIALMETHODS': ('ref/specialnames', 'BASICMETHODS ATTRIBUTEMETHODS CALLABLEMETHODS SEQUENCEMETHODS1 MAPPINGMETHODS SEQUENCEMETHODS2 NUMBERMETHODS CLASSES'),
1431 'BASICMETHODS': ('ref/customization', 'cmp hash repr str SPECIALMETHODS'),
1432 'ATTRIBUTEMETHODS': ('ref/attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1433 'CALLABLEMETHODS': ('ref/callable-types', 'CALLS SPECIALMETHODS'),
1434 'SEQUENCEMETHODS1': ('ref/sequence-types', 'SEQUENCES SEQUENCEMETHODS2 SPECIALMETHODS'),
1435 'SEQUENCEMETHODS2': ('ref/sequence-methods', 'SEQUENCES SEQUENCEMETHODS1 SPECIALMETHODS'),
1436 'MAPPINGMETHODS': ('ref/sequence-types', 'MAPPINGS SPECIALMETHODS'),
1437 'NUMBERMETHODS': ('ref/numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT SPECIALMETHODS'),
1438 'EXECUTION': ('ref/execframes', ''),
1439 'NAMESPACES': ('ref/execframes', 'global ASSIGNMENT DELETION'),
1440 'SCOPING': 'NAMESPACES',
1441 'FRAMES': 'NAMESPACES',
1442 'EXCEPTIONS': ('ref/exceptions', 'try except finally raise'),
1443 'COERCIONS': 'CONVERSIONS',
1444 'CONVERSIONS': ('ref/conversions', ''),
1445 'IDENTIFIERS': ('ref/identifiers', 'keywords SPECIALIDENTIFIERS'),
1446 'SPECIALIDENTIFIERS': ('ref/id-classes', ''),
1447 'PRIVATENAMES': ('ref/atom-identifiers', ''),
1448 'LITERALS': ('ref/atom-literals', 'STRINGS BACKQUOTES NUMBERS TUPLELITERALS LISTLITERALS DICTIONARYLITERALS'),
1449 'TUPLES': 'SEQUENCES',
1450 'TUPLELITERALS': ('ref/exprlists', 'TUPLES LITERALS'),
1451 'LISTS': ('lib/typesseq-mutable', 'LISTLITERALS'),
1452 'LISTLITERALS': ('ref/lists', 'LISTS LITERALS'),
1453 'DICTIONARIES': ('lib/typesmapping', 'DICTIONARYLITERALS'),
1454 'DICTIONARYLITERALS': ('ref/dict', 'DICTIONARIES LITERALS'),
1455 'BACKQUOTES': ('ref/string-conversions', 'repr str STRINGS LITERALS'),
1456 'ATTRIBUTES': ('ref/attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
1457 'SUBSCRIPTS': ('ref/subscriptions', 'SEQUENCEMETHODS1'),
1458 'SLICINGS': ('ref/slicings', 'SEQUENCEMETHODS2'),
1459 'CALLS': ('ref/calls', 'EXPRESSIONS'),
1460 'POWER': ('ref/power', 'EXPRESSIONS'),
1461 'UNARY': ('ref/unary', 'EXPRESSIONS'),
1462 'BINARY': ('ref/binary', 'EXPRESSIONS'),
1463 'SHIFTING': ('ref/shifting', 'EXPRESSIONS'),
1464 'BITWISE': ('ref/bitwise', 'EXPRESSIONS'),
1465 'COMPARISON': ('ref/comparisons', 'EXPRESSIONS BASICMETHODS'),
1466 'BOOLEAN': ('ref/lambda', 'EXPRESSIONS TRUTHVALUE'),
1467 'ASSERTION': 'assert',
1468 'ASSIGNMENT': ('ref/assignment', 'AUGMENTEDASSIGNMENT'),
1469 'AUGMENTEDASSIGNMENT': ('ref/augassign', 'NUMBERMETHODS'),
1471 'PRINTING': 'print',
1472 'RETURNING': 'return',
1473 'IMPORTING': 'import',
1474 'CONDITIONAL': 'if',
1475 'LOOPING': ('ref/compound', 'for while break continue'),
1476 'TRUTHVALUE': ('lib/truth', 'if while and or not BASICMETHODS'),
1477 'DEBUGGING': ('lib/module-pdb', 'pdb'),
1480 def __init__(self
, input, output
):
1482 self
.output
= output
1484 execdir
= os
.path
.dirname(sys
.executable
)
1485 homedir
= os
.environ
.get('PYTHONHOME')
1486 for dir in [os
.environ
.get('PYTHONDOCS'),
1487 homedir
and os
.path
.join(homedir
, 'doc'),
1488 os
.path
.join(execdir
, 'doc'),
1489 '/usr/doc/python-docs-' + split(sys
.version
)[0],
1490 '/usr/doc/python-' + split(sys
.version
)[0],
1491 '/usr/doc/python-docs-' + sys
.version
[:3],
1492 '/usr/doc/python-' + sys
.version
[:3]]:
1493 if dir and os
.path
.isdir(os
.path
.join(dir, 'lib')):
1497 if inspect
.stack()[1][3] == '?':
1500 return '<pydoc.Helper instance>'
1502 def __call__(self
, request
=None):
1503 if request
is not None:
1508 self
.output
.write('''
1509 You are now leaving help and returning to the Python interpreter.
1510 If you want to ask for help on a particular object directly from the
1511 interpreter, you can type "help(object)". Executing "help('string')"
1512 has the same effect as typing a particular string at the help> prompt.
1516 self
.output
.write('\n')
1518 self
.output
.write('help> ')
1521 request
= self
.input.readline()
1522 if not request
: break
1523 except KeyboardInterrupt: break
1524 request
= strip(replace(request
, '"', '', "'", ''))
1525 if lower(request
) in ['q', 'quit']: break
1528 def help(self
, request
):
1529 if type(request
) is type(''):
1530 if request
== 'help': self
.intro()
1531 elif request
== 'keywords': self
.listkeywords()
1532 elif request
== 'topics': self
.listtopics()
1533 elif request
== 'modules': self
.listmodules()
1534 elif request
[:8] == 'modules ':
1535 self
.listmodules(split(request
)[1])
1536 elif self
.keywords
.has_key(request
): self
.showtopic(request
)
1537 elif self
.topics
.has_key(request
): self
.showtopic(request
)
1538 elif request
: doc(request
, 'Help on %s:')
1539 elif isinstance(request
, Helper
): self()
1540 else: doc(request
, 'Help on %s:')
1541 self
.output
.write('\n')
1544 self
.output
.write('''
1545 Welcome to Python %s! This is the online help utility.
1547 If this is your first time using Python, you should definitely check out
1548 the tutorial on the Internet at http://www.python.org/doc/tut/.
1550 Enter the name of any module, keyword, or topic to get help on writing
1551 Python programs and using Python modules. To quit this help utility and
1552 return to the interpreter, just type "quit".
1554 To get a list of available modules, keywords, or topics, type "modules",
1555 "keywords", or "topics". Each module also comes with a one-line summary
1556 of what it does; to list the modules whose summaries contain a given word
1557 such as "spam", type "modules spam".
1558 ''' % sys
.version
[:3])
1560 def list(self
, items
, columns
=4, width
=80):
1563 colw
= width
/ columns
1564 rows
= (len(items
) + columns
- 1) / columns
1565 for row
in range(rows
):
1566 for col
in range(columns
):
1567 i
= col
* rows
+ row
1569 self
.output
.write(items
[i
])
1570 if col
< columns
- 1:
1571 self
.output
.write(' ' + ' ' * (colw
-1 - len(items
[i
])))
1572 self
.output
.write('\n')
1574 def listkeywords(self
):
1575 self
.output
.write('''
1576 Here is a list of the Python keywords. Enter any keyword to get more help.
1579 self
.list(self
.keywords
.keys())
1581 def listtopics(self
):
1582 self
.output
.write('''
1583 Here is a list of available topics. Enter any topic name to get more help.
1586 self
.list(self
.topics
.keys())
1588 def showtopic(self
, topic
):
1590 self
.output
.write('''
1591 Sorry, topic and keyword documentation is not available because the Python
1592 HTML documentation files could not be found. If you have installed them,
1593 please set the environment variable PYTHONDOCS to indicate their location.
1596 target
= self
.topics
.get(topic
, self
.keywords
.get(topic
))
1598 self
.output
.write('no documentation found for %s\n' % repr(topic
))
1600 if type(target
) is type(''):
1601 return self
.showtopic(target
)
1603 filename
, xrefs
= target
1604 filename
= self
.docdir
+ '/' + filename
+ '.html'
1606 file = open(filename
)
1608 self
.output
.write('could not read docs from %s\n' % filename
)
1611 divpat
= re
.compile('<div[^>]*navigat.*?</div.*?>', re
.I | re
.S
)
1612 addrpat
= re
.compile('<address.*?>.*?</address.*?>', re
.I | re
.S
)
1613 document
= re
.sub(addrpat
, '', re
.sub(divpat
, '', file.read()))
1616 import htmllib
, formatter
, StringIO
1617 buffer = StringIO
.StringIO()
1618 parser
= htmllib
.HTMLParser(
1619 formatter
.AbstractFormatter(formatter
.DumbWriter(buffer)))
1620 parser
.start_table
= parser
.do_p
1621 parser
.end_table
= lambda parser
=parser
: parser
.do_p({})
1622 parser
.start_tr
= parser
.do_br
1623 parser
.start_td
= parser
.start_th
= lambda a
, b
=buffer: b
.write('\t')
1624 parser
.feed(document
)
1625 buffer = replace(buffer.getvalue(), '\xa0', ' ', '\n', '\n ')
1626 pager(' ' + strip(buffer) + '\n')
1628 buffer = StringIO
.StringIO()
1629 formatter
.DumbWriter(buffer).send_flowing_data(
1630 'Related help topics: ' + join(split(xrefs
), ', ') + '\n')
1631 self
.output
.write('\n%s\n' % buffer.getvalue())
1633 def listmodules(self
, key
=''):
1635 self
.output
.write('''
1636 Here is a list of matching modules. Enter any module name to get more help.
1641 self
.output
.write('''
1642 Please wait a moment while I gather a list of all available modules...
1646 def callback(path
, modname
, desc
, modules
=modules
):
1647 if modname
and modname
[-9:] == '.__init__':
1648 modname
= modname
[:-9] + ' (package)'
1649 if find(modname
, '.') < 0:
1650 modules
[modname
] = 1
1651 ModuleScanner().run(callback
)
1652 self
.list(modules
.keys())
1653 self
.output
.write('''
1654 Enter any module name to get more help. Or, type "modules spam" to search
1655 for modules whose descriptions contain the word "spam".
1658 help = Helper(sys
.stdin
, sys
.stdout
)
1661 """A generic tree iterator."""
1662 def __init__(self
, roots
, children
, descendp
):
1663 self
.roots
= roots
[:]
1665 self
.children
= children
1666 self
.descendp
= descendp
1672 root
= self
.roots
.pop(0)
1673 self
.state
= [(root
, self
.children(root
))]
1674 node
, children
= self
.state
[-1]
1678 child
= children
.pop(0)
1679 if self
.descendp(child
):
1680 self
.state
.append((child
, self
.children(child
)))
1683 class ModuleScanner(Scanner
):
1684 """An interruptible scanner that searches module synopses."""
1686 roots
= map(lambda dir: (dir, ''), pathdirs())
1687 Scanner
.__init
__(self
, roots
, self
.submodules
, self
.isnewpackage
)
1688 self
.inodes
= map(lambda (dir, pkg
): os
.stat(dir)[1], roots
)
1690 def submodules(self
, (dir, package
)):
1692 for file in os
.listdir(dir):
1693 path
= os
.path
.join(dir, file)
1695 children
.append((path
, package
+ (package
and '.') + file))
1697 children
.append((path
, package
))
1698 children
.sort() # so that spam.py comes before spam.pyc or spam.pyo
1701 def isnewpackage(self
, (dir, package
)):
1702 inode
= os
.path
.exists(dir) and os
.stat(dir)[1]
1703 if not (os
.path
.islink(dir) and inode
in self
.inodes
):
1704 self
.inodes
.append(inode
) # detect circular symbolic links
1705 return ispackage(dir)
1707 def run(self
, callback
, key
=None, completer
=None):
1708 if key
: key
= lower(key
)
1712 for modname
in sys
.builtin_module_names
:
1713 if modname
!= '__main__':
1716 callback(None, modname
, '')
1718 desc
= split(__import__(modname
).__doc
__ or '', '\n')[0]
1719 if find(lower(modname
+ ' - ' + desc
), key
) >= 0:
1720 callback(None, modname
, desc
)
1722 while not self
.quit
:
1725 path
, package
= node
1726 modname
= inspect
.getmodulename(path
)
1727 if os
.path
.isfile(path
) and modname
:
1728 modname
= package
+ (package
and '.') + modname
1729 if not seen
.has_key(modname
):
1730 seen
[modname
] = 1 # if we see spam.py, skip spam.pyc
1732 callback(path
, modname
, '')
1734 desc
= synopsis(path
) or ''
1735 if find(lower(modname
+ ' - ' + desc
), key
) >= 0:
1736 callback(path
, modname
, desc
)
1737 if completer
: completer()
1740 """Print all the one-line module summaries that contain a substring."""
1741 def callback(path
, modname
, desc
):
1742 if modname
[-9:] == '.__init__':
1743 modname
= modname
[:-9] + ' (package)'
1744 print modname
, desc
and '- ' + desc
1745 try: import warnings
1746 except ImportError: pass
1747 else: warnings
.filterwarnings('ignore') # ignore problems during import
1748 ModuleScanner().run(callback
, key
)
1750 # --------------------------------------------------- web browser interface
1752 def serve(port
, callback
=None, completer
=None):
1753 import BaseHTTPServer
, mimetools
, select
1755 # Patch up mimetools.Message so it doesn't break if rfc822 is reloaded.
1756 class Message(mimetools
.Message
):
1757 def __init__(self
, fp
, seekable
=1):
1758 Message
= self
.__class
__
1759 Message
.__bases
__[0].__bases
__[0].__init
__(self
, fp
, seekable
)
1760 self
.encodingheader
= self
.getheader('content-transfer-encoding')
1761 self
.typeheader
= self
.getheader('content-type')
1765 class DocHandler(BaseHTTPServer
.BaseHTTPRequestHandler
):
1766 def send_document(self
, title
, contents
):
1768 self
.send_response(200)
1769 self
.send_header('Content-Type', 'text/html')
1771 self
.wfile
.write(html
.page(title
, contents
))
1772 except IOError: pass
1776 if path
[-5:] == '.html': path
= path
[:-5]
1777 if path
[:1] == '/': path
= path
[1:]
1778 if path
and path
!= '.':
1780 obj
= locate(path
, forceload
=1)
1781 except ErrorDuringImport
, value
:
1782 self
.send_document(path
, html
.escape(str(value
)))
1785 self
.send_document(describe(obj
), html
.document(obj
, path
))
1787 self
.send_document(path
,
1788 'no Python documentation found for %s' % repr(path
))
1790 heading
= html
.heading(
1791 '<big><big><strong>Python: Index of Modules</strong></big></big>',
1792 '#ffffff', '#7799ee')
1793 def bltinlink(name
):
1794 return '<a href="%s.html">%s</a>' % (name
, name
)
1795 names
= filter(lambda x
: x
!= '__main__',
1796 sys
.builtin_module_names
)
1797 contents
= html
.multicolumn(names
, bltinlink
)
1798 indices
= ['<p>' + html
.bigsection(
1799 'Built-in Modules', '#ffffff', '#ee77aa', contents
)]
1802 for dir in pathdirs():
1803 indices
.append(html
.index(dir, seen
))
1804 contents
= heading
+ join(indices
) + '''<p align=right>
1805 <font color="#909090" face="helvetica, arial"><strong>
1806 pydoc</strong> by Ka-Ping Yee <ping@lfw.org></font>'''
1807 self
.send_document('Index of Modules', contents
)
1809 def log_message(self
, *args
): pass
1811 class DocServer(BaseHTTPServer
.HTTPServer
):
1812 def __init__(self
, port
, callback
):
1813 host
= (sys
.platform
== 'mac') and '127.0.0.1' or 'localhost'
1814 self
.address
= ('', port
)
1815 self
.url
= 'http://%s:%d/' % (host
, port
)
1816 self
.callback
= callback
1817 self
.base
.__init
__(self
, self
.address
, self
.handler
)
1819 def serve_until_quit(self
):
1822 while not self
.quit
:
1823 rd
, wr
, ex
= select
.select([self
.socket
.fileno()], [], [], 1)
1824 if rd
: self
.handle_request()
1826 def server_activate(self
):
1827 self
.base
.server_activate(self
)
1828 if self
.callback
: self
.callback(self
)
1830 DocServer
.base
= BaseHTTPServer
.HTTPServer
1831 DocServer
.handler
= DocHandler
1832 DocHandler
.MessageClass
= Message
1835 DocServer(port
, callback
).serve_until_quit()
1836 except (KeyboardInterrupt, select
.error
):
1839 if completer
: completer()
1841 # ----------------------------------------------------- graphical interface
1844 """Graphical interface (starts web server and pops up a control window)."""
1846 def __init__(self
, window
, port
=7464):
1847 self
.window
= window
1852 self
.server_frm
= Tkinter
.Frame(window
)
1853 self
.title_lbl
= Tkinter
.Label(self
.server_frm
,
1854 text
='Starting server...\n ')
1855 self
.open_btn
= Tkinter
.Button(self
.server_frm
,
1856 text
='open browser', command
=self
.open, state
='disabled')
1857 self
.quit_btn
= Tkinter
.Button(self
.server_frm
,
1858 text
='quit serving', command
=self
.quit
, state
='disabled')
1860 self
.search_frm
= Tkinter
.Frame(window
)
1861 self
.search_lbl
= Tkinter
.Label(self
.search_frm
, text
='Search for')
1862 self
.search_ent
= Tkinter
.Entry(self
.search_frm
)
1863 self
.search_ent
.bind('<Return>', self
.search
)
1864 self
.stop_btn
= Tkinter
.Button(self
.search_frm
,
1865 text
='stop', pady
=0, command
=self
.stop
, state
='disabled')
1866 if sys
.platform
== 'win32':
1867 # Trying to hide and show this button crashes under Windows.
1868 self
.stop_btn
.pack(side
='right')
1870 self
.window
.title('pydoc')
1871 self
.window
.protocol('WM_DELETE_WINDOW', self
.quit
)
1872 self
.title_lbl
.pack(side
='top', fill
='x')
1873 self
.open_btn
.pack(side
='left', fill
='x', expand
=1)
1874 self
.quit_btn
.pack(side
='right', fill
='x', expand
=1)
1875 self
.server_frm
.pack(side
='top', fill
='x')
1877 self
.search_lbl
.pack(side
='left')
1878 self
.search_ent
.pack(side
='right', fill
='x', expand
=1)
1879 self
.search_frm
.pack(side
='top', fill
='x')
1880 self
.search_ent
.focus_set()
1882 font
= ('helvetica', sys
.platform
== 'win32' and 8 or 10)
1883 self
.result_lst
= Tkinter
.Listbox(window
, font
=font
, height
=6)
1884 self
.result_lst
.bind('<Button-1>', self
.select
)
1885 self
.result_lst
.bind('<Double-Button-1>', self
.goto
)
1886 self
.result_scr
= Tkinter
.Scrollbar(window
,
1887 orient
='vertical', command
=self
.result_lst
.yview
)
1888 self
.result_lst
.config(yscrollcommand
=self
.result_scr
.set)
1890 self
.result_frm
= Tkinter
.Frame(window
)
1891 self
.goto_btn
= Tkinter
.Button(self
.result_frm
,
1892 text
='go to selected', command
=self
.goto
)
1893 self
.hide_btn
= Tkinter
.Button(self
.result_frm
,
1894 text
='hide results', command
=self
.hide
)
1895 self
.goto_btn
.pack(side
='left', fill
='x', expand
=1)
1896 self
.hide_btn
.pack(side
='right', fill
='x', expand
=1)
1898 self
.window
.update()
1899 self
.minwidth
= self
.window
.winfo_width()
1900 self
.minheight
= self
.window
.winfo_height()
1901 self
.bigminheight
= (self
.server_frm
.winfo_reqheight() +
1902 self
.search_frm
.winfo_reqheight() +
1903 self
.result_lst
.winfo_reqheight() +
1904 self
.result_frm
.winfo_reqheight())
1905 self
.bigwidth
, self
.bigheight
= self
.minwidth
, self
.bigminheight
1907 self
.window
.wm_geometry('%dx%d' % (self
.minwidth
, self
.minheight
))
1908 self
.window
.wm_minsize(self
.minwidth
, self
.minheight
)
1912 target
=serve
, args
=(port
, self
.ready
, self
.quit
)).start()
1914 def ready(self
, server
):
1915 self
.server
= server
1916 self
.title_lbl
.config(
1917 text
='Python documentation server at\n' + server
.url
)
1918 self
.open_btn
.config(state
='normal')
1919 self
.quit_btn
.config(state
='normal')
1921 def open(self
, event
=None, url
=None):
1922 url
= url
or self
.server
.url
1925 webbrowser
.open(url
)
1926 except ImportError: # pre-webbrowser.py compatibility
1927 if sys
.platform
== 'win32':
1928 os
.system('start "%s"' % url
)
1929 elif sys
.platform
== 'mac':
1931 except ImportError: pass
1932 else: ic
.launchurl(url
)
1934 rc
= os
.system('netscape -remote "openURL(%s)" &' % url
)
1935 if rc
: os
.system('netscape "%s" &' % url
)
1937 def quit(self
, event
=None):
1939 self
.server
.quit
= 1
1942 def search(self
, event
=None):
1943 key
= self
.search_ent
.get()
1944 self
.stop_btn
.pack(side
='right')
1945 self
.stop_btn
.config(state
='normal')
1946 self
.search_lbl
.config(text
='Searching for "%s"...' % key
)
1947 self
.search_ent
.forget()
1948 self
.search_lbl
.pack(side
='left')
1949 self
.result_lst
.delete(0, 'end')
1950 self
.goto_btn
.config(state
='disabled')
1955 self
.scanner
.quit
= 1
1956 self
.scanner
= ModuleScanner()
1957 threading
.Thread(target
=self
.scanner
.run
,
1958 args
=(self
.update
, key
, self
.done
)).start()
1960 def update(self
, path
, modname
, desc
):
1961 if modname
[-9:] == '.__init__':
1962 modname
= modname
[:-9] + ' (package)'
1963 self
.result_lst
.insert('end',
1964 modname
+ ' - ' + (desc
or '(no description)'))
1966 def stop(self
, event
=None):
1968 self
.scanner
.quit
= 1
1973 self
.search_lbl
.config(text
='Search for')
1974 self
.search_lbl
.pack(side
='left')
1975 self
.search_ent
.pack(side
='right', fill
='x', expand
=1)
1976 if sys
.platform
!= 'win32': self
.stop_btn
.forget()
1977 self
.stop_btn
.config(state
='disabled')
1979 def select(self
, event
=None):
1980 self
.goto_btn
.config(state
='normal')
1982 def goto(self
, event
=None):
1983 selection
= self
.result_lst
.curselection()
1985 modname
= split(self
.result_lst
.get(selection
[0]))[0]
1986 self
.open(url
=self
.server
.url
+ modname
+ '.html')
1989 if not self
.expanded
: return
1990 self
.result_frm
.forget()
1991 self
.result_scr
.forget()
1992 self
.result_lst
.forget()
1993 self
.bigwidth
= self
.window
.winfo_width()
1994 self
.bigheight
= self
.window
.winfo_height()
1995 self
.window
.wm_geometry('%dx%d' % (self
.minwidth
, self
.minheight
))
1996 self
.window
.wm_minsize(self
.minwidth
, self
.minheight
)
2000 if self
.expanded
: return
2001 self
.result_frm
.pack(side
='bottom', fill
='x')
2002 self
.result_scr
.pack(side
='right', fill
='y')
2003 self
.result_lst
.pack(side
='top', fill
='both', expand
=1)
2004 self
.window
.wm_geometry('%dx%d' % (self
.bigwidth
, self
.bigheight
))
2005 self
.window
.wm_minsize(self
.minwidth
, self
.bigminheight
)
2008 def hide(self
, event
=None):
2014 gui
= GUI(Tkinter
.Tk())
2016 except KeyboardInterrupt:
2019 # -------------------------------------------------- command-line interface
2022 return type(x
) is types
.StringType
and find(x
, os
.sep
) >= 0
2025 """Command-line interface (looks at sys.argv to decide what to do)."""
2027 class BadUsage
: pass
2029 # Scripts don't get the current directory in their path by default.
2030 scriptdir
= os
.path
.dirname(sys
.argv
[0])
2031 if scriptdir
in sys
.path
:
2032 sys
.path
.remove(scriptdir
)
2033 sys
.path
.insert(0, '.')
2036 opts
, args
= getopt
.getopt(sys
.argv
[1:], 'gk:p:w')
2039 for opt
, val
in opts
:
2052 print 'pydoc server ready at %s' % server
.url
2054 print 'pydoc server stopped'
2055 serve(port
, ready
, stopped
)
2060 if not args
: raise BadUsage
2063 if ispath(arg
) and os
.path
.isfile(arg
):
2064 arg
= importfile(arg
)
2066 if ispath(arg
) and os
.path
.isdir(arg
):
2072 except ErrorDuringImport
, value
:
2075 except (getopt
.error
, BadUsage
):
2077 print """pydoc - the Python documentation tool
2080 Show text documentation on something. <name> may be the name of a
2081 function, module, or package, or a dotted reference to a class or
2082 function within a module or module in a package. If <name> contains
2083 a '%s', it is used as the path to a Python source file to document.
2086 Search for a keyword in the synopsis lines of all available modules.
2089 Start an HTTP server on the given port on the local machine.
2092 Pop up a graphical interface for finding and serving documentation.
2095 Write out the HTML documentation for a module to a file in the current
2096 directory. If <name> contains a '%s', it is treated as a filename; if
2097 it names a directory, documentation is written for all the contents.
2098 """ % (cmd
, os
.sep
, cmd
, cmd
, cmd
, cmd
, os
.sep
)
2100 if __name__
== '__main__': cli()