[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:
guido 2007-02-06 14:19:16 +01:00
parent 410e00320d
commit 3690e384a9
6 changed files with 137 additions and 49 deletions

View File

@ -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()

View File

@ -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')

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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">&quot;bar&quot;</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">&quot;bar&quot;</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">&quot;&quot;&quot;\\</span>'
'</td></tr>'
'<tr><td class="code">'
'<span class="string">foo bar</span>'
'</td></tr>'
'<tr><td class="code">'
'<span class="string">&quot;&quot;&quot;</span>'
'</td></tr>'
'</tbody>'
'</table>'
'</div>')
def test_show_property():
assert htmlgen.show_property('foo')