def _PySet_NextEntry(space, w_set, ppos, pkey, phash): if w_set is None or not PyAnySet_Check(space, w_set): PyErr_BadInternalCall(space) return -1 if not pkey: PyErr_BadInternalCall(space) return -1 pos = ppos[0] py_obj = as_pyobj(space, w_set) py_set = rffi.cast(PySetObject, py_obj) if pos == 0: # Store the current item list in the PySetObject. # w_keys must use the object strategy in order to keep the keys alive w_keys = space.newlist(space.listview(w_set)) w_keys.switch_to_object_strategy() oldlist = py_set.c__tmplist py_set.c__tmplist = create_ref(space, w_keys) incref(space, py_set.c__tmplist) decref(space, oldlist) else: if not py_set.c__tmplist: # pos should have been 0, cannot fail so return 0 return 0 w_keys = from_ref(space, py_set.c__tmplist) ppos[0] += 1 if pos >= space.len_w(w_keys): decref(space, py_set.c__tmplist) py_set.c__tmplist = lltype.nullptr(PyObject.TO) return 0 w_key = space.listview(w_keys)[pos] pkey[0] = as_pyobj(space, w_key) if phash: phash[0] = space.hash_w(w_key) return 1
def __init__(self, space, ptr, size, w_obj, format='B', shape=None, strides=None, ndim=1, itemsize=1, readonly=True, needs_decref=False, releasebufferproc=rffi.cast(rffi.VOIDP, 0)): self.space = space self.ptr = ptr self.size = size self.w_obj = w_obj # kept alive self.pyobj = as_pyobj(space, w_obj) self.format = format self.ndim = ndim self.itemsize = itemsize # cf. Objects/memoryobject.c:init_shape_strides() if ndim == 0: self.shape = [] self.strides = [] elif ndim == 1: if shape is None: self.shape = [size // itemsize] else: self.shape = shape if strides is None: self.strides = [itemsize] else: self.strides = strides else: assert len(shape) == ndim self.shape = shape # XXX: missing init_strides_from_shape self.strides = strides self.readonly = readonly self.needs_decref = needs_decref self.releasebufferproc = releasebufferproc
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 = as_pyobj(space, space.w_object) 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) return w_obj
def __init__(self, space, ptr, size, w_obj, format='B', shape=None, strides=None, ndim=1, itemsize=1, readonly=True, needs_decref=False, releasebufferproc=rffi.cast(rffi.VOIDP, 0)): self.space = space self.ptr = ptr self.size = size self.w_obj = w_obj # kept alive self.pyobj = as_pyobj(space, w_obj) self.format = format self.ndim = ndim self.itemsize = itemsize if not shape: self.shape = [size] else: self.shape = shape if not strides: self.strides = [1] else: self.strides = strides self.readonly = readonly self.needs_decref = needs_decref self.releasebufferproc = releasebufferproc
def call(self, space, w_self, w_args, w_kw): func_to_call = self.func if self.offset: pto = as_pyobj(space, self.w_objclass) # make ptr the equivalent of this, using the offsets #func_to_call = rffi.cast(rffi.VOIDP, ptr.c_tp_as_number.c_nb_multiply) if pto: cptr = rffi.cast(rffi.CCHARP, pto) for o in self.offset: ptr = rffi.cast(rffi.VOIDPP, rffi.ptradd(cptr, o))[0] cptr = rffi.cast(rffi.CCHARP, ptr) func_to_call = rffi.cast(rffi.VOIDP, cptr) else: # Should never happen, assert to get a traceback assert False, "failed to convert w_type %s to PyObject" % str( self.w_objclass) assert func_to_call if self.wrapper_func is None: assert self.wrapper_func_kwds is not None return self.wrapper_func_kwds(space, w_self, w_args, func_to_call, w_kw) if space.is_true(w_kw): raise oefmt(space.w_TypeError, "wrapper %s doesn't take any keyword arguments", self.method_name) return self.wrapper_func(space, w_self, w_args, func_to_call)
def PySequence_ITEM(space, w_obj, i): """Return the ith element of o or NULL on failure. Macro form of PySequence_GetItem() but without checking that PySequence_Check(o)() is true and without adjustment for negative indices. This function used an int type for i. This might require changes in your code for properly supporting 64-bit systems.""" # XXX we should call Py*_GET_ITEM() instead of Py*_GetItem() # from here, but we cannot because we are also called from # PySequence_GetItem() py_obj = as_pyobj(space, w_obj) if isinstance(w_obj, tupleobject.W_TupleObject): from pypy.module.cpyext.tupleobject import PyTuple_GetItem py_res = PyTuple_GetItem(space, py_obj, i) incref(space, py_res) keepalive_until_here(w_obj) return py_res if isinstance(w_obj, W_ListObject): from pypy.module.cpyext.listobject import PyList_GetItem py_res = PyList_GetItem(space, py_obj, i) incref(space, py_res) keepalive_until_here(w_obj) return py_res as_sequence = py_obj.c_ob_type.c_tp_as_sequence if not as_sequence or not as_sequence.c_sq_item: raise oefmt(space.w_TypeError, "'%T' object does not support indexing", w_obj) ret = generic_cpy_call(space, as_sequence.c_sq_item, w_obj, i) return make_ref(space, ret)
def create_module_from_def_and_spec(space, moddef, w_spec, name): moddef = rffi.cast(PyModuleDef, moddef) if moddef.c_m_size < 0: raise oefmt( space.w_SystemError, "module %s: m_size may not be negative for multi-phase " "initialization", name) createf = lltype.nullptr(rffi.VOIDP.TO) has_execution_slots = False cur_slot = rffi.cast(rffi.CArrayPtr(PyModuleDef_Slot), moddef.c_m_slots) if cur_slot: while True: slot = rffi.cast(lltype.Signed, cur_slot[0].c_slot) if slot == 0: break elif slot == 1: if createf: raise oefmt(space.w_SystemError, "module %s has multiple create slots", name) createf = cur_slot[0].c_value elif slot < 0 or slot > 2: raise oefmt(space.w_SystemError, "module %s uses unknown slot ID %d", name, slot) else: has_execution_slots = True cur_slot = rffi.ptradd(cur_slot, 1) if createf: createf = rffi.cast(createfunctype, createf) w_mod = generic_cpy_call(space, createf, w_spec, moddef) else: w_mod = Module(space, space.newtext(name)) if isinstance(w_mod, Module): mod = rffi.cast(PyModuleObject, as_pyobj(space, w_mod)) #mod.c_md_state = None mod.c_md_def = moddef else: if moddef.c_m_size > 0 or moddef.c_m_traverse or moddef.c_m_clear or \ moddef.c_m_free: raise oefmt( space.w_SystemError, "module %s is not a module object, but requests " "module state", name) if has_execution_slots: raise oefmt( space.w_SystemError, "module %s specifies execution slots, but did not " "create a ModuleType instance", name) dict_w = {} convert_method_defs(space, dict_w, moddef.c_m_methods, None, w_mod, name) for key, w_value in dict_w.items(): space.setattr(w_mod, space.newtext(key), w_value) if moddef.c_m_doc: doc = rffi.charp2str(rffi.cast(rffi.CCHARP, moddef.c_m_doc)) space.setattr(w_mod, space.newtext('__doc__'), space.newtext(doc)) return w_mod
def PyModule_GetName(space, w_mod): """ Return module's __name__ value. If the module does not provide one, or if it is not a string, SystemError is raised and NULL is returned. """ # NOTE: this version of the code works only because w_mod.w_name is # a wrapped string object attached to w_mod; so it makes a # PyStringObject that will live as long as the module itself, # and returns a "char *" inside this PyStringObject. if not isinstance(w_mod, Module): raise oefmt(space.w_SystemError, "PyModule_GetName(): not a module") from pypy.module.cpyext.bytesobject import PyString_AsString return PyString_AsString(space, as_pyobj(space, w_mod.w_name))
def _type_realize(space, py_obj): """ Creates an interpreter type from a PyTypeObject structure. """ # missing: # 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 = as_pyobj(space, space.w_object) py_type.c_tp_base = rffi.cast(PyTypeObjectPtr, base) finish_type_1(space, py_type) if py_type.c_ob_type: w_metatype = from_ref(space, rffi.cast(PyObject, py_type.c_ob_type)) else: # Somehow the tp_base type is created with no ob_type, notably # PyString_Type and PyBaseString_Type # While this is a hack, cpython does it as well. w_metatype = space.w_type w_obj = rawrefcount.to_obj(W_PyCTypeObject, py_obj) if w_obj is None: w_obj = space.allocate_instance(W_PyCTypeObject, w_metatype) track_reference(space, py_obj, w_obj) # __init__ wraps all slotdefs functions from py_type via add_operators w_obj.__init__(space, py_type) w_obj.ready() finish_type_2(space, py_type, w_obj) base = py_type.c_tp_base if base: # XXX refactor - parts of this are done in finish_type_2 -> inherit_slots if not py_type.c_tp_as_number: py_type.c_tp_as_number = base.c_tp_as_number py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_CHECKTYPES py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS if not py_type.c_tp_as_sequence: py_type.c_tp_as_sequence = base.c_tp_as_sequence py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS if not py_type.c_tp_as_mapping: py_type.c_tp_as_mapping = base.c_tp_as_mapping #if not py_type.c_tp_as_buffer: py_type.c_tp_as_buffer = base.c_tp_as_buffer return w_obj
def _type_realize(space, py_obj): """ Creates an interpreter type from a PyTypeObject structure. """ # missing: # 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 = as_pyobj(space, space.w_object) py_type.c_tp_base = rffi.cast(PyTypeObjectPtr, base) finish_type_1(space, py_type) if py_type.c_ob_type: w_metatype = from_ref(space, rffi.cast(PyObject, py_type.c_ob_type)) else: # Somehow the tp_base type is created with no ob_type, notably # PyString_Type and PyBaseString_Type # While this is a hack, cpython does it as well. w_metatype = space.w_type w_obj = space.allocate_instance(W_PyCTypeObject, w_metatype) track_reference(space, py_obj, w_obj) # __init__ wraps all slotdefs functions from py_type via add_operators w_obj.__init__(space, py_type) w_obj.ready() finish_type_2(space, py_type, w_obj) base = py_type.c_tp_base if base: # XXX refactor - parts of this are done in finish_type_2 -> inherit_slots if not py_type.c_tp_as_number: py_type.c_tp_as_number = base.c_tp_as_number py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_CHECKTYPES py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS if not py_type.c_tp_as_sequence: py_type.c_tp_as_sequence = base.c_tp_as_sequence py_type.c_tp_flags |= base.c_tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS if not py_type.c_tp_as_mapping: py_type.c_tp_as_mapping = base.c_tp_as_mapping #if not py_type.c_tp_as_buffer: py_type.c_tp_as_buffer = base.c_tp_as_buffer return w_obj
def dict_attach(space, py_obj, w_obj, w_userdata=None): """ Fills a newly allocated PyDictObject with the given dict object. """ py_dict = rffi.cast(PyDictObject, py_obj) py_dict.c__tmpkeys = lltype.nullptr(PyObject.TO) # Problems: if this dict is a typedict, we may have unbound GetSetProperty # functions in the dict. The corresponding PyGetSetDescrObject must be # bound to a class, but the actual w_type will be unavailable later on. # Solution: use the w_userdata argument when assigning a PyTypeObject's # tp_dict slot to pass a w_type in, and force creation of the pair here if not space.is_w(w_userdata, space.gettypefor(GetSetProperty)): # do not do this for type dict of GetSetProperty, that would recurse w_vals = space.call_method(space.w_dict, "values", w_obj) vals = space.listview(w_vals) for w_v in vals: if isinstance(w_v, GetSetProperty): pyobj = as_pyobj(space, w_v, w_userdata)
def get_func_to_call(self): func_to_call = self.func if self.offset: pto = as_pyobj(self.space, self.w_objclass) # make ptr the equivalent of this, using the offsets #func_to_call = rffi.cast(rffi.VOIDP, ptr.c_tp_as_number.c_nb_multiply) if pto: cptr = rffi.cast(rffi.CCHARP, pto) for o in self.offset: ptr = rffi.cast(rffi.VOIDPP, rffi.ptradd(cptr, o))[0] cptr = rffi.cast(rffi.CCHARP, ptr) func_to_call = rffi.cast(rffi.VOIDP, cptr) else: # Should never happen, assert to get a traceback assert False, "failed to convert w_type %s to PyObject" % str( self.w_objclass) assert func_to_call return func_to_call
def PySequence_Fast_ITEMS(space, w_obj): """Return the underlying array of PyObject pointers. Assumes that o was returned by PySequence_Fast() and o is not NULL. Note, if a list gets resized, the reallocation may relocate the items array. So, only use the underlying array pointer in contexts where the sequence cannot change. """ if isinstance(w_obj, W_ListObject): cpy_strategy = space.fromcache(CPyListStrategy) if w_obj.strategy is cpy_strategy: return w_obj.get_raw_items() # asserts it's a cpyext strategy elif isinstance(w_obj, tupleobject.W_TupleObject): from pypy.module.cpyext.tupleobject import PyTupleObject py_obj = as_pyobj(space, w_obj) py_tuple = rffi.cast(PyTupleObject, py_obj) return rffi.cast(PyObjectP, py_tuple.c_ob_item) raise oefmt( space.w_TypeError, "PySequence_Fast_ITEMS called but object is not the result of " "PySequence_Fast")
def PyModule_Create2(space, module, api_version): """Create a new module object, given the definition in module, assuming the API version module_api_version. If that version does not match the version of the running interpreter, a RuntimeWarning is emitted. Most uses of this function should be using PyModule_Create() instead; only use this if you are sure you need it.""" modname = rffi.charp2str(rffi.cast(rffi.CCHARP, module.c_m_name)) if module.c_m_doc: doc = rffi.charp2str(rffi.cast(rffi.CCHARP, module.c_m_doc)) else: doc = None methods = module.c_m_methods state = space.fromcache(State) f_name, f_path = state.package_context if f_name is not None: modname = f_name w_mod = Module(space, space.newtext(modname)) py_mod = rffi.cast(PyModuleObject, as_pyobj(space, w_mod)) py_mod.c_md_def = module state.package_context = None, None if f_path is not None: dict_w = {'__file__': space.newfilename(f_path)} else: dict_w = {} convert_method_defs(space, dict_w, methods, None, w_mod, modname) for key, w_value in dict_w.items(): space.setattr(w_mod, space.newtext(key), w_value) if doc: space.setattr(w_mod, space.newtext("__doc__"), space.newtext(doc)) if module.c_m_size > 0: py_mod.c_md_state = lltype.malloc(rffi.VOIDP.TO, module.c_m_size, flavor='raw', zero=True) return w_mod
def gi_attach(space, py_obj, w_obj, w_userdata=None): assert isinstance(w_obj, GeneratorIterator) cts.cast('PyGenObject*', py_obj).c_gi_code = as_pyobj(space, w_obj.pycode)
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 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 of the keys as you iterate over the dictionary, but only so long as the set of keys does 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 # XXX XXX PyDict_Next is not efficient. Storing an iterator would probably # work, but we can't work out how to not leak it if iteration does # not complete. Alternatively, we could add some RPython-only # dict-iterator method to move forward by N steps. w_dict.ensure_object_strategy() # make sure both keys and values can # be borrwed try: w_iter = space.call_method(space.w_dict, "iteritems", w_dict) pos = ppos[0] while pos: space.call_method(w_iter, "next") pos -= 1 w_item = space.call_method(w_iter, "next") w_key, w_value = space.fixedview(w_item, 2) if pkey: pkey[0] = as_pyobj(space, w_key) if pvalue: pvalue[0] = as_pyobj(space, w_value) ppos[0] += 1 except OperationError as e: if not e.match(space, space.w_StopIteration): raise return 0 return 1
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 of the keys as you iterate over the dictionary, but only so long as the set of keys does 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 # XXX XXX PyDict_Next is not efficient. Storing an iterator would probably # work, but we can't work out how to not leak it if iteration does # not complete. Alternatively, we could add some RPython-only # dict-iterator method to move forward by N steps. w_dict.ensure_object_strategy() # make sure both keys and values can # be borrwed try: w_iter = space.call_method(space.w_dict, "iteritems", w_dict) pos = ppos[0] while pos: space.call_method(w_iter, "next") pos -= 1 w_item = space.call_method(w_iter, "next") w_key, w_value = space.fixedview(w_item, 2) if pkey: pkey[0] = as_pyobj(space, w_key) if pvalue: pvalue[0] = as_pyobj(space, w_value) ppos[0] += 1 except OperationError, e: if not e.match(space, space.w_StopIteration): raise return 0
def _get_ob_type(space, w_obj): # please ensure that w_obj stays alive ob_type = as_pyobj(space, space.type(w_obj)) return rffi.cast(PyTypeObjectPtr, ob_type)
def _PyUnicode_Ready(space, w_obj): assert isinstance(w_obj, unicodeobject.W_UnicodeObject) py_obj = as_pyobj(space, w_obj) assert get_kind(py_obj) == WCHAR_KIND return _readify(space, py_obj, w_obj._value)