[pypy-svn] r40841 - in pypy/dist: demo pypy/lib pypy/lib/test2
hpk at codespeak.net
hpk at codespeak.net
Tue Mar 20 14:59:52 CET 2007
Author: hpk
Date: Tue Mar 20 14:59:50 2007
New Revision: 40841
Added:
pypy/dist/pypy/lib/test2/test_tputil.py (contents, props changed)
pypy/dist/pypy/lib/tputil.py (contents, props changed)
Modified:
pypy/dist/demo/tp-persistence.py
Log:
initial draft for some support for transparent
proxies, with tests. adapating the demo a bit.
Modified: pypy/dist/demo/tp-persistence.py
==============================================================================
--- pypy/dist/demo/tp-persistence.py (original)
+++ pypy/dist/demo/tp-persistence.py Tue Mar 20 14:59:50 2007
@@ -5,39 +5,26 @@
"""
from pypymagic import transparent_proxy, get_transparent_controller
-from types import MethodType
+from tputil import BaseDispatcher
-class PersistentListController(object):
+class PListDispatcher(BaseDispatcher):
_changeops = ('__iadd__ __imul__ __delitem__ __setitem__ '
- '__delslice__ __setslice__ __init__ '
+ '__delslice__ __setslice__ '
'append extend insert pop remove reverse sort').split()
- def __init__(self, obj, storage):
- self._obj = obj
+ def __init__(self, realobj, storage):
+ parent = super(PListDispatcher, self)
+ parent.__init__(realobj, list)
self._storage = storage
- self.persist()
- self.proxy = transparent_proxy(list, self.perform)
- def persist(self):
- self._storage.dump(self._obj)
-
- def perform(self, operation, *args, **kwargs):
- result = getattr(self._obj, operation)(*args, **kwargs)
- if operation in self._changeops:
- # state was modified, do maximally eager checkpointing
+ def op_default(self, realmethod, *args, **kwargs):
+ res = realmethod(*args, **kwargs)
+ if realmethod.__name__ in self._changeops:
self.persist()
- if result is self._obj:
- # If the result is the proxied list
- # return the proxy instead.
- result = self.proxy
- elif (isinstance(result, MethodType) and
- result.im_self is self._obj):
- # Convert methods bound to the proxied list
- # to methods bound to the proxy.
- # This is to have calls to the method become calls
- # to perform.
- result = MethodType(result.im_func, self.proxy, result.im_class)
- return result
+ return res
+
+ def persist(self):
+ self._storage.dump(self.realobj)
@classmethod
def load(cls, storage):
@@ -46,6 +33,7 @@
def work_with_list(mylist):
assert isinstance(mylist, list)
+ assert mylist.__class__ is list
mylist.append(4)
mylist += [5,6,7]
@@ -54,7 +42,7 @@
storage = py.path.local("/tmp/mystorage")
somelist = [1,2,3]
- newlist = PersistentListController(somelist, storage).proxy
+ newlist = PListDispatcher(somelist, storage).proxyobj
# here we may call into application code which can
# not detect easily that it is dealing with a persistent
@@ -62,6 +50,12 @@
work_with_list(newlist)
del somelist, newlist
- restoredlist = PersistentListController.load(storage).proxy
+ restoredlist = PListDispatcher.load(storage).proxyobj
print "restored list", restoredlist
- print restoredlist == [1,2,3,4,5,6,7]
+ assert restoredlist == [1,2,3,4,5,6,7]
+ restoredlist *= 2
+ del restoredlist
+ restoredlist = PListDispatcher.load(storage).proxyobj
+ print "restored list 2", restoredlist
+ assert restoredlist == [1,2,3,4,5,6,7] * 2
+
Added: pypy/dist/pypy/lib/test2/test_tputil.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lib/test2/test_tputil.py Tue Mar 20 14:59:50 2007
@@ -0,0 +1,36 @@
+from pypy.conftest import gettestobjspace
+
+class AppTestTPListproxy:
+ def setup_class(cls):
+ cls.space = gettestobjspace(**{"objspace.std.withtproxy": True})
+ cls.w_BaseDispatcher = cls.space.appexec([],"""
+ ():
+ from tputil import BaseDispatcher
+ return BaseDispatcher
+ """)
+
+ def test_listproxy_basic(self):
+ x = []
+ wrapper = self.BaseDispatcher(x)
+ assert wrapper.realobj is x
+ l = wrapper.proxyobj
+ assert type(l) is list
+ l.append(1)
+ l.extend([2,3])
+ assert l == [1,2,3]
+ assert x == l
+
+ def test_listproxy_getattribute(self):
+ disp = self.BaseDispatcher([])
+ meth = disp.proxyobj.append
+ assert meth.im_self == disp.proxyobj
+ meth = disp.proxyobj.__getattribute__
+ assert meth.im_self == disp.proxyobj
+
+ def test_listproxy_hook(self):
+ class MyBaseDispatcher(self.BaseDispatcher):
+ def op___getitem__(self, *args, **kwargs):
+ return 42
+ l = MyBaseDispatcher([]).proxyobj
+ assert l[0] == 42
+ assert l[-1] == 42
Added: pypy/dist/pypy/lib/tputil.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lib/tputil.py Tue Mar 20 14:59:50 2007
@@ -0,0 +1,39 @@
+"""
+
+application level support module for transparent proxies.
+This currently contains a BaseDispatcher class
+whose subclasses may define "op_METH" where METH
+is the original method operation name for
+the proxied object.
+
+"""
+from pypymagic import transparent_proxy
+from types import MethodType
+
+class BaseDispatcher(object):
+ def __init__(self, realobj, typ=None):
+ self.realobj = realobj
+ if typ is None:
+ typ = type(realobj)
+ self.proxyobj = transparent_proxy(typ, self.invoke)
+
+ def invoke(self, operation, *args, **kwargs):
+ """ return result from dispatching to proxied operation. """
+ realmethod = getattr(self.realobj, operation)
+ print "operation", operation
+ dispmethod = getattr(self, "op_" + operation, None)
+ if dispmethod is None:
+ dispmethod = self.op_default
+ res = dispmethod(realmethod, *args, **kwargs)
+ return res
+
+ def op___getattribute__(self, realmethod, *args, **kwargs):
+ res = realmethod(*args, **kwargs)
+ if (isinstance(res, MethodType) and
+ res.im_self is self.realobj):
+ res= MethodType(res.im_func, self.proxyobj, res.im_class)
+ return res
+
+ def op_default(self, realmethod, *args, **kwargs):
+ return realmethod(*args, **kwargs)
+
More information about the Pypy-commit
mailing list