""" transparent.py - Several transparent proxy helpers """ from pypy.interpreter import gateway from pypy.interpreter.error import OperationError, oefmt from pypy.interpreter.typedef import Function, GeneratorIterator, PyTraceback, \ PyFrame, PyCode from pypy.objspace.std.proxyobject import W_Transparent from pypy.objspace.std.typeobject import W_TypeObject from rpython.rlib.unroll import unrolling_iterable class W_TransparentFunction(W_Transparent): typedef = Function.typedef class W_TransparentTraceback(W_Transparent): typedef = PyTraceback.typedef class W_TransparentCode(W_Transparent): typedef = PyCode.typedef class W_TransparentFrame(W_Transparent): typedef = PyFrame.typedef class W_TransparentGenerator(W_Transparent): typedef = GeneratorIterator.typedef class TypeCache(object): def __init__(self): self.cache = [] def _freeze_(self): self.cache = unrolling_iterable(self.cache) return True type_cache = TypeCache() def setup(space): """Add proxy functions to the __pypy__ module.""" w___pypy__ = space.getbuiltinmodule("__pypy__") space.setattr(w___pypy__, space.newtext('tproxy'), app_proxy.spacebind(space)) space.setattr(w___pypy__, space.newtext('get_tproxy_controller'), app_proxy_controller.spacebind(space)) def proxy(space, w_type, w_controller): """tproxy(typ, controller) -> obj Return something that looks like it is of type typ. Its behaviour is completely controlled by the controller.""" if not space.is_true(space.callable(w_controller)): raise oefmt(space.w_TypeError, "controller should be function") if isinstance(w_type, W_TypeObject): if space.issubtype_w(w_type, space.gettypeobject(Function.typedef)): return W_TransparentFunction(space, w_type, w_controller) if space.issubtype_w(w_type, space.gettypeobject(PyTraceback.typedef)): return W_TransparentTraceback(space, w_type, w_controller) if space.issubtype_w(w_type, space.gettypeobject(PyFrame.typedef)): return W_TransparentFrame(space, w_type, w_controller) if space.issubtype_w(w_type, space.gettypeobject(GeneratorIterator.typedef)): return W_TransparentGenerator(space, w_type, w_controller) if space.issubtype_w(w_type, space.gettypeobject(PyCode.typedef)): return W_TransparentCode(space, w_type, w_controller) if w_type.layout.typedef is space.w_object.layout.typedef: return W_Transparent(space, w_type, w_controller) else: raise oefmt(space.w_TypeError, "type expected as first argument") w_lookup = w_type for k, v in type_cache.cache: if w_lookup == k: return v(space, w_type, w_controller) raise oefmt(space.w_TypeError, "'%N' object could not be wrapped", w_type) def register_proxyable(space, cls): tpdef = cls.typedef class W_TransparentUserCreated(W_Transparent): typedef = tpdef type_cache.cache.append((space.gettypeobject(tpdef), W_TransparentUserCreated)) def proxy_controller(space, w_object): """get_tproxy_controller(obj) -> controller If obj is really a transparent proxy, return its controller. Otherwise return None.""" if isinstance(w_object, W_Transparent): return w_object.w_controller #if isinstance(w_object, W_TransparentObject): # return w_object.w_controller return None app_proxy = gateway.interp2app(proxy) app_proxy_controller = gateway.interp2app(proxy_controller)