[svn r37383] Added call stacks, made that method pages aren't built at all anymore, made
that build_namespace_view isn't called for anything but namespaces anymore, made that parts of documents are hidden at first (with a link to 'open' them). --HG-- branch : trunk
This commit is contained in:
parent
c72120b8fc
commit
b67ef229df
|
@ -1,7 +1,22 @@
|
|||
function showhideel(el) {
|
||||
/* show or hide the element
|
||||
|
||||
sets the value of el.style.display to 'none' or 'block' depending
|
||||
on the current value
|
||||
*/
|
||||
if (el.style.display == 'none') {
|
||||
el.style.display = 'block';
|
||||
} else {
|
||||
el.style.display = 'none';
|
||||
};
|
||||
};
|
||||
|
||||
function getnextsibling(el) {
|
||||
/* return next non-text sibling (or null) */
|
||||
var node = el.nextSibling;
|
||||
while (node && node.nodeType != 1) {
|
||||
node = node.nextSibling;
|
||||
};
|
||||
return node;
|
||||
};
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ def build(pkgdir, dsa):
|
|||
|
||||
ns_data = apb.prepare_namespace_pages(namespace_tree)
|
||||
class_names = dsa.get_class_names()
|
||||
class_data, method_data = apb.prepare_class_pages(namespace_tree,
|
||||
class_data = apb.prepare_class_pages(namespace_tree,
|
||||
class_names)
|
||||
function_names = dsa.get_function_names()
|
||||
func_data = apb.prepare_function_pages(namespace_tree, function_names)
|
||||
|
@ -45,7 +45,7 @@ def build(pkgdir, dsa):
|
|||
|
||||
apb.build_namespace_pages(ns_data, proj)
|
||||
apb.build_class_pages(class_data, proj)
|
||||
apb.build_method_pages(method_data, proj)
|
||||
#apb.build_method_pages(method_data, proj)
|
||||
apb.build_function_pages(func_data, proj)
|
||||
spb.build_pages(source_data, proj, pkgdir)
|
||||
|
||||
|
|
|
@ -14,8 +14,11 @@ raw = py.xml.raw
|
|||
|
||||
# HTML related stuff
|
||||
class H(html):
|
||||
class Description(html.div):
|
||||
class Content(html.div):
|
||||
style = html.Style(margin_left='15em')
|
||||
|
||||
class Description(html.div):
|
||||
pass
|
||||
|
||||
class NamespaceDescription(Description):
|
||||
pass
|
||||
|
@ -79,6 +82,12 @@ class H(html):
|
|||
class ValueDescItem(html.li):
|
||||
pass
|
||||
|
||||
class CallStackDescription(Description):
|
||||
pass
|
||||
|
||||
class CallStackItem(html.div):
|
||||
class_ = 'callstackitem'
|
||||
|
||||
def get_param_htmldesc(linker, func):
|
||||
""" get the html for the parameters of a function """
|
||||
import inspect
|
||||
|
@ -321,14 +330,23 @@ class ApiPageBuilder(AbstractPageBuilder):
|
|||
else:
|
||||
csource = H.SourceDef('could not get source file')
|
||||
|
||||
csdiv = H.div(style='display: none')
|
||||
for cs, _ in self.dsa.get_function_callpoints(dotted_name):
|
||||
csdiv.append(self.build_callsite(dotted_name, cs))
|
||||
callstack = H.CallStackDescription(
|
||||
H.a('show/hide call sites',
|
||||
href='#',
|
||||
onclick='showhideel(getnextsibling(this)); return false;'),
|
||||
csdiv,
|
||||
)
|
||||
snippet = H.FunctionDescription(
|
||||
H.FunctionDef(localname, argdesc),
|
||||
H.Docstring(docstring or H.em('no docstring available')),
|
||||
H.div(H.a('show/hide info',
|
||||
href='#',
|
||||
onclick=('showhideel(this.parentNode.lastChild);'
|
||||
onclick=('showhideel(getnextsibling(this));'
|
||||
'return false;')),
|
||||
H.div(valuedesc, csource, style='display: none',
|
||||
H.div(valuedesc, csource, callstack, style='display: none',
|
||||
class_='funcinfo')),
|
||||
)
|
||||
|
||||
|
@ -397,7 +415,7 @@ class ApiPageBuilder(AbstractPageBuilder):
|
|||
H.NamespaceDef(namespace_dotted_name),
|
||||
H.Docstring(docstring or H.em('no docstring available'))
|
||||
)
|
||||
for dotted_name in item_dotted_names:
|
||||
for dotted_name in sorted(item_dotted_names):
|
||||
itemname = dotted_name.split('.')[-1]
|
||||
if is_private(itemname):
|
||||
continue
|
||||
|
@ -412,26 +430,20 @@ class ApiPageBuilder(AbstractPageBuilder):
|
|||
|
||||
def prepare_class_pages(self, namespace_tree, classes_dotted_names):
|
||||
passed = []
|
||||
methodsdata = []
|
||||
for dotted_name in classes_dotted_names:
|
||||
for dotted_name in sorted(classes_dotted_names):
|
||||
parent_dotted_name, _ = split_of_last_part(dotted_name)
|
||||
try:
|
||||
sibling_dotted_names = namespace_tree[parent_dotted_name]
|
||||
except KeyError:
|
||||
# no siblings (built-in module or sth)
|
||||
sibling_dotted_names = []
|
||||
tag = self.build_class_view(dotted_name)
|
||||
tag = H.Content(self.build_class_view(dotted_name))
|
||||
nav = self.build_navigation(parent_dotted_name,
|
||||
sibling_dotted_names, dotted_name)
|
||||
reltargetpath = "api/%s.html" % (dotted_name,)
|
||||
self.linker.set_link(dotted_name, reltargetpath)
|
||||
passed.append((dotted_name, tag, nav, reltargetpath))
|
||||
method_dotted_names = ['%s.%s' % (dotted_name, method_name) for
|
||||
method_name in
|
||||
self.dsa.get_class_methods(dotted_name)]
|
||||
methodsdata += self.prepare_method_pages(namespace_tree,
|
||||
method_dotted_names)
|
||||
return passed, methodsdata
|
||||
return passed
|
||||
|
||||
def build_class_pages(self, data, project):
|
||||
""" build the full api pages for a set of classes """
|
||||
|
@ -443,7 +455,7 @@ class ApiPageBuilder(AbstractPageBuilder):
|
|||
# XXX note that even though these pages are still built, there's no nav
|
||||
# pointing to them anymore...
|
||||
passed = []
|
||||
for dotted_name in method_dotted_names:
|
||||
for dotted_name in sorted(method_dotted_names):
|
||||
parent_dotted_name, _ = split_of_last_part(dotted_name)
|
||||
module_dotted_name, _ = split_of_last_part(parent_dotted_name)
|
||||
sibling_dotted_names = namespace_tree[module_dotted_name]
|
||||
|
@ -462,11 +474,11 @@ class ApiPageBuilder(AbstractPageBuilder):
|
|||
|
||||
def prepare_function_pages(self, namespace_tree, method_dotted_names):
|
||||
passed = []
|
||||
for dotted_name in method_dotted_names:
|
||||
for dotted_name in sorted(method_dotted_names):
|
||||
# XXX should we create a build_function_view instead?
|
||||
parent_dotted_name, _ = split_of_last_part(dotted_name)
|
||||
sibling_dotted_names = namespace_tree[parent_dotted_name]
|
||||
tag = self.build_callable_view(dotted_name)
|
||||
tag = H.Content(self.build_callable_view(dotted_name))
|
||||
nav = self.build_navigation(parent_dotted_name,
|
||||
sibling_dotted_names, dotted_name)
|
||||
reltargetpath = "api/%s.html" % (dotted_name,)
|
||||
|
@ -485,9 +497,14 @@ class ApiPageBuilder(AbstractPageBuilder):
|
|||
|
||||
names = namespace_tree.keys()
|
||||
names.sort()
|
||||
for dotted_name in names:
|
||||
function_names = self.dsa.get_function_names()
|
||||
class_names = self.dsa.get_class_names()
|
||||
for dotted_name in sorted(names):
|
||||
if dotted_name in function_names or dotted_name in class_names:
|
||||
continue
|
||||
subitem_dotted_names = namespace_tree[dotted_name]
|
||||
tag = self.build_namespace_view(dotted_name, subitem_dotted_names)
|
||||
tag = H.Content(self.build_namespace_view(dotted_name,
|
||||
subitem_dotted_names))
|
||||
nav = self.build_navigation(dotted_name, subitem_dotted_names,
|
||||
dotted_name)
|
||||
if dotted_name == '':
|
||||
|
@ -588,3 +605,42 @@ class ApiPageBuilder(AbstractPageBuilder):
|
|||
def is_in_pkg(self, sourcefile):
|
||||
return py.path.local(sourcefile).relto(self.projpath)
|
||||
|
||||
def build_callsite(self, functionname, call_site):
|
||||
tbtag = self.gen_traceback(functionname, call_site)
|
||||
tag = H.CallStackItem(
|
||||
H.a("%s - line %s" % (call_site[0].filename, call_site[0].lineno + 1),
|
||||
href='#',
|
||||
onclick="showhideel(getnextsibling(this)); return false;"),
|
||||
H.div(tbtag, style='display: none')
|
||||
)
|
||||
return tag
|
||||
|
||||
def gen_traceback(self, funcname, call_site):
|
||||
tbdiv = H.div()
|
||||
for line in call_site:
|
||||
lineno = line.lineno - line.firstlineno
|
||||
source = line.source
|
||||
sourcefile = line.filename
|
||||
mangled = []
|
||||
for i, sline in enumerate(str(source).split('\n')):
|
||||
if i == lineno:
|
||||
l = '-> %s' % (sline,)
|
||||
else:
|
||||
l = ' %s' % (sline,)
|
||||
mangled.append(l)
|
||||
if sourcefile:
|
||||
linktext = '%s - line %s' % (sourcefile, line.lineno + 1)
|
||||
# skip py.code.Source objects and source files outside of the
|
||||
# package
|
||||
if (not sourcefile.startswith('None') and
|
||||
self.is_in_pkg(sourcefile)):
|
||||
href = self.linker.get_lazyhref(sourcefile)
|
||||
sourcelink = H.a(linktext, href=href)
|
||||
else:
|
||||
sourcelink = H.div(linktext)
|
||||
else:
|
||||
sourcelink = H.div('source unknown')
|
||||
tbdiv.append(sourcelink)
|
||||
tbdiv.append(H.pre('\n'.join(mangled)))
|
||||
return tbdiv
|
||||
|
||||
|
|
|
@ -163,9 +163,9 @@ class TestApiPageBuilder(AbstractBuilderTest):
|
|||
_checkhtmlsnippet(html)
|
||||
|
||||
def test_build_class_pages(self):
|
||||
data, methodsdata = self.apb.prepare_class_pages(self.namespace_tree,
|
||||
['main.SomeClass',
|
||||
'main.SomeSubClass'])
|
||||
data = self.apb.prepare_class_pages(self.namespace_tree,
|
||||
['main.SomeClass',
|
||||
'main.SomeSubClass'])
|
||||
self.apb.build_class_pages(data, self.project)
|
||||
clsfile = self.base.join('api/main.SomeClass.html')
|
||||
assert clsfile.check()
|
||||
|
@ -173,10 +173,10 @@ class TestApiPageBuilder(AbstractBuilderTest):
|
|||
_checkhtml(html)
|
||||
|
||||
def test_build_class_pages_instance(self):
|
||||
data, methodsdata = self.apb.prepare_class_pages(self.namespace_tree,
|
||||
['main.SomeClass',
|
||||
'main.SomeSubClass',
|
||||
'main.SomeInstance'])
|
||||
data = self.apb.prepare_class_pages(self.namespace_tree,
|
||||
['main.SomeClass',
|
||||
'main.SomeSubClass',
|
||||
'main.SomeInstance'])
|
||||
self.apb.build_class_pages(data, self.project)
|
||||
clsfile = self.base.join('api/main.SomeInstance.html')
|
||||
assert clsfile.check()
|
||||
|
@ -187,9 +187,9 @@ class TestApiPageBuilder(AbstractBuilderTest):
|
|||
])
|
||||
|
||||
def test_build_class_pages_nav_links(self):
|
||||
data, methodsdata = self.apb.prepare_class_pages(self.namespace_tree,
|
||||
['main.SomeSubClass',
|
||||
'main.SomeClass'])
|
||||
data = self.apb.prepare_class_pages(self.namespace_tree,
|
||||
['main.SomeSubClass',
|
||||
'main.SomeClass'])
|
||||
# fake some stuff that would be built from other methods
|
||||
self.linker.set_link('', 'api/index.html')
|
||||
self.linker.set_link('main', 'api/main.html')
|
||||
|
@ -212,9 +212,9 @@ class TestApiPageBuilder(AbstractBuilderTest):
|
|||
_checkhtml(html)
|
||||
|
||||
def test_build_class_pages_base_link(self):
|
||||
data, methodsdata = self.apb.prepare_class_pages(self.namespace_tree,
|
||||
['main.SomeSubClass',
|
||||
'main.SomeClass'])
|
||||
data = self.apb.prepare_class_pages(self.namespace_tree,
|
||||
['main.SomeSubClass',
|
||||
'main.SomeClass'])
|
||||
self.apb.build_class_pages(data, self.project)
|
||||
clsfile = self.base.join('api/main.SomeSubClass.html')
|
||||
assert clsfile.check()
|
||||
|
@ -227,9 +227,9 @@ class TestApiPageBuilder(AbstractBuilderTest):
|
|||
_checkhtml(html)
|
||||
|
||||
def test_source_links(self):
|
||||
data, methodsdata = self.apb.prepare_class_pages(self.namespace_tree,
|
||||
['main.SomeSubClass',
|
||||
'main.SomeClass'])
|
||||
data = self.apb.prepare_class_pages(self.namespace_tree,
|
||||
['main.SomeSubClass',
|
||||
'main.SomeClass'])
|
||||
sourcedata = self.spb.prepare_pages(self.fs_root)
|
||||
self.apb.build_class_pages(data, self.project)
|
||||
self.spb.build_pages(sourcedata, self.project, self.fs_root)
|
||||
|
|
|
@ -113,9 +113,9 @@ def test_apigen_functional():
|
|||
html = sometestclass_source.read()
|
||||
assert '<div class="project_title">sources for sometestclass.py</div>' in html
|
||||
|
||||
# XXX later...
|
||||
#index = sourcedir.join('index.html')
|
||||
#assert index.check(file=True)
|
||||
#html = index.read()
|
||||
#assert '<a href="main/index.html">main</a>' in html
|
||||
index = sourcedir.join('index.html')
|
||||
assert index.check(file=True)
|
||||
html = index.read()
|
||||
print html
|
||||
assert '<a href="test/index.html">test</a>' in html
|
||||
|
||||
|
|
Loading…
Reference in New Issue