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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
|
""" 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)
|