[Zope3-checkins] CVS: Zope3/src/zope/app - context.py:1.3

Jim Fulton jim@zope.com
Mon, 2 Jun 2003 07:05:27 -0400


Update of /cvs-repository/Zope3/src/zope/app
In directory cvs.zope.org:/tmp/cvs-serv19766/src/zope/app

Modified Files:
	context.py 
Log Message:
Moved functionality to:

- Prevent pickling of context wrappers

- Provide integration of wrapper interfaces in interface specs

to a subclass of the basic wrapper class. The subclass is in zope.app, 
because it reflects zope-specific policies.


=== Zope3/src/zope/app/context.py 1.2 => 1.3 ===
--- Zope3/src/zope/app/context.py:1.2	Sun Jun  1 13:23:34 2003
+++ Zope3/src/zope/app/context.py	Mon Jun  2 07:04:57 2003
@@ -19,23 +19,89 @@
 $Id$
 """
 
-from zope.interface import moduleProvides
-from zope.security.proxy import Proxy, getChecker
-from zope.context.wrapper import getdictcreate
-from zope.context.wrapper import getcontext
-from zope.context.wrapper import Wrapper
-from zope.security.checker import defineChecker, selectChecker, BasicTypes
-from zope.proxy import queryProxy, getProxiedObject
-from zope.app.interfaces.context import IContextWrapper
 from pickle import PicklingError
-from zope.proxy import getProxiedObject
-from zope.interface import providedBy
+from zope.app.interfaces.context import IContextWrapper
+from zope.context.wrapper import getcontext
+from zope.context.wrapper import getdictcreate
+from zope.context.wrapper import Wrapper as BaseWrapper
 from zope.interface.declarations import getObjectSpecification
 from zope.interface.declarations import ObjectSpecification
 from zope.interface.declarations import ObjectSpecificationDescriptor
+from zope.interface import moduleProvides, implements, providedBy
+from zope.proxy import queryProxy, getProxiedObject
+from zope.security.checker import defineChecker, selectChecker, BasicTypes
+from zope.security.proxy import Proxy, getChecker
 
 moduleProvides(IContextWrapper)
 __all__ = tuple(IContextWrapper)
+
+class DecoratorSpecificationDescriptor(ObjectSpecificationDescriptor):
+    """Support for interface declarations on decorators
+
+    >>> from zope.interface import *
+    >>> class I1(Interface):
+    ...     pass
+    >>> class I2(Interface):
+    ...     pass
+    >>> class I3(Interface):
+    ...     pass
+    >>> class I4(Interface):
+    ...     pass
+
+    >>> class D1(Wrapper):
+    ...   implements(I1)
+
+
+    >>> class D2(Wrapper):
+    ...   implements(I2)
+
+    >>> class X:
+    ...   implements(I3)
+
+    >>> x = X()
+    >>> directlyProvides(x, I4)
+
+    Interfaces of X are ordered with the directly-provided interfaces first
+
+    >>> [interface.__name__ for interface in list(providedBy(x))]
+    ['I4', 'I3']
+
+    When we decorate objects, what order should the interfaces come
+    in?  One could argue that decorators are less specific, so they
+    should come last.
+
+    >>> [interface.__name__ for interface in list(providedBy(D1(x)))]
+    ['I4', 'I3', 'I1']
+
+    >>> [interface.__name__ for interface in list(providedBy(D2(D1(x))))]
+    ['I4', 'I3', 'I1', 'I2']
+
+    $Id$
+    """
+
+    def __get__(self, inst, cls):
+        if inst is None:
+            return getObjectSpecification(cls)
+        else:
+            provided = providedBy(getProxiedObject(inst))
+
+            # Use type rather than __class__ because inst is a proxy and
+            # will return the proxied object's class.
+            cls = type(inst) 
+            return ObjectSpecification(provided, cls)
+        
+
+class Wrapper(BaseWrapper):
+    """Zope-specific context wrapper
+    """
+
+    def __reduce_ex__(self, proto=None):
+        raise PicklingError, "Zope context wrappers cannot be pickled"
+
+    __reduce__ = __reduce_ex__
+
+    __providedBy__ = DecoratorSpecificationDescriptor()
+
 
 def ContextWrapper(_ob, _parent, **kw):