def test_fsconverter(self, space, api): # Input is bytes w_input = space.wrapbytes("test") with lltype.scoped_alloc(PyObjectP.TO, 1) as result: # Decoder ret = api.PyUnicode_FSDecoder(w_input, result) assert ret == Py_CLEANUP_SUPPORTED assert space.isinstance_w(from_ref(space, result[0]), space.w_unicode) assert api.PyUnicode_FSDecoder(None, result) == 1 # Converter ret = api.PyUnicode_FSConverter(w_input, result) assert ret == Py_CLEANUP_SUPPORTED assert space.eq_w(from_ref(space, result[0]), w_input) assert api.PyUnicode_FSDecoder(None, result) == 1 # Input is unicode w_input = space.wrap("test") with lltype.scoped_alloc(PyObjectP.TO, 1) as result: # Decoder ret = api.PyUnicode_FSDecoder(w_input, result) assert ret == Py_CLEANUP_SUPPORTED assert space.eq_w(from_ref(space, result[0]), w_input) assert api.PyUnicode_FSDecoder(None, result) == 1 # Converter ret = api.PyUnicode_FSConverter(w_input, result) assert ret == Py_CLEANUP_SUPPORTED assert space.isinstance_w(from_ref(space, result[0]), space.w_bytes) assert api.PyUnicode_FSDecoder(None, result) == 1
def PyString_Size(space, ref): if from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.w_str: ref = rffi.cast(PyStringObject, ref) return ref.c_size else: w_obj = from_ref(space, ref) return space.len_w(w_obj)
def PyString_AsStringAndSize(space, ref, buffer, length): if not PyString_Check(space, ref): from pypy.module.cpyext.unicodeobject import ( PyUnicode_Check, _PyUnicode_AsDefaultEncodedString) if PyUnicode_Check(space, ref): ref = _PyUnicode_AsDefaultEncodedString(space, ref, lltype.nullptr(rffi.CCHARP.TO)) else: raise oefmt(space.w_TypeError, "expected string or Unicode object, %T found", from_ref(space, ref)) ref_str = rffi.cast(PyStringObject, ref) if not ref_str.c_buffer: # copy string buffer w_str = from_ref(space, ref) s = space.str_w(w_str) ref_str.c_buffer = rffi.str2charp(s) buffer[0] = ref_str.c_buffer if length: length[0] = ref_str.c_size else: i = 0 while ref_str.c_buffer[i] != '\0': i += 1 if i != ref_str.c_size: raise OperationError(space.w_TypeError, space.wrap( "expected string without null bytes")) return 0
def test_tuple_resize(self, space, api): w_42 = space.wrap(42) ar = lltype.malloc(PyObjectP.TO, 1, flavor='raw') py_tuple = api.PyTuple_New(3) # inside py_tuple is an array of "PyObject *" items which each hold # a reference rffi.cast(PyTupleObject, py_tuple).c_ob_item[0] = make_ref(space, w_42) ar[0] = py_tuple api._PyTuple_Resize(ar, 2) w_tuple = from_ref(space, ar[0]) assert space.int_w(space.len(w_tuple)) == 2 assert space.int_w(space.getitem(w_tuple, space.wrap(0))) == 42 api.Py_DecRef(ar[0]) py_tuple = api.PyTuple_New(3) rffi.cast(PyTupleObject, py_tuple).c_ob_item[0] = make_ref(space, w_42) ar[0] = py_tuple api._PyTuple_Resize(ar, 10) w_tuple = from_ref(space, ar[0]) assert space.int_w(space.len(w_tuple)) == 10 assert space.int_w(space.getitem(w_tuple, space.wrap(0))) == 42 api.Py_DecRef(ar[0]) lltype.free(ar, flavor='raw')
def PyUnicode_GetSize(space, ref): if from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.w_unicode: ref = rffi.cast(PyUnicodeObject, ref) return ref.c_length else: w_obj = from_ref(space, ref) return space.len_w(w_obj)
def test_iterkeys(self, space, api): w_dict = space.sys.getdict(space) py_dict = make_ref(space, w_dict) ppos = lltype.malloc(Py_ssize_tP.TO, 1, flavor='raw') pkey = lltype.malloc(PyObjectP.TO, 1, flavor='raw') pvalue = lltype.malloc(PyObjectP.TO, 1, flavor='raw') keys_w = [] values_w = [] try: ppos[0] = 0 while api.PyDict_Next(w_dict, ppos, pkey, None): w_key = from_ref(space, pkey[0]) keys_w.append(w_key) ppos[0] = 0 while api.PyDict_Next(w_dict, ppos, None, pvalue): w_value = from_ref(space, pvalue[0]) values_w.append(w_value) finally: lltype.free(ppos, flavor='raw') lltype.free(pkey, flavor='raw') lltype.free(pvalue, flavor='raw') api.Py_DecRef(py_dict) # release borrowed references assert space.eq_w(space.newlist(keys_w), space.call_method(w_dict, "keys")) assert space.eq_w(space.newlist(values_w), space.call_method(w_dict, "values"))
def test_traceback(self, space, api): w_traceback = space.appexec( [], """(): import sys try: 1/0 except: return sys.exc_info()[2] """, ) py_obj = make_ref(space, w_traceback) py_traceback = rffi.cast(PyTracebackObject, py_obj) assert from_ref(space, rffi.cast(PyObject, py_traceback.c_ob_type)) is space.gettypeobject(PyTraceback.typedef) traceback = space.interp_w(PyTraceback, w_traceback) assert traceback.lasti == py_traceback.c_tb_lasti assert traceback.get_lineno() == py_traceback.c_tb_lineno assert space.eq_w(space.getattr(w_traceback, space.wrap("tb_lasti")), space.wrap(py_traceback.c_tb_lasti)) assert space.is_w( space.getattr(w_traceback, space.wrap("tb_frame")), from_ref(space, rffi.cast(PyObject, py_traceback.c_tb_frame)), ) while not space.is_w(w_traceback, space.w_None): assert space.is_w(w_traceback, from_ref(space, rffi.cast(PyObject, py_traceback))) w_traceback = space.getattr(w_traceback, space.wrap("tb_next")) py_traceback = py_traceback.c_tb_next assert lltype.normalizeptr(py_traceback) is None api.Py_DecRef(py_obj)
def test_function(self, space, api): w_function = space.appexec([], """(): def f(): pass return f """) ref = make_ref(space, w_function) assert (from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.gettypeobject(Function.typedef)) assert "f" == space.unwrap( from_ref(space, rffi.cast(PyFunctionObject, ref).c_func_name)) api.Py_DecRef(ref)
def PyString_AsString(space, ref): if from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.w_str: pass # typecheck returned "ok" without forcing 'ref' at all elif not PyString_Check(space, ref): # otherwise, use the alternate way raise OperationError(space.w_TypeError, space.wrap( "PyString_AsString only support strings")) ref_str = rffi.cast(PyStringObject, ref) if not ref_str.c_buffer: # copy string buffer w_str = from_ref(space, ref) s = space.str_w(w_str) ref_str.c_buffer = rffi.str2charp(s) return ref_str.c_buffer
def PyErr_NormalizeException(space, exc_p, val_p, tb_p): """Under certain circumstances, the values returned by PyErr_Fetch() below can be "unnormalized", meaning that *exc is a class object but *val is not an instance of the same class. This function can be used to instantiate the class in that case. If the values are already normalized, nothing happens. The delayed normalization is implemented to improve performance.""" operr = OperationError(from_ref(space, exc_p[0]), from_ref(space, val_p[0])) operr.normalize_exception(space) Py_DecRef(space, exc_p[0]) Py_DecRef(space, val_p[0]) exc_p[0] = make_ref(space, operr.w_type) val_p[0] = make_ref(space, operr.get_w_value(space))
def test_tuple_resize(self, space, api): py_tuple = api.PyTuple_New(3) ar = lltype.malloc(PyObjectP.TO, 1, flavor='raw') ar[0] = rffi.cast(PyObject, make_ref(space, py_tuple)) api._PyTuple_Resize(ar, 2) py_tuple = from_ref(space, ar[0]) assert space.int_w(space.len(py_tuple)) == 2 api._PyTuple_Resize(ar, 10) py_tuple = from_ref(space, ar[0]) assert space.int_w(space.len(py_tuple)) == 10 api.Py_DecRef(ar[0]) lltype.free(ar, flavor='raw')
def _PyString_AsString(space, ref): if from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.w_str: pass # typecheck returned "ok" without forcing 'ref' at all elif not PyString_Check(space, ref): # otherwise, use the alternate way from pypy.module.cpyext.unicodeobject import ( PyUnicode_Check, _PyUnicode_AsDefaultEncodedString) if PyUnicode_Check(space, ref): ref = _PyUnicode_AsDefaultEncodedString(space, ref, lltype.nullptr(rffi.CCHARP.TO)) else: raise oefmt(space.w_TypeError, "expected string or Unicode object, %T found", from_ref(space, ref)) ref_str = rffi.cast(PyBytesObject, ref) return ref_str.c_ob_sval
def test_getcode(self, space, api): w_function = space.appexec([], """(): def func(x, y, z): return x return func """) w_code = api.PyFunction_GetCode(w_function) assert w_code.co_name == "func" ref = make_ref(space, w_code) assert (from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.gettypeobject(PyCode.typedef)) assert "func" == space.unwrap( from_ref(space, rffi.cast(PyCodeObject, ref).c_co_name)) assert 3 == rffi.cast(PyCodeObject, ref).c_co_argcount api.Py_DecRef(ref)
def PyMember_GetOne(space, obj, w_member): addr = rffi.cast(ADDR, obj) addr += w_member.c_offset member_type = rffi.cast(lltype.Signed, w_member.c_type) for converter in integer_converters: typ, lltyp, _ = converter if typ == member_type: result = rffi.cast(rffi.CArrayPtr(lltyp), addr) if lltyp is rffi.FLOAT: w_result = space.wrap(lltype.cast_primitive(lltype.Float, result[0])) elif typ == T_BOOL: x = rffi.cast(lltype.Signed, result[0]) w_result = space.wrap(x != 0) else: w_result = space.wrap(result[0]) return w_result if member_type == T_STRING: result = rffi.cast(rffi.CCHARPP, addr) if result[0]: w_result = PyString_FromString(space, result[0]) else: w_result = space.w_None elif member_type == T_STRING_INPLACE: result = rffi.cast(rffi.CCHARP, addr) w_result = PyString_FromString(space, result) elif member_type == T_CHAR: result = rffi.cast(rffi.CCHARP, addr) w_result = space.wrap(result[0]) elif member_type == T_OBJECT: obj_ptr = rffi.cast(PyObjectP, addr) if obj_ptr[0]: w_result = from_ref(space, obj_ptr[0]) else: w_result = space.w_None elif member_type == T_OBJECT_EX: obj_ptr = rffi.cast(PyObjectP, addr) if obj_ptr[0]: w_result = from_ref(space, obj_ptr[0]) else: w_name = space.wrap(rffi.charp2str(w_member.c_name)) raise OperationError(space.w_AttributeError, w_name) else: raise OperationError(space.w_SystemError, space.wrap("bad memberdescr type")) return w_result
def _type_realize(space, py_obj): """ Creates an interpreter type from a PyTypeObject structure. """ # missing: # inheriting tp_as_* slots # unsupported: # tp_mro, tp_subclasses py_type = rffi.cast(PyTypeObjectPtr, py_obj) if not py_type.c_tp_base: # borrowed reference, but w_object is unlikely to disappear base = make_ref(space, space.w_object) Py_DecRef(space, base) py_type.c_tp_base = rffi.cast(PyTypeObjectPtr, base) finish_type_1(space, py_type) w_metatype = from_ref(space, rffi.cast(PyObject, py_type.c_ob_type)) w_obj = space.allocate_instance(W_PyCTypeObject, w_metatype) track_reference(space, py_obj, w_obj) w_obj.__init__(space, py_type) w_obj.ready() finish_type_2(space, py_type, w_obj) state = space.fromcache(RefcountState) state.non_heaptypes_w.append(w_obj) return w_obj
def getitems(self, w_list): # called when switching list strategy, so convert storage storage = self.unerase(w_list.lstorage) retval = [None] * storage._length for i in range(storage._length): retval[i] = from_ref(w_list.space, storage._elems[i]) return retval
def frame_realize(space, py_obj): """ Creates the frame in the interpreter. The PyFrameObject structure must not be modified after this call. """ py_frame = rffi.cast(PyFrameObject, py_obj) py_code = rffi.cast(PyObject, py_frame.c_f_code) w_code = from_ref(space, py_code) code = space.interp_w(PyCode, w_code) w_globals = from_ref(space, py_frame.c_f_globals) frame = space.FrameClass(space, code, w_globals, closure=None) frame.f_lineno = py_frame.c_f_lineno w_obj = space.wrap(frame) track_reference(space, py_obj, w_obj) return w_obj
def int_realize(space, obj): intval = rffi.cast(lltype.Signed, rffi.cast(PyIntObject, obj).c_ob_ival) w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type)) w_obj = space.allocate_instance(W_IntObject, w_type) w_obj.__init__(intval) track_reference(space, obj, w_obj) return w_obj
def _PyTuple_Resize(space, ref, newsize): """Can be used to resize a tuple. newsize will be the new length of the tuple. Because tuples are supposed to be immutable, this should only be used if there is only one reference to the object. Do not use this if the tuple may already be known to some other part of the code. The tuple will always grow or shrink at the end. Think of this as destroying the old tuple and creating a new one, only more efficiently. Returns 0 on success. Client code should never assume that the resulting value of *p will be the same as before calling this function. If the object referenced by *p is replaced, the original *p is destroyed. On failure, returns -1 and sets *p to NULL, and raises MemoryError or SystemError.""" py_tuple = from_ref(space, ref[0]) if not PyTuple_Check(space, py_tuple): PyErr_BadInternalCall(space) py_newtuple = PyTuple_New(space, newsize) to_cp = newsize oldsize = space.int_w(space.len(py_tuple)) if oldsize < newsize: to_cp = oldsize for i in range(to_cp): _setitem_tuple(py_newtuple, i, space.getitem(py_tuple, space.wrap(i))) Py_DecRef(space, ref[0]) ref[0] = make_ref(space, py_newtuple) return 0
def finish_type_2(space, pto, w_obj): """ Sets up other attributes, when the interpreter type has been created. """ pto.c_tp_mro = make_ref(space, space.newtuple(w_obj.mro_w)) base = pto.c_tp_base if base: inherit_special(space, pto, base) for w_base in space.fixedview(from_ref(space, pto.c_tp_bases)): inherit_slots(space, pto, w_base) if not pto.c_tp_setattro: from pypy.module.cpyext.object import PyObject_GenericSetAttr pto.c_tp_setattro = llhelper( PyObject_GenericSetAttr.api_func.functype, PyObject_GenericSetAttr.api_func.get_wrapper(space)) if not pto.c_tp_getattro: from pypy.module.cpyext.object import PyObject_GenericGetAttr pto.c_tp_getattro = llhelper( PyObject_GenericGetAttr.api_func.functype, PyObject_GenericGetAttr.api_func.get_wrapper(space)) if w_obj.is_cpytype(): Py_DecRef(space, pto.c_tp_dict) w_dict = w_obj.getdict(space) pto.c_tp_dict = make_ref(space, w_dict)
def __init__(self, space, pto): bases_w = space.fixedview(from_ref(space, pto.c_tp_bases)) dict_w = {} add_operators(space, dict_w, pto) convert_method_defs(space, dict_w, pto.c_tp_methods, self) convert_getset_defs(space, dict_w, pto.c_tp_getset, self) convert_member_defs(space, dict_w, pto.c_tp_members, self) name = rffi.charp2str(pto.c_tp_name) flag_heaptype = pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE if flag_heaptype: minsize = rffi.sizeof(PyHeapTypeObject.TO) else: minsize = rffi.sizeof(PyObject.TO) new_layout = (pto.c_tp_basicsize > minsize or pto.c_tp_itemsize > 0) W_TypeObject.__init__(self, space, name, bases_w or [space.w_object], dict_w, force_new_layout=new_layout, is_heaptype=flag_heaptype) self.flag_cpytype = True # if a sequence or a mapping, then set the flag to force it if pto.c_tp_as_sequence and pto.c_tp_as_sequence.c_sq_item: self.flag_map_or_seq = 'S' elif (pto.c_tp_as_mapping and pto.c_tp_as_mapping.c_mp_subscript and not (pto.c_tp_as_sequence and pto.c_tp_as_sequence.c_sq_slice)): self.flag_map_or_seq = 'M' if pto.c_tp_doc: self.w_doc = space.wrap(rffi.charp2str(pto.c_tp_doc))
def PyString_AsString(space, ref): ref_str = rffi.cast(PyStringObject, ref) if not ref_str.c_buffer: # copy string buffer w_str = from_ref(space, ref) s = space.str_w(w_str) ref_str.c_buffer = rffi.str2charp(s) return ref_str.c_buffer
def methoddescr_realize(space, obj): # XXX NOT TESTED When is this ever called? method = rffi.cast(lltype.Ptr(PyMethodDef), obj) w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type)) w_obj = space.allocate_instance(W_PyCMethodObject, w_type) w_obj.__init__(space, method, w_type) track_reference(space, obj, w_obj) return w_obj
def wrap_result(self, space, lresult): space.getbuiltinmodule("cpyext") from pypy.module.cpyext.pyobject import PyObject, from_ref, make_ref, Py_DecRef result = rffi.cast(PyObject, lresult) w_obj = from_ref(space, result) if result: Py_DecRef(space, result) return w_obj
def frame_realize(space, py_obj): """ Creates the frame in the interpreter. The PyFrameObject structure must not be modified after this call. """ py_frame = rffi.cast(PyFrameObject, py_obj) py_code = rffi.cast(PyObject, py_frame.c_f_code) w_code = from_ref(space, py_code) code = space.interp_w(PyCode, w_code) w_globals = from_ref(space, py_frame.c_f_globals) frame = space.FrameClass(space, code, w_globals, outer_func=None) d = frame.getorcreatedebug() d.f_lineno = rffi.getintfield(py_frame, 'c_f_lineno') w_obj = space.wrap(frame) track_reference(space, py_obj, w_obj) return w_obj
def test_coerce(self, space, api): w_obj1 = space.wrap(123) w_obj2 = space.wrap(456.789) pp1 = lltype.malloc(PyObjectP.TO, 1, flavor='raw') pp1[0] = make_ref(space, w_obj1) pp2 = lltype.malloc(PyObjectP.TO, 1, flavor='raw') pp2[0] = make_ref(space, w_obj2) assert api.PyNumber_Coerce(pp1, pp2) == 0 assert space.str_w(space.repr(from_ref(space, pp1[0]))) == '123.0' assert space.str_w(space.repr(from_ref(space, pp2[0]))) == '456.789' Py_DecRef(space, pp1[0]) Py_DecRef(space, pp2[0]) lltype.free(pp1, flavor='raw') # Yes, decrement twice since we decoupled between w_obj* and pp*[0]. Py_DecRef(space, w_obj1) Py_DecRef(space, w_obj2) lltype.free(pp2, flavor='raw')
def test_setitem(self, space, api): py_tuple = api.PyTuple_New(2) api.PyTuple_SetItem(py_tuple, 0, make_ref(space, space.wrap(42))) api.PyTuple_SetItem(py_tuple, 1, make_ref(space, space.wrap(43))) w_tuple = from_ref(space, py_tuple) assert space.eq_w(w_tuple, space.newtuple([space.wrap(42), space.wrap(43)]))
def PyUnicode_AsUnicode(space, ref): """Return a read-only pointer to the Unicode object's internal Py_UNICODE buffer, NULL if unicode is not a Unicode object.""" # Don't use PyUnicode_Check, it will realize the object :-( w_type = from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) if not space.issubtype_w(w_type, space.w_unicode): raise oefmt(space.w_TypeError, "expected unicode object") return PyUnicode_AS_UNICODE(space, rffi.cast(rffi.VOIDP, ref))
def slot_tp_new(space, type, w_args, w_kwds): from pypy.module.cpyext.tupleobject import PyTuple_Check pyo = rffi.cast(PyObject, type) w_type = from_ref(space, pyo) w_func = space.getattr(w_type, space.wrap("__new__")) assert PyTuple_Check(space, w_args) args_w = [w_type] + space.fixedview(w_args) w_args_new = space.newtuple(args_w) return space.call(w_func, w_args_new, w_kwds)
def int_realize(space, obj): intval = rffi.cast(lltype.Signed, rffi.cast(PyIntObject, obj).c_ob_ival) w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type)) w_obj = space.allocate_instance(W_IntObject, w_type) w_obj.__init__(intval) track_reference(space, obj, w_obj) state = space.fromcache(RefcountState) state.set_lifeline(w_obj, obj) return w_obj
def test_frombuffer(self, space, api): w_buf = space.newbuffer(StringBuffer("hello")) w_memoryview = api.PyMemoryView_FromObject(w_buf) c_memoryview = rffi.cast(PyMemoryViewObject, make_ref(space, w_memoryview)) view = c_memoryview.c_view assert view.c_ndim == 1 f = rffi.charp2str(view.c_format) assert f == 'B' assert view.c_shape[0] == 5 assert view.c_strides[0] == 1 assert view.c_len == 5 o = rffi.charp2str(view.c_buf) assert o == 'hello' ref = api.PyMemoryView_FromBuffer(view) w_mv = from_ref(space, ref) for f in ('format', 'itemsize', 'ndim', 'readonly', 'shape', 'strides', 'suboffsets'): w_f = space.wrap(f) assert space.eq_w(space.getattr(w_mv, w_f), space.getattr(w_memoryview, w_f)) decref(space, ref) decref(space, c_memoryview)
def PyString_AsStringAndSize(space, ref, buffer, length): if not PyString_Check(space, ref): raise OperationError( space.w_TypeError, space.wrap("PyString_AsStringAndSize only support strings")) ref_str = rffi.cast(PyStringObject, ref) if not ref_str.c_buffer: # copy string buffer w_str = from_ref(space, ref) s = space.str_w(w_str) ref_str.c_buffer = rffi.str2charp(s) buffer[0] = ref_str.c_buffer if length: length[0] = ref_str.c_size else: i = 0 while ref_str.c_buffer[i] != '\0': i += 1 if i != ref_str.c_size: raise OperationError( space.w_TypeError, space.wrap("expected string without null bytes")) return 0
def test_sequence_api(self, space, api): w_tup = space.wrap((1, 2, 3, 4)) assert api.PySequence_Fast(w_tup, "message") is w_tup w_l = space.wrap([1, 2, 3, 4]) assert api.PySequence_Fast(w_l, "message") is w_l py_result = api.PySequence_Fast_GET_ITEM(w_l, 1) w_result = from_ref(space, py_result) assert space.int_w(w_result) == 2 assert api.PySequence_Fast_GET_SIZE(w_l) == 4 w_set = space.wrap(set((1, 2, 3, 4))) w_seq = api.PySequence_Fast(w_set, "message") assert space.type(w_seq) is space.w_tuple assert space.len_w(w_seq) == 4 w_seq = api.PySequence_Tuple(w_set) assert space.type(w_seq) is space.w_tuple assert sorted(space.unwrap(w_seq)) == [1, 2, 3, 4] w_seq = api.PySequence_List(w_set) assert space.type(w_seq) is space.w_list assert sorted(space.unwrap(w_seq)) == [1, 2, 3, 4]
def PyDict_Next(space, w_dict, ppos, pkey, pvalue): """Iterate over all key-value pairs in the dictionary p. The Py_ssize_t referred to by ppos must be initialized to 0 prior to the first call to this function to start the iteration; the function returns true for each pair in the dictionary, and false once all pairs have been reported. The parameters pkey and pvalue should either point to PyObject* variables that will be filled in with each key and value, respectively, or may be NULL. Any references returned through them are borrowed. ppos should not be altered during iteration. Its value represents offsets within the internal dictionary structure, and since the structure is sparse, the offsets are not consecutive. For example: PyObject *key, *value; Py_ssize_t pos = 0; while (PyDict_Next(self->dict, &pos, &key, &value)) { /* do something interesting with the values... */ ... } The dictionary p should not be mutated during iteration. It is safe (since Python 2.1) to modify the values but not the keys as you iterate over the dictionary, the keys must not change. For example: PyObject *key, *value; Py_ssize_t pos = 0; while (PyDict_Next(self->dict, &pos, &key, &value)) { int i = PyInt_AS_LONG(value) + 1; PyObject *o = PyInt_FromLong(i); if (o == NULL) return -1; if (PyDict_SetItem(self->dict, key, o) < 0) { Py_DECREF(o); return -1; } Py_DECREF(o); }""" if w_dict is None: return 0 if not space.isinstance_w(w_dict, space.w_dict): return 0 pos = ppos[0] py_obj = as_pyobj(space, w_dict) py_dict = rffi.cast(PyDictObject, py_obj) if pos == 0: # Store the current keys in the PyDictObject. from pypy.objspace.std.listobject import W_ListObject decref(space, py_dict.c__tmpkeys) w_keys = space.call_method(space.w_dict, "keys", w_dict) # w_keys must use the object strategy in order to keep the keys alive if not isinstance(w_keys, W_ListObject): return 0 # XXX should not call keys() above w_keys.switch_to_object_strategy() py_dict.c__tmpkeys = create_ref(space, w_keys) incref(space, py_dict.c__tmpkeys) else: if not py_dict.c__tmpkeys: # pos should have been 0, cannot fail so return 0 return 0 w_keys = from_ref(space, py_dict.c__tmpkeys) ppos[0] += 1 if pos >= space.len_w(w_keys): decref(space, py_dict.c__tmpkeys) py_dict.c__tmpkeys = lltype.nullptr(PyObject.TO) return 0 w_key = space.listview(w_keys)[pos] # fast iff w_keys uses object strat w_value = space.getitem(w_dict, w_key) if pkey: pkey[0] = as_pyobj(space, w_key) if pvalue: pvalue[0] = as_pyobj(space, w_value) return 1
def generic_cpy_call(space, func, *args): boxed_args = () to_decref = [] assert len(args) == len(FT.ARGS) for i, ARG in unrolling_arg_types: arg = args[i] if is_PyObject(ARG): if arg is None: boxed_args += (lltype.nullptr(PyObject.TO),) elif isinstance(arg, W_Root): ref = make_ref(space, arg) boxed_args += (ref,) if decref_args: to_decref.append(ref) else: boxed_args += (arg,) else: boxed_args += (arg,) try: # create a new container for borrowed references state = space.fromcache(RefcountState) old_container = state.swap_borrow_container(None) try: # Call the function result = call_external_function(func, *boxed_args) finally: state.swap_borrow_container(old_container) if is_PyObject(RESULT_TYPE): if result is None: ret = result elif isinstance(result, W_Root): ret = result else: ret = from_ref(space, result) # The object reference returned from a C function # that is called from Python must be an owned reference # - ownership is transferred from the function to its caller. if result: Py_DecRef(space, result) # Check for exception consistency has_error = PyErr_Occurred(space) is not None has_result = ret is not None if has_error and has_result: raise OperationError(space.w_SystemError, space.wrap( "An exception was set, but function returned a value")) elif not expect_null and not has_error and not has_result: raise OperationError(space.w_SystemError, space.wrap( "Function returned a NULL result without setting an exception")) if has_error: state = space.fromcache(State) state.check_and_raise_exception() return ret return result finally: if decref_args: for ref in to_decref: Py_DecRef(space, ref)
def getitem(self, w_list, index): storage = self.unerase(w_list.lstorage) index = self._check_index(index, storage._length) return from_ref(w_list.space, storage._elems[index])
def HPy_FromPyObject(space, ctx, obj): w_obj = pyobject.from_ref(space, rffi.cast(pyobject.PyObject, obj)) return handles.new(space, w_obj)
def _get_w_obj(space, c_obj): return from_ref(space, cts.cast('PyObject*', c_obj._as_ptr()))
def PyType_IsSubtype(space, a, b): """Return true if a is a subtype of b. """ w_type1 = from_ref(space, rffi.cast(PyObject, a)) w_type2 = from_ref(space, rffi.cast(PyObject, b)) return int(abstract_issubclass_w(space, w_type1, w_type2)) #XXX correct?
def PyType_FromSpecWithBases(space, spec, bases): from pypy.module.cpyext.unicodeobject import PyUnicode_FromString state = space.fromcache(State) p_type = cts.cast('PyTypeObject*', make_ref(space, space.w_type)) res = state.ccall("PyType_GenericAlloc", p_type, 0) res = cts.cast('PyHeapTypeObject *', res) typ = res.c_ht_type typ.c_tp_flags = rffi.cast(lltype.Unsigned, spec.c_flags) typ.c_tp_flags |= Py_TPFLAGS_HEAPTYPE specname = rffi.charp2str(cts.cast('char*', spec.c_name)) dotpos = specname.rfind('.') if dotpos < 0: name = specname else: name = specname[dotpos + 1:] res.c_ht_name = make_ref(space, space.newtext(name)) res.c_ht_qualname = res.c_ht_name incref(space, res.c_ht_qualname) typ.c_tp_name = spec.c_name slotdefs = rffi.cast(rffi.CArrayPtr(cts.gettype('PyType_Slot')), spec.c_slots) if not bases: w_base = space.w_object bases_w = [] i = 0 while True: slotdef = slotdefs[i] slotnum = rffi.cast(lltype.Signed, slotdef.c_slot) if slotnum == 0: break elif slotnum == cts.macros['Py_tp_base']: w_base = from_ref(space, cts.cast('PyObject*', slotdef.c_pfunc)) elif slotnum == cts.macros['Py_tp_bases']: bases = cts.cast('PyObject*', slotdef.c_pfunc) bases_w = space.fixedview(from_ref(space, bases)) i += 1 if not bases_w: bases_w = [w_base] else: bases_w = space.fixedview(from_ref(space, bases)) w_base = best_base(space, bases_w) base = cts.cast('PyTypeObject*', make_ref(space, w_base)) if False: # not base.c_tp_flags & Py_TPFLAGS_BASETYPE: raise oefmt(space.w_TypeError, "type '%s' is not an acceptable base type", rffi.charp2str(base.c_tp_name)) typ.c_tp_as_async = res.c_as_async typ.c_tp_as_number = res.c_as_number typ.c_tp_as_sequence = res.c_as_sequence typ.c_tp_as_mapping = res.c_as_mapping typ.c_tp_as_buffer = res.c_as_buffer typ.c_tp_bases = bases typ.c_tp_base = base typ.c_tp_basicsize = cts.cast('Py_ssize_t', spec.c_basicsize) typ.c_tp_itemsize = cts.cast('Py_ssize_t', spec.c_itemsize) i = 0 while True: slotdef = slotdefs[i] slot = rffi.cast(lltype.Signed, slotdef.c_slot) if slot == 0: break if slot < 0: # or slot > len(slotoffsets): raise oefmt(space.w_RuntimeError, "invalid slot offset") if slot in (cts.macros['Py_tp_base'], cts.macros['Py_tp_bases']): # Processed above i += 1 continue fill_ht_slot(res, slot, slotdef.c_pfunc) # XXX: need to make a copy of the docstring slot, which usually # points to a static string literal i += 1 if not typ.c_tp_dealloc: typ.c_tp_dealloc = state.C._PyPy_subtype_dealloc py_type_ready(space, typ) return cts.cast('PyObject*', res)
def add_tp_new_wrapper(space, dict_w, pto): if "__new__" in dict_w: return pyo = rffi.cast(PyObject, pto) dict_w["__new__"] = PyCFunction_NewEx(space, get_new_method_def(space), from_ref(space, pyo), None)
def PyUnicode_CheckExact(space, ref): if not ref: return False w_obj = from_ref(space, rffi.cast(PyObject, ref)) w_obj_type = space.type(w_obj) return space.is_w(w_obj_type, space.w_unicode)
def getitems_unroll(self, w_list): storage = self.unerase(w_list.lstorage) retval = [None] * storage._length for i in range(storage._length): retval[i] = from_ref(w_list.space, storage._elems[i]) return retval
def tuple_check_ref(space, ref): w_type = from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) return (w_type is space.w_tuple or space.issubtype_w(w_type, space.w_tuple))