2
Generic support to turn interpreter objects (subclasses of Wrappable)
3
into CPython objects (subclasses of W_Object) based on their typedef.
6
from pypy.objspace.cpy.capi import *
7
from pypy.interpreter.error import OperationError
8
from pypy.interpreter.baseobjspace import Wrappable, SpaceCache
9
from pypy.interpreter.function import Function
10
from pypy.interpreter.typedef import GetSetProperty
11
from pypy.rlib.objectmodel import we_are_translated
12
from pypy.rpython.rcpy import CPyTypeInterface, cpy_export, cpy_import
13
from pypy.rpython.rcpy import cpy_typeobject, rpython_object, cpy_allocate
14
from pypy.rpython.rcpy import init_rpython_data, get_rpython_data
15
from pypy.rpython.lltypesystem import lltype
18
def rpython2cpython(space, x):
19
cache = space.fromcache(TypeDefCache)
20
typeintf = cache.getorbuild(x.typedef)
21
if we_are_translated():
22
obj = cpy_export(typeintf, x)
25
w_x = x.__cpy_wrapper__
27
w_type = cache.wraptypeintf(x.__class__, typeintf)
28
w_x = W_Object(rpython_object.__new__(w_type.value))
29
init_rpython_data(w_x.value, x)
30
x.__cpy_wrapper__ = w_x
32
rpython2cpython.allow_someobjects = True
33
rpython2cpython._annspecialcase_ = "specialize:argtype(1)"
35
def rpython2cpytype(space, Cls):
36
cache = space.fromcache(TypeDefCache)
37
typeintf = cache.getorbuild(Cls.typedef)
38
if we_are_translated():
39
cpytype = cpy_typeobject(typeintf, Cls)
40
return W_Object(cpytype)
42
return cache.wraptypeintf(Cls, typeintf)
43
rpython2cpytype.allow_someobjects = True
44
rpython2cpytype._annspecialcase_ = "specialize:arg(1)"
46
def cpython2rpython_raw(space, w_obj):
49
w_obj, result, follow = space.wrap_cache[id(w_obj)]
51
if isinstance(w_obj.value, rpython_object):
52
result = get_rpython_data(w_obj.value)
57
def cpython2rpython(space, RequiredClass, w_obj):
58
if we_are_translated():
59
cache = space.fromcache(TypeDefCache)
60
typeintf = cache.getorbuild(RequiredClass.typedef)
61
cpytype = cpy_typeobject(typeintf, RequiredClass)
62
w_cpytype = W_Object(cpytype)
63
if space.is_true(space.isinstance(w_obj, w_cpytype)):
65
return cpy_import(RequiredClass, x)
67
result = cpython2rpython_raw(space, w_obj)
68
if isinstance(result, RequiredClass):
70
w_objtype = space.type(w_obj)
71
w_name = space.getattr(w_objtype, space.wrap('__name__'))
72
typename = space.str_w(w_name)
73
msg = "'%s' object expected, got '%s' instead" % (
74
RequiredClass.typedef.name, typename)
75
raise OperationError(space.w_TypeError, space.wrap(msg))
76
cpython2rpython._annspecialcase_ = 'specialize:arg(1)'
77
cpython2rpython.allow_someobjects = True
79
def cpython_allocate(cls, w_subtype):
80
return cpy_allocate(cls, w_subtype.value)
81
cpython_allocate._annspecialcase_ = 'specialize:arg(0)'
82
cpython_allocate.allow_someobjects = True
84
# ____________________________________________________________
86
class TypeDefCache(SpaceCache):
87
def __init__(self, space):
88
super(TypeDefCache, self).__init__(space)
89
self.wrappedtypes = {}
91
def build(cache, typedef):
92
if typedef in (Function.typedef, GetSetProperty.typedef):
93
raise ValueError("cannot wrap at run-time an interpreter object "
94
"of type %r" % (typedef.name,))
97
for name, value in typedef.rawdict.items():
98
#if name.startswith('__') and name.endswith('__'):
99
# raise NotImplementedError("missing support for special "
100
# "attributes in TypeDef-to-CPython "
101
# "converter (%s.%s)" % (
102
# typedef.name, name))
103
w_value = space.wrap(value)
104
objects[name] = lltype.pyobjectptr(w_value.value)
105
typeintf = CPyTypeInterface(typedef.name, objects, typedef.acceptable_as_base_class)
108
def wraptypeintf(cache, cls, typeintf):
109
"NOT_RPYTHON. Not available after translation."
111
return cache.wrappedtypes[cls]
113
typedef = cls.typedef
115
newtype = typeintf.emulate(cls)
116
w_result = W_Object(newtype)
117
space.wrap_cache[id(w_result)] = w_result, typedef, follow_annotations
118
cache.wrappedtypes[cls] = w_result
121
def follow_annotations(bookkeeper, w_type):
126
Wrappable.__cpy_wrapper__ = None