/pypy/objspace/std/fake.py
Python | 260 lines | 214 code | 35 blank | 11 comment | 44 complexity | 42de181a21b8424d051114e5d417ed86 MD5 | raw file
- import types
- from pypy.interpreter.error import OperationError, debug_print
- from pypy.interpreter import baseobjspace
- from pypy.interpreter import eval
- from pypy.interpreter.function import Function, BuiltinFunction
- from pypy.objspace.std.stdtypedef import *
- from pypy.objspace.std.model import W_Object, UnwrapError
- from pypy.interpreter.baseobjspace import Wrappable
- from pypy.interpreter.typedef import TypeDef
- from pypy.interpreter import gateway, argument
- # this file automatically generates non-reimplementations of CPython
- # types that we do not yet implement in the standard object space
- def fake_object(space, x):
- if isinstance(x, file):
- debug_print("fake-wrapping interp file %s" % x)
- if isinstance(x, type):
- ft = fake_type(x)
- return space.gettypeobject(ft.typedef)
- #debug_print("faking obj %s" % x)
- ft = fake_type(type(x))
- return ft(space, x)
- import sys
- _fake_type_cache = {}
- # real-to-wrapped exceptions
- def wrap_exception(space):
- """NOT_RPYTHON"""
- exc, value, tb = sys.exc_info()
- if exc is OperationError:
- raise exc, value, tb # just re-raise it
- name = exc.__name__
- if hasattr(space, 'w_' + name):
- w_exc = getattr(space, 'w_' + name)
- w_value = space.call_function(w_exc,
- *[space.wrap(a) for a in value.args])
- for key, value in value.__dict__.items():
- if not key.startswith('_'):
- space.setattr(w_value, space.wrap(key), space.wrap(value))
- else:
- debug_print('likely crashes because of faked exception %s: %s' % (
- exc.__name__, value))
- w_exc = space.wrap(exc)
- w_value = space.wrap(value)
- raise OperationError, OperationError(w_exc, w_value), tb
- def fake_type(cpy_type):
- assert isinstance(type(cpy_type), type)
- try:
- return _fake_type_cache[cpy_type]
- except KeyError:
- faked_type = really_build_fake_type(cpy_type)
- _fake_type_cache[cpy_type] = faked_type
- return faked_type
- def really_build_fake_type(cpy_type):
- "NOT_RPYTHON (not remotely so!)."
- debug_print('faking %r'%(cpy_type,))
- kw = {}
- if cpy_type.__name__ == 'SRE_Pattern':
- import re
- import __builtin__
- p = re.compile("foo")
- for meth_name in p.__methods__:
- kw[meth_name] = EvenMoreObscureWrapping(__builtin__.eval("lambda p,*args,**kwds: p.%s(*args,**kwds)" % meth_name))
- elif cpy_type.__name__ == 'SRE_Match':
- import re
- import __builtin__
- m = re.compile("foo").match('foo')
- for meth_name in m.__methods__:
- kw[meth_name] = EvenMoreObscureWrapping(__builtin__.eval("lambda m,*args,**kwds: m.%s(*args,**kwds)" % meth_name))
- else:
- for s, v in cpy_type.__dict__.items():
- if not (cpy_type is unicode and s in ['__add__', '__contains__']):
- if s != '__getattribute__' or cpy_type is type(sys) or cpy_type is type(Exception):
- kw[s] = v
- kw['__module__'] = cpy_type.__module__
- def fake__new__(space, w_type, __args__):
- args_w, kwds_w = __args__.unpack()
- args = [space.unwrap(w_arg) for w_arg in args_w]
- kwds = {}
- for (key, w_value) in kwds_w.items():
- kwds[key] = space.unwrap(w_value)
- try:
- r = cpy_type.__new__(*[cpy_type]+args, **kwds)
- except:
- wrap_exception(space)
- raise
- w_obj = space.allocate_instance(W_Fake, w_type)
- W_Fake.__init__(w_obj, space, r)
- return w_obj
- fake__new__.func_name = "fake__new__" + cpy_type.__name__
- kw['__new__'] = gateway.interp2app(fake__new__)
- if cpy_type.__base__ is object or issubclass(cpy_type, Exception):
- base = None
- elif cpy_type.__base__ is basestring:
- from pypy.objspace.std.basestringtype import basestring_typedef
- base = basestring_typedef
- elif cpy_type.__base__ is tuple:
- from pypy.objspace.std.tupletype import tuple_typedef
- base = tuple_typedef
- elif cpy_type.__base__ is type:
- from pypy.objspace.std.typetype import type_typedef
- base = type_typedef
- else:
- raise NotImplementedError(cpy_type, cpy_type.__base__)
- class W_Fake(W_Object):
- typedef = StdTypeDef(
- cpy_type.__name__, base, **kw)
- def __init__(w_self, space, val):
- w_self.val = val
- w_self.space = space
- def getdict(w_self, space):
- try:
- d = w_self.val.__dict__
- except AttributeError:
- return W_Object.getdict(w_self, space)
- return space.wrap(d)
- def unwrap(w_self, space):
- return w_self.val
- if cpy_type is types.FunctionType:
- def __get__(self, obj, owner):
- return fake_object(self.space, self.val.__get__(obj, owner))
- W_Fake.__name__ = 'W_Fake%s'%(cpy_type.__name__.capitalize())
- W_Fake.typedef.fakedcpytype = cpy_type
- return W_Fake
- # ____________________________________________________________
- #
- # Special case for built-in functions, methods, and slot wrappers.
- class CPythonFakeCode(eval.Code):
- def __init__(self, cpy_callable):
- eval.Code.__init__(self, getattr(cpy_callable, '__name__', '?'))
- self.cpy_callable = cpy_callable
- assert callable(cpy_callable), cpy_callable
- def signature(self):
- return argument.Signature([], 'args', 'kwds')
- def funcrun(self, func, args):
- frame = func.space.createframe(self, func.w_func_globals,
- func)
- sig = self.signature()
- scope_w = args.parse_obj(None, func.name, sig, func.defs_w)
- frame.setfastscope(scope_w)
- return frame.run()
- class CPythonFakeFrame(eval.Frame):
- def __init__(self, space, code, w_globals=None):
- self.fakecode = code
- eval.Frame.__init__(self, space, w_globals)
- def getcode(self):
- return self.fakecode
- def setfastscope(self, scope_w):
- w_args, w_kwds = scope_w
- try:
- self.unwrappedargs = self.space.unwrap(w_args)
- self.unwrappedkwds = self.space.unwrap(w_kwds)
- except UnwrapError, e:
- code = self.fakecode
- assert isinstance(code, CPythonFakeCode)
- raise UnwrapError('calling %s: %s' % (code.cpy_callable, e))
- def getfastscope(self):
- raise OperationError(self.space.w_TypeError,
- self.space.wrap("cannot get fastscope of a CPythonFakeFrame"))
- def run(self):
- code = self.fakecode
- assert isinstance(code, CPythonFakeCode)
- fn = code.cpy_callable
- try:
- result = apply(fn, self.unwrappedargs, self.unwrappedkwds)
- except:
- wrap_exception(self.space)
- raise
- return self.space.wrap(result)
- class EvenMoreObscureWrapping(baseobjspace.Wrappable):
- def __init__(self, val):
- self.val = val
- def __spacebind__(self, space):
- return fake_builtin_callable(space, self.val)
- def fake_builtin_callable(space, val):
- return Function(space, CPythonFakeCode(val))
- def fake_builtin_function(space, fn):
- func = fake_builtin_callable(space, fn)
- if fn.__self__ is None:
- func = BuiltinFunction(func)
- return func
- _fake_type_cache[type(len)] = fake_builtin_function
- _fake_type_cache[type(list.append)] = fake_builtin_callable
- _fake_type_cache[type(type(None).__repr__)] = fake_builtin_callable
- class W_FakeDescriptor(Wrappable):
- # Mimics pypy.interpreter.typedef.GetSetProperty.
- def __init__(self, space, d):
- self.name = d.__name__
- def descr_descriptor_get(self, space, w_obj, w_cls=None):
- # XXX HAAAAAAAAAAAACK (but possibly a good one)
- if (space.is_w(w_obj, space.w_None)
- and not space.is_w(w_cls, space.type(space.w_None))):
- #print self, w_obj, w_cls
- return space.wrap(self)
- else:
- name = self.name
- obj = space.unwrap(w_obj)
- try:
- val = getattr(obj, name) # this gives a "not RPython" warning
- except:
- wrap_exception(space)
- raise
- return space.wrap(val)
- def descr_descriptor_set(self, space, w_obj, w_value):
- name = self.name
- obj = space.unwrap(w_obj)
- val = space.unwrap(w_value)
- try:
- setattr(obj, name, val) # this gives a "not RPython" warning
- except:
- wrap_exception(space)
- def descr_descriptor_del(self, space, w_obj):
- name = self.name
- obj = space.unwrap(w_obj)
- try:
- delattr(obj, name)
- except:
- wrap_exception(space)
- W_FakeDescriptor.typedef = TypeDef(
- "FakeDescriptor",
- __get__ = gateway.interp2app(W_FakeDescriptor.descr_descriptor_get),
- __set__ = gateway.interp2app(W_FakeDescriptor.descr_descriptor_set),
- __delete__ = gateway.interp2app(W_FakeDescriptor.descr_descriptor_del),
- )
- if hasattr(file, 'softspace'): # CPython only
- _fake_type_cache[type(file.softspace)] = W_FakeDescriptor
- _fake_type_cache[type(type.__dict__['__dict__'])] = W_FakeDescriptor