[Zope3-checkins] SVN: Zope3/trunk/src/zope/app/apidoc/classmodule/ Added a list of known subclasses to the apidoc class information page.

Marius Gedminas marius at pov.lt
Mon Jul 19 10:28:23 EDT 2004


Log message for revision 26631:
  Added a list of known subclasses to the apidoc class information page.
  
  


Changed:
  U   Zope3/trunk/src/zope/app/apidoc/classmodule/__init__.py
  U   Zope3/trunk/src/zope/app/apidoc/classmodule/browser.py
  U   Zope3/trunk/src/zope/app/apidoc/classmodule/class_index.pt


-=-
Modified: Zope3/trunk/src/zope/app/apidoc/classmodule/__init__.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/classmodule/__init__.py	2004-07-19 14:11:45 UTC (rev 26630)
+++ Zope3/trunk/src/zope/app/apidoc/classmodule/__init__.py	2004-07-19 14:28:22 UTC (rev 26631)
@@ -73,6 +73,9 @@
     def getBases():
         """Return the base classes of the class."""
 
+    def getKnownSubclasses():
+        """Return the known subclasses classes of the class."""
+
     def getInterfaces():
         """Return the interfaces the class implements."""
 
@@ -300,6 +303,16 @@
       >>> klass.getBases()
       (<class 'zope.app.apidoc.utilities.ReadContainerBase'>,)
 
+    In the other direction, you can get a list of known subclasses.  The list
+    only includes those subclasses that are registered with the global
+    classRegistry in this module. In our example::
+
+      >>> class APIDocSubclass(zope.app.apidoc.APIDocumentation):
+      ...   pass
+      >>> klass2 = Class(module, 'APIDocSubclass', APIDocSubclass)
+      >>> klass.getKnownSubclasses()
+      [<class 'zope.app.apidoc.classmodule.APIDocSubclass'>]
+
     For a more detailed analysis, you can also retrieve the public attributes
     and methods of this class::
 
@@ -342,6 +355,11 @@
         """See IClassDocumentation."""
         return self.__klass.__bases__
 
+    def getKnownSubclasses(self):
+        """See IClassDocumentation."""
+        global classRegistry
+        return [k for n, k in classRegistry.getSubclassesOf(self.__klass)]
+
     def getInterfaces(self):
         """See IClassDocumentation."""
         return self.__interfaces
@@ -611,7 +629,8 @@
     This little registry allows us to quickly query a complete list of classes
     that are defined and used by Zope 3. The prime feature of the class is the
     'getClassesThatImplement(iface)' method that returns all classes that
-    implement the passed interface.
+    implement the passed interface. Another method, 'getSubclassesOf(klass)'
+    returns all registered subclassess of the given class.
 
     Here is the registry in action::
 
@@ -638,34 +657,56 @@
       >>> class C(object):
       ...    implements(IC)
       >>> reg['C'] = C
+      >>> class A2(A):
+      ...    pass
+      >>> reg['A2'] = A2
 
       >>> names = reg.keys()
       >>> names.sort()
       >>> names
-      ['A', 'B', 'B2', 'C']
+      ['A', 'A2', 'B', 'B2', 'C']
 
       >>> reg['A'] is A
       True
 
-      >>> [n for n, k in reg.getClassesThatImplement(IA)]
-      ['A', 'B', 'B2']
-      >>> [n for n, k in reg.getClassesThatImplement(IB)]
+      >>> def names(l):
+      ...   l = [n for n, k in l]
+      ...   l.sort()
+      ...   return l
+
+      >>> names(reg.getClassesThatImplement(IA))
+      ['A', 'A2', 'B', 'B2']
+      >>> names(reg.getClassesThatImplement(IB))
       ['B', 'B2']
-      >>> [n for n, k in reg.getClassesThatImplement(IC)]
+      >>> names(reg.getClassesThatImplement(IC))
       ['C']
-      >>> [n for n, k in reg.getClassesThatImplement(ID)]
+      >>> names(reg.getClassesThatImplement(ID))
       []
+
+      >>> names(reg.getSubclassesOf(A))
+      ['A2']
+      >>> names(reg.getSubclassesOf(B))
+      []
+
     """
 
     def getClassesThatImplement(self, iface):
-        """Return the all class items that implement iface.
+        """Return all class items that implement iface.
 
-        Methods returns a 2-tuple of the form (path, class).
+        Methods returns a list of 2-tuples of the form (path, class).
         """
         return [(path, klass) for path, klass in self.items()
                 if iface.implementedBy(klass)]
 
+    def getSubclassesOf(self, klass):
+        """Return all class items that are proper subclasses of klass.
 
+        Methods returns a list of 2-tuples of the form (path, class).
+        """
+        return [(path, klass2) for path, klass2 in self.items()
+                if issubclass(klass2, klass) and klass2 is not klass]
+
+
 classRegistry = ClassRegistry()
 
 def cleanUp():

Modified: Zope3/trunk/src/zope/app/apidoc/classmodule/browser.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/classmodule/browser.py	2004-07-19 14:11:45 UTC (rev 26630)
+++ Zope3/trunk/src/zope/app/apidoc/classmodule/browser.py	2004-07-19 14:28:22 UTC (rev 26631)
@@ -423,15 +423,59 @@
           [{'path': 'zope.app.apidoc.classmodule.Module',
             'url': 'http://127.0.0.1/zope/app/apidoc/classmodule/Module'}]
         """
+        return self._listClasses(self.context.getBases())
+
+
+    def getKnownSubclasses(self):
+        """Get all known subclasses of this class.
+
+        Example::
+
+          The class we are using for this view is
+          zope.app.apidoc.classmodule.ClassModule.
+
+          >>> import pprint
+          >>> from tests import getClassDetailsView
+          >>> view = getClassDetailsView()
+
+          >>> pprint.pprint(view.getKnownSubclasses())
+          []
+        """
+        entries = self._listClasses(self.context.getKnownSubclasses())
+        entries.sort(lambda x, y: cmp(x['path'], y['path']))
+        return entries
+
+    def _listClasses(self, classes):
+        """Prepare a list of classes for presentation.
+
+        Example::
+
+          >>> import pprint
+          >>> from tests import getClassDetailsView
+          >>> view = getClassDetailsView()
+          >>> import zope.app.apidoc
+          >>> import zope.app.apidoc.classmodule
+
+          >>> pprint.pprint(view._listClasses([
+          ...       zope.app.apidoc.APIDocumentation,
+          ...       zope.app.apidoc.classmodule.Module]))
+          [{'path': 'zope.app.apidoc.APIDocumentation',
+            'url': 'http://127.0.0.1/zope/app/apidoc/APIDocumentation'},
+           {'path': 'zope.app.apidoc.classmodule.Module',
+            'url': 'http://127.0.0.1/zope/app/apidoc/classmodule/Module'}]
+        """
         info = []
         classModule = zapi.getUtility(IDocumentationModule, "Class")
-        for base in self.context.getBases():
-            path = getPythonPath(base)
+        for cls in classes:
+            # XXX Certain classes cause the following line to raise an
+            #     exception.  The easiest way to reproduce the problem is to
+            #     go to /++apidoc++/Class/__builtin__/object/index.html
+            path = getPythonPath(cls)
             try:
                 klass = zapi.traverse(classModule, path.replace('.', '/'))
                 url = zapi.getView(klass, 'absolute_url', self.request)()
             except NotFoundError:
-                # If one of the base classes is implemented in C, we will not
+                # If one of the classes is implemented in C, we will not
                 # be able to find it.
                 url = None
             info.append({'path': path, 'url': url})

Modified: Zope3/trunk/src/zope/app/apidoc/classmodule/class_index.pt
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/classmodule/class_index.pt	2004-07-19 14:11:45 UTC (rev 26630)
+++ Zope3/trunk/src/zope/app/apidoc/classmodule/class_index.pt	2004-07-19 14:28:22 UTC (rev 26631)
@@ -17,7 +17,7 @@
 
     <div class="indent"
          tal:define="bases view/getBases">
-    
+
     <ul class="attr-list" tal:condition="bases">
       <li tal:repeat="base bases">
         <a href=""
@@ -29,31 +29,31 @@
         </div>
       </li>
     </ul>
-    
+
     <p tal:condition="not: bases">
       <em i18n:translate="">There are no base classes.</em>
     </p>
-    
+
     </div>
 
   <h2 class="details-section" i18n:translate="">Implemented Interfaces</h2>
 
     <div class="indent"
          tal:define="ifaces view/getInterfaces">
-    
+
     <ul class="attr-list" tal:condition="ifaces">
       <li tal:repeat="iface ifaces">
         <a href=""
-           tal:attributes="href 
+           tal:attributes="href
                string:${view/getBaseURL}/Interface/$iface/apiindex.html"
            tal:content="iface" />
       </li>
     </ul>
-    
+
     <p tal:condition="not: ifaces">
       <em i18n:translate="">There are no implemented interfaces.</em>
     </p>
-    
+
     </div>
 
 
@@ -63,7 +63,7 @@
       tal:define="attributes view/getAttributes">
 
   <ul class="attr-list" tal:condition="attributes">
-  
+
     <li tal:repeat="attr attributes">
       <b><code tal:content="attr/name">attr</code></b>
       <tal:omit-tag condition="not: attr/type_link">
@@ -71,7 +71,7 @@
       </tal:omit-tag>
       <tal:omit-tag condition="attr/type_link">
         (<span i18n:translate="">type:</span>
-        <a href="" 
+        <a href=""
            tal:attributes="href string:./index.html?path=${attr/type_link}">
           <code tal:content="attr/type" /></a>)
       </tal:omit-tag>
@@ -82,15 +82,15 @@
       <span class="small" tal:condition="attr/interface">
         <i i18n:translate="">Interface:</i>
         <a href=""
-           tal:attributes="href 
+           tal:attributes="href
           string:${view/getBaseURL}/Interface/${attr/interface}/apiindex.html"
            tal:content="attr/interface">Iface</a><br />
       </span>
-      <span class="small" 
+      <span class="small"
           tal:condition="python: attr['read_perm'] and attr['write_perm']">
         <i i18n:translate="">Permissions:</i>
         <span tal:replace="attr/read_perm">zope.View</span>
-            <span i18n:translate="">(read)</span>, 
+            <span i18n:translate="">(read)</span>,
         <span tal:replace="attr/write_perm">zope.View</span>
             <span i18n:translate="">(write)</span>
       </span>
@@ -111,9 +111,9 @@
       tal:define="methods view/getMethods">
 
   <ul class="attr-list" tal:condition="methods">
-  
+
     <li tal:repeat="method view/getMethods">
-      <b><code 
+      <b><code
           tal:content="string:${method/name}${method/signature}" />
       </b><br>
       <div class="inline-documentation" tal:content="structure method/doc">
@@ -123,16 +123,16 @@
       <span class="small" tal:condition="method/interface">
         <i i18n:translate="">Interface:</i>
         <a href=""
-           tal:attributes="href 
+           tal:attributes="href
           string:${view/getBaseURL}/Interface/${method/interface}/apiindex.html"
            tal:content="method/interface">Iface</a><br/>
       </span>
-      
-      <span class="small" 
+
+      <span class="small"
           tal:condition="python: method['read_perm'] and method['write_perm']">
         <i i18n:translate="">Permissions:</i>
         <span tal:replace="method/read_perm">zope.View</span>
-            <span i18n:translate="">(read)</span>, 
+            <span i18n:translate="">(read)</span>,
         <span tal:replace="method/write_perm">zope.View</span>
             <span i18n:translate="">(write)</span>
       </span>
@@ -146,6 +146,28 @@
 
   </div>
 
+  <h2 class="details-section" i18n:translate="">Known Subclasses</h2>
 
+  <div class="indent"
+       tal:define="subclasses view/getKnownSubclasses">
+
+    <ul class="attr-list" tal:condition="subclasses">
+      <li tal:repeat="cls subclasses">
+        <a href=""
+            tal:attributes="href string:${cls/url}/index.html"
+            tal:content="cls/path"
+            tal:condition="cls/url" />
+        <div tal:condition="not: cls/url">
+          <span tal:replace="cls/path" /> (C-based class)
+        </div>
+      </li>
+    </ul>
+
+    <p tal:condition="not: subclasses">
+      <em i18n:translate="">There are no known subclasses.</em>
+    </p>
+
+  </div>
+
 </body>
 </html>



More information about the Zope3-Checkins mailing list