[pypy-svn] r35609 - in pypy/dist/pypy/lib: distributed test2

fijal at codespeak.net fijal at codespeak.net
Tue Dec 12 00:04:55 CET 2006


Author: fijal
Date: Tue Dec 12 00:04:41 2006
New Revision: 35609

Modified:
   pypy/dist/pypy/lib/distributed/__init__.py
   pypy/dist/pypy/lib/distributed/objkeeper.py
   pypy/dist/pypy/lib/distributed/protocol.py
   pypy/dist/pypy/lib/test2/test_distributed.py
Log:
Added some support for exceptions (but tracebacks has some garbage inside - also due to old greenlets interface)


Modified: pypy/dist/pypy/lib/distributed/__init__.py
==============================================================================
--- pypy/dist/pypy/lib/distributed/__init__.py	(original)
+++ pypy/dist/pypy/lib/distributed/__init__.py	Tue Dec 12 00:04:41 2006
@@ -1,2 +1,2 @@
 
-from protocol import RemoteProtocol, test_env
+from protocol import RemoteProtocol, test_env, remote_loop

Modified: pypy/dist/pypy/lib/distributed/objkeeper.py
==============================================================================
--- pypy/dist/pypy/lib/distributed/objkeeper.py	(original)
+++ pypy/dist/pypy/lib/distributed/objkeeper.py	Tue Dec 12 00:04:41 2006
@@ -2,6 +2,15 @@
 """ objkeeper - Storage for remoteprotocol
 """
 
+# XXX jeez
+
+import sys
+try:
+    1/0
+except:
+    _, _, tb = sys.exc_info()
+    GetSetDescriptor = type(type(tb).tb_frame)
+
 class ObjKeeper(object):
     def __init__(self, exported_names = {}):
         self.exported_objects = [] # list of object that we've exported outside
@@ -16,11 +25,22 @@
         self.exported_objects.append(obj)
         return len(self.exported_objects) - 1
     
+    def ignore(self, key, value):
+        #key not in ('__dict__', '__weakref__', '__class__', '__new__',
+        #        '__base__', '__flags__', '__mro__', '__bases__')]
+        if key in ('__dict__', '__weakref__', '__class__', '__new__'):
+            return True
+        if isinstance(value, GetSetDescriptor):
+            return True
+        return False
+    
     def register_type(self, protocol, tp):
         try:
             return self.exported_types[tp]
         except KeyError:
             print "Registering type %s as %s" % (tp, self.exported_types_id)
+            if str(tp).find('getset') != -1:
+                import pdb;pdb.set_trace()
             self.exported_types[tp] = self.exported_types_id
             tp_id = self.exported_types_id
             self.exported_types_id += 1
@@ -28,8 +48,7 @@
         # XXX: We don't support inheritance here, nor recursive types
         #      shall we???
         _dict = dict([(key, protocol.wrap(getattr(tp, key))) for key in dir(tp) 
-            if key not in ('__dict__', '__weakref__', '__class__', '__new__',
-                '__base__', '__flags__', '__mro__', '__bases__')])
+            if not self.ignore(key, getattr(tp, key))])
         protocol.send(("type_reg", (tp_id, 
             tp.__name__, _dict)))
         return tp_id

Modified: pypy/dist/pypy/lib/distributed/protocol.py
==============================================================================
--- pypy/dist/pypy/lib/distributed/protocol.py	(original)
+++ pypy/dist/pypy/lib/distributed/protocol.py	Tue Dec 12 00:04:41 2006
@@ -58,15 +58,21 @@
 
 import types
 from marshal import dumps
+import exceptions
 
 class AbstractProtocol(object):
     immutable_primitives = (str, int, float, long, unicode, bool, types.NotImplementedType)
-    mutable_primitives = (list, dict, types.FunctionType, types.FrameType)
+    mutable_primitives = (list, dict, types.FunctionType, types.FrameType, types.TracebackType,
+        types.CodeType)
+    exc_dir = dict((val, name) for name, val in exceptions.__dict__.iteritems())
     
     letter_types = {
         'l' : list,
         'd' : dict,
+        'c' : types.CodeType,
         't' : tuple,
+        'e' : Exception,
+        'ex': exceptions, # for instances
         'i' : int,
         'b' : bool,
         'f' : float,
@@ -82,6 +88,7 @@
         'type' : type,
         'tp' : None,
         'fr' : types.FrameType,
+        'tb' : types.TracebackType,
     }
     type_letters = dict([(value, key) for key, value in letter_types.items()])
     assert len(type_letters) == len(letter_types)
@@ -95,6 +102,12 @@
     def wrap(self, obj):
         """ Wrap an object as sth prepared for sending
         """
+        def is_element(x, iterable):
+            try:
+                return x in iterable
+            except (TypeError, ValueError):
+                return False
+        
         tp = type(obj)
         ctrl = get_transparent_controller(obj)
         if ctrl:
@@ -104,6 +117,11 @@
         elif tp in self.immutable_primitives:
             # simple, immutable object, just copy
             return (self.type_letters[tp], obj)
+        elif hasattr(obj, '__class__') and obj.__class__ in self.exc_dir:
+            return (self.type_letters[Exception], (self.exc_dir[obj.__class__], \
+                self.wrap(obj.args)))
+        elif is_element(obj, self.exc_dir): # weird hashing problems
+            return (self.type_letters[exceptions], self.exc_dir[obj])
         elif tp is tuple:
             # we just pack all of the items
             return ('t', tuple([self.wrap(elem) for elem in obj]))
@@ -147,6 +165,12 @@
             p = proxy(tp, ro.perform)
             ro.obj = p
             return p
+        elif tp is Exception:
+            cls_name, w_args = obj_data
+            return getattr(exceptions, cls_name)(self.unwrap(w_args))
+        elif tp is exceptions:
+            cls_name = obj_data
+            return getattr(exceptions, cls_name)
         elif tp is types.MethodType:
             w_class, w_name, w_func, w_self = obj_data
             tp = self.unwrap(w_class)
@@ -240,10 +264,17 @@
         elif command == 'call':
             id, name, args, kwargs = data
             args, kwargs = protocol.unpack_args(args, kwargs)
-            retval = getattr(protocol.keeper.get_object(id), name)(*args, **kwargs)
-            send(("finished", wrap(retval)))
+            try:
+                retval = getattr(protocol.keeper.get_object(id), name)(*args, **kwargs)
+            except:
+                send(("raised", wrap(sys.exc_info())))
+            else:
+                send(("finished", wrap(retval)))
         elif command == 'finished':
             return unwrap(data)
+        elif command == 'raised':
+            exc, val, tb = unwrap(data)
+            raise exc, val, tb
         elif command == 'type_reg':
             type_id, name, _dict = data
             protocol.keeper.fake_remote_type(protocol, type_id, name, _dict)
@@ -272,7 +303,11 @@
     def perform(self, id, name, *args, **kwargs):
         args, kwargs = self.pack_args(args, kwargs)
         self.send(('call', (id, name, args, kwargs)))
-        retval = remote_loop(self)
+        try:
+            retval = remote_loop(self)
+        except:
+            e, val, tb = sys.exc_info()
+            raise e, val, tb.tb_next.tb_next
         return retval
     
     def get_remote(self, name):

Modified: pypy/dist/pypy/lib/test2/test_distributed.py
==============================================================================
--- pypy/dist/pypy/lib/test2/test_distributed.py	(original)
+++ pypy/dist/pypy/lib/test2/test_distributed.py	Tue Dec 12 00:04:41 2006
@@ -180,3 +180,20 @@
         xf = protocol.get_remote('f')
         assert f.f_globals.keys() == xf.f_globals.keys()
         assert f.f_locals.keys() == xf.f_locals.keys()
+
+    def test_remote_exception(self):
+        from distributed import test_env
+        
+        def raising():
+            1/0
+        
+        protocol = test_env({'raising':raising})
+        xr = protocol.get_remote('raising')
+        try:
+            xr()
+        except ZeroDivisionError:
+            import sys
+            exc_info, val, tb  = sys.exc_info()
+            #assert tb.tb_next is None
+        else:
+            raise AssertionError("Did not raise")



More information about the Pypy-commit mailing list