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 PyList_Sort(space, w_list): """Sort the items of list in place. Return 0 on success, -1 on failure. This is equivalent to list.sort().""" if not isinstance(w_list, W_ListObject): PyErr_BadInternalCall(space) space.call_method(w_list, "sort") return 0
def PyModule_GetDict(space, w_mod): if PyModule_Check(space, w_mod): assert isinstance(w_mod, Module) w_dict = w_mod.getdict(space) return w_dict # borrowed reference, likely from w_mod.w_dict else: PyErr_BadInternalCall(space)
def PyList_Reverse(space, w_list): """Reverse the items of list in place. Return 0 on success, -1 on failure. This is the equivalent of list.reverse().""" if not isinstance(w_list, W_ListObject): PyErr_BadInternalCall(space) space.call_method(w_list, "reverse") return 0
def _PyTuple_Resize(space, p_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.""" ref = p_ref[0] if not tuple_check_ref(space, ref): PyErr_BadInternalCall(space) oldref = rffi.cast(PyTupleObject, ref) oldsize = oldref.c_ob_size p_ref[0] = new_empty_tuple(space, newsize) newref = rffi.cast(PyTupleObject, p_ref[0]) try: if oldsize < newsize: to_cp = oldsize else: to_cp = newsize for i in range(to_cp): ob = oldref.c_ob_item[i] incref(space, ob) newref.c_ob_item[i] = ob except: decref(space, p_ref[0]) p_ref[0] = lltype.nullptr(PyObject.TO) raise finally: decref(space, ref) return 0
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 PyDict_SetItemString(space, w_dict, key_ptr, w_obj): if PyDict_Check(space, w_dict): key = rffi.charp2str(key_ptr) space.setitem_str(w_dict, key, w_obj) return 0 else: PyErr_BadInternalCall(space)
def PyTuple_SetItem(space, w_t, pos, w_obj): if not PyTuple_Check(space, w_t): # XXX this should also steal a reference, test it!!! PyErr_BadInternalCall(space) _setitem_tuple(w_t, pos, w_obj) Py_DecRef(space, w_obj) # SetItem steals a reference! return 0
def _PyTuple_Resize(space, p_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.""" ref = p_ref[0] if not tuple_check_ref(space, ref): PyErr_BadInternalCall(space) ref = rffi.cast(PyTupleObject, ref) oldsize = ref.c_ob_size oldp = ref.c_ob_item newp = lltype.malloc(ObjectItems, newsize, zero=True, flavor='raw', add_memory_pressure=True) try: if oldsize < newsize: to_cp = oldsize else: to_cp = newsize for i in range(to_cp): newp[i] = oldp[i] except: lltype.free(newp, flavor='raw') raise ref.c_ob_item = newp ref.c_ob_size = newsize lltype.free(oldp, flavor='raw') # in this version, p_ref[0] never needs to be updated return 0
def PyModule_GetDict(space, w_mod): if PyModule_Check(space, w_mod): assert isinstance(w_mod, Module) w_dict = w_mod.getdict(space) return borrow_from(w_mod, w_dict) else: PyErr_BadInternalCall(space)
def PySlice_Unpack(space, w_slice, start_p, stop_p, step_p): if not isinstance(w_slice, W_SliceObject): raise PyErr_BadInternalCall(space) if space.is_none(w_slice.w_step): step = 1 else: step = W_SliceObject.eval_slice_index(space, w_slice.w_step) if step == 0: raise oefmt(space.w_ValueError, "slice step cannot be zero") if step < -sys.maxint: step = -sys.maxint step_p[0] = step if space.is_none(w_slice.w_start): start = sys.maxint if step < 0 else 0 else: start = W_SliceObject.eval_slice_index(space, w_slice.w_start) start_p[0] = start if space.is_none(w_slice.w_stop): stop = -sys.maxint - 1 if step < 0 else sys.maxint else: stop = W_SliceObject.eval_slice_index(space, w_slice.w_stop) stop_p[0] = stop return 0
def PyTuple_GetItem(space, ref, index): if not tuple_check_ref(space, ref): PyErr_BadInternalCall(space) ref = rffi.cast(PyTupleObject, ref) size = ref.c_ob_size if index < 0 or index >= size: raise oefmt(space.w_IndexError, "tuple index out of range") return ref.c_ob_item[index] # borrowed ref
def PyDict_GetItemWithError(space, w_dict, w_key): """Variant of PyDict_GetItem() that does not suppress exceptions. Return NULL with an exception set if an exception occurred. Return NULL without an exception set if the key wasn't present.""" if not isinstance(w_dict, W_DictMultiObject): PyErr_BadInternalCall(space) return w_dict.getitem(w_key)
def PyDict_DelItemString(space, w_dict, key_ptr): """Remove the entry in dictionary p which has a key specified by the string key. Return 0 on success or -1 on failure.""" w_key = space.newtext(rffi.charp2str(key_ptr)) if not isinstance(w_dict, W_DictMultiObject): raise PyErr_BadInternalCall(space) w_dict.descr_delitem(space, w_key) return 0
def PyDict_DelItemString(space, w_dict, key_ptr): """Remove the entry in dictionary p which has a key specified by the string key. Return 0 on success or -1 on failure.""" if PyDict_Check(space, w_dict): key = rffi.charp2str(key_ptr) # our dicts dont have a standardized interface, so we need # to go through the space space.delitem(w_dict, space.newtext(key)) return 0 else: PyErr_BadInternalCall(space)
def PyList_GetItem(space, w_list, index): """Return the object at position pos in the list pointed to by p. The position must be positive, indexing from the end of the list is not supported. If pos is out of bounds, return NULL and set an IndexError exception.""" if not isinstance(w_list, W_ListObject): PyErr_BadInternalCall(space) if index < 0 or index >= w_list.length(): raise oefmt(space.w_IndexError, "list index out of range") storage = get_list_storage(space, w_list) return storage._elems[index] # borrowed ref
def PyInstance_NewRaw(space, w_class, w_dict): """Create a new instance of a specific class without calling its constructor. class is the class of new object. The dict parameter will be used as the object's __dict__; if NULL, a new dictionary will be created for the instance.""" if not isinstance(w_class, W_ClassObject): return PyErr_BadInternalCall(space) w_result = w_class.instantiate(space) if w_dict is not None: w_result.setdict(space, w_dict) return w_result
def PySet_Discard(space, w_s, w_obj): """Return 1 if found and removed, 0 if not found (no action taken), and -1 if an error is encountered. Does not raise KeyError for missing keys. Raise a TypeError if the key is unhashable. Unlike the Python discard() method, this function does not automatically convert unhashable sets into temporary frozensets. Raise PyExc_SystemError if set is an not an instance of set or its subtype.""" if not PySet_Check(space, w_s): PyErr_BadInternalCall(space) space.call_method(w_s, 'discard', w_obj) return 0
def PyList_GetItem(space, w_list, index): """Return the object at position pos in the list pointed to by p. The position must be positive, indexing from the end of the list is not supported. If pos is out of bounds, return NULL and set an IndexError exception.""" if not isinstance(w_list, W_ListObject): PyErr_BadInternalCall(space) wrappeditems = w_list.getitems() if index < 0 or index >= len(wrappeditems): raise OperationError(space.w_IndexError, space.wrap( "list index out of range")) return borrow_from(w_list, wrappeditems[index])
def PyList_SetItem(space, w_list, index, w_item): """Set the item at index index in list to item. Return 0 on success or -1 on failure. This function "steals" a reference to item and discards a reference to an item already in the list at the affected position. """ Py_DecRef(space, w_item) if not isinstance(w_list, W_ListObject): PyErr_BadInternalCall(space) if index < 0 or index >= w_list.length(): raise oefmt(space.w_IndexError, "list assignment index out of range") w_list.setitem(index, w_item) return 0
def PySlice_GetIndicesEx(space, w_slice, length, start_p, stop_p, step_p, slicelength_p): """Usable replacement for PySlice_GetIndices(). Retrieve the start, stop, and step indices from the slice object slice assuming a sequence of length length, and store the length of the slice in slicelength. Out of bounds indices are clipped in a manner consistent with the handling of normal slices. Returns 0 on success and -1 on error with exception set.""" if not isinstance(w_slice, W_SliceObject): PyErr_BadInternalCall(space) start_p[0], stop_p[0], step_p[0], slicelength_p[0] = \ w_slice.indices4(space, length) return 0
def PyList_GetItem(space, w_list, index): """Return the object at position pos in the list pointed to by p. The position must be positive, indexing from the end of the list is not supported. If pos is out of bounds, return NULL and set an IndexError exception.""" if not isinstance(w_list, W_ListObject): PyErr_BadInternalCall(space) if index < 0 or index >= w_list.length(): raise OperationError(space.w_IndexError, space.wrap("list index out of range")) w_list.ensure_object_strategy() # make sure we can return a borrowed obj # XXX ^^^ how does this interact with CPyListStrategy? w_res = w_list.getitem(index) return w_res # borrowed ref
def PyDict_Contains(space, w_dict, w_key): """Determine if dictionary p contains key. If an item in p is matches key, return 1, otherwise return 0. On error, return -1. This is equivalent to the Python expression key in p. """ if not isinstance(w_dict, W_DictMultiObject): raise PyErr_BadInternalCall(space) try: w_obj = w_dict.getitem(w_key) if (w_obj is None): return 0 return 1 except OperationError: return 0
def PySet_Add(space, w_s, w_obj): """Add key to a set instance. Does not apply to frozenset instances. Return 0 on success or -1 on failure. Raise a TypeError if the key is unhashable. Raise a MemoryError if there is no room to grow. Raise a SystemError if set is an not an instance of set or its subtype. Now works with instances of frozenset or its subtypes. Like PyTuple_SetItem() in that it can be used to fill-in the values of brand new frozensets before they are exposed to other code.""" if not PySet_Check(space, w_s): PyErr_BadInternalCall(space) space.call_method(space.w_set, 'add', w_s, w_obj) return 0
def PyLong_AsUnsignedLongLong(space, w_long): """ Return a C unsigned long representation of the contents of pylong. If pylong is greater than ULONG_MAX, an OverflowError is raised.""" if not w_long: return PyErr_BadInternalCall(space) try: return rffi.cast(rffi.ULONGLONG, space.r_ulonglong_w(w_long)) except OperationError as e: if e.match(space, space.w_ValueError): if not w_long: raise e.w_type = space.w_OverflowError raise
def PyObject_RichCompare(space, w_o1, w_o2, opid_int): """Compare the values of o1 and o2 using the operation specified by opid, which must be one of Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT, or Py_GE, corresponding to <, <=, ==, !=, >, or >= respectively. This is the equivalent of the Python expression o1 op o2, where op is the operator corresponding to opid. Returns the value of the comparison on success, or NULL on failure.""" opid = rffi.cast(lltype.Signed, opid_int) if opid == Py_LT: return space.lt(w_o1, w_o2) if opid == Py_LE: return space.le(w_o1, w_o2) if opid == Py_EQ: return space.eq(w_o1, w_o2) if opid == Py_NE: return space.ne(w_o1, w_o2) if opid == Py_GT: return space.gt(w_o1, w_o2) if opid == Py_GE: return space.ge(w_o1, w_o2) PyErr_BadInternalCall(space)
def PyList_GetItem(space, w_list, index): """Return the object at position pos in the list pointed to by p. The position must be positive, indexing from the end of the list is not supported. If pos is out of bounds, return NULL and set an IndexError exception.""" from pypy.module.cpyext.sequence import CPyListStrategy if not isinstance(w_list, W_ListObject): PyErr_BadInternalCall(space) if index < 0 or index >= w_list.length(): raise oefmt(space.w_IndexError, "list index out of range") cpy_strategy = space.fromcache(CPyListStrategy) if w_list.strategy is not cpy_strategy: w_list.ensure_object_strategy( ) # make sure we can return a borrowed obj w_res = w_list.getitem(index) return w_res # borrowed ref
def PyTuple_SetItem(space, ref, index, py_obj): # XXX this will not complain when changing tuples that have # already been realized as a W_TupleObject, but won't update the # W_TupleObject if not tuple_check_ref(space, ref): decref(space, py_obj) PyErr_BadInternalCall(space) ref = rffi.cast(PyTupleObject, ref) size = ref.c_ob_size if index < 0 or index >= size: decref(space, py_obj) raise oefmt(space.w_IndexError, "tuple assignment index out of range") old_ref = ref.c_ob_item[index] ref.c_ob_item[index] = py_obj # consumes a reference if old_ref: decref(space, old_ref) return 0
def PyList_SetItem(space, w_list, index, py_item): """Set the item at index index in list to item. Return 0 on success or -1 on failure. This function "steals" a reference to item and discards a reference to an item already in the list at the affected position. """ if not isinstance(w_list, W_ListObject): decref(space, py_item) PyErr_BadInternalCall(space) if index < 0 or index >= w_list.length(): decref(space, py_item) raise oefmt(space.w_IndexError, "list assignment index out of range") storage = get_list_storage(space, w_list) py_old = storage._elems[index] storage._elems[index] = py_item decref(w_list.space, py_old) return 0
def PySlice_GetIndices(space, w_slice, length, start_p, stop_p, step_p): """Retrieve the start, stop and step indices from the slice object slice, assuming a sequence of length length. Treats indices greater than length as errors. Returns 0 on success and -1 on error with no exception set (unless one of the indices was not None and failed to be converted to an integer, in which case -1 is returned with an exception set). You probably do not want to use this function. If you want to use slice objects in versions of Python prior to 2.3, you would probably do well to incorporate the source of PySlice_GetIndicesEx(), suitably renamed, in the source of your extension.""" if not isinstance(w_slice, W_SliceObject): PyErr_BadInternalCall(space) start_p[0], stop_p[0], step_p[0] = \ w_slice.indices3(space, length) return 0