[py-svn] r37922 - in py/trunk/py/apigen: . testing

guido at codespeak.net guido at codespeak.net
Sun Feb 4 16:47:35 CET 2007


Author: guido
Date: Sun Feb  4 16:47:33 2007
New Revision: 37922

Modified:
   py/trunk/py/apigen/html.py
   py/trunk/py/apigen/htmlgen.py
   py/trunk/py/apigen/layout.py
   py/trunk/py/apigen/style.css
   py/trunk/py/apigen/testing/test_apigen_functional.py
   py/trunk/py/apigen/testing/test_htmlgen.py
   py/trunk/py/apigen/todo-apigen.txt
Log:
Made that properties (class attributes) are displayed, fixed the links in the
menubar.


Modified: py/trunk/py/apigen/html.py
==============================================================================
--- py/trunk/py/apigen/html.py	(original)
+++ py/trunk/py/apigen/html.py	Sun Feb  4 16:47:33 2007
@@ -47,12 +47,21 @@
             super(H.FunctionInfo, self).__init__(
                 H.Hideable('funcinfo', 'funcinfo', valuedesc, csource,
                            callstack))
+    
+    class PropertyDescription(html.div):
+        def __init__(self, name, value):
+            if type(value) not in [str, unicode]:
+                value = str(value)
+            if len(value) > 100:
+                value = value[:100] + '...'
+            super(H.PropertyDescription, self).__init__(H.strong(name), ': ',
+                                                      H.em(value),
+                                                      class_='property')
 
     class ParameterDescription(html.div):
         pass
 
     class Docstring(html.pre):
-        style = html.Style(width='100%')
         pass
 
     class Navigation(html.div):

Modified: py/trunk/py/apigen/htmlgen.py
==============================================================================
--- py/trunk/py/apigen/htmlgen.py	(original)
+++ py/trunk/py/apigen/htmlgen.py	Sun Feb  4 16:47:33 2007
@@ -17,6 +17,17 @@
 def is_navigateable(name):
     return (not is_private(name) and name != '__doc__')
 
+def show_property(name):
+    if not name.startswith('_'):
+        return True
+    if name.startswith('__') and name.endswith('__'):
+        # XXX do we need to skip more manually here?
+        if (name not in dir(object) and
+                name not in ['__doc__', '__dict__', '__name__', '__module__',
+                             '__weakref__']):
+            return True
+    return False
+
 def deindent(str, linesep='\n'):
     """ de-indent string
 
@@ -351,7 +362,24 @@
         docstring = cls.__doc__
         if docstring:
             docstring = deindent(docstring)
-        methods = self.dsa.get_class_methods(dotted_name)
+        if not hasattr(cls, '__name__'):
+            clsname = 'instance of %s' % (cls.__class__.__name__,)
+        else:
+            clsname = cls.__name__
+        bases = self.build_bases(dotted_name)
+        properties = self.build_properties(cls)
+        methods = self.build_methods(dotted_name)
+        snippet = H.ClassDescription(
+            # XXX bases HTML
+            H.ClassDef('%s(' % (clsname,), *bases),
+            H.Docstring(docstring or '*no docstring available*'),
+            sourcelink,
+            *(properties+methods)
+        )
+
+        return snippet
+
+    def build_bases(self, dotted_name):
         basehtml = []
         bases = self.dsa.get_possible_base_classes(dotted_name)
         for base in bases:
@@ -366,23 +394,33 @@
         if basehtml:
             basehtml.pop()
         basehtml.append('):')
-        if not hasattr(cls, '__name__'):
-            clsname = 'instance of %s' % (cls.__class__.__name__,)
-        else:
-            clsname = cls.__name__
-        snippet = H.ClassDescription(
-            # XXX bases HTML
-            H.ClassDef('%s(' % (clsname,), *basehtml),
-            H.Docstring(docstring or '*no docstring available*'),
-            sourcelink,
-        )
+        return basehtml
+
+    def build_properties(self, cls):
+        properties = []
+        for attr in dir(cls):
+            val = getattr(cls, attr)
+            if show_property(attr) and not callable(val):
+                if isinstance(val, property):
+                    val = '<property object (dynamically calculated value)>'
+                properties.append((attr, val))
+        properties.sort(key=lambda a: a[0]) # sort on name
+        ret = []
+        if properties:
+            ret.append(H.h2('properties:'))
+            for name, val in properties:
+                ret.append(H.PropertyDescription(name, val))
+        return ret
+
+    def build_methods(self, dotted_name):
+        ret = []
+        methods = self.dsa.get_class_methods(dotted_name)
         if methods:
-            snippet.append(H.h2('methods:'))
+            ret.append(H.h2('methods:'))
             for method in methods:
-                snippet += self.build_callable_view('%s.%s' % (dotted_name,
-                                                    method))
-        # XXX properties
-        return snippet
+                ret += self.build_callable_view('%s.%s' % (dotted_name,
+                                                           method))
+        return ret
 
     def build_namespace_view(self, namespace_dotted_name, item_dotted_names):
         """ build the html for a namespace (module) """

Modified: py/trunk/py/apigen/layout.py
==============================================================================
--- py/trunk/py/apigen/layout.py	(original)
+++ py/trunk/py/apigen/layout.py	Sun Feb  4 16:47:33 2007
@@ -26,9 +26,17 @@
 
     def fill(self):
         super(LayoutPage, self).fill()
-        #self.menubar[:] = []
+        self.update_menubar_links(self.menubar)
         self.body.insert(0, self.nav)
 
+    def update_menubar_links(self, node):
+        for item in node:
+            if not isinstance(item, py.xml.Tag):
+                continue
+            if (item.__class__.__name__ == 'a' and hasattr(item.attr, 'href')
+                    and not item.attr.href.startswith('http://')):
+                item.attr.href = self.relpath + '../py/doc/' + item.attr.href
+
     def setup_scripts_styles(self, copyto=None):
         for path, name in self.stylesheets:
             if copyto:

Modified: py/trunk/py/apigen/style.css
==============================================================================
--- py/trunk/py/apigen/style.css	(original)
+++ py/trunk/py/apigen/style.css	Sun Feb  4 16:47:33 2007
@@ -18,7 +18,6 @@
 #content {
   border: 0px;
   height: 95%;
-  width: 100%;
 }
 
 ul {
@@ -76,6 +75,10 @@
   background-color: white;
 }
 
+.property {
+  font-size: 1.2em;
+}
+
 .callstackitem {
   border: 1px solid black;
   margin-bottom: 1em;

Modified: py/trunk/py/apigen/testing/test_apigen_functional.py
==============================================================================
--- py/trunk/py/apigen/testing/test_apigen_functional.py	(original)
+++ py/trunk/py/apigen/testing/test_apigen_functional.py	Sun Feb  4 16:47:33 2007
@@ -19,6 +19,7 @@
     temp.ensure('pak/sometestclass.py').write(py.code.Source("""\
         class SomeTestClass(object):
             " docstring sometestclass "
+            someattr = 'somevalue'
             def __init__(self, somevar):
                 self.somevar = somevar
                 
@@ -129,12 +130,10 @@
     sometestclass_api = apidir.join('main.SomeTestClass.html')
     assert sometestclass_api.check(file=True)
     html = sometestclass_api.read()
+    print html
     assert '<a href="main.SomeTestClass.html">SomeTestClass</a>' in html
-    # XXX not linking to method files anymore
-    #sometestclass_init_api = apidir.join('main.SomeTestClass.__init__.html')
-    #assert sometestclass_init_api.check(file=True)
-    #assert sometestclass_init_api.read().find(
-    #        '<a href="main.SomeTestClass.__init__.html">__init__</a>') > -1
+    assert '<strong>someattr</strong>: <em>somevalue</em>' in html
+    
     namespace_api = apidir.join('main.html')
     assert namespace_api.check(file=True)
     html = namespace_api.read()
@@ -156,4 +155,5 @@
     html = index.read()
     print html
     assert '<a href="test/index.html">test</a>' in html
+    assert 'href="../../py/doc/home.html"'
 

Modified: py/trunk/py/apigen/testing/test_htmlgen.py
==============================================================================
--- py/trunk/py/apigen/testing/test_htmlgen.py	(original)
+++ py/trunk/py/apigen/testing/test_htmlgen.py	Sun Feb  4 16:47:33 2007
@@ -55,3 +55,12 @@
                    ' <span class="string">"bar"</span>\n'
                    '</div>')
 
+def test_show_property():
+    assert htmlgen.show_property('foo')
+    assert not htmlgen.show_property('_foo')
+    assert htmlgen.show_property('__foo__')
+    assert not htmlgen.show_property('__doc__')
+    assert not htmlgen.show_property('__dict__')
+    assert not htmlgen.show_property('__name__')
+    assert not htmlgen.show_property('__class__')
+

Modified: py/trunk/py/apigen/todo-apigen.txt
==============================================================================
--- py/trunk/py/apigen/todo-apigen.txt	(original)
+++ py/trunk/py/apigen/todo-apigen.txt	Sun Feb  4 16:47:33 2007
@@ -1,5 +1,7 @@
 
-* format docstrings more nicely (with tests) - DONE I guess
+* format docstrings more nicely (with tests)
+
+  DONE I guess
 
 * have the API function view be as informative as possible
   without having to go to the "single method" view
@@ -10,10 +12,12 @@
   viewed.  method views (when navigating there through
   the class view) should also have the source there 
 
-  DONE I think
+  DONE I think, single method view is gone
 
 * have class-level attributes be displayed
 
+  DONE
+
 * use "inherited" doc strings, i.e. for
     class A:
         def meth(self):
@@ -25,8 +29,12 @@
     B.meth should display the A.meth docstring, probably 
     with special formatting (italics or so). 
 
+  NOT YET DONE (later?)
+
 * factor out some common code in the build_* functions
 
+  (mostly) DONE
+
 * refactor the apigen/rsession interaction to become
   cleaner (e.g. apigen's get_documentable_items should
   be separately tested and the caller should not need
@@ -76,9 +84,15 @@
        
 * add syntax coloring for Python source snippets
 
+  DONE
+
 * remove py.test/apigen cruft from stack traces
 
+  DONE, thanks to fijal
+
 * fix non-ascii source encoding support
 
+  DONE
+
 * XXX
 



More information about the pytest-commit mailing list