[pypy-svn] r34645 - in pypy/dist/pypy/lib: . test2

fijal at codespeak.net fijal at codespeak.net
Thu Nov 16 00:19:16 CET 2006


Author: fijal
Date: Thu Nov 16 00:19:14 2006
New Revision: 34645

Modified:
   pypy/dist/pypy/lib/distributed.py
   pypy/dist/pypy/lib/test2/test_distributed.py
Log:
(pedronis, fijal) - Basic demo of methods now works. Now we need to perform some refactoring, cause code grows a bit too much, as well as some stackless module inspection.


Modified: pypy/dist/pypy/lib/distributed.py
==============================================================================
--- pypy/dist/pypy/lib/distributed.py	(original)
+++ pypy/dist/pypy/lib/distributed.py	Thu Nov 16 00:19:14 2006
@@ -43,37 +43,27 @@
 
 # XXX We do not make any garbage collection. We'll need it at some point
 
+"""
+TODO list:
+
+1. Move it to more than one file
+2. Refactor it a bit (split class into logical/bookkeeper one)
+3. Add some garbage collection
+4. Add caching of objects that are presented (even on name level)
+"""
+
 from pypymagic import pypy_repr
 
 import types
 from marshal import dumps
 
-def get_bound(im_class, im_self, im_func):
-    return FakeMethod(im_class, im_self, im_func)
-
-class FakeMethod(object):
-    def __init__(self, im_class, im_self, im_func):
-        self.im_self = im_self
-        self.im_func = im_func
-        self.im_class = im_class
-    
-    def __call__(self, *args, **kwargs):
-        return self.im_func(self.im_self, *args, **kwargs)
-    
-    def __get__(self, instance, owner=None):
-        if self.im_self is not None:
-            return self
-        if not owner is None and not issubclass(owner, self.im_class):
-            return self
-        else:
-            return get_bound(self.im_class, instance, self.im_func)
-
 class AbstractProtocol(object):
     letter_types = {
         'l' : list,
         'd' : dict,
         't' : tuple,
         'i' : int,
+        'b' : bool,
         'f' : float,
         'u' : unicode,
         'l' : long,
@@ -83,13 +73,14 @@
         'fun' : types.FunctionType,
         'cus' : object,
         'meth' : types.MethodType,
+        'type' : type,
         'tp' : None,
     }
     type_letters = dict([(value, key) for key, value in letter_types.items()])
     assert len(type_letters) == len(letter_types)
     
     def __init__(self):
-        self.remote_objects = {}
+        self.remote_objects = {} # a dictionary controller --> id
         self.objs = [] # we just store everything, maybe later
            # we'll need some kind of garbage collection
     
@@ -106,7 +97,7 @@
             return "tp", self.remote_objects[ctrl]
         elif obj is None:
             return self.type_letters[tp]
-        elif tp in (str, int, float, long, unicode):
+        elif tp in (str, int, float, long, unicode, bool):
             # simple, immutable object, just copy
             return (self.type_letters[tp], obj)
         elif tp is tuple:
@@ -115,14 +106,18 @@
         elif tp in (list, dict, types.FunctionType):
             id = self.register_obj(obj)
             return (self.type_letters[tp], id)
+        elif tp is type:
+            id = self.register_type(obj)
+            return (self.type_letters[tp], id)
         elif tp is types.MethodType:
             type_id = self.register_type(obj.im_class)
-            self_ = self.wrap(obj.im_self)
-            func_ = self.wrap(obj.im_func)
-            return (self.type_letters[tp], (type_id, self_, func_))
+            w_func = self.wrap(obj.im_func)
+            w_self = self.wrap(obj.im_self)
+            return (self.type_letters[tp], (type_id, \
+                self.wrap(obj.im_func.func_name), w_func, w_self))
         else:
-            type_id = self.register_type(tp)
             id = self.register_obj(obj)
+            type_id = self.register_type(tp)
             return ("cus", (type_id, id))
     
     def unwrap(self, data):
@@ -134,7 +129,7 @@
         tp = self.letter_types[tp_letter]
         if tp is None:
             return self.objs[obj_data]
-        elif tp in (str, int, float, long, unicode):
+        elif tp in (str, int, float, long, unicode, bool):
             return obj_data # this is the object
         elif tp is tuple:
             return tuple([self.unwrap(i) for i in obj_data])
@@ -144,9 +139,19 @@
             self.remote_objects[ro.perform] = id
             return proxy(tp, ro.perform)
         elif tp is types.MethodType:
-            type_id, w_self, w_func = obj_data
+            type_id, w_name, w_func, w_self = obj_data
             tp = self.get_type(type_id)
-            return FakeMethod(tp, self.unwrap(w_self), self.unwrap(w_func))
+            name = self.unwrap(w_name)
+            self_ = self.unwrap(w_self)
+            if self_:
+                return getattr(tp, name).__get__(self_, tp)
+            func = self.unwrap(w_func)
+            setattr(tp, name, func)
+            return getattr(tp, name)
+        elif tp is type:
+            id = obj_data
+            elem = self.get_type(obj_data)
+            return elem
         elif tp is object:
             # we need to create a proper type
             type_id, id = obj_data
@@ -171,9 +176,6 @@
         kwargs = dict([(self.unwrap(key), self.unwrap(val)) for key, val in kwargs.items()])
         return args, kwargs
     
-    def fake_deferred(self):
-        pass
-
 class LocalProtocol(AbstractProtocol):
     """ This is stupid protocol for testing purposes only
     """
@@ -197,12 +199,12 @@
     def get_type(self, id):
         return self.types[id]
 
-def remote_loop(send, receive, exported_names, protocol=None):
+def remote_loop(protocol):
     # the simplest version possible, without any concurrency and such
-    if protocol is None:
-        protocol = RemoteProtocol(send, receive, exported_names)
     wrap = protocol.wrap
     unwrap = protocol.unwrap
+    send = protocol.send
+    receive = protocol.receive
     # we need this for wrap/unwrap
     while 1:
         command, data = receive()
@@ -215,7 +217,6 @@
             retval = getattr(protocol.objs[id], name)(*args, **kwargs)
             send(("finished", wrap(retval)))
         elif command == 'finished':
-            #protocol.fake_deferred()
             return unwrap(data)
         elif command == 'type_reg':
             type_id, name, _dict = data
@@ -234,17 +235,16 @@
         self.type_cache = {}
         self.type_id = 0
         self.remote_types = {}
-        #self.deferred_attr_set = []
     
     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.send, self.receive, self)
+        retval = remote_loop(self)
         return retval
     
     def get_remote(self, name):
         self.send(("get", name))
-        retval = remote_loop(self.send, self.receive, self)
+        retval = remote_loop(self)
         return retval
     
     def register_type(self, tp):
@@ -259,17 +259,12 @@
         # XXX: We don't support inheritance here, nor recursive types
         #      shall we???
         _dict = dict([(key, self.wrap(getattr(tp, key))) for key in dir(tp) 
-            if key not in ('__dict__', '__weakref__', '__class__', '__new__')])
+            if key not in ('__dict__', '__weakref__', '__class__', '__new__',
+                '__base__', '__flags__', '__mro__', '__bases__')])
         self.send(("type_reg", (tp_id, 
             tp.__name__, _dict)))
         return tp_id
     
-    #def fake_deferred(self):
-    #    for tp, _dict in self.deferred_attr_set:
-    #        for key, value in _dict.items():
-    #            setattr(tp, key, self.unwrap(value))
-    #    self.deferred_attr_set = []
-    
     def register_fake_type(self, type_id, _name, _dict):
         print "Faking type %s as %s" % (_name, type_id)
         # create and register new type
@@ -280,7 +275,10 @@
         self.remote_types[type_id] = tp
         for key, value in _dict.items():
             if key != '__doc__':
-                setattr(tp, key, self.unwrap(value))
+                try:
+                    setattr(tp, key, self.unwrap(value))
+                except TypeError:
+                    import pdb;pdb.set_trace()
     
     def get_type(self, id):
         try:
@@ -302,7 +300,7 @@
     # XXX: This is a hack, proper support for recursive type is needed
     inp, out = channel(), channel()
     remote_protocol = RemoteProtocol(inp.send, out.receive, exported_names)
-    t = tasklet(remote_loop)(inp.send, out.receive, exported_names, remote_protocol)
+    t = tasklet(remote_loop)(remote_protocol)
     return RemoteProtocol(out.send, inp.receive)
 
 #def bootstrap(gw):

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	Thu Nov 16 00:19:14 2006
@@ -122,3 +122,22 @@
         assert xa.x == 3
         assert len(xa) == 11
     
+    def test_remote_doc_and_callback(self):
+        class A:
+            """xxx"""
+            def __init__(self):
+                pass
+
+            def meth(self, x):
+                return x() + 3
+        
+        def x():
+            return 1
+        
+        a = A()
+        
+        from distributed import test_env
+        protocol = test_env({'a':a})
+        xa = protocol.get_remote('a')
+        assert xa.__class__.__doc__ == 'xxx'
+        assert xa.meth(x) == 4



More information about the Pypy-commit mailing list