[svn r38005] Made that source snippets are now shown in two tables, to allow selecting
the source without the line numbers, decreased font size a bit, made that the Page class can be passed in from the outside (build() method) to more easily allow customization of the layout and pages. --HG-- branch : trunk
This commit is contained in:
parent
410e00320d
commit
3690e384a9
|
@ -12,6 +12,8 @@ from py.__.apigen import linker
|
|||
from py.__.apigen import project
|
||||
from py.__.apigen.tracer.docstorage import pkg_to_dict
|
||||
|
||||
from layout import LayoutPage
|
||||
|
||||
def get_documentable_items_pkgdir(pkgdir):
|
||||
""" get all documentable items from an initpkg pkgdir
|
||||
|
||||
|
@ -31,20 +33,27 @@ def get_documentable_items(pkgdir):
|
|||
return pkgname, pkgdict
|
||||
|
||||
def build(pkgdir, dsa, capture):
|
||||
# create a linker (link database) for cross-linking
|
||||
l = linker.Linker()
|
||||
|
||||
# create a project.Project instance to contain the LayoutPage instances
|
||||
proj = project.Project()
|
||||
|
||||
# output dir
|
||||
if 'APIGEN_TARGET' in os.environ:
|
||||
targetdir = py.path.local(os.environ['APIGEN_TARGET'])
|
||||
else:
|
||||
targetdir = pkgdir.dirpath().join('apigen')
|
||||
targetdir.ensure(dir=True)
|
||||
|
||||
# find out what to build
|
||||
all_names = dsa._get_names(filter=lambda x, y: True)
|
||||
namespace_tree = htmlgen.create_namespace_tree(all_names)
|
||||
|
||||
# and build it
|
||||
apb = htmlgen.ApiPageBuilder(targetdir, l, dsa, pkgdir, namespace_tree,
|
||||
capture)
|
||||
spb = htmlgen.SourcePageBuilder(targetdir, l, pkgdir, capture)
|
||||
capture, LayoutPage)
|
||||
spb = htmlgen.SourcePageBuilder(targetdir, l, pkgdir, capture, LayoutPage)
|
||||
|
||||
capture.err.writeorg('preparing namespace pages\n')
|
||||
ns_data = apb.prepare_namespace_pages()
|
||||
|
|
|
@ -4,7 +4,8 @@ from py.xml import html
|
|||
# HTML related stuff
|
||||
class H(html):
|
||||
class Content(html.div):
|
||||
pass # style = html.Style(margin_left='15em')
|
||||
def __init__(self, *args):
|
||||
super(H.Content, self).__init__(id='apigen-content', *args)
|
||||
|
||||
class Description(html.div):
|
||||
pass
|
||||
|
@ -88,12 +89,29 @@ class H(html):
|
|||
if href:
|
||||
link = H.a(text, href=href)
|
||||
super(H.SourceSnippet, self).__init__(
|
||||
link, H.div(class_='code', *sourceels))
|
||||
link, H.div(*sourceels))
|
||||
|
||||
class SourceDef(html.div):
|
||||
def __init__(self, *sourceels):
|
||||
super(H.SourceDef, self).__init__(
|
||||
H.div(class_='code', *sourceels))
|
||||
H.div(*sourceels))
|
||||
|
||||
class SourceCode(html.div):
|
||||
style = html.Style(margin_top='1em', margin_bottom='1em')
|
||||
def __init__(self):
|
||||
self.linenotable = lntable = H.table(style='float: left')
|
||||
self.linenotbody = lntbody = H.tbody()
|
||||
lntable.append(lntbody)
|
||||
|
||||
self.linetable = ltable = H.table()
|
||||
self.linetbody = ltbody = H.tbody()
|
||||
ltable.append(ltbody)
|
||||
|
||||
super(H.SourceCode, self).__init__(lntable, ltable)
|
||||
|
||||
def add_line(self, lineno, els):
|
||||
self.linenotbody.append(H.tr(H.td(lineno, class_='lineno')))
|
||||
self.linetbody.append(H.tr(H.td(class_='code', *els)))
|
||||
|
||||
class NonPythonSource(html.pre):
|
||||
pass # style = html.Style(margin_left='15em')
|
||||
|
|
|
@ -115,32 +115,65 @@ def create_namespace_tree(dotted_names):
|
|||
ret[ns].append(itempath)
|
||||
return ret
|
||||
|
||||
def wrap_page(project, title, contentel, navel, relbase, basepath):
|
||||
page = LayoutPage(project, title, nav=navel, encoding='UTF-8',
|
||||
def wrap_page(project, title, contentel, navel, relbase, basepath,
|
||||
pageclass):
|
||||
page = pageclass(project, title, nav=navel, encoding='UTF-8',
|
||||
relpath=relbase)
|
||||
page.set_content(contentel)
|
||||
page.setup_scripts_styles(basepath)
|
||||
return page
|
||||
|
||||
def enumerate_and_color(codelines, firstlineno, enc):
|
||||
snippet = H.SourceCode()
|
||||
tokenizer = source_color.Tokenizer(source_color.PythonSchema)
|
||||
for i, line in enumerate(codelines):
|
||||
try:
|
||||
snippet.add_line(i + firstlineno + 1,
|
||||
source_html.prepare_line([line], tokenizer, enc))
|
||||
except py.error.ENOENT:
|
||||
# error reading source code, giving up
|
||||
snippet = org
|
||||
break
|
||||
return snippet
|
||||
|
||||
def get_obj(pkg, dotted_name):
|
||||
full_dotted_name = '%s.%s' % (pkg.__name__, dotted_name)
|
||||
if dotted_name == '':
|
||||
return pkg
|
||||
path = dotted_name.split('.')
|
||||
ret = pkg
|
||||
for item in path:
|
||||
marker = []
|
||||
ret = getattr(ret, item, marker)
|
||||
if ret is marker:
|
||||
raise NameError('can not access %s in %s' % (item,
|
||||
full_dotted_name))
|
||||
return ret
|
||||
|
||||
# the PageBuilder classes take care of producing the docs (using the stuff
|
||||
# above)
|
||||
class AbstractPageBuilder(object):
|
||||
pageclass = LayoutPage
|
||||
|
||||
def write_page(self, title, reltargetpath, project, tag, nav):
|
||||
targetpath = self.base.join(reltargetpath)
|
||||
relbase= relpath('%s%s' % (targetpath.dirpath(), targetpath.sep),
|
||||
self.base.strpath + '/')
|
||||
page = wrap_page(project, title, tag, nav, relbase, self.base)
|
||||
page = wrap_page(project, title, tag, nav, relbase, self.base,
|
||||
self.pageclass)
|
||||
content = self.linker.call_withbase(reltargetpath, page.unicode)
|
||||
targetpath.ensure()
|
||||
targetpath.write(content.encode("utf8"))
|
||||
|
||||
class SourcePageBuilder(AbstractPageBuilder):
|
||||
""" builds the html for a source docs page """
|
||||
def __init__(self, base, linker, projroot, capture=None):
|
||||
def __init__(self, base, linker, projroot, capture=None,
|
||||
pageclass=LayoutPage):
|
||||
self.base = base
|
||||
self.linker = linker
|
||||
self.projroot = projroot
|
||||
self.capture = capture
|
||||
self.pageclass = pageclass
|
||||
|
||||
def build_navigation(self, fspath):
|
||||
nav = H.Navigation(class_='sidebar')
|
||||
|
@ -191,7 +224,7 @@ class SourcePageBuilder(AbstractPageBuilder):
|
|||
source = fspath.read()
|
||||
sep = get_linesep(source)
|
||||
colored = enumerate_and_color(source.split(sep), 0, enc)
|
||||
tag = H.SourceDef(*colored)
|
||||
tag = H.SourceDef(colored)
|
||||
nav = self.build_navigation(fspath)
|
||||
return tag, nav
|
||||
|
||||
|
@ -260,38 +293,10 @@ class SourcePageBuilder(AbstractPageBuilder):
|
|||
'/')
|
||||
self.write_page(title, reltargetpath, project, tag, nav)
|
||||
|
||||
def enumerate_and_color(codelines, firstlineno, enc):
|
||||
tokenizer = source_color.Tokenizer(source_color.PythonSchema)
|
||||
colored = []
|
||||
for i, line in enumerate(codelines):
|
||||
try:
|
||||
colored.append(H.span('%04s: ' % (i + firstlineno + 1)))
|
||||
colored.append(source_html.prepare_line([line], tokenizer, enc))
|
||||
colored.append('\n')
|
||||
except py.error.ENOENT:
|
||||
# error reading source code, giving up
|
||||
colored = org
|
||||
break
|
||||
return colored
|
||||
|
||||
def get_obj(pkg, dotted_name):
|
||||
full_dotted_name = '%s.%s' % (pkg.__name__, dotted_name)
|
||||
if dotted_name == '':
|
||||
return pkg
|
||||
path = dotted_name.split('.')
|
||||
ret = pkg
|
||||
for item in path:
|
||||
marker = []
|
||||
ret = getattr(ret, item, marker)
|
||||
if ret is marker:
|
||||
raise NameError('can not access %s in %s' % (item,
|
||||
full_dotted_name))
|
||||
return ret
|
||||
|
||||
class ApiPageBuilder(AbstractPageBuilder):
|
||||
""" builds the html for an api docs page """
|
||||
def __init__(self, base, linker, dsa, projroot, namespace_tree,
|
||||
capture=None):
|
||||
capture=None, pageclass=LayoutPage):
|
||||
self.base = base
|
||||
self.linker = linker
|
||||
self.dsa = dsa
|
||||
|
@ -299,6 +304,7 @@ class ApiPageBuilder(AbstractPageBuilder):
|
|||
self.projpath = py.path.local(projroot)
|
||||
self.namespace_tree = namespace_tree
|
||||
self.capture = capture
|
||||
self.pageclass = pageclass
|
||||
|
||||
pkgname = self.dsa.get_module_name().split('/')[-1]
|
||||
self.pkg = __import__(pkgname)
|
||||
|
@ -327,7 +333,7 @@ class ApiPageBuilder(AbstractPageBuilder):
|
|||
firstlineno = func.func_code.co_firstlineno
|
||||
sep = get_linesep(callable_source)
|
||||
org = callable_source.split(sep)
|
||||
colored = enumerate_and_color(org, firstlineno, enc)
|
||||
colored = [enumerate_and_color(org, firstlineno, enc)]
|
||||
text = 'source: %s' % (sourcefile,)
|
||||
if is_in_pkg:
|
||||
href = self.linker.get_lazyhref(sourcefile)
|
||||
|
@ -657,11 +663,12 @@ class ApiPageBuilder(AbstractPageBuilder):
|
|||
else:
|
||||
enc = 'latin-1'
|
||||
sourcelink = H.div(linktext)
|
||||
colored = enumerate_and_color(mangled, frame.firstlineno, enc)
|
||||
colored = [enumerate_and_color(mangled,
|
||||
frame.firstlineno, enc)]
|
||||
else:
|
||||
sourcelink = H.div('source unknown (%s)' % (sourcefile,))
|
||||
colored = mangled[:]
|
||||
tbdiv.append(sourcelink)
|
||||
tbdiv.append(H.div(class_='code', *colored))
|
||||
tbdiv.append(H.div(*colored))
|
||||
return tbdiv
|
||||
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
#apigen-content {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
div.sidebar {
|
||||
font-family: Verdana, Helvetica, Arial, sans-serif;
|
||||
font-size: 0.9em;
|
||||
width: 155px;
|
||||
vertical-align: top;
|
||||
margin-top: 0.5em;
|
||||
|
|
|
@ -26,6 +26,14 @@ def setup_fs_project(name):
|
|||
def get_somevar(self):
|
||||
" get_somevar docstring "
|
||||
return self.somevar
|
||||
|
||||
def get_some_source(self):
|
||||
ret = py.code.Source('''\\
|
||||
def foo():
|
||||
return 'bar'
|
||||
''')
|
||||
return ret
|
||||
|
||||
"""))
|
||||
temp.ensure('pak/sometestsubclass.py').write(py.code.Source("""\
|
||||
from sometestclass import SomeTestClass
|
||||
|
|
|
@ -47,13 +47,54 @@ def test_enumerate_and_color():
|
|||
colored = htmlgen.enumerate_and_color(['def foo():', ' print "bar"'], 0,
|
||||
'ascii')
|
||||
div = py.xml.html.div(*colored).unicode(indent=0)
|
||||
assert div == ('<div>'
|
||||
'<span> 1: </span>'
|
||||
'<span class="alt_keyword">def</span> foo():\n'
|
||||
'<span> 2: </span>'
|
||||
' <span class="keyword">print</span>'
|
||||
' <span class="string">"bar"</span>\n'
|
||||
'</div>')
|
||||
print repr(div)
|
||||
assert div == (u'<div>'
|
||||
'<table style="float: left">'
|
||||
'<tbody>'
|
||||
'<tr><td class="lineno">1</td></tr>'
|
||||
'<tr><td class="lineno">2</td></tr>'
|
||||
'</tbody>'
|
||||
'</table>'
|
||||
'<table>'
|
||||
'<tbody>'
|
||||
'<tr><td class="code">'
|
||||
'<span class="alt_keyword">def</span> foo():'
|
||||
'</td></tr>'
|
||||
'<tr><td class="code">'
|
||||
' <span class="keyword">print</span>'
|
||||
' <span class="string">"bar"</span>'
|
||||
'</td></tr>'
|
||||
'</tbody>'
|
||||
'</table>'
|
||||
'</div>')
|
||||
|
||||
def test_enumerate_and_color_multiline():
|
||||
colored = htmlgen.enumerate_and_color(['code = """\\', 'foo bar', '"""'],
|
||||
0, 'ascii')
|
||||
div = py.xml.html.div(*colored).unicode(indent=0)
|
||||
print repr(div)
|
||||
assert div == (u'<div>'
|
||||
'<table style="float: left">'
|
||||
'<tbody>'
|
||||
'<tr><td class="lineno">1</td></tr>'
|
||||
'<tr><td class="lineno">2</td></tr>'
|
||||
'<tr><td class="lineno">3</td></tr>'
|
||||
'</tbody>'
|
||||
'</table>'
|
||||
'<table>'
|
||||
'<tbody>'
|
||||
'<tr><td class="code">'
|
||||
'code = <span class="string">"""\\</span>'
|
||||
'</td></tr>'
|
||||
'<tr><td class="code">'
|
||||
'<span class="string">foo bar</span>'
|
||||
'</td></tr>'
|
||||
'<tr><td class="code">'
|
||||
'<span class="string">"""</span>'
|
||||
'</td></tr>'
|
||||
'</tbody>'
|
||||
'</table>'
|
||||
'</div>')
|
||||
|
||||
def test_show_property():
|
||||
assert htmlgen.show_property('foo')
|
||||
|
|
Loading…
Reference in New Issue