[Zope3-checkins] CVS: Zope3/lib/python/Zope/ContextWrapper - SimpleMethodWrapper.py:1.3 __init__.py:1.3

Steve Alexander steve@cat-box.net
Thu, 31 Oct 2002 07:30:50 -0500


Update of /cvs-repository/Zope3/lib/python/Zope/ContextWrapper
In directory cvs.zope.org:/tmp/cvs-serv1415/lib/python/Zope/ContextWrapper

Modified Files:
	SimpleMethodWrapper.py __init__.py 
Log Message:
Refactored and improved quality and coverage of tests for ContextMethods.
Implemented ContextProperties in three flavours:

  ContextProperty:    gives both get and set methods a wrapped_self.

  ContextGetProperty: gives get method a wrapped_self,
                      leaves set method with a regular self.

  ContextSetProperty: leaves get method with a regular self,
                      gives set method a wrapped_self.
                     



=== Zope3/lib/python/Zope/ContextWrapper/SimpleMethodWrapper.py 1.2 => 1.3 ===
--- Zope3/lib/python/Zope/ContextWrapper/SimpleMethodWrapper.py:1.2	Mon Jun 10 19:29:25 2002
+++ Zope3/lib/python/Zope/ContextWrapper/SimpleMethodWrapper.py	Thu Oct 31 07:30:49 2002
@@ -14,22 +14,39 @@
 
 # This method wrapper does not work for builtin methods.
 
-from Zope.ContextWrapper.wrapper import Wrapper
+from Zope.ContextWrapper.wrapper import Wrapper, getbaseobject
 
-class ContextMethod(object):
+__metaclass__ = type
+
+class ContextMethod:
     def __new__(cls, method):
         try:
-            method.__dict__['Zope.ContextWrapper.contextful'] = 1
+            method.__dict__['Zope.ContextWrapper.contextful_get'] = True
         except AttributeError:
-            raise TypeError, \
+            raise TypeError(
                 "Cannot make %s into a contextmethod" % type(method)
+                )
         return method
 
 
+class ContextProperty(property):
+    """A property that provides a context wrapper to its getter and setter
+    methods"""
+    __dict__ = {'Zope.ContextWrapper.contextful_get': True,
+                'Zope.ContextWrapper.contextful_set': True}
+
+class ContextGetProperty(property):
+    """A property that provides a context wrapper to its getter method"""
+    __dict__ = {'Zope.ContextWrapper.contextful_get': True}
+
+class ContextSetProperty(property):
+    """A property that provides a context wrapper to its setter method"""
+    __dict__ = {'Zope.ContextWrapper.contextful_set': True}
+
 def wrapperCreator(object, context=None, **data):
     if hasattr(object, '__call__'):
         attrdict = getattr(object.__call__, '__dict__', {})
-        if attrdict.get('Zope.ContextWrapper.contextful'):
+        if attrdict.get('Zope.ContextWrapper.contextful_get'):
             return SimpleCallableMethodWrapper(object, context, **data)
 
     return SimpleMethodWrapper(object, context, **data)
@@ -37,14 +54,51 @@
 
 class SimpleMethodWrapper(Wrapper):
 
-    def __getattribute__(self, name, empty_dict={}):
-        attr = Wrapper.__getattribute__(self, name)
-        attrdict = getattr(attr, '__dict__', empty_dict)
-        if attrdict.get('Zope.ContextWrapper.contextful'):
-            attr = attr.__get__(self)
-        return attr
-        
-        
+    def __getattribute__(self, name, empty_dict={},
+                         getbaseobject=getbaseobject):
+        """Support for ContextMethod and ContextProperty.__get__"""
+        obj = getbaseobject(self)
+        if name not in (getattr(obj, '__dict__', empty_dict) or 
+                        getattr(obj, '__slots__', empty_dict)):
+            attr = getattr(obj.__class__, name, None)
+            if attr is not None:
+                attrdict = getattr(attr, '__dict__', empty_dict)
+                if attrdict.get('Zope.ContextWrapper.contextful_get'):
+                    return attr.__get__(self)
+        return Wrapper.__getattribute__(self, name)
+        # This has much the same effect, but the call to
+        # Wrapper.__getattribute__ is more "correct".
+        #
+        #return getattr(obj, name)
+
+
+    # Original getattribute that doesn't support gettable properties.
+    # Left in so it can be reenabled if we decide we don't actually
+    # need gettable properties.
+    #
+    #def __getattribute__(self, name, empty_dict={}):
+    #    attr = Wrapper.__getattribute__(self, name)
+    #    attrdict = getattr(attr, '__dict__', empty_dict)
+    #    if attrdict.get('Zope.ContextWrapper.contextful'):
+    #        attr = attr.__get__(self)
+    #    return attr
+
+
+    def __setattr__(self, name, value, empty_dict={},
+                    getbaseobject=getbaseobject):
+        """Support for ContextProperty.__set__"""
+        obj = getbaseobject(self)
+        if name not in (getattr(obj, '__dict__', empty_dict) or 
+                        getattr(obj, '__slots__', empty_dict)):
+            attr = getattr(obj.__class__, name, None)
+            if attr is not None:
+                attrdict = getattr(attr, '__dict__', empty_dict)
+                if attrdict.get('Zope.ContextWrapper.contextful_set'):
+                    attr.__set__(self, value)
+                    return
+        setattr(obj, name, value)
+
+
 class SimpleCallableMethodWrapper(SimpleMethodWrapper):
 
     def __call__(self, *args, **kw):


=== Zope3/lib/python/Zope/ContextWrapper/__init__.py 1.2 => 1.3 ===
--- Zope3/lib/python/Zope/ContextWrapper/__init__.py:1.2	Mon Jun 10 19:29:25 2002
+++ Zope3/lib/python/Zope/ContextWrapper/__init__.py	Thu Oct 31 07:30:49 2002
@@ -24,8 +24,10 @@
 # method's __dict__, as the current ContextMethod does.
 # 
 from SimpleMethodWrapper import wrapperCreator as Wrapper
-from SimpleMethodWrapper import ContextMethod
+from SimpleMethodWrapper import ContextMethod, ContextProperty
+from SimpleMethodWrapper import ContextGetProperty, ContextSetProperty
 
-from SimpleMethodWrapper import SimpleMethodWrapper,SimpleCallableMethodWrapper
+from SimpleMethodWrapper import \
+    SimpleMethodWrapper, SimpleCallableMethodWrapper
 wrapperTypes = (SimpleMethodWrapper, SimpleCallableMethodWrapper)
 del SimpleMethodWrapper, SimpleCallableMethodWrapper