[pypy-svn] r40966 - in pypy/dist: demo pypy/lib pypy/lib/test2
hpk at codespeak.net
hpk at codespeak.net
Wed Mar 21 20:02:35 CET 2007
Author: hpk
Date: Wed Mar 21 20:02:34 2007
New Revision: 40966
Modified:
pypy/dist/demo/tp-persistence.py
pypy/dist/pypy/lib/test2/test_tputil.py
pypy/dist/pypy/lib/tputil.py
Log:
settling the tputil API to handle both virtual
and concrete proxies (the latter are instantiated
through providing an instance 'obj' and there is
convenient help to delegate operations to it,
see the tests and docstring for details)
Modified: pypy/dist/demo/tp-persistence.py
==============================================================================
--- pypy/dist/demo/tp-persistence.py (original)
+++ pypy/dist/demo/tp-persistence.py Wed Mar 21 20:02:34 2007
@@ -5,7 +5,7 @@
"""
from pypymagic import tproxy, get_tproxy_controller
-from tputil import make_instance_proxy
+from tputil import make_proxy
list_changeops = set('__iadd__ __imul__ __delitem__ __setitem__ '
'__delslice__ __setslice__ '
@@ -13,11 +13,11 @@
def make_plist(instance, storage):
def perform(invocation):
- res = invocation.perform()
+ res = invocation.delegate()
if invocation.opname in list_changeops:
storage.dump(instance)
return res
- return make_instance_proxy(instance, perform, typ=list)
+ return make_proxy(perform, type=list, obj=instance)
def get_plist(storage):
obj = storage.load()
Modified: pypy/dist/pypy/lib/test2/test_tputil.py
==============================================================================
--- pypy/dist/pypy/lib/test2/test_tputil.py (original)
+++ pypy/dist/pypy/lib/test2/test_tputil.py Wed Mar 21 20:02:34 2007
@@ -1,35 +1,59 @@
from pypy.conftest import gettestobjspace
-class AppTestTPListproxy:
+class AppTest_make_proxy:
def setup_class(cls):
cls.space = gettestobjspace(**{"objspace.std.withtproxy": True})
+
+ def test_errors(self):
+ from tputil import make_proxy
+ raises(TypeError, "make_proxy(None)")
+ raises(TypeError, "make_proxy(None, None)")
+ def f(): pass
+ raises(TypeError, "make_proxy(f)")
+ raises(TypeError, "make_proxy(f, None, None)")
+
+ def test_virtual_proxy(self):
+ from tputil import make_proxy
+ l = []
+ tp = make_proxy(l.append, type=list)
+ x = len(tp)
+ assert len(l) == 1
+ assert l[0].opname == '__len__'
- def test_listproxy_basic(self):
- from tputil import make_instance_proxy
+ def test_simple(self):
+ from tputil import make_proxy
record = []
- def func(invocation):
- record.append(invocation)
- return invocation.perform()
- l = make_instance_proxy([], func)
+ def func(operation):
+ record.append(operation)
+ return operation.delegate()
+ l = make_proxy(func, obj=[])
l.append(1)
assert len(record) == 2
i1, i2 = record
assert i1.opname == '__getattribute__'
assert i2.opname == 'append'
+ def test_missing_attr(self):
+ from tputil import make_proxy
+ def func(operation):
+ return operation.delegate()
+ l = make_proxy(func, obj=[])
+ excinfo = raises(AttributeError, "l.asdasd")
+ assert str(excinfo).find("asdasd") != -1
+
def test_proxy_double(self):
- from tputil import make_instance_proxy
+ from tputil import make_proxy
r1 = []
r2 = []
- def func1(invocation):
- r1.append(invocation)
- return invocation.perform()
- def func2(invocation):
- r2.append(invocation)
- return invocation.perform()
+ def func1(operation):
+ r1.append(operation)
+ return operation.delegate()
+ def func2(operation):
+ r2.append(operation)
+ return operation.delegate()
- l = make_instance_proxy([], func1)
- l2 = make_instance_proxy(l, func2)
+ l = make_proxy(func1, obj=[])
+ l2 = make_proxy(func2, obj=l)
assert not r1 and not r2
l2.append
assert len(r2) == 1
@@ -42,12 +66,12 @@
def test_proxy_inplace_add(self):
r = []
- from tputil import make_instance_proxy
- def func1(invocation):
- r.append(invocation)
- return invocation.perform()
+ from tputil import make_proxy
+ def func1(operation):
+ r.append(operation)
+ return operation.delegate()
- l2 = make_instance_proxy([], func1)
+ l2 = make_proxy(func1, obj=[])
l = l2
l += [3]
assert l is l2
Modified: pypy/dist/pypy/lib/tputil.py
==============================================================================
--- pypy/dist/pypy/lib/tputil.py (original)
+++ pypy/dist/pypy/lib/tputil.py Wed Mar 21 20:02:34 2007
@@ -10,34 +10,59 @@
from pypymagic import tproxy
from types import MethodType
-def make_instance_proxy(instance, invokefunc=None, typ=None):
- if typ is None:
- typ = type(instance)
+_dummy = object()
+origtype = type
+
+def make_proxy(controller, type=_dummy, obj=_dummy):
+ """ return a tranparent proxy controlled by the given
+ 'controller' callable. The proxy will appear
+ as a completely regular instance of the given
+ type but all operations on it are send to the
+ specified controller - which receices on
+ ProxyOperation instance on each such call. A non-specified
+ type will default to type(obj) if obj is specified.
+ """
+ if type is _dummy:
+ if obj is _dummy:
+ raise TypeError("you must specify a type or an instance obj")
+ type = origtype(obj)
def perform(opname, *args, **kwargs):
- invocation = Invocation(tp, instance, opname, args, kwargs)
- return invokefunc(invocation)
- tp = tproxy(typ, perform)
+ operation = ProxyOperation(tp, type, obj, opname, args, kwargs)
+ return controller(operation)
+ tp = tproxy(type, perform)
return tp
-class Invocation(object):
- def __init__(self, proxyobj, realobj, opname, args, kwargs):
+class ProxyOperation(object):
+ def __init__(self, proxyobj, type, obj, opname, args, kwargs):
self.proxyobj = proxyobj
- self.realobj = realobj
self.opname = opname
self.args = args
self.kwargs = kwargs
- self.realmethod = getattr(realobj, opname)
+ self.type = type
+ if obj is not _dummy:
+ self.obj = obj
- def perform(self):
- res = self.realmethod(*self.args, **self.kwargs)
+ def delegate(self):
+ """ return result from delegating this operation to the
+ underyling self.obj - which must exist and is usually
+ provided through the initial make_proxy(..., obj=...)
+ creation.
+ """
+ try:
+ obj = getattr(self, 'obj')
+ except AttributeError:
+ raise TypeError("proxy does not have an underlying 'obj', "
+ "cannot delegate")
+ objattr = getattr(obj, self.opname)
+ res = objattr(*self.args, **self.kwargs)
if self.opname == "__getattribute__":
if (isinstance(res, MethodType) and
- res.im_self is self.realobj):
+ res.im_self is self.instance):
res = MethodType(res.im_func, self.proxyobj, res.im_class)
- if res is self.realobj:
- return self.proxyobj
+ if res is self.obj:
+ res = self.proxyobj
return res
def __repr__(self):
- return "<Invocation %s(*%r, **%r)" %(self.realmethod,
- self.args, self.kwargs)
+ return "<ProxyOperation %s(*%r, **%r) %x>" %(
+ self.opname, self.args, self.kwargs, id(self))
More information about the Pypy-commit
mailing list