[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 ===