1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
|
"""
application level support module for transparent proxies.
"""
from __pypy__ import tproxy
from types import MethodType
_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 receives 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 of it")
type = origtype(obj)
def perform(opname, *args, **kwargs):
operation = ProxyOperation(tp, obj, opname, args, kwargs)
return controller(operation)
tp = tproxy(type, perform)
return tp
class ProxyOperation(object):
def __init__(self, proxyobj, obj, opname, args, kwargs):
self.proxyobj = proxyobj
self.opname = opname
self.args = args
self.kwargs = kwargs
if obj is not _dummy:
self.obj = obj
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.instance):
res = MethodType(res.im_func, self.proxyobj, res.im_class)
if res is self.obj:
res = self.proxyobj
return res
def __repr__(self):
args = ", ".join([repr(x) for x in self.args])
args = "<0x%x>, " % id(self.proxyobj) + args
if self.kwargs:
args += ", ".join(["%s=%r" % item
for item in self.kwargs.items()])
return "<ProxyOperation %s.%s(%s)>" %(
type(self.proxyobj).__name__, self.opname, args)
|