[Zope3-checkins] SVN: Zope3/trunk/src/zope/ Changed implementedBy so it always suceeds for callable objects.

Jim Fulton jim at zope.com
Fri Feb 11 12:44:17 EST 2005


Log message for revision 29118:
  Changed implementedBy so it always suceeds for callable objects.
  
  Added an api function, factoryImplements, for declating interfaces
  implemented by a factory, which are the interfaces provided by the
  objects created by the factory.
  

Changed:
  U   Zope3/trunk/src/zope/component/factory.py
  U   Zope3/trunk/src/zope/component/tests/test_factory.py
  U   Zope3/trunk/src/zope/interface/README.txt
  U   Zope3/trunk/src/zope/interface/__init__.py
  U   Zope3/trunk/src/zope/interface/declarations.py
  U   Zope3/trunk/src/zope/interface/interfaces.py

-=-
Modified: Zope3/trunk/src/zope/component/factory.py
===================================================================
--- Zope3/trunk/src/zope/component/factory.py	2005-02-11 17:04:02 UTC (rev 29117)
+++ Zope3/trunk/src/zope/component/factory.py	2005-02-11 17:44:16 UTC (rev 29118)
@@ -41,9 +41,4 @@
             spec = Implements(*self._interfaces)
             spec.__name__ = getattr(self._callable, '__name__', '[callable]')
             return spec
-        try:
-            return implementedBy(self._callable)
-        except TypeError:
-            spec = Implements()
-            spec.__name__ = getattr(self._callable, '__name__', '[callable]')
-            return spec
+        return implementedBy(self._callable)

Modified: Zope3/trunk/src/zope/component/tests/test_factory.py
===================================================================
--- Zope3/trunk/src/zope/component/tests/test_factory.py	2005-02-11 17:04:02 UTC (rev 29117)
+++ Zope3/trunk/src/zope/component/tests/test_factory.py	2005-02-11 17:44:16 UTC (rev 29118)
@@ -66,16 +66,12 @@
         implemented = self._factory.getInterfaces()
         self.assert_(implemented.isOrExtends(IKlass))
         self.assertEqual(list(implemented), [IKlass])
-        self.assertEqual(implemented.__name__,
-                         'zope.component.tests.test_factory.Klass')
 
         implemented2 = self._factory2.getInterfaces()
         self.assertEqual(list(implemented2), [])
-        self.assertEqual(implemented2.__name__, '<lambda>')
 
         implemented3 = self._factory3.getInterfaces()
         self.assertEqual(list(implemented3), [IFunction])
-        self.assertEqual(implemented3.__name__, '<lambda>')
 
 
 class TestFactoryZAPIFunctions(PlacelessSetup, unittest.TestCase):

Modified: Zope3/trunk/src/zope/interface/README.txt
===================================================================
--- Zope3/trunk/src/zope/interface/README.txt	2005-02-11 17:04:02 UTC (rev 29117)
+++ Zope3/trunk/src/zope/interface/README.txt	2005-02-11 17:44:16 UTC (rev 29118)
@@ -147,9 +147,16 @@
    It is important to note that classes don't usually provide the
    interfaces that the implement.
 
+   We can generalize this to factories.  For any callable object we
+   can declare that it produces objects that provides some interfaces
+   by saying that the factory implements the interfaces.
+
 Now that we've defined these terms, we can talk about the API for
 declaring interfaces.
 
+Declaring implemented interfaces
+--------------------------------
+
 The most common way to declare interfaces is using the implements
 function in a class statement::
 
@@ -190,17 +197,18 @@
   >>> list(zope.interface.implementedBy(Foo))
   [<InterfaceClass __main__.IFoo>]
 
-It's an error to ask for interfaces implemented by a non-class::
+It's an error to ask for interfaces implemented by a non-callable
+object::
 
   >>> IFoo.implementedBy(foo)
   Traceback (most recent call last):
   ...
-  TypeError: ('ImplementedBy called for non-type', Foo(None))
+  TypeError: ('ImplementedBy called for non-factory', Foo(None))
 
   >>> list(zope.interface.implementedBy(foo))
   Traceback (most recent call last):
   ...
-  TypeError: ('ImplementedBy called for non-type', Foo(None))
+  TypeError: ('ImplementedBy called for non-factory', Foo(None))
 
 Similarly, we can ask what interfaces are provided by an object::
 
@@ -209,6 +217,36 @@
   >>> list(zope.interface.providedBy(Foo))
   []
 
+We can declare interfaces implemented by other factories (besides
+classes).  We do this using a Python-2.4-style decorator named
+`implementer`.  In versions of Python before 2.4, this looks like:
+
+
+  >>> def yfoo(y):
+  ...     foo = Foo()
+  ...     foo.y = y
+  ...     return foo
+  >>> zope.interface.implementer(IFoo)(yfoo)
+
+  >>> list(zope.interface.implementedBy(yfoo))
+  [<InterfaceClass __main__.IFoo>]
+
+Note that the implementer decorator may modify it's argument. Callers
+should not assume that a new object is created.
+
+Also note that, at least for now, implementer cannt be used with
+classes:
+
+  >>> zope.interface.implementer(IFoo)(Foo)
+  ... # doctest: +NORMALIZE_WHITESPACE
+  Traceback (most recent call last):
+    ...
+  TypeError: Can't use implementer with classes.  
+  Use one of the class-declaration functions instead.
+
+Declaring provided interfaces
+-----------------------------
+
 We can declare interfaces directly provided by objects.  Suppose that
 we want to document what the `__init__` method of the `Foo` class
 does.  It's not *really* part of `IFoo`.  You wouldn't normally call

Modified: Zope3/trunk/src/zope/interface/__init__.py
===================================================================
--- Zope3/trunk/src/zope/interface/__init__.py	2005-02-11 17:04:02 UTC (rev 29117)
+++ Zope3/trunk/src/zope/interface/__init__.py	2005-02-11 17:44:16 UTC (rev 29118)
@@ -63,7 +63,7 @@
 from zope.interface.declarations import providedBy, implementedBy
 from zope.interface.declarations import classImplements, classImplementsOnly
 from zope.interface.declarations import directlyProvidedBy, directlyProvides
-from zope.interface.declarations import alsoProvides
+from zope.interface.declarations import alsoProvides, implementer
 from zope.interface.declarations import implements, implementsOnly
 from zope.interface.declarations import classProvides, moduleProvides
 from zope.interface.declarations import Declaration

Modified: Zope3/trunk/src/zope/interface/declarations.py
===================================================================
--- Zope3/trunk/src/zope/interface/declarations.py	2005-02-11 17:04:02 UTC (rev 29117)
+++ Zope3/trunk/src/zope/interface/declarations.py	2005-02-11 17:44:16 UTC (rev 29118)
@@ -346,7 +346,9 @@
         try:
             bases = cls.__bases__
         except AttributeError:
-            raise TypeError("ImplementedBy called for non-type", cls)
+            if not callable(cls):
+                raise TypeError("ImplementedBy called for non-factory", cls)
+            bases = ()
 
         spec = Implements(*[implementedBy(c) for c in bases])
         spec.inherit = cls
@@ -485,6 +487,23 @@
     classImplements(cls, *interfaces)
     return cls
 
+
+class implementer:
+
+    def __init__(self, *interfaces):
+        self.interfaces = interfaces
+
+    def __call__(self, ob):
+        if isinstance(ob, DescriptorAwareMetaClasses):
+            raise TypeError("Can't use implementer with classes.  Use one of "
+                            "the class-declaration functions instead."
+                            )
+        spec = Implements(*self.interfaces)
+        try:
+            ob.__implemented__ = spec
+        except AttributeError:
+            raise TypeError("Can't declare implements", ob)
+
 def _implements(name, interfaces, classImplements):
     frame = sys._getframe(2)
     locals = frame.f_locals

Modified: Zope3/trunk/src/zope/interface/interfaces.py
===================================================================
--- Zope3/trunk/src/zope/interface/interfaces.py	2005-02-11 17:04:02 UTC (rev 29117)
+++ Zope3/trunk/src/zope/interface/interfaces.py	2005-02-11 17:44:16 UTC (rev 29118)
@@ -418,6 +418,14 @@
         instances of ``A`` and ``B`` provide.
         """
 
+    def implementer(*interfaces):
+        """Create a decorator for declaring interfaces implemented by a facory
+
+        A callable is returned that makes an implements declaration on
+        objects passed to it.
+        
+        """
+
     def classImplementsOnly(class_, *interfaces):
         """Declare the only interfaces implemented by instances of a class
 



More information about the Zope3-Checkins mailing list