[Zope3-checkins] CVS: Zope3/src/zope/interface - adapter.py:1.4 implementor.py:1.5 implements.py:1.5 interface.py:1.9 type.py:1.8 verify.py:1.6

Jim Fulton jim@zope.com
Sat, 3 May 2003 12:36:35 -0400


Update of /cvs-repository/Zope3/src/zope/interface
In directory cvs.zope.org:/tmp/cvs-serv24176/src/zope/interface

Modified Files:
	adapter.py implementor.py implements.py interface.py type.py 
	verify.py 
Log Message:
Updated to use new interface declaration machinery.



=== Zope3/src/zope/interface/adapter.py 1.3 => 1.4 ===
--- Zope3/src/zope/interface/adapter.py:1.3	Mon Jan 20 15:02:52 2003
+++ Zope3/src/zope/interface/adapter.py	Sat May  3 12:36:05 2003
@@ -19,16 +19,17 @@
 """
 __metaclass__ = type # All classes are new style when run with Python 2.2+
 
-from zope.interface import Interface
+from zope.interface import Interface, implements, providedBy
+from zope.interface import InterfaceSpecification
 from zope.interface.interfaces import IInterface
-from zope.interface._flatten import _flatten
 from zope.interface.interfaces import IAdapterRegistry
+from _flatten import _flatten
 
 class AdapterRegistry:
     """Adapter-style interface registry
     """
 
-    __implements__ = IAdapterRegistry
+    implements(IAdapterRegistry)
 
     # The implementation uses a mapping:
     #
@@ -90,7 +91,18 @@
             cache = getattr(self, '_v_cache', self)
             if cache is self:
                 cache = self._v_cache = {}
-            key = `ob_interface_provide`
+
+            # get the cache key
+            interfaces, provide = ob_interface_provide
+            try:
+                key = interfaces.__signature__
+            except AttributeError:
+                if interfaces is None:
+                    key = None
+                else:
+                    key = InterfaceSpecification(interfaces).__signature__
+            key = key, provide.__identifier__
+                
             cached = cache.get(key, self)
             if cached is self:
                 cached = self._uncached_get(ob_interface_provide,
@@ -102,8 +114,20 @@
                                   default, filter)
 
     def _uncached_get(self, (ob_interface, provide), default, filter):
+
+        try:
+            flattened = ob_interface.flattened
+        except AttributeError:
+            # Somebodey (probably a test) passed us a bare interface
+            if ob_interface is not None:
+                flattened = InterfaceSpecification(ob_interface).flattened()
+            else:
+                flattened = None,
+        else:
+            flattened = flattened()
         
-        for interface in _flatten(ob_interface, 1):
+
+        for interface in flattened:
             c = self._reg.get((interface, provide))
             if c:
                 c = c[1]
@@ -111,12 +135,21 @@
                     return c
                 if filter(c):
                     return c
+        
+        c = self._reg.get((None, provide))
+        if c:
+            c = c[1]
+            if filter is None:
+                return c
+            if filter(c):
+                return c
+
+
 
         return default
 
     def getForObject(self, object, interface, filter=None):
-        return self.get((getattr(object, '__implements__', None), interface),
-                        filter=filter)
+        return self.get((providedBy(object), interface), filter=filter)
 
     def getRegistered(self, require, provide):
         data = self._reg.get((require, provide))


=== Zope3/src/zope/interface/implementor.py 1.4 => 1.5 ===
--- Zope3/src/zope/interface/implementor.py:1.4	Thu Apr  3 17:05:35 2003
+++ Zope3/src/zope/interface/implementor.py	Sat May  3 12:36:05 2003
@@ -19,7 +19,7 @@
 """
 __metaclass__ = type # All classes are new style when run with Python 2.2+
 
-from zope.interface import Interface
+from zope.interface import Interface, implements
 from zope.interface.interfaces import IInterface
 from zope.interface.interfaces import IImplementorRegistry
 
@@ -27,7 +27,7 @@
     """Implementor-style interface registry
     """
 
-    __implements__ = IImplementorRegistry
+    implements(IImplementorRegistry)
 
     # The implementation uses a mapping:
     #


=== Zope3/src/zope/interface/implements.py 1.4 => 1.5 ===
--- Zope3/src/zope/interface/implements.py:1.4	Thu Apr 10 11:43:16 2003
+++ Zope3/src/zope/interface/implements.py	Sat May  3 12:36:05 2003
@@ -17,42 +17,20 @@
 $Id$
 """
 
+from zope.interface.declarations import providedBy, implementedBy
+from zope.interface.declarations import classImplements
+from zope.interface.declarations import InterfaceSpecification
+
+
 from zope.interface import exceptions
 from zope.interface.verify import verifyClass
 from zope.interface.interface import InterfaceClass
 from types import TupleType, ClassType, StringType
 
-# Special value indicating the object supports
-# what its class supports.
-CLASS_INTERFACES = 1
-
-ClassTypes = ClassType, type
-
-_typeImplements = {}
-
-def getImplements(object):
-    # Decide whether or not the object is a class.  If it is a class,
-    # return it's __class_implements__ rather than its __implements__.
-    if isinstance(object, ClassTypes):
-        ci = getattr(object, '__class_implements__', None)
-        if ci is not None:
-            return ci
-    else:
-        impl = getattr(object, '__implements__', None)
-        if impl is not None:
-            return impl
-
-    return _typeImplements.get(type(object))
-
+getImplements = providedBy
+getImplementsOfInstances = implementedBy
 
-def getImplementsOfInstances(klass):
-    if isinstance(klass, ClassTypes):
-        return getattr(klass, '__implements__', None)
-    else:
-        return _typeImplements.get(klass)
-
-
-def visitImplements(implements, object, visitor, getInterface=None):
+def visitImplements(implements, object, visitor):
     """Call visitor for each interace.
 
     Visits the interfaces described by an __implements__ attribute,
@@ -60,76 +38,27 @@
     If the visitor returns anything true, the loop stops.
     This does not, and should not, visit superinterfaces.
     """
-    # this allows us to work with proxy wrappers in Python 2.2,
-    # yet remain compatible with earlier versions of python.
-    implements_class = getattr(implements, '__class__', None)
-
-    if InterfaceClass in implements_class.__mro__:
-        return visitor(implements)
-    elif implements == CLASS_INTERFACES:
-        klass = getattr(object, '__class__', None)
-        if klass is not None:
-            i = getImplementsOfInstances(klass)
-            if i:
-                return visitImplements(i, object, visitor, getInterface)
-    elif implements_class == StringType or type(implements) is StringType:
-        if getInterface is not None:
-            # Look up a named interface.
-            i = getInterface(object, implements)
-            if i is not None:
-                return visitImplements(i, object, visitor, getInterface)
-    elif implements_class == TupleType or type(implements) is TupleType:
-        for i in implements:
-            r = visitImplements(i, object, visitor, getInterface)
-            if r:
-                # If the visitor returns anything true, stop.
-                return r
-    else:
-        if implements_class is not None and \
-           type(implements) != implements_class:
-            raise exceptions.BadImplements(
-                """__implements__ should be an interface or tuple,
-                not a %s pretending to be a %s"""
-                % (type(implements).__name__, implements_class.__name__)
-                )
-        raise exceptions.BadImplements(
-            """__implements__ should be an interface or tuple,
-            not a %s""" % type(implements).__name__)
-    return None
-
-
-def assertTypeImplements(type, interfaces):
-    """Assign a set of interfaces to a Python type such as int, str, tuple,
-       list and dict.
-    """
-    _typeImplements[type] = interfaces
 
-def objectImplements(object, getInterface=None):
-    r = []
-    implements = getImplements(object)
-    if not implements:
-        return r
-    visitImplements(implements, object, r.append, getInterface)
-    return r
-
-def instancesOfObjectImplements(klass, getInterface=None):
-    r = []
-    implements = getImplementsOfInstances(klass)
-    if not implements:
-        return r
-    visitImplements(implements, klass, r.append, getInterface)
-    return r
+    for interface in InterfaceSpecification(implements):
+        if visitor(interface):
+            break
+
+
+assertTypeImplements = classImplements
+
+objectImplements = providedBy
+instancesOfObjectImplements = implementedBy
 
 def _flatten(i, append):
-    if isinstance(i, (list, tuple)):
-        for iface in i:
-            _flatten(iface, append)
-    else:
+    if InterfaceClass in i.__class__.__mro__:
         append(i)
         bases = i.getBases()
         if bases:
             for b in bases:
                 _flatten(b, append)
+    else:
+        for iface in i:
+            _flatten(iface, append)
 
 def flattenInterfaces(interfaces, remove_duplicates=1):
     res = []


=== Zope3/src/zope/interface/interface.py 1.8 => 1.9 ===
--- Zope3/src/zope/interface/interface.py:1.8	Mon Apr 14 04:29:09 2003
+++ Zope3/src/zope/interface/interface.py	Sat May  3 12:36:05 2003
@@ -17,6 +17,7 @@
 $Id$
 """
 
+import sys
 from inspect import currentframe
 from types import FunctionType
 
@@ -75,17 +76,22 @@
                  __module__=None):
 
         if __module__ is None:
-            if attrs is not None and ('__module__' in attrs):
+            if (attrs is not None and
+                ('__module__' in attrs) and
+                isinstance(attrs['__module__'], str)
+                ):
                 __module__ = attrs['__module__']
                 del attrs['__module__']
             else:
+
                 try:
                     # Figure out what module defined the interface.
                     # This is how cPython figures out the module of
                     # a class, but of course it does it in C. :-/
-                    __module__ = currentframe().f_back.f_globals['__name__']
+                    __module__ = sys._getframe(1).f_globals['__name__']
                 except (AttributeError, KeyError):
                     pass
+
         self.__module__ = __module__
 
         for b in bases:
@@ -108,6 +114,8 @@
 
         Element.__init__(self, name, __doc__)
 
+        self.__iro__ = mergeOrderings([_flattenInterface(self, [])])
+
         for k, v in attrs.items():
             if isinstance(v, Attribute):
                 v.interface = name
@@ -120,6 +128,9 @@
 
         self.__attrs = attrs
 
+        self.__identifier__ = "%s.%s" % (self.__module__, self.__name__)
+
+
     def getBases(self):
         return self.__bases__
 
@@ -143,34 +154,25 @@
         """Does the given object implement the interface?"""
 
         # OPT Cache implements lookups
-        implements = getImplements(object)
-        if implements is None:
-            return False
-
+        implements = providedBy(object)
         cache = getattr(self, '_v_cache', self)
         if cache is self:
             cache = self._v_cache = {}
 
-        key = `implements`
+
+        key = implements.__signature__
 
         r = cache.get(key)
         if r is None:
-            r = bool(
-                visitImplements(
-                  implements, object, self.isEqualOrExtendedBy,
-                  self._getInterface)
-                )
+            r = bool(implements.extends(self))
             cache[key] = r
 
         return r
 
     def isImplementedByInstancesOf(self, klass):
         """Do instances of the given class implement the interface?"""
-        i = getImplementsOfInstances(klass)
-        if i is not None:
-            return visitImplements(
-                i, klass, self.isEqualOrExtendedBy, self._getInterface)
-        return False
+        i = implementedBy(klass)
+        return bool(i.extends(self))
 
     def names(self, all=False):
         """Return the attribute names defined by the interface."""
@@ -329,7 +331,48 @@
         return c > 0
 
 
-Interface = InterfaceClass("Interface")
+def mergeOrderings(orderings, seen=None):
+    """Merge multiple orderings so that within-ordering order is preserved
+
+    Orderings are constrained in such a way that if an object appears
+    in two or more orderings, then the suffix that begins with the
+    object must be in both orderings.
+
+    For example:
+
+    >>> _mergeOrderings([
+    ... ['x', 'y', 'z'],
+    ... ['q', 'z'],
+    ... [1, 3, 5],
+    ... ['z']
+    ... ])
+    ['x', 'y', 'q', 1, 3, 5, 'z']
+
+    """
+
+    if seen is None:
+        seen = {}
+    result = []
+    orderings.reverse()
+    for ordering in orderings:
+        ordering = list(ordering)
+        ordering.reverse()
+        for o in ordering:
+            if o not in seen:
+                seen[o] = 1
+                result.append(o)
+
+    result.reverse()
+    return result
+
+def _flattenInterface(iface, result):
+    result.append(iface)
+    for base in iface.__bases__:
+        _flattenInterface(base, result)
+
+    return result
+
+Interface = InterfaceClass("Interface", __module__ = 'zope.interface')
 
 class Attribute(Element):
     """Attribute descriptions
@@ -427,23 +470,21 @@
     func = meth.im_func
     return fromFunction(func, interface, imlevel=1)
 
+
 # Now we can create the interesting interfaces and wire them up:
 def _wire():
-
-    from zope.interface.implements import implements
+    from zope.interface.declarations import classImplements
 
     from zope.interface.interfaces import IAttribute
-    implements(Attribute, IAttribute)
+    classImplements(Attribute, IAttribute)
 
     from zope.interface.interfaces import IMethod
-    implements(Method, IMethod)
+    classImplements(Method, IMethod)
 
     from zope.interface.interfaces import IInterface
-    implements(InterfaceClass, IInterface)
+    classImplements(InterfaceClass, IInterface)
 
 # We import this here to deal with module dependencies.
-from zope.interface.implements import getImplementsOfInstances
-from zope.interface.implements import visitImplements, getImplements
-from zope.interface.implements import instancesOfObjectImplements
+from zope.interface.declarations import providedBy, implementedBy
 from zope.interface.exceptions import InvalidInterface
 from zope.interface.exceptions import BrokenImplementation


=== Zope3/src/zope/interface/type.py 1.7 => 1.8 ===
--- Zope3/src/zope/interface/type.py:1.7	Thu May  1 15:35:44 2003
+++ Zope3/src/zope/interface/type.py	Sat May  3 12:36:05 2003
@@ -19,8 +19,8 @@
 """
 __metaclass__ = type # All classes are new style when run with Python 2.2+
 
+from zope.interface import Interface, providedBy
 from zope.interface.interfaces import IInterface
-from zope.interface._flatten import _flatten
 from zope.interface.interfaces import ITypeRegistry
 
 class TypeRegistry:
@@ -72,7 +72,7 @@
 
     def getAll(self, interface_spec):
         result = []
-        for interface in _flatten(interface_spec):
+        for interface in interface_spec.flattened():
             object = self._reg.get(interface)
             if object is not None:
                 result.append(object)
@@ -88,7 +88,7 @@
         # XXX This isn't quite right, since it doesn't take into
         # account implementation registries for objects that can't
         # have '__implements__' attributes.
-        return self.getAll(getattr(object, '__implements__', None))
+        return self.getAll(providedBy(object))
 
     def getTypesMatching(self, interface):
         if interface is None:


=== Zope3/src/zope/interface/verify.py 1.5 => 1.6 ===
--- Zope3/src/zope/interface/verify.py:1.5	Fri Apr 18 09:59:54 2003
+++ Zope3/src/zope/interface/verify.py	Sat May  3 12:36:05 2003
@@ -15,7 +15,7 @@
 from zope.interface.exceptions import BrokenImplementation, DoesNotImplement
 from zope.interface.exceptions import BrokenMethodImplementation
 from types import FunctionType, MethodType
-from zope.interface.interface import fromMethod, fromFunction
+from zope.interface.interface import fromMethod, fromFunction, Method
 
 # This will be monkey-patched when running under Zope 2, so leave this
 # here:
@@ -49,6 +49,11 @@
 
     for n, d in iface.namesAndDescriptions(1):
         if not hasattr(candidate, n):
+            if (not isinstance(d, Method)) and vtype == 'c':
+                # We can't verify non-methods on classes, since the
+                # class may provide attrs in it's __init__.
+                continue
+            
             raise BrokenImplementation(iface, n)
 
         attr = getattr(candidate, n)