[Zope-CVS] CVS: Packages/zasync - manager.py:1.4

Gary Poster gary at zope.com
Fri Oct 29 21:39:52 EDT 2004


Update of /cvs-repository/Packages/zasync
In directory cvs.zope.org:/tmp/cvs-serv27722

Modified Files:
	manager.py 
Log Message:
Add sanitize method so that calls to (and from zope_exec) do not have persistent objects.

Remove an opportunity for Conflict Error in the client.

Fix bug in zope_exec plugin.



=== Packages/zasync/manager.py 1.3 => 1.4 ===
--- Packages/zasync/manager.py:1.3	Tue Oct 19 12:42:21 2004
+++ Packages/zasync/manager.py	Fri Oct 29 21:39:22 2004
@@ -18,11 +18,12 @@
 """
 
 from types import NoneType
-import datetime, random, sys, os, logging
+import datetime, random, sys, os, logging, sets
 
 from twisted.internet import defer
 from twisted.python import failure
 
+from Persistence import Persistent
 from ZODB.POSException import ConflictError
 from ZEO.Exceptions import ClientDisconnected
 from Globals import InitializeClass, Persistent
@@ -50,7 +51,107 @@
 
 # try to make failure.Failure available to restricted python
 allow_class(failure.Failure) # in particular, this should allow access to
-# 'getErrorMessage', 'getBriefTraceback', and 'getTraceback'.
+# 'getErrorMessage', 'getBriefTraceback', 'getTraceback', and 'trap'.
+
+def iterable(value):
+    try:
+        iter(value)
+    except TypeError:
+        return False
+    else:
+        return True
+
+def countable(value):
+    try:
+        len(value)
+    except TypeError:
+        return False
+    else:
+        return True
+
+class Reference:
+    
+    def __init__(self, obj):
+        try:
+            self._path = obj.getPhysicalPath()
+        except (AttributeError, KeyError):
+            self._path = None
+        self._repr = repr(obj)
+    
+    def dereference(self, context):
+        return context.restrictedTraverse(self._path, None)
+    
+    def __repr__(self):
+        return self._repr
+allow_class(Reference)
+
+class StandIn:
+    
+    data = klass = contents = None
+    
+    def __init__(self, obj, depth, contents=None):
+        d = getattr(obj, '__dict__', None)
+        if d is not None:
+            self.data = sanitize(d, depth)
+        self.klass = obj.__class__
+        self.contents = contents
+        self._repr = repr(obj)
+    
+    def __getattr__(self, name):    
+        if self.data is not None and self.data is not MAX_DEPTH_MARKER:
+            try:
+                return self.data[name]
+            except KeyError:
+                pass
+        raise AttributeError(name)
+    
+    def __repr__(self):
+        return self._repr
+allow_class(StandIn)
+
+MAX_DEPTH = 4
+
+class MAX_DEPTH_MARKER: pass # singleton
+
+def sanitize(value, depth=0, max_depth=MAX_DEPTH):
+    if depth >= max_depth:
+        return MAX_DEPTH_MARKER
+    depth += 1
+    if aq_base(value) is not value or isinstance(value, Persistent):
+        if (aq_parent(value) is not None and 
+            getattr(aq_base(value), 'getPhysicalPath', None) is not None):
+            value = Reference(value)
+        else:
+            value = StandIn(value, depth) # XXX could theoretically do a better 
+            # job for BTrees, but don't think I really want to make sending
+            # those across the wire all that easy
+    elif getattr(value, '__dict__', None) is not None:
+        value = StandIn(value, depth) # XXX not ideal for subclasses of built 
+        # in types, but oh well
+    elif isinstance(value, (list, tuple, sets.Set)):
+        val_type = type(value)
+        contents = [sanitize(item, depth) for item in value]
+        if val_type is list:
+            value = contents
+        else:
+            try:
+                value = val_type(contents)
+            except TypeError:
+                value = StandIn(value, depth, contents)
+    elif isinstance(value, dict):
+        contents = [
+            (sanitize(k, depth), sanitize(v, depth)) for k, v in value.items()]
+        val_type = type(value)
+        try:
+            value = val_type(contents)
+        except TypeError:
+            value = StandIn(value, depth, contents)
+    elif not isinstance(value, basestring) and iterable(value):
+        contents = None
+        if countable(value):
+            contents = [sanitize(item, depth) for item in value]
+        value = StandIn(value, depth, contents)
+    return value
 
 # Expression class copied from CMFCore/Expression.py
 class Expression (Persistent):
@@ -475,6 +576,8 @@
                 key = _id_prefix + (randomizer,)
             if self.getDeferred(key) is None:
                 break
+        args = sanitize(args)
+        kwargs = sanitize(kwargs)
         d = Deferred(_plugin, args, kwargs)
         d.key = key
         d.id = repr(key)



More information about the Zope-CVS mailing list