[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) {
|
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') {
|
if (el.style.display == 'none') {
|
||||||
el.style.display = 'block';
|
el.style.display = 'block';
|
||||||
} else {
|
} else {
|
||||||
el.style.display = 'none';
|
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)
|
ns_data = apb.prepare_namespace_pages(namespace_tree)
|
||||||
class_names = dsa.get_class_names()
|
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)
|
class_names)
|
||||||
function_names = dsa.get_function_names()
|
function_names = dsa.get_function_names()
|
||||||
func_data = apb.prepare_function_pages(namespace_tree, 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_namespace_pages(ns_data, proj)
|
||||||
apb.build_class_pages(class_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)
|
apb.build_function_pages(func_data, proj)
|
||||||
spb.build_pages(source_data, proj, pkgdir)
|
spb.build_pages(source_data, proj, pkgdir)
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,11 @@ raw = py.xml.raw
|
||||||
|
|
||||||
# HTML related stuff
|
# HTML related stuff
|
||||||
class H(html):
|
class H(html):
|
||||||
class Description(html.div):
|
class Content(html.div):
|
||||||
style = html.Style(margin_left='15em')
|
style = html.Style(margin_left='15em')
|
||||||
|
|
||||||
|
class Description(html.div):
|
||||||
|
pass
|
||||||
|
|
||||||
class NamespaceDescription(Description):
|
class NamespaceDescription(Description):
|
||||||
pass
|
pass
|
||||||
|
@ -79,6 +82,12 @@ class H(html):
|
||||||
class ValueDescItem(html.li):
|
class ValueDescItem(html.li):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class CallStackDescription(Description):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class CallStackItem(html.div):
|
||||||
|
class_ = 'callstackitem'
|
||||||
|
|
||||||
def get_param_htmldesc(linker, func):
|
def get_param_htmldesc(linker, func):
|
||||||
""" get the html for the parameters of a function """
|
""" get the html for the parameters of a function """
|
||||||
import inspect
|
import inspect
|
||||||
|
@ -321,14 +330,23 @@ class ApiPageBuilder(AbstractPageBuilder):
|
||||||
else:
|
else:
|
||||||
csource = H.SourceDef('could not get source file')
|
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(
|
snippet = H.FunctionDescription(
|
||||||
H.FunctionDef(localname, argdesc),
|
H.FunctionDef(localname, argdesc),
|
||||||
H.Docstring(docstring or H.em('no docstring available')),
|
H.Docstring(docstring or H.em('no docstring available')),
|
||||||
H.div(H.a('show/hide info',
|
H.div(H.a('show/hide info',
|
||||||
href='#',
|
href='#',
|
||||||
onclick=('showhideel(this.parentNode.lastChild);'
|
onclick=('showhideel(getnextsibling(this));'
|
||||||
'return false;')),
|
'return false;')),
|
||||||
H.div(valuedesc, csource, style='display: none',
|
H.div(valuedesc, csource, callstack, style='display: none',
|
||||||
class_='funcinfo')),
|
class_='funcinfo')),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -397,7 +415,7 @@ class ApiPageBuilder(AbstractPageBuilder):
|
||||||
H.NamespaceDef(namespace_dotted_name),
|
H.NamespaceDef(namespace_dotted_name),
|
||||||
H.Docstring(docstring or H.em('no docstring available'))
|
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]
|
itemname = dotted_name.split('.')[-1]
|
||||||
if is_private(itemname):
|
if is_private(itemname):
|
||||||
continue
|
continue
|
||||||
|
@ -412,26 +430,20 @@ class ApiPageBuilder(AbstractPageBuilder):
|
||||||
|
|
||||||
def prepare_class_pages(self, namespace_tree, classes_dotted_names):
|
def prepare_class_pages(self, namespace_tree, classes_dotted_names):
|
||||||
passed = []
|
passed = []
|
||||||
methodsdata = []
|
for dotted_name in sorted(classes_dotted_names):
|
||||||
for dotted_name in classes_dotted_names:
|
|
||||||
parent_dotted_name, _ = split_of_last_part(dotted_name)
|
parent_dotted_name, _ = split_of_last_part(dotted_name)
|
||||||
try:
|
try:
|
||||||
sibling_dotted_names = namespace_tree[parent_dotted_name]
|
sibling_dotted_names = namespace_tree[parent_dotted_name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# no siblings (built-in module or sth)
|
# no siblings (built-in module or sth)
|
||||||
sibling_dotted_names = []
|
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,
|
nav = self.build_navigation(parent_dotted_name,
|
||||||
sibling_dotted_names, dotted_name)
|
sibling_dotted_names, dotted_name)
|
||||||
reltargetpath = "api/%s.html" % (dotted_name,)
|
reltargetpath = "api/%s.html" % (dotted_name,)
|
||||||
self.linker.set_link(dotted_name, reltargetpath)
|
self.linker.set_link(dotted_name, reltargetpath)
|
||||||
passed.append((dotted_name, tag, nav, reltargetpath))
|
passed.append((dotted_name, tag, nav, reltargetpath))
|
||||||
method_dotted_names = ['%s.%s' % (dotted_name, method_name) for
|
return passed
|
||||||
method_name in
|
|
||||||
self.dsa.get_class_methods(dotted_name)]
|
|
||||||
methodsdata += self.prepare_method_pages(namespace_tree,
|
|
||||||
method_dotted_names)
|
|
||||||
return passed, methodsdata
|
|
||||||
|
|
||||||
def build_class_pages(self, data, project):
|
def build_class_pages(self, data, project):
|
||||||
""" build the full api pages for a set of classes """
|
""" 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
|
# XXX note that even though these pages are still built, there's no nav
|
||||||
# pointing to them anymore...
|
# pointing to them anymore...
|
||||||
passed = []
|
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)
|
parent_dotted_name, _ = split_of_last_part(dotted_name)
|
||||||
module_dotted_name, _ = split_of_last_part(parent_dotted_name)
|
module_dotted_name, _ = split_of_last_part(parent_dotted_name)
|
||||||
sibling_dotted_names = namespace_tree[module_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):
|
def prepare_function_pages(self, namespace_tree, method_dotted_names):
|
||||||
passed = []
|
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?
|
# XXX should we create a build_function_view instead?
|
||||||
parent_dotted_name, _ = split_of_last_part(dotted_name)
|
parent_dotted_name, _ = split_of_last_part(dotted_name)
|
||||||
sibling_dotted_names = namespace_tree[parent_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,
|
nav = self.build_navigation(parent_dotted_name,
|
||||||
sibling_dotted_names, dotted_name)
|
sibling_dotted_names, dotted_name)
|
||||||
reltargetpath = "api/%s.html" % (dotted_name,)
|
reltargetpath = "api/%s.html" % (dotted_name,)
|
||||||
|
@ -485,9 +497,14 @@ class ApiPageBuilder(AbstractPageBuilder):
|
||||||
|
|
||||||
names = namespace_tree.keys()
|
names = namespace_tree.keys()
|
||||||
names.sort()
|
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]
|
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,
|
nav = self.build_navigation(dotted_name, subitem_dotted_names,
|
||||||
dotted_name)
|
dotted_name)
|
||||||
if dotted_name == '':
|
if dotted_name == '':
|
||||||
|
@ -588,3 +605,42 @@ class ApiPageBuilder(AbstractPageBuilder):
|
||||||
def is_in_pkg(self, sourcefile):
|
def is_in_pkg(self, sourcefile):
|
||||||
return py.path.local(sourcefile).relto(self.projpath)
|
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)
|
_checkhtmlsnippet(html)
|
||||||
|
|
||||||
def test_build_class_pages(self):
|
def test_build_class_pages(self):
|
||||||
data, methodsdata = self.apb.prepare_class_pages(self.namespace_tree,
|
data = self.apb.prepare_class_pages(self.namespace_tree,
|
||||||
['main.SomeClass',
|
['main.SomeClass',
|
||||||
'main.SomeSubClass'])
|
'main.SomeSubClass'])
|
||||||
self.apb.build_class_pages(data, self.project)
|
self.apb.build_class_pages(data, self.project)
|
||||||
clsfile = self.base.join('api/main.SomeClass.html')
|
clsfile = self.base.join('api/main.SomeClass.html')
|
||||||
assert clsfile.check()
|
assert clsfile.check()
|
||||||
|
@ -173,10 +173,10 @@ class TestApiPageBuilder(AbstractBuilderTest):
|
||||||
_checkhtml(html)
|
_checkhtml(html)
|
||||||
|
|
||||||
def test_build_class_pages_instance(self):
|
def test_build_class_pages_instance(self):
|
||||||
data, methodsdata = self.apb.prepare_class_pages(self.namespace_tree,
|
data = self.apb.prepare_class_pages(self.namespace_tree,
|
||||||
['main.SomeClass',
|
['main.SomeClass',
|
||||||
'main.SomeSubClass',
|
'main.SomeSubClass',
|
||||||
'main.SomeInstance'])
|
'main.SomeInstance'])
|
||||||
self.apb.build_class_pages(data, self.project)
|
self.apb.build_class_pages(data, self.project)
|
||||||
clsfile = self.base.join('api/main.SomeInstance.html')
|
clsfile = self.base.join('api/main.SomeInstance.html')
|
||||||
assert clsfile.check()
|
assert clsfile.check()
|
||||||
|
@ -187,9 +187,9 @@ class TestApiPageBuilder(AbstractBuilderTest):
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_build_class_pages_nav_links(self):
|
def test_build_class_pages_nav_links(self):
|
||||||
data, methodsdata = self.apb.prepare_class_pages(self.namespace_tree,
|
data = self.apb.prepare_class_pages(self.namespace_tree,
|
||||||
['main.SomeSubClass',
|
['main.SomeSubClass',
|
||||||
'main.SomeClass'])
|
'main.SomeClass'])
|
||||||
# fake some stuff that would be built from other methods
|
# fake some stuff that would be built from other methods
|
||||||
self.linker.set_link('', 'api/index.html')
|
self.linker.set_link('', 'api/index.html')
|
||||||
self.linker.set_link('main', 'api/main.html')
|
self.linker.set_link('main', 'api/main.html')
|
||||||
|
@ -212,9 +212,9 @@ class TestApiPageBuilder(AbstractBuilderTest):
|
||||||
_checkhtml(html)
|
_checkhtml(html)
|
||||||
|
|
||||||
def test_build_class_pages_base_link(self):
|
def test_build_class_pages_base_link(self):
|
||||||
data, methodsdata = self.apb.prepare_class_pages(self.namespace_tree,
|
data = self.apb.prepare_class_pages(self.namespace_tree,
|
||||||
['main.SomeSubClass',
|
['main.SomeSubClass',
|
||||||
'main.SomeClass'])
|
'main.SomeClass'])
|
||||||
self.apb.build_class_pages(data, self.project)
|
self.apb.build_class_pages(data, self.project)
|
||||||
clsfile = self.base.join('api/main.SomeSubClass.html')
|
clsfile = self.base.join('api/main.SomeSubClass.html')
|
||||||
assert clsfile.check()
|
assert clsfile.check()
|
||||||
|
@ -227,9 +227,9 @@ class TestApiPageBuilder(AbstractBuilderTest):
|
||||||
_checkhtml(html)
|
_checkhtml(html)
|
||||||
|
|
||||||
def test_source_links(self):
|
def test_source_links(self):
|
||||||
data, methodsdata = self.apb.prepare_class_pages(self.namespace_tree,
|
data = self.apb.prepare_class_pages(self.namespace_tree,
|
||||||
['main.SomeSubClass',
|
['main.SomeSubClass',
|
||||||
'main.SomeClass'])
|
'main.SomeClass'])
|
||||||
sourcedata = self.spb.prepare_pages(self.fs_root)
|
sourcedata = self.spb.prepare_pages(self.fs_root)
|
||||||
self.apb.build_class_pages(data, self.project)
|
self.apb.build_class_pages(data, self.project)
|
||||||
self.spb.build_pages(sourcedata, self.project, self.fs_root)
|
self.spb.build_pages(sourcedata, self.project, self.fs_root)
|
||||||
|
|
|
@ -113,9 +113,9 @@ def test_apigen_functional():
|
||||||
html = sometestclass_source.read()
|
html = sometestclass_source.read()
|
||||||
assert '<div class="project_title">sources for sometestclass.py</div>' in html
|
assert '<div class="project_title">sources for sometestclass.py</div>' in html
|
||||||
|
|
||||||
# XXX later...
|
index = sourcedir.join('index.html')
|
||||||
#index = sourcedir.join('index.html')
|
assert index.check(file=True)
|
||||||
#assert index.check(file=True)
|
html = index.read()
|
||||||
#html = index.read()
|
print html
|
||||||
#assert '<a href="main/index.html">main</a>' in html
|
assert '<a href="test/index.html">test</a>' in html
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue