mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
Show inherited methods, with hyperlinks to the base class they came from.
Font adjustment to improve viewing in Windows (the default monospaced font, Courier New, seems to have no reasonable size in IE!) Improve error handling. Try very hard to distinguish between failure to find a module and failure during the module importing process. Improve reloading behaviour. (Still needs some work.) Add '.' to sys.path when running as a script at the command-line. Don't automatically assume '-g' based on the platform. We'll just have the batch file supply -g.
This commit is contained in:
parent
16a0b17460
commit
3bda87991a
1 changed files with 168 additions and 112 deletions
254
Lib/pydoc.py
254
Lib/pydoc.py
|
@ -41,7 +41,7 @@ Mynd you, m
|
||||||
|
|
||||||
import sys, imp, os, stat, re, types, inspect
|
import sys, imp, os, stat, re, types, inspect
|
||||||
from repr import Repr
|
from repr import Repr
|
||||||
from string import expandtabs, find, join, lower, split, strip, rstrip
|
from string import expandtabs, find, join, lower, split, strip, rfind, rstrip
|
||||||
|
|
||||||
# --------------------------------------------------------- common routines
|
# --------------------------------------------------------- common routines
|
||||||
|
|
||||||
|
@ -84,10 +84,7 @@ def pathdirs():
|
||||||
|
|
||||||
def getdoc(object):
|
def getdoc(object):
|
||||||
"""Get the doc string or comments for an object."""
|
"""Get the doc string or comments for an object."""
|
||||||
result = inspect.getdoc(object)
|
result = inspect.getdoc(object) or inspect.getcomments(object)
|
||||||
if not result:
|
|
||||||
try: result = inspect.getcomments(object)
|
|
||||||
except: pass
|
|
||||||
return result and re.sub('^ *\n', '', rstrip(result)) or ''
|
return result and re.sub('^ *\n', '', rstrip(result)) or ''
|
||||||
|
|
||||||
def classname(object, modname):
|
def classname(object, modname):
|
||||||
|
@ -137,19 +134,29 @@ def modulename(path):
|
||||||
if len(filename) > length and filename[-length:] == suffix:
|
if len(filename) > length and filename[-length:] == suffix:
|
||||||
return filename[:-length]
|
return filename[:-length]
|
||||||
|
|
||||||
class DocImportError(Exception):
|
def allmethods(cl):
|
||||||
"""Class for errors while trying to import something to document it."""
|
methods = {}
|
||||||
def __init__(self, filename, (type, value, tb)):
|
for key, value in inspect.getmembers(cl, inspect.ismethod):
|
||||||
|
methods[key] = 1
|
||||||
|
for base in cl.__bases__:
|
||||||
|
methods.update(allmethods(base)) # all your base are belong to us
|
||||||
|
for key in methods.keys():
|
||||||
|
methods[key] = getattr(cl, key)
|
||||||
|
return methods
|
||||||
|
|
||||||
|
class ErrorDuringImport(Exception):
|
||||||
|
"""Errors that occurred while trying to import something to document it."""
|
||||||
|
def __init__(self, filename, (exc, value, tb)):
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
self.type = type
|
self.exc = exc
|
||||||
self.value = value
|
self.value = value
|
||||||
self.tb = tb
|
self.tb = tb
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
t = self.type
|
exc = self.exc
|
||||||
if type(t) is types.ClassType:
|
if type(exc) is types.ClassType:
|
||||||
t = t.__name__
|
exc = exc.__name__
|
||||||
return 'problem in %s - %s: %s' % (self.filename, t, self.value)
|
return 'problem in %s - %s: %s' % (self.filename, exc, self.value)
|
||||||
|
|
||||||
def importfile(path):
|
def importfile(path):
|
||||||
"""Import a Python source file or compiled file given its path."""
|
"""Import a Python source file or compiled file given its path."""
|
||||||
|
@ -166,7 +173,7 @@ def importfile(path):
|
||||||
try:
|
try:
|
||||||
module = imp.load_module(name, file, path, (ext, 'r', kind))
|
module = imp.load_module(name, file, path, (ext, 'r', kind))
|
||||||
except:
|
except:
|
||||||
raise DocImportError(path, sys.exc_info())
|
raise ErrorDuringImport(path, sys.exc_info())
|
||||||
file.close()
|
file.close()
|
||||||
return module
|
return module
|
||||||
|
|
||||||
|
@ -250,7 +257,9 @@ class HTMLDoc(Doc):
|
||||||
"""Format an HTML page."""
|
"""Format an HTML page."""
|
||||||
return '''
|
return '''
|
||||||
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">
|
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||||
<html><title>Python: %s</title><body bgcolor="#f0f0f8">
|
<html><head><title>Python: %s</title>
|
||||||
|
<style>TT { font-family: lucida console, lucida typewriter, courier }</style>
|
||||||
|
</head><body bgcolor="#f0f0f8">
|
||||||
%s
|
%s
|
||||||
</body></html>''' % (title, contents)
|
</body></html>''' % (title, contents)
|
||||||
|
|
||||||
|
@ -279,11 +288,9 @@ class HTMLDoc(Doc):
|
||||||
if prelude:
|
if prelude:
|
||||||
result = result + '''
|
result = result + '''
|
||||||
<tr bgcolor="%s"><td>%s</td>
|
<tr bgcolor="%s"><td>%s</td>
|
||||||
<td colspan=2>%s</td></tr>
|
<td colspan=2>%s</td></tr>''' % (bgcol, marginalia, prelude)
|
||||||
''' % (bgcol, marginalia, prelude)
|
|
||||||
result = result + '''
|
result = result + '''
|
||||||
<tr><td bgcolor="%s">%s</td><td>%s</td>
|
<tr><td bgcolor="%s">%s</td><td>%s</td>''' % (bgcol, marginalia, gap)
|
||||||
''' % (bgcol, marginalia, gap)
|
|
||||||
|
|
||||||
return result + '<td width="100%%">%s</td></tr></table>' % contents
|
return result + '<td width="100%%">%s</td></tr></table>' % contents
|
||||||
|
|
||||||
|
@ -306,7 +313,7 @@ class HTMLDoc(Doc):
|
||||||
result = result + '<td width="%d%%" valign=top>' % (100/cols)
|
result = result + '<td width="%d%%" valign=top>' % (100/cols)
|
||||||
for i in range(rows*col, rows*col+rows):
|
for i in range(rows*col, rows*col+rows):
|
||||||
if i < len(list):
|
if i < len(list):
|
||||||
result = result + format(list[i]) + '<br>'
|
result = result + format(list[i]) + '<br>\n'
|
||||||
result = result + '</td>'
|
result = result + '</td>'
|
||||||
return '<table width="100%%"><tr>%s</tr></table>' % result
|
return '<table width="100%%"><tr>%s</tr></table>' % result
|
||||||
|
|
||||||
|
@ -354,8 +361,8 @@ class HTMLDoc(Doc):
|
||||||
escape = escape or self.escape
|
escape = escape or self.escape
|
||||||
results = []
|
results = []
|
||||||
here = 0
|
here = 0
|
||||||
pattern = re.compile(r'\b(((http|ftp)://\S+[\w/])|'
|
pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
|
||||||
r'(RFC[- ]?(\d+))|'
|
r'RFC[- ]?(\d+)|'
|
||||||
r'(self\.)?(\w+))\b')
|
r'(self\.)?(\w+))\b')
|
||||||
while 1:
|
while 1:
|
||||||
match = pattern.search(text, here)
|
match = pattern.search(text, here)
|
||||||
|
@ -363,14 +370,13 @@ class HTMLDoc(Doc):
|
||||||
start, end = match.span()
|
start, end = match.span()
|
||||||
results.append(escape(text[here:start]))
|
results.append(escape(text[here:start]))
|
||||||
|
|
||||||
all, url, scheme, rfc, rfcnum, selfdot, name = match.groups()
|
all, scheme, rfc, selfdot, name = match.groups()
|
||||||
if url:
|
if scheme:
|
||||||
results.append('<a href="%s">%s</a>' % (url, escape(url)))
|
results.append('<a href="%s">%s</a>' % (all, escape(all)))
|
||||||
elif rfc:
|
elif rfc:
|
||||||
url = 'http://www.rfc-editor.org/rfc/rfc%s.txt' % rfcnum
|
url = 'http://www.rfc-editor.org/rfc/rfc%s.txt' % rfc
|
||||||
results.append('<a href="%s">%s</a>' % (url, escape(rfc)))
|
results.append('<a href="%s">%s</a>' % (url, escape(all)))
|
||||||
else:
|
elif text[end:end+1] == '(':
|
||||||
if text[end:end+1] == '(':
|
|
||||||
results.append(self.namelink(name, methods, funcs, classes))
|
results.append(self.namelink(name, methods, funcs, classes))
|
||||||
elif selfdot:
|
elif selfdot:
|
||||||
results.append('self.<strong>%s</strong>' % name)
|
results.append('self.<strong>%s</strong>' % name)
|
||||||
|
@ -528,12 +534,13 @@ class HTMLDoc(Doc):
|
||||||
contents = ''
|
contents = ''
|
||||||
|
|
||||||
methods, mdict = [], {}
|
methods, mdict = [], {}
|
||||||
for key, value in inspect.getmembers(object, inspect.ismethod):
|
for key, value in allmethods(object).items():
|
||||||
methods.append((key, value))
|
methods.append((key, value))
|
||||||
mdict[key] = mdict[value] = '#' + name + '-' + key
|
mdict[key] = mdict[value] = '#' + name + '-' + key
|
||||||
|
methods.sort()
|
||||||
for key, value in methods:
|
for key, value in methods:
|
||||||
contents = contents + self.document(
|
contents = contents + self.document(
|
||||||
value, key, funcs, classes, mdict, name)
|
value, key, funcs, classes, mdict, object)
|
||||||
|
|
||||||
if name == realname:
|
if name == realname:
|
||||||
title = '<a name="%s">class <strong>%s</strong></a>' % (
|
title = '<a name="%s">class <strong>%s</strong></a>' % (
|
||||||
|
@ -541,7 +548,6 @@ class HTMLDoc(Doc):
|
||||||
else:
|
else:
|
||||||
title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
|
title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
|
||||||
name, name, realname)
|
name, name, realname)
|
||||||
|
|
||||||
if bases:
|
if bases:
|
||||||
parents = []
|
parents = []
|
||||||
for base in bases:
|
for base in bases:
|
||||||
|
@ -550,7 +556,7 @@ class HTMLDoc(Doc):
|
||||||
title = title + '(%s)' % join(parents, ', ')
|
title = title + '(%s)' % join(parents, ', ')
|
||||||
doc = self.markup(
|
doc = self.markup(
|
||||||
getdoc(object), self.preformat, funcs, classes, mdict)
|
getdoc(object), self.preformat, funcs, classes, mdict)
|
||||||
if doc: doc = self.small('<tt>%s</tt>' % doc)
|
doc = self.small('<tt>%s<br> </tt>' % doc)
|
||||||
return self.section(title, '#000000', '#ffc8d8', contents, 10, doc)
|
return self.section(title, '#000000', '#ffc8d8', contents, 10, doc)
|
||||||
|
|
||||||
def formatvalue(self, object):
|
def formatvalue(self, object):
|
||||||
|
@ -558,25 +564,42 @@ class HTMLDoc(Doc):
|
||||||
return self.small(self.grey('=' + self.repr(object)))
|
return self.small(self.grey('=' + self.repr(object)))
|
||||||
|
|
||||||
def docroutine(self, object, name=None,
|
def docroutine(self, object, name=None,
|
||||||
funcs={}, classes={}, methods={}, clname=''):
|
funcs={}, classes={}, methods={}, cl=None):
|
||||||
"""Produce HTML documentation for a function or method object."""
|
"""Produce HTML documentation for a function or method object."""
|
||||||
realname = object.__name__
|
realname = object.__name__
|
||||||
name = name or realname
|
name = name or realname
|
||||||
anchor = clname + '-' + realname
|
anchor = (cl and cl.__name__ or '') + '-' + name
|
||||||
note = ''
|
note = ''
|
||||||
|
skipdocs = 0
|
||||||
if inspect.ismethod(object):
|
if inspect.ismethod(object):
|
||||||
if not clname:
|
if cl:
|
||||||
note = self.small(self.grey(
|
if not cl.__dict__.has_key(name):
|
||||||
object.im_self and
|
base = object.im_class
|
||||||
|
url = '#%s-%s' % (base.__name__, name)
|
||||||
|
basename = base.__name__
|
||||||
|
if base.__module__ != cl.__module__:
|
||||||
|
url = base.__module__ + '.html' + url
|
||||||
|
basename = base.__module__ + '.' + basename
|
||||||
|
note = ' from <a href="%s">%s</a>' % (url, basename)
|
||||||
|
skipdocs = 1
|
||||||
|
else:
|
||||||
|
note = (object.im_self and
|
||||||
'method of ' + self.repr(object.im_self) or
|
'method of ' + self.repr(object.im_self) or
|
||||||
' unbound %s method' % object.im_class.__name__))
|
' unbound %s method' % object.im_class.__name__)
|
||||||
object = object.im_func
|
object = object.im_func
|
||||||
|
|
||||||
if name == realname:
|
if name == realname:
|
||||||
title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
|
title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
|
||||||
else:
|
else:
|
||||||
title = '<strong>%s</strong> = <a name="%s">%s</a>' % (
|
if (cl and cl.__dict__.has_key(realname) and
|
||||||
name, anchor, realname)
|
cl.__dict__[realname] is object):
|
||||||
|
reallink = '<a href="%s">%s</a>' % (
|
||||||
|
cl.__name__ + '-' + realname, realname)
|
||||||
|
skipdocs = 1
|
||||||
|
else:
|
||||||
|
reallink = realname
|
||||||
|
title = '<a name="%s"><strong>%s</strong></a> = %s' % (
|
||||||
|
anchor, name, reallink)
|
||||||
if inspect.isbuiltin(object):
|
if inspect.isbuiltin(object):
|
||||||
argspec = '(...)'
|
argspec = '(...)'
|
||||||
else:
|
else:
|
||||||
|
@ -587,11 +610,13 @@ class HTMLDoc(Doc):
|
||||||
decl = '<em>lambda</em>'
|
decl = '<em>lambda</em>'
|
||||||
argspec = argspec[1:-1] # remove parentheses
|
argspec = argspec[1:-1] # remove parentheses
|
||||||
|
|
||||||
decl = title + argspec + note
|
decl = title + argspec + (note and self.small(self.grey(note)))
|
||||||
|
|
||||||
|
if skipdocs:
|
||||||
|
return '<dl><dt>%s</dl>' % decl
|
||||||
|
else:
|
||||||
doc = self.markup(
|
doc = self.markup(
|
||||||
getdoc(object), self.preformat, funcs, classes, methods)
|
getdoc(object), self.preformat, funcs, classes, methods)
|
||||||
doc = replace(doc, ('<br>\n', '</tt></small\n><dd><small><tt>'))
|
|
||||||
doc = doc and '<tt>%s</tt>' % doc
|
doc = doc and '<tt>%s</tt>' % doc
|
||||||
return '<dl><dt>%s<dd>%s</dl>' % (decl, self.small(doc))
|
return '<dl><dt>%s<dd>%s</dl>' % (decl, self.small(doc))
|
||||||
|
|
||||||
|
@ -703,14 +728,15 @@ class TextDoc(Doc):
|
||||||
def docmodule(self, object, name=None):
|
def docmodule(self, object, name=None):
|
||||||
"""Produce text documentation for a given module object."""
|
"""Produce text documentation for a given module object."""
|
||||||
name = object.__name__ # ignore the passed-in name
|
name = object.__name__ # ignore the passed-in name
|
||||||
|
namesec = name
|
||||||
lines = split(strip(getdoc(object)), '\n')
|
lines = split(strip(getdoc(object)), '\n')
|
||||||
if len(lines) == 1:
|
if len(lines) == 1:
|
||||||
if lines[0]: name = name + ' - ' + lines[0]
|
if lines[0]: namesec = namesec + ' - ' + lines[0]
|
||||||
lines = []
|
lines = []
|
||||||
elif len(lines) >= 2 and not rstrip(lines[1]):
|
elif len(lines) >= 2 and not rstrip(lines[1]):
|
||||||
if lines[0]: name = name + ' - ' + lines[0]
|
if lines[0]: namesec = namesec + ' - ' + lines[0]
|
||||||
lines = lines[2:]
|
lines = lines[2:]
|
||||||
result = self.section('NAME', name)
|
result = self.section('NAME', namesec)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
file = inspect.getabsfile(object)
|
file = inspect.getabsfile(object)
|
||||||
|
@ -791,13 +817,16 @@ class TextDoc(Doc):
|
||||||
else:
|
else:
|
||||||
title = self.bold(name) + ' = class ' + realname
|
title = self.bold(name) + ' = class ' + realname
|
||||||
if bases:
|
if bases:
|
||||||
parents = map(lambda c, m=object.__module__: classname(c, m), bases)
|
def makename(c, m=object.__module__): return classname(c, m)
|
||||||
|
parents = map(makename, bases)
|
||||||
title = title + '(%s)' % join(parents, ', ')
|
title = title + '(%s)' % join(parents, ', ')
|
||||||
|
|
||||||
doc = getdoc(object)
|
doc = getdoc(object)
|
||||||
contents = doc and doc + '\n'
|
contents = doc and doc + '\n'
|
||||||
for key, value in inspect.getmembers(object, inspect.ismethod):
|
methods = allmethods(object).items()
|
||||||
contents = contents + '\n' + self.document(value, key, name)
|
methods.sort()
|
||||||
|
for key, value in methods:
|
||||||
|
contents = contents + '\n' + self.document(value, key, object)
|
||||||
|
|
||||||
if not contents: return title + '\n'
|
if not contents: return title + '\n'
|
||||||
return title + '\n' + self.indent(rstrip(contents), ' | ') + '\n'
|
return title + '\n' + self.indent(rstrip(contents), ' | ') + '\n'
|
||||||
|
@ -806,13 +835,22 @@ class TextDoc(Doc):
|
||||||
"""Format an argument default value as text."""
|
"""Format an argument default value as text."""
|
||||||
return '=' + self.repr(object)
|
return '=' + self.repr(object)
|
||||||
|
|
||||||
def docroutine(self, object, name=None, clname=None):
|
def docroutine(self, object, name=None, cl=None):
|
||||||
"""Produce text documentation for a function or method object."""
|
"""Produce text documentation for a function or method object."""
|
||||||
realname = object.__name__
|
realname = object.__name__
|
||||||
name = name or realname
|
name = name or realname
|
||||||
note = ''
|
note = ''
|
||||||
|
skipdocs = 0
|
||||||
if inspect.ismethod(object):
|
if inspect.ismethod(object):
|
||||||
if not clname:
|
if cl:
|
||||||
|
if not cl.__dict__.has_key(name):
|
||||||
|
base = object.im_class
|
||||||
|
basename = base.__name__
|
||||||
|
if base.__module__ != cl.__module__:
|
||||||
|
basename = base.__module__ + '.' + basename
|
||||||
|
note = ' from %s' % basename
|
||||||
|
skipdocs = 1
|
||||||
|
else:
|
||||||
if object.im_self:
|
if object.im_self:
|
||||||
note = ' method of %s' % self.repr(object.im_self)
|
note = ' method of %s' % self.repr(object.im_self)
|
||||||
else:
|
else:
|
||||||
|
@ -822,6 +860,9 @@ class TextDoc(Doc):
|
||||||
if name == realname:
|
if name == realname:
|
||||||
title = self.bold(realname)
|
title = self.bold(realname)
|
||||||
else:
|
else:
|
||||||
|
if (cl and cl.__dict__.has_key(realname) and
|
||||||
|
cl.__dict__[realname] is object):
|
||||||
|
skipdocs = 1
|
||||||
title = self.bold(name) + ' = ' + realname
|
title = self.bold(name) + ' = ' + realname
|
||||||
if inspect.isbuiltin(object):
|
if inspect.isbuiltin(object):
|
||||||
argspec = '(...)'
|
argspec = '(...)'
|
||||||
|
@ -834,11 +875,11 @@ class TextDoc(Doc):
|
||||||
argspec = argspec[1:-1] # remove parentheses
|
argspec = argspec[1:-1] # remove parentheses
|
||||||
decl = title + argspec + note
|
decl = title + argspec + note
|
||||||
|
|
||||||
doc = getdoc(object)
|
if skipdocs:
|
||||||
if doc:
|
|
||||||
return decl + '\n' + rstrip(self.indent(doc)) + '\n'
|
|
||||||
else:
|
|
||||||
return decl + '\n'
|
return decl + '\n'
|
||||||
|
else:
|
||||||
|
doc = getdoc(object) or ''
|
||||||
|
return decl + '\n' + (doc and rstrip(self.indent(doc)) + '\n')
|
||||||
|
|
||||||
def docother(self, object, name=None, maxlen=None):
|
def docother(self, object, name=None, maxlen=None):
|
||||||
"""Produce text documentation for a data object."""
|
"""Produce text documentation for a data object."""
|
||||||
|
@ -951,7 +992,7 @@ def plainpager(text):
|
||||||
sys.stdout.write(plain(text))
|
sys.stdout.write(plain(text))
|
||||||
|
|
||||||
def describe(thing):
|
def describe(thing):
|
||||||
"""Produce a short description of the given kind of thing."""
|
"""Produce a short description of the given thing."""
|
||||||
if inspect.ismodule(thing):
|
if inspect.ismodule(thing):
|
||||||
if thing.__name__ in sys.builtin_module_names:
|
if thing.__name__ in sys.builtin_module_names:
|
||||||
return 'built-in module ' + thing.__name__
|
return 'built-in module ' + thing.__name__
|
||||||
|
@ -971,52 +1012,69 @@ def describe(thing):
|
||||||
return 'instance of ' + thing.__class__.__name__
|
return 'instance of ' + thing.__class__.__name__
|
||||||
return type(thing).__name__
|
return type(thing).__name__
|
||||||
|
|
||||||
def freshimp(path, cache={}):
|
def freshimport(name, cache={}):
|
||||||
"""Import a module, reloading it if the source file has changed."""
|
"""Import a module, reloading it if the source file has changed."""
|
||||||
module = __import__(path)
|
topmodule = __import__(name)
|
||||||
|
module = None
|
||||||
|
for component in split(name, '.'):
|
||||||
|
if module == None:
|
||||||
|
module = topmodule
|
||||||
|
path = split(name, '.')[0]
|
||||||
|
else:
|
||||||
|
module = getattr(module, component)
|
||||||
|
path = path + '.' + component
|
||||||
if hasattr(module, '__file__'):
|
if hasattr(module, '__file__'):
|
||||||
file = module.__file__
|
file = module.__file__
|
||||||
|
if os.path.exists(file):
|
||||||
info = (file, os.path.getmtime(file), os.path.getsize(file))
|
info = (file, os.path.getmtime(file), os.path.getsize(file))
|
||||||
if cache.has_key(path):
|
if cache.has_key(path) and cache[path] != info:
|
||||||
if cache[path] != info:
|
|
||||||
module = reload(module)
|
module = reload(module)
|
||||||
|
file = module.__file__
|
||||||
|
if os.path.exists(file):
|
||||||
|
info = (file, os.path.getmtime(file), os.path.getsize(file))
|
||||||
cache[path] = info
|
cache[path] = info
|
||||||
return module
|
return module
|
||||||
|
|
||||||
def locate(path):
|
def locate(path):
|
||||||
"""Locate an object by name (or dotted path), importing as necessary."""
|
"""Locate an object by name (or dotted path), importing as necessary."""
|
||||||
if not path: # special case: imp.find_module('') strangely succeeds
|
if not path: # special case: imp.find_module('') strangely succeeds
|
||||||
return None, None
|
return None
|
||||||
if type(path) is not types.StringType:
|
if type(path) is not types.StringType:
|
||||||
return None, path
|
return path
|
||||||
parts = split(path, '.')
|
parts = split(path, '.')
|
||||||
n = 1
|
n = len(parts)
|
||||||
while n <= len(parts):
|
while n > 0:
|
||||||
path = join(parts[:n], '.')
|
path = join(parts[:n], '.')
|
||||||
try:
|
try:
|
||||||
module = freshimp(path)
|
module = freshimport(path)
|
||||||
except:
|
except:
|
||||||
# determine if error occurred before or after module was found
|
# Did the error occur before or after the module was found?
|
||||||
|
(exc, value, tb) = info = sys.exc_info()
|
||||||
if sys.modules.has_key(path):
|
if sys.modules.has_key(path):
|
||||||
filename = sys.modules[path].__file__
|
# An error occured while executing the imported module.
|
||||||
elif sys.exc_type is SyntaxError:
|
raise ErrorDuringImport(sys.modules[path].__file__, info)
|
||||||
filename = sys.exc_value.filename
|
elif exc is SyntaxError:
|
||||||
|
# A SyntaxError occurred before we could execute the module.
|
||||||
|
raise ErrorDuringImport(value.filename, info)
|
||||||
|
elif exc is ImportError and \
|
||||||
|
split(lower(str(value)))[:2] == ['no', 'module']:
|
||||||
|
# The module was not found.
|
||||||
|
n = n - 1
|
||||||
|
continue
|
||||||
else:
|
else:
|
||||||
# module not found, so stop looking
|
# Some other error occurred before executing the module.
|
||||||
break
|
|
||||||
# error occurred in the imported module, so report it
|
|
||||||
raise DocImportError(filename, sys.exc_info())
|
raise DocImportError(filename, sys.exc_info())
|
||||||
try:
|
try:
|
||||||
x = module
|
x = module
|
||||||
for p in parts[1:]:
|
for p in parts[n:]:
|
||||||
x = getattr(x, p)
|
x = getattr(x, p)
|
||||||
return join(parts[:-1], '.'), x
|
return x
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
n = n + 1
|
n = n - 1
|
||||||
continue
|
continue
|
||||||
if hasattr(__builtins__, path):
|
if hasattr(__builtins__, path):
|
||||||
return None, getattr(__builtins__, path)
|
return getattr(__builtins__, path)
|
||||||
return None, None
|
return None
|
||||||
|
|
||||||
# --------------------------------------- interactive interpreter interface
|
# --------------------------------------- interactive interpreter interface
|
||||||
|
|
||||||
|
@ -1027,12 +1085,12 @@ def doc(thing):
|
||||||
"""Display documentation on an object (for interactive use)."""
|
"""Display documentation on an object (for interactive use)."""
|
||||||
if type(thing) is type(""):
|
if type(thing) is type(""):
|
||||||
try:
|
try:
|
||||||
path, x = locate(thing)
|
object = locate(thing)
|
||||||
except DocImportError, value:
|
except ErrorDuringImport, value:
|
||||||
print value
|
print value
|
||||||
return
|
return
|
||||||
if x:
|
if object:
|
||||||
thing = x
|
thing = object
|
||||||
else:
|
else:
|
||||||
print 'no Python documentation found for %s' % repr(thing)
|
print 'no Python documentation found for %s' % repr(thing)
|
||||||
return
|
return
|
||||||
|
@ -1046,8 +1104,8 @@ def doc(thing):
|
||||||
def writedoc(key):
|
def writedoc(key):
|
||||||
"""Write HTML documentation to a file in the current directory."""
|
"""Write HTML documentation to a file in the current directory."""
|
||||||
try:
|
try:
|
||||||
path, object = locate(key)
|
object = locate(key)
|
||||||
except DocImportError, value:
|
except ErrorDuringImport, value:
|
||||||
print value
|
print value
|
||||||
else:
|
else:
|
||||||
if object:
|
if object:
|
||||||
|
@ -1090,10 +1148,11 @@ help = Helper()
|
||||||
|
|
||||||
def man(key):
|
def man(key):
|
||||||
"""Display documentation on an object in a form similar to man(1)."""
|
"""Display documentation on an object in a form similar to man(1)."""
|
||||||
path, object = locate(key)
|
object = locate(key)
|
||||||
if object:
|
if object:
|
||||||
title = 'Python Library Documentation: ' + describe(object)
|
title = 'Python Library Documentation: ' + describe(object)
|
||||||
if path: title = title + ' in ' + path
|
lastdot = rfind(key, '.')
|
||||||
|
if lastdot > 0: title = title + ' in ' + key[:lastdot]
|
||||||
pager('\n' + title + '\n\n' + text.document(object, key))
|
pager('\n' + title + '\n\n' + text.document(object, key))
|
||||||
found = 1
|
found = 1
|
||||||
else:
|
else:
|
||||||
|
@ -1149,7 +1208,7 @@ class ModuleScanner(Scanner):
|
||||||
for modname in sys.builtin_module_names:
|
for modname in sys.builtin_module_names:
|
||||||
if modname != '__main__':
|
if modname != '__main__':
|
||||||
seen[modname] = 1
|
seen[modname] = 1
|
||||||
desc = split(freshimp(modname).__doc__ or '', '\n')[0]
|
desc = split(freshimport(modname).__doc__ or '', '\n')[0]
|
||||||
if find(lower(modname + ' - ' + desc), lower(key)) >= 0:
|
if find(lower(modname + ' - ' + desc), lower(key)) >= 0:
|
||||||
callback(None, modname, desc)
|
callback(None, modname, desc)
|
||||||
|
|
||||||
|
@ -1205,12 +1264,12 @@ def serve(port, callback=None):
|
||||||
if path[:1] == '/': path = path[1:]
|
if path[:1] == '/': path = path[1:]
|
||||||
if path and path != '.':
|
if path and path != '.':
|
||||||
try:
|
try:
|
||||||
p, x = locate(path)
|
obj = locate(path)
|
||||||
except DocImportError, value:
|
except ErrorDuringImport, value:
|
||||||
self.send_document(path, html.escape(str(value)))
|
self.send_document(path, html.escape(str(value)))
|
||||||
return
|
return
|
||||||
if x:
|
if obj:
|
||||||
self.send_document(describe(x), html.document(x, path))
|
self.send_document(describe(obj), html.document(obj, path))
|
||||||
else:
|
else:
|
||||||
self.send_document(path,
|
self.send_document(path,
|
||||||
'no Python documentation found for %s' % repr(path))
|
'no Python documentation found for %s' % repr(path))
|
||||||
|
@ -1220,13 +1279,12 @@ def serve(port, callback=None):
|
||||||
'#ffffff', '#7799ee')
|
'#ffffff', '#7799ee')
|
||||||
def bltinlink(name):
|
def bltinlink(name):
|
||||||
return '<a href="%s.html">%s</a>' % (name, name)
|
return '<a href="%s.html">%s</a>' % (name, name)
|
||||||
names = filter(lambda x: x != '__main__', sys.builtin_module_names)
|
names = filter(lambda x: x != '__main__',
|
||||||
|
sys.builtin_module_names)
|
||||||
contents = html.multicolumn(names, bltinlink)
|
contents = html.multicolumn(names, bltinlink)
|
||||||
indices = ['<p>' + html.bigsection(
|
indices = ['<p>' + html.bigsection(
|
||||||
'Built-in Modules', '#ffffff', '#ee77aa', contents)]
|
'Built-in Modules', '#ffffff', '#ee77aa', contents)]
|
||||||
|
|
||||||
# for skip in ['', '.', os.getcwd(), os.path.dirname(sys.argv[0])]:
|
|
||||||
# if skip in sys.path: sys.path.remove(skip)
|
|
||||||
seen = {}
|
seen = {}
|
||||||
for dir in pathdirs():
|
for dir in pathdirs():
|
||||||
indices.append(html.index(dir, seen))
|
indices.append(html.index(dir, seen))
|
||||||
|
@ -1453,12 +1511,10 @@ def cli():
|
||||||
import getopt
|
import getopt
|
||||||
class BadUsage: pass
|
class BadUsage: pass
|
||||||
|
|
||||||
try:
|
# Scripts don't get the current directory in their path by default.
|
||||||
if sys.platform in ['mac', 'win32'] and not sys.argv[1:]:
|
sys.path.insert(0, '.')
|
||||||
# graphical platforms with threading (and no CLI)
|
|
||||||
gui()
|
|
||||||
return
|
|
||||||
|
|
||||||
|
try:
|
||||||
opts, args = getopt.getopt(sys.argv[1:], 'gk:p:w')
|
opts, args = getopt.getopt(sys.argv[1:], 'gk:p:w')
|
||||||
writing = 0
|
writing = 0
|
||||||
|
|
||||||
|
@ -1493,7 +1549,7 @@ def cli():
|
||||||
writedoc(arg)
|
writedoc(arg)
|
||||||
else:
|
else:
|
||||||
man(arg)
|
man(arg)
|
||||||
except DocImportError, value:
|
except ErrorDuringImport, value:
|
||||||
print value
|
print value
|
||||||
|
|
||||||
except (getopt.error, BadUsage):
|
except (getopt.error, BadUsage):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue