[Zope-Checkins] CVS: Zope3/lib/python/Interface - Standard.py:1.2.178.1 Util.py:1.7.58.1 __init__.py:1.5.134.2 iclass.py:1.11.58.1 test.py:NONE unitfixtures.py:NONE unittests.py:NONE

Shane Hathaway shane@digicool.com
Fri, 16 Nov 2001 15:34:06 -0500


Update of /cvs-repository/Zope3/lib/python/Interface
In directory cvs.zope.org:/tmp/cvs-serv30072

Modified Files:
      Tag: Zope-3x-branch
	Standard.py Util.py __init__.py iclass.py 
Removed Files:
      Tag: Zope-3x-branch
	test.py unitfixtures.py unittests.py 
Log Message:
Merged changes to Interface package from ComponentArchitecture-branch,
fixing unit tests.


=== Zope3/lib/python/Interface/Standard.py 1.2 => 1.2.178.1 ===
 import iclass, Util
 
-Interface=Util.impliedInterface(
-    iclass.Interface, "Interface",
-    """Interface of Interface objects
-    """)
-iclass.Interface.__implements__=Interface
-
-from iclass import Named, Class
+from iclass import Named, Class, InterfaceInterface
 
 from Basic import *
 


=== Zope3/lib/python/Interface/Util.py 1.7 => 1.7.58.1 ===
-from iclass import Interface, Class, ClassTypes, Base, \
-     assertTypeImplements, _typeImplements #uuh..
-from types import FunctionType
+from iclass import Interface, assertTypeImplements, CLASS_INTERFACES, \
+     getImplements, getImplementsOfInstances, visitImplements
+from types import FunctionType, StringType
 
 
 def impliedInterface(klass, __name__=None, __doc__=None):
@@ -22,53 +22,49 @@
         items[k]=v
     for b in klass.__bases__: _ii(b, items)
     return items
-    
-def objectImplements(object, tiget=_typeImplements.get):        
-    """Return the interfaces implemented by the object
-    """
-    r=[]
-
-    t=type(object)
-    if t in ClassTypes:
-        if hasattr(object, '__class_implements__'):
-            implements=object.__class_implements__
-        else:
-            implements=Class
-    elif hasattr(object, '__implements__'):
-        implements=object.__implements__
-    else:
-        implements=tiget(t, None)
-        if implements is None: return r
 
-    if isinstance(implements,Interface): r.append(implements)
-    else: _wi(implements, r.append)
 
+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, tiget=_typeImplements.get):
-    """Return the interfaces that instanced implement (by default)
-    """
-    r=[]
-
-    if type(klass) in ClassTypes:
-        if hasattr(klass, '__implements__'):
-            implements=klass.__implements__
-        else: return r
-    elif hasattr(klass, 'instancesImplements'):
-        # Hook for ExtensionClass. :)
-        implements=klass.instancesImplements()
-    else:
-        implements=tiget(klass,None)
-
-    if implements is not None: 
-        if isinstance(implements,Interface): r.append(implements)
-        else: _wi(implements, r.append)
 
+def instancesOfObjectImplements(klass, getInterface=None):
+    r = []
+    implements = getImplementsOfInstances(klass)
+    if not implements:
+        return r
+    visitImplements(implements, klass, r.append, getInterface)
     return r
 
 
-def _wi(interfaces, append):
+def _flatten(i, append):
+    append(i)
+    bases = i.getBases()
+    if bases:
+        for b in bases:
+            _flatten(b, append)
+
+
+def flattenInterfaces(interfaces, remove_duplicates=1):
+    res = []
     for i in interfaces:
-        if isinstance(i,Interface): append(i)
-        else: _wi(i, append)
+        _flatten(i, res.append)
+    if remove_duplicates:
+        # Remove duplicates in reverse.
+        # Similar to Python 2.2's method resolution order.
+        seen = {}
+        index = len(res) - 1
+        while index >= 0:
+            i = res[index]
+            if seen.has_key(i):
+                del res[index]
+            else:
+                seen[i] = 1
+            index = index - 1
+    return res
+


=== Zope3/lib/python/Interface/__init__.py 1.5.134.1 => 1.5.134.2 ===
-from Standard import Base
+from Standard import Base, InterfaceInterface
 Interface = Base
 
 import iclass
 new=iclass.Interface
-InterfaceInterface=iclass.InterfaceInterface
+CLASS_INTERFACES = iclass.CLASS_INTERFACES
 # del iclass
 
 from Util import impliedInterface


=== Zope3/lib/python/Interface/iclass.py 1.11 => 1.11.58.1 ===
 """
 
+from inspect import currentframe
+import sys
+
 from Method import Method
 from Attr import Attribute
-from types import FunctionType, ClassType
+from types import FunctionType, ClassType, StringType
 import Exceptions
 from InterfaceBase import InterfaceBase
 
 try:
-    from ExtensionClass import Base
+    import ExtensionClass
 except ImportError:
     ClassTypes = (ClassType,)
 else:
-    class dummy (Base): pass
+    class dummy (ExtensionClass.Base): pass
     ClassTypes = (type(dummy), ClassType)
 
 
+# Special value indicating the object supports
+# what its class supports.
+CLASS_INTERFACES = 1
+
 _typeImplements={}
 
+
+def getImplements(object, tiget=_typeImplements.get):
+    t = type(object)
+    if t in ClassTypes:
+        if hasattr(object, '__class_implements__'):
+            return object.__class_implements__
+        else:
+            return Class
+    elif hasattr(object, '__implements__'):
+        return object.__implements__
+    else:
+        return tiget(t, None)
+
+
+def getImplementsOfInstances(klass, tiget=_typeImplements.get):
+    if type(klass) in ClassTypes:
+        if hasattr(klass, '__implements__'):
+            return klass.__implements__
+        else:
+            return None
+    elif hasattr(klass, 'instancesImplements'):
+        # Hook for ExtensionClass. :)
+        # XXX Potential security problem since "instancesImplements"
+        # is a valid Zope identifier.
+        return klass.instancesImplements()
+    else:
+        return tiget(klass, None)
+
+
+def visitImplements(implements, object, visitor, getInterface=None):
+    """
+    Visits the interfaces described by an __implements__ attribute,
+    invoking the visitor for each interface object.
+    If the visitor returns anything true, the loop stops.
+    This does not, and should not, visit superinterfaces.
+    """
+    if isinstance(implements, Interface):
+        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 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)
+    else:
+        # A sequence of interfaces.
+        for i in implements:
+            r = visitImplements(i, object, visitor, getInterface)
+            if r:
+                # If the visitor returns anything true, stop.
+                return r
+    return None
+
+
 class Interface(InterfaceBase):
     """Prototype (scarecrow) Interfaces Implementation
     """
-
     def __init__(self, name, bases=(), attrs=None, __doc__=None):
         """Create a new interface
-        """        
+        """
         for b in bases:
             if not isinstance(b, Interface):
                 raise TypeError, 'Expected base interfaces'
@@ -68,50 +134,34 @@
         """Does an interface extend another?
         """
         for b in self.__bases__:
-            if b is other: return 1
+            if b == other: return 1
             if b.extends(other): return 1
         return 0
 
-    def isImplementedBy(self, object,
-                      tiget=_typeImplements.get):
+    def isEqualOrExtendedBy(self, other):
+        """Same interface or extends?
+        """
+        if self == other:
+            return 1
+        return other.extends(self)
+
+    def isImplementedBy(self, object):
         """Does the given object implement the interface?
         """
-        t=type(object)
-        if t in ClassTypes:
-            if hasattr(object, '__class_implements__'):
-                implements=object.__class_implements__
-            else: implements=Class
-        elif hasattr(object, '__implements__'):
-            implements=object.__implements__
-        else:
-            implements=tiget(t, None)
-            if implements is None: return 0
-    
-        if isinstance(implements,Interface):
-            return implements is self or implements.extends(self)
-        else:
-            return self.__any(implements)
+        i = getImplements(object)
+        if i is not None:
+            return visitImplements(
+                i, object, self.isEqualOrExtendedBy, self._getInterface)
+        return 0
 
-    def isImplementedByInstancesOf(self, klass,
-                                 tiget=_typeImplements.get):
+    def isImplementedByInstancesOf(self, klass):
         """Do instances of the given class implement the interface?
         """
-        if type(klass) in ClassTypes:
-            if hasattr(klass, '__implements__'):
-                implements=klass.__implements__
-            else: return 0
-        elif hasattr(klass, 'instancesImplement'):
-            # Hook for ExtensionClass. :)
-            implements=klass.instancesImplement()
-        else:
-            implements=tiget(klass,None)
-
-        if implements is None: return 0
-        
-        if isinstance(implements,Interface):
-            return implements is self or implements.extends(self)
-        else:
-            return self.__any(implements)
+        i = getImplementsOfInstances(klass)
+        if i is not None:
+            return visitImplements(
+                i, klass, self.isEqualOrExtendedBy, self._getInterface)
+        return 0
 
     def names(self):
         """Return the attribute names defined by the interface
@@ -143,6 +193,12 @@
 
         return klass
 
+    def _getInterface(self, ob, name):
+        '''
+        Retrieve a named interface.
+        '''
+        return None
+            
     def __d(self, dict):
 
         for k, v in self.__attrs.items():
@@ -150,21 +206,73 @@
                 dict[k]=v
 
         for b in self.__bases__: b.__d(dict)
-            
 
-    def __any(self, interfaces):
-        for i in interfaces:
-            if isinstance(i,Interface):
-                if i is self or i.extends(self): return 1
+    def __repr__(self):
+        return "<Interface %s at %x>" % (self.__name__, id(self))
+
+
+# Persist interfaces created from classes by reference using
+# a module and name.
+
+
+class InterfaceFromClass (Interface):
+    def __init__(self, name, bases=(), attrs=None, __doc__=None,
+                 __module__=None):
+        if __module__ is None:
+            if attrs is not None and attrs.has_key('__module__'):
+                __module__ = attrs['__module__']
+                del attrs['__module__']
             else:
-                if self.__any(i): return 1
-        return 0
+                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__']
+                except AttributeError, KeyError:
+                    pass
+        self.__module__ = __module__
+        Interface.__init__(self, name, bases, attrs, __doc__)
+
+    def __getinitargs__(self):
+        # What this returns will be passed as arguments to
+        # interface_loader.__call__().
+        if not self.__module__:
+            raise SystemError, 'Module of interface object is unknown'
+        return (self.__module__, self.__name__)
+
+    def __getstate__(self):
+        # No need to save details.
+        return None
+
+    def __setstate__(self, state):
+        assert state == None
 
     def __repr__(self):
-        return "<Interface %s at %x>" % (self.__name__, id(self))
+        name = self.__name__
+        m = self.__module__
+        if m:
+            name = '%s.%s' % (m, name)
+        return "<InterfaceFromClass %s at %x>" % (name, id(self))
+
+
+class InterfaceLoader:
+
+    __safe_for_unpickling__ = 1
+
+    def __call__(self, module, name):
+        __import__(module)
+        mod = sys.modules[module]
+        i = getattr(mod, name)
+        return i
+
+interface_loader = InterfaceLoader()
+
+
+InterfaceFromClass.__name__ = 'interface_loader'  # Trick unpicklers.
+
+Base = InterfaceFromClass("Interface")
 
 
-Base=Interface("Interface")
 
 class Named(Base):
     "Objects that have a name."
@@ -266,4 +374,5 @@
 
         """
 
-Interface.__implements__ = (InterfaceInterface,)
+Interface.__implements__ = InterfaceInterface
+

=== Removed File Zope3/lib/python/Interface/test.py ===

=== Removed File Zope3/lib/python/Interface/unitfixtures.py ===

=== Removed File Zope3/lib/python/Interface/unittests.py ===