[Zope-Checkins] CVS: Zope/lib/python/Interface - iclass.py:1.11.8.2

Shane Hathaway shane@digicool.com
Tue, 7 Aug 2001 11:27:44 -0400


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

Modified Files:
      Tag: NR-branch
	iclass.py 
Log Message:
Made it possible to store interfaces by reference to a module and name,
the same as classes, using deep internals of pickling machinery.
Don't shoot me unless you know a better way to achieve this. :-)


=== Zope/lib/python/Interface/iclass.py 1.11.8.1 => 1.11.8.2 ===
 """
 
+from inspect import currentframe
+import sys
+
 from Method import Method
 from Attr import Attribute
 from types import FunctionType, ClassType
@@ -16,11 +19,11 @@
 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)
 
 
@@ -32,7 +35,7 @@
 
     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'
@@ -164,7 +167,69 @@
         return "<Interface %s at %x>" % (self.__name__, id(self))
 
 
-Base=Interface("Interface")
+# 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:
+                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, making
+                    # it more reliable. :-/
+                    __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):
+        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")
+
+
 
 class Named(Base):
     "Objects that have a name."