Пример #1
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
Пример #2
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
Пример #3
0
def PyBuffer_FillInfo(space, view, obj, buf, length, readonly, flags):
    """
    Fills in a buffer-info structure correctly for an exporter that can only
    share a contiguous chunk of memory of "unsigned bytes" of the given
    length. Returns 0 on success and -1 (with raising an error) on error.
    """
    flags = widen(flags)
    if flags & PyBUF_WRITABLE and readonly:
        raise oefmt(space.w_ValueError, "Object is not writable")
    view.c_buf = buf
    view.c_len = length
    view.c_obj = obj
    if obj:
        incref(space, obj)
    view.c_itemsize = 1
    rffi.setintfield(view, 'c_readonly', readonly)
    rffi.setintfield(view, 'c_ndim', 1)
    view.c_format = lltype.nullptr(rffi.CCHARP.TO)
    if (flags & PyBUF_FORMAT) == PyBUF_FORMAT:
        # NB: this needs to be a static string, because nothing frees it
        view.c_format = DEFAULT_FMT
    view.c_shape = lltype.nullptr(Py_ssize_tP.TO)
    if (flags & PyBUF_ND) == PyBUF_ND:
        view.c_shape = rffi.cast(Py_ssize_tP, view.c__shape)
        view.c_shape[0] = view.c_len
    view.c_strides = lltype.nullptr(Py_ssize_tP.TO)
    if (flags & PyBUF_STRIDES) == PyBUF_STRIDES:
        view.c_strides = rffi.cast(Py_ssize_tP, view.c__strides)
        view.c_strides[0] = view.c_itemsize
    view.c_suboffsets = lltype.nullptr(Py_ssize_tP.TO)
    view.c_internal = lltype.nullptr(rffi.VOIDP.TO)

    return 0
Пример #4
0
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)
Пример #5
0
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
Пример #6
0
 def test_tupleobject_base(self, space):
     assert not PyTuple_Check(space, space.w_None)
     with raises_w(space, SystemError):
         n = make_ref(space, space.w_None)
         incref(space, n)
         PyTuple_SetItem(space, n, 0, n)
     atuple = space.newtuple(
         [space.wrap(0), space.wrap(1),
          space.wrap('yay')])
     assert PyTuple_Size(space, atuple) == 3
     with raises_w(space, SystemError):
         PyTuple_Size(space, space.newlist([]))
Пример #7
0
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
Пример #8
0
def PyObject_SelfIter(space, ref):
    """Undocumented function, this is what CPython does."""
    incref(space, ref)
    return ref
Пример #9
0
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)