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 summary="heading">
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 <table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
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%%" summary="list"><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, *ignored
):
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
={},
606 """Produce HTML documentation for a class object."""
607 realname
= object.__name
__
608 name
= name
or realname
609 bases
= object.__bases
__
612 push
= contents
.append
614 # Cute little class to pump out a horizontal rule between sections.
615 class HorizontalRule
:
622 hr
= HorizontalRule()
624 # List the mro, if non-trivial.
625 mro
= list(inspect
.getmro(object))
628 push('<dl><dt>Method resolution order:</dt>\n')
630 push('<dd>%s</dd>\n' % self
.classlink(base
,
634 def spill(msg
, attrs
, predicate
):
635 ok
, attrs
= _split_list(attrs
, predicate
)
639 for name
, kind
, homecls
, value
in ok
:
640 push(self
.document(getattr(object, name
), name
, mod
,
641 funcs
, classes
, mdict
, object))
645 def spillproperties(msg
, attrs
, predicate
):
646 ok
, attrs
= _split_list(attrs
, predicate
)
650 for name
, kind
, homecls
, value
in ok
:
651 push('<dl><dt><strong>%s</strong></dt>\n' % name
)
652 if value
.__doc
__ is not None:
653 doc
= self
.markup(value
.__doc
__, self
.preformat
,
654 funcs
, classes
, mdict
)
655 push('<dd><tt>%s</tt></dd>\n' % doc
)
656 for attr
, tag
in [("fget", " getter"),
658 ("fdel", " deleter")]:
659 func
= getattr(value
, attr
)
661 base
= self
.document(func
, name
+ tag
, mod
,
662 funcs
, classes
, mdict
, object)
663 push('<dd>%s</dd>\n' % base
)
667 def spilldata(msg
, attrs
, predicate
):
668 ok
, attrs
= _split_list(attrs
, predicate
)
672 for name
, kind
, homecls
, value
in ok
:
673 base
= self
.docother(getattr(object, name
), name
, mod
)
674 doc
= getattr(value
, "__doc__", None)
676 push('<dl><dt>%s</dl>\n' % base
)
678 doc
= self
.markup(getdoc(value
), self
.preformat
,
679 funcs
, classes
, mdict
)
680 doc
= '<dd><tt>%s</tt>' % doc
681 push('<dl><dt>%s%s</dl>\n' % (base
, doc
))
685 attrs
= inspect
.classify_class_attrs(object)
687 for key
, kind
, homecls
, value
in attrs
:
688 mdict
[key
] = anchor
= '#' + name
+ '-' + key
689 value
= getattr(object, key
)
691 # The value may not be hashable (e.g., a data attr with
692 # a dict or list value).
693 mdict
[value
] = anchor
699 thisclass
= mro
.pop(0)
701 thisclass
= attrs
[0][2]
702 attrs
, inherited
= _split_list(attrs
, lambda t
: t
[2] is thisclass
)
704 if thisclass
is object:
707 tag
= "inherited from %s" % self
.classlink(thisclass
,
711 # Sort attrs by name.
712 attrs
.sort(lambda t1
, t2
: cmp(t1
[0], t2
[0]))
714 # Pump out the attrs, segregated by kind.
715 attrs
= spill("Methods %s" % tag
, attrs
,
716 lambda t
: t
[1] == 'method')
717 attrs
= spill("Class methods %s" % tag
, attrs
,
718 lambda t
: t
[1] == 'class method')
719 attrs
= spill("Static methods %s" % tag
, attrs
,
720 lambda t
: t
[1] == 'static method')
721 attrs
= spillproperties("Properties %s" % tag
, attrs
,
722 lambda t
: t
[1] == 'property')
723 attrs
= spilldata("Data and non-method functions %s" % tag
, attrs
,
724 lambda t
: t
[1] == 'data')
728 contents
= ''.join(contents
)
731 title
= '<a name="%s">class <strong>%s</strong></a>' % (
734 title
= '<strong>%s</strong> = <a name="%s">class %s</a>' % (
735 name
, name
, realname
)
739 parents
.append(self
.classlink(base
, object.__module
__))
740 title
= title
+ '(%s)' % join(parents
, ', ')
741 doc
= self
.markup(getdoc(object), self
.preformat
, funcs
, classes
, mdict
)
742 doc
= doc
and '<tt>%s<br> </tt>' % doc
or ' '
744 return self
.section(title
, '#000000', '#ffc8d8', contents
, 5, doc
)
746 def formatvalue(self
, object):
747 """Format an argument default value as text."""
748 return self
.grey('=' + self
.repr(object))
750 def docroutine(self
, object, name
=None, mod
=None,
751 funcs
={}, classes
={}, methods
={}, cl
=None):
752 """Produce HTML documentation for a function or method object."""
753 realname
= object.__name
__
754 name
= name
or realname
755 anchor
= (cl
and cl
.__name
__ or '') + '-' + name
758 if inspect
.ismethod(object):
759 imclass
= object.im_class
761 if imclass
is not cl
:
762 note
= ' from ' + self
.classlink(imclass
, mod
)
765 note
= ' method of %s instance' % self
.classlink(
766 object.im_self
.__class
__, mod
)
768 note
= ' unbound %s method' % self
.classlink(imclass
,mod
)
769 object = object.im_func
772 title
= '<a name="%s"><strong>%s</strong></a>' % (anchor
, realname
)
774 if (cl
and cl
.__dict
__.has_key(realname
) and
775 cl
.__dict
__[realname
] is object):
776 reallink
= '<a href="#%s">%s</a>' % (
777 cl
.__name
__ + '-' + realname
, realname
)
781 title
= '<a name="%s"><strong>%s</strong></a> = %s' % (
782 anchor
, name
, reallink
)
783 if inspect
.isfunction(object):
784 args
, varargs
, varkw
, defaults
= inspect
.getargspec(object)
785 argspec
= inspect
.formatargspec(
786 args
, varargs
, varkw
, defaults
, formatvalue
=self
.formatvalue
)
787 if realname
== '<lambda>':
788 title
= '<strong>%s</strong> <em>lambda</em> ' % name
789 argspec
= argspec
[1:-1] # remove parentheses
793 decl
= title
+ argspec
+ (note
and self
.grey(
794 '<font face="helvetica, arial">%s</font>' % note
))
797 return '<dl><dt>%s</dt></dl>\n' % decl
800 getdoc(object), self
.preformat
, funcs
, classes
, methods
)
801 doc
= doc
and '<dd><tt>%s</tt></dd>' % doc
802 return '<dl><dt>%s</dt>%s</dl>\n' % (decl
, doc
)
804 def docother(self
, object, name
=None, mod
=None, *ignored
):
805 """Produce HTML documentation for a data object."""
806 lhs
= name
and '<strong>%s</strong> = ' % name
or ''
807 return lhs
+ self
.repr(object)
809 def index(self
, dir, shadowed
=None):
810 """Generate an HTML index for a directory of modules."""
812 if shadowed
is None: shadowed
= {}
814 files
= os
.listdir(dir)
816 def found(name
, ispackage
,
817 modpkgs
=modpkgs
, shadowed
=shadowed
, seen
=seen
):
818 if not seen
.has_key(name
):
819 modpkgs
.append((name
, '', ispackage
, shadowed
.has_key(name
)))
823 # Package spam/__init__.py takes precedence over module spam.py.
825 path
= os
.path
.join(dir, file)
826 if ispackage(path
): found(file, 1)
828 path
= os
.path
.join(dir, file)
829 if os
.path
.isfile(path
):
830 modname
= inspect
.getmodulename(file)
831 if modname
: found(modname
, 0)
834 contents
= self
.multicolumn(modpkgs
, self
.modpkglink
)
835 return self
.bigsection(dir, '#ffffff', '#ee77aa', contents
)
837 # -------------------------------------------- text documentation generator
839 class TextRepr(Repr
):
840 """Class for safely making a text representation of a Python object."""
843 self
.maxlist
= self
.maxtuple
= 20
845 self
.maxstring
= self
.maxother
= 100
847 def repr1(self
, x
, level
):
848 methodname
= 'repr_' + join(split(type(x
).__name
__), '_')
849 if hasattr(self
, methodname
):
850 return getattr(self
, methodname
)(x
, level
)
852 return cram(stripid(repr(x
)), self
.maxother
)
854 def repr_string(self
, x
, level
):
855 test
= cram(x
, self
.maxstring
)
856 testrepr
= repr(test
)
857 if '\\' in test
and '\\' not in replace(testrepr
, r
'\\', ''):
858 # Backslashes are only literal in the string and are never
859 # needed to make any special characters, so show a raw string.
860 return 'r' + testrepr
[0] + test
+ testrepr
[0]
863 def repr_instance(self
, x
, level
):
865 return cram(stripid(repr(x
)), self
.maxstring
)
867 return '<%s instance>' % x
.__class
__.__name
__
870 """Formatter class for text documentation."""
872 # ------------------------------------------- text formatting utilities
874 _repr_instance
= TextRepr()
875 repr = _repr_instance
.repr
877 def bold(self
, text
):
878 """Format a string in bold by overstriking."""
879 return join(map(lambda ch
: ch
+ '\b' + ch
, text
), '')
881 def indent(self
, text
, prefix
=' '):
882 """Indent text by prepending a given prefix to each line."""
883 if not text
: return ''
884 lines
= split(text
, '\n')
885 lines
= map(lambda line
, prefix
=prefix
: prefix
+ line
, lines
)
886 if lines
: lines
[-1] = rstrip(lines
[-1])
887 return join(lines
, '\n')
889 def section(self
, title
, contents
):
890 """Format a section with a given heading."""
891 return self
.bold(title
) + '\n' + rstrip(self
.indent(contents
)) + '\n\n'
893 # ---------------------------------------------- type-specific routines
895 def formattree(self
, tree
, modname
, parent
=None, prefix
=''):
896 """Render in text a class tree as returned by inspect.getclasstree()."""
899 if type(entry
) is type(()):
901 result
= result
+ prefix
+ classname(c
, modname
)
902 if bases
and bases
!= (parent
,):
903 parents
= map(lambda c
, m
=modname
: classname(c
, m
), bases
)
904 result
= result
+ '(%s)' % join(parents
, ', ')
905 result
= result
+ '\n'
906 elif type(entry
) is type([]):
907 result
= result
+ self
.formattree(
908 entry
, modname
, c
, prefix
+ ' ')
911 def docmodule(self
, object, name
=None, mod
=None):
912 """Produce text documentation for a given module object."""
913 name
= object.__name
__ # ignore the passed-in name
914 synop
, desc
= splitdoc(getdoc(object))
915 result
= self
.section('NAME', name
+ (synop
and ' - ' + synop
))
918 file = inspect
.getabsfile(object)
921 result
= result
+ self
.section('FILE', file)
923 result
= result
+ self
.section('DESCRIPTION', desc
)
926 for key
, value
in inspect
.getmembers(object, inspect
.isclass
):
927 if (inspect
.getmodule(value
) or object) is object:
928 classes
.append((key
, value
))
930 for key
, value
in inspect
.getmembers(object, inspect
.isroutine
):
931 if inspect
.isbuiltin(value
) or inspect
.getmodule(value
) is object:
932 funcs
.append((key
, value
))
934 for key
, value
in inspect
.getmembers(object, isdata
):
935 if key
not in ['__builtins__', '__doc__']:
936 data
.append((key
, value
))
938 if hasattr(object, '__path__'):
940 for file in os
.listdir(object.__path
__[0]):
941 path
= os
.path
.join(object.__path
__[0], file)
942 modname
= inspect
.getmodulename(file)
943 if modname
and modname
not in modpkgs
:
944 modpkgs
.append(modname
)
945 elif ispackage(path
):
946 modpkgs
.append(file + ' (package)')
948 result
= result
+ self
.section(
949 'PACKAGE CONTENTS', join(modpkgs
, '\n'))
952 classlist
= map(lambda (key
, value
): value
, classes
)
953 contents
= [self
.formattree(
954 inspect
.getclasstree(classlist
, 1), name
)]
955 for key
, value
in classes
:
956 contents
.append(self
.document(value
, key
, name
))
957 result
= result
+ self
.section('CLASSES', join(contents
, '\n'))
961 for key
, value
in funcs
:
962 contents
.append(self
.document(value
, key
, name
))
963 result
= result
+ self
.section('FUNCTIONS', join(contents
, '\n'))
967 for key
, value
in data
:
968 contents
.append(self
.docother(value
, key
, name
, 70))
969 result
= result
+ self
.section('DATA', join(contents
, '\n'))
971 if hasattr(object, '__version__'):
972 version
= str(object.__version
__)
973 if version
[:11] == '$' + 'Revision: ' and version
[-1:] == '$':
974 version
= strip(version
[11:-1])
975 result
= result
+ self
.section('VERSION', version
)
976 if hasattr(object, '__date__'):
977 result
= result
+ self
.section('DATE', str(object.__date
__))
978 if hasattr(object, '__author__'):
979 result
= result
+ self
.section('AUTHOR', str(object.__author
__))
980 if hasattr(object, '__credits__'):
981 result
= result
+ self
.section('CREDITS', str(object.__credits
__))
984 def docclass(self
, object, name
=None, mod
=None):
985 """Produce text documentation for a given class object."""
986 realname
= object.__name
__
987 name
= name
or realname
988 bases
= object.__bases
__
990 def makename(c
, m
=object.__module
__):
991 return classname(c
, m
)
994 title
= 'class ' + self
.bold(realname
)
996 title
= self
.bold(name
) + ' = class ' + realname
998 parents
= map(makename
, bases
)
999 title
= title
+ '(%s)' % join(parents
, ', ')
1001 doc
= getdoc(object)
1002 contents
= doc
and [doc
+ '\n'] or []
1003 push
= contents
.append
1005 # List the mro, if non-trivial.
1006 mro
= list(inspect
.getmro(object))
1008 push("Method resolution order:")
1010 push(' ' + makename(base
))
1013 # Cute little class to pump out a horizontal rule between sections.
1014 class HorizontalRule
:
1021 hr
= HorizontalRule()
1023 def spill(msg
, attrs
, predicate
):
1024 ok
, attrs
= _split_list(attrs
, predicate
)
1028 for name
, kind
, homecls
, value
in ok
:
1029 push(self
.document(getattr(object, name
),
1033 def spillproperties(msg
, attrs
, predicate
):
1034 ok
, attrs
= _split_list(attrs
, predicate
)
1038 for name
, kind
, homecls
, value
in ok
:
1040 need_blank_after_doc
= 0
1041 doc
= getdoc(value
) or ''
1043 push(self
.indent(doc
))
1044 need_blank_after_doc
= 1
1045 for attr
, tag
in [("fget", " getter"),
1046 ("fset", " setter"),
1047 ("fdel", " deleter")]:
1048 func
= getattr(value
, attr
)
1049 if func
is not None:
1050 if need_blank_after_doc
:
1052 need_blank_after_doc
= 0
1053 base
= self
.docother(func
, name
+ tag
, mod
, 70)
1054 push(self
.indent(base
))
1058 def spilldata(msg
, attrs
, predicate
):
1059 ok
, attrs
= _split_list(attrs
, predicate
)
1063 for name
, kind
, homecls
, value
in ok
:
1064 doc
= getattr(value
, "__doc__", None)
1065 push(self
.docother(getattr(object, name
),
1066 name
, mod
, 70, doc
) + '\n')
1069 attrs
= inspect
.classify_class_attrs(object)
1072 thisclass
= mro
.pop(0)
1074 thisclass
= attrs
[0][2]
1075 attrs
, inherited
= _split_list(attrs
, lambda t
: t
[2] is thisclass
)
1077 if thisclass
is object:
1078 tag
= "defined here"
1080 tag
= "inherited from %s" % classname(thisclass
,
1083 # Sort attrs by name.
1084 attrs
.sort(lambda t1
, t2
: cmp(t1
[0], t2
[0]))
1086 # Pump out the attrs, segregated by kind.
1087 attrs
= spill("Methods %s:\n" % tag
, attrs
,
1088 lambda t
: t
[1] == 'method')
1089 attrs
= spill("Class methods %s:\n" % tag
, attrs
,
1090 lambda t
: t
[1] == 'class method')
1091 attrs
= spill("Static methods %s:\n" % tag
, attrs
,
1092 lambda t
: t
[1] == 'static method')
1093 attrs
= spillproperties("Properties %s:\n" % tag
, attrs
,
1094 lambda t
: t
[1] == 'property')
1095 attrs
= spilldata("Data and non-method functions %s:\n" % tag
,
1096 attrs
, lambda t
: t
[1] == 'data')
1100 contents
= '\n'.join(contents
)
1103 return title
+ '\n' + self
.indent(rstrip(contents
), ' | ') + '\n'
1105 def formatvalue(self
, object):
1106 """Format an argument default value as text."""
1107 return '=' + self
.repr(object)
1109 def docroutine(self
, object, name
=None, mod
=None, cl
=None):
1110 """Produce text documentation for a function or method object."""
1111 realname
= object.__name
__
1112 name
= name
or realname
1115 if inspect
.ismethod(object):
1116 imclass
= object.im_class
1118 if imclass
is not cl
:
1119 note
= ' from ' + classname(imclass
, mod
)
1122 note
= ' method of %s instance' % classname(
1123 object.im_self
.__class
__, mod
)
1125 note
= ' unbound %s method' % classname(imclass
,mod
)
1126 object = object.im_func
1128 if name
== realname
:
1129 title
= self
.bold(realname
)
1131 if (cl
and cl
.__dict
__.has_key(realname
) and
1132 cl
.__dict
__[realname
] is object):
1134 title
= self
.bold(name
) + ' = ' + realname
1135 if inspect
.isfunction(object):
1136 args
, varargs
, varkw
, defaults
= inspect
.getargspec(object)
1137 argspec
= inspect
.formatargspec(
1138 args
, varargs
, varkw
, defaults
, formatvalue
=self
.formatvalue
)
1139 if realname
== '<lambda>':
1141 argspec
= argspec
[1:-1] # remove parentheses
1144 decl
= title
+ argspec
+ note
1149 doc
= getdoc(object) or ''
1150 return decl
+ '\n' + (doc
and rstrip(self
.indent(doc
)) + '\n')
1152 def docother(self
, object, name
=None, mod
=None, maxlen
=None, doc
=None):
1153 """Produce text documentation for a data object."""
1154 repr = self
.repr(object)
1156 line
= (name
and name
+ ' = ' or '') + repr
1157 chop
= maxlen
- len(line
)
1158 if chop
< 0: repr = repr[:chop
] + '...'
1159 line
= (name
and self
.bold(name
) + ' = ' or '') + repr
1161 line
+= '\n' + self
.indent(str(doc
))
1164 # --------------------------------------------------------- user interfaces
1167 """The first time this is called, determine what kind of pager to use."""
1173 """Decide what method to use for paging through text."""
1174 if type(sys
.stdout
) is not types
.FileType
:
1176 if not sys
.stdin
.isatty() or not sys
.stdout
.isatty():
1178 if os
.environ
.get('TERM') in ['dumb', 'emacs']:
1180 if os
.environ
.has_key('PAGER'):
1181 if sys
.platform
== 'win32': # pipes completely broken in Windows
1182 return lambda text
: tempfilepager(plain(text
), os
.environ
['PAGER'])
1183 elif os
.environ
.get('TERM') in ['dumb', 'emacs']:
1184 return lambda text
: pipepager(plain(text
), os
.environ
['PAGER'])
1186 return lambda text
: pipepager(text
, os
.environ
['PAGER'])
1187 if sys
.platform
== 'win32':
1188 return lambda text
: tempfilepager(plain(text
), 'more <')
1189 if hasattr(os
, 'system') and os
.system('less 2>/dev/null') == 0:
1190 return lambda text
: pipepager(text
, 'less')
1193 filename
= tempfile
.mktemp()
1194 open(filename
, 'w').close()
1196 if hasattr(os
, 'system') and os
.system('more %s' % filename
) == 0:
1197 return lambda text
: pipepager(text
, 'more')
1204 """Remove boldface formatting from text."""
1205 return re
.sub('.\b', '', text
)
1207 def pipepager(text
, cmd
):
1208 """Page through text by feeding it to another program."""
1209 pipe
= os
.popen(cmd
, 'w')
1214 pass # Ignore broken pipes caused by quitting the pager program.
1216 def tempfilepager(text
, cmd
):
1217 """Page through text by invoking a program on a temporary file."""
1219 filename
= tempfile
.mktemp()
1220 file = open(filename
, 'w')
1224 os
.system(cmd
+ ' ' + filename
)
1229 """Page through text on a text terminal."""
1230 lines
= split(plain(text
), '\n')
1233 fd
= sys
.stdin
.fileno()
1234 old
= tty
.tcgetattr(fd
)
1236 getchar
= lambda: sys
.stdin
.read(1)
1237 except (ImportError, AttributeError):
1239 getchar
= lambda: sys
.stdin
.readline()[:-1][:1]
1242 r
= inc
= os
.environ
.get('LINES', 25) - 1
1243 sys
.stdout
.write(join(lines
[:inc
], '\n') + '\n')
1245 sys
.stdout
.write('-- more --')
1250 sys
.stdout
.write('\r \r')
1252 elif c
in ['\r', '\n']:
1253 sys
.stdout
.write('\r \r' + lines
[r
] + '\n')
1256 if c
in ['b', 'B', '\x1b']:
1259 sys
.stdout
.write('\n' + join(lines
[r
:r
+inc
], '\n') + '\n')
1264 tty
.tcsetattr(fd
, tty
.TCSAFLUSH
, old
)
1266 def plainpager(text
):
1267 """Simply print unformatted text. This is the ultimate fallback."""
1268 sys
.stdout
.write(plain(text
))
1270 def describe(thing
):
1271 """Produce a short description of the given thing."""
1272 if inspect
.ismodule(thing
):
1273 if thing
.__name
__ in sys
.builtin_module_names
:
1274 return 'built-in module ' + thing
.__name
__
1275 if hasattr(thing
, '__path__'):
1276 return 'package ' + thing
.__name
__
1278 return 'module ' + thing
.__name
__
1279 if inspect
.isbuiltin(thing
):
1280 return 'built-in function ' + thing
.__name
__
1281 if inspect
.isclass(thing
):
1282 return 'class ' + thing
.__name
__
1283 if inspect
.isfunction(thing
):
1284 return 'function ' + thing
.__name
__
1285 if inspect
.ismethod(thing
):
1286 return 'method ' + thing
.__name
__
1287 if type(thing
) is types
.InstanceType
:
1288 return 'instance of ' + thing
.__class
__.__name
__
1289 return type(thing
).__name
__
1291 def locate(path
, forceload
=0):
1292 """Locate an object by name or dotted path, importing as necessary."""
1293 parts
= split(path
, '.')
1295 while n
< len(parts
):
1296 nextmodule
= safeimport(join(parts
[:n
+1], '.'), forceload
)
1297 if nextmodule
: module
, n
= nextmodule
, n
+ 1
1301 for part
in parts
[n
:]:
1302 try: object = getattr(object, part
)
1303 except AttributeError: return None
1307 if hasattr(__builtin__
, path
):
1308 return getattr(__builtin__
, path
)
1310 # --------------------------------------- interactive interpreter interface
1315 def doc(thing
, title
='Python Library Documentation: %s', forceload
=0):
1316 """Display text documentation, given an object or a path to an object."""
1317 suffix
, name
= '', None
1318 if type(thing
) is type(''):
1320 object = locate(thing
, forceload
)
1321 except ErrorDuringImport
, value
:
1325 print 'no Python documentation found for %s' % repr(thing
)
1327 parts
= split(thing
, '.')
1328 if len(parts
) > 1: suffix
= ' in ' + join(parts
[:-1], '.')
1332 desc
= describe(thing
)
1333 module
= inspect
.getmodule(thing
)
1334 if not suffix
and module
and module
is not thing
:
1335 suffix
= ' in module ' + module
.__name
__
1336 pager(title
% (desc
+ suffix
) + '\n\n' + text
.document(thing
, name
))
1338 def writedoc(key
, forceload
=0):
1339 """Write HTML documentation to a file in the current directory."""
1341 object = locate(key
, forceload
)
1342 except ErrorDuringImport
, value
:
1346 page
= html
.page(describe(object),
1347 html
.document(object, object.__name
__))
1348 file = open(key
+ '.html', 'w')
1351 print 'wrote', key
+ '.html'
1353 print 'no Python documentation found for %s' % repr(key
)
1355 def writedocs(dir, pkgpath
='', done
=None):
1356 """Write out HTML documentation for all modules in a directory tree."""
1357 if done
is None: done
= {}
1358 for file in os
.listdir(dir):
1359 path
= os
.path
.join(dir, file)
1361 writedocs(path
, pkgpath
+ file + '.', done
)
1362 elif os
.path
.isfile(path
):
1363 modname
= inspect
.getmodulename(path
)
1365 modname
= pkgpath
+ modname
1366 if not done
.has_key(modname
):
1373 'assert': ('ref/assert', ''),
1374 'break': ('ref/break', 'while for'),
1375 'class': ('ref/class', 'CLASSES SPECIALMETHODS'),
1376 'continue': ('ref/continue', 'while for'),
1377 'def': ('ref/function', ''),
1378 'del': ('ref/del', 'BASICMETHODS'),
1380 'else': ('ref/if', 'while for'),
1382 'exec': ('ref/exec', ''),
1384 'for': ('ref/for', 'break continue while'),
1386 'global': ('ref/global', 'NAMESPACES'),
1387 'if': ('ref/if', 'TRUTHVALUE'),
1388 'import': ('ref/import', 'MODULES'),
1389 'in': ('ref/comparisons', 'SEQUENCEMETHODS2'),
1391 'lambda': ('ref/lambda', 'FUNCTIONS'),
1395 'print': ('ref/print', ''),
1396 'raise': ('ref/raise', 'EXCEPTIONS'),
1397 'return': ('ref/return', 'FUNCTIONS'),
1398 'try': ('ref/try', 'EXCEPTIONS'),
1399 'while': ('ref/while', 'break continue if TRUTHVALUE'),
1403 'TYPES': ('ref/types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS FUNCTIONS CLASSES MODULES FILES inspect'),
1404 'STRINGS': ('ref/strings', 'str UNICODE SEQUENCES STRINGMETHODS FORMATTING TYPES'),
1405 'STRINGMETHODS': ('lib/string-methods', 'STRINGS FORMATTING'),
1406 'FORMATTING': ('lib/typesseq-strings', 'OPERATORS'),
1407 'UNICODE': ('ref/unicode', 'encodings unicode TYPES STRING'),
1408 'NUMBERS': ('ref/numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1409 'INTEGER': ('ref/integers', 'int range'),
1410 'FLOAT': ('ref/floating', 'float math'),
1411 'COMPLEX': ('ref/imaginary', 'complex cmath'),
1412 'SEQUENCES': ('lib/typesseq', 'STRINGMETHODS FORMATTING xrange LISTS'),
1413 'MAPPINGS': 'DICTIONARIES',
1414 'FUNCTIONS': ('lib/typesfunctions', 'def TYPES'),
1415 'METHODS': ('lib/typesmethods', 'class def CLASSES TYPES'),
1416 'CODEOBJECTS': ('lib/bltin-code-objects', 'compile FUNCTIONS TYPES'),
1417 'TYPEOBJECTS': ('lib/bltin-type-objects', 'types TYPES'),
1418 'FRAMEOBJECTS': 'TYPES',
1419 'TRACEBACKS': 'TYPES',
1420 'NONE': ('lib/bltin-null-object', ''),
1421 'ELLIPSIS': ('lib/bltin-ellipsis-object', 'SLICINGS'),
1422 'FILES': ('lib/bltin-file-objects', ''),
1423 'SPECIALATTRIBUTES': ('lib/specialattrs', ''),
1424 'CLASSES': ('ref/types', 'class SPECIALMETHODS PRIVATENAMES'),
1425 'MODULES': ('lib/typesmodules', 'import'),
1426 'PACKAGES': 'import',
1427 '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'),
1428 'OPERATORS': 'EXPRESSIONS',
1429 'PRECEDENCE': 'EXPRESSIONS',
1430 'OBJECTS': ('ref/objects', 'TYPES'),
1431 'SPECIALMETHODS': ('ref/specialnames', 'BASICMETHODS ATTRIBUTEMETHODS CALLABLEMETHODS SEQUENCEMETHODS1 MAPPINGMETHODS SEQUENCEMETHODS2 NUMBERMETHODS CLASSES'),
1432 'BASICMETHODS': ('ref/customization', 'cmp hash repr str SPECIALMETHODS'),
1433 'ATTRIBUTEMETHODS': ('ref/attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1434 'CALLABLEMETHODS': ('ref/callable-types', 'CALLS SPECIALMETHODS'),
1435 'SEQUENCEMETHODS1': ('ref/sequence-types', 'SEQUENCES SEQUENCEMETHODS2 SPECIALMETHODS'),
1436 'SEQUENCEMETHODS2': ('ref/sequence-methods', 'SEQUENCES SEQUENCEMETHODS1 SPECIALMETHODS'),
1437 'MAPPINGMETHODS': ('ref/sequence-types', 'MAPPINGS SPECIALMETHODS'),
1438 'NUMBERMETHODS': ('ref/numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT SPECIALMETHODS'),
1439 'EXECUTION': ('ref/execframes', ''),
1440 'NAMESPACES': ('ref/execframes', 'global ASSIGNMENT DELETION'),
1441 'SCOPING': 'NAMESPACES',
1442 'FRAMES': 'NAMESPACES',
1443 'EXCEPTIONS': ('ref/exceptions', 'try except finally raise'),
1444 'COERCIONS': 'CONVERSIONS',
1445 'CONVERSIONS': ('ref/conversions', ''),
1446 'IDENTIFIERS': ('ref/identifiers', 'keywords SPECIALIDENTIFIERS'),
1447 'SPECIALIDENTIFIERS': ('ref/id-classes', ''),
1448 'PRIVATENAMES': ('ref/atom-identifiers', ''),
1449 'LITERALS': ('ref/atom-literals', 'STRINGS BACKQUOTES NUMBERS TUPLELITERALS LISTLITERALS DICTIONARYLITERALS'),
1450 'TUPLES': 'SEQUENCES',
1451 'TUPLELITERALS': ('ref/exprlists', 'TUPLES LITERALS'),
1452 'LISTS': ('lib/typesseq-mutable', 'LISTLITERALS'),
1453 'LISTLITERALS': ('ref/lists', 'LISTS LITERALS'),
1454 'DICTIONARIES': ('lib/typesmapping', 'DICTIONARYLITERALS'),
1455 'DICTIONARYLITERALS': ('ref/dict', 'DICTIONARIES LITERALS'),
1456 'BACKQUOTES': ('ref/string-conversions', 'repr str STRINGS LITERALS'),
1457 'ATTRIBUTES': ('ref/attribute-references', 'getattr hasattr setattr ATTRIBUTEMETHODS'),
1458 'SUBSCRIPTS': ('ref/subscriptions', 'SEQUENCEMETHODS1'),
1459 'SLICINGS': ('ref/slicings', 'SEQUENCEMETHODS2'),
1460 'CALLS': ('ref/calls', 'EXPRESSIONS'),
1461 'POWER': ('ref/power', 'EXPRESSIONS'),
1462 'UNARY': ('ref/unary', 'EXPRESSIONS'),
1463 'BINARY': ('ref/binary', 'EXPRESSIONS'),
1464 'SHIFTING': ('ref/shifting', 'EXPRESSIONS'),
1465 'BITWISE': ('ref/bitwise', 'EXPRESSIONS'),
1466 'COMPARISON': ('ref/comparisons', 'EXPRESSIONS BASICMETHODS'),
1467 'BOOLEAN': ('ref/lambda', 'EXPRESSIONS TRUTHVALUE'),
1468 'ASSERTION': 'assert',
1469 'ASSIGNMENT': ('ref/assignment', 'AUGMENTEDASSIGNMENT'),
1470 'AUGMENTEDASSIGNMENT': ('ref/augassign', 'NUMBERMETHODS'),
1472 'PRINTING': 'print',
1473 'RETURNING': 'return',
1474 'IMPORTING': 'import',
1475 'CONDITIONAL': 'if',
1476 'LOOPING': ('ref/compound', 'for while break continue'),
1477 'TRUTHVALUE': ('lib/truth', 'if while and or not BASICMETHODS'),
1478 'DEBUGGING': ('lib/module-pdb', 'pdb'),
1481 def __init__(self
, input, output
):
1483 self
.output
= output
1485 execdir
= os
.path
.dirname(sys
.executable
)
1486 homedir
= os
.environ
.get('PYTHONHOME')
1487 for dir in [os
.environ
.get('PYTHONDOCS'),
1488 homedir
and os
.path
.join(homedir
, 'doc'),
1489 os
.path
.join(execdir
, 'doc'),
1490 '/usr/doc/python-docs-' + split(sys
.version
)[0],
1491 '/usr/doc/python-' + split(sys
.version
)[0],
1492 '/usr/doc/python-docs-' + sys
.version
[:3],
1493 '/usr/doc/python-' + sys
.version
[:3]]:
1494 if dir and os
.path
.isdir(os
.path
.join(dir, 'lib')):
1498 if inspect
.stack()[1][3] == '?':
1501 return '<pydoc.Helper instance>'
1503 def __call__(self
, request
=None):
1504 if request
is not None:
1509 self
.output
.write('''
1510 You are now leaving help and returning to the Python interpreter.
1511 If you want to ask for help on a particular object directly from the
1512 interpreter, you can type "help(object)". Executing "help('string')"
1513 has the same effect as typing a particular string at the help> prompt.
1517 self
.output
.write('\n')
1519 self
.output
.write('help> ')
1522 request
= self
.input.readline()
1523 if not request
: break
1524 except KeyboardInterrupt: break
1525 request
= strip(replace(request
, '"', '', "'", ''))
1526 if lower(request
) in ['q', 'quit']: break
1529 def help(self
, request
):
1530 if type(request
) is type(''):
1531 if request
== 'help': self
.intro()
1532 elif request
== 'keywords': self
.listkeywords()
1533 elif request
== 'topics': self
.listtopics()
1534 elif request
== 'modules': self
.listmodules()
1535 elif request
[:8] == 'modules ':
1536 self
.listmodules(split(request
)[1])
1537 elif self
.keywords
.has_key(request
): self
.showtopic(request
)
1538 elif self
.topics
.has_key(request
): self
.showtopic(request
)
1539 elif request
: doc(request
, 'Help on %s:')
1540 elif isinstance(request
, Helper
): self()
1541 else: doc(request
, 'Help on %s:')
1542 self
.output
.write('\n')
1545 self
.output
.write('''
1546 Welcome to Python %s! This is the online help utility.
1548 If this is your first time using Python, you should definitely check out
1549 the tutorial on the Internet at http://www.python.org/doc/tut/.
1551 Enter the name of any module, keyword, or topic to get help on writing
1552 Python programs and using Python modules. To quit this help utility and
1553 return to the interpreter, just type "quit".
1555 To get a list of available modules, keywords, or topics, type "modules",
1556 "keywords", or "topics". Each module also comes with a one-line summary
1557 of what it does; to list the modules whose summaries contain a given word
1558 such as "spam", type "modules spam".
1559 ''' % sys
.version
[:3])
1561 def list(self
, items
, columns
=4, width
=80):
1564 colw
= width
/ columns
1565 rows
= (len(items
) + columns
- 1) / columns
1566 for row
in range(rows
):
1567 for col
in range(columns
):
1568 i
= col
* rows
+ row
1570 self
.output
.write(items
[i
])
1571 if col
< columns
- 1:
1572 self
.output
.write(' ' + ' ' * (colw
-1 - len(items
[i
])))
1573 self
.output
.write('\n')
1575 def listkeywords(self
):
1576 self
.output
.write('''
1577 Here is a list of the Python keywords. Enter any keyword to get more help.
1580 self
.list(self
.keywords
.keys())
1582 def listtopics(self
):
1583 self
.output
.write('''
1584 Here is a list of available topics. Enter any topic name to get more help.
1587 self
.list(self
.topics
.keys())
1589 def showtopic(self
, topic
):
1591 self
.output
.write('''
1592 Sorry, topic and keyword documentation is not available because the Python
1593 HTML documentation files could not be found. If you have installed them,
1594 please set the environment variable PYTHONDOCS to indicate their location.
1597 target
= self
.topics
.get(topic
, self
.keywords
.get(topic
))
1599 self
.output
.write('no documentation found for %s\n' % repr(topic
))
1601 if type(target
) is type(''):
1602 return self
.showtopic(target
)
1604 filename
, xrefs
= target
1605 filename
= self
.docdir
+ '/' + filename
+ '.html'
1607 file = open(filename
)
1609 self
.output
.write('could not read docs from %s\n' % filename
)
1612 divpat
= re
.compile('<div[^>]*navigat.*?</div.*?>', re
.I | re
.S
)
1613 addrpat
= re
.compile('<address.*?>.*?</address.*?>', re
.I | re
.S
)
1614 document
= re
.sub(addrpat
, '', re
.sub(divpat
, '', file.read()))
1617 import htmllib
, formatter
, StringIO
1618 buffer = StringIO
.StringIO()
1619 parser
= htmllib
.HTMLParser(
1620 formatter
.AbstractFormatter(formatter
.DumbWriter(buffer)))
1621 parser
.start_table
= parser
.do_p
1622 parser
.end_table
= lambda parser
=parser
: parser
.do_p({})
1623 parser
.start_tr
= parser
.do_br
1624 parser
.start_td
= parser
.start_th
= lambda a
, b
=buffer: b
.write('\t')
1625 parser
.feed(document
)
1626 buffer = replace(buffer.getvalue(), '\xa0', ' ', '\n', '\n ')
1627 pager(' ' + strip(buffer) + '\n')
1629 buffer = StringIO
.StringIO()
1630 formatter
.DumbWriter(buffer).send_flowing_data(
1631 'Related help topics: ' + join(split(xrefs
), ', ') + '\n')
1632 self
.output
.write('\n%s\n' % buffer.getvalue())
1634 def listmodules(self
, key
=''):
1636 self
.output
.write('''
1637 Here is a list of matching modules. Enter any module name to get more help.
1642 self
.output
.write('''
1643 Please wait a moment while I gather a list of all available modules...
1647 def callback(path
, modname
, desc
, modules
=modules
):
1648 if modname
and modname
[-9:] == '.__init__':
1649 modname
= modname
[:-9] + ' (package)'
1650 if find(modname
, '.') < 0:
1651 modules
[modname
] = 1
1652 ModuleScanner().run(callback
)
1653 self
.list(modules
.keys())
1654 self
.output
.write('''
1655 Enter any module name to get more help. Or, type "modules spam" to search
1656 for modules whose descriptions contain the word "spam".
1659 help = Helper(sys
.stdin
, sys
.stdout
)
1662 """A generic tree iterator."""
1663 def __init__(self
, roots
, children
, descendp
):
1664 self
.roots
= roots
[:]
1666 self
.children
= children
1667 self
.descendp
= descendp
1673 root
= self
.roots
.pop(0)
1674 self
.state
= [(root
, self
.children(root
))]
1675 node
, children
= self
.state
[-1]
1679 child
= children
.pop(0)
1680 if self
.descendp(child
):
1681 self
.state
.append((child
, self
.children(child
)))
1684 class ModuleScanner(Scanner
):
1685 """An interruptible scanner that searches module synopses."""
1687 roots
= map(lambda dir: (dir, ''), pathdirs())
1688 Scanner
.__init
__(self
, roots
, self
.submodules
, self
.isnewpackage
)
1689 self
.inodes
= map(lambda (dir, pkg
): os
.stat(dir)[1], roots
)
1691 def submodules(self
, (dir, package
)):
1693 for file in os
.listdir(dir):
1694 path
= os
.path
.join(dir, file)
1696 children
.append((path
, package
+ (package
and '.') + file))
1698 children
.append((path
, package
))
1699 children
.sort() # so that spam.py comes before spam.pyc or spam.pyo
1702 def isnewpackage(self
, (dir, package
)):
1703 inode
= os
.path
.exists(dir) and os
.stat(dir)[1]
1704 if not (os
.path
.islink(dir) and inode
in self
.inodes
):
1705 self
.inodes
.append(inode
) # detect circular symbolic links
1706 return ispackage(dir)
1708 def run(self
, callback
, key
=None, completer
=None):
1709 if key
: key
= lower(key
)
1713 for modname
in sys
.builtin_module_names
:
1714 if modname
!= '__main__':
1717 callback(None, modname
, '')
1719 desc
= split(__import__(modname
).__doc
__ or '', '\n')[0]
1720 if find(lower(modname
+ ' - ' + desc
), key
) >= 0:
1721 callback(None, modname
, desc
)
1723 while not self
.quit
:
1726 path
, package
= node
1727 modname
= inspect
.getmodulename(path
)
1728 if os
.path
.isfile(path
) and modname
:
1729 modname
= package
+ (package
and '.') + modname
1730 if not seen
.has_key(modname
):
1731 seen
[modname
] = 1 # if we see spam.py, skip spam.pyc
1733 callback(path
, modname
, '')
1735 desc
= synopsis(path
) or ''
1736 if find(lower(modname
+ ' - ' + desc
), key
) >= 0:
1737 callback(path
, modname
, desc
)
1738 if completer
: completer()
1741 """Print all the one-line module summaries that contain a substring."""
1742 def callback(path
, modname
, desc
):
1743 if modname
[-9:] == '.__init__':
1744 modname
= modname
[:-9] + ' (package)'
1745 print modname
, desc
and '- ' + desc
1746 try: import warnings
1747 except ImportError: pass
1748 else: warnings
.filterwarnings('ignore') # ignore problems during import
1749 ModuleScanner().run(callback
, key
)
1751 # --------------------------------------------------- web browser interface
1753 def serve(port
, callback
=None, completer
=None):
1754 import BaseHTTPServer
, mimetools
, select
1756 # Patch up mimetools.Message so it doesn't break if rfc822 is reloaded.
1757 class Message(mimetools
.Message
):
1758 def __init__(self
, fp
, seekable
=1):
1759 Message
= self
.__class
__
1760 Message
.__bases
__[0].__bases
__[0].__init
__(self
, fp
, seekable
)
1761 self
.encodingheader
= self
.getheader('content-transfer-encoding')
1762 self
.typeheader
= self
.getheader('content-type')
1766 class DocHandler(BaseHTTPServer
.BaseHTTPRequestHandler
):
1767 def send_document(self
, title
, contents
):
1769 self
.send_response(200)
1770 self
.send_header('Content-Type', 'text/html')
1772 self
.wfile
.write(html
.page(title
, contents
))
1773 except IOError: pass
1777 if path
[-5:] == '.html': path
= path
[:-5]
1778 if path
[:1] == '/': path
= path
[1:]
1779 if path
and path
!= '.':
1781 obj
= locate(path
, forceload
=1)
1782 except ErrorDuringImport
, value
:
1783 self
.send_document(path
, html
.escape(str(value
)))
1786 self
.send_document(describe(obj
), html
.document(obj
, path
))
1788 self
.send_document(path
,
1789 'no Python documentation found for %s' % repr(path
))
1791 heading
= html
.heading(
1792 '<big><big><strong>Python: Index of Modules</strong></big></big>',
1793 '#ffffff', '#7799ee')
1794 def bltinlink(name
):
1795 return '<a href="%s.html">%s</a>' % (name
, name
)
1796 names
= filter(lambda x
: x
!= '__main__',
1797 sys
.builtin_module_names
)
1798 contents
= html
.multicolumn(names
, bltinlink
)
1799 indices
= ['<p>' + html
.bigsection(
1800 'Built-in Modules', '#ffffff', '#ee77aa', contents
)]
1803 for dir in pathdirs():
1804 indices
.append(html
.index(dir, seen
))
1805 contents
= heading
+ join(indices
) + '''<p align=right>
1806 <font color="#909090" face="helvetica, arial"><strong>
1807 pydoc</strong> by Ka-Ping Yee <ping@lfw.org></font>'''
1808 self
.send_document('Index of Modules', contents
)
1810 def log_message(self
, *args
): pass
1812 class DocServer(BaseHTTPServer
.HTTPServer
):
1813 def __init__(self
, port
, callback
):
1814 host
= (sys
.platform
== 'mac') and '127.0.0.1' or 'localhost'
1815 self
.address
= ('', port
)
1816 self
.url
= 'http://%s:%d/' % (host
, port
)
1817 self
.callback
= callback
1818 self
.base
.__init
__(self
, self
.address
, self
.handler
)
1820 def serve_until_quit(self
):
1823 while not self
.quit
:
1824 rd
, wr
, ex
= select
.select([self
.socket
.fileno()], [], [], 1)
1825 if rd
: self
.handle_request()
1827 def server_activate(self
):
1828 self
.base
.server_activate(self
)
1829 if self
.callback
: self
.callback(self
)
1831 DocServer
.base
= BaseHTTPServer
.HTTPServer
1832 DocServer
.handler
= DocHandler
1833 DocHandler
.MessageClass
= Message
1836 DocServer(port
, callback
).serve_until_quit()
1837 except (KeyboardInterrupt, select
.error
):
1840 if completer
: completer()
1842 # ----------------------------------------------------- graphical interface
1845 """Graphical interface (starts web server and pops up a control window)."""
1847 def __init__(self
, window
, port
=7464):
1848 self
.window
= window
1853 self
.server_frm
= Tkinter
.Frame(window
)
1854 self
.title_lbl
= Tkinter
.Label(self
.server_frm
,
1855 text
='Starting server...\n ')
1856 self
.open_btn
= Tkinter
.Button(self
.server_frm
,
1857 text
='open browser', command
=self
.open, state
='disabled')
1858 self
.quit_btn
= Tkinter
.Button(self
.server_frm
,
1859 text
='quit serving', command
=self
.quit
, state
='disabled')
1861 self
.search_frm
= Tkinter
.Frame(window
)
1862 self
.search_lbl
= Tkinter
.Label(self
.search_frm
, text
='Search for')
1863 self
.search_ent
= Tkinter
.Entry(self
.search_frm
)
1864 self
.search_ent
.bind('<Return>', self
.search
)
1865 self
.stop_btn
= Tkinter
.Button(self
.search_frm
,
1866 text
='stop', pady
=0, command
=self
.stop
, state
='disabled')
1867 if sys
.platform
== 'win32':
1868 # Trying to hide and show this button crashes under Windows.
1869 self
.stop_btn
.pack(side
='right')
1871 self
.window
.title('pydoc')
1872 self
.window
.protocol('WM_DELETE_WINDOW', self
.quit
)
1873 self
.title_lbl
.pack(side
='top', fill
='x')
1874 self
.open_btn
.pack(side
='left', fill
='x', expand
=1)
1875 self
.quit_btn
.pack(side
='right', fill
='x', expand
=1)
1876 self
.server_frm
.pack(side
='top', fill
='x')
1878 self
.search_lbl
.pack(side
='left')
1879 self
.search_ent
.pack(side
='right', fill
='x', expand
=1)
1880 self
.search_frm
.pack(side
='top', fill
='x')
1881 self
.search_ent
.focus_set()
1883 font
= ('helvetica', sys
.platform
== 'win32' and 8 or 10)
1884 self
.result_lst
= Tkinter
.Listbox(window
, font
=font
, height
=6)
1885 self
.result_lst
.bind('<Button-1>', self
.select
)
1886 self
.result_lst
.bind('<Double-Button-1>', self
.goto
)
1887 self
.result_scr
= Tkinter
.Scrollbar(window
,
1888 orient
='vertical', command
=self
.result_lst
.yview
)
1889 self
.result_lst
.config(yscrollcommand
=self
.result_scr
.set)
1891 self
.result_frm
= Tkinter
.Frame(window
)
1892 self
.goto_btn
= Tkinter
.Button(self
.result_frm
,
1893 text
='go to selected', command
=self
.goto
)
1894 self
.hide_btn
= Tkinter
.Button(self
.result_frm
,
1895 text
='hide results', command
=self
.hide
)
1896 self
.goto_btn
.pack(side
='left', fill
='x', expand
=1)
1897 self
.hide_btn
.pack(side
='right', fill
='x', expand
=1)
1899 self
.window
.update()
1900 self
.minwidth
= self
.window
.winfo_width()
1901 self
.minheight
= self
.window
.winfo_height()
1902 self
.bigminheight
= (self
.server_frm
.winfo_reqheight() +
1903 self
.search_frm
.winfo_reqheight() +
1904 self
.result_lst
.winfo_reqheight() +
1905 self
.result_frm
.winfo_reqheight())
1906 self
.bigwidth
, self
.bigheight
= self
.minwidth
, self
.bigminheight
1908 self
.window
.wm_geometry('%dx%d' % (self
.minwidth
, self
.minheight
))
1909 self
.window
.wm_minsize(self
.minwidth
, self
.minheight
)
1913 target
=serve
, args
=(port
, self
.ready
, self
.quit
)).start()
1915 def ready(self
, server
):
1916 self
.server
= server
1917 self
.title_lbl
.config(
1918 text
='Python documentation server at\n' + server
.url
)
1919 self
.open_btn
.config(state
='normal')
1920 self
.quit_btn
.config(state
='normal')
1922 def open(self
, event
=None, url
=None):
1923 url
= url
or self
.server
.url
1926 webbrowser
.open(url
)
1927 except ImportError: # pre-webbrowser.py compatibility
1928 if sys
.platform
== 'win32':
1929 os
.system('start "%s"' % url
)
1930 elif sys
.platform
== 'mac':
1932 except ImportError: pass
1933 else: ic
.launchurl(url
)
1935 rc
= os
.system('netscape -remote "openURL(%s)" &' % url
)
1936 if rc
: os
.system('netscape "%s" &' % url
)
1938 def quit(self
, event
=None):
1940 self
.server
.quit
= 1
1943 def search(self
, event
=None):
1944 key
= self
.search_ent
.get()
1945 self
.stop_btn
.pack(side
='right')
1946 self
.stop_btn
.config(state
='normal')
1947 self
.search_lbl
.config(text
='Searching for "%s"...' % key
)
1948 self
.search_ent
.forget()
1949 self
.search_lbl
.pack(side
='left')
1950 self
.result_lst
.delete(0, 'end')
1951 self
.goto_btn
.config(state
='disabled')
1956 self
.scanner
.quit
= 1
1957 self
.scanner
= ModuleScanner()
1958 threading
.Thread(target
=self
.scanner
.run
,
1959 args
=(self
.update
, key
, self
.done
)).start()
1961 def update(self
, path
, modname
, desc
):
1962 if modname
[-9:] == '.__init__':
1963 modname
= modname
[:-9] + ' (package)'
1964 self
.result_lst
.insert('end',
1965 modname
+ ' - ' + (desc
or '(no description)'))
1967 def stop(self
, event
=None):
1969 self
.scanner
.quit
= 1
1974 self
.search_lbl
.config(text
='Search for')
1975 self
.search_lbl
.pack(side
='left')
1976 self
.search_ent
.pack(side
='right', fill
='x', expand
=1)
1977 if sys
.platform
!= 'win32': self
.stop_btn
.forget()
1978 self
.stop_btn
.config(state
='disabled')
1980 def select(self
, event
=None):
1981 self
.goto_btn
.config(state
='normal')
1983 def goto(self
, event
=None):
1984 selection
= self
.result_lst
.curselection()
1986 modname
= split(self
.result_lst
.get(selection
[0]))[0]
1987 self
.open(url
=self
.server
.url
+ modname
+ '.html')
1990 if not self
.expanded
: return
1991 self
.result_frm
.forget()
1992 self
.result_scr
.forget()
1993 self
.result_lst
.forget()
1994 self
.bigwidth
= self
.window
.winfo_width()
1995 self
.bigheight
= self
.window
.winfo_height()
1996 self
.window
.wm_geometry('%dx%d' % (self
.minwidth
, self
.minheight
))
1997 self
.window
.wm_minsize(self
.minwidth
, self
.minheight
)
2001 if self
.expanded
: return
2002 self
.result_frm
.pack(side
='bottom', fill
='x')
2003 self
.result_scr
.pack(side
='right', fill
='y')
2004 self
.result_lst
.pack(side
='top', fill
='both', expand
=1)
2005 self
.window
.wm_geometry('%dx%d' % (self
.bigwidth
, self
.bigheight
))
2006 self
.window
.wm_minsize(self
.minwidth
, self
.bigminheight
)
2009 def hide(self
, event
=None):
2015 gui
= GUI(Tkinter
.Tk())
2017 except KeyboardInterrupt:
2020 # -------------------------------------------------- command-line interface
2023 return type(x
) is types
.StringType
and find(x
, os
.sep
) >= 0
2026 """Command-line interface (looks at sys.argv to decide what to do)."""
2028 class BadUsage
: pass
2030 # Scripts don't get the current directory in their path by default.
2031 scriptdir
= os
.path
.dirname(sys
.argv
[0])
2032 if scriptdir
in sys
.path
:
2033 sys
.path
.remove(scriptdir
)
2034 sys
.path
.insert(0, '.')
2037 opts
, args
= getopt
.getopt(sys
.argv
[1:], 'gk:p:w')
2040 for opt
, val
in opts
:
2053 print 'pydoc server ready at %s' % server
.url
2055 print 'pydoc server stopped'
2056 serve(port
, ready
, stopped
)
2061 if not args
: raise BadUsage
2064 if ispath(arg
) and os
.path
.isfile(arg
):
2065 arg
= importfile(arg
)
2067 if ispath(arg
) and os
.path
.isdir(arg
):
2073 except ErrorDuringImport
, value
:
2076 except (getopt
.error
, BadUsage
):
2078 print """pydoc - the Python documentation tool
2081 Show text documentation on something. <name> may be the name of a
2082 function, module, or package, or a dotted reference to a class or
2083 function within a module or module in a package. If <name> contains
2084 a '%s', it is used as the path to a Python source file to document.
2087 Search for a keyword in the synopsis lines of all available modules.
2090 Start an HTTP server on the given port on the local machine.
2093 Pop up a graphical interface for finding and serving documentation.
2096 Write out the HTML documentation for a module to a file in the current
2097 directory. If <name> contains a '%s', it is treated as a filename; if
2098 it names a directory, documentation is written for all the contents.
2099 """ % (cmd
, os
.sep
, cmd
, cmd
, cmd
, cmd
, os
.sep
)
2101 if __name__
== '__main__': cli()