[py-svn] r33422 - in py/dist/py/test/tracer: . testing

guido at codespeak.net guido at codespeak.net
Wed Oct 18 22:12:37 CEST 2006


Author: guido
Date: Wed Oct 18 22:12:36 2006
New Revision: 33422

Modified:
   py/dist/py/test/tracer/genrest.py
   py/dist/py/test/tracer/testing/test_rest.py
Log:
Changed 'write_file' into 'write_section' and made removed hard-coded file and
link names, now it's possible to change the directory structure, or even write
to a single file. Split up rendering of the index (a list of links to the doc
sections) and documentation sections to allow treating them differently (mostly
to allow locating the index above the document on single document rendering,
not too fond of this solution still, though). Added functionality on the 
writers to re-write internal links, so the writers can decide whether to link
to 'fun_foo.txt', 'fun_foo.html' or '#fun_foo', depending on their output.
Some whitespace and indentation cleanups.


Modified: py/dist/py/test/tracer/genrest.py
==============================================================================
--- py/dist/py/test/tracer/genrest.py	(original)
+++ py/dist/py/test/tracer/genrest.py	Wed Oct 18 22:12:36 2006
@@ -22,8 +22,8 @@
     """ Link writer for ViewVC version control viewer
     """
     def __init__(self, basepath):
-        self.basepath = basepath # XXX: should try to guess from working
-            # copy of svn
+        # XXX: should try to guess from a working copy of svn
+        self.basepath = basepath
     
     def getpkgpath(self, filename):
         # XXX: very simple thing
@@ -37,12 +37,13 @@
     
     def getlink(self, filename, lineno):
         path = str(self.getpkgpath(filename))
-        assert filename.startswith(path), "%s does not belong to package %s" %\
-            (filename, path)
+        assert filename.startswith(path), (
+            "%s does not belong to package %s" % (filename, path))
         relname = filename[len(path):]
         if relname.endswith('.pyc'):
             relname = relname[:-1]
-        return ('%s:%s' % (filename, lineno), self.basepath + relname[1:] + '?view=markup')
+        return ('%s:%s' % (filename, lineno),
+                self.basepath + relname[1:] + '?view=markup')
 
 class DirectPaste(AbstractLinkWriter):
     """ No-link writer (inliner)
@@ -54,13 +55,19 @@
     def __init__(self, output=sys.stdout):
         self.output = output
     
-    def write_file(self, filename, data):
-        text = "Written file: %s" % filename
+    def write_index(self, data):
+        self.write_section('index', data)
+
+    def write_section(self, name, data):
+        text = "Written file: %s.txt" % (name,)
         self.output.write(text + "\n")
         self.output.write("=" * len(text) + "\n")
         self.output.write("\n")
         self.output.write(data + "\n")
-    
+
+    def rewrite_link(self, target):
+        return '%s.txt' % (target,)
+
 class DirWriter(object):
     def __init__(self, directory=None):
         if directory is None:
@@ -68,9 +75,38 @@
         else:
             self.directory = py.path.local(directory)
     
-    def write_file(self, filename, data):
+    def write_section(self, name, data):
+        filename = '%s.txt' % (name,)
         self.directory.ensure(filename).write(data)
 
+    def write_index(self, data):
+        self.write_section('index', data)
+
+    def rewrite_link(self, target):
+        # we assume the result will get converted to HTML...
+        return '%s.html' % (target,)
+
+class FileWriter(object):
+    def __init__(self, fpath):
+        self.fpath = fpath
+        self.fp = fpath.open('w+')
+
+    def write_section(self, name, data):
+        self.fp.write(data)
+        self.fp.flush()
+
+    def write_index(self, data):
+        self.fp.seek(0)
+        curdata = self.fp.read()
+        data += curdata
+        self.fp.seek(0)
+        self.fp.truncate(0)
+        self.fp.write(data)
+        self.fp.flush()
+
+    def rewrite_link(self, target):
+        return '#%s' % (target,)
+
 class RestGen(object):
     def __init__(self, ds, linkgen, writer=PipeWriter()):
         self.dsa = DocStorageAccessor(ds)
@@ -80,44 +116,54 @@
     def write(self):
         # first write down a file with all the exported interfaces,
         # sorted by type
-        self.write_interface("index.txt")
+        self.write_interface()
     
-    def write_interface(self, filename):
+    def write_interface(self):
         lst = [Title("Module: %s" % self.dsa.get_module_name(), belowchar="="),
-            Paragraph(self.dsa.get_module_info()),
-            Title("Exported functions:", belowchar="-")]
+               Paragraph(self.dsa.get_module_info()),
+               Title("Exported functions:", belowchar="-")]
         self.write_function_list(lst)
         lst.append(Title("Exported classes:", belowchar="-"))
         self.write_class_list(lst)
-        self.writer.write_file(filename, Rest(*lst).text())
+        self.writer.write_index(Rest(*lst).text())
     
     def write_function_list(self, lst):
         for name in self.dsa.get_function_names():
             # XXX: should be .html here?
-            lst.append(ListItem(Text("Function: "), Link(name, "function_%s.html" % name)))
-            self.write_function('function_' + name + '.txt', name)
+            sectionname = 'function_%s' % (name,)
+            linktarget = self.writer.rewrite_link(sectionname)
+            lst.append(ListItem(Text("Function: "),
+                       Link(name, linktarget)))
+            self.write_function(sectionname, name)
     
     def write_class_list(self, lst):
         for name in self.dsa.get_class_names():
-            lst.append(ListItem(Text("Class: "), Link(name, "class_%s.html" % name)))
-            self.write_class('class_' + name + '.txt', name)
+            sectionname = 'class_%s' % (name,)
+            linktarget = self.writer.rewrite_link(sectionname)
+            lst.append(ListItem(Text("Class: "),
+                       Link(name, linktarget)))
+            self.write_class(sectionname, name)
     
-    def write_class(self, filename, class_name):
+    def write_class(self, section_name, class_name):
+        # XXX no docstring?
         lst = [Title("Class: %s" % class_name, belowchar='-')]
         
         # write down exported methods
         lst.append(Title("Exported methods:", belowchar="^"))
         for method in self.dsa.get_class_methods(class_name):
-            fname = "method_%s" % (class_name + \
-                "_" + method)
-            lst.append(ListItem(Link(method, fname+'.html')))
-            self.write_function(fname+'.txt', class_name + "." + method)
-        
-        self.writer.write_file(filename, Rest(*lst).text())
-    
-    def write_function(self, filename, fun_name):
+            sectionname = 'method_%s_%s' % (class_name, method)
+            linktarget = self.writer.rewrite_link(sectionname)
+            lst.append(ListItem(Link(method, linktarget)))
+            self.write_function(sectionname, class_name + "." + method)
+        
+        self.writer.write_section(section_name, Rest(*lst).text())
+    
+    def write_function(self, section_name, fun_name):
+        # XXX I think the docstring should either be split on \n\n and cleaned
+        # from indentation, or treated as ReST too (although this is obviously
+        # dangerous for non-ReST docstrings)...
         lst = [Title("Function: %s" % fun_name, belowchar="-"),
-            Paragraph(self.dsa.get_function_doc(fun_name)),
+            BlockQuote(self.dsa.get_function_doc(fun_name)),
             BlockQuote(self.dsa.get_function_definition(fun_name))]
         
         lst.append(Paragraph("Function source: XXX (to write a link here)"))
@@ -128,7 +174,8 @@
         # for the type declaration (if this is known)
         arg_str = "(%s)" % (",".join([str(i.knowntype) for i in args]))
         ret_str = str(retval.knowntype)
-        arg_quote = Paragraph("Function type:", Quote(arg_str), '->', Quote(ret_str))
+        arg_quote = Paragraph("Function type:", Quote(arg_str), '->',
+                              Quote(ret_str))
         lst.append(arg_quote)
         
         # call sites..
@@ -139,7 +186,8 @@
         for call_site, frame in self.dsa.get_function_callpoints(fun_name):
             link_str = "File %s:%s" % (call_site.filename,
                 call_site.lineno)
-            #_, link_target = self.linkgen.getlink(call_site.filename, call_site.lineno)
+            #_, link_target = self.linkgen.getlink(call_site.filename,
+            #                                      call_site.lineno)
             #if link_target: # otherwise it's just inline text
             #    call_sites.append(Paragraph(Link(link_str, link_target)))
             #else:
@@ -152,12 +200,12 @@
             for num, line in enumerate(source):
                 if num == call_site.lineno - frame.code.firstlineno - 1:
                     m = re.match("^( *)(.*)", line)
-                    lines.append(">" + "-"*len(m.group(1)) + m.group(2))
+                    lines.append("%s >" + "-"*len(m.group(1)) + m.group(2))
                 else:
                     lines.append(" " + line)
             call_sites.append(BlockQuote("\n".join(lines)))
         
-        self.writer.write_file(filename, Rest(*lst).text())
+        self.writer.write_section(section_name, Rest(*lst).text())
 ##class RestGen(object):
 ##    def __init__(self, ds, linkgen, output=sys.stdout):
 ##        self.dsa = DocStorageAccessor(ds)
@@ -189,14 +237,16 @@
 ##            for call_site in self.dsa.get_function_callpoints(key):
 ##                link_str = "File %s:%s" % (call_site.filename,
 ##                    call_site.lineno)
-##                link_target = self.linkgen.getlink(call_site.filename, call_site.lineno)
+##                link_target = self.linkgen.getlink(call_site.filename,
+##                                                   call_site.lineno)
 ##                if link_target: # otherwise it's just inline text
 ##                    call_sites.append(Paragraph(Link(link_str, link_target)))
 ##                else:
 ##                    call_sites.append(Paragraph(link_str))
 ##                call_sites.append(BlockQuote(call_site.source))
 ##            
-##            for item in [title, docstr, arg_quote, call_site_title] + call_sites:
+##            for item in [title, docstr, arg_quote,
+##                         call_site_title] + call_sites:
 ##                self.add(item)
 ##            
 ##            #for call_site in self.dsa.get_function_callpoints(key):

Modified: py/dist/py/test/tracer/testing/test_rest.py
==============================================================================
--- py/dist/py/test/tracer/testing/test_rest.py	(original)
+++ py/dist/py/test/tracer/testing/test_rest.py	Wed Oct 18 22:12:36 2006
@@ -5,8 +5,8 @@
 import py
 
 try:
-    from py.__.test.tracer.genrest import ViewVC, RestGen, PipeWriter, DirWriter,\
-        DirectPaste
+    from py.__.test.tracer.genrest import ViewVC, RestGen, PipeWriter, \
+                                            DirWriter, FileWriter, DirectPaste
     from py.__.test.tracer.tracer import DocStorage, Tracer
 
     from StringIO import StringIO
@@ -14,10 +14,14 @@
 except ImportError, s:
     py.test.skip("Cannot import: %s" % str(s))
 
+def setup_module(mod):
+    mod.temppath = py.test.ensuretemp('restgen')
+
 def test_links():
     vcview = ViewVC("http://codespeak.net/viewvc/")
     _, linkname = vcview.getlink(cut_pyc(__file__), 0)
-    assert linkname == 'http://codespeak.net/viewvc/py/test/tracer/testing/test_rest.py?view=markup'
+    assert linkname == ('http://codespeak.net/viewvc/py/test/tracer/'
+                        'testing/test_rest.py?view=markup')
 
 class SomeClass(object):
     def __init__(self, a):
@@ -27,32 +31,37 @@
         return a + b + c
 
 def fun(a, b, c):
-    "Some docstring"
+    """Some docstring
+    
+        Let's make it span a couple of lines to be interesting...
+
+        Note:
+
+         * rest
+         * should
+         * be
+         * supported
+         * or
+         * ignored...
+    """
     return "d"
 
 def test_dir_writer():
     p = StringIO()
-    dir = py.test.ensuretemp("dirwriter")
+    dir = temppath.ensure("dirwriter", dir=True)
     w = DirWriter(dir)
-    w.write_file("one", "one data")
-    w.write_file("two", "two data")
-    assert dir.join("one").read() == "one data"
-    assert dir.join("two").read() == "two data"
+    w.write_section("one", "one data")
+    w.write_section("two", "two data")
+    assert dir.join("one.txt").read() == "one data"
+    assert dir.join("two.txt").read() == "two data"
 
 def test_direct_link():
-    assert DirectPaste().getlink(cut_pyc(__file__), 2)[0] == '""" tests document generation\n'
+    assert DirectPaste().getlink(cut_pyc(__file__), 2)[0] == (
+        '""" tests document generation\n')
     # C-c C-v ....
 
 class TestRest(object):
-    def check_rest(self, tmpdir):
-        from py.__.misc import rest 
-        for path in tmpdir.listdir('*.txt'):
-            rest.process(path)
-    
-    def test_generation_simple_api(self):
-        descs = {'SomeClass':SomeClass, 'fun':fun}
-        ds = DocStorage().from_dict(descs)
-        lg = DirectPaste()
+    def get_some_trace(self, ds):
         t = Tracer(ds)
         t.start_tracing()
         s1 = SomeClass("a")
@@ -61,11 +70,56 @@
         s2.method(1,2,3)
         fun(1, 3, s2)
         t.end_tracing()
-        tmpdir = py.test.ensuretemp("test_generation")
-        r = RestGen(ds, lg, DirWriter(tmpdir))
+    
+    def check_rest(self, tempdir):
+        from py.__.misc import rest
+        for path in tempdir.listdir('*.txt'):
+            rest.process(path)
+    
+    def test_generation_simple_api(self):
+        descs = {'SomeClass':SomeClass, 'fun':fun}
+        ds = DocStorage().from_dict(descs)
+        t = self.get_some_trace(ds)
+        lg = DirectPaste()
+        tempdir = temppath.ensure("test_generation_simple_api", dir=True)
+        r = RestGen(ds, lg, DirWriter(tempdir))
         r.write()
+        basenames = [p.basename for p in tempdir.listdir('*.txt')]
+        assert sorted(basenames) == [
+            'class_SomeClass.txt',
+            'function_fun.txt',
+            'index.txt',
+            'method_SomeClass___init__.txt',
+            'method_SomeClass_method.txt',
+        ]
         # now we check out...
-        self.check_rest(tmpdir)
+        self.check_rest(tempdir)
+
+    def test_check_internal_links(self):
+        descs = {'SomeClass': SomeClass,
+                 'fun': fun}
+        ds = DocStorage().from_dict(descs)
+        t = self.get_some_trace(ds)
+
+        lg = DirectPaste()
+        tempdir = temppath.ensure('test_generation_internal_links', dir=True)
+        r = RestGen(ds, lg, DirWriter(tempdir))
+        r.write()
+        index = tempdir.join('index.txt')
+        assert index.check(file=True)
+        data = index.read()
+        assert data.find('.. _`fun`: function_fun.html\n') > -1
+        assert data.find('.. _`fun`: #fun\n') == -1
+
+        tempfile = temppath.ensure('test_generation_internal_links.txt',
+                                  file=True)
+        r = RestGen(ds, lg, FileWriter(tempfile))
+        r.write()
+        data = tempfile.read()
+        print 'data:', data
+        assert data.find('.. _`fun`: #function_fun\n') > -1
+        assert data.find('.. _`fun`: function_fun.html') == -1
+
 
 ##def test_generation():
 ##    py.test.skip("WIP")


More information about the py-svn mailing list