diff --git a/py/apigen/apigen.py b/py/apigen/apigen.py
index c86c27c61..d2953dcd3 100644
--- a/py/apigen/apigen.py
+++ b/py/apigen/apigen.py
@@ -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()
diff --git a/py/apigen/html.py b/py/apigen/html.py
index d522278e1..67becb66f 100644
--- a/py/apigen/html.py
+++ b/py/apigen/html.py
@@ -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')
diff --git a/py/apigen/htmlgen.py b/py/apigen/htmlgen.py
index 74fa25ac4..a8a6c8cc2 100644
--- a/py/apigen/htmlgen.py
+++ b/py/apigen/htmlgen.py
@@ -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
diff --git a/py/apigen/style.css b/py/apigen/style.css
index 991767005..71ee2631a 100644
--- a/py/apigen/style.css
+++ b/py/apigen/style.css
@@ -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;
diff --git a/py/apigen/testing/test_apigen_functional.py b/py/apigen/testing/test_apigen_functional.py
index 5945e94b3..6ba4b77cb 100644
--- a/py/apigen/testing/test_apigen_functional.py
+++ b/py/apigen/testing/test_apigen_functional.py
@@ -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
diff --git a/py/apigen/testing/test_htmlgen.py b/py/apigen/testing/test_htmlgen.py
index f1953f8d7..df6738f74 100644
--- a/py/apigen/testing/test_htmlgen.py
+++ b/py/apigen/testing/test_htmlgen.py
@@ -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 == ('
'
- ' 1: '
- 'def foo():\n'
- ' 2: '
- ' print'
- ' "bar"\n'
- '
')
+ print repr(div)
+ assert div == (u''
+ '
'
+ ''
+ '1 |
'
+ '2 |
'
+ ''
+ '
'
+ '
'
+ ''
+ ''
+ 'def foo():'
+ ' |
'
+ ''
+ ' print'
+ ' "bar"'
+ ' |
'
+ ''
+ '
'
+ '
')
+
+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''
+ '
'
+ ''
+ '1 |
'
+ '2 |
'
+ '3 |
'
+ ''
+ '
'
+ '
'
+ ''
+ ''
+ 'code = """\\'
+ ' |
'
+ ''
+ 'foo bar'
+ ' |
'
+ ''
+ '"""'
+ ' |
'
+ ''
+ '
'
+ '
')
def test_show_property():
assert htmlgen.show_property('foo')