[svn r41620] Re-added anchors to the (full) source files, and using them from the API

documentation.

--HG--
branch : trunk
This commit is contained in:
guido
2007-03-29 13:56:14 +02:00
parent 9466961ee4
commit cd6471e71f
7 changed files with 152 additions and 22 deletions

View File

@@ -18,6 +18,25 @@ raw = py.xml.raw
REDUCE_CALLSITES = True
def find_method_origin(meth):
cls = getattr(meth, 'im_class', None)
if cls is None:
return None # XXX unknown origin (built-in function or method or sth)
name = meth.im_func.func_name
origin = cls
# XXX old-style classes support required? :|
mro = inspect.getmro(cls)
for base in mro:
m = getattr(base, name, None)
if m is None:
continue
if not hasattr(m, 'im_func'):
# builtin
return None
if m.im_func is meth.im_func:
origin = base
return origin
def is_navigateable(name):
return (not is_private(name) and name != '__doc__')
@@ -135,10 +154,17 @@ def enumerate_and_color(codelines, firstlineno, enc):
source_html.prepare_line([line], tokenizer, enc))
except py.error.ENOENT:
# error reading source code, giving up
snippet = org
snippet = codelines
break
return snippet
def enumerate_and_color_module(path, enc):
snippet = H.SourceBlock()
tokenizer = source_color.Tokenizer(source_color.PythonSchema)
for i, text in enumerate(source_html.prepare_module(path, tokenizer, enc)):
snippet.add_line(i + 1, text)
return snippet
_get_obj_cache = {}
def get_obj(dsa, pkg, dotted_name):
full_dotted_name = '%s.%s' % (pkg.__name__, dotted_name)
@@ -258,9 +284,16 @@ class SourcePageBuilder(AbstractPageBuilder):
# XXX two reads of the same file here... not very bad (disk caches
# and such) but also not very nice...
enc = source_html.get_module_encoding(fspath.strpath)
source = fspath.read()
sep = get_linesep(source)
colored = [enumerate_and_color(source.split(sep), 0, enc)]
try:
colored = [enumerate_and_color_module(fspath, enc)]
except (KeyboardInterrupt, SystemExit):
raise
except Exception, e:
#self.capture.err.writeorg('\ncompilation exception: %s\n' % (e,))
# problem building HTML with anchors; let's try without...
source = fspath.read()
sep = get_linesep(source)
colored = [enumerate_and_color(source.split(sep), 0, enc)]
tag = H.PythonSource(colored)
nav = self.build_navigation(fspath)
return tag, nav
@@ -316,7 +349,7 @@ class SourcePageBuilder(AbstractPageBuilder):
if fspath.check(ext='.py'):
try:
tag, nav = self.build_python_page(fspath)
except (KeyboardInterrupt, SystemError):
except (KeyboardInterrupt, SystemExit):
raise
except: # XXX strange stuff going wrong at times... need to fix
raise
@@ -398,8 +431,8 @@ class ApiPageBuilder(AbstractPageBuilder):
relpath = get_rel_sourcepath(self.projroot, sourcefile, sourcefile)
text = 'source: %s' % (relpath,)
if is_in_pkg:
href = self.linker.get_lazyhref(sourcefile)
href = self.linker.get_lazyhref(sourcefile,
self.get_anchor(func))
csource = H.SourceSnippet(text, href, colored)
cslinks = self.build_callsites(dotted_name)
snippet = H.FunctionDescription(localname, argdesc, docstring,
@@ -432,7 +465,8 @@ class ApiPageBuilder(AbstractPageBuilder):
if sourcefile[-1] in ['o', 'c']:
sourcefile = sourcefile[:-1]
sourcelink = H.div(H.a('view source',
href=self.linker.get_lazyhref(sourcefile)))
href=self.linker.get_lazyhref(sourcefile,
self.get_anchor(cls))))
snippet = H.ClassDescription(
# XXX bases HTML
@@ -651,6 +685,10 @@ class ApiPageBuilder(AbstractPageBuilder):
return lst
name, _desc_type, is_degenerated = data
if not is_degenerated:
try:
obj = self.dsa.get_obj(name)
except KeyError:
obj = None
linktarget = self.linker.get_lazyhref(name)
lst.append(H.a(str(_type), href=linktarget))
else:
@@ -695,6 +733,7 @@ class ApiPageBuilder(AbstractPageBuilder):
_reg_source = py.std.re.compile(r'([^>]*)<(.*)>')
def gen_traceback(self, dotted_name, call_site):
tbtag = H.CallStackDescription()
obj = self.dsa.get_obj(dotted_name)
for frame in call_site:
lineno = frame.lineno - frame.firstlineno
source = frame.source
@@ -772,3 +811,20 @@ class ApiPageBuilder(AbstractPageBuilder):
self._revcache[dotted_name] = rev
return rev
def get_anchor(self, obj):
# XXX may not always return the right results...
anchor = None
if hasattr(obj, 'im_func'):
# method
origin = find_method_origin(obj)
if origin:
anchor = '%s.%s' % (origin.__name__,
obj.im_func.func_name)
elif hasattr(obj, 'func_name'):
anchor = obj.func_name
elif hasattr(obj, '__name__'):
anchor = obj.__name__
elif hasattr(obj, '__class__'):
anchor = obj.__class__.__name__
return anchor