[Zope3-checkins] SVN: Zope3/trunk/src/zope/app/apidoc/ifacemodule/ Changed the interface module menu to provide a search field instead of the

Stephan Richter srichter at cosmos.phy.tufts.edu
Wed Feb 16 17:50:39 EST 2005


Log message for revision 29172:
  Changed the interface module menu to provide a search field instead of the 
  not so effective tree; you have the choice between name and full-text 
  search. 
  
  
  
  

Changed:
  U   Zope3/trunk/src/zope/app/apidoc/ifacemodule/configure.zcml
  U   Zope3/trunk/src/zope/app/apidoc/ifacemodule/ftests.py
  U   Zope3/trunk/src/zope/app/apidoc/ifacemodule/menu.pt
  U   Zope3/trunk/src/zope/app/apidoc/ifacemodule/menu.py

-=-
Modified: Zope3/trunk/src/zope/app/apidoc/ifacemodule/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/ifacemodule/configure.zcml	2005-02-16 21:20:50 UTC (rev 29171)
+++ Zope3/trunk/src/zope/app/apidoc/ifacemodule/configure.zcml	2005-02-16 22:50:38 UTC (rev 29172)
@@ -27,12 +27,6 @@
 
   <!-- Interface Documentation Module Menu -->
 
-  <adapter
-      provides="zope.app.tree.interfaces.IChildObjects"
-      for=".IInterfaceModule"
-      factory=".menu.InterfaceModuleChildObjects"
-      />
-
   <browser:page
       for=".InterfaceModule"
       permission="zope.app.apidoc.UseAPIDoc"

Modified: Zope3/trunk/src/zope/app/apidoc/ifacemodule/ftests.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/ifacemodule/ftests.py	2005-02-16 21:20:50 UTC (rev 29171)
+++ Zope3/trunk/src/zope/app/apidoc/ifacemodule/ftests.py	2005-02-16 22:50:38 UTC (rev 29172)
@@ -24,11 +24,12 @@
     def testMenu(self):
         response = self.publish(
             '/++apidoc++/Interface/menu.html', 
-            basic='mgr:mgrpw')
+            basic='mgr:mgrpw',
+            env = {'name_only': True, 'search_str': 'IComponent'})
         self.assertEqual(response.getStatus(), 200)
         body = response.getBody()
         self.assert_(body.find(
-            'zope.app.apidoc.ifacemodule.IInterfaceModule') > 0)
+            'zope.app.component.interfaces.registration.IComponent') > 0)
         self.checkForBrokenLinks(body, '/++apidoc++/Interface/menu.html',
                                  basic='mgr:mgrpw')
 

Modified: Zope3/trunk/src/zope/app/apidoc/ifacemodule/menu.pt
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/ifacemodule/menu.pt	2005-02-16 21:20:50 UTC (rev 29171)
+++ Zope3/trunk/src/zope/app/apidoc/ifacemodule/menu.pt	2005-02-16 22:50:38 UTC (rev 29172)
@@ -1,6 +1,35 @@
 <html metal:use-macro="views/apidoc_macros/menu">
 <body>
 
+  <div metal:fill-slot="menu" class="small">
+
+    <div>
+      <span i18n:translate="">Interface Finder:</span> 
+    </div>
+    <form action="menu.html" method="post">
+      <input type="checkbox" name="name_only" value="on" checked="checked" />
+      name only search
+      <br />
+      <input type="text" name="search_str" 
+             style="font-size: 80%; width=95%" 
+             tal:attributes="value request/search_str|nothing" />
+      <input type="submit" name="SUBMIT" value="Find" 
+             i18n:attributes="value find-button" style="font-size: 80%"/>
+    </form>
+
+    <div tal:define="ifaces view/findInterfaces"
+         tal:condition="ifaces">
+    
+      <a href="" target="main"
+         tal:repeat="info ifaces"
+         tal:attributes="href info/url"
+         tal:content="info/name">
+        zope.app.component.interfaces.ILocalSiteManager
+      </a>
+    </div>
+
+  </div>
+
   <p metal:fill-slot="post_menu" class="small" i18n:translate="">
     Note: These are only interfaces that are registered with the site manager. 
   </p>

Modified: Zope3/trunk/src/zope/app/apidoc/ifacemodule/menu.py
===================================================================
--- Zope3/trunk/src/zope/app/apidoc/ifacemodule/menu.py	2005-02-16 21:20:50 UTC (rev 29171)
+++ Zope3/trunk/src/zope/app/apidoc/ifacemodule/menu.py	2005-02-16 22:50:38 UTC (rev 29172)
@@ -20,160 +20,108 @@
 $Id$
 """
 __docformat__ = 'restructuredtext'
-
-from zope.interface import implements
 from zope.security.proxy import removeSecurityProxy
 
-from zope.app import zapi
-from zope.app.location.interfaces import ILocation
-from zope.app.location import LocationProxy
-from zope.app.tree.interfaces import IChildObjects
+def getAllTextOfInterface(iface):
+    """Get all searchable text from an interface
 
-from zope.app.apidoc.ifacemodule import IInterfaceModule
-from zope.app.apidoc.utilities import ReadContainerBase
+    Example:
 
-class IModule(ILocation):
-    """Represents some module
-
-    Marker interface, so that we can register an adapter for it."""
+    >>> import zope.interface
+    >>> import zope.schema
+    >>> class IFoo(zope.interface.Interface):
+    ...     '''foo'''
+    ...
+    ...     def bar(self):
+    ...         '''bar'''
+    ...
+    ...     blah = zope.interface.Attribute('blah', 'blah')
+    ...
+    ...     field = zope.schema.Field(
+    ...         title = u'title', description = u'description')
     
-
-class Module(ReadContainerBase):
-    r"""Represents a Python module
-
-    Examples: zope, zope.app, zope.app.interfaces
-
-    However, we usually use it only for the last case.
-
-    Usage::
-
-      >>> from zope.app.apidoc.ifacemodule import InterfaceModule
-
-      >>> module = Module(InterfaceModule(), 'zope.app')
-      >>> module.get('apidoc.interfaces.IDocumentationModule').getName()
-      'IDocumentationModule'
-
-      >>> module.get(
-      ...     'zope.app.apidoc.interfaces.IDocumentationModule') is None
-      True
-
-      >>> print '\n'.join([id for id, iface in module.items()])
-      zope.app.apidoc.interfaces.IDocumentationModule
-    """
+    Now get the text. Note that there is no particular order during the text
+    collection.
     
-    implements(IModule)
+    >>> text = getAllTextOfInterface(IFoo)
+    >>> u'foo' in text
+    True
+    >>> u'bar' in text
+    True
+    >>> u'blah' in text
+    True
+    >>> u'field' in text
+    True
+    >>> u'title' in text
+    True
+    >>> u'description' in text
+    True
+    """
+    iface = removeSecurityProxy(iface)
+    text = iface.__doc__ or ''
+    for name in iface:
+        attr = iface[name]
+        text += attr.getName()
+        text += attr.getDoc()
+    return text
 
-    def __init__(self, parent, name):
-        self.__parent__ = parent
-        self.__name__ = name
 
-    def get(self, key, default=None):
-        name = self.__name__ + '.' + key
-        return self.__parent__.get(name, default)
+class Menu(object):
+    """Menu for the Interface Documentation Module.
 
-    def items(self):
-        parent = self.__parent__
-        items = []
-        for key in parent.keys():
-            if key.startswith(self.__name__):
-                items.append((key, LocationProxy(parent[key], self, key)))
-        return items
-
-
-class InterfaceModuleChildObjects(object):
-    r"""Module Adapter for Static Tree
-
-    This adapter is used when building a static tree for the browser.
-
-    Functionality::
-
-      >>> from zope.app.apidoc.ifacemodule import InterfaceModule
-      >>> from zope.app.apidoc.ifacemodule import tests
-
-      >>> module = InterfaceModule()
-      >>> module = tests.rootLocation(module, 'Interface')
-      >>> adapter = InterfaceModuleChildObjects(module)
-      >>> adapter.hasChildren()
-      True
-
-      >>> print '\n'.join([c.__name__ for c in adapter.getChildObjects()])
-      IInterfaceModule
-      zope.app.apidoc.interfaces
+    The menu allows for looking for interfaces by full-text search or partial
+    names. See `findInterfaces()` for the simple search implementation.
     """
 
-    implements(IChildObjects)
-    __used_for__ = IInterfaceModule
+    def findInterfaces(self):
+        """Find the interface that match any text in the documentation strings
+        or a partial path.
 
-    def __init__(self, context):
-        self.context = context
+        Before we can test the method, let's create a Menu instance:
 
-    def hasChildren(self):
-        """See zope.app.tree.interfaces.IChildObject"""
-        return bool(len(self.context))
+        >>> from zope.interface.interfaces import IElement, IAttribute
 
-    def getChildObjects(self):
-        """See zope.app.tree.interfaces.IChildObject"""
-        objects = {}
-        names = removeSecurityProxy(self.context.keys())
-        names.sort()
-        for name in names:
-            # Split these long names and make part of the module path separate
-            # entries. Currently we only split by the term '.interfaces', but
-            # a more sophisticated algorithm could be developed. 
-            iface_loc = name.find('.interfaces')
-            if iface_loc == -1:
-                objects[name] = LocationProxy(self.context[name],
-                                              self.context, name)
-            else:
-                module_name = name[:iface_loc+11]
-                objects[module_name] = Module(self.context, module_name)
-        items = objects.items()
-        items.sort()
-        return [x[1] for x in items]
+        >>> menu = Menu()
+        >>> menu.context = {'IElement': IElement, 'IAttribute': IAttribute}
+        >>> menu.request = {'name_only': 'on', 'search_str': ''}
 
+        Now let's see how successful our searches are:
 
-class Menu(object):
-    """Menu View Helper Class
+        >>> from zope.app.apidoc.tests import pprint
+        >>> menu.request['search_str'] = 'Elem'
+        >>> pprint(menu.findInterfaces())
+        [[('name', 'IElement'), ('url', './IElement/apiindex.html')]]
 
-    A class that helps building the menu. The menu_macros expects the menu view
-    class to have the `getMenuTitle(node)` and `getMenuLink(node)` methods
-    implemented. `node` is a `zope.app.tree.node.Node` instance.
+        >>> menu.request['search_str'] = 'I'
+        >>> pprint(menu.findInterfaces())
+        [[('name', 'IAttribute'), ('url', './IAttribute/apiindex.html')],
+         [('name', 'IElement'), ('url', './IElement/apiindex.html')]]
 
-    Examples::
+        Now using the full text search:
 
-      >>> from zope.app.apidoc.ifacemodule import InterfaceModule
-      >>> from zope.app.apidoc.ifacemodule.tests import Root
-      >>> from zope.app.tree.node import Node 
+        >>> del menu.request['name_only']
 
-      >>> ifacemod = InterfaceModule()
-      >>> ifacemod.__parent__ = Root()
-      >>> ifacemod.__name__ = 'Interfaces'
-      >>> mod = Module(ifacemod, 'zope.app.apidoc.interfaces')
-      >>> menu = Menu()
+        >>> menu.request['search_str'] = 'object'
+        >>> pprint(menu.findInterfaces())
+        [[('name', 'IAttribute'), ('url', './IAttribute/apiindex.html')],
+         [('name', 'IElement'), ('url', './IElement/apiindex.html')]]
 
-      >>> node = Node(mod.get('IDocumentationModule'))
-      >>> menu.getMenuTitle(node)
-      'zope.app.apidoc.interfaces.IDocumentationModule'
-
-      >>> values = mod.values()
-      >>> values.sort()
-      >>> node = Node(values[0])
-      >>> menu.getMenuTitle(node)
-      u'IDocumentationModule'
-
-      >>> menu.getMenuLink(node)
-      u'./zope.app.apidoc.interfaces.IDocumentationModule/apiindex.html'
-    """
-
-    def getMenuTitle(self, node):
-        """Return the title of the node that is displayed in the menu."""
-        if zapi.isinstance(node.context.__parent__, Module):
-            parent = node.context.__parent__
-            return zapi.name(node.context).replace(zapi.name(parent)+'.', '')
-        return zapi.name(node.context)
-
-    def getMenuLink(self, node):
-        """Return the HTML link of the node that is displayed in the menu."""
-        if zapi.isinstance(node.context, Module):
-            return None
-        return './' + zapi.name(node.context) + '/apiindex.html'
+        >>> menu.request['search_str'] = 'Stores'
+        >>> pprint(menu.findInterfaces())
+        [[('name', 'IAttribute'), ('url', './IAttribute/apiindex.html')]]
+        """
+        name_only = ('name_only' in self.request) and True or False
+        search_str = self.request.get('search_str', None)
+        results = []
+        
+        if search_str is None:
+            return results
+        for name, iface in self.context.items():
+            if (search_str in name or
+                (not name_only and search_str in getAllTextOfInterface(iface))):
+                results.append(
+                    {'name': name,
+                     'url': './%s/apiindex.html' %name
+                     })
+        results.sort(lambda x, y: cmp(x['name'], y['name']))
+        return results



More information about the Zope3-Checkins mailing list