def init_typeobject(space): # Probably a hack space.model.typeorder[W_PyCTypeObject] = [(W_PyCTypeObject, None), (W_TypeObject, None), (W_Root, None)] make_typedescr(space.w_type.instancetypedef, basestruct=PyTypeObject, alloc=type_alloc, attach=type_attach, realize=type_realize, dealloc=type_dealloc) # some types are difficult to create because of cycles. # - object.ob_type = type # - type.ob_type = type # - tuple.ob_type = type # - type.tp_base = object # - tuple.tp_base = object # - type.tp_bases is a tuple # - object.tp_bases is a tuple # - tuple.tp_bases is a tuple # insert null placeholders to please create_ref() track_reference(space, lltype.nullptr(PyObject.TO), space.w_type) track_reference(space, lltype.nullptr(PyObject.TO), space.w_object) track_reference(space, lltype.nullptr(PyObject.TO), space.w_tuple) track_reference(space, lltype.nullptr(PyObject.TO), space.w_str) # create the objects py_type = create_ref(space, space.w_type) py_object = create_ref(space, space.w_object) py_tuple = create_ref(space, space.w_tuple) py_str = create_ref(space, space.w_str) # form cycles pto_type = rffi.cast(PyTypeObjectPtr, py_type) py_type.c_ob_type = pto_type py_object.c_ob_type = pto_type py_tuple.c_ob_type = pto_type pto_object = rffi.cast(PyTypeObjectPtr, py_object) pto_type.c_tp_base = pto_object pto_tuple = rffi.cast(PyTypeObjectPtr, py_tuple) pto_tuple.c_tp_base = pto_object pto_type.c_tp_bases.c_ob_type = pto_tuple pto_object.c_tp_bases.c_ob_type = pto_tuple pto_tuple.c_tp_bases.c_ob_type = pto_tuple for typ in (py_type, py_object, py_tuple, py_str): heaptype = rffi.cast(PyHeapTypeObject, typ) heaptype.c_ht_name.c_ob_type = pto_type # Restore the mapping track_reference(space, py_type, space.w_type, replace=True) track_reference(space, py_object, space.w_object, replace=True) track_reference(space, py_tuple, space.w_tuple, replace=True) track_reference(space, py_str, space.w_str, replace=True)
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 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