diff --git a/py/apigen/htmlgen.py b/py/apigen/htmlgen.py
index 4e0edfa3e..15a447e48 100644
--- a/py/apigen/htmlgen.py
+++ b/py/apigen/htmlgen.py
@@ -311,9 +311,25 @@ class SourcePageBuilder(AbstractPageBuilder):
else:
tag, nav = self.build_nonpython_page(fspath)
title = 'sources for %s' % (fspath.basename,)
+ rev = self.get_revision(fspath)
+ if rev:
+ title += ' [rev. %s]' % (rev,)
reltargetpath = outputpath.relto(self.base).replace(os.path.sep,
'/')
self.write_page(title, reltargetpath, tag, nav)
+
+ _revcache = {}
+ def get_revision(self, path):
+ strpath = path.strpath
+ if strpath in self._revcache:
+ return self._revcache[strpath]
+ wc = py.path.svnwc(path)
+ if wc.check(versioned=True):
+ rev = wc.info().created_rev
+ else:
+ rev = None
+ self._revcache[strpath] = rev
+ return rev
class ApiPageBuilder(AbstractPageBuilder):
""" builds the html for an api docs page """
@@ -528,9 +544,13 @@ class ApiPageBuilder(AbstractPageBuilder):
else:
reltargetpath = 'api/%s.html' % (dotted_name,)
self.linker.set_link(dotted_name, reltargetpath)
+ title_name = dotted_name
if dotted_name == '':
- dotted_name = self.dsa.get_module_name().split('/')[-1]
- title = 'index of %s namespace' % (dotted_name,)
+ title_name = self.dsa.get_module_name()
+ title = 'index of %s' % (title_name,)
+ rev = self.get_revision(dotted_name)
+ if rev:
+ title += ' [rev. %s]' % (rev,)
self.write_page(title, reltargetpath, tag, nav)
return passed
@@ -697,18 +717,35 @@ class ApiPageBuilder(AbstractPageBuilder):
obj = get_obj(self.dsa, self.pkg, dotted_name)
return getattr(obj, '__apigen_hide_from_nav__', False)
+ _revcache = {}
+ def get_proj_revision(self):
+ if '' in self._revcache:
+ return self._revcache['']
+ wc = py.path.svnwc(self.projpath)
+ if wc.check(versioned=True):
+ rev = wc.info().created_rev
+ else:
+ rev = None
+ self._revcache[''] = rev
+ return rev
+
def get_revision(self, dotted_name):
+ if dotted_name in self._revcache:
+ return self._revcache[dotted_name]
obj = get_obj(self.dsa, self.pkg, dotted_name)
+ rev = None
try:
sourcefile = inspect.getsourcefile(obj)
except TypeError:
- return None
- if sourcefile is None:
- return None
- if sourcefile[-1] in ['o', 'c']:
- sourcefile = sourcefile[:-1]
- wc = py.path.svnwc(sourcefile)
- if wc.check(versioned=True):
- return wc.status().rev
- return None
+ pass
+ else:
+ if sourcefile is not None:
+ if sourcefile[-1] in ['o', 'c']:
+ sourcefile = sourcefile[:-1]
+ wc = py.path.svnwc(sourcefile)
+ if wc.check(versioned=True):
+ rev = wc.info().created_rev
+ rev = rev or self.get_proj_revision()
+ self._revcache[dotted_name] = rev
+ return rev
diff --git a/py/apigen/testing/test_apigen_example.py b/py/apigen/testing/test_apigen_example.py
index af5851e8b..8f62db8c9 100644
--- a/py/apigen/testing/test_apigen_example.py
+++ b/py/apigen/testing/test_apigen_example.py
@@ -8,6 +8,7 @@ from py.__.apigen.tracer.tracer import Tracer
from py.__.apigen.project import Project
from py.__.test.web import webcheck
from py.__.apigen.conftest import option
+from py.__.path.svn.testing.svntestbase import make_test_repo
def run_string_sequence_test(data, seq):
currpos = -1
@@ -21,8 +22,7 @@ def run_string_sequence_test(data, seq):
py.test.fail('string %r: %s' % (s, message))
currpos = newpos
-def setup_fs_project():
- temp = py.test.ensuretemp('apigen_example')
+def setup_fs_project(temp):
temp.ensure("pkg/func.py").write(py.code.Source("""\
def func(arg1):
"docstring"
@@ -96,7 +96,8 @@ def _checkhtmlsnippet(htmlstring):
class AbstractBuilderTest(object):
def setup_class(cls):
- cls.fs_root, cls.pkg_name = setup_fs_project()
+ temp = py.test.ensuretemp('apigen_example')
+ cls.fs_root, cls.pkg_name = setup_fs_project(temp)
cls.ds, cls.dsa = get_dsa(cls.fs_root, cls.pkg_name)
cls.project = Project()
@@ -240,14 +241,14 @@ class TestApiPageBuilder(AbstractBuilderTest):
html = mainfile.read()
print html
run_string_sequence_test(html, [
- 'index of main namespace',
+ 'index of main',
])
otherfile = self.base.join('api/other.html')
assert otherfile.check()
otherhtml = otherfile.read()
print otherhtml
run_string_sequence_test(otherhtml, [
- 'index of other namespace',
+ 'index of other',
])
_checkhtml(html)
_checkhtml(otherhtml)
@@ -257,7 +258,7 @@ class TestApiPageBuilder(AbstractBuilderTest):
pkgfile = self.base.join('api/index.html')
assert pkgfile.check()
html = pkgfile.read()
- assert 'index of project pkg namespace'
+ assert 'index of pkg' in html
_checkhtml(html)
def test_build_namespace_pages_subnamespace(self):
@@ -318,6 +319,66 @@ class TestApiPageBuilder(AbstractBuilderTest):
assert '' in html
_checkhtml(html)
+ def test_get_revision(self):
+ # XXX a lot of setup required for this one... more like a functional
+ # test I fear
+
+ # create test repo and checkout
+ repo = make_test_repo('test_get_revision_api_repo')
+ wc = py.path.svnwc(py.test.ensuretemp('test_get_revision_api_wc'))
+ wc.checkout(repo.url)
+ assert wc.status().rev == '0'
+
+ # create a temp package inside the working copy
+ fs_root, pkg_name = setup_fs_project(wc)
+ ds, dsa = get_dsa(self.fs_root, self.pkg_name)
+ wc.commit('test get revision commit')
+ wc.update()
+
+ # clear cache
+ py.__.apigen.htmlgen._get_obj_cache = {}
+
+ # fiddle about a bit with paths so that our package is picked up :|
+ old_path = py.std.sys.path
+ try:
+ py.std.sys.path.insert(0, fs_root.strpath)
+ pkgkeys = [k for k in py.std.sys.modules.keys() if
+ k == 'pkg' or k.startswith('pkg.')]
+ # remove modules from sys.modules
+ for key in pkgkeys:
+ del py.std.sys.modules[key]
+
+ # now create a new apb that uses the wc pkg
+ apb = ApiPageBuilder(self.base, self.linker, dsa,
+ fs_root.join(pkg_name),
+ self.namespace_tree, self.project)
+ apb._revcache = {} # clear cache, this is on class level!!
+
+ pkg = wc.join('pkg')
+ assert pkg.check(versioned=True)
+ assert pkg.info().created_rev == 1
+
+ funcpath = pkg.join('func.py')
+ classpath = pkg.join('someclass.py')
+ assert funcpath.check(versioned=True)
+ assert classpath.check(versioned=True)
+ assert apb.get_revision('main.sub.func') == 1
+ assert apb.get_revision('main.SomeClass') == 1
+ assert apb.get_revision('') == 1
+ assert apb.get_revision('main.sub') == 1
+ funcpath.write(funcpath.read() + '\n')
+ funcpath.commit('updated func')
+ wc.update()
+ apb._revcache = {} # clear cache
+ assert apb.get_revision('main.sub.func') == 2
+ assert apb.get_revision('') == 1
+ assert apb.get_revision('main.SomeClass') == 1
+ finally:
+ py.std.sys.path = old_path
+ # clear caches again
+ py.__.apigen.htmlgen._get_obj_cache = {}
+ apb._revcache = {}
+
class TestSourcePageBuilder(AbstractBuilderTest):
def test_build_pages(self):
self.spb.build_pages(self.fs_root)
@@ -376,3 +437,25 @@ class TestSourcePageBuilder(AbstractBuilderTest):
'href="somesubclass.py.html">somesubclass.py',
])
+ def test_get_revision(self):
+ repo = make_test_repo('test_get_revision_source_repo')
+ wc = py.path.svnwc(py.test.ensuretemp('test_get_revision_source_wc'))
+ wc.checkout(repo.url)
+
+ dir = wc.ensure('dir', dir=True)
+ file = dir.ensure('file.py', file=True)
+ wc.commit('added dir and file')
+ wc.update()
+ assert file.check(versioned=True)
+ assert wc.status().rev == '1'
+
+ assert self.spb.get_revision(dir) == 1
+ assert self.spb.get_revision(file) == 1
+
+ file.write('while 1:\n print "py lib is cool\n"')
+ file.commit('added some code')
+ assert file.status().rev == '2'
+ self.spb._revcache = {}
+ assert self.spb.get_revision(file) == 2
+ assert self.spb.get_revision(dir) == 1
+
diff --git a/py/apigen/todo-apigen.txt b/py/apigen/todo-apigen.txt
index fba583d95..64ee7cca6 100644
--- a/py/apigen/todo-apigen.txt
+++ b/py/apigen/todo-apigen.txt
@@ -12,7 +12,5 @@
NOT YET DONE (later?)
-* add SVN info to the (source only?) pages
-
* add warning about py.test possibly not covering the whole API