[Zope3-checkins] CVS: Zope3/src/zope/proxy/context - __init__.py:1.1.2.2 context.py:NONE

Jim Fulton jim@zope.com
Mon, 23 Dec 2002 18:53:09 -0500


Update of /cvs-repository/Zope3/src/zope/proxy/context
In directory cvs.zope.org:/tmp/cvs-serv2518/zope/proxy/context

Modified Files:
      Tag: NameGeddon-branch
	__init__.py 
Removed Files:
      Tag: NameGeddon-branch
	context.py 
Log Message:
refactored context wrappers so we get them just from zope.proxy.context

=== Zope3/src/zope/proxy/context/__init__.py 1.1.2.1 => 1.1.2.2 ===
--- Zope3/src/zope/proxy/context/__init__.py:1.1.2.1	Mon Dec 23 14:33:05 2002
+++ Zope3/src/zope/proxy/context/__init__.py	Mon Dec 23 18:52:38 2002
@@ -11,21 +11,251 @@
 # FOR A PARTICULAR PURPOSE.
 # 
 ##############################################################################
-"""ContextWrapper package initialization."""
+"""Wrapping/proxy coordination
 
-from zope.proxy.context.wrapper import *
+Specifically, coordinate use of context wrappers and security proxies.
 
-# import the current, and rather hacky, python implementation of
-# method rebinding.
+Revision information:
+$Id$
+"""
+
+from zope.security.proxy import Proxy, getChecker, getObject
+from zope.proxy.context.wrapper import getobject, getdict
+from zope.proxy.context.wrapper import getcontext, getinnercontext
+from zope.proxy.context.wrapper import getinnerwrapper
+from zope.proxy.context.wrapper import Wrapper as _Wrapper
+from zope.security.checker import defineChecker, selectChecker, BasicTypes
+
+from zope.proxy.interfaces.context import IContextWrapper
+
+__implements__ = IContextWrapper
+
+def ContextWrapper(_ob, _parent, **kw):
+    """Create a context wrapper around an object with data
+
+    If the object is wrapped in a security proxy, then the context
+    wrapper is inserted inside an equivalent security proxy.
+    """
+    
+    if type(_ob) in BasicTypes:
+        # Don't wrap basic objects
+        return _ob
+    elif type(_ob) is Proxy:
+        # insert into proxies
+        checker = getChecker(_ob)
+        _ob = getObject(_ob)
+        _ob = Proxy(_Wrapper(_ob, _parent, **kw), checker)
+    else:
+        _ob = _Wrapper(_ob, _parent, **kw)
+        
+    return _ob
+
+def getWrapperObject(_ob):
+    """Remove a context wrapper around an object with data
+
+    If the object is wrapped in a security proxy, then the object
+    is inserted inside an equivalent security proxy.
+    """
+    
+    if type(_ob) in BasicTypes:
+        # Don't wrap basic objects
+        return _ob
+    elif type(_ob) is Proxy:
+        # insert into proxies
+        checker = getChecker(_ob)
+        _ob = getObject(_ob)
+        _ob = Proxy(getobject(_ob), checker)
+    else:
+        _ob = getobject(_ob)
+        
+    return _ob
+
+def _contextWrapperChecker(ob):
+    return selectChecker(getobject(ob))
+
+def getWrapperData(_ob):
+    if type(_ob) is Proxy:
+        _ob = getObject(_ob)
+    return getdict(_ob)
+
+def getInnerWrapperData(_ob):
+    if type(_ob) is Proxy:
+        _ob = getObject(_ob)
+    return getdict(getinnerwrapper(_ob))
+
+def getWrapperContainer(_ob):
+    if type(_ob) is Proxy:
+        _ob = getObject(_ob)
+    return getinnercontext(_ob)
+
+def getWrapperContext(_ob):
+    if type(_ob) is Proxy:
+        _ob = getObject(_ob)
+    return getcontext(_ob)
+    
+def isWrapper(_ob):
+    if type(_ob) is Proxy:
+        _ob = getObject(_ob)
+    return type(_ob) in wrapperTypes 
+
+class ContainmentIterator:
+
+    def __init__(self, obj):
+        self._ob = _Wrapper(None, obj)
+
+    def __iter__(self):
+        return self
+    
+    def next(self):
+        _ob = self._ob
+
+        if type(_ob) is Proxy:
+            _ob = getObject(_ob)
+        
+        if type(_ob) not in wrapperTypes:
+            raise StopIteration
+
+        _ob = getinnercontext(_ob)
+        self._ob = _ob
+        return _ob
+
+def getItem(collection, name):
+    return ContextWrapper(collection[name], collection, name=name)
+
+def getAttr(collection, name):
+    return ContextWrapper(getattr(collection, name), collection, name=name)
+
+def queryItem(collection, name, default=None):
+    return ContextWrapper(collection.get(name, default),
+                          collection, name=name)
+
+def queryAttr(collection, name, default=None):
+    return ContextWrapper(getattr(collection, name, default),
+                          collection, name=name)
+
+
+
+##############################################################################
 # 
-# eventually this should be replaced by some C, and ContextMethod
-# should be a decriptor class rather than a factory that hacks the
-# method's __dict__, as the current ContextMethod does.
+# Approach
+#
+# The facilities here work by adding markers on methods or properties
+# that a custom wrapper class looks for.  We rely on the custom
+# wrapper class's __getattribute__ to rebind things on the way out.
 # 
-from zope.proxy.context.context import wrapperCreator as Wrapper
-from zope.proxy.context.context import ContextMethod, ContextProperty
-from zope.proxy.context.context import ContextGetProperty, ContextSetProperty
+# For further discission, see this wiki page (all on one line):
+# http://dev.zope.org/Wikis/DevSite/Projects/ComponentArchitecture/...
+# Zope.ContextWrapper.ContextMethod
+#
+##############################################################################
+
+
+# This method wrapper does not work for builtin methods.
+
+from zope.proxy.context.wrapper import Wrapper, getbaseobject
+
+__metaclass__ = type
+
+class ContextMethod:
+    def __new__(cls, method):
+        try:
+            method.__Zope_ContextWrapper_contextful_get__ = True
+        except AttributeError:
+            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"""
+    __Zope_ContextWrapper_contextful_get__ = True
+    __Zope_ContextWrapper_contextful_set__ = True
+
+class ContextGetProperty(property):
+    """A property that provides a context wrapper to its getter method"""
+    __Zope_ContextWrapper_contextful_get__ = True
+
+class ContextSetProperty(property):
+    """A property that provides a context wrapper to its setter method"""
+    __Zope_ContextWrapper_contextful_set__ = True
+
+def wrapperCreator(object, context=None, **data):
+    has_call = (hasattr(object, '__call__') and 
+                getattr(object.__call__,
+                        '__Zope_ContextWrapper_contextful_get__', False))
+    has_getitem = (hasattr(object, '__getitem__') and
+                   getattr(object.__getitem__,
+                           '__Zope_ContextWrapper_contextful_get__', False))
+    if has_call and has_getitem:
+        factory = SimpleCallableGetitemMethodWrapper
+    elif has_call:
+        factory = SimpleCallableMethodWrapper
+    elif has_getitem:
+        factory = SimpleGetitemMethodWrapper
+    else:
+        factory = SimpleMethodWrapper
+
+    return factory(object, context, **data)
+
+class SimpleMethodWrapper(Wrapper):
+
+    def __getattribute__(self, name):
+        """Support for ContextMethod and ContextProperty.__get__"""
+        obj = getbaseobject(self)
+        class_ = obj.__class__
+        class_value = getattr(class_, name, None)
+        if hasattr(class_value, '__get__'):
+            if getattr(class_value,
+                       '__Zope_ContextWrapper_contextful_get__', False):
+                return class_value.__get__(self, class_)
+            
+        return Wrapper.__getattribute__(self, name)
+
+    def __setattr__(self, name, value):
+        """Support for ContextProperty.__set__"""
+        obj = getbaseobject(self)
+        class_ = obj.__class__
+        class_value = getattr(class_, name, None)
+        if hasattr(class_value, '__set__'):
+            if getattr(class_value,
+                       '__Zope_ContextWrapper_contextful_set__', False):
+                class_value.__set__(self, value)
+                return
+        setattr(obj, name, value)
+
+
+class SimpleCallableMethodWrapper(SimpleMethodWrapper):
+
+    def __call__(self, *args, **kw):
+        attr = Wrapper.__getattribute__(self, '__call__')
+        return attr.__get__(self)(*args, **kw)
+
+class SimpleGetitemMethodWrapper(SimpleMethodWrapper):
+
+    def __getitem__(self, key, *args, **kw):
+        attr = Wrapper.__getattribute__(self, '__getitem__')
+        return attr.__get__(self)(key, *args, **kw)
+
+class SimpleCallableGetitemMethodWrapper(SimpleCallableMethodWrapper,
+                                         SimpleGetitemMethodWrapper):
+    pass
+
+wrapperTypes = (SimpleMethodWrapper, SimpleCallableMethodWrapper,
+                SimpleGetitemMethodWrapper,
+                SimpleCallableGetitemMethodWrapper)
+
+for wrapper_type in wrapperTypes:
+    defineChecker(wrapper_type, _contextWrapperChecker)
+
+class ContextSuper:
 
-from zope.proxy.context.context import wrapperTypes
-from zope.proxy.context.context import ContextSuper
+    def __init__(self, class_, inst):
+        self.__inst = inst
+        self.__class = class_
 
+    def __getattr__(self, name):
+        inst = self.__inst
+        return getattr(super(self.__class, getbaseobject(inst)), name
+                       ).__get__(inst)

=== Removed File Zope3/src/zope/proxy/context/context.py ===