]> git.proxmox.com Git - mirror_edk2.git/blob - AppPkg/Applications/Python/Python-2.7.10/PyMod-2.7.10/Lib/pydoc.py
AppPkg/Applications/Python/Python-2.7.10: Initial Checkin part 5/5.
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.10 / PyMod-2.7.10 / Lib / pydoc.py
1 #!/usr/bin/env python
2 # -*- coding: latin-1 -*-
3 """Generate Python documentation in HTML or text for interactive use.
4
5 In the Python interpreter, do "from pydoc import help" to provide online
6 help. Calling help(thing) on a Python object documents the object.
7
8 Or, at the shell command line outside of Python:
9
10 Run "pydoc <name>" to show documentation on something. <name> may be
11 the name of a function, module, package, or a dotted reference to a
12 class or function within a module or module in a package. If the
13 argument contains a path segment delimiter (e.g. slash on Unix,
14 backslash on Windows) it is treated as the path to a Python source file.
15
16 Run "pydoc -k <keyword>" to search for a keyword in the synopsis lines
17 of all available modules.
18
19 Run "pydoc -p <port>" to start an HTTP server on a given port on the
20 local machine to generate documentation web pages. Port number 0 can be
21 used to get an arbitrary unused port.
22
23 For platforms without a command line, "pydoc -g" starts the HTTP server
24 and also pops up a little window for controlling it.
25
26 Run "pydoc -w <name>" to write out the HTML documentation for a module
27 to a file named "<name>.html".
28
29 Module docs for core modules are assumed to be in
30
31 http://docs.python.org/library/
32
33 This can be overridden by setting the PYTHONDOCS environment variable
34 to a different URL or to a local directory containing the Library
35 Reference Manual pages.
36 """
37
38 __author__ = "Ka-Ping Yee <ping@lfw.org>"
39 __date__ = "26 February 2001"
40
41 __version__ = "$Revision: 88564 $"
42 __credits__ = """Guido van Rossum, for an excellent programming language.
43 Tommy Burnette, the original creator of manpy.
44 Paul Prescod, for all his work on onlinehelp.
45 Richard Chamberlain, for the first implementation of textdoc.
46 """
47
48 # Known bugs that can't be fixed here:
49 # - imp.load_module() cannot be prevented from clobbering existing
50 # loaded modules, so calling synopsis() on a binary module file
51 # changes the contents of any existing module with the same name.
52 # - If the __file__ attribute on a module is a relative path and
53 # the current directory is changed with os.chdir(), an incorrect
54 # path will be displayed.
55
56 import sys, imp, os, re, types, inspect, __builtin__, pkgutil, warnings
57 from repr import Repr
58 from string import expandtabs, find, join, lower, split, strip, rfind, rstrip
59 from traceback import extract_tb
60 try:
61 from collections import deque
62 except ImportError:
63 # Python 2.3 compatibility
64 class deque(list):
65 def popleft(self):
66 return self.pop(0)
67
68 # --------------------------------------------------------- common routines
69
70 def pathdirs():
71 """Convert sys.path into a list of absolute, existing, unique paths."""
72 dirs = []
73 normdirs = []
74 for dir in sys.path:
75 dir = os.path.abspath(dir or '.')
76 normdir = os.path.normcase(dir)
77 if normdir not in normdirs and os.path.isdir(dir):
78 dirs.append(dir)
79 normdirs.append(normdir)
80 return dirs
81
82 def getdoc(object):
83 """Get the doc string or comments for an object."""
84 result = inspect.getdoc(object) or inspect.getcomments(object)
85 result = _encode(result)
86 return result and re.sub('^ *\n', '', rstrip(result)) or ''
87
88 def splitdoc(doc):
89 """Split a doc string into a synopsis line (if any) and the rest."""
90 lines = split(strip(doc), '\n')
91 if len(lines) == 1:
92 return lines[0], ''
93 elif len(lines) >= 2 and not rstrip(lines[1]):
94 return lines[0], join(lines[2:], '\n')
95 return '', join(lines, '\n')
96
97 def classname(object, modname):
98 """Get a class name and qualify it with a module name if necessary."""
99 name = object.__name__
100 if object.__module__ != modname:
101 name = object.__module__ + '.' + name
102 return name
103
104 def isdata(object):
105 """Check if an object is of a type that probably means it's data."""
106 return not (inspect.ismodule(object) or inspect.isclass(object) or
107 inspect.isroutine(object) or inspect.isframe(object) or
108 inspect.istraceback(object) or inspect.iscode(object))
109
110 def replace(text, *pairs):
111 """Do a series of global replacements on a string."""
112 while pairs:
113 text = join(split(text, pairs[0]), pairs[1])
114 pairs = pairs[2:]
115 return text
116
117 def cram(text, maxlen):
118 """Omit part of a string if needed to make it fit in a maximum length."""
119 if len(text) > maxlen:
120 pre = max(0, (maxlen-3)//2)
121 post = max(0, maxlen-3-pre)
122 return text[:pre] + '...' + text[len(text)-post:]
123 return text
124
125 _re_stripid = re.compile(r' at 0x[0-9a-f]{6,16}(>+)$', re.IGNORECASE)
126 def stripid(text):
127 """Remove the hexadecimal id from a Python object representation."""
128 # The behaviour of %p is implementation-dependent in terms of case.
129 return _re_stripid.sub(r'\1', text)
130
131 def _is_some_method(obj):
132 return inspect.ismethod(obj) or inspect.ismethoddescriptor(obj)
133
134 def allmethods(cl):
135 methods = {}
136 for key, value in inspect.getmembers(cl, _is_some_method):
137 methods[key] = 1
138 for base in cl.__bases__:
139 methods.update(allmethods(base)) # all your base are belong to us
140 for key in methods.keys():
141 methods[key] = getattr(cl, key)
142 return methods
143
144 def _split_list(s, predicate):
145 """Split sequence s via predicate, and return pair ([true], [false]).
146
147 The return value is a 2-tuple of lists,
148 ([x for x in s if predicate(x)],
149 [x for x in s if not predicate(x)])
150 """
151
152 yes = []
153 no = []
154 for x in s:
155 if predicate(x):
156 yes.append(x)
157 else:
158 no.append(x)
159 return yes, no
160
161 def visiblename(name, all=None, obj=None):
162 """Decide whether to show documentation on a variable."""
163 # Certain special names are redundant.
164 _hidden_names = ('__builtins__', '__doc__', '__file__', '__path__',
165 '__module__', '__name__', '__slots__', '__package__')
166 if name in _hidden_names: return 0
167 # Private names are hidden, but special names are displayed.
168 if name.startswith('__') and name.endswith('__'): return 1
169 # Namedtuples have public fields and methods with a single leading underscore
170 if name.startswith('_') and hasattr(obj, '_fields'):
171 return 1
172 if all is not None:
173 # only document that which the programmer exported in __all__
174 return name in all
175 else:
176 return not name.startswith('_')
177
178 def classify_class_attrs(object):
179 """Wrap inspect.classify_class_attrs, with fixup for data descriptors."""
180 def fixup(data):
181 name, kind, cls, value = data
182 if inspect.isdatadescriptor(value):
183 kind = 'data descriptor'
184 return name, kind, cls, value
185 return map(fixup, inspect.classify_class_attrs(object))
186
187 # ----------------------------------------------------- Unicode support helpers
188
189 try:
190 _unicode = unicode
191 except NameError:
192 # If Python is built without Unicode support, the unicode type
193 # will not exist. Fake one that nothing will match, and make
194 # the _encode function that do nothing.
195 class _unicode(object):
196 pass
197 _encoding = 'ascii'
198 def _encode(text, encoding='ascii'):
199 return text
200 else:
201 import locale
202 _encoding = locale.getpreferredencoding()
203
204 def _encode(text, encoding=None):
205 if isinstance(text, unicode):
206 return text.encode(encoding or _encoding, 'xmlcharrefreplace')
207 else:
208 return text
209
210 def _binstr(obj):
211 # Ensure that we have an encoded (binary) string representation of obj,
212 # even if it is a unicode string.
213 if isinstance(obj, _unicode):
214 return obj.encode(_encoding, 'xmlcharrefreplace')
215 return str(obj)
216
217 # ----------------------------------------------------- module manipulation
218
219 def ispackage(path):
220 """Guess whether a path refers to a package directory."""
221 if os.path.isdir(path):
222 for ext in ('.py', '.pyc', '.pyo'):
223 if os.path.isfile(os.path.join(path, '__init__' + ext)):
224 return True
225 return False
226
227 def source_synopsis(file):
228 line = file.readline()
229 while line[:1] == '#' or not strip(line):
230 line = file.readline()
231 if not line: break
232 line = strip(line)
233 if line[:4] == 'r"""': line = line[1:]
234 if line[:3] == '"""':
235 line = line[3:]
236 if line[-1:] == '\\': line = line[:-1]
237 while not strip(line):
238 line = file.readline()
239 if not line: break
240 result = strip(split(line, '"""')[0])
241 else: result = None
242 return result
243
244 def synopsis(filename, cache={}):
245 """Get the one-line summary out of a module file."""
246 mtime = os.stat(filename).st_mtime
247 lastupdate, result = cache.get(filename, (None, None))
248 if lastupdate is None or lastupdate < mtime:
249 info = inspect.getmoduleinfo(filename)
250 try:
251 file = open(filename)
252 except IOError:
253 # module can't be opened, so skip it
254 return None
255 if info and 'b' in info[2]: # binary modules have to be imported
256 try: module = imp.load_module('__temp__', file, filename, info[1:])
257 except: return None
258 result = module.__doc__.splitlines()[0] if module.__doc__ else None
259 del sys.modules['__temp__']
260 else: # text modules can be directly examined
261 result = source_synopsis(file)
262 file.close()
263 cache[filename] = (mtime, result)
264 return result
265
266 class ErrorDuringImport(Exception):
267 """Errors that occurred while trying to import something to document it."""
268 def __init__(self, filename, exc_info):
269 exc, value, tb = exc_info
270 self.filename = filename
271 self.exc = exc
272 self.value = value
273 self.tb = tb
274
275 def __str__(self):
276 exc = self.exc
277 if type(exc) is types.ClassType:
278 exc = exc.__name__
279 return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
280
281 def importfile(path):
282 """Import a Python source file or compiled file given its path."""
283 magic = imp.get_magic()
284 file = open(path, 'r')
285 if file.read(len(magic)) == magic:
286 kind = imp.PY_COMPILED
287 else:
288 kind = imp.PY_SOURCE
289 file.close()
290 filename = os.path.basename(path)
291 name, ext = os.path.splitext(filename)
292 file = open(path, 'r')
293 try:
294 module = imp.load_module(name, file, path, (ext, 'r', kind))
295 except:
296 raise ErrorDuringImport(path, sys.exc_info())
297 file.close()
298 return module
299
300 def safeimport(path, forceload=0, cache={}):
301 """Import a module; handle errors; return None if the module isn't found.
302
303 If the module *is* found but an exception occurs, it's wrapped in an
304 ErrorDuringImport exception and reraised. Unlike __import__, if a
305 package path is specified, the module at the end of the path is returned,
306 not the package at the beginning. If the optional 'forceload' argument
307 is 1, we reload the module from disk (unless it's a dynamic extension)."""
308 try:
309 # If forceload is 1 and the module has been previously loaded from
310 # disk, we always have to reload the module. Checking the file's
311 # mtime isn't good enough (e.g. the module could contain a class
312 # that inherits from another module that has changed).
313 if forceload and path in sys.modules:
314 if path not in sys.builtin_module_names:
315 # Avoid simply calling reload() because it leaves names in
316 # the currently loaded module lying around if they're not
317 # defined in the new source file. Instead, remove the
318 # module from sys.modules and re-import. Also remove any
319 # submodules because they won't appear in the newly loaded
320 # module's namespace if they're already in sys.modules.
321 subs = [m for m in sys.modules if m.startswith(path + '.')]
322 for key in [path] + subs:
323 # Prevent garbage collection.
324 cache[key] = sys.modules[key]
325 del sys.modules[key]
326 module = __import__(path)
327 except:
328 # Did the error occur before or after the module was found?
329 (exc, value, tb) = info = sys.exc_info()
330 if path in sys.modules:
331 # An error occurred while executing the imported module.
332 raise ErrorDuringImport(sys.modules[path].__file__, info)
333 elif exc is SyntaxError:
334 # A SyntaxError occurred before we could execute the module.
335 raise ErrorDuringImport(value.filename, info)
336 elif exc is ImportError and extract_tb(tb)[-1][2]=='safeimport':
337 # The import error occurred directly in this function,
338 # which means there is no such module in the path.
339 return None
340 else:
341 # Some other error occurred during the importing process.
342 raise ErrorDuringImport(path, sys.exc_info())
343 for part in split(path, '.')[1:]:
344 try: module = getattr(module, part)
345 except AttributeError: return None
346 return module
347
348 # ---------------------------------------------------- formatter base class
349
350 class Doc:
351 def document(self, object, name=None, *args):
352 """Generate documentation for an object."""
353 args = (object, name) + args
354 # 'try' clause is to attempt to handle the possibility that inspect
355 # identifies something in a way that pydoc itself has issues handling;
356 # think 'super' and how it is a descriptor (which raises the exception
357 # by lacking a __name__ attribute) and an instance.
358 if inspect.isgetsetdescriptor(object): return self.docdata(*args)
359 if inspect.ismemberdescriptor(object): return self.docdata(*args)
360 try:
361 if inspect.ismodule(object): return self.docmodule(*args)
362 if inspect.isclass(object): return self.docclass(*args)
363 if inspect.isroutine(object): return self.docroutine(*args)
364 except AttributeError:
365 pass
366 if isinstance(object, property): return self.docproperty(*args)
367 return self.docother(*args)
368
369 def fail(self, object, name=None, *args):
370 """Raise an exception for unimplemented types."""
371 message = "don't know how to document object%s of type %s" % (
372 name and ' ' + repr(name), type(object).__name__)
373 raise TypeError, message
374
375 docmodule = docclass = docroutine = docother = docproperty = docdata = fail
376
377 def getdocloc(self, object):
378 """Return the location of module docs or None"""
379
380 try:
381 file = inspect.getabsfile(object)
382 except TypeError:
383 file = '(built-in)'
384
385 docloc = os.environ.get("PYTHONDOCS",
386 "http://docs.python.org/library")
387 basedir = os.path.join(sys.exec_prefix, "lib",
388 "python"+sys.version[0:3])
389 if (isinstance(object, type(os)) and
390 (object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
391 'marshal', 'posix', 'signal', 'sys',
392 'thread', 'zipimport') or
393 (file.startswith(basedir) and
394 not file.startswith(os.path.join(basedir, 'site-packages')))) and
395 object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
396 if docloc.startswith("http://"):
397 docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
398 else:
399 docloc = os.path.join(docloc, object.__name__ + ".html")
400 else:
401 docloc = None
402 return docloc
403
404 # -------------------------------------------- HTML documentation generator
405
406 class HTMLRepr(Repr):
407 """Class for safely making an HTML representation of a Python object."""
408 def __init__(self):
409 Repr.__init__(self)
410 self.maxlist = self.maxtuple = 20
411 self.maxdict = 10
412 self.maxstring = self.maxother = 100
413
414 def escape(self, text):
415 return replace(text, '&', '&amp;', '<', '&lt;', '>', '&gt;')
416
417 def repr(self, object):
418 return Repr.repr(self, object)
419
420 def repr1(self, x, level):
421 if hasattr(type(x), '__name__'):
422 methodname = 'repr_' + join(split(type(x).__name__), '_')
423 if hasattr(self, methodname):
424 return getattr(self, methodname)(x, level)
425 return self.escape(cram(stripid(repr(x)), self.maxother))
426
427 def repr_string(self, x, level):
428 test = cram(x, self.maxstring)
429 testrepr = repr(test)
430 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
431 # Backslashes are only literal in the string and are never
432 # needed to make any special characters, so show a raw string.
433 return 'r' + testrepr[0] + self.escape(test) + testrepr[0]
434 return re.sub(r'((\\[\\abfnrtv\'"]|\\[0-9]..|\\x..|\\u....)+)',
435 r'<font color="#c040c0">\1</font>',
436 self.escape(testrepr))
437
438 repr_str = repr_string
439
440 def repr_instance(self, x, level):
441 try:
442 return self.escape(cram(stripid(repr(x)), self.maxstring))
443 except:
444 return self.escape('<%s instance>' % x.__class__.__name__)
445
446 repr_unicode = repr_string
447
448 class HTMLDoc(Doc):
449 """Formatter class for HTML documentation."""
450
451 # ------------------------------------------- HTML formatting utilities
452
453 _repr_instance = HTMLRepr()
454 repr = _repr_instance.repr
455 escape = _repr_instance.escape
456
457 def page(self, title, contents):
458 """Format an HTML page."""
459 return _encode('''
460 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
461 <html><head><title>Python: %s</title>
462 <meta charset="utf-8">
463 </head><body bgcolor="#f0f0f8">
464 %s
465 </body></html>''' % (title, contents), 'ascii')
466
467 def heading(self, title, fgcol, bgcol, extras=''):
468 """Format a page heading."""
469 return '''
470 <table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
471 <tr bgcolor="%s">
472 <td valign=bottom>&nbsp;<br>
473 <font color="%s" face="helvetica, arial">&nbsp;<br>%s</font></td
474 ><td align=right valign=bottom
475 ><font color="%s" face="helvetica, arial">%s</font></td></tr></table>
476 ''' % (bgcol, fgcol, title, fgcol, extras or '&nbsp;')
477
478 def section(self, title, fgcol, bgcol, contents, width=6,
479 prelude='', marginalia=None, gap='&nbsp;'):
480 """Format a section with a heading."""
481 if marginalia is None:
482 marginalia = '<tt>' + '&nbsp;' * width + '</tt>'
483 result = '''<p>
484 <table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
485 <tr bgcolor="%s">
486 <td colspan=3 valign=bottom>&nbsp;<br>
487 <font color="%s" face="helvetica, arial">%s</font></td></tr>
488 ''' % (bgcol, fgcol, title)
489 if prelude:
490 result = result + '''
491 <tr bgcolor="%s"><td rowspan=2>%s</td>
492 <td colspan=2>%s</td></tr>
493 <tr><td>%s</td>''' % (bgcol, marginalia, prelude, gap)
494 else:
495 result = result + '''
496 <tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
497
498 return result + '\n<td width="100%%">%s</td></tr></table>' % contents
499
500 def bigsection(self, title, *args):
501 """Format a section with a big heading."""
502 title = '<big><strong>%s</strong></big>' % title
503 return self.section(title, *args)
504
505 def preformat(self, text):
506 """Format literal preformatted text."""
507 text = self.escape(expandtabs(text))
508 return replace(text, '\n\n', '\n \n', '\n\n', '\n \n',
509 ' ', '&nbsp;', '\n', '<br>\n')
510
511 def multicolumn(self, list, format, cols=4):
512 """Format a list of items into a multi-column list."""
513 result = ''
514 rows = (len(list)+cols-1)//cols
515 for col in range(cols):
516 result = result + '<td width="%d%%" valign=top>' % (100//cols)
517 for i in range(rows*col, rows*col+rows):
518 if i < len(list):
519 result = result + format(list[i]) + '<br>\n'
520 result = result + '</td>'
521 return '<table width="100%%" summary="list"><tr>%s</tr></table>' % result
522
523 def grey(self, text): return '<font color="#909090">%s</font>' % text
524
525 def namelink(self, name, *dicts):
526 """Make a link for an identifier, given name-to-URL mappings."""
527 for dict in dicts:
528 if name in dict:
529 return '<a href="%s">%s</a>' % (dict[name], name)
530 return name
531
532 def classlink(self, object, modname):
533 """Make a link for a class."""
534 name, module = object.__name__, sys.modules.get(object.__module__)
535 if hasattr(module, name) and getattr(module, name) is object:
536 return '<a href="%s.html#%s">%s</a>' % (
537 module.__name__, name, classname(object, modname))
538 return classname(object, modname)
539
540 def modulelink(self, object):
541 """Make a link for a module."""
542 return '<a href="%s.html">%s</a>' % (object.__name__, object.__name__)
543
544 def modpkglink(self, data):
545 """Make a link for a module or package to display in an index."""
546 name, path, ispackage, shadowed = data
547 if shadowed:
548 return self.grey(name)
549 if path:
550 url = '%s.%s.html' % (path, name)
551 else:
552 url = '%s.html' % name
553 if ispackage:
554 text = '<strong>%s</strong>&nbsp;(package)' % name
555 else:
556 text = name
557 return '<a href="%s">%s</a>' % (url, text)
558
559 def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
560 """Mark up some plain text, given a context of symbols to look for.
561 Each context dictionary maps object names to anchor names."""
562 escape = escape or self.escape
563 results = []
564 here = 0
565 pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
566 r'RFC[- ]?(\d+)|'
567 r'PEP[- ]?(\d+)|'
568 r'(self\.)?(\w+))')
569 while True:
570 match = pattern.search(text, here)
571 if not match: break
572 start, end = match.span()
573 results.append(escape(text[here:start]))
574
575 all, scheme, rfc, pep, selfdot, name = match.groups()
576 if scheme:
577 url = escape(all).replace('"', '&quot;')
578 results.append('<a href="%s">%s</a>' % (url, url))
579 elif rfc:
580 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
581 results.append('<a href="%s">%s</a>' % (url, escape(all)))
582 elif pep:
583 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
584 results.append('<a href="%s">%s</a>' % (url, escape(all)))
585 elif selfdot:
586 # Create a link for methods like 'self.method(...)'
587 # and use <strong> for attributes like 'self.attr'
588 if text[end:end+1] == '(':
589 results.append('self.' + self.namelink(name, methods))
590 else:
591 results.append('self.<strong>%s</strong>' % name)
592 elif text[end:end+1] == '(':
593 results.append(self.namelink(name, methods, funcs, classes))
594 else:
595 results.append(self.namelink(name, classes))
596 here = end
597 results.append(escape(text[here:]))
598 return join(results, '')
599
600 # ---------------------------------------------- type-specific routines
601
602 def formattree(self, tree, modname, parent=None):
603 """Produce HTML for a class tree as given by inspect.getclasstree()."""
604 result = ''
605 for entry in tree:
606 if type(entry) is type(()):
607 c, bases = entry
608 result = result + '<dt><font face="helvetica, arial">'
609 result = result + self.classlink(c, modname)
610 if bases and bases != (parent,):
611 parents = []
612 for base in bases:
613 parents.append(self.classlink(base, modname))
614 result = result + '(' + join(parents, ', ') + ')'
615 result = result + '\n</font></dt>'
616 elif type(entry) is type([]):
617 result = result + '<dd>\n%s</dd>\n' % self.formattree(
618 entry, modname, c)
619 return '<dl>\n%s</dl>\n' % result
620
621 def docmodule(self, object, name=None, mod=None, *ignored):
622 """Produce HTML documentation for a module object."""
623 name = object.__name__ # ignore the passed-in name
624 try:
625 all = object.__all__
626 except AttributeError:
627 all = None
628 parts = split(name, '.')
629 links = []
630 for i in range(len(parts)-1):
631 links.append(
632 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
633 (join(parts[:i+1], '.'), parts[i]))
634 linkedname = join(links + parts[-1:], '.')
635 head = '<big><big><strong>%s</strong></big></big>' % linkedname
636 try:
637 path = inspect.getabsfile(object)
638 url = path
639 if sys.platform == 'win32':
640 import nturl2path
641 url = nturl2path.pathname2url(path)
642 filelink = '<a href="file:%s">%s</a>' % (url, path)
643 except TypeError:
644 filelink = '(built-in)'
645 info = []
646 if hasattr(object, '__version__'):
647 version = _binstr(object.__version__)
648 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
649 version = strip(version[11:-1])
650 info.append('version %s' % self.escape(version))
651 if hasattr(object, '__date__'):
652 info.append(self.escape(_binstr(object.__date__)))
653 if info:
654 head = head + ' (%s)' % join(info, ', ')
655 docloc = self.getdocloc(object)
656 if docloc is not None:
657 docloc = '<br><a href="%(docloc)s">Module Docs</a>' % locals()
658 else:
659 docloc = ''
660 result = self.heading(
661 head, '#ffffff', '#7799ee',
662 '<a href=".">index</a><br>' + filelink + docloc)
663
664 modules = inspect.getmembers(object, inspect.ismodule)
665
666 classes, cdict = [], {}
667 for key, value in inspect.getmembers(object, inspect.isclass):
668 # if __all__ exists, believe it. Otherwise use old heuristic.
669 if (all is not None or
670 (inspect.getmodule(value) or object) is object):
671 if visiblename(key, all, object):
672 classes.append((key, value))
673 cdict[key] = cdict[value] = '#' + key
674 for key, value in classes:
675 for base in value.__bases__:
676 key, modname = base.__name__, base.__module__
677 module = sys.modules.get(modname)
678 if modname != name and module and hasattr(module, key):
679 if getattr(module, key) is base:
680 if not key in cdict:
681 cdict[key] = cdict[base] = modname + '.html#' + key
682 funcs, fdict = [], {}
683 for key, value in inspect.getmembers(object, inspect.isroutine):
684 # if __all__ exists, believe it. Otherwise use old heuristic.
685 if (all is not None or
686 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
687 if visiblename(key, all, object):
688 funcs.append((key, value))
689 fdict[key] = '#-' + key
690 if inspect.isfunction(value): fdict[value] = fdict[key]
691 data = []
692 for key, value in inspect.getmembers(object, isdata):
693 if visiblename(key, all, object):
694 data.append((key, value))
695
696 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
697 doc = doc and '<tt>%s</tt>' % doc
698 result = result + '<p>%s</p>\n' % doc
699
700 if hasattr(object, '__path__'):
701 modpkgs = []
702 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
703 modpkgs.append((modname, name, ispkg, 0))
704 modpkgs.sort()
705 contents = self.multicolumn(modpkgs, self.modpkglink)
706 result = result + self.bigsection(
707 'Package Contents', '#ffffff', '#aa55cc', contents)
708 elif modules:
709 contents = self.multicolumn(
710 modules, lambda key_value, s=self: s.modulelink(key_value[1]))
711 result = result + self.bigsection(
712 'Modules', '#ffffff', '#aa55cc', contents)
713
714 if classes:
715 classlist = map(lambda key_value: key_value[1], classes)
716 contents = [
717 self.formattree(inspect.getclasstree(classlist, 1), name)]
718 for key, value in classes:
719 contents.append(self.document(value, key, name, fdict, cdict))
720 result = result + self.bigsection(
721 'Classes', '#ffffff', '#ee77aa', join(contents))
722 if funcs:
723 contents = []
724 for key, value in funcs:
725 contents.append(self.document(value, key, name, fdict, cdict))
726 result = result + self.bigsection(
727 'Functions', '#ffffff', '#eeaa77', join(contents))
728 if data:
729 contents = []
730 for key, value in data:
731 contents.append(self.document(value, key))
732 result = result + self.bigsection(
733 'Data', '#ffffff', '#55aa55', join(contents, '<br>\n'))
734 if hasattr(object, '__author__'):
735 contents = self.markup(_binstr(object.__author__), self.preformat)
736 result = result + self.bigsection(
737 'Author', '#ffffff', '#7799ee', contents)
738 if hasattr(object, '__credits__'):
739 contents = self.markup(_binstr(object.__credits__), self.preformat)
740 result = result + self.bigsection(
741 'Credits', '#ffffff', '#7799ee', contents)
742
743 return result
744
745 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
746 *ignored):
747 """Produce HTML documentation for a class object."""
748 realname = object.__name__
749 name = name or realname
750 bases = object.__bases__
751
752 contents = []
753 push = contents.append
754
755 # Cute little class to pump out a horizontal rule between sections.
756 class HorizontalRule:
757 def __init__(self):
758 self.needone = 0
759 def maybe(self):
760 if self.needone:
761 push('<hr>\n')
762 self.needone = 1
763 hr = HorizontalRule()
764
765 # List the mro, if non-trivial.
766 mro = deque(inspect.getmro(object))
767 if len(mro) > 2:
768 hr.maybe()
769 push('<dl><dt>Method resolution order:</dt>\n')
770 for base in mro:
771 push('<dd>%s</dd>\n' % self.classlink(base,
772 object.__module__))
773 push('</dl>\n')
774
775 def spill(msg, attrs, predicate):
776 ok, attrs = _split_list(attrs, predicate)
777 if ok:
778 hr.maybe()
779 push(msg)
780 for name, kind, homecls, value in ok:
781 try:
782 value = getattr(object, name)
783 except Exception:
784 # Some descriptors may meet a failure in their __get__.
785 # (bug #1785)
786 push(self._docdescriptor(name, value, mod))
787 else:
788 push(self.document(value, name, mod,
789 funcs, classes, mdict, object))
790 push('\n')
791 return attrs
792
793 def spilldescriptors(msg, attrs, predicate):
794 ok, attrs = _split_list(attrs, predicate)
795 if ok:
796 hr.maybe()
797 push(msg)
798 for name, kind, homecls, value in ok:
799 push(self._docdescriptor(name, value, mod))
800 return attrs
801
802 def spilldata(msg, attrs, predicate):
803 ok, attrs = _split_list(attrs, predicate)
804 if ok:
805 hr.maybe()
806 push(msg)
807 for name, kind, homecls, value in ok:
808 base = self.docother(getattr(object, name), name, mod)
809 if (hasattr(value, '__call__') or
810 inspect.isdatadescriptor(value)):
811 doc = getattr(value, "__doc__", None)
812 else:
813 doc = None
814 if doc is None:
815 push('<dl><dt>%s</dl>\n' % base)
816 else:
817 doc = self.markup(getdoc(value), self.preformat,
818 funcs, classes, mdict)
819 doc = '<dd><tt>%s</tt>' % doc
820 push('<dl><dt>%s%s</dl>\n' % (base, doc))
821 push('\n')
822 return attrs
823
824 attrs = filter(lambda data: visiblename(data[0], obj=object),
825 classify_class_attrs(object))
826 mdict = {}
827 for key, kind, homecls, value in attrs:
828 mdict[key] = anchor = '#' + name + '-' + key
829 try:
830 value = getattr(object, name)
831 except Exception:
832 # Some descriptors may meet a failure in their __get__.
833 # (bug #1785)
834 pass
835 try:
836 # The value may not be hashable (e.g., a data attr with
837 # a dict or list value).
838 mdict[value] = anchor
839 except TypeError:
840 pass
841
842 while attrs:
843 if mro:
844 thisclass = mro.popleft()
845 else:
846 thisclass = attrs[0][2]
847 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
848
849 if thisclass is __builtin__.object:
850 attrs = inherited
851 continue
852 elif thisclass is object:
853 tag = 'defined here'
854 else:
855 tag = 'inherited from %s' % self.classlink(thisclass,
856 object.__module__)
857 tag += ':<br>\n'
858
859 # Sort attrs by name.
860 try:
861 attrs.sort(key=lambda t: t[0])
862 except TypeError:
863 attrs.sort(lambda t1, t2: cmp(t1[0], t2[0])) # 2.3 compat
864
865 # Pump out the attrs, segregated by kind.
866 attrs = spill('Methods %s' % tag, attrs,
867 lambda t: t[1] == 'method')
868 attrs = spill('Class methods %s' % tag, attrs,
869 lambda t: t[1] == 'class method')
870 attrs = spill('Static methods %s' % tag, attrs,
871 lambda t: t[1] == 'static method')
872 attrs = spilldescriptors('Data descriptors %s' % tag, attrs,
873 lambda t: t[1] == 'data descriptor')
874 attrs = spilldata('Data and other attributes %s' % tag, attrs,
875 lambda t: t[1] == 'data')
876 assert attrs == []
877 attrs = inherited
878
879 contents = ''.join(contents)
880
881 if name == realname:
882 title = '<a name="%s">class <strong>%s</strong></a>' % (
883 name, realname)
884 else:
885 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
886 name, name, realname)
887 if bases:
888 parents = []
889 for base in bases:
890 parents.append(self.classlink(base, object.__module__))
891 title = title + '(%s)' % join(parents, ', ')
892 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
893 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc
894
895 return self.section(title, '#000000', '#ffc8d8', contents, 3, doc)
896
897 def formatvalue(self, object):
898 """Format an argument default value as text."""
899 return self.grey('=' + self.repr(object))
900
901 def docroutine(self, object, name=None, mod=None,
902 funcs={}, classes={}, methods={}, cl=None):
903 """Produce HTML documentation for a function or method object."""
904 realname = object.__name__
905 name = name or realname
906 anchor = (cl and cl.__name__ or '') + '-' + name
907 note = ''
908 skipdocs = 0
909 if inspect.ismethod(object):
910 imclass = object.im_class
911 if cl:
912 if imclass is not cl:
913 note = ' from ' + self.classlink(imclass, mod)
914 else:
915 if object.im_self is not None:
916 note = ' method of %s instance' % self.classlink(
917 object.im_self.__class__, mod)
918 else:
919 note = ' unbound %s method' % self.classlink(imclass,mod)
920 object = object.im_func
921
922 if name == realname:
923 title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
924 else:
925 if (cl and realname in cl.__dict__ and
926 cl.__dict__[realname] is object):
927 reallink = '<a href="#%s">%s</a>' % (
928 cl.__name__ + '-' + realname, realname)
929 skipdocs = 1
930 else:
931 reallink = realname
932 title = '<a name="%s"><strong>%s</strong></a> = %s' % (
933 anchor, name, reallink)
934 if inspect.isfunction(object):
935 args, varargs, varkw, defaults = inspect.getargspec(object)
936 argspec = inspect.formatargspec(
937 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
938 if realname == '<lambda>':
939 title = '<strong>%s</strong> <em>lambda</em> ' % name
940 argspec = argspec[1:-1] # remove parentheses
941 else:
942 argspec = '(...)'
943
944 decl = title + argspec + (note and self.grey(
945 '<font face="helvetica, arial">%s</font>' % note))
946
947 if skipdocs:
948 return '<dl><dt>%s</dt></dl>\n' % decl
949 else:
950 doc = self.markup(
951 getdoc(object), self.preformat, funcs, classes, methods)
952 doc = doc and '<dd><tt>%s</tt></dd>' % doc
953 return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
954
955 def _docdescriptor(self, name, value, mod):
956 results = []
957 push = results.append
958
959 if name:
960 push('<dl><dt><strong>%s</strong></dt>\n' % name)
961 if value.__doc__ is not None:
962 doc = self.markup(getdoc(value), self.preformat)
963 push('<dd><tt>%s</tt></dd>\n' % doc)
964 push('</dl>\n')
965
966 return ''.join(results)
967
968 def docproperty(self, object, name=None, mod=None, cl=None):
969 """Produce html documentation for a property."""
970 return self._docdescriptor(name, object, mod)
971
972 def docother(self, object, name=None, mod=None, *ignored):
973 """Produce HTML documentation for a data object."""
974 lhs = name and '<strong>%s</strong> = ' % name or ''
975 return lhs + self.repr(object)
976
977 def docdata(self, object, name=None, mod=None, cl=None):
978 """Produce html documentation for a data descriptor."""
979 return self._docdescriptor(name, object, mod)
980
981 def index(self, dir, shadowed=None):
982 """Generate an HTML index for a directory of modules."""
983 modpkgs = []
984 if shadowed is None: shadowed = {}
985 for importer, name, ispkg in pkgutil.iter_modules([dir]):
986 modpkgs.append((name, '', ispkg, name in shadowed))
987 shadowed[name] = 1
988
989 modpkgs.sort()
990 contents = self.multicolumn(modpkgs, self.modpkglink)
991 return self.bigsection(dir, '#ffffff', '#ee77aa', contents)
992
993 # -------------------------------------------- text documentation generator
994
995 class TextRepr(Repr):
996 """Class for safely making a text representation of a Python object."""
997 def __init__(self):
998 Repr.__init__(self)
999 self.maxlist = self.maxtuple = 20
1000 self.maxdict = 10
1001 self.maxstring = self.maxother = 100
1002
1003 def repr1(self, x, level):
1004 if hasattr(type(x), '__name__'):
1005 methodname = 'repr_' + join(split(type(x).__name__), '_')
1006 if hasattr(self, methodname):
1007 return getattr(self, methodname)(x, level)
1008 return cram(stripid(repr(x)), self.maxother)
1009
1010 def repr_string(self, x, level):
1011 test = cram(x, self.maxstring)
1012 testrepr = repr(test)
1013 if '\\' in test and '\\' not in replace(testrepr, r'\\', ''):
1014 # Backslashes are only literal in the string and are never
1015 # needed to make any special characters, so show a raw string.
1016 return 'r' + testrepr[0] + test + testrepr[0]
1017 return testrepr
1018
1019 repr_str = repr_string
1020
1021 def repr_instance(self, x, level):
1022 try:
1023 return cram(stripid(repr(x)), self.maxstring)
1024 except:
1025 return '<%s instance>' % x.__class__.__name__
1026
1027 class TextDoc(Doc):
1028 """Formatter class for text documentation."""
1029
1030 # ------------------------------------------- text formatting utilities
1031
1032 _repr_instance = TextRepr()
1033 repr = _repr_instance.repr
1034
1035 def bold(self, text):
1036 """Format a string in bold by overstriking."""
1037 return join(map(lambda ch: ch + '\b' + ch, text), '')
1038
1039 def indent(self, text, prefix=' '):
1040 """Indent text by prepending a given prefix to each line."""
1041 if not text: return ''
1042 lines = split(text, '\n')
1043 lines = map(lambda line, prefix=prefix: prefix + line, lines)
1044 if lines: lines[-1] = rstrip(lines[-1])
1045 return join(lines, '\n')
1046
1047 def section(self, title, contents):
1048 """Format a section with a given heading."""
1049 return self.bold(title) + '\n' + rstrip(self.indent(contents)) + '\n\n'
1050
1051 # ---------------------------------------------- type-specific routines
1052
1053 def formattree(self, tree, modname, parent=None, prefix=''):
1054 """Render in text a class tree as returned by inspect.getclasstree()."""
1055 result = ''
1056 for entry in tree:
1057 if type(entry) is type(()):
1058 c, bases = entry
1059 result = result + prefix + classname(c, modname)
1060 if bases and bases != (parent,):
1061 parents = map(lambda c, m=modname: classname(c, m), bases)
1062 result = result + '(%s)' % join(parents, ', ')
1063 result = result + '\n'
1064 elif type(entry) is type([]):
1065 result = result + self.formattree(
1066 entry, modname, c, prefix + ' ')
1067 return result
1068
1069 def docmodule(self, object, name=None, mod=None):
1070 """Produce text documentation for a given module object."""
1071 name = object.__name__ # ignore the passed-in name
1072 synop, desc = splitdoc(getdoc(object))
1073 result = self.section('NAME', name + (synop and ' - ' + synop))
1074
1075 try:
1076 all = object.__all__
1077 except AttributeError:
1078 all = None
1079
1080 try:
1081 file = inspect.getabsfile(object)
1082 except TypeError:
1083 file = '(built-in)'
1084 result = result + self.section('FILE', file)
1085
1086 docloc = self.getdocloc(object)
1087 if docloc is not None:
1088 result = result + self.section('MODULE DOCS', docloc)
1089
1090 if desc:
1091 result = result + self.section('DESCRIPTION', desc)
1092
1093 classes = []
1094 for key, value in inspect.getmembers(object, inspect.isclass):
1095 # if __all__ exists, believe it. Otherwise use old heuristic.
1096 if (all is not None
1097 or (inspect.getmodule(value) or object) is object):
1098 if visiblename(key, all, object):
1099 classes.append((key, value))
1100 funcs = []
1101 for key, value in inspect.getmembers(object, inspect.isroutine):
1102 # if __all__ exists, believe it. Otherwise use old heuristic.
1103 if (all is not None or
1104 inspect.isbuiltin(value) or inspect.getmodule(value) is object):
1105 if visiblename(key, all, object):
1106 funcs.append((key, value))
1107 data = []
1108 for key, value in inspect.getmembers(object, isdata):
1109 if visiblename(key, all, object):
1110 data.append((key, value))
1111
1112 modpkgs = []
1113 modpkgs_names = set()
1114 if hasattr(object, '__path__'):
1115 for importer, modname, ispkg in pkgutil.iter_modules(object.__path__):
1116 modpkgs_names.add(modname)
1117 if ispkg:
1118 modpkgs.append(modname + ' (package)')
1119 else:
1120 modpkgs.append(modname)
1121
1122 modpkgs.sort()
1123 result = result + self.section(
1124 'PACKAGE CONTENTS', join(modpkgs, '\n'))
1125
1126 # Detect submodules as sometimes created by C extensions
1127 submodules = []
1128 for key, value in inspect.getmembers(object, inspect.ismodule):
1129 if value.__name__.startswith(name + '.') and key not in modpkgs_names:
1130 submodules.append(key)
1131 if submodules:
1132 submodules.sort()
1133 result = result + self.section(
1134 'SUBMODULES', join(submodules, '\n'))
1135
1136 if classes:
1137 classlist = map(lambda key_value: key_value[1], classes)
1138 contents = [self.formattree(
1139 inspect.getclasstree(classlist, 1), name)]
1140 for key, value in classes:
1141 contents.append(self.document(value, key, name))
1142 result = result + self.section('CLASSES', join(contents, '\n'))
1143
1144 if funcs:
1145 contents = []
1146 for key, value in funcs:
1147 contents.append(self.document(value, key, name))
1148 result = result + self.section('FUNCTIONS', join(contents, '\n'))
1149
1150 if data:
1151 contents = []
1152 for key, value in data:
1153 contents.append(self.docother(value, key, name, maxlen=70))
1154 result = result + self.section('DATA', join(contents, '\n'))
1155
1156 if hasattr(object, '__version__'):
1157 version = _binstr(object.__version__)
1158 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
1159 version = strip(version[11:-1])
1160 result = result + self.section('VERSION', version)
1161 if hasattr(object, '__date__'):
1162 result = result + self.section('DATE', _binstr(object.__date__))
1163 if hasattr(object, '__author__'):
1164 result = result + self.section('AUTHOR', _binstr(object.__author__))
1165 if hasattr(object, '__credits__'):
1166 result = result + self.section('CREDITS', _binstr(object.__credits__))
1167 return result
1168
1169 def docclass(self, object, name=None, mod=None, *ignored):
1170 """Produce text documentation for a given class object."""
1171 realname = object.__name__
1172 name = name or realname
1173 bases = object.__bases__
1174
1175 def makename(c, m=object.__module__):
1176 return classname(c, m)
1177
1178 if name == realname:
1179 title = 'class ' + self.bold(realname)
1180 else:
1181 title = self.bold(name) + ' = class ' + realname
1182 if bases:
1183 parents = map(makename, bases)
1184 title = title + '(%s)' % join(parents, ', ')
1185
1186 doc = getdoc(object)
1187 contents = doc and [doc + '\n'] or []
1188 push = contents.append
1189
1190 # List the mro, if non-trivial.
1191 mro = deque(inspect.getmro(object))
1192 if len(mro) > 2:
1193 push("Method resolution order:")
1194 for base in mro:
1195 push(' ' + makename(base))
1196 push('')
1197
1198 # Cute little class to pump out a horizontal rule between sections.
1199 class HorizontalRule:
1200 def __init__(self):
1201 self.needone = 0
1202 def maybe(self):
1203 if self.needone:
1204 push('-' * 70)
1205 self.needone = 1
1206 hr = HorizontalRule()
1207
1208 def spill(msg, attrs, predicate):
1209 ok, attrs = _split_list(attrs, predicate)
1210 if ok:
1211 hr.maybe()
1212 push(msg)
1213 for name, kind, homecls, value in ok:
1214 try:
1215 value = getattr(object, name)
1216 except Exception:
1217 # Some descriptors may meet a failure in their __get__.
1218 # (bug #1785)
1219 push(self._docdescriptor(name, value, mod))
1220 else:
1221 push(self.document(value,
1222 name, mod, object))
1223 return attrs
1224
1225 def spilldescriptors(msg, attrs, predicate):
1226 ok, attrs = _split_list(attrs, predicate)
1227 if ok:
1228 hr.maybe()
1229 push(msg)
1230 for name, kind, homecls, value in ok:
1231 push(self._docdescriptor(name, value, mod))
1232 return attrs
1233
1234 def spilldata(msg, attrs, predicate):
1235 ok, attrs = _split_list(attrs, predicate)
1236 if ok:
1237 hr.maybe()
1238 push(msg)
1239 for name, kind, homecls, value in ok:
1240 if (hasattr(value, '__call__') or
1241 inspect.isdatadescriptor(value)):
1242 doc = getdoc(value)
1243 else:
1244 doc = None
1245 push(self.docother(getattr(object, name),
1246 name, mod, maxlen=70, doc=doc) + '\n')
1247 return attrs
1248
1249 attrs = filter(lambda data: visiblename(data[0], obj=object),
1250 classify_class_attrs(object))
1251 while attrs:
1252 if mro:
1253 thisclass = mro.popleft()
1254 else:
1255 thisclass = attrs[0][2]
1256 attrs, inherited = _split_list(attrs, lambda t: t[2] is thisclass)
1257
1258 if thisclass is __builtin__.object:
1259 attrs = inherited
1260 continue
1261 elif thisclass is object:
1262 tag = "defined here"
1263 else:
1264 tag = "inherited from %s" % classname(thisclass,
1265 object.__module__)
1266
1267 # Sort attrs by name.
1268 attrs.sort()
1269
1270 # Pump out the attrs, segregated by kind.
1271 attrs = spill("Methods %s:\n" % tag, attrs,
1272 lambda t: t[1] == 'method')
1273 attrs = spill("Class methods %s:\n" % tag, attrs,
1274 lambda t: t[1] == 'class method')
1275 attrs = spill("Static methods %s:\n" % tag, attrs,
1276 lambda t: t[1] == 'static method')
1277 attrs = spilldescriptors("Data descriptors %s:\n" % tag, attrs,
1278 lambda t: t[1] == 'data descriptor')
1279 attrs = spilldata("Data and other attributes %s:\n" % tag, attrs,
1280 lambda t: t[1] == 'data')
1281 assert attrs == []
1282 attrs = inherited
1283
1284 contents = '\n'.join(contents)
1285 if not contents:
1286 return title + '\n'
1287 return title + '\n' + self.indent(rstrip(contents), ' | ') + '\n'
1288
1289 def formatvalue(self, object):
1290 """Format an argument default value as text."""
1291 return '=' + self.repr(object)
1292
1293 def docroutine(self, object, name=None, mod=None, cl=None):
1294 """Produce text documentation for a function or method object."""
1295 realname = object.__name__
1296 name = name or realname
1297 note = ''
1298 skipdocs = 0
1299 if inspect.ismethod(object):
1300 imclass = object.im_class
1301 if cl:
1302 if imclass is not cl:
1303 note = ' from ' + classname(imclass, mod)
1304 else:
1305 if object.im_self is not None:
1306 note = ' method of %s instance' % classname(
1307 object.im_self.__class__, mod)
1308 else:
1309 note = ' unbound %s method' % classname(imclass,mod)
1310 object = object.im_func
1311
1312 if name == realname:
1313 title = self.bold(realname)
1314 else:
1315 if (cl and realname in cl.__dict__ and
1316 cl.__dict__[realname] is object):
1317 skipdocs = 1
1318 title = self.bold(name) + ' = ' + realname
1319 if inspect.isfunction(object):
1320 args, varargs, varkw, defaults = inspect.getargspec(object)
1321 argspec = inspect.formatargspec(
1322 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
1323 if realname == '<lambda>':
1324 title = self.bold(name) + ' lambda '
1325 argspec = argspec[1:-1] # remove parentheses
1326 else:
1327 argspec = '(...)'
1328 decl = title + argspec + note
1329
1330 if skipdocs:
1331 return decl + '\n'
1332 else:
1333 doc = getdoc(object) or ''
1334 return decl + '\n' + (doc and rstrip(self.indent(doc)) + '\n')
1335
1336 def _docdescriptor(self, name, value, mod):
1337 results = []
1338 push = results.append
1339
1340 if name:
1341 push(self.bold(name))
1342 push('\n')
1343 doc = getdoc(value) or ''
1344 if doc:
1345 push(self.indent(doc))
1346 push('\n')
1347 return ''.join(results)
1348
1349 def docproperty(self, object, name=None, mod=None, cl=None):
1350 """Produce text documentation for a property."""
1351 return self._docdescriptor(name, object, mod)
1352
1353 def docdata(self, object, name=None, mod=None, cl=None):
1354 """Produce text documentation for a data descriptor."""
1355 return self._docdescriptor(name, object, mod)
1356
1357 def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
1358 """Produce text documentation for a data object."""
1359 repr = self.repr(object)
1360 if maxlen:
1361 line = (name and name + ' = ' or '') + repr
1362 chop = maxlen - len(line)
1363 if chop < 0: repr = repr[:chop] + '...'
1364 line = (name and self.bold(name) + ' = ' or '') + repr
1365 if doc is not None:
1366 line += '\n' + self.indent(str(doc))
1367 return line
1368
1369 # --------------------------------------------------------- user interfaces
1370
1371 def pager(text):
1372 """The first time this is called, determine what kind of pager to use."""
1373 global pager
1374 pager = getpager()
1375 pager(text)
1376
1377 def getpager():
1378 """Decide what method to use for paging through text."""
1379 if type(sys.stdout) is not types.FileType:
1380 return plainpager
1381 if not hasattr(sys.stdin, "isatty"):
1382 return plainpager
1383 if not sys.stdin.isatty() or not sys.stdout.isatty():
1384 return plainpager
1385 if 'PAGER' in os.environ:
1386 if sys.platform == 'win32': # pipes completely broken in Windows
1387 return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
1388 elif os.environ.get('TERM') in ('dumb', 'emacs'):
1389 return lambda text: pipepager(plain(text), os.environ['PAGER'])
1390 else:
1391 return lambda text: pipepager(text, os.environ['PAGER'])
1392 if os.environ.get('TERM') in ('dumb', 'emacs'):
1393 return plainpager
1394 if sys.platform == 'win32' or sys.platform.startswith('os2'):
1395 return lambda text: tempfilepager(plain(text), 'more <')
1396 if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
1397 return lambda text: pipepager(text, 'less')
1398
1399 import tempfile
1400 (fd, filename) = tempfile.mkstemp()
1401 os.close(fd)
1402 try:
1403 if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
1404 return lambda text: pipepager(text, 'more')
1405 else:
1406 return ttypager
1407 finally:
1408 os.unlink(filename)
1409
1410 def plain(text):
1411 """Remove boldface formatting from text."""
1412 return re.sub('.\b', '', text)
1413
1414 def pipepager(text, cmd):
1415 """Page through text by feeding it to another program."""
1416 pipe = os.popen(cmd, 'w')
1417 try:
1418 pipe.write(_encode(text))
1419 pipe.close()
1420 except IOError:
1421 pass # Ignore broken pipes caused by quitting the pager program.
1422
1423 def tempfilepager(text, cmd):
1424 """Page through text by invoking a program on a temporary file."""
1425 import tempfile
1426 filename = tempfile.mktemp()
1427 file = open(filename, 'w')
1428 file.write(_encode(text))
1429 file.close()
1430 try:
1431 os.system(cmd + ' "' + filename + '"')
1432 finally:
1433 os.unlink(filename)
1434
1435 def ttypager(text):
1436 """Page through text on a text terminal."""
1437 lines = plain(_encode(plain(text), getattr(sys.stdout, 'encoding', _encoding))).split('\n')
1438 try:
1439 import tty
1440 fd = sys.stdin.fileno()
1441 old = tty.tcgetattr(fd)
1442 tty.setcbreak(fd)
1443 getchar = lambda: sys.stdin.read(1)
1444 except (ImportError, AttributeError):
1445 tty = None
1446 getchar = lambda: sys.stdin.readline()[:-1][:1]
1447
1448 try:
1449 try:
1450 h = int(os.environ.get('LINES', 0))
1451 except ValueError:
1452 h = 0
1453 if h <= 1:
1454 h = 25
1455 r = inc = h - 1
1456 sys.stdout.write(join(lines[:inc], '\n') + '\n')
1457 while lines[r:]:
1458 sys.stdout.write('-- more --')
1459 sys.stdout.flush()
1460 c = getchar()
1461
1462 if c in ('q', 'Q'):
1463 sys.stdout.write('\r \r')
1464 break
1465 elif c in ('\r', '\n'):
1466 sys.stdout.write('\r \r' + lines[r] + '\n')
1467 r = r + 1
1468 continue
1469 if c in ('b', 'B', '\x1b'):
1470 r = r - inc - inc
1471 if r < 0: r = 0
1472 sys.stdout.write('\n' + join(lines[r:r+inc], '\n') + '\n')
1473 r = r + inc
1474
1475 finally:
1476 if tty:
1477 tty.tcsetattr(fd, tty.TCSAFLUSH, old)
1478
1479 def plainpager(text):
1480 """Simply print unformatted text. This is the ultimate fallback."""
1481 sys.stdout.write(_encode(plain(text), getattr(sys.stdout, 'encoding', _encoding)))
1482
1483 def describe(thing):
1484 """Produce a short description of the given thing."""
1485 if inspect.ismodule(thing):
1486 if thing.__name__ in sys.builtin_module_names:
1487 return 'built-in module ' + thing.__name__
1488 if hasattr(thing, '__path__'):
1489 return 'package ' + thing.__name__
1490 else:
1491 return 'module ' + thing.__name__
1492 if inspect.isbuiltin(thing):
1493 return 'built-in function ' + thing.__name__
1494 if inspect.isgetsetdescriptor(thing):
1495 return 'getset descriptor %s.%s.%s' % (
1496 thing.__objclass__.__module__, thing.__objclass__.__name__,
1497 thing.__name__)
1498 if inspect.ismemberdescriptor(thing):
1499 return 'member descriptor %s.%s.%s' % (
1500 thing.__objclass__.__module__, thing.__objclass__.__name__,
1501 thing.__name__)
1502 if inspect.isclass(thing):
1503 return 'class ' + thing.__name__
1504 if inspect.isfunction(thing):
1505 return 'function ' + thing.__name__
1506 if inspect.ismethod(thing):
1507 return 'method ' + thing.__name__
1508 if type(thing) is types.InstanceType:
1509 return 'instance of ' + thing.__class__.__name__
1510 return type(thing).__name__
1511
1512 def locate(path, forceload=0):
1513 """Locate an object by name or dotted path, importing as necessary."""
1514 parts = [part for part in split(path, '.') if part]
1515 module, n = None, 0
1516 while n < len(parts):
1517 nextmodule = safeimport(join(parts[:n+1], '.'), forceload)
1518 if nextmodule: module, n = nextmodule, n + 1
1519 else: break
1520 if module:
1521 object = module
1522 else:
1523 object = __builtin__
1524 for part in parts[n:]:
1525 try:
1526 object = getattr(object, part)
1527 except AttributeError:
1528 return None
1529 return object
1530
1531 # --------------------------------------- interactive interpreter interface
1532
1533 text = TextDoc()
1534 html = HTMLDoc()
1535
1536 class _OldStyleClass: pass
1537 _OLD_INSTANCE_TYPE = type(_OldStyleClass())
1538
1539 def resolve(thing, forceload=0):
1540 """Given an object or a path to an object, get the object and its name."""
1541 if isinstance(thing, str):
1542 object = locate(thing, forceload)
1543 if object is None:
1544 raise ImportError, 'no Python documentation found for %r' % thing
1545 return object, thing
1546 else:
1547 name = getattr(thing, '__name__', None)
1548 return thing, name if isinstance(name, str) else None
1549
1550 def render_doc(thing, title='Python Library Documentation: %s', forceload=0):
1551 """Render text documentation, given an object or a path to an object."""
1552 object, name = resolve(thing, forceload)
1553 desc = describe(object)
1554 module = inspect.getmodule(object)
1555 if name and '.' in name:
1556 desc += ' in ' + name[:name.rfind('.')]
1557 elif module and module is not object:
1558 desc += ' in module ' + module.__name__
1559 if type(object) is _OLD_INSTANCE_TYPE:
1560 # If the passed object is an instance of an old-style class,
1561 # document its available methods instead of its value.
1562 object = object.__class__
1563 elif not (inspect.ismodule(object) or
1564 inspect.isclass(object) or
1565 inspect.isroutine(object) or
1566 inspect.isgetsetdescriptor(object) or
1567 inspect.ismemberdescriptor(object) or
1568 isinstance(object, property)):
1569 # If the passed object is a piece of data or an instance,
1570 # document its available methods instead of its value.
1571 object = type(object)
1572 desc += ' object'
1573 return title % desc + '\n\n' + text.document(object, name)
1574
1575 def doc(thing, title='Python Library Documentation: %s', forceload=0):
1576 """Display text documentation, given an object or a path to an object."""
1577 try:
1578 pager(render_doc(thing, title, forceload))
1579 except (ImportError, ErrorDuringImport), value:
1580 print value
1581
1582 def writedoc(thing, forceload=0):
1583 """Write HTML documentation to a file in the current directory."""
1584 try:
1585 object, name = resolve(thing, forceload)
1586 page = html.page(describe(object), html.document(object, name))
1587 file = open(name + '.html', 'w')
1588 file.write(page)
1589 file.close()
1590 print 'wrote', name + '.html'
1591 except (ImportError, ErrorDuringImport), value:
1592 print value
1593
1594 def writedocs(dir, pkgpath='', done=None):
1595 """Write out HTML documentation for all modules in a directory tree."""
1596 if done is None: done = {}
1597 for importer, modname, ispkg in pkgutil.walk_packages([dir], pkgpath):
1598 writedoc(modname)
1599 return
1600
1601 class Helper:
1602
1603 # These dictionaries map a topic name to either an alias, or a tuple
1604 # (label, seealso-items). The "label" is the label of the corresponding
1605 # section in the .rst file under Doc/ and an index into the dictionary
1606 # in pydoc_data/topics.py.
1607 #
1608 # CAUTION: if you change one of these dictionaries, be sure to adapt the
1609 # list of needed labels in Doc/tools/pyspecific.py and
1610 # regenerate the pydoc_data/topics.py file by running
1611 # make pydoc-topics
1612 # in Doc/ and copying the output file into the Lib/ directory.
1613
1614 keywords = {
1615 'and': 'BOOLEAN',
1616 'as': 'with',
1617 'assert': ('assert', ''),
1618 'break': ('break', 'while for'),
1619 'class': ('class', 'CLASSES SPECIALMETHODS'),
1620 'continue': ('continue', 'while for'),
1621 'def': ('function', ''),
1622 'del': ('del', 'BASICMETHODS'),
1623 'elif': 'if',
1624 'else': ('else', 'while for'),
1625 'except': 'try',
1626 'exec': ('exec', ''),
1627 'finally': 'try',
1628 'for': ('for', 'break continue while'),
1629 'from': 'import',
1630 'global': ('global', 'NAMESPACES'),
1631 'if': ('if', 'TRUTHVALUE'),
1632 'import': ('import', 'MODULES'),
1633 'in': ('in', 'SEQUENCEMETHODS2'),
1634 'is': 'COMPARISON',
1635 'lambda': ('lambda', 'FUNCTIONS'),
1636 'not': 'BOOLEAN',
1637 'or': 'BOOLEAN',
1638 'pass': ('pass', ''),
1639 'print': ('print', ''),
1640 'raise': ('raise', 'EXCEPTIONS'),
1641 'return': ('return', 'FUNCTIONS'),
1642 'try': ('try', 'EXCEPTIONS'),
1643 'while': ('while', 'break continue if TRUTHVALUE'),
1644 'with': ('with', 'CONTEXTMANAGERS EXCEPTIONS yield'),
1645 'yield': ('yield', ''),
1646 }
1647 # Either add symbols to this dictionary or to the symbols dictionary
1648 # directly: Whichever is easier. They are merged later.
1649 _symbols_inverse = {
1650 'STRINGS' : ("'", "'''", "r'", "u'", '"""', '"', 'r"', 'u"'),
1651 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&',
1652 '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'),
1653 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'),
1654 'UNARY' : ('-', '~'),
1655 'AUGMENTEDASSIGNMENT' : ('+=', '-=', '*=', '/=', '%=', '&=', '|=',
1656 '^=', '<<=', '>>=', '**=', '//='),
1657 'BITWISE' : ('<<', '>>', '&', '|', '^', '~'),
1658 'COMPLEX' : ('j', 'J')
1659 }
1660 symbols = {
1661 '%': 'OPERATORS FORMATTING',
1662 '**': 'POWER',
1663 ',': 'TUPLES LISTS FUNCTIONS',
1664 '.': 'ATTRIBUTES FLOAT MODULES OBJECTS',
1665 '...': 'ELLIPSIS',
1666 ':': 'SLICINGS DICTIONARYLITERALS',
1667 '@': 'def class',
1668 '\\': 'STRINGS',
1669 '_': 'PRIVATENAMES',
1670 '__': 'PRIVATENAMES SPECIALMETHODS',
1671 '`': 'BACKQUOTES',
1672 '(': 'TUPLES FUNCTIONS CALLS',
1673 ')': 'TUPLES FUNCTIONS CALLS',
1674 '[': 'LISTS SUBSCRIPTS SLICINGS',
1675 ']': 'LISTS SUBSCRIPTS SLICINGS'
1676 }
1677 for topic, symbols_ in _symbols_inverse.iteritems():
1678 for symbol in symbols_:
1679 topics = symbols.get(symbol, topic)
1680 if topic not in topics:
1681 topics = topics + ' ' + topic
1682 symbols[symbol] = topics
1683
1684 topics = {
1685 'TYPES': ('types', 'STRINGS UNICODE NUMBERS SEQUENCES MAPPINGS '
1686 'FUNCTIONS CLASSES MODULES FILES inspect'),
1687 'STRINGS': ('strings', 'str UNICODE SEQUENCES STRINGMETHODS FORMATTING '
1688 'TYPES'),
1689 'STRINGMETHODS': ('string-methods', 'STRINGS FORMATTING'),
1690 'FORMATTING': ('formatstrings', 'OPERATORS'),
1691 'UNICODE': ('strings', 'encodings unicode SEQUENCES STRINGMETHODS '
1692 'FORMATTING TYPES'),
1693 'NUMBERS': ('numbers', 'INTEGER FLOAT COMPLEX TYPES'),
1694 'INTEGER': ('integers', 'int range'),
1695 'FLOAT': ('floating', 'float math'),
1696 'COMPLEX': ('imaginary', 'complex cmath'),
1697 'SEQUENCES': ('typesseq', 'STRINGMETHODS FORMATTING xrange LISTS'),
1698 'MAPPINGS': 'DICTIONARIES',
1699 'FUNCTIONS': ('typesfunctions', 'def TYPES'),
1700 'METHODS': ('typesmethods', 'class def CLASSES TYPES'),
1701 'CODEOBJECTS': ('bltin-code-objects', 'compile FUNCTIONS TYPES'),
1702 'TYPEOBJECTS': ('bltin-type-objects', 'types TYPES'),
1703 'FRAMEOBJECTS': 'TYPES',
1704 'TRACEBACKS': 'TYPES',
1705 'NONE': ('bltin-null-object', ''),
1706 'ELLIPSIS': ('bltin-ellipsis-object', 'SLICINGS'),
1707 'FILES': ('bltin-file-objects', ''),
1708 'SPECIALATTRIBUTES': ('specialattrs', ''),
1709 'CLASSES': ('types', 'class SPECIALMETHODS PRIVATENAMES'),
1710 'MODULES': ('typesmodules', 'import'),
1711 'PACKAGES': 'import',
1712 'EXPRESSIONS': ('operator-summary', 'lambda or and not in is BOOLEAN '
1713 'COMPARISON BITWISE SHIFTING BINARY FORMATTING POWER '
1714 'UNARY ATTRIBUTES SUBSCRIPTS SLICINGS CALLS TUPLES '
1715 'LISTS DICTIONARIES BACKQUOTES'),
1716 'OPERATORS': 'EXPRESSIONS',
1717 'PRECEDENCE': 'EXPRESSIONS',
1718 'OBJECTS': ('objects', 'TYPES'),
1719 'SPECIALMETHODS': ('specialnames', 'BASICMETHODS ATTRIBUTEMETHODS '
1720 'CALLABLEMETHODS SEQUENCEMETHODS1 MAPPINGMETHODS '
1721 'SEQUENCEMETHODS2 NUMBERMETHODS CLASSES'),
1722 'BASICMETHODS': ('customization', 'cmp hash repr str SPECIALMETHODS'),
1723 'ATTRIBUTEMETHODS': ('attribute-access', 'ATTRIBUTES SPECIALMETHODS'),
1724 'CALLABLEMETHODS': ('callable-types', 'CALLS SPECIALMETHODS'),
1725 'SEQUENCEMETHODS1': ('sequence-types', 'SEQUENCES SEQUENCEMETHODS2 '
1726 'SPECIALMETHODS'),
1727 'SEQUENCEMETHODS2': ('sequence-methods', 'SEQUENCES SEQUENCEMETHODS1 '
1728 'SPECIALMETHODS'),
1729 'MAPPINGMETHODS': ('sequence-types', 'MAPPINGS SPECIALMETHODS'),
1730 'NUMBERMETHODS': ('numeric-types', 'NUMBERS AUGMENTEDASSIGNMENT '
1731 'SPECIALMETHODS'),
1732 'EXECUTION': ('execmodel', 'NAMESPACES DYNAMICFEATURES EXCEPTIONS'),
1733 'NAMESPACES': ('naming', 'global ASSIGNMENT DELETION DYNAMICFEATURES'),
1734 'DYNAMICFEATURES': ('dynamic-features', ''),
1735 'SCOPING': 'NAMESPACES',
1736 'FRAMES': 'NAMESPACES',
1737 'EXCEPTIONS': ('exceptions', 'try except finally raise'),
1738 'COERCIONS': ('coercion-rules','CONVERSIONS'),
1739 'CONVERSIONS': ('conversions', 'COERCIONS'),
1740 'IDENTIFIERS': ('identifiers', 'keywords SPECIALIDENTIFIERS'),
1741 'SPECIALIDENTIFIERS': ('id-classes', ''),
1742 'PRIVATENAMES': ('atom-identifiers', ''),
1743 'LITERALS': ('atom-literals', 'STRINGS BACKQUOTES NUMBERS '
1744 'TUPLELITERALS LISTLITERALS DICTIONARYLITERALS'),
1745 'TUPLES': 'SEQUENCES',
1746 'TUPLELITERALS': ('exprlists', 'TUPLES LITERALS'),
1747 'LISTS': ('typesseq-mutable', 'LISTLITERALS'),
1748 'LISTLITERALS': ('lists', 'LISTS LITERALS'),
1749 'DICTIONARIES': ('typesmapping', 'DICTIONARYLITERALS'),
1750 'DICTIONARYLITERALS': ('dict', 'DICTIONARIES LITERALS'),
1751 'BACKQUOTES': ('string-conversions', 'repr str STRINGS LITERALS'),
1752 'ATTRIBUTES': ('attribute-references', 'getattr hasattr setattr '
1753 'ATTRIBUTEMETHODS'),
1754 'SUBSCRIPTS': ('subscriptions', 'SEQUENCEMETHODS1'),
1755 'SLICINGS': ('slicings', 'SEQUENCEMETHODS2'),
1756 'CALLS': ('calls', 'EXPRESSIONS'),
1757 'POWER': ('power', 'EXPRESSIONS'),
1758 'UNARY': ('unary', 'EXPRESSIONS'),
1759 'BINARY': ('binary', 'EXPRESSIONS'),
1760 'SHIFTING': ('shifting', 'EXPRESSIONS'),
1761 'BITWISE': ('bitwise', 'EXPRESSIONS'),
1762 'COMPARISON': ('comparisons', 'EXPRESSIONS BASICMETHODS'),
1763 'BOOLEAN': ('booleans', 'EXPRESSIONS TRUTHVALUE'),
1764 'ASSERTION': 'assert',
1765 'ASSIGNMENT': ('assignment', 'AUGMENTEDASSIGNMENT'),
1766 'AUGMENTEDASSIGNMENT': ('augassign', 'NUMBERMETHODS'),
1767 'DELETION': 'del',
1768 'PRINTING': 'print',
1769 'RETURNING': 'return',
1770 'IMPORTING': 'import',
1771 'CONDITIONAL': 'if',
1772 'LOOPING': ('compound', 'for while break continue'),
1773 'TRUTHVALUE': ('truth', 'if while and or not BASICMETHODS'),
1774 'DEBUGGING': ('debugger', 'pdb'),
1775 'CONTEXTMANAGERS': ('context-managers', 'with'),
1776 }
1777
1778 def __init__(self, input=None, output=None):
1779 self._input = input
1780 self._output = output
1781
1782 input = property(lambda self: self._input or sys.stdin)
1783 output = property(lambda self: self._output or sys.stdout)
1784
1785 def __repr__(self):
1786 if inspect.stack()[1][3] == '?':
1787 self()
1788 return ''
1789 return '<pydoc.Helper instance>'
1790
1791 _GoInteractive = object()
1792 def __call__(self, request=_GoInteractive):
1793 if request is not self._GoInteractive:
1794 self.help(request)
1795 else:
1796 self.intro()
1797 self.interact()
1798 self.output.write('''
1799 You are now leaving help and returning to the Python interpreter.
1800 If you want to ask for help on a particular object directly from the
1801 interpreter, you can type "help(object)". Executing "help('string')"
1802 has the same effect as typing a particular string at the help> prompt.
1803 ''')
1804
1805 def interact(self):
1806 self.output.write('\n')
1807 while True:
1808 try:
1809 request = self.getline('help> ')
1810 if not request: break
1811 except (KeyboardInterrupt, EOFError):
1812 break
1813 request = strip(replace(request, '"', '', "'", ''))
1814 if lower(request) in ('q', 'quit'): break
1815 self.help(request)
1816
1817 def getline(self, prompt):
1818 """Read one line, using raw_input when available."""
1819 if self.input is sys.stdin:
1820 return raw_input(prompt)
1821 else:
1822 self.output.write(prompt)
1823 self.output.flush()
1824 return self.input.readline()
1825
1826 def help(self, request):
1827 if type(request) is type(''):
1828 request = request.strip()
1829 if request == 'help': self.intro()
1830 elif request == 'keywords': self.listkeywords()
1831 elif request == 'symbols': self.listsymbols()
1832 elif request == 'topics': self.listtopics()
1833 elif request == 'modules': self.listmodules()
1834 elif request[:8] == 'modules ':
1835 self.listmodules(split(request)[1])
1836 elif request in self.symbols: self.showsymbol(request)
1837 elif request in self.keywords: self.showtopic(request)
1838 elif request in self.topics: self.showtopic(request)
1839 elif request: doc(request, 'Help on %s:')
1840 elif isinstance(request, Helper): self()
1841 else: doc(request, 'Help on %s:')
1842 self.output.write('\n')
1843
1844 def intro(self):
1845 self.output.write('''
1846 Welcome to Python %s! This is the online help utility.
1847
1848 If this is your first time using Python, you should definitely check out
1849 the tutorial on the Internet at http://docs.python.org/%s/tutorial/.
1850
1851 Enter the name of any module, keyword, or topic to get help on writing
1852 Python programs and using Python modules. To quit this help utility and
1853 return to the interpreter, just type "quit".
1854
1855 To get a list of available modules, keywords, or topics, type "modules",
1856 "keywords", or "topics". Each module also comes with a one-line summary
1857 of what it does; to list the modules whose summaries contain a given word
1858 such as "spam", type "modules spam".
1859 ''' % tuple([sys.version[:3]]*2))
1860
1861 def list(self, items, columns=4, width=80):
1862 items = items[:]
1863 items.sort()
1864 colw = width / columns
1865 rows = (len(items) + columns - 1) / columns
1866 for row in range(rows):
1867 for col in range(columns):
1868 i = col * rows + row
1869 if i < len(items):
1870 self.output.write(items[i])
1871 if col < columns - 1:
1872 self.output.write(' ' + ' ' * (colw-1 - len(items[i])))
1873 self.output.write('\n')
1874
1875 def listkeywords(self):
1876 self.output.write('''
1877 Here is a list of the Python keywords. Enter any keyword to get more help.
1878
1879 ''')
1880 self.list(self.keywords.keys())
1881
1882 def listsymbols(self):
1883 self.output.write('''
1884 Here is a list of the punctuation symbols which Python assigns special meaning
1885 to. Enter any symbol to get more help.
1886
1887 ''')
1888 self.list(self.symbols.keys())
1889
1890 def listtopics(self):
1891 self.output.write('''
1892 Here is a list of available topics. Enter any topic name to get more help.
1893
1894 ''')
1895 self.list(self.topics.keys())
1896
1897 def showtopic(self, topic, more_xrefs=''):
1898 try:
1899 import pydoc_data.topics
1900 except ImportError:
1901 self.output.write('''
1902 Sorry, topic and keyword documentation is not available because the
1903 module "pydoc_data.topics" could not be found.
1904 ''')
1905 return
1906 target = self.topics.get(topic, self.keywords.get(topic))
1907 if not target:
1908 self.output.write('no documentation found for %s\n' % repr(topic))
1909 return
1910 if type(target) is type(''):
1911 return self.showtopic(target, more_xrefs)
1912
1913 label, xrefs = target
1914 try:
1915 doc = pydoc_data.topics.topics[label]
1916 except KeyError:
1917 self.output.write('no documentation found for %s\n' % repr(topic))
1918 return
1919 pager(strip(doc) + '\n')
1920 if more_xrefs:
1921 xrefs = (xrefs or '') + ' ' + more_xrefs
1922 if xrefs:
1923 import StringIO, formatter
1924 buffer = StringIO.StringIO()
1925 formatter.DumbWriter(buffer).send_flowing_data(
1926 'Related help topics: ' + join(split(xrefs), ', ') + '\n')
1927 self.output.write('\n%s\n' % buffer.getvalue())
1928
1929 def showsymbol(self, symbol):
1930 target = self.symbols[symbol]
1931 topic, _, xrefs = target.partition(' ')
1932 self.showtopic(topic, xrefs)
1933
1934 def listmodules(self, key=''):
1935 if key:
1936 self.output.write('''
1937 Here is a list of matching modules. Enter any module name to get more help.
1938
1939 ''')
1940 apropos(key)
1941 else:
1942 self.output.write('''
1943 Please wait a moment while I gather a list of all available modules...
1944
1945 ''')
1946 modules = {}
1947 def callback(path, modname, desc, modules=modules):
1948 if modname and modname[-9:] == '.__init__':
1949 modname = modname[:-9] + ' (package)'
1950 if find(modname, '.') < 0:
1951 modules[modname] = 1
1952 def onerror(modname):
1953 callback(None, modname, None)
1954 ModuleScanner().run(callback, onerror=onerror)
1955 self.list(modules.keys())
1956 self.output.write('''
1957 Enter any module name to get more help. Or, type "modules spam" to search
1958 for modules whose descriptions contain the word "spam".
1959 ''')
1960
1961 help = Helper()
1962
1963 class Scanner:
1964 """A generic tree iterator."""
1965 def __init__(self, roots, children, descendp):
1966 self.roots = roots[:]
1967 self.state = []
1968 self.children = children
1969 self.descendp = descendp
1970
1971 def next(self):
1972 if not self.state:
1973 if not self.roots:
1974 return None
1975 root = self.roots.pop(0)
1976 self.state = [(root, self.children(root))]
1977 node, children = self.state[-1]
1978 if not children:
1979 self.state.pop()
1980 return self.next()
1981 child = children.pop(0)
1982 if self.descendp(child):
1983 self.state.append((child, self.children(child)))
1984 return child
1985
1986
1987 class ModuleScanner:
1988 """An interruptible scanner that searches module synopses."""
1989
1990 def run(self, callback, key=None, completer=None, onerror=None):
1991 if key: key = lower(key)
1992 self.quit = False
1993 seen = {}
1994
1995 for modname in sys.builtin_module_names:
1996 if modname != '__main__':
1997 seen[modname] = 1
1998 if key is None:
1999 callback(None, modname, '')
2000 else:
2001 desc = split(__import__(modname).__doc__ or '', '\n')[0]
2002 if find(lower(modname + ' - ' + desc), key) >= 0:
2003 callback(None, modname, desc)
2004
2005 for importer, modname, ispkg in pkgutil.walk_packages(onerror=onerror):
2006 if self.quit:
2007 break
2008 if key is None:
2009 callback(None, modname, '')
2010 else:
2011 loader = importer.find_module(modname)
2012 if hasattr(loader,'get_source'):
2013 import StringIO
2014 desc = source_synopsis(
2015 StringIO.StringIO(loader.get_source(modname))
2016 ) or ''
2017 if hasattr(loader,'get_filename'):
2018 path = loader.get_filename(modname)
2019 else:
2020 path = None
2021 else:
2022 module = loader.load_module(modname)
2023 desc = module.__doc__.splitlines()[0] if module.__doc__ else ''
2024 path = getattr(module,'__file__',None)
2025 if find(lower(modname + ' - ' + desc), key) >= 0:
2026 callback(path, modname, desc)
2027
2028 if completer:
2029 completer()
2030
2031 def apropos(key):
2032 """Print all the one-line module summaries that contain a substring."""
2033 def callback(path, modname, desc):
2034 if modname[-9:] == '.__init__':
2035 modname = modname[:-9] + ' (package)'
2036 print modname, desc and '- ' + desc
2037 def onerror(modname):
2038 pass
2039 with warnings.catch_warnings():
2040 warnings.filterwarnings('ignore') # ignore problems during import
2041 ModuleScanner().run(callback, key, onerror=onerror)
2042
2043 # --------------------------------------------------- web browser interface
2044
2045 def serve(port, callback=None, completer=None):
2046 import BaseHTTPServer, mimetools, select
2047
2048 # Patch up mimetools.Message so it doesn't break if rfc822 is reloaded.
2049 class Message(mimetools.Message):
2050 def __init__(self, fp, seekable=1):
2051 Message = self.__class__
2052 Message.__bases__[0].__bases__[0].__init__(self, fp, seekable)
2053 self.encodingheader = self.getheader('content-transfer-encoding')
2054 self.typeheader = self.getheader('content-type')
2055 self.parsetype()
2056 self.parseplist()
2057
2058 class DocHandler(BaseHTTPServer.BaseHTTPRequestHandler):
2059 def send_document(self, title, contents):
2060 try:
2061 self.send_response(200)
2062 self.send_header('Content-Type', 'text/html')
2063 self.end_headers()
2064 self.wfile.write(html.page(title, contents))
2065 except IOError: pass
2066
2067 def do_GET(self):
2068 path = self.path
2069 if path[-5:] == '.html': path = path[:-5]
2070 if path[:1] == '/': path = path[1:]
2071 if path and path != '.':
2072 try:
2073 obj = locate(path, forceload=1)
2074 except ErrorDuringImport, value:
2075 self.send_document(path, html.escape(str(value)))
2076 return
2077 if obj:
2078 self.send_document(describe(obj), html.document(obj, path))
2079 else:
2080 self.send_document(path,
2081 'no Python documentation found for %s' % repr(path))
2082 else:
2083 heading = html.heading(
2084 '<big><big><strong>Python: Index of Modules</strong></big></big>',
2085 '#ffffff', '#7799ee')
2086 def bltinlink(name):
2087 return '<a href="%s.html">%s</a>' % (name, name)
2088 names = filter(lambda x: x != '__main__',
2089 sys.builtin_module_names)
2090 contents = html.multicolumn(names, bltinlink)
2091 indices = ['<p>' + html.bigsection(
2092 'Built-in Modules', '#ffffff', '#ee77aa', contents)]
2093
2094 seen = {}
2095 for dir in sys.path:
2096 indices.append(html.index(dir, seen))
2097 contents = heading + join(indices) + '''<p align=right>
2098 <font color="#909090" face="helvetica, arial"><strong>
2099 pydoc</strong> by Ka-Ping Yee &lt;ping@lfw.org&gt;</font>'''
2100 self.send_document('Index of Modules', contents)
2101
2102 def log_message(self, *args): pass
2103
2104 class DocServer(BaseHTTPServer.HTTPServer):
2105 def __init__(self, port, callback):
2106 host = 'localhost'
2107 self.address = (host, port)
2108 self.callback = callback
2109 self.base.__init__(self, self.address, self.handler)
2110
2111 def serve_until_quit(self):
2112 import select
2113 self.quit = False
2114 while not self.quit:
2115 rd, wr, ex = select.select([self.socket.fileno()], [], [], 1)
2116 if rd: self.handle_request()
2117
2118 def server_activate(self):
2119 self.base.server_activate(self)
2120 self.url = 'http://%s:%d/' % (self.address[0], self.server_port)
2121 if self.callback: self.callback(self)
2122
2123 DocServer.base = BaseHTTPServer.HTTPServer
2124 DocServer.handler = DocHandler
2125 DocHandler.MessageClass = Message
2126 try:
2127 try:
2128 DocServer(port, callback).serve_until_quit()
2129 except (KeyboardInterrupt, select.error):
2130 pass
2131 finally:
2132 if completer: completer()
2133
2134 # ----------------------------------------------------- graphical interface
2135
2136 def gui():
2137 """Graphical interface (starts web server and pops up a control window)."""
2138 class GUI:
2139 def __init__(self, window, port=7464):
2140 self.window = window
2141 self.server = None
2142 self.scanner = None
2143
2144 import Tkinter
2145 self.server_frm = Tkinter.Frame(window)
2146 self.title_lbl = Tkinter.Label(self.server_frm,
2147 text='Starting server...\n ')
2148 self.open_btn = Tkinter.Button(self.server_frm,
2149 text='open browser', command=self.open, state='disabled')
2150 self.quit_btn = Tkinter.Button(self.server_frm,
2151 text='quit serving', command=self.quit, state='disabled')
2152
2153 self.search_frm = Tkinter.Frame(window)
2154 self.search_lbl = Tkinter.Label(self.search_frm, text='Search for')
2155 self.search_ent = Tkinter.Entry(self.search_frm)
2156 self.search_ent.bind('<Return>', self.search)
2157 self.stop_btn = Tkinter.Button(self.search_frm,
2158 text='stop', pady=0, command=self.stop, state='disabled')
2159 if sys.platform == 'win32':
2160 # Trying to hide and show this button crashes under Windows.
2161 self.stop_btn.pack(side='right')
2162
2163 self.window.title('pydoc')
2164 self.window.protocol('WM_DELETE_WINDOW', self.quit)
2165 self.title_lbl.pack(side='top', fill='x')
2166 self.open_btn.pack(side='left', fill='x', expand=1)
2167 self.quit_btn.pack(side='right', fill='x', expand=1)
2168 self.server_frm.pack(side='top', fill='x')
2169
2170 self.search_lbl.pack(side='left')
2171 self.search_ent.pack(side='right', fill='x', expand=1)
2172 self.search_frm.pack(side='top', fill='x')
2173 self.search_ent.focus_set()
2174
2175 font = ('helvetica', sys.platform == 'win32' and 8 or 10)
2176 self.result_lst = Tkinter.Listbox(window, font=font, height=6)
2177 self.result_lst.bind('<Button-1>', self.select)
2178 self.result_lst.bind('<Double-Button-1>', self.goto)
2179 self.result_scr = Tkinter.Scrollbar(window,
2180 orient='vertical', command=self.result_lst.yview)
2181 self.result_lst.config(yscrollcommand=self.result_scr.set)
2182
2183 self.result_frm = Tkinter.Frame(window)
2184 self.goto_btn = Tkinter.Button(self.result_frm,
2185 text='go to selected', command=self.goto)
2186 self.hide_btn = Tkinter.Button(self.result_frm,
2187 text='hide results', command=self.hide)
2188 self.goto_btn.pack(side='left', fill='x', expand=1)
2189 self.hide_btn.pack(side='right', fill='x', expand=1)
2190
2191 self.window.update()
2192 self.minwidth = self.window.winfo_width()
2193 self.minheight = self.window.winfo_height()
2194 self.bigminheight = (self.server_frm.winfo_reqheight() +
2195 self.search_frm.winfo_reqheight() +
2196 self.result_lst.winfo_reqheight() +
2197 self.result_frm.winfo_reqheight())
2198 self.bigwidth, self.bigheight = self.minwidth, self.bigminheight
2199 self.expanded = 0
2200 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2201 self.window.wm_minsize(self.minwidth, self.minheight)
2202 self.window.tk.willdispatch()
2203
2204 import threading
2205 threading.Thread(
2206 target=serve, args=(port, self.ready, self.quit)).start()
2207
2208 def ready(self, server):
2209 self.server = server
2210 self.title_lbl.config(
2211 text='Python documentation server at\n' + server.url)
2212 self.open_btn.config(state='normal')
2213 self.quit_btn.config(state='normal')
2214
2215 def open(self, event=None, url=None):
2216 url = url or self.server.url
2217 try:
2218 import webbrowser
2219 webbrowser.open(url)
2220 except ImportError: # pre-webbrowser.py compatibility
2221 if sys.platform == 'win32':
2222 os.system('start "%s"' % url)
2223 else:
2224 rc = os.system('netscape -remote "openURL(%s)" &' % url)
2225 if rc: os.system('netscape "%s" &' % url)
2226
2227 def quit(self, event=None):
2228 if self.server:
2229 self.server.quit = 1
2230 self.window.quit()
2231
2232 def search(self, event=None):
2233 key = self.search_ent.get()
2234 self.stop_btn.pack(side='right')
2235 self.stop_btn.config(state='normal')
2236 self.search_lbl.config(text='Searching for "%s"...' % key)
2237 self.search_ent.forget()
2238 self.search_lbl.pack(side='left')
2239 self.result_lst.delete(0, 'end')
2240 self.goto_btn.config(state='disabled')
2241 self.expand()
2242
2243 import threading
2244 if self.scanner:
2245 self.scanner.quit = 1
2246 self.scanner = ModuleScanner()
2247 threading.Thread(target=self.scanner.run,
2248 args=(self.update, key, self.done)).start()
2249
2250 def update(self, path, modname, desc):
2251 if modname[-9:] == '.__init__':
2252 modname = modname[:-9] + ' (package)'
2253 self.result_lst.insert('end',
2254 modname + ' - ' + (desc or '(no description)'))
2255
2256 def stop(self, event=None):
2257 if self.scanner:
2258 self.scanner.quit = 1
2259 self.scanner = None
2260
2261 def done(self):
2262 self.scanner = None
2263 self.search_lbl.config(text='Search for')
2264 self.search_lbl.pack(side='left')
2265 self.search_ent.pack(side='right', fill='x', expand=1)
2266 if sys.platform != 'win32': self.stop_btn.forget()
2267 self.stop_btn.config(state='disabled')
2268
2269 def select(self, event=None):
2270 self.goto_btn.config(state='normal')
2271
2272 def goto(self, event=None):
2273 selection = self.result_lst.curselection()
2274 if selection:
2275 modname = split(self.result_lst.get(selection[0]))[0]
2276 self.open(url=self.server.url + modname + '.html')
2277
2278 def collapse(self):
2279 if not self.expanded: return
2280 self.result_frm.forget()
2281 self.result_scr.forget()
2282 self.result_lst.forget()
2283 self.bigwidth = self.window.winfo_width()
2284 self.bigheight = self.window.winfo_height()
2285 self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
2286 self.window.wm_minsize(self.minwidth, self.minheight)
2287 self.expanded = 0
2288
2289 def expand(self):
2290 if self.expanded: return
2291 self.result_frm.pack(side='bottom', fill='x')
2292 self.result_scr.pack(side='right', fill='y')
2293 self.result_lst.pack(side='top', fill='both', expand=1)
2294 self.window.wm_geometry('%dx%d' % (self.bigwidth, self.bigheight))
2295 self.window.wm_minsize(self.minwidth, self.bigminheight)
2296 self.expanded = 1
2297
2298 def hide(self, event=None):
2299 self.stop()
2300 self.collapse()
2301
2302 import Tkinter
2303 try:
2304 root = Tkinter.Tk()
2305 # Tk will crash if pythonw.exe has an XP .manifest
2306 # file and the root has is not destroyed explicitly.
2307 # If the problem is ever fixed in Tk, the explicit
2308 # destroy can go.
2309 try:
2310 gui = GUI(root)
2311 root.mainloop()
2312 finally:
2313 root.destroy()
2314 except KeyboardInterrupt:
2315 pass
2316
2317 # -------------------------------------------------- command-line interface
2318
2319 def ispath(x):
2320 return isinstance(x, str) and find(x, os.sep) >= 0
2321
2322 def cli():
2323 """Command-line interface (looks at sys.argv to decide what to do)."""
2324 import getopt
2325 class BadUsage: pass
2326
2327 # Scripts don't get the current directory in their path by default
2328 # unless they are run with the '-m' switch
2329 if '' not in sys.path:
2330 scriptdir = os.path.dirname(sys.argv[0])
2331 if scriptdir in sys.path:
2332 sys.path.remove(scriptdir)
2333 sys.path.insert(0, '.')
2334
2335 try:
2336 opts, args = getopt.getopt(sys.argv[1:], 'gk:p:w')
2337 writing = 0
2338
2339 for opt, val in opts:
2340 if opt == '-g':
2341 gui()
2342 return
2343 if opt == '-k':
2344 apropos(val)
2345 return
2346 if opt == '-p':
2347 try:
2348 port = int(val)
2349 except ValueError:
2350 raise BadUsage
2351 def ready(server):
2352 print 'pydoc server ready at %s' % server.url
2353 def stopped():
2354 print 'pydoc server stopped'
2355 serve(port, ready, stopped)
2356 return
2357 if opt == '-w':
2358 writing = 1
2359
2360 if not args: raise BadUsage
2361 for arg in args:
2362 if ispath(arg) and not os.path.exists(arg):
2363 print 'file %r does not exist' % arg
2364 break
2365 try:
2366 if ispath(arg) and os.path.isfile(arg):
2367 arg = importfile(arg)
2368 if writing:
2369 if ispath(arg) and os.path.isdir(arg):
2370 writedocs(arg)
2371 else:
2372 writedoc(arg)
2373 else:
2374 help.help(arg)
2375 except ErrorDuringImport, value:
2376 print value
2377
2378 except (getopt.error, BadUsage):
2379 cmd = os.path.basename(sys.argv[0])
2380 print """pydoc - the Python documentation tool
2381
2382 %s <name> ...
2383 Show text documentation on something. <name> may be the name of a
2384 Python keyword, topic, function, module, or package, or a dotted
2385 reference to a class or function within a module or module in a
2386 package. If <name> contains a '%s', it is used as the path to a
2387 Python source file to document. If name is 'keywords', 'topics',
2388 or 'modules', a listing of these things is displayed.
2389
2390 %s -k <keyword>
2391 Search for a keyword in the synopsis lines of all available modules.
2392
2393 %s -p <port>
2394 Start an HTTP server on the given port on the local machine. Port
2395 number 0 can be used to get an arbitrary unused port.
2396
2397 %s -g
2398 Pop up a graphical interface for finding and serving documentation.
2399
2400 %s -w <name> ...
2401 Write out the HTML documentation for a module to a file in the current
2402 directory. If <name> contains a '%s', it is treated as a filename; if
2403 it names a directory, documentation is written for all the contents.
2404 """ % (cmd, os.sep, cmd, cmd, cmd, cmd, os.sep)
2405
2406 if __name__ == '__main__': cli()