def frame_attach(space, py_obj, w_obj): "Fills a newly allocated PyFrameObject with a frame object" frame = space.interp_w(PyFrame, w_obj) py_frame = rffi.cast(PyFrameObject, py_obj) py_frame.c_f_code = rffi.cast(PyCodeObject, make_ref(space, frame.pycode)) py_frame.c_f_globals = make_ref(space, frame.w_globals) rffi.setintfield(py_frame, 'c_f_lineno', frame.f_lineno)
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 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 PyErr_GetExcInfo(space, ptype, pvalue, ptraceback): """---Cython extension--- Retrieve the exception info, as known from ``sys.exc_info()``. This refers to an exception that was already caught, not to an exception that was freshly raised. Returns new references for the three objects, any of which may be *NULL*. Does not modify the exception info state. .. note:: This function is not normally used by code that wants to handle exceptions. Rather, it can be used when code needs to save and restore the exception state temporarily. Use :c:func:`PyErr_SetExcInfo` to restore or clear the exception state. """ ec = space.getexecutioncontext() operror = ec.sys_exc_info() if operror: ptype[0] = make_ref(space, operror.w_type) pvalue[0] = make_ref(space, operror.get_w_value(space)) ptraceback[0] = make_ref(space, space.wrap(operror.get_traceback())) else: ptype[0] = lltype.nullptr(PyObject.TO) pvalue[0] = lltype.nullptr(PyObject.TO) ptraceback[0] = lltype.nullptr(PyObject.TO)
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 PyFrame_New(space, tstate, w_code, w_globals, w_locals): typedescr = get_typedescr(PyFrame.typedef) py_obj = typedescr.allocate(space, space.gettypeobject(PyFrame.typedef)) py_frame = rffi.cast(PyFrameObject, py_obj) space.interp_w(PyCode, w_code) # sanity check py_frame.c_f_code = rffi.cast(PyCodeObject, make_ref(space, w_code)) py_frame.c_f_globals = make_ref(space, w_globals) return py_frame
def type_attach(space, py_obj, w_type): """ Fills a newly allocated PyTypeObject from an existing type. """ from pypy.module.cpyext.object import PyObject_Del assert isinstance(w_type, W_TypeObject) pto = rffi.cast(PyTypeObjectPtr, py_obj) typedescr = get_typedescr(w_type.layout.typedef) # dealloc pto.c_tp_dealloc = typedescr.get_dealloc(space) # buffer protocol if space.is_w(w_type, space.w_str): setup_string_buffer_procs(space, pto) if space.is_w(w_type, space.w_buffer): setup_buffer_buffer_procs(space, pto) pto.c_tp_free = llhelper(PyObject_Del.api_func.functype, PyObject_Del.api_func.get_wrapper(space)) pto.c_tp_alloc = llhelper(PyType_GenericAlloc.api_func.functype, PyType_GenericAlloc.api_func.get_wrapper(space)) if pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE: w_typename = space.getattr(w_type, space.wrap('__name__')) heaptype = rffi.cast(PyHeapTypeObject, pto) heaptype.c_ht_name = make_ref(space, w_typename) from pypy.module.cpyext.bytesobject import PyString_AsString pto.c_tp_name = PyString_AsString(space, heaptype.c_ht_name) else: pto.c_tp_name = rffi.str2charp(w_type.name) # uninitialized fields: # c_tp_print, c_tp_getattr, c_tp_setattr # XXX implement # c_tp_compare and the following fields (see http://docs.python.org/c-api/typeobj.html ) w_base = best_base(space, w_type.bases_w) pto.c_tp_base = rffi.cast(PyTypeObjectPtr, make_ref(space, w_base)) builder = space.fromcache(StaticObjectBuilder) if builder.cpyext_type_init is not None: builder.cpyext_type_init.append((pto, w_type)) else: finish_type_1(space, pto) finish_type_2(space, pto, w_type) pto.c_tp_basicsize = rffi.sizeof(typedescr.basestruct) if pto.c_tp_base: if pto.c_tp_base.c_tp_basicsize > pto.c_tp_basicsize: pto.c_tp_basicsize = pto.c_tp_base.c_tp_basicsize # will be filled later on with the correct value # may not be 0 if space.is_w(w_type, space.w_object): pto.c_tp_new = rffi.cast(newfunc, 1) update_all_slots(space, w_type, pto) pto.c_tp_flags |= Py_TPFLAGS_READY return pto
def slice_attach(space, py_obj, w_obj): """ Fills a newly allocated PySliceObject with the given slice object. The fields must not be modified. """ py_slice = rffi.cast(PySliceObject, py_obj) assert isinstance(w_obj, W_SliceObject) py_slice.c_start = make_ref(space, w_obj.w_start) py_slice.c_stop = make_ref(space, w_obj.w_stop) py_slice.c_step = make_ref(space, w_obj.w_step)
def code_attach(space, py_obj, w_obj): py_code = rffi.cast(PyCodeObject, py_obj) assert isinstance(w_obj, PyCode) py_code.c_co_name = make_ref(space, space.wrap(w_obj.co_name)) py_code.c_co_filename = make_ref(space, space.wrap(w_obj.co_filename)) co_flags = 0 for name, value in ALL_CODE_FLAGS: if w_obj.co_flags & getattr(pycode, name): co_flags |= value rffi.setintfield(py_code, 'c_co_flags', co_flags) rffi.setintfield(py_code, 'c_co_argcount', w_obj.co_argcount)
def traceback_attach(space, py_obj, w_obj): py_traceback = rffi.cast(PyTracebackObject, py_obj) traceback = space.interp_w(PyTraceback, w_obj) if traceback.next is None: w_next_traceback = None else: w_next_traceback = space.wrap(traceback.next) py_traceback.c_tb_next = rffi.cast(PyTracebackObject, make_ref(space, w_next_traceback)) py_traceback.c_tb_frame = rffi.cast(PyFrameObject, make_ref(space, space.wrap(traceback.frame))) rffi.setintfield(py_traceback, 'c_tb_lasti', traceback.lasti) rffi.setintfield(py_traceback, 'c_tb_lineno',traceback.get_lineno())
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_ConcatAndDel(self, space, api): ref1 = make_ref(space, space.wrap('abc')) ref2 = make_ref(space, space.wrap('def')) ptr = lltype.malloc(PyObjectP.TO, 1, flavor='raw') ptr[0] = ref1 api.PyString_ConcatAndDel(ptr, ref2) assert space.str_w(from_ref(space, ptr[0])) == 'abcdef' assert ref2.c_ob_refcnt == 0 Py_DecRef(space, ptr[0]) ptr[0] = lltype.nullptr(PyObject.TO) ref2 = make_ref(space, space.wrap('foo')) api.PyString_ConcatAndDel(ptr, ref2) # should not crash assert ref2.c_ob_refcnt == 0 lltype.free(ptr, flavor='raw')
def PyList_SET_ITEM(space, w_list, index, w_item): """Macro form of PyList_SetItem() without error checking. This is normally only used to fill in new lists where there is no previous content. This function "steals" a reference to item, and, unlike PyList_SetItem(), does not discard a reference to any item that it being replaced; any reference in list at position i will be leaked. """ assert isinstance(w_list, W_ListObject) assert 0 <= index < w_list.length() # Deliberately leak, so that it can be safely decref'd. make_ref(space, w_list.getitem(index)) Py_DecRef(space, w_item) w_list.setitem(index, w_item) return w_item
def bytes_getbuffer(space, w_str, view, flags): from pypy.module.cpyext.bytesobject import PyBytes_AsString view.c_obj = make_ref(space, w_str) view.c_buf = rffi.cast(rffi.VOIDP, PyBytes_AsString(space, view.c_obj)) view.c_len = space.len_w(w_str) return 0
def convert_argument_libffi(self, space, w_obj, argchain, call_local): if hasattr(space, "fake"): raise NotImplementedError space.getbuiltinmodule("cpyext") from pypy.module.cpyext.pyobject import make_ref ref = make_ref(space, w_obj) argchain.arg(rffi.cast(rffi.VOIDP, ref))
def PyObject_GetBuffer(space, w_obj, view, flags): """Export obj into a Py_buffer, view. These arguments must never be NULL. The flags argument is a bit field indicating what kind of buffer the caller is prepared to deal with and therefore what kind of buffer the exporter is allowed to return. The buffer interface allows for complicated memory sharing possibilities, but some caller may not be able to handle all the complexity but may want to see if the exporter will let them take a simpler view to its memory. Some exporters may not be able to share memory in every possible way and may need to raise errors to signal to some consumers that something is just not possible. These errors should be a BufferError unless there is another error that is actually causing the problem. The exporter can use flags information to simplify how much of the Py_buffer structure is filled in with non-default values and/or raise an error if the object can't support a simpler view of its memory. 0 is returned on success and -1 on error.""" flags = widen(flags) buf = space.buffer_w(w_obj, flags) try: view.c_buf = rffi.cast(rffi.VOIDP, buf.get_raw_address()) except ValueError: raise BufferError("could not create buffer from object") ret = fill_Py_buffer(space, buf, view) view.c_obj = make_ref(space, w_obj) return ret
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 _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 buffer_attach(space, py_obj, w_obj): """ Fills a newly allocated PyBufferObject with the given (str) buffer object. """ py_buf = rffi.cast(PyBufferObject, py_obj) py_buf.c_b_offset = 0 rffi.setintfield(py_buf, 'c_b_readonly', 1) rffi.setintfield(py_buf, 'c_b_hash', -1) if isinstance(w_obj, SubBuffer): py_buf.c_b_offset = w_obj.offset w_obj = w_obj.buffer # If w_obj already allocated a fixed buffer, use it, and keep a # reference to w_obj. # Otherwise, b_base stays NULL, and we own the b_ptr. if isinstance(w_obj, StringBuffer): py_buf.c_b_base = lltype.nullptr(PyObject.TO) py_buf.c_b_ptr = rffi.cast(rffi.VOIDP, rffi.str2charp(w_obj.value)) py_buf.c_b_size = w_obj.getlength() elif isinstance(w_obj, ArrayBuffer): w_base = w_obj.array py_buf.c_b_base = make_ref(space, w_base) py_buf.c_b_ptr = rffi.cast(rffi.VOIDP, w_obj.array._charbuf_start()) py_buf.c_b_size = w_obj.getlength() else: raise OperationError(space.w_NotImplementedError, space.wrap( "buffer flavor not supported"))
def PyByteArray_FromObject(space, w_obj): """Return a new bytearray object from any object, o, that implements the buffer protocol. XXX expand about the buffer protocol, at least somewhere""" w_buffer = space.call_function(space.w_bytearray, w_obj) return make_ref(space, w_buffer)
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 __init__(self, space, lst): self.space = space self._elems = lltype.malloc(PyObjectList.TO, len(lst), flavor='raw') self._length = len(lst) self._allocated = len(lst) for i, item in enumerate(lst): self._elems[i] = make_ref(space, lst[i])
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 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 PyErr_Fetch(space, ptype, pvalue, ptraceback): """Retrieve the error indicator into three variables whose addresses are passed. If the error indicator is not set, set all three variables to NULL. If it is set, it will be cleared and you own a reference to each object retrieved. The value and traceback object may be NULL even when the type object is not. This function is normally only used by code that needs to handle exceptions or by code that needs to save and restore the error indicator temporarily.""" state = space.fromcache(State) operror = state.clear_exception() if operror: ptype[0] = make_ref(space, operror.w_type) pvalue[0] = make_ref(space, operror.get_w_value(space)) ptraceback[0] = make_ref(space, space.wrap(operror.get_traceback())) else: ptype[0] = lltype.nullptr(PyObject.TO) pvalue[0] = lltype.nullptr(PyObject.TO) ptraceback[0] = lltype.nullptr(PyObject.TO)
def inherit_special(space, pto, base_pto): # XXX missing: copy basicsize and flags in a magical way flags = rffi.cast(lltype.Signed, pto.c_tp_flags) base_object_pyo = make_ref(space, space.w_object) base_object_pto = rffi.cast(PyTypeObjectPtr, base_object_pyo) if base_pto != base_object_pto or flags & Py_TPFLAGS_HEAPTYPE: if not pto.c_tp_new: pto.c_tp_new = base_pto.c_tp_new Py_DecRef(space, base_object_pyo)
def PyByteArray_FromStringAndSize(space, char_p, length): """Create a new bytearray object from string and its length, len. On failure, NULL is returned.""" if char_p: w_s = space.newbytes(rffi.charpsize2str(char_p, length)) else: w_s = space.newint(length) w_buffer = space.call_function(space.w_bytearray, w_s) return make_ref(space, w_buffer)
def member_setter(self, space, w_self, w_value): assert isinstance(self, W_MemberDescr) check_descr(space, w_self, self.w_type) pyref = make_ref(space, w_self) try: PyMember_SetOne( space, rffi.cast(rffi.CCHARP, pyref), self.member, w_value) finally: Py_DecRef(space, pyref)
def get_flags(signature, body="pass"): w_code = space.appexec([], """(): def func(%s): %s return func.__code__ """ % (signature, body)) ref = make_ref(space, w_code) co_flags = rffi.cast(PyCodeObject, ref).c_co_flags api.Py_DecRef(ref) return co_flags
def _PyUnicode_AsDefaultEncodedString(space, ref, errors): # Returns a borrowed reference. py_uni = rffi.cast(PyUnicodeObject, ref) if not py_uni.c_defenc: py_uni.c_defenc = make_ref( space, PyUnicode_AsEncodedString( space, ref, lltype.nullptr(rffi.CCHARP.TO), errors)) return py_uni.c_defenc
def new_thread_state(self, space): """ Create a new ThreadStateCapsule to hold the PyThreadState for a particular execution context. :param space: A space. :returns: A new ThreadStateCapsule holding a newly allocated PyThreadState and referring to this interpreter state. """ capsule = ThreadStateCapsule(space) ts = capsule.memory ts.c_interp = self.interpreter_state ts.c_dict = make_ref(space, space.newdict()) return capsule
def preload_builtins(cls, space): """ Eagerly create pyobjs for various builtins so they don't look like leaks. """ from pypy.module.cpyext.pyobject import make_ref w_to_preload = space.appexec([], """(): import sys import mmap # # copied&pasted to avoid importing the whole types.py, which is # expensive on py3k # <types.py> def _f(): pass FunctionType = type(_f) CodeType = type(_f.__code__) try: raise TypeError except TypeError: tb = sys.exc_info()[2] TracebackType = type(tb) FrameType = type(tb.tb_frame) del tb # </types.py> return [ buffer, mmap.mmap, FunctionType, CodeType, TracebackType, FrameType, type(str.join), ] """) for w_obj in space.unpackiterable(w_to_preload): make_ref(space, w_obj)
def memory_attach(space, py_obj, w_obj, w_userdata=None): """ Fills a newly allocated PyMemoryViewObject with the given W_MemoryView object. """ assert isinstance(w_obj, W_MemoryView) py_obj = rffi.cast(PyMemoryViewObject, py_obj) view = py_obj.c_view ndim = w_obj.getndim() if ndim >= Py_MAX_NDIMS: # XXX warn? return fill_Py_buffer(space, w_obj.view, view) try: view.c_buf = rffi.cast(rffi.VOIDP, w_obj.view.get_raw_address()) # not used in PyPy to keep something alive, # but some c-extensions check the type without checking for NULL view.c_obj = make_ref(space, space.w_None) rffi.setintfield(view, 'c_readonly', w_obj.view.readonly) except ValueError: w_s = w_obj.descr_tobytes(space) view.c_obj = make_ref(space, w_s) view.c_buf = rffi.cast(rffi.VOIDP, rffi.str2charp(space.bytes_w(w_s), track_allocation=False)) rffi.setintfield(view, 'c_readonly', 1)
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 test_class_with___buffer__(self, space, api): w_obj = space.appexec([], """(): from __pypy__.bufferable import bufferable class B(bufferable): def __init__(self): self.buf = bytearray(10) def __buffer__(self, flags): return memoryview(self.buf) return B()""") py_obj = make_ref(space, w_obj) assert py_obj.c_ob_type.c_tp_as_buffer assert py_obj.c_ob_type.c_tp_as_buffer.c_bf_getbuffer assert py_obj.c_ob_type.c_tp_as_buffer.c_bf_getreadbuffer assert py_obj.c_ob_type.c_tp_as_buffer.c_bf_getwritebuffer
def _PyDateTime_Import(space): datetimeAPI = lltype.malloc(PyDateTime_CAPI, flavor='raw', track_allocation=False) w_datetime = PyImport_Import(space, space.wrap("datetime")) w_type = space.getattr(w_datetime, space.wrap("date")) datetimeAPI.c_DateType = rffi.cast(PyTypeObjectPtr, make_ref(space, w_type)) w_type = space.getattr(w_datetime, space.wrap("datetime")) datetimeAPI.c_DateTimeType = rffi.cast(PyTypeObjectPtr, make_ref(space, w_type)) w_type = space.getattr(w_datetime, space.wrap("time")) datetimeAPI.c_TimeType = rffi.cast(PyTypeObjectPtr, make_ref(space, w_type)) w_type = space.getattr(w_datetime, space.wrap("timedelta")) datetimeAPI.c_DeltaType = rffi.cast(PyTypeObjectPtr, make_ref(space, w_type)) return datetimeAPI
def wrap_getreadbuffer(space, w_self, w_args, func): func_target = rffi.cast(readbufferproc, func) py_obj = make_ref(space, w_self) py_type = py_obj.c_ob_type rbp = rffi.cast(rffi.VOIDP, 0) if py_type.c_tp_as_buffer: rbp = rffi.cast(rffi.VOIDP, py_type.c_tp_as_buffer.c_bf_releasebuffer) decref(space, py_obj) with lltype.scoped_alloc(rffi.VOIDPP.TO, 1) as ptr: index = rffi.cast(Py_ssize_t, 0) size = generic_cpy_call(space, func_target, w_self, index, ptr) if size < 0: space.fromcache(State).check_and_raise_exception(always=True) buf = CPyBuffer(space, ptr[0], size, w_self, releasebufferproc=rbp) fq.register_finalizer(buf) return space.newbuffer(buf)
def finish_type_1(space, pto): """ Sets up tp_bases, necessary before creating the interpreter type. """ base = pto.c_tp_base base_pyo = rffi.cast(PyObject, pto.c_tp_base) if base and not base.c_tp_flags & Py_TPFLAGS_READY: type_realize(space, rffi.cast(PyObject, base_pyo)) if base and not pto.c_ob_type: # will be filled later pto.c_ob_type = base.c_ob_type if not pto.c_tp_bases: if not base: bases = space.newtuple([]) else: bases = space.newtuple([from_ref(space, base_pyo)]) pto.c_tp_bases = make_ref(space, bases)
def wrap_getbuffer(space, w_self, w_args, func): func_target = rffi.cast(getbufferproc, func) py_obj = make_ref(space, w_self) py_type = py_obj.c_ob_type rbp = rffi.cast(rffi.VOIDP, 0) if py_type.c_tp_as_buffer: rbp = rffi.cast(rffi.VOIDP, py_type.c_tp_as_buffer.c_bf_releasebuffer) decref(space, py_obj) with lltype.scoped_alloc(Py_buffer) as pybuf: _flags = 0 if space.len_w(w_args) > 0: _flags = space.int_w(space.listview(w_args)[0]) flags = rffi.cast(rffi.INT_real, _flags) size = generic_cpy_call(space, func_target, w_self, pybuf, flags) if widen(size) < 0: space.fromcache(State).check_and_raise_exception(always=True) ptr = pybuf.c_buf size = pybuf.c_len ndim = widen(pybuf.c_ndim) shape = None if pybuf.c_shape: shape = [pybuf.c_shape[i] for i in range(ndim)] strides = None if pybuf.c_strides: strides = [pybuf.c_strides[i] for i in range(ndim)] if pybuf.c_format: format = rffi.charp2str(pybuf.c_format) else: format = 'B' # the CPython docs mandates that you do an incref whenever you call # bf_getbuffer; so, we pass needs_decref=True to ensure that we don't # leak we release the buffer: # https://docs.python.org/3.5/c-api/typeobj.html#c.PyBufferProcs.bf_getbuffer buf = CPyBuffer(space, ptr, size, w_self, format=format, ndim=ndim, shape=shape, strides=strides, itemsize=pybuf.c_itemsize, readonly=widen(pybuf.c_readonly), needs_decref=True, releasebufferproc=rbp) fq.register_finalizer(buf) return space.newbuffer(buf)
def PyMember_SetOne(space, obj, w_member, w_value): addr = rffi.cast(ADDR, obj) addr += w_member.c_offset member_type = rffi.cast(lltype.Signed, w_member.c_type) flags = rffi.cast(lltype.Signed, w_member.c_flags) if flags & READONLY: raise oefmt(space.w_AttributeError, "readonly attribute") elif member_type in [T_STRING, T_STRING_INPLACE]: raise oefmt(space.w_TypeError, "readonly attribute") elif w_value is None: if member_type == T_OBJECT_EX: if not rffi.cast(PyObjectP, addr)[0]: w_name = space.newtext(rffi.charp2str(w_member.c_name)) raise OperationError(space.w_AttributeError, w_name) elif member_type != T_OBJECT: raise oefmt(space.w_TypeError, "can't delete numeric/char attribute") for converter in integer_converters: typ, lltyp, getter, range_checking = converter if typ == member_type: value = getter(space, w_value) array = rffi.cast(rffi.CArrayPtr(lltyp), addr) casted = rffi.cast(lltyp, value) if range_checking: if rffi.cast(lltype.typeOf(value), casted) != value: space.warn( space.newtext("structmember: truncation of value"), space.w_RuntimeWarning) array[0] = casted return 0 if member_type == T_CHAR: str_value = space.text_w(w_value) if len(str_value) != 1: raise oefmt(space.w_TypeError, "string of length 1 expected") array = rffi.cast(rffi.CCHARP, addr) array[0] = str_value[0] elif member_type in [T_OBJECT, T_OBJECT_EX]: array = rffi.cast(PyObjectP, addr) if array[0]: decref(space, array[0]) array[0] = make_ref(space, w_value) else: raise oefmt(space.w_SystemError, "bad memberdescr type") return 0
def PyBytes_Concat(space, ref, w_newpart): """Create a new string object in *string containing the contents of newpart appended to string; the caller will own the new reference. The reference to the old value of string will be stolen. If the new string cannot be created, the old reference to string will still be discarded and the value of *string will be set to NULL; the appropriate exception will be set.""" old = ref[0] if not old: return ref[0] = lltype.nullptr(PyObject.TO) w_str = get_w_obj_and_decref(space, old) if w_newpart is not None and PyBytes_Check(space, old): # XXX: should use buffer protocol w_newstr = space.add(w_str, w_newpart) ref[0] = make_ref(space, w_newstr)
def setup_library(space): "NOT_RPYTHON" from pypy.module.cpyext.pyobject import make_ref export_symbols = list(FUNCTIONS) + SYMBOLS_C + list(GLOBALS) from rpython.translator.c.database import LowLevelDatabase db = LowLevelDatabase() generate_macros(export_symbols, prefix='PyPy') functions = generate_decls_and_callbacks(db, [], api_struct=False) code = "#include <Python.h>\n" + "\n".join(functions) eci = build_eci(False, export_symbols, code) space.fromcache(State).install_dll(eci) run_bootstrap_functions(space) setup_va_functions(eci) # populate static data for name, (typ, expr) in GLOBALS.iteritems(): name = name.replace("#", "") if name.startswith('PyExc_'): name = '_' + name from pypy.module import cpyext w_obj = eval(expr) if typ in ('PyObject*', 'PyTypeObject*'): struct_ptr = make_ref(space, w_obj) elif typ == 'PyDateTime_CAPI*': continue else: assert False, "Unknown static data: %s %s" % (typ, name) struct = rffi.cast(get_structtype_for_ctype(typ), struct_ptr)._obj struct._compilation_info = eci export_struct(name, struct) for name, func in FUNCTIONS.iteritems(): newname = mangle_name('PyPy', name) or name deco = entrypoint_lowlevel("cpyext", func.argtypes, newname, relax=True) deco(func.get_wrapper(space)) setup_init_functions(eci, translating=True) trunk_include = pypydir.dirpath() / 'include' copy_header_files(trunk_include)
def unwrapper(space, *args): from pypy.module.cpyext.pyobject import Py_DecRef from pypy.module.cpyext.pyobject import make_ref, from_ref from pypy.module.cpyext.pyobject import Reference newargs = () to_decref = [] assert len(args) == len(api_function.argtypes) for i, (ARG, is_wrapped) in types_names_enum_ui: input_arg = args[i] if is_PyObject(ARG) and not is_wrapped: # build a reference if input_arg is None: arg = lltype.nullptr(PyObject.TO) elif isinstance(input_arg, W_Root): ref = make_ref(space, input_arg) to_decref.append(ref) arg = rffi.cast(ARG, ref) else: arg = input_arg elif is_PyObject(ARG) and is_wrapped: # convert to a wrapped object if input_arg is None: arg = input_arg elif isinstance(input_arg, W_Root): arg = input_arg else: try: arg = from_ref(space, rffi.cast(PyObject, input_arg)) except TypeError, e: err = OperationError(space.w_TypeError, space.wrap( "could not cast arg to PyObject")) if not catch_exception: raise err state = space.fromcache(State) state.set_exception(err) if is_PyObject(restype): return None else: return api_function.error_value else: # convert to a wrapped object arg = input_arg newargs += (arg, )
def inherit_slots(space, pto, w_base): # XXX missing: nearly everything base_pyo = make_ref(space, w_base) try: base = rffi.cast(PyTypeObjectPtr, base_pyo) if not pto.c_tp_dealloc: pto.c_tp_dealloc = base.c_tp_dealloc if not pto.c_tp_init: pto.c_tp_init = base.c_tp_init if not pto.c_tp_alloc: pto.c_tp_alloc = base.c_tp_alloc # XXX check for correct GC flags! if not pto.c_tp_free: pto.c_tp_free = base.c_tp_free if not pto.c_tp_setattro: pto.c_tp_setattro = base.c_tp_setattro finally: Py_DecRef(space, base_pyo)
def finish_type_1(space, pto, bases_w=None): """ Sets up tp_bases, necessary before creating the interpreter type. """ base = pto.c_tp_base base_pyo = rffi.cast(PyObject, pto.c_tp_base) if base and not base.c_tp_flags & Py_TPFLAGS_READY: name = rffi.charp2str(cts.cast('char*', base.c_tp_name)) type_realize(space, base_pyo) if base and not pto.c_ob_type: # will be filled later pto.c_ob_type = base.c_ob_type if not pto.c_tp_bases: if bases_w is None: if not base: bases_w = [] else: bases_w = [from_ref(space, base_pyo)] pto.c_tp_bases = make_ref(space, space.newtuple(bases_w))
def tp_new_wrapper(space, self, w_args, w_kwds): self_pytype = rffi.cast(PyTypeObjectPtr, self) tp_new = self_pytype.c_tp_new # Check that the user doesn't do something silly and unsafe like # object.__new__(dict). To do this, we check that the most # derived base that's not a heap type is this type. # XXX do it args_w = space.fixedview(w_args) w_subtype = args_w[0] w_args = space.newtuple(args_w[1:]) subtype = rffi.cast(PyTypeObjectPtr, make_ref(space, w_subtype)) try: w_obj = generic_cpy_call(space, tp_new, subtype, w_args, w_kwds) finally: decref(space, subtype) return w_obj
def PyString_InternInPlace(space, string): """Intern the argument *string in place. The argument must be the address of a pointer variable pointing to a Python string object. If there is an existing interned string that is the same as *string, it sets *string to it (decrementing the reference count of the old string object and incrementing the reference count of the interned string object), otherwise it leaves *string alone and interns it (incrementing its reference count). (Clarification: even though there is a lot of talk about reference counts, think of this function as reference-count-neutral; you own the object after the call if and only if you owned it before the call.) This function is not available in 3.x and does not have a PyBytes alias.""" w_str = from_ref(space, string[0]) w_str = space.new_interned_w_str(w_str) Py_DecRef(space, string[0]) string[0] = make_ref(space, w_str)
def PyString_Concat(space, ref, w_newpart): """Create a new string object in *string containing the contents of newpart appended to string; the caller will own the new reference. The reference to the old value of string will be stolen. If the new string cannot be created, the old reference to string will still be discarded and the value of *string will be set to NULL; the appropriate exception will be set.""" if not ref[0]: return if w_newpart is None or not PyString_Check(space, ref[0]) or \ not PyString_Check(space, w_newpart): Py_DecRef(space, ref[0]) ref[0] = lltype.nullptr(PyObject.TO) return w_str = from_ref(space, ref[0]) w_newstr = space.add(w_str, w_newpart) Py_DecRef(space, ref[0]) ref[0] = make_ref(space, w_newstr)
def type_alloc(space, w_metatype): metatype = rffi.cast(PyTypeObjectPtr, make_ref(space, w_metatype)) # Don't increase refcount for non-heaptypes if metatype: flags = rffi.cast(lltype.Signed, metatype.c_tp_flags) if not flags & Py_TPFLAGS_HEAPTYPE: Py_DecRef(space, w_metatype) heaptype = lltype.malloc(PyHeapTypeObject.TO, flavor='raw', zero=True) pto = heaptype.c_ht_type pto.c_ob_refcnt = 1 pto.c_ob_type = metatype pto.c_tp_flags |= Py_TPFLAGS_HEAPTYPE pto.c_tp_as_number = heaptype.c_as_number pto.c_tp_as_sequence = heaptype.c_as_sequence pto.c_tp_as_mapping = heaptype.c_as_mapping pto.c_tp_as_buffer = heaptype.c_as_buffer return rffi.cast(PyObject, heaptype)
def PyMember_SetOne(space, obj, w_member, w_value): addr = rffi.cast(ADDR, obj) addr += w_member.c_offset member_type = rffi.cast(lltype.Signed, w_member.c_type) flags = rffi.cast(lltype.Signed, w_member.c_flags) if (flags & READONLY or member_type in [T_STRING, T_STRING_INPLACE]): raise OperationError(space.w_TypeError, space.wrap("readonly attribute")) elif w_value is None: if member_type == T_OBJECT_EX: if not rffi.cast(PyObjectP, addr)[0]: w_name = space.wrap(rffi.charp2str(w_member.c_name)) raise OperationError(space.w_AttributeError, w_name) elif member_type != T_OBJECT: raise OperationError( space.w_TypeError, space.wrap("can't delete numeric/char attribute")) for converter in integer_converters: typ, lltyp, getter = converter if typ == member_type: value = getter(space, w_value) array = rffi.cast(rffi.CArrayPtr(lltyp), addr) array[0] = rffi.cast(lltyp, value) return 0 if member_type == T_CHAR: str_value = space.str_w(w_value) if len(str_value) != 1: raise OperationError(space.w_TypeError, space.wrap("string of length 1 expected")) array = rffi.cast(rffi.CCHARP, addr) array[0] = str_value[0] elif member_type in [T_OBJECT, T_OBJECT_EX]: array = rffi.cast(PyObjectP, addr) if array[0]: Py_DecRef(space, array[0]) array[0] = make_ref(space, w_value) else: raise OperationError(space.w_SystemError, space.wrap("bad memberdescr type")) return 0
def test_typedict1(self, space): py_type = make_ref(space, space.w_int) py_dict = rffi.cast(PyTypeObjectPtr, py_type).c_tp_dict ppos = lltype.malloc(Py_ssize_tP.TO, 1, flavor='raw') ppos[0] = 0 pkey = lltype.malloc(PyObjectP.TO, 1, flavor='raw') pvalue = lltype.malloc(PyObjectP.TO, 1, flavor='raw') try: w_copy = space.newdict() while PyDict_Next(space, py_dict, ppos, pkey, pvalue): w_key = from_ref(space, pkey[0]) w_value = from_ref(space, pvalue[0]) space.setitem(w_copy, w_key, w_value) finally: lltype.free(ppos, flavor='raw') lltype.free(pkey, flavor='raw') lltype.free(pvalue, flavor='raw') decref(space, py_type) # release borrowed references
def finish_type_1(space, pto, bases_w=None): """ Sets up tp_bases, necessary before creating the interpreter type. """ base = pto.c_tp_base base_pyo = rffi.cast(PyObject, base) if base and not base.c_tp_flags & Py_TPFLAGS_READY: type_realize(space, base_pyo) if base and not pto.c_ob_type: # will be filled later pto.c_ob_type = base.c_ob_type if not pto.c_tp_bases: if bases_w is None: if not base: bases_w = [] else: bases_w = [from_ref(space, base_pyo)] is_heaptype = bool(pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE) pto.c_tp_bases = make_ref(space, space.newtuple(bases_w), immortal=not is_heaptype)
def PyMemoryView_GetContiguous(space, w_obj, buffertype, order): """ Return a new memoryview object based on a contiguous exporter with buffertype={PyBUF_READ, PyBUF_WRITE} and order={'C', 'F'ortran, or 'A'ny}. The logical structure of the input and output buffers is the same (i.e. tolist(input) == tolist(output)), but the physical layout in memory can be explicitly chosen. As usual, if buffertype=PyBUF_WRITE, the exporter's buffer must be writable, otherwise it may be writable or read-only. If the exporter is already contiguous with the desired target order, the memoryview will be directly based on the exporter. Otherwise, if the buffertype is PyBUF_READ, the memoryview will be based on a new bytes object. If order={'C', 'A'ny}, use 'C' order, 'F'ortran order otherwise. """ buffertype = widen(buffertype) if buffertype != PyBUF_READ and buffertype != PyBUF_WRITE: raise oefmt(space.w_ValueError, "buffertype must be PyBUF_READ or PyBUF_WRITE") if order != 'C' and order != 'F' and order != 'A': raise oefmt(space.w_ValueError, "order must be in ('C', 'F', 'A')") w_mv = space.call_method(space.builtin, "memoryview", w_obj) mv = make_ref(space, w_mv) mv = rffi.cast(PyMemoryViewObject, mv) view = mv.c_view if buffertype == PyBUF_WRITE and widen(view.c_readonly): raise oefmt(space.w_BufferError, "underlying buffer is not writable") if PyBuffer_IsContiguous(space, view, order): return w_mv if buffertype == PyBUF_WRITE: raise oefmt( space.w_BufferError, "writable contiguous buffer requested " "for a non-contiguous object.") return memory_from_contiguous_copy(space, view, order)
def PyString_Concat(space, ref, w_newpart): """Create a new string object in *string containing the contents of newpart appended to string; the caller will own the new reference. The reference to the old value of string will be stolen. If the new string cannot be created, the old reference to string will still be discarded and the value of *string will be set to NULL; the appropriate exception will be set.""" old = ref[0] if not old: return ref[0] = lltype.nullptr(PyObject.TO) w_str = get_w_obj_and_decref(space, old) if w_newpart is not None and PyString_Check(space, old): # xxx if w_newpart is not a string or unicode or bytearray, # this might call __radd__() on it, whereas CPython raises # a TypeError in this case. w_newstr = space.add(w_str, w_newpart) ref[0] = make_ref(space, w_newstr)
def PyUnicode_FSDecoder(space, w_obj, result): """ParseTuple converter: decode bytes objects to str using PyUnicode_DecodeFSDefaultAndSize(); str objects are output as-is. result must be a PyUnicodeObject* which must be released when it is no longer used. """ if not w_obj: # Implement ParseTuple cleanup support decref(space, result[0]) return 1 if space.isinstance_w(w_obj, space.w_unicode): w_output = w_obj else: w_obj = PyBytes_FromObject(space, w_obj) w_output = space.fsdecode(w_obj) if not space.isinstance_w(w_output, space.w_unicode): raise oefmt(space.w_TypeError, "decoder failed to return unicode") data = space.unicode0_w(w_output) # Check for NUL bytes result[0] = make_ref(space, w_output) return Py_CLEANUP_SUPPORTED
def test_tuple_resize(self, space, api): w_42 = space.wrap(42) w_43 = space.wrap(43) w_44 = space.wrap(44) ar = lltype.malloc(PyObjectP.TO, 1, flavor='raw') state = space.fromcache(State) py_tuple = state.ccall("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) rffi.cast(PyTupleObject, py_tuple).c_ob_item[1] = make_ref(space, w_43) 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 assert space.int_w(space.getitem(w_tuple, space.wrap(1))) == 43 decref(space, ar[0]) py_tuple = state.ccall("PyTuple_New", 3) rffi.cast(PyTupleObject, py_tuple).c_ob_item[0] = make_ref(space, w_42) rffi.cast(PyTupleObject, py_tuple).c_ob_item[1] = make_ref(space, w_43) rffi.cast(PyTupleObject, py_tuple).c_ob_item[2] = make_ref(space, w_44) ar[0] = py_tuple api._PyTuple_Resize(ar, 10) assert api.PyTuple_Size(ar[0]) == 10 for i in range(3, 10): rffi.cast(PyTupleObject, ar[0]).c_ob_item[i] = make_ref(space, space.wrap(42 + i)) w_tuple = from_ref(space, ar[0]) assert space.int_w(space.len(w_tuple)) == 10 for i in range(10): assert space.int_w(space.getitem(w_tuple, space.wrap(i))) == 42 + i decref(space, ar[0]) py_tuple = state.ccall("PyTuple_New", 1) ar[0] = py_tuple api._PyTuple_Resize(ar, 1) assert api.PyTuple_Size(ar[0]) == 1 decref(space, ar[0]) py_tuple = state.ccall("PyTuple_New", 1) ar[0] = py_tuple api._PyTuple_Resize(ar, 5) assert api.PyTuple_Size(ar[0]) == 5 decref(space, ar[0]) lltype.free(ar, flavor='raw')
def PyUnicode_FSConverter(space, w_obj, result): """ParseTuple converter: encode str objects to bytes using PyUnicode_EncodeFSDefault(); bytes objects are output as-is. result must be a PyBytesObject* which must be released when it is no longer used. """ if not w_obj: # Implement ParseTuple cleanup support Py_DecRef(space, result[0]) return 1 if space.isinstance_w(w_obj, space.w_bytes): w_output = w_obj else: w_obj = PyUnicode_FromObject(space, w_obj) w_output = space.fsencode(w_obj) if not space.isinstance_w(w_output, space.w_bytes): raise OperationError(space.w_TypeError, space.wrap("encoder failed to return bytes")) data = space.bytes0_w(w_output) # Check for NUL bytes result[0] = make_ref(space, w_output) return Py_CLEANUP_SUPPORTED
def inherit_slots(space, pto, w_base): base_pyo = make_ref(space, w_base) try: base = rffi.cast(PyTypeObjectPtr, base_pyo) if not pto.c_tp_dealloc: pto.c_tp_dealloc = base.c_tp_dealloc if not pto.c_tp_init: pto.c_tp_init = base.c_tp_init if not pto.c_tp_alloc: pto.c_tp_alloc = base.c_tp_alloc # XXX check for correct GC flags! if not pto.c_tp_free: pto.c_tp_free = base.c_tp_free if not pto.c_tp_setattro: pto.c_tp_setattro = base.c_tp_setattro if not pto.c_tp_getattro: pto.c_tp_getattro = base.c_tp_getattro if not pto.c_tp_as_buffer: pto.c_tp_as_buffer = base.c_tp_as_buffer if base.c_tp_as_buffer: # inherit base.c_tp_as_buffer functions not inherited from w_type # note: builtin types are handled in setup_buffer_procs pto_as = pto.c_tp_as_buffer base_as = base.c_tp_as_buffer if not pto_as.c_bf_getbuffer: pto_as.c_bf_getbuffer = base_as.c_bf_getbuffer if not pto_as.c_bf_getcharbuffer: pto_as.c_bf_getcharbuffer = base_as.c_bf_getcharbuffer if not pto_as.c_bf_getwritebuffer: pto_as.c_bf_getwritebuffer = base_as.c_bf_getwritebuffer if not pto_as.c_bf_getreadbuffer: pto_as.c_bf_getreadbuffer = base_as.c_bf_getreadbuffer if not pto_as.c_bf_getsegcount: pto_as.c_bf_getsegcount = base_as.c_bf_getsegcount if not pto_as.c_bf_releasebuffer: pto_as.c_bf_releasebuffer = base_as.c_bf_releasebuffer finally: decref(space, base_pyo)
def test_tp_new_from_python(self, space, api): w_date = space.appexec([], """(): class Date(object): def __new__(cls, year, month, day): self = object.__new__(cls) self.year = year self.month = month self.day = day return self return Date """) py_datetype = rffi.cast(PyTypeObjectPtr, make_ref(space, w_date)) one = space.newint(1) arg = space.newtuple([one, one, one]) # call w_date.__new__ w_obj = space.call_function(w_date, one, one, one) w_year = space.getattr(w_obj, space.newtext('year')) assert space.int_w(w_year) == 1 w_obj = generic_cpy_call(space, py_datetype.c_tp_new, py_datetype, arg, space.newdict({})) w_year = space.getattr(w_obj, space.newtext('year')) assert space.int_w(w_year) == 1
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)