From c7fa5db37b8867bf5c553523ea640554a49cb67b Mon Sep 17 00:00:00 2001 From: guido Date: Mon, 12 Feb 2007 16:21:35 +0100 Subject: [PATCH] [svn r38571] Using wcpath.info().created_rev (last changed revision) rather than wcpath.status().rev (current wc rev) as revision, added revision for source and namespace pages. --HG-- branch : trunk --- py/apigen/htmlgen.py | 59 ++++++++++++--- py/apigen/testing/test_apigen_example.py | 95 ++++++++++++++++++++++-- py/apigen/todo-apigen.txt | 2 - 3 files changed, 137 insertions(+), 19 deletions(-) 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