[Checkins] SVN: zope.app.apidoc/trunk/ Expanded the module documentation

Shane Hathaway shane at hathawaymix.org
Tue Feb 3 04:41:10 EST 2009


Log message for revision 96021:
  Expanded the module documentation
  

Changed:
  U   zope.app.apidoc/trunk/CHANGES.txt
  U   zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/browser/README.txt
  U   zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/browser/module.py
  U   zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/browser/module_index.pt
  U   zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/configure.zcml
  U   zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/interfaces.py
  U   zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/module.py
  U   zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/text.py
  U   zope.app.apidoc/trunk/src/zope/app/apidoc/utilities.py

-=-
Modified: zope.app.apidoc/trunk/CHANGES.txt
===================================================================
--- zope.app.apidoc/trunk/CHANGES.txt	2009-02-03 08:10:54 UTC (rev 96020)
+++ zope.app.apidoc/trunk/CHANGES.txt	2009-02-03 09:41:10 UTC (rev 96021)
@@ -12,6 +12,8 @@
   version of the transaction package puts savepoint.txt in the `tests`
   subpackage.
 
+- Expanded the presentation of module documentation.
+
 3.6.0 (2009-01-31)
 ------------------
 

Modified: zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/browser/README.txt
===================================================================
--- zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/browser/README.txt	2009-02-03 08:10:54 UTC (rev 96020)
+++ zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/browser/README.txt	2009-02-03 09:41:10 UTC (rev 96021)
@@ -2,7 +2,7 @@
 Code Browser Presentation Components
 ====================================
 
-This document describes the API of the views complementing the varius code
+This document describes the API of the views complementing the various code
 browser documentation components. The views can be found in
 
   >>> from zope.app.apidoc.codemodule import browser
@@ -23,11 +23,9 @@
 process to get a module documentation object:
 
   >>> from zope.traversing.api import traverse
-  >>> details = browser.module.ModuleDetails(None, None)
-  >>> details.context = traverse(cm,
-  ...     'zope/app/apidoc/codemodule/codemodule')
+  >>> _context = traverse(cm, 'zope/app/apidoc/codemodule/codemodule')
   >>> from zope.publisher.browser import TestRequest
-  >>> details.request = TestRequest()
+  >>> details = browser.module.ModuleDetails(_context, TestRequest())
 
 `getDoc()`
 ~~~~~~~~~~
@@ -39,22 +37,31 @@
   <p>This module is able to take a dotted name of any class and display
   documentation for it.</p>
 
-`getEntries(columns=True)`
-~~~~~~~~~~~~~~~~~~~~~~~~~~
+Module data
+~~~~~~~~~~~
 
-Return info objects for all modules and classes in this module.
+Return info objects for all classes in this module.
 
-  >>> pprint(details.getEntries(False))
-  [{'isclass': True,
-    'isfunction': False,
-    'isinterface': False,
-    'ismodule': False,
-    'istextfile': False,
-    'iszcmlfile': False,
+  >>> pprint(details.getClasses())
+  [{'doc': 'Represent the code browser documentation root',
     'name': 'CodeModule',
-    'path': 'zope.app.apidoc.codemodule.class_.CodeModule',
     'url': 'http://127.0.0.1/zope/app/apidoc/codemodule/codemodule/CodeModule'}]
 
+This module doesn't contain anything else.
+
+  >>> pprint(details.getInterfaces())
+  []
+  >>> pprint(details.getModules())
+  []
+  >>> pprint(details.getModuleInterfaces())
+  []
+  >>> pprint(details.getTextFiles())
+  []
+  >>> pprint(details.getZCMLFiles())
+  []
+  >>> pprint(details.getFunctions())
+  []
+
 `getBreadCrumbs()`
 ~~~~~~~~~~~~~~~~~~
 

Modified: zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/browser/module.py
===================================================================
--- zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/browser/module.py	2009-02-03 08:10:54 UTC (rev 96020)
+++ zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/browser/module.py	2009-02-03 09:41:10 UTC (rev 96021)
@@ -18,29 +18,52 @@
 __docformat__ = 'restructuredtext'
 from zope.component import getMultiAdapter
 from zope.i18nmessageid import ZopeMessageFactory as _
-from zope.interface.interface import InterfaceClass
+from zope.interface.interfaces import IInterface
 from zope.proxy import removeAllProxies
 from zope.publisher.browser import BrowserView
-from zope.security.proxy import isinstance, removeSecurityProxy
+from zope.security.proxy import isinstance
 from zope.traversing.api import getParent
 from zope.traversing.browser import absoluteURL
 
 from zope.app.apidoc.apidoc import APIDocumentation
-from zope.app.apidoc.utilities import getPythonPath, renderText, columnize
-from zope.app.apidoc.codemodule.module import Module
-from zope.app.apidoc.codemodule.class_ import Class
-from zope.app.apidoc.codemodule.function import Function
-from zope.app.apidoc.codemodule.text import TextFile
-from zope.app.apidoc.codemodule.zcml import ZCMLFile
+from zope.app.apidoc.utilities import getPythonPath, renderText
+from zope.app.apidoc.codemodule.interfaces import IModuleDocumentation
+from zope.app.apidoc.codemodule.interfaces import IClassDocumentation
+from zope.app.apidoc.codemodule.interfaces import IFunctionDocumentation
+from zope.app.apidoc.codemodule.interfaces import IZCMLFile
+from zope.app.apidoc.codemodule.interfaces import ITextFile
 
 def findAPIDocumentationRoot(obj, request):
     if isinstance(obj, APIDocumentation):
         return absoluteURL(obj, request)
     return findAPIDocumentationRoot(getParent(obj), request)
 
+def formatDocString(text, module=None, summary=False):
+    """Format a doc string for display.
 
+    module is either a Python module (from sys.modules) or the dotted name
+    of a module.
+
+    If summary is true, the result is plain text and includes only
+    the summary part of the doc string.
+    If summary is false, the result is HTML and includes the whole doc string.
+    """
+    if text is None:
+        return None
+    lines = text.strip().split('\n')
+    # Get rid of possible CVS id.
+    lines = [line for line in lines if not line.startswith('$Id')]
+    if summary:
+        for i in range(len(lines)):
+            if not lines[i].strip():
+                del lines[i:]
+                break
+        return '\n'.join(lines)
+    return renderText('\n'.join(lines), module)
+
+
 class ModuleDetails(BrowserView):
-    """Represents the details of the module."""
+    """Represents the details of a module or package."""
 
     def __init__(self, context, request):
         super(ModuleDetails, self).__init__(context, request)
@@ -50,35 +73,44 @@
             # Probably context without location; it's a test
             self.apidocRoot = ''
 
+        items = list(self.context.items())
+        items.sort()
+        self.text_files = []
+        self.zcml_files = []
+        self.modules = []
+        self.interfaces = []
+        self.classes = []
+        self.functions = []
+        for name, obj in items:
+            entry = {'name': name, 'url': absoluteURL(obj, self.request)}
+            if IFunctionDocumentation.providedBy(obj):
+                entry['doc'] = formatDocString(
+                    obj.getDocString(), self.context.getPath())
+                entry['signature'] = obj.getSignature()
+                self.functions.append(entry)
+            elif IModuleDocumentation.providedBy(obj):
+                entry['doc'] = formatDocString(
+                    obj.getDocString(), obj.getPath(), True)
+                self.modules.append(entry)
+            elif IInterface.providedBy(obj):
+                entry['path'] = getPythonPath(removeAllProxies(obj))
+                entry['doc'] = formatDocString(
+                    obj.__doc__, obj.__module__, True)
+                self.interfaces.append(entry)
+            elif IClassDocumentation.providedBy(obj):
+                entry['doc'] = formatDocString(
+                    obj.getDocString(), self.context.getPath(), True)
+                self.classes.append(entry)
+            elif IZCMLFile.providedBy(obj):
+                self.zcml_files.append(entry)
+            elif ITextFile.providedBy(obj):
+                self.text_files.append(entry)
+
     def getDoc(self):
-        """Get the doc string of the module STX formatted."""
-        text = self.context.getDocString()
-        if text is None:
-            return None
-        lines = text.strip().split('\n')
-        # Get rid of possible CVS id.
-        lines = [line for line in lines if not line.startswith('$Id')]
-        return renderText('\n'.join(lines), self.context.getPath())
+        """Get the doc string of the module, formatted as HTML."""
+        return formatDocString(
+            self.context.getDocString(), self.context.getPath())
 
-    def getEntries(self, columns=True):
-        """Return info objects for all modules and classes in this module."""
-        entries = [{'name': name,
-                    # only for interfaces; should be done differently somewhen
-                    'path': getPythonPath(removeAllProxies(obj)),
-                    'url': absoluteURL(obj, self.request),
-                    'ismodule': isinstance(obj, Module),
-                    'isinterface': isinstance(
-                         removeAllProxies(obj), InterfaceClass),
-                    'isclass': isinstance(obj, Class),
-                    'isfunction': isinstance(obj, Function),
-                    'istextfile': isinstance(obj, TextFile),
-                    'iszcmlfile': isinstance(obj, ZCMLFile)}
-                   for name, obj in self.context.items()]
-        entries.sort(lambda x, y: cmp(x['name'], y['name']))
-        if columns:
-            entries = columnize(entries)
-        return entries
-
     def getPath(self):
         """Return the path to the module"""
         return self.context.getPath()
@@ -86,3 +118,37 @@
     def isPackage(self):
         """Return true if this module is a package"""
         return self.context.isPackage()
+
+    def getModuleInterfaces(self):
+        """Return entries about interfaces the module provides"""
+        entries = []
+        for iface in self.context.getDeclaration():
+            entries.append({
+                'name': iface.__name__,
+                'path': getPythonPath(removeAllProxies(iface))
+            })
+        return entries
+
+    def getModules(self):
+        """Return entries about contained modules and subpackages"""
+        return self.modules
+
+    def getInterfaces(self):
+        """Return entries about interfaces declared by the module"""
+        return self.interfaces
+
+    def getClasses(self):
+        """Return entries about classes declared by the module"""
+        return self.classes
+
+    def getTextFiles(self):
+        """Return entries about text files contained in the package"""
+        return self.text_files
+
+    def getZCMLFiles(self):
+        """Return entries about ZCML files contained in the package"""
+        return self.zcml_files
+
+    def getFunctions(self):
+        """Return entries about functions declared by the package"""
+        return self.functions

Modified: zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/browser/module_index.pt
===================================================================
--- zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/browser/module_index.pt	2009-02-03 08:10:54 UTC (rev 96020)
+++ zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/browser/module_index.pt	2009-02-03 09:41:10 UTC (rev 96021)
@@ -34,9 +34,99 @@
     Module Documentation
   </div>
 
+  <div tal:define="ifaces view/getModuleInterfaces" tal:condition="ifaces">
+  <p>Module Interfaces:
+    <b tal:repeat="iface ifaces">
+    <a href=""
+       tal:attributes="
+           href string:${view/apidocRoot}/Interface/${iface/path}/index.html"
+       tal:content="iface/name" /><span tal:condition="not:repeat/iface/end">,</span>
+    </b>
+  </p>
+  </div>
 
-  <table width="100%"><tr valign="top">
+  <div tal:define="files view/getTextFiles" tal:condition="files">
+  <p>Text Files:
+    <i tal:repeat="file files">
+    <a href=""
+         tal:attributes="href string:${file/url}/index.html"
+         tal:content="file/name"/><span tal:condition="not:repeat/file/end">,</span>
+    </i>
+  </p>
+  </div>
 
+  <div tal:define="files view/getZCMLFiles" tal:condition="files">
+  <p>ZCML Files:
+    <i tal:repeat="file files">
+    <a href=""
+         tal:attributes="href string:${file/url}/index.html"
+         tal:content="file/name"/><span tal:condition="not:repeat/file/end">,</span>
+    </i>
+  </p>
+  </div>
+
+  <div tal:define="entries view/getModules" tal:condition="entries">
+  <h2 class="details-section">Modules and Subpackages</h2>
+  <table width="100%">
+  <tr valign="top" tal:repeat="entry entries">
+    <td width="20%">
+      <a href=""
+         tal:attributes="href string:${entry/url}/index.html"
+         tal:content="entry/name"/>
+    </td>
+    <td width="80%" tal:content="entry/doc">
+    </td>
+  </tr>
+  </table>
+  </div>
+
+  <div tal:define="ifaces view/getInterfaces" tal:condition="ifaces">
+  <h2 class="details-section">Interfaces</h2>
+  <table width="100%">
+  <tr valign="top" tal:repeat="iface ifaces">
+    <td width="20%">
+      <a href=""
+        tal:attributes="
+           href string:${view/apidocRoot}/Interface/${iface/path}/index.html"
+        tal:content="iface/name" />
+    </td>
+    <td width="80%" tal:content="iface/doc">
+    </td>
+  </tr>
+  </table>
+  </div>
+
+  <div tal:define="classes view/getClasses" tal:condition="classes">
+  <h2 class="details-section">Classes</h2>
+  <table width="100%">
+  <tr valign="top" tal:repeat="entry classes">
+    <td width="20%">
+      <a href=""
+         tal:attributes="href string:${entry/url}/index.html"
+         tal:content="entry/name"/>
+    </td>
+    <td width="80%" tal:content="entry/doc">
+    </td>
+  </tr>
+  </table>
+  </div>
+
+  <div tal:define="functions view/getFunctions" tal:condition="functions">
+  <h2 class="details-section">Functions</h2>
+  <ul>
+    <li tal:repeat="function functions">
+      <b><code
+          tal:content="string:${function/name}${function/signature}" />
+      </b><br>
+      <div class="inline documentation" tal:content="structure function/doc">
+        function desc
+      </div>
+    </li>
+  </ul>
+  </div>
+
+  <!--table width="100%"><tr valign="top">
+
   <td tal:repeat="column view/getEntries"><ul>
     <li tal:repeat="entry column">
       <a href=""
@@ -67,7 +157,7 @@
     </li>
   </ul></td>
 
-  </tr></table>
+  </tr></table-->
 
 </body>
 </html>

Modified: zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/configure.zcml
===================================================================
--- zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/configure.zcml	2009-02-03 08:10:54 UTC (rev 96020)
+++ zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/configure.zcml	2009-02-03 09:41:10 UTC (rev 96021)
@@ -24,7 +24,7 @@
   </class>
 
   <class class=".text.TextFile">
-    <allow attributes="getContent path" />
+    <allow interface=".interfaces.ITextFile" />
   </class>
 
   <class class=".codemodule.CodeModule">

Modified: zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/interfaces.py
===================================================================
--- zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/interfaces.py	2009-02-03 08:10:54 UTC (rev 96020)
+++ zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/interfaces.py	2009-02-03 09:41:10 UTC (rev 96021)
@@ -48,7 +48,14 @@
     def isPackage():
         """Return true if this module is a Python package."""
 
+    def getDeclaration():
+        """Return the interfaces provided by the module.
 
+        The returned value provides zope.interface.interfaces.IDeclaration.
+        To get the list of interfaces, iterate over the returned value.
+        The list will be empty if the module does not provide any interfaces.
+        """
+
 class IClassDocumentation(zope.interface.Interface):
     """Representation of a class or type for documentation."""
 
@@ -200,3 +207,15 @@
         title=_("XML Root Element"),
         description=_("XML element representing the configuration root."),
         required=True)
+
+
+class ITextFile(zope.interface.Interface):
+    """Text file object"""
+
+    path = zope.schema.BytesLine(
+        title=_('Path'),
+        description=_('Path to the text file'),
+        required=True)
+
+    def getContent():
+        """Return the content of the text file, in unicode"""

Modified: zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/module.py
===================================================================
--- zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/module.py	2009-02-03 08:10:54 UTC (rev 96020)
+++ zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/module.py	2009-02-03 09:41:10 UTC (rev 96021)
@@ -99,7 +99,7 @@
 
         # List the classes and functions in module, if any are available.
         zope.deprecation.__show__.off()
-        module_decl = providedBy(self._module)
+        module_decl = self.getDeclaration()
         ifaces = list(module_decl)
         if ifaces:
             # The module has an interface declaration.  Yay!
@@ -145,21 +145,25 @@
 
 
     def getDocString(self):
-        """See IModule."""
+        """See IModuleDocumentation."""
         return self._module.__doc__
 
     def getFileName(self):
-        """See IModule."""
+        """See IModuleDocumentation."""
         return self._module.__file__
 
     def getPath(self):
-        """See IModule."""
+        """See IModuleDocumentation."""
         return self._module.__name__
 
     def isPackage(self):
         """See IModuleDocumentation."""
         return self._package
 
+    def getDeclaration(self):
+        """See IModuleDocumentation."""
+        return providedBy(self._module)
+
     def get(self, key, default=None):
         """See zope.container.interfaces.IReadContainer."""
         obj = self._children.get(key, default)

Modified: zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/text.py
===================================================================
--- zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/text.py	2009-02-03 08:10:54 UTC (rev 96020)
+++ zope.app.apidoc/trunk/src/zope/app/apidoc/codemodule/text.py	2009-02-03 09:41:10 UTC (rev 96021)
@@ -13,15 +13,17 @@
 ##############################################################################
 """Function representation for code browser
 
-$Id: __init__.py 29143 2005-02-14 22:43:16Z srichter $
+$Id$
 """
 __docformat__ = 'restructuredtext'
 from zope.interface import implements
 from zope.location.interfaces import ILocation
 
+from zope.app.apidoc.codemodule.interfaces import ITextFile
+
 class TextFile(object):
     """This class represents a function declared in the module."""
-    implements(ILocation)
+    implements(ILocation, ITextFile)
 
     def __init__(self, path, name, package):
         self.path = path

Modified: zope.app.apidoc/trunk/src/zope/app/apidoc/utilities.py
===================================================================
--- zope.app.apidoc/trunk/src/zope/app/apidoc/utilities.py	2009-02-03 08:10:54 UTC (rev 96020)
+++ zope.app.apidoc/trunk/src/zope/app/apidoc/utilities.py	2009-02-03 09:41:10 UTC (rev 96021)
@@ -317,10 +317,11 @@
     if module is not None:
         if isinstance(module, (str, unicode)):
             module = sys.modules.get(module, None)
-        format = getDocFormat(module)
+        if format is None:
+            format = getDocFormat(module)
 
     if format is None:
-        format = 'zope.source.stx'
+        format = 'zope.source.rest'
 
     assert format in _format_dict.values()
 



More information about the Checkins mailing list