[Zope3-checkins] CVS: Zope3/src/zope/app/apidoc/ifacemodule - browser.py:1.5

Stephan Richter srichter at cosmos.phy.tufts.edu
Sun Mar 28 18:40:37 EST 2004


Update of /cvs-repository/Zope3/src/zope/app/apidoc/ifacemodule
In directory cvs.zope.org:/tmp/cvs-serv22630/src/zope/app/apidoc/ifacemodule

Modified Files:
	browser.py 
Log Message:


Added tests.



Improve factory detection and URL computation.



Use new class registry to find a list of all classes that implement the
interface.



Fix factories finder.



Better utility info computation.




=== Zope3/src/zope/app/apidoc/ifacemodule/browser.py 1.4 => 1.5 ===
--- Zope3/src/zope/app/apidoc/ifacemodule/browser.py:1.4	Tue Mar  9 07:39:02 2004
+++ Zope3/src/zope/app/apidoc/ifacemodule/browser.py	Sun Mar 28 18:40:36 2004
@@ -15,7 +15,7 @@
 
 $Id$
 """
-
+from types import FunctionType, MethodType, ClassType, TypeType
 from zope.component import ComponentLookupError
 from zope.interface.declarations import providedBy
 from zope.interface.interfaces import IMethod, IInterface 
@@ -24,9 +24,32 @@
 
 from zope.app import zapi
 from zope.app.apidoc.utilities import getPythonPath, stx2html
+from zope.app.apidoc.classmodule import classRegistry
 
 def _get(iface, type):
-    """Return a dictionary containing all the Fields in a schema."""
+    """Return a dictionary containing all the attributes in an interface.
+
+    The type specifies whether we are looking for attributes or methods.
+
+    Example::
+
+      >>> from zope.interface import Interface, Attribute
+      >>> from zope.schema import Field
+
+      >>> class IFoo(Interface):
+      ...     foo = Field()
+      ...     bar = Field()
+      ...     def blah():
+      ...         pass
+
+      >>> _get(IFoo, IMethod).keys()
+      ['blah']
+
+      >>> names = _get(IFoo, IField).keys()
+      >>> names.sort()
+      >>> names
+      ['bar', 'foo']
+    """
     iface = removeAllProxies(iface)
     items = {}
     for name in iface:
@@ -35,28 +58,103 @@
             items[name] = attr
     return items
 
+
 def _getInOrder(iface, type,
                 _itemsorter=lambda x, y: cmp(x[1].order, y[1].order)):
-    """Return a list of (name, value) tuples in native schema order."""
+    """Return a list of (name, value) tuples in native interface order.
+
+    The type specifies whether we are looking for attributes or methods. The
+    '_itemsorter' argument provides the function that is used to order the
+    fields. The default function should be the correct one for 99% of your
+    needs.
+
+    Example::
+
+      >>> from zope.interface import Interface, Attribute
+      >>> from zope.schema import Field
+
+      >>> class IFoo(Interface):
+      ...     foo = Field()
+      ...     bar = Field()
+      ...     def blah():
+      ...         pass
+
+      >>> [n for n, a in _getInOrder(IFoo, IMethod)]
+      ['blah']
+
+      >>> [n for n, a in _getInOrder(IFoo, IField)]
+      ['foo', 'bar']
+    """
     items = _get(iface, type).items()
     items.sort(_itemsorter)
     return items
 
+
 def _getFieldInterface(field):
-    """Return PT-friendly dict about the field's interface."""
+    """Return PT-friendly dict about the field's interface.
+
+    Examples::
+
+      >>> import pprint
+      >>> from zope.interface import implements, Interface
+      
+      >>> class IField(Interface):
+      ...     pass
+      >>> class ISpecialField(IField):
+      ...     pass
+      >>> class Field:
+      ...     implements(IField)
+      >>> class SpecialField:
+      ...     implements(ISpecialField)
+      >>> class ExtraField(SpecialField):
+      ...     pass
+
+      >>> info = _getFieldInterface(Field()).items()
+      >>> info.sort()
+      >>> pprint.pprint(info)
+      [('id', 'zope.app.apidoc.ifacemodule.browser.IField'), ('name', 'IField')]
+
+      >>> info = _getFieldInterface(SpecialField()).items()
+      >>> info.sort()
+      >>> pprint.pprint(info)
+      [('id', 'zope.app.apidoc.ifacemodule.browser.ISpecialField'),
+       ('name', 'ISpecialField')]
+
+      >>> info = _getFieldInterface(ExtraField()).items()
+      >>> info.sort()
+      >>> pprint.pprint(info)
+      [('id', 'zope.app.apidoc.ifacemodule.browser.ISpecialField'),
+       ('name', 'ISpecialField')]
+    """
     field = removeAllProxies(field)
     # This is bad, but due to bootstrapping, directlyProvidedBy does
     # not work 
     name = field.__class__.__name__
     ifaces = list(providedBy(field))
+    # Usually fields have interfaces with the same name (with an 'I')
     for iface in ifaces:
         if iface.getName() == 'I' + name:
             return {'name': iface.getName(), 'id': getPythonPath(iface)}
     # Giving up...
     return {'name': ifaces[0].getName(), 'id': getPythonPath(ifaces[0])}
 
+
 def _getRequired(field):
-    """Return a string representation of whether the field is required."""
+    """Return a string representation of whether the field is required.
+
+    Examples::
+
+      >>> class Field:
+      ...     required = False
+
+      >>> field = Field()
+      >>> _getRequired(field)
+      'optional'
+      >>> field.required = True
+      >>> _getRequired(field)
+      'required'
+
+    """
     if field.required:
         return 'required'
     else:
@@ -66,28 +164,69 @@
 class InterfaceDetails(object):
     """View class for an Interface."""
 
-    def __init__(self, context, request):
-        self.context = context
-        self.request = request
-
     def getId(self):
-        """Return the id of the field as it is defined in the interface
-        service."""
+        """Return the id of the field as it is defined for the interface
+        utility.
+
+        Example::
+
+          >>> from tests import getInterfaceDetails
+          >>> details = getInterfaceDetails()
+          >>> details.getId()
+          'IFoo'
+        """
         return zapi.name(self.context)
 
     def getDoc(self):
-        """Return the main documentation string of the interface."""
+        """Return the main documentation string of the interface.
+
+        Example::
+
+          >>> from tests import getInterfaceDetails
+          >>> details = getInterfaceDetails()
+          >>> details.getDoc()[:34]
+          '<h1>This is the Foo interface</h1>'
+        """
         return stx2html(self.context.getDoc())
 
     def getBases(self):
-        """Get all bases of this class"""
+        """Get all bases of this class
+
+        Example::
+
+          >>> from tests import getInterfaceDetails
+          >>> details = getInterfaceDetails()
+          >>> details.getBases()
+          ['zope.interface.Interface']
+        """
         return [getPythonPath(base) for base in self.context.__bases__]
 
     def getTypes(self):
         """Return a list of interface types that are specified for this
         interface.
 
-        Note that you should only expect one type at a time."""
+        Note that you should only expect one type at a time.
+
+        Example::
+
+          >>> import pprint
+          >>> pprint = pprint.PrettyPrinter(width=69).pprint
+          >>> from tests import getInterfaceDetails
+          >>> from zope.interface import Interface, directlyProvides
+          >>> class IType(Interface):
+          ...     pass
+
+          >>> details = getInterfaceDetails()
+          >>> details.getTypes()
+          []
+
+          >>> directlyProvides(removeAllProxies(details.context), IType)
+          >>> type = details.getTypes()[0].items()
+          >>> type.sort()
+          >>> pprint(type)
+          [('name', 'IType'),
+           ('path', 'zope.app.apidoc.ifacemodule.browser.IType')]
+        """
         context = removeAllProxies(self.context)
         types = list(providedBy(context))
         types.remove(IInterface)
@@ -96,7 +235,23 @@
                 for type in types]
     
     def getAttributes(self):
-        """Return a list of attributes in the order they were specified."""
+        r"""Return a list of attributes in the order they were specified.
+
+        Example::
+
+          >>> import pprint
+          >>> pprint = pprint.PrettyPrinter(width=69).pprint
+          >>> from tests import getInterfaceDetails
+          >>> details = getInterfaceDetails()
+
+          >>> attrs = details.getAttributes()
+          >>> attrs = [a.items() for a in attrs]
+          >>> attrs = [a for a in attrs if a.sort() is None]
+          >>> attrs.sort()
+          >>> pprint(attrs)
+          [[('doc', '<p>This is bar.</p>\n'), ('name', 'bar')],
+           [('doc', '<p>This is foo.</p>\n'), ('name', 'foo')]]
+        """
         iface = removeAllProxies(self.context)
         attrs = []
         for name in iface:
@@ -108,7 +263,27 @@
                 for attr in attrs]
 
     def getMethods(self):
-        """Return a list of methods in the order they were specified."""
+        r"""Return a list of methods in the order they were specified.
+
+        Example::
+
+          >>> import pprint
+          >>> pprint = pprint.PrettyPrinter(width=69).pprint
+          >>> from tests import getInterfaceDetails
+          >>> details = getInterfaceDetails()
+
+          >>> methods = details.getMethods()
+          >>> methods = [m.items() for m in methods]
+          >>> methods = [m for m in methods if m.sort() is None]
+          >>> methods.sort()
+          >>> pprint(methods)
+          [[('doc', '<p>This is blah.</p>\n'),
+            ('name', 'blah'),
+            ('signature', '()')],
+           [('doc', '<p>This is get.</p>\n'),
+            ('name', 'get'),
+            ('signature', '(key, default=None)')]]
+        """        
         methods = []
         return [{'name': method.getName(),
                  'signature': method.getSignatureString(),
@@ -116,61 +291,212 @@
                 for method in _get(self.context, IMethod).values()]
             
     def getFields(self):
-        """Return a list of fields in the order they were specified."""
+        """Return a list of fields in the order they were specified.
+
+        Example::
+
+          >>> import pprint
+          >>> pprint = pprint.PrettyPrinter(width=69).pprint
+          >>> from tests import getInterfaceDetails
+          >>> details = getInterfaceDetails()
+
+          >>> fields = details.getFields()
+
+          Convert all dictionaries to list of tuples and sort them.
+
+          >>> fields = [f.items() for f in fields]
+          >>> fields = [f for f in fields if f.sort() is None]
+          >>> fields = [f[:2] + [(f[2][0], f[2][1].items())] + f[3:]
+          ...           for f in fields]
+          >>> fields = [f for f in fields if f[2][1].sort() is None]
+          >>> pprint(fields)
+          [[('default', "u'Foo'"),
+            ('description', u'Title'),
+            ('iface',
+             [('id', 'zope.schema.interfaces.ITextLine'),
+              ('name', 'ITextLine')]),
+            ('name', 'title'),
+            ('required', 'required')],
+           [('default', "u'Foo.'"),
+            ('description', u'Desc'),
+            ('iface',
+             [('id', 'zope.schema.interfaces.IText'), ('name', 'IText')]),
+            ('name', 'description'),
+            ('required', 'optional')]]
+        """
         fields = map(lambda x: x[1], _getInOrder(self.context, IField))
         return [{'name': field.getName(),
                  'iface': _getFieldInterface(field),
                  'required': _getRequired(field),
-                 'default': field.default.__repr__,
+                 'default': field.default.__repr__(),
                  'description': field.description
                  }
                 for field in fields]
 
     def getRequiredAdapters(self):
-        """Get adapters where this interface is required."""
+        """Get adapters where this interface is required.
+
+        Example::
+
+          >>> import pprint
+          >>> pprint = pprint.PrettyPrinter(width=69).pprint
+          >>> from tests import getInterfaceDetails
+          >>> details = getInterfaceDetails()
+
+          >>> adapters = details.getRequiredAdapters()
+          >>> adapters = [a.items() for a in adapters]
+          >>> adapters = [a for a in adapters if a.sort() is None]
+          >>> adapters.sort()
+          >>> pprint(adapters)
+          [[('factory', 'zope.app.location.LocationPhysicallyLocatable'),
+            ('factory_url', 'zope/app/location/LocationPhysicallyLocatable'),
+            ('name', u''),
+            ('provided',
+             'zope.app.traversing.interfaces.IPhysicallyLocatable'),
+            ('required', [])]]
+        """
         service = zapi.getService(self.context, 'Adapters')
         context = removeAllProxies(self.context)
         adapters = []
         for adapter in service.getRegisteredMatching(required=context):
+            path = getPythonPath(adapter[4])
+            if type(adapter[4]) in (FunctionType, MethodType):
+               url = None
+            else:
+                url = path.replace('.', '/')
             adapters.append({
                 'provided': getPythonPath(adapter[1]),
                 'required': [getPythonPath(iface) for iface in adapter[2]],
                 'name': adapter[3],
-                'factory': getPythonPath(adapter[4][0])
+                'factory': path,
+                'factory_url': url
                 })
         return adapters
         
     def getProvidedAdapters(self):
-        """Get adapters where this interface is provided."""
+        """Get adapters where this interface is provided.
+
+        Example::
+
+          >>> import pprint
+          >>> pprint = pprint.PrettyPrinter(width=69).pprint
+          >>> from tests import getInterfaceDetails
+          >>> details = getInterfaceDetails()
+
+          >>> adapters = details.getProvidedAdapters()
+          >>> adapters = [a.items() for a in adapters]
+          >>> adapters = [a for a in adapters if a.sort() is None]
+          >>> adapters.sort()
+          >>> pprint(adapters)
+          [[('factory', '__builtin__.object'),
+            ('factory_url', '__builtin__/object'),
+            ('name', u''),
+            ('required', ['zope.app.apidoc.ifacemodule.tests.IBar'])]]
+        """
         service = zapi.getService(self.context, 'Adapters')
         context = removeAllProxies(self.context)
         adapters = []
         for adapter in service.getRegisteredMatching(provided=context):
+            path = getPythonPath(adapter[4])
+            if type(adapter[4]) in (FunctionType, MethodType):
+               url = None
+            else:
+                url = path.replace('.', '/')
             adapters.append({
                 'required': [getPythonPath(iface)
                              for iface in adapter[2]+(adapter[0],)],
                 'name': adapter[3],
-                'factory': getPythonPath(adapter[4][0])
+                'factory': path,
+                'factory_url': url
                 })
         return adapters
 
+    def getClasses(self):
+        """Get the classes that implement this interface.
+
+        Example::
+
+          >>> import pprint
+          >>> pprint = pprint.PrettyPrinter(width=69).pprint
+          >>> from tests import getInterfaceDetails
+          >>> details = getInterfaceDetails()
+
+          >>> classes = details.getClasses()
+          >>> classes = [c.items() for c in classes]
+          >>> classes = [c for c in classes if c.sort() is None]
+          >>> classes.sort()
+          >>> pprint(classes)
+          [[('path', 'zope.app.apidoc.ifacemodule.tests.Foo'),
+            ('url', 'zope/app/apidoc/ifacemodule/tests/Foo')]]
+        """
+        iface = removeAllProxies(self.context)
+        classes = classRegistry.getClassesThatImplement(iface)
+        return [{'path': path, 'url': path.replace('.', '/')}
+                for path, klass in classes]
+
     def getFactories(self):
         """Return the factories, who will provide objects implementing this
-        interface."""
+        interface.
+
+        Example::
+
+          >>> from tests import getInterfaceDetails
+          >>> details = getInterfaceDetails()
+
+          >>> factories = details.getFactories()
+          >>> factories = [f.items() for f in factories]
+          >>> factories = [f for f in factories if f.sort() is None]
+          >>> factories.sort()
+          >>> factories
+          [[('name', 'FooFactory'), ('title', 'Foo Factory')]]
+        """
         iface = removeAllProxies(self.context)
-        return [{'name': n, 'factory': f, 'title': f.title} \
-                for n, f in zapi.queryUtilitiesFor(IFactory, ()) \
-                if ISource in tuple(f.getInterfaces)]
+        return [{'name': n, 'title': f.title} \
+                for n, f in zapi.getFactoriesFor(self.context, iface) \
+                if iface in tuple(f.getInterfaces())]
 
     def getUtilities(self):
-        """Return all utilities that provide this interface."""
+        """Return all utilities that provide this interface.
+
+        Example::
+
+          >>> import pprint
+          >>> pprint = pprint.PrettyPrinter(width=69).pprint
+          >>> from tests import getInterfaceDetails
+          >>> details = getInterfaceDetails()
+
+          >>> utils = details.getUtilities()
+          >>> utils = [u.items() for u in utils]
+          >>> utils = [u for u in utils if u.sort() is None]
+          >>> utils.sort()
+          >>> pprint(utils)
+          [[('name', 'The Foo'),
+            ('path', 'zope.app.apidoc.ifacemodule.tests.Foo'),
+            ('url', 'zope/app/apidoc/ifacemodule/tests/Foo')]]
+        """
         service = zapi.getService(self.context, 'Utilities')
         utils = service.getUtilitiesFor(removeAllProxies(self.context))
-        return [{'name': util[0],
-                 'path': getPythonPath(util[1].__class__)} for util in utils]
+        info = []
+        for name, util in utils:
+            if type(util) in (ClassType, TypeType):
+                klass = util
+            else:
+                klass = util.__class__
+            path = getPythonPath(klass)
+            info.append({'name': name, 'path': path,
+                         'url': path.replace('.', '/')})
+        return info
 
     def getServices(self):
-        """Return all services (at most one)  that provide this interface."""
+        """Return all services (at most one)  that provide this interface.
+
+        Example::
+
+          >>> from tests import getInterfaceDetails
+          >>> details = getInterfaceDetails()
+          >>> details.getServices()
+          ['Foo']
+        """
         iface = removeAllProxies(self.context)
         service = zapi.getService(self.context, 'Services')
         services = service.getServiceDefinitions()




More information about the Zope3-Checkins mailing list