[svn r38043] Changed the way the lazy linking is handled: instead of building the pages
and replacing the links all in memory, pages are now written to disk with temporary hrefs, which are replaced afterwards. --HG-- branch : trunk
This commit is contained in:
parent
b91e13d5df
commit
8ab4468b5c
|
@ -34,7 +34,7 @@ def get_documentable_items(pkgdir):
|
||||||
|
|
||||||
def build(pkgdir, dsa, capture):
|
def build(pkgdir, dsa, capture):
|
||||||
# create a linker (link database) for cross-linking
|
# create a linker (link database) for cross-linking
|
||||||
l = linker.Linker()
|
l = linker.TempLinker()
|
||||||
|
|
||||||
# create a project.Project instance to contain the LayoutPage instances
|
# create a project.Project instance to contain the LayoutPage instances
|
||||||
proj = project.Project()
|
proj = project.Project()
|
||||||
|
@ -52,27 +52,26 @@ def build(pkgdir, dsa, capture):
|
||||||
|
|
||||||
# and build it
|
# and build it
|
||||||
apb = htmlgen.ApiPageBuilder(targetdir, l, dsa, pkgdir, namespace_tree,
|
apb = htmlgen.ApiPageBuilder(targetdir, l, dsa, pkgdir, namespace_tree,
|
||||||
capture, LayoutPage)
|
proj, capture, LayoutPage)
|
||||||
spb = htmlgen.SourcePageBuilder(targetdir, l, pkgdir, capture, LayoutPage)
|
spb = htmlgen.SourcePageBuilder(targetdir, l, pkgdir, proj, capture,
|
||||||
|
LayoutPage)
|
||||||
capture.err.writeorg('preparing namespace pages\n')
|
|
||||||
ns_data = apb.prepare_namespace_pages()
|
|
||||||
capture.err.writeorg('preparing class pages\n')
|
|
||||||
class_names = dsa.get_class_names()
|
|
||||||
class_data = apb.prepare_class_pages(class_names)
|
|
||||||
capture.err.writeorg('preparing function pages\n')
|
|
||||||
function_names = dsa.get_function_names()
|
|
||||||
func_data = apb.prepare_function_pages(function_names)
|
|
||||||
capture.err.writeorg('preparing source pages\n')
|
|
||||||
source_data = spb.prepare_pages(pkgdir)
|
|
||||||
|
|
||||||
capture.err.writeorg('building namespace pages\n')
|
capture.err.writeorg('building namespace pages\n')
|
||||||
apb.build_namespace_pages(ns_data, proj)
|
apb.build_namespace_pages()
|
||||||
|
|
||||||
capture.err.writeorg('building class pages\n')
|
capture.err.writeorg('building class pages\n')
|
||||||
apb.build_class_pages(class_data, proj)
|
class_names = dsa.get_class_names()
|
||||||
|
apb.build_class_pages(class_names)
|
||||||
|
|
||||||
capture.err.writeorg('building function pages\n')
|
capture.err.writeorg('building function pages\n')
|
||||||
apb.build_function_pages(func_data, proj)
|
function_names = dsa.get_function_names()
|
||||||
|
apb.build_function_pages(function_names)
|
||||||
|
|
||||||
capture.err.writeorg('building source pages\n')
|
capture.err.writeorg('building source pages\n')
|
||||||
spb.build_pages(source_data, proj, pkgdir)
|
spb.build_pages(pkgdir)
|
||||||
|
|
||||||
|
capture.err.writeorg('replacing temporary links\n')
|
||||||
|
l.replace_dirpath(targetdir)
|
||||||
|
|
||||||
capture.err.writeorg('done building documentation\n')
|
capture.err.writeorg('done building documentation\n')
|
||||||
|
|
||||||
|
|
|
@ -128,6 +128,8 @@ class H(html):
|
||||||
super(H.SourceCode, self).__init__(lntable, ltable)
|
super(H.SourceCode, self).__init__(lntable, ltable)
|
||||||
|
|
||||||
def add_line(self, lineno, els):
|
def add_line(self, lineno, els):
|
||||||
|
if els == []:
|
||||||
|
els = [u'\xa0']
|
||||||
self.linenotbody.append(H.tr(H.td(lineno, class_='lineno')))
|
self.linenotbody.append(H.tr(H.td(lineno, class_='lineno')))
|
||||||
self.linetbody.append(H.tr(H.td(class_='code', *els)))
|
self.linetbody.append(H.tr(H.td(class_='code', *els)))
|
||||||
|
|
||||||
|
|
|
@ -155,23 +155,26 @@ def get_obj(pkg, dotted_name):
|
||||||
class AbstractPageBuilder(object):
|
class AbstractPageBuilder(object):
|
||||||
pageclass = LayoutPage
|
pageclass = LayoutPage
|
||||||
|
|
||||||
def write_page(self, title, reltargetpath, project, tag, nav):
|
def write_page(self, title, reltargetpath, tag, nav):
|
||||||
targetpath = self.base.join(reltargetpath)
|
targetpath = self.base.join(reltargetpath)
|
||||||
relbase= relpath('%s%s' % (targetpath.dirpath(), targetpath.sep),
|
relbase= relpath('%s%s' % (targetpath.dirpath(), targetpath.sep),
|
||||||
self.base.strpath + '/')
|
self.base.strpath + '/')
|
||||||
page = wrap_page(project, title, tag, nav, relbase, self.base,
|
page = wrap_page(self.project, title, tag, nav, relbase, self.base,
|
||||||
self.pageclass)
|
self.pageclass)
|
||||||
content = self.linker.call_withbase(reltargetpath, page.unicode)
|
# we write the page with _temporary_ hrefs here, need to be replaced
|
||||||
|
# from the TempLinker later
|
||||||
|
content = page.unicode()
|
||||||
targetpath.ensure()
|
targetpath.ensure()
|
||||||
targetpath.write(content.encode("utf8"))
|
targetpath.write(content.encode("utf8"))
|
||||||
|
|
||||||
class SourcePageBuilder(AbstractPageBuilder):
|
class SourcePageBuilder(AbstractPageBuilder):
|
||||||
""" builds the html for a source docs page """
|
""" builds the html for a source docs page """
|
||||||
def __init__(self, base, linker, projroot, capture=None,
|
def __init__(self, base, linker, projroot, project, capture=None,
|
||||||
pageclass=LayoutPage):
|
pageclass=LayoutPage):
|
||||||
self.base = base
|
self.base = base
|
||||||
self.linker = linker
|
self.linker = linker
|
||||||
self.projroot = projroot
|
self.projroot = projroot
|
||||||
|
self.project = project
|
||||||
self.capture = capture
|
self.capture = capture
|
||||||
self.pageclass = pageclass
|
self.pageclass = pageclass
|
||||||
|
|
||||||
|
@ -240,13 +243,11 @@ class SourcePageBuilder(AbstractPageBuilder):
|
||||||
try:
|
try:
|
||||||
tag = H.NonPythonSource(unicode(fspath.read(), 'utf-8'))
|
tag = H.NonPythonSource(unicode(fspath.read(), 'utf-8'))
|
||||||
except UnicodeError:
|
except UnicodeError:
|
||||||
# XXX we should fix non-ascii support here!!
|
|
||||||
tag = H.NonPythonSource('no source available (binary file?)')
|
tag = H.NonPythonSource('no source available (binary file?)')
|
||||||
nav = self.build_navigation(fspath)
|
nav = self.build_navigation(fspath)
|
||||||
return tag, nav
|
return tag, nav
|
||||||
|
|
||||||
def prepare_pages(self, base):
|
def build_pages(self, base):
|
||||||
passed = []
|
|
||||||
for fspath in [base] + list(base.visit()):
|
for fspath in [base] + list(base.visit()):
|
||||||
if fspath.ext in ['.pyc', '.pyo']:
|
if fspath.ext in ['.pyc', '.pyo']:
|
||||||
continue
|
continue
|
||||||
|
@ -264,38 +265,36 @@ class SourcePageBuilder(AbstractPageBuilder):
|
||||||
reloutputpath = reloutputpath.replace(os.path.sep, '/')
|
reloutputpath = reloutputpath.replace(os.path.sep, '/')
|
||||||
outputpath = self.base.join(reloutputpath)
|
outputpath = self.base.join(reloutputpath)
|
||||||
self.linker.set_link(str(fspath), reloutputpath)
|
self.linker.set_link(str(fspath), reloutputpath)
|
||||||
passed.append((fspath, outputpath))
|
self.build_page(fspath, outputpath, base)
|
||||||
return passed
|
|
||||||
|
|
||||||
def build_pages(self, data, project, base):
|
def build_page(self, fspath, outputpath, base):
|
||||||
""" build syntax-colored source views """
|
""" build syntax-colored source views """
|
||||||
for fspath, outputpath in data:
|
if fspath.check(ext='.py'):
|
||||||
if fspath.check(ext='.py'):
|
try:
|
||||||
try:
|
tag, nav = self.build_python_page(fspath)
|
||||||
tag, nav = self.build_python_page(fspath)
|
except (KeyboardInterrupt, SystemError):
|
||||||
except (KeyboardInterrupt, SystemError):
|
raise
|
||||||
raise
|
except: # XXX strange stuff going wrong at times... need to fix
|
||||||
except: # XXX strange stuff going wrong at times... need to fix
|
raise
|
||||||
raise
|
exc, e, tb = py.std.sys.exc_info()
|
||||||
exc, e, tb = py.std.sys.exc_info()
|
print '%s - %s' % (exc, e)
|
||||||
print '%s - %s' % (exc, e)
|
print
|
||||||
print
|
print ''.join(py.std.traceback.format_tb(tb))
|
||||||
print ''.join(py.std.traceback.format_tb(tb))
|
print '-' * 79
|
||||||
print '-' * 79
|
del tb
|
||||||
del tb
|
|
||||||
tag, nav = self.build_nonpython_page(fspath)
|
|
||||||
elif fspath.check(dir=True):
|
|
||||||
tag, nav = self.build_dir_page(fspath)
|
|
||||||
else:
|
|
||||||
tag, nav = self.build_nonpython_page(fspath)
|
tag, nav = self.build_nonpython_page(fspath)
|
||||||
title = 'sources for %s' % (fspath.basename,)
|
elif fspath.check(dir=True):
|
||||||
reltargetpath = outputpath.relto(self.base).replace(os.path.sep,
|
tag, nav = self.build_dir_page(fspath)
|
||||||
'/')
|
else:
|
||||||
self.write_page(title, reltargetpath, project, tag, nav)
|
tag, nav = self.build_nonpython_page(fspath)
|
||||||
|
title = 'sources for %s' % (fspath.basename,)
|
||||||
|
reltargetpath = outputpath.relto(self.base).replace(os.path.sep,
|
||||||
|
'/')
|
||||||
|
self.write_page(title, reltargetpath, tag, nav)
|
||||||
|
|
||||||
class ApiPageBuilder(AbstractPageBuilder):
|
class ApiPageBuilder(AbstractPageBuilder):
|
||||||
""" builds the html for an api docs page """
|
""" builds the html for an api docs page """
|
||||||
def __init__(self, base, linker, dsa, projroot, namespace_tree,
|
def __init__(self, base, linker, dsa, projroot, namespace_tree, project,
|
||||||
capture=None, pageclass=LayoutPage):
|
capture=None, pageclass=LayoutPage):
|
||||||
self.base = base
|
self.base = base
|
||||||
self.linker = linker
|
self.linker = linker
|
||||||
|
@ -303,6 +302,7 @@ class ApiPageBuilder(AbstractPageBuilder):
|
||||||
self.projroot = projroot
|
self.projroot = projroot
|
||||||
self.projpath = py.path.local(projroot)
|
self.projpath = py.path.local(projroot)
|
||||||
self.namespace_tree = namespace_tree
|
self.namespace_tree = namespace_tree
|
||||||
|
self.project = project
|
||||||
self.capture = capture
|
self.capture = capture
|
||||||
self.pageclass = pageclass
|
self.pageclass = pageclass
|
||||||
|
|
||||||
|
@ -440,11 +440,9 @@ class ApiPageBuilder(AbstractPageBuilder):
|
||||||
)
|
)
|
||||||
return snippet
|
return snippet
|
||||||
|
|
||||||
def prepare_class_pages(self, classes_dotted_names):
|
def build_class_pages(self, classes_dotted_names):
|
||||||
passed = []
|
passed = []
|
||||||
for dotted_name in sorted(classes_dotted_names):
|
for dotted_name in sorted(classes_dotted_names):
|
||||||
#if self.capture:
|
|
||||||
# self.capture.err.writeorg('preparing: %s\n' % (dotted_name,))
|
|
||||||
parent_dotted_name, _ = split_of_last_part(dotted_name)
|
parent_dotted_name, _ = split_of_last_part(dotted_name)
|
||||||
try:
|
try:
|
||||||
sibling_dotted_names = self.namespace_tree[parent_dotted_name]
|
sibling_dotted_names = self.namespace_tree[parent_dotted_name]
|
||||||
|
@ -455,42 +453,13 @@ class ApiPageBuilder(AbstractPageBuilder):
|
||||||
nav = self.build_navigation(dotted_name, False)
|
nav = self.build_navigation(dotted_name, False)
|
||||||
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))
|
title = 'api documentation for %s' % (dotted_name,)
|
||||||
|
self.write_page(title, reltargetpath, tag, nav)
|
||||||
return passed
|
return passed
|
||||||
|
|
||||||
def build_class_pages(self, data, project):
|
def build_function_pages(self, method_dotted_names):
|
||||||
""" build the full api pages for a set of classes """
|
|
||||||
for dotted_name, tag, nav, reltargetpath in data:
|
|
||||||
#if self.capture:
|
|
||||||
# self.capture.err.writeorg('building: %s\n' % (dotted_name,))
|
|
||||||
title = 'api documentation for %s' % (dotted_name,)
|
|
||||||
self.write_page(title, reltargetpath, project, tag, nav)
|
|
||||||
|
|
||||||
def prepare_method_pages(self, method_dotted_names):
|
|
||||||
# XXX note that even though these pages are still built, there's no nav
|
|
||||||
# pointing to them anymore...
|
|
||||||
passed = []
|
passed = []
|
||||||
for dotted_name in sorted(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 = self.namespace_tree[module_dotted_name]
|
|
||||||
tag = self.build_callable_view(dotted_name)
|
|
||||||
nav = self.build_navigation(dotted_name, False)
|
|
||||||
reltargetpath = "api/%s.html" % (dotted_name,)
|
|
||||||
self.linker.set_link(dotted_name, reltargetpath)
|
|
||||||
passed.append((dotted_name, tag, nav, reltargetpath))
|
|
||||||
return passed
|
|
||||||
|
|
||||||
def build_method_pages(self, data, project):
|
|
||||||
for dotted_name, tag, nav, reltargetpath in data:
|
|
||||||
title = 'api documentation for %s' % (dotted_name,)
|
|
||||||
self.write_page(title, reltargetpath, project, tag, nav)
|
|
||||||
|
|
||||||
def prepare_function_pages(self, method_dotted_names):
|
|
||||||
passed = []
|
|
||||||
for dotted_name in sorted(method_dotted_names):
|
|
||||||
#if self.capture:
|
|
||||||
# self.capture.err.writeorg('preparing: %s\n' % (dotted_name,))
|
|
||||||
# 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 = self.namespace_tree[parent_dotted_name]
|
sibling_dotted_names = self.namespace_tree[parent_dotted_name]
|
||||||
|
@ -498,17 +467,11 @@ class ApiPageBuilder(AbstractPageBuilder):
|
||||||
nav = self.build_navigation(dotted_name, False)
|
nav = self.build_navigation(dotted_name, False)
|
||||||
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))
|
title = 'api documentation for %s' % (dotted_name,)
|
||||||
|
self.write_page(title, reltargetpath, tag, nav)
|
||||||
return passed
|
return passed
|
||||||
|
|
||||||
def build_function_pages(self, data, project):
|
def build_namespace_pages(self):
|
||||||
for dotted_name, tag, nav, reltargetpath in data:
|
|
||||||
#if self.capture:
|
|
||||||
# self.capture.err.writeorg('building: %s\n' % (dotted_name,))
|
|
||||||
title = 'api documentation for %s' % (dotted_name,)
|
|
||||||
self.write_page(title, reltargetpath, project, tag, nav)
|
|
||||||
|
|
||||||
def prepare_namespace_pages(self):
|
|
||||||
passed = []
|
passed = []
|
||||||
module_name = self.dsa.get_module_name().split('/')[-1]
|
module_name = self.dsa.get_module_name().split('/')[-1]
|
||||||
|
|
||||||
|
@ -517,8 +480,6 @@ class ApiPageBuilder(AbstractPageBuilder):
|
||||||
function_names = self.dsa.get_function_names()
|
function_names = self.dsa.get_function_names()
|
||||||
class_names = self.dsa.get_class_names()
|
class_names = self.dsa.get_class_names()
|
||||||
for dotted_name in sorted(names):
|
for dotted_name in sorted(names):
|
||||||
#if self.capture:
|
|
||||||
# self.capture.err.writeorg('preparing: %s\n' % (dotted_name,))
|
|
||||||
if dotted_name in function_names or dotted_name in class_names:
|
if dotted_name in function_names or dotted_name in class_names:
|
||||||
continue
|
continue
|
||||||
subitem_dotted_names = self.namespace_tree[dotted_name]
|
subitem_dotted_names = self.namespace_tree[dotted_name]
|
||||||
|
@ -530,17 +491,11 @@ class ApiPageBuilder(AbstractPageBuilder):
|
||||||
else:
|
else:
|
||||||
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))
|
|
||||||
return passed
|
|
||||||
|
|
||||||
def build_namespace_pages(self, data, project):
|
|
||||||
for dotted_name, tag, nav, reltargetpath in data:
|
|
||||||
#if self.capture:
|
|
||||||
# self.capture.err.writeorg('building: %s\n' % (dotted_name,))
|
|
||||||
if dotted_name == '':
|
if dotted_name == '':
|
||||||
dotted_name = self.dsa.get_module_name().split('/')[-1]
|
dotted_name = self.dsa.get_module_name().split('/')[-1]
|
||||||
title = 'index of %s namespace' % (dotted_name,)
|
title = 'index of %s namespace' % (dotted_name,)
|
||||||
self.write_page(title, reltargetpath, project, tag, nav)
|
self.write_page(title, reltargetpath, tag, nav)
|
||||||
|
return passed
|
||||||
|
|
||||||
def build_navigation(self, dotted_name, build_children=True):
|
def build_navigation(self, dotted_name, build_children=True):
|
||||||
navitems = []
|
navitems = []
|
||||||
|
|
|
@ -42,6 +42,57 @@ class Linker(object):
|
||||||
finally:
|
finally:
|
||||||
del self.fromlocation
|
del self.fromlocation
|
||||||
|
|
||||||
|
class TempLinker(object):
|
||||||
|
""" performs a similar role to the Linker, but with a different approach
|
||||||
|
|
||||||
|
instead of returning 'lazy' hrefs, this returns a simple URL-style
|
||||||
|
string
|
||||||
|
|
||||||
|
the 'temporary urls' are replaced on the filesystem after building the
|
||||||
|
files, so that means even though a second pass is still required,
|
||||||
|
things don't have to be built in-memory (as with the Linker)
|
||||||
|
"""
|
||||||
|
fromlocation = None
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self._linkid2target = {}
|
||||||
|
|
||||||
|
def get_lazyhref(self, linkid):
|
||||||
|
return 'apigen.linker://%s' % (linkid,)
|
||||||
|
|
||||||
|
def set_link(self, linkid, target):
|
||||||
|
assert linkid not in self._linkid2target
|
||||||
|
self._linkid2target[linkid] = target
|
||||||
|
|
||||||
|
def get_target(self, tempurl, fromlocation=None):
|
||||||
|
linkid = '://'.join(tempurl.split('://')[1:])
|
||||||
|
linktarget = self._linkid2target[linkid]
|
||||||
|
if fromlocation is not None:
|
||||||
|
linktarget = relpath(fromlocation, linktarget)
|
||||||
|
return linktarget
|
||||||
|
|
||||||
|
_reg_tempurl = py.std.re.compile('"(apigen.linker:\/\/[^"\s]*)"')
|
||||||
|
def replace_dirpath(self, dirpath, stoponerrors=True):
|
||||||
|
""" replace temporary links in all html files in dirpath and below """
|
||||||
|
for fpath in dirpath.visit('*.html'):
|
||||||
|
html = fpath.read()
|
||||||
|
while 1:
|
||||||
|
match = self._reg_tempurl.search(html)
|
||||||
|
if not match:
|
||||||
|
break
|
||||||
|
tempurl = match.group(1)
|
||||||
|
try:
|
||||||
|
html = html.replace('"' + tempurl + '"',
|
||||||
|
'"' + self.get_target(tempurl,
|
||||||
|
fpath.relto(dirpath)) + '"')
|
||||||
|
except KeyError:
|
||||||
|
if stoponerrors:
|
||||||
|
raise
|
||||||
|
html = html.replace('"' + tempurl + '"',
|
||||||
|
'"apigen.notfound://%s"' % (tempurl,))
|
||||||
|
fpath.write(html)
|
||||||
|
|
||||||
|
|
||||||
def relpath(p1, p2, sep=os.path.sep, back='..', normalize=True):
|
def relpath(p1, p2, sep=os.path.sep, back='..', normalize=True):
|
||||||
""" create a relative path from p1 to p2
|
""" create a relative path from p1 to p2
|
||||||
|
|
||||||
|
|
|
@ -89,3 +89,10 @@ ul li {
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
td.lineno {
|
||||||
|
line-height: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.code {
|
||||||
|
line-height: 1.1em;
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
# -*- coding: UTF-8 -*-
|
||||||
import py
|
import py
|
||||||
html = py.xml.html
|
html = py.xml.html
|
||||||
from py.__.apigen.linker import Linker
|
from py.__.apigen.linker import TempLinker
|
||||||
from py.__.apigen.htmlgen import *
|
from py.__.apigen.htmlgen import *
|
||||||
from py.__.apigen.tracer.docstorage import DocStorage, DocStorageAccessor
|
from py.__.apigen.tracer.docstorage import DocStorage, DocStorageAccessor
|
||||||
from py.__.apigen.tracer.tracer import Tracer
|
from py.__.apigen.tracer.tracer import Tracer
|
||||||
|
@ -96,15 +97,9 @@ class AbstractBuilderTest(object):
|
||||||
cls.project = Project()
|
cls.project = Project()
|
||||||
|
|
||||||
def setup_method(self, meth):
|
def setup_method(self, meth):
|
||||||
class LinkerForTests(Linker):
|
|
||||||
def get_target(self, linkid):
|
|
||||||
try:
|
|
||||||
return super(LinkerForTests, self).get_target(linkid)
|
|
||||||
except KeyError:
|
|
||||||
return 'unknown_link_%s' % (linkid,)
|
|
||||||
self.base = base = py.test.ensuretemp('%s_%s' % (
|
self.base = base = py.test.ensuretemp('%s_%s' % (
|
||||||
self.__class__.__name__, meth.im_func.func_name))
|
self.__class__.__name__, meth.im_func.func_name))
|
||||||
self.linker = linker = LinkerForTests()
|
self.linker = linker = TempLinker()
|
||||||
namespace_tree = create_namespace_tree(['main.sub',
|
namespace_tree = create_namespace_tree(['main.sub',
|
||||||
'main.sub.func',
|
'main.sub.func',
|
||||||
'main.SomeClass',
|
'main.SomeClass',
|
||||||
|
@ -116,9 +111,10 @@ class AbstractBuilderTest(object):
|
||||||
self.namespace_tree = namespace_tree
|
self.namespace_tree = namespace_tree
|
||||||
self.apb = ApiPageBuilder(base, linker, self.dsa,
|
self.apb = ApiPageBuilder(base, linker, self.dsa,
|
||||||
self.fs_root.join(self.pkg_name),
|
self.fs_root.join(self.pkg_name),
|
||||||
namespace_tree)
|
namespace_tree, self.project)
|
||||||
self.spb = SourcePageBuilder(base, linker,
|
self.spb = SourcePageBuilder(base, linker,
|
||||||
self.fs_root.join(self.pkg_name))
|
self.fs_root.join(self.pkg_name),
|
||||||
|
self.project)
|
||||||
|
|
||||||
class TestApiPageBuilder(AbstractBuilderTest):
|
class TestApiPageBuilder(AbstractBuilderTest):
|
||||||
def test_build_callable_view(self):
|
def test_build_callable_view(self):
|
||||||
|
@ -156,8 +152,7 @@ class TestApiPageBuilder(AbstractBuilderTest):
|
||||||
_checkhtmlsnippet(html)
|
_checkhtmlsnippet(html)
|
||||||
|
|
||||||
def test_build_function_pages(self):
|
def test_build_function_pages(self):
|
||||||
data = self.apb.prepare_function_pages(['main.sub.func'])
|
self.apb.build_function_pages(['main.sub.func'])
|
||||||
self.apb.build_function_pages(data, self.project)
|
|
||||||
funcfile = self.base.join('api/main.sub.func.html')
|
funcfile = self.base.join('api/main.sub.func.html')
|
||||||
assert funcfile.check()
|
assert funcfile.check()
|
||||||
html = funcfile.read()
|
html = funcfile.read()
|
||||||
|
@ -169,19 +164,16 @@ class TestApiPageBuilder(AbstractBuilderTest):
|
||||||
_checkhtmlsnippet(html)
|
_checkhtmlsnippet(html)
|
||||||
|
|
||||||
def test_build_class_pages(self):
|
def test_build_class_pages(self):
|
||||||
data = self.apb.prepare_class_pages(['main.SomeClass',
|
self.apb.build_class_pages(['main.SomeClass', 'main.SomeSubClass'])
|
||||||
'main.SomeSubClass'])
|
|
||||||
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()
|
||||||
html = clsfile.read()
|
html = clsfile.read()
|
||||||
_checkhtml(html)
|
_checkhtml(html)
|
||||||
|
|
||||||
def test_build_class_pages_instance(self):
|
def test_build_class_pages_instance(self):
|
||||||
data = self.apb.prepare_class_pages(['main.SomeClass',
|
self.apb.build_class_pages(['main.SomeClass',
|
||||||
'main.SomeSubClass',
|
'main.SomeSubClass',
|
||||||
'main.SomeInstance'])
|
'main.SomeInstance'])
|
||||||
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()
|
||||||
html = clsfile.read()
|
html = clsfile.read()
|
||||||
|
@ -191,13 +183,11 @@ class TestApiPageBuilder(AbstractBuilderTest):
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_build_class_pages_nav_links(self):
|
def test_build_class_pages_nav_links(self):
|
||||||
data = self.apb.prepare_class_pages(['main.SomeSubClass',
|
self.apb.build_class_pages(['main.SomeSubClass',
|
||||||
'main.SomeClass'])
|
'main.SomeClass'])
|
||||||
self.apb.prepare_namespace_pages()
|
self.apb.build_namespace_pages()
|
||||||
# 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.replace_dirpath(self.base, False)
|
||||||
self.linker.set_link('main', 'api/main.html')
|
|
||||||
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()
|
||||||
html = clsfile.read()
|
html = clsfile.read()
|
||||||
|
@ -217,9 +207,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 = self.apb.prepare_class_pages(['main.SomeSubClass',
|
self.apb.build_class_pages(['main.SomeSubClass',
|
||||||
'main.SomeClass'])
|
'main.SomeClass'])
|
||||||
self.apb.build_class_pages(data, self.project)
|
self.linker.replace_dirpath(self.base, False)
|
||||||
clsfile = self.base.join('api/main.SomeSubClass.html')
|
clsfile = self.base.join('api/main.SomeSubClass.html')
|
||||||
assert clsfile.check()
|
assert clsfile.check()
|
||||||
html = clsfile.read()
|
html = clsfile.read()
|
||||||
|
@ -231,18 +221,15 @@ class TestApiPageBuilder(AbstractBuilderTest):
|
||||||
_checkhtml(html)
|
_checkhtml(html)
|
||||||
|
|
||||||
def test_source_links(self):
|
def test_source_links(self):
|
||||||
data = self.apb.prepare_class_pages(['main.SomeSubClass',
|
self.apb.build_class_pages(['main.SomeSubClass', 'main.SomeClass'])
|
||||||
'main.SomeClass'])
|
self.spb.build_pages(self.fs_root)
|
||||||
sourcedata = self.spb.prepare_pages(self.fs_root)
|
self.linker.replace_dirpath(self.base, False)
|
||||||
self.apb.build_class_pages(data, self.project)
|
|
||||||
self.spb.build_pages(sourcedata, self.project, self.fs_root)
|
|
||||||
funchtml = self.base.join('api/main.SomeClass.html').read()
|
funchtml = self.base.join('api/main.SomeClass.html').read()
|
||||||
assert funchtml.find('href="../source/pkg/someclass.py.html"') > -1
|
assert funchtml.find('href="../source/pkg/someclass.py.html"') > -1
|
||||||
_checkhtml(funchtml)
|
_checkhtml(funchtml)
|
||||||
|
|
||||||
def test_build_namespace_pages(self):
|
def test_build_namespace_pages(self):
|
||||||
data = self.apb.prepare_namespace_pages()
|
self.apb.build_namespace_pages()
|
||||||
self.apb.build_namespace_pages(data, self.project)
|
|
||||||
mainfile = self.base.join('api/main.html')
|
mainfile = self.base.join('api/main.html')
|
||||||
assert mainfile.check()
|
assert mainfile.check()
|
||||||
html = mainfile.read()
|
html = mainfile.read()
|
||||||
|
@ -261,8 +248,7 @@ class TestApiPageBuilder(AbstractBuilderTest):
|
||||||
_checkhtml(otherhtml)
|
_checkhtml(otherhtml)
|
||||||
|
|
||||||
def test_build_namespace_pages_index(self):
|
def test_build_namespace_pages_index(self):
|
||||||
data = self.apb.prepare_namespace_pages()
|
self.apb.build_namespace_pages()
|
||||||
self.apb.build_namespace_pages(data, self.project)
|
|
||||||
pkgfile = self.base.join('api/index.html')
|
pkgfile = self.base.join('api/index.html')
|
||||||
assert pkgfile.check()
|
assert pkgfile.check()
|
||||||
html = pkgfile.read()
|
html = pkgfile.read()
|
||||||
|
@ -270,19 +256,18 @@ class TestApiPageBuilder(AbstractBuilderTest):
|
||||||
_checkhtml(html)
|
_checkhtml(html)
|
||||||
|
|
||||||
def test_build_namespace_pages_subnamespace(self):
|
def test_build_namespace_pages_subnamespace(self):
|
||||||
data = self.apb.prepare_namespace_pages()
|
self.apb.build_namespace_pages()
|
||||||
self.apb.build_namespace_pages(data, self.project)
|
|
||||||
subfile = self.base.join('api/main.sub.html')
|
subfile = self.base.join('api/main.sub.html')
|
||||||
assert subfile.check()
|
assert subfile.check()
|
||||||
html = subfile.read()
|
html = subfile.read()
|
||||||
_checkhtml(html)
|
_checkhtml(html)
|
||||||
|
|
||||||
def test_build_function_api_pages_nav(self):
|
def test_build_function_api_pages_nav(self):
|
||||||
data = self.apb.prepare_function_pages(['main.sub.func'])
|
self.linker.set_link('main.sub', 'api/main.sub.html')
|
||||||
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')
|
||||||
self.linker.set_link('main.sub', 'api/main.sub.html')
|
self.apb.build_function_pages(['main.sub.func'])
|
||||||
self.apb.build_function_pages(data, self.project)
|
self.linker.replace_dirpath(self.base, False)
|
||||||
funcfile = self.base.join('api/main.sub.func.html')
|
funcfile = self.base.join('api/main.sub.func.html')
|
||||||
html = funcfile.read()
|
html = funcfile.read()
|
||||||
print html
|
print html
|
||||||
|
@ -295,31 +280,32 @@ class TestApiPageBuilder(AbstractBuilderTest):
|
||||||
_checkhtml(html)
|
_checkhtml(html)
|
||||||
|
|
||||||
def test_build_function_navigation(self):
|
def test_build_function_navigation(self):
|
||||||
self.apb.prepare_namespace_pages()
|
self.apb.build_namespace_pages()
|
||||||
self.apb.prepare_function_pages(['main.sub.func'])
|
self.apb.build_function_pages(['main.sub.func'])
|
||||||
self.apb.prepare_class_pages(['main.SomeClass',
|
self.apb.build_class_pages(['main.SomeClass',
|
||||||
'main.SomeSubClass',
|
'main.SomeSubClass',
|
||||||
'main.SomeInstance'])
|
'main.SomeInstance'])
|
||||||
nav = self.apb.build_navigation('main.sub.func', False)
|
self.linker.replace_dirpath(self.base, False)
|
||||||
html = nav.unicode(indent=0)
|
html = self.base.join('api/main.sub.func.html').read()
|
||||||
print html.encode('UTF-8')
|
print html
|
||||||
assert (u'<div class="selected"><a href="api/index.html">pkg</a></div>'
|
# XXX NOTE: do not mess with the string below, the spaces between the
|
||||||
u'<div class="selected">\xa0\xa0<a href="api/main.html">main</a></div>'
|
# <div> and <a> are actually UTF-8 \xa0 characters (non-breaking
|
||||||
u'<div>\xa0\xa0\xa0\xa0<a href="api/main.SomeClass.html">'
|
# spaces)!
|
||||||
u'SomeClass</a></div>'
|
assert """\
|
||||||
u'<div>\xa0\xa0\xa0\xa0<a href="api/main.SomeInstance.html">'
|
<div class="sidebar">
|
||||||
u'SomeInstance</a></div>'
|
<div class="selected"><a href="index.html">pkg</a></div>
|
||||||
u'<div>\xa0\xa0\xa0\xa0<a href="api/main.SomeSubClass.html">'
|
<div class="selected"> <a href="main.html">main</a></div>
|
||||||
u'SomeSubClass</a></div>'
|
<div> <a href="main.SomeClass.html">SomeClass</a></div>
|
||||||
u'<div class="selected">\xa0\xa0\xa0\xa0'
|
<div> <a href="main.SomeInstance.html">SomeInstance</a></div>
|
||||||
u'<a href="api/main.sub.html">sub</a></div>'
|
<div> <a href="main.SomeSubClass.html">SomeSubClass</a></div>
|
||||||
u'<div class="selected">\xa0\xa0\xa0\xa0\xa0\xa0'
|
<div class="selected"> <a href="main.sub.html">sub</a></div>
|
||||||
u'<a href="api/main.sub.func.html">func</a></div>'
|
<div class="selected"> <a href="main.sub.func.html">func</a></div>
|
||||||
) in html
|
<div> <a href="other.html">other</a></div></div>
|
||||||
|
""" in html
|
||||||
|
|
||||||
def test_build_root_namespace_view(self):
|
def test_build_root_namespace_view(self):
|
||||||
data = self.apb.prepare_namespace_pages()
|
self.apb.build_namespace_pages()
|
||||||
self.apb.build_namespace_pages(data, self.project)
|
self.linker.replace_dirpath(self.base, False)
|
||||||
rootfile = self.base.join('api/index.html')
|
rootfile = self.base.join('api/index.html')
|
||||||
assert rootfile.check()
|
assert rootfile.check()
|
||||||
html = rootfile.read()
|
html = rootfile.read()
|
||||||
|
@ -328,14 +314,13 @@ class TestApiPageBuilder(AbstractBuilderTest):
|
||||||
|
|
||||||
class TestSourcePageBuilder(AbstractBuilderTest):
|
class TestSourcePageBuilder(AbstractBuilderTest):
|
||||||
def test_build_pages(self):
|
def test_build_pages(self):
|
||||||
data = self.spb.prepare_pages(self.fs_root)
|
self.spb.build_pages(self.fs_root)
|
||||||
self.spb.build_pages(data, self.project, self.fs_root)
|
|
||||||
somesource = self.base.join('source/pkg/func.py.html').read()
|
somesource = self.base.join('source/pkg/func.py.html').read()
|
||||||
_checkhtml(somesource)
|
_checkhtml(somesource)
|
||||||
|
|
||||||
def test_build_pages_nav(self):
|
def test_build_pages_nav(self):
|
||||||
data = self.spb.prepare_pages(self.fs_root)
|
self.spb.build_pages(self.fs_root)
|
||||||
self.spb.build_pages(data, self.project, self.fs_root)
|
self.linker.replace_dirpath(self.base, False)
|
||||||
funcsource = self.base.join('source/pkg/func.py.html')
|
funcsource = self.base.join('source/pkg/func.py.html')
|
||||||
assert funcsource.check(file=True)
|
assert funcsource.check(file=True)
|
||||||
html = funcsource.read()
|
html = funcsource.read()
|
||||||
|
@ -348,8 +333,8 @@ class TestSourcePageBuilder(AbstractBuilderTest):
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_build_dir_page(self):
|
def test_build_dir_page(self):
|
||||||
data = self.spb.prepare_pages(self.fs_root)
|
self.spb.build_pages(self.fs_root)
|
||||||
self.spb.build_pages(data, self.project, self.fs_root)
|
self.linker.replace_dirpath(self.base, False)
|
||||||
pkgindex = self.base.join('source/pkg/index.html')
|
pkgindex = self.base.join('source/pkg/index.html')
|
||||||
assert pkgindex.check(file=True)
|
assert pkgindex.check(file=True)
|
||||||
html = pkgindex.read()
|
html = pkgindex.read()
|
||||||
|
@ -365,8 +350,8 @@ class TestSourcePageBuilder(AbstractBuilderTest):
|
||||||
_checkhtml(html)
|
_checkhtml(html)
|
||||||
|
|
||||||
def test_build_source_page(self):
|
def test_build_source_page(self):
|
||||||
data = self.spb.prepare_pages(self.fs_root)
|
self.spb.build_pages(self.fs_root)
|
||||||
self.spb.build_pages(data, self.project, self.fs_root)
|
self.linker.replace_dirpath(self.base, False)
|
||||||
funcsource = self.base.join('source/pkg/func.py.html')
|
funcsource = self.base.join('source/pkg/func.py.html')
|
||||||
assert funcsource.check(file=True)
|
assert funcsource.check(file=True)
|
||||||
html = funcsource.read()
|
html = funcsource.read()
|
||||||
|
@ -374,14 +359,14 @@ class TestSourcePageBuilder(AbstractBuilderTest):
|
||||||
assert ('<span class="alt_keyword">def</span> func(arg1)') in html
|
assert ('<span class="alt_keyword">def</span> func(arg1)') in html
|
||||||
|
|
||||||
def test_build_navigation_root(self):
|
def test_build_navigation_root(self):
|
||||||
self.spb.prepare_pages(self.fs_root)
|
self.spb.build_pages(self.fs_root)
|
||||||
nav = self.spb.build_navigation(self.fs_root.join('pkg'))
|
self.linker.replace_dirpath(self.base)
|
||||||
html = nav.unicode(indent=0)
|
html = self.base.join('source/pkg/index.html').read()
|
||||||
print html.encode('UTF-8')
|
print html
|
||||||
run_string_sequence_test(html, [
|
run_string_sequence_test(html, [
|
||||||
'href="source/pkg/index.html">pkg',
|
'href="index.html">pkg',
|
||||||
'href="source/pkg/func.py.html">func.py',
|
'href="func.py.html">func.py',
|
||||||
'href="source/pkg/someclass.py.html">someclass.py',
|
'href="someclass.py.html">someclass.py',
|
||||||
'href="source/pkg/somesubclass.py.html">somesubclass.py',
|
'href="somesubclass.py.html">somesubclass.py',
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import py
|
import py
|
||||||
from py.__.apigen.linker import Linker, getrelfspath, relpath
|
from py.__.apigen.linker import Linker, TempLinker, getrelfspath, relpath
|
||||||
|
|
||||||
class TestLinker(object):
|
class TestLinker(object):
|
||||||
def test_get_target(self):
|
def test_get_target(self):
|
||||||
|
@ -29,6 +29,24 @@ testspec = [
|
||||||
'c:\\foo\\bar c:\\foo ../foo \\',
|
'c:\\foo\\bar c:\\foo ../foo \\',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
class TestTempLinker(object):
|
||||||
|
def test_get_target(self):
|
||||||
|
linker = TempLinker()
|
||||||
|
temphref = linker.get_lazyhref('py.path.local')
|
||||||
|
linker.set_link('py.path.local', 'py/path/local.html')
|
||||||
|
relpath = linker.get_target(temphref)
|
||||||
|
assert relpath == 'py/path/local.html'
|
||||||
|
|
||||||
|
def test_functional(self):
|
||||||
|
temp = py.test.ensuretemp('TestTempLinker.test_functional')
|
||||||
|
l = TempLinker()
|
||||||
|
bar = temp.ensure('foo/bar.html', file=True)
|
||||||
|
baz = temp.ensure('foo/baz.html', file=True)
|
||||||
|
l.set_link(baz.strpath, baz.relto(temp))
|
||||||
|
bar.write('<a href="%s">baz</a>' % (l.get_lazyhref(baz.strpath),))
|
||||||
|
l.replace_dirpath(temp)
|
||||||
|
assert bar.read() == '<a href="baz.html">baz</a>'
|
||||||
|
|
||||||
def gen_check(frompath, topath, sep, expected):
|
def gen_check(frompath, topath, sep, expected):
|
||||||
result = relpath(frompath, topath, sep=sep)
|
result = relpath(frompath, topath, sep=sep)
|
||||||
assert result == expected
|
assert result == expected
|
||||||
|
|
Loading…
Reference in New Issue