[Zope3-checkins] CVS: Zope3/src/zope/app/container - zopecontainer.py:1.26

Albertas Agejevas alga@codeworks.lt
Thu, 17 Jul 2003 10:45:22 -0400


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

Modified Files:
	zopecontainer.py 
Log Message:
A temporary workaround for making context aware descriptors work with
ZopeContainerDecorator.  A more generic fix for this problem should be
made in wrapper.c.


=== Zope3/src/zope/app/container/zopecontainer.py 1.25 => 1.26 ===
--- Zope3/src/zope/app/container/zopecontainer.py:1.25	Mon Jul  7 13:14:47 2003
+++ Zope3/src/zope/app/container/zopecontainer.py	Thu Jul 17 10:45:17 2003
@@ -25,6 +25,7 @@
 from zope.app.interfaces.container import IContainerNamesContainer
 from zope.component import queryAdapter, getAdapter
 from zope.app.context import ContextWrapper, Wrapper
+from zope.context import ContextDescriptor
 from zope.app.event import publish
 from zope.app.interfaces.container import IAddNotifiable
 from zope.app.interfaces.container import IDeleteNotifiable
@@ -35,8 +36,62 @@
 from zope.app.event.objectevent import ObjectRemovedEvent
 from zope.app.event.objectevent import ObjectModifiedEvent, ObjectAddedEvent
 from zope.interface import implements
-
+from zope.context.wrapper import getdescriptor
 _marker = object()
+
+__metaclass__ = type
+
+class ContainerDecoratorSuper:
+    """Like a super() but for wrappers.
+
+    The descriptors get their self rebound to a wrapper if they are
+    context descriptors.
+
+    XXX: this is just a plug to get context awareness work on Zope
+    container instances.  This has to be implemented in wrapper.c
+    """
+
+    __slots__ = 'wrapper',
+
+    def __init__(self, wrapper):
+        self.wrapper = wrapper
+
+    def _getDescriptor(self, attr):
+        '''Returns a bound method with self rebound if the descriptor
+        is a ContextDescriptor, and a normal method otherwise.
+        '''
+        wrapper = self.wrapper
+        obj = getProxiedObject(wrapper)
+        cls = getattr(obj, '__class__', type(obj))
+        descriptor = getdescriptor(obj, attr)
+        if isinstance(descriptor, ContextDescriptor):
+            return descriptor.__get__(wrapper, cls)
+        else:
+            return getattr(obj, attr)
+
+    def __getitem__(self, key):
+        return self._getDescriptor('__getitem__')(key)
+
+    def __contains__(self, key):
+        return self._getDescriptor('__contains__')(key)
+
+    def get(self, key, default):
+        return self._getDescriptor('get')(key, default)
+
+    def items(self):
+        return self._getDescriptor('items')()
+
+    def values(self):
+        return self._getDescriptor('values')()
+
+    def __delitem__(self, key):
+        return self._getDescriptor('__delitem__')(key)
+
+    def setObject(self, key, value):
+        return self._getDescriptor('setObject')(key, value)
+
+
+
 class ZopeItemContainerDecorator(Wrapper):
     """Decorates an IItemContainer object for context-awareness.
 
@@ -46,7 +101,8 @@
 
     def __getitem__(self, key):
         "See IZopeItemContainer"
-        return ContextWrapper(getProxiedObject(self)[key], self, name=key)
+        return ContextWrapper(ContainerDecoratorSuper(self)[key],
+                              self, name=key)
 
     def get(self, key, default=None):
         "See IZopeSimpleReadContainer"
@@ -59,7 +115,7 @@
     def __contains__(self, key):
         "See IReadMapping"
         # '__contains__' in terms of __getitem__ on the proxied object
-        container = getProxiedObject(self)
+        container = ContainerDecoratorSuper(self)
         try:
             container[key]
             return True
@@ -72,7 +128,7 @@
 
     def get(self, key, default=None):
         "See IZopeSimpleReadContainer"
-        container = getProxiedObject(self)
+        container = ContainerDecoratorSuper(self)
         value = container.get(key, _marker)
         if value is not _marker:
             return ContextWrapper(value, self, name=key)
@@ -85,7 +141,7 @@
 
     def values(self):
         "See IZopeReadContainer"
-        container = getProxiedObject(self)
+        container = ContainerDecoratorSuper(self)
         result = []
         for key, value in container.items():
             result.append(ContextWrapper(value, self, name=key))
@@ -93,7 +149,7 @@
 
     def items(self):
         "See IZopeReadContainer"
-        container = getProxiedObject(self)
+        container = ContainerDecoratorSuper(self)
         result = []
         for key, value in container.items():
             result.append((key, ContextWrapper(value, self, name=key)))
@@ -112,11 +168,12 @@
 
     def setObject(self, key, object):
         "See IZopeWriteContainer"
-        container = getProxiedObject(self)
+        container = ContainerDecoratorSuper(self)
+        unwrapped = removeAllProxies(self)
 
         if not key:
-            if not (IOptionalNamesContainer.isImplementedBy(container)
-                    or IContainerNamesContainer.isImplementedBy(container)):
+            if not (IOptionalNamesContainer.isImplementedBy(unwrapped)
+                    or IContainerNamesContainer.isImplementedBy(unwrapped)):
                 raise ValueError("Empty names are not allowed")
             key = ''
         else:
@@ -149,7 +206,7 @@
 
     def __delitem__(self, key):
         "See IZopeWriteContainer"
-        container = getProxiedObject(self)
+        container = ContainerDecoratorSuper(self)
 
         # Dependency Note: This is a dependency on IItemContainer
         object = ContextWrapper(container[key], self, name=key)