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 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
|
"""
These are the default implementation for type slots that we put
in user-defined app-level Python classes, if the class implements
the corresponding '__xxx__' special method. It should mostly just
call back the general version of the space operation.
This is only approximately correct. One problem is that some
details are likely subtly wrong. Another problem is that we don't
track changes to an app-level Python class (addition or removal of
'__xxx__' special methods) after initalization of the PyTypeObject.
"""
from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.rlib.rarithmetic import widen
from pypy.interpreter.error import oefmt
from pypy.interpreter.argument import Arguments
from pypy.module.cpyext.api import (
slot_function, PyObject, Py_ssize_t, Py_bufferP, PyTypeObjectPtr,
CANNOT_FAIL,
)
from pypy.module.cpyext.memoryobject import fill_Py_buffer
from pypy.module.cpyext.pyobject import make_ref
@slot_function([PyObject], Py_ssize_t, error=-1)
def slot_sq_length(space, w_obj):
return space.int_w(space.len(w_obj))
@slot_function([PyObject], lltype.Signed, error=-1)
def slot_tp_hash(space, w_obj):
return space.hash_w(w_obj)
@slot_function([PyObject, Py_ssize_t], PyObject)
def slot_sq_item(space, w_obj, index):
return space.getitem(w_obj, space.newint(index))
@slot_function([PyTypeObjectPtr, PyObject, PyObject], PyObject)
def slot_tp_new(space, w_type, w_args, w_kwds):
# XXX problem - we need to find the actual __new__ function to call.
# but we have no 'self' argument. Theoretically, self will be
# w_type, but if w_type is a subclass of self, and w_type has a
# __new__ function that calls super().__new__, and that call ends
# up here, we will get infinite recursion. Prevent the recursion
# in the simple case (from cython) where w_type is a cpytype, but
# we know (since we are in this function) that self is not a cpytype
from pypy.module.cpyext.typeobject import W_PyCTypeObject
w_type0 = w_type
mro_w = space.listview(space.getattr(w_type0, space.newtext('__mro__')))
for w_m in mro_w[1:]:
if not w_type0.is_cpytype():
break
w_type0 = w_m
w_impl = space.getattr(w_type0, space.newtext('__new__'))
args = Arguments(space, [w_type],
w_stararg=w_args, w_starstararg=w_kwds)
return space.call_args(w_impl, args)
@slot_function([PyObject, PyObject, PyObject], rffi.INT_real, error=-1)
def slot_tp_init(space, w_type, w_args, w_kwds):
w_impl = space.lookup(w_type, '__init__')
args = Arguments(space, [w_type],
w_stararg=w_args, w_starstararg=w_kwds)
space.call_args(w_impl, args)
return 0
@slot_function([PyObject, PyObject, PyObject], PyObject)
def slot_tp_call(space, w_self, w_args, w_kwds):
args = Arguments(space, [], w_stararg=w_args, w_starstararg=w_kwds)
return space.call_args(w_self, args)
# unary functions
@slot_function([PyObject], PyObject)
def slot_tp_str(space, w_obj):
return space.str(w_obj)
@slot_function([PyObject], PyObject)
def slot_tp_repr(space, w_obj):
return space.repr(w_obj)
@slot_function([PyObject], PyObject)
def slot_nb_int(space, w_obj):
return space.call_function(space.w_int, w_obj)
@slot_function([PyObject], PyObject)
def slot_nb_float(space, w_obj):
return space.float(w_obj)
@slot_function([PyObject], PyObject)
def slot_nb_index(space, w_obj):
return space.index(w_obj)
#binary functions
@slot_function([PyObject, PyObject], PyObject)
def slot_nb_add(space, w_obj1, w_obj2):
return space.add(w_obj1, w_obj2)
@slot_function([PyObject, PyObject], PyObject)
def slot_nb_subtract(space, w_obj1, w_obj2):
return space.sub(w_obj1, w_obj2)
@slot_function([PyObject, PyObject], PyObject)
def slot_nb_multiply(space, w_obj1, w_obj2):
return space.mul(w_obj1, w_obj2)
@slot_function([PyObject, PyObject], PyObject)
def slot_nb_divide(space, w_obj1, w_obj2):
return space.div(w_obj1, w_obj2)
@slot_function([PyObject, PyObject], PyObject)
def slot_nb_inplace_add(space, w_obj1, w_obj2):
return space.add(w_obj1, w_obj2)
@slot_function([PyObject, PyObject], PyObject)
def slot_nb_inplace_subtract(space, w_obj1, w_obj2):
return space.sub(w_obj1, w_obj2)
@slot_function([PyObject, PyObject], PyObject)
def slot_nb_inplace_multiply(space, w_obj1, w_obj2):
return space.mul(w_obj1, w_obj2)
@slot_function([PyObject, PyObject], PyObject)
def slot_nb_inplace_divide(space, w_obj1, w_obj2):
return space.div(w_obj1, w_obj2)
@slot_function([PyObject, PyObject], PyObject)
def slot_sq_concat(space, w_obj1, w_obj2):
return space.add(w_obj1, w_obj2)
@slot_function([PyObject, PyObject], PyObject)
def slot_sq_inplace_concat(space, w_obj1, w_obj2):
return space.add(w_obj1, w_obj2)
@slot_function([PyObject, PyObject], PyObject)
def slot_mp_subscript(space, w_obj1, w_obj2):
return space.getitem(w_obj1, w_obj2)
@slot_function([PyObject, PyObject], PyObject)
def slot_tp_getattr_hook(space, w_obj1, w_obj2):
return space.getattr(w_obj1, w_obj2)
@slot_function([PyObject, PyObject, PyObject], PyObject)
def slot_tp_descr_get(space, w_self, w_obj, w_type):
if w_obj is None:
w_obj = space.w_None
return space.get(w_self, w_obj, w_type)
@slot_function([PyObject, PyObject, PyObject], rffi.INT_real, error=-1)
def slot_tp_descr_set(space, w_self, w_obj, w_value):
if w_value is not None:
space.set(w_self, w_obj, w_value)
else:
space.delete(w_self, w_obj)
return 0
@slot_function([PyObject], PyObject)
def slot_tp_iter(space, w_self):
return space.iter(w_self)
@slot_function([PyObject], PyObject)
def slot_tp_iternext(space, w_self):
return space.next(w_self)
@slot_function([PyObject], PyObject)
def slot_am_await(space, w_self):
w_await = space.lookup(w_self, "__await__")
if w_await is None:
raise oefmt(space.w_TypeError,
"object %T does not have __await__ method", w_self)
return space.get_and_call_function(w_await, w_self)
@slot_function([PyObject], PyObject)
def slot_am_aiter(space, w_self):
w_aiter = space.lookup(w_self, "__aiter__")
if w_aiter is None:
raise oefmt(space.w_TypeError,
"object %T does not have __aiter__ method", w_self)
return space.get_and_call_function(w_aiter, w_self)
@slot_function([PyObject], PyObject)
def slot_am_anext(space, w_self):
w_anext = space.lookup(w_self, "__anext__")
if w_anext is None:
raise oefmt(space.w_TypeError,
"object %T does not have __anext__ method", w_self)
return space.get_and_call_function(w_anext, w_self)
@slot_function([PyObject, Py_bufferP, rffi.INT_real], rffi.INT_real, error=-1)
def slot_bf_getbuffer(space, w_self, c_view, flags):
if c_view:
c_view.c_obj = rffi.cast(PyObject, 0)
w_buffer = space.lookup(w_self, "__buffer__")
if not w_buffer:
raise oefmt(space.w_BufferError,
"object %T does have the buffer interface (via the __buffer__ method)",
w_self)
flags = widen(flags)
args = Arguments(space, [w_self, space.newint(flags)])
w_obj = space.call_args(w_buffer, args)
# Like slot_from_buffer_w, fill c_view from w_obj
buf = space.buffer_w(w_obj, flags)
try:
c_view.c_buf = rffi.cast(rffi.VOIDP, buf.get_raw_address())
c_view.c_obj = make_ref(space, w_obj)
if space.isinstance_w(w_obj, space.w_bytes):
rffi.setintfield(c_view, 'c_readonly', 1)
except ValueError:
s = buf.as_str()
w_s = space.newbytes(s)
c_view.c_obj = make_ref(space, w_s)
c_view.c_buf = rffi.cast(rffi.VOIDP, rffi.str2charp(
s, track_allocation=False))
rffi.setintfield(c_view, 'c_readonly', 1)
ret = fill_Py_buffer(space, buf, c_view)
return ret
return 0
@slot_function([PyObject, Py_bufferP], lltype.Void, error=CANNOT_FAIL)
def slot_bf_releasebuffer(space, w_self, c_view):
return
|