[pypy-svn] r39730 - in pypy/dist/pypy/lib/distributed: . test

fijal at codespeak.net fijal at codespeak.net
Fri Mar 2 18:06:54 CET 2007


Author: fijal
Date: Fri Mar  2 18:06:52 2007
New Revision: 39730

Modified:
   pypy/dist/pypy/lib/distributed/objkeeper.py
   pypy/dist/pypy/lib/distributed/protocol.py
   pypy/dist/pypy/lib/distributed/test/test_distributed.py
Log:
Make classmethods work remotely


Modified: pypy/dist/pypy/lib/distributed/objkeeper.py
==============================================================================
--- pypy/dist/pypy/lib/distributed/objkeeper.py	(original)
+++ pypy/dist/pypy/lib/distributed/objkeeper.py	Fri Mar  2 18:06:52 2007
@@ -11,18 +11,18 @@
     _, _, tb = sys.exc_info()
     GetSetDescriptor = type(type(tb).tb_frame)
 
-class noninstantiabletype(object):
-    def __new__(cls, *args, **kwargs):
-        raise NotImplementedError("Cannot instantiate remote type")
+class RemoteBase(object):
+    pass
 
 class ObjKeeper(object):
     def __init__(self, exported_names = {}):
         self.exported_objects = [] # list of object that we've exported outside
         self.exported_names = exported_names # dictionary of visible objects
-        self.exported_types = {} # list of exported types
+        self.exported_types = {} # dict of exported types
         self.remote_types = {}
         self.remote_objects = {}
         self.exported_types_id = 0 # unique id of exported types
+        self.exported_types_reverse = {} # reverse dict of exported types
     
     def register_object(self, obj):
         # XXX: At some point it makes sense not to export them again and again...
@@ -30,7 +30,7 @@
         return len(self.exported_objects) - 1
     
     def ignore(self, key, value):
-        if key in ('__dict__', '__weakref__', '__class__', '__new__'):
+        if key in ('__dict__', '__weakref__', '__class__'):
             return True
         if isinstance(value, GetSetDescriptor):
             return True
@@ -42,6 +42,7 @@
         except KeyError:
             print "Registering type %s as %s" % (tp, self.exported_types_id)
             self.exported_types[tp] = self.exported_types_id
+            self.exported_types_reverse[self.exported_types_id] = tp
             tp_id = self.exported_types_id
             self.exported_types_id += 1
         
@@ -56,15 +57,21 @@
     def fake_remote_type(self, protocol, type_id, _name, _dict):
         print "Faking type %s as %s" % (_name, type_id)
         # create and register new type
-        d = dict([(key, None) for key in _dict if key != '__new__'])
+        d = dict([(key, None) for key in _dict])
+        # some stuff needs to go first...
         if '__doc__' in _dict:
             d['__doc__'] = protocol.unwrap(_dict['__doc__'])
-        tp = type(_name, (noninstantiabletype,), d)
+        tp = type(_name, (RemoteBase,), d)
+        tp.__metaremote__ = type_id
         # Make sure we cannot instantiate the remote type
         self.remote_types[type_id] = tp
         for key, value in _dict.items():
             if key != '__doc__':
                 setattr(tp, key, protocol.unwrap(value))
+            #elif key == '__new__':
+            #    import pdb
+            #    pdb.set_trace()
+            #    tp.new = value
                     
     def get_type(self, id):
         return self.remote_types[id]

Modified: pypy/dist/pypy/lib/distributed/protocol.py
==============================================================================
--- pypy/dist/pypy/lib/distributed/protocol.py	(original)
+++ pypy/dist/pypy/lib/distributed/protocol.py	Fri Mar  2 18:06:52 2007
@@ -41,7 +41,7 @@
 except ImportError:
     raise ImportError("Cannot work without transparent proxy functionality")
 
-from distributed.objkeeper import ObjKeeper
+from distributed.objkeeper import ObjKeeper, RemoteBase
 import sys
 
 # XXX We do not make any garbage collection. We'll need it at some point
@@ -91,6 +91,7 @@
         'tp' : None,
         'fr' : types.FrameType,
         'tb' : types.TracebackType,
+        'reg' : RemoteBase
     }
     type_letters = dict([(value, key) for key, value in letter_types.items()])
     assert len(type_letters) == len(letter_types)
@@ -131,6 +132,10 @@
             id = self.keeper.register_object(obj)
             return (self.type_letters[tp], id)
         elif tp is type:
+            if isinstance(obj, RemoteBase):
+                import pdb
+                pdb.set_trace()
+                return "reg", obj.__metaremote__
             try:
                 return self.type_letters[tp], self.type_letters[obj]
             except KeyError:
@@ -156,6 +161,8 @@
         tp = self.letter_types[tp_letter]
         if tp is None:
             return self.keeper.get_object(obj_data)
+        elif tp is RemoteBase:
+            return self.keeper.exported_types_reverse[obj_data]
         elif tp in self.immutable_primitives:
             return obj_data # this is the object
         elif tp is tuple:
@@ -179,6 +186,9 @@
             name = self.unwrap(w_name)
             self_ = self.unwrap(w_self)
             if self_:
+                if not tp:
+                    setattr(self_, name, classmethod(self.unwrap(w_func)))
+                    return getattr(self_, name)
                 return getattr(tp, name).__get__(self_, tp)
             func = self.unwrap(w_func)
             setattr(tp, name, func)
@@ -368,4 +378,13 @@
     inp, out = channel(), channel()
     remote_protocol = RemoteProtocol(inp.send, out.receive, exported_names)
     t = tasklet(remote_loop)(remote_protocol)
-    return RemoteProtocol(out.send, inp.receive)
+    
+    def send_trace(data):
+        print "Sending %s" % (data,)
+        out.send(data)
+
+    def receive_trace():
+        data = inp.receive()
+        print "Received %s" % (data,)
+        return data
+    return RemoteProtocol(send_trace, receive_trace)

Modified: pypy/dist/pypy/lib/distributed/test/test_distributed.py
==============================================================================
--- pypy/dist/pypy/lib/distributed/test/test_distributed.py	(original)
+++ pypy/dist/pypy/lib/distributed/test/test_distributed.py	Fri Mar  2 18:06:52 2007
@@ -198,11 +198,25 @@
         else:
             raise AssertionError("Did not raise")
 
+    def test_remote_classmethod(self):
+        class A:
+            z = 8
+
+            @classmethod
+            def x(cls):
+                return cls.z
+
+        a = A()
+        protocol = self.test_env({'a':a})
+        xa = protocol.get_remote("a")
+        res = xa.x()
+        assert res == 8
+
     def test_instantiate_remote_type(self):
-        #skip("Land of infinite recursion")
+        skip("Doesn't work yet")
         class C:
             pass
 
         protocol = self.test_env({'C':C})
         xC = protocol.get_remote('C')
-        raises(NotImplementedError, "xC()")
+        xC()


More information about the pypy-svn mailing list