Beispiel #1
0
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, w_obj, base)
    for w_base in space.fixedview(from_ref(space, pto.c_tp_bases)):
        if isinstance(w_base, W_TypeObject):
            inherit_slots(space, pto, w_base)
        #else:
        #   w_base is a W_ClassObject, ignore it

    if not pto.c_tp_setattro:
        from pypy.module.cpyext.object import PyObject_GenericSetAttr
        pto.c_tp_setattro = llslot(space, PyObject_GenericSetAttr)

    if not pto.c_tp_getattro:
        from pypy.module.cpyext.object import PyObject_GenericGetAttr
        pto.c_tp_getattro = llslot(space, PyObject_GenericGetAttr)

    if w_obj.is_cpytype():
        decref(space, pto.c_tp_dict)
    w_dict = w_obj.getdict(space)
    # pass in the w_obj to convert any values that are
    # unbound GetSetProperty into bound PyGetSetDescrObject
    pto.c_tp_dict = make_ref(space, w_dict, w_obj)
Beispiel #2
0
def setup_buffer_procs(space, w_type, pto):
    bufspec = w_type.layout.typedef.buffer
    if bufspec is None and not space.is_w(w_type, space.w_unicode):
        # not a buffer, but let w_unicode be a read buffer
        return
    c_buf = lltype.malloc(PyBufferProcs, flavor='raw', zero=True)
    lltype.render_immortal(c_buf)
    c_buf.c_bf_getsegcount = llslot(space, bf_segcount)
    if space.is_w(w_type, space.w_bytes):
        # Special case: str doesn't support get_raw_address(), so we have a
        # custom get*buffer that instead gives the address of the char* in the
        # PyBytesObject*!
        c_buf.c_bf_getreadbuffer = llslot(space, str_getreadbuffer)
        c_buf.c_bf_getcharbuffer = llslot(space, str_getcharbuffer)
    elif space.is_w(w_type, space.w_unicode):
        # Special case: unicode doesn't support get_raw_address(), so we have a
        # custom get*buffer that instead gives the address of the char* in the
        # PyUnicodeObject*!
        c_buf.c_bf_getreadbuffer = llslot(space, unicode_getreadbuffer)
    elif space.is_w(w_type, space.w_buffer):
        # Special case: we store a permanent address on the cpyext wrapper,
        # so we'll reuse that.
        # Note: we could instead store a permanent address on the buffer object,
        # and use get_raw_address()
        c_buf.c_bf_getreadbuffer = llslot(space, buf_getreadbuffer)
        c_buf.c_bf_getcharbuffer = llslot(space, buf_getcharbuffer)
    else:
        # use get_raw_address()
        c_buf.c_bf_getreadbuffer = llslot(space, bf_getreadbuffer)
        c_buf.c_bf_getcharbuffer = llslot(space, bf_getcharbuffer)
        if bufspec == 'read-write':
            c_buf.c_bf_getwritebuffer = llslot(space, bf_getwritebuffer)
    pto.c_tp_as_buffer = c_buf
    pto.c_tp_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER
    pto.c_tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER
Beispiel #3
0
def setup_buffer_procs(space, w_type, pto):
    bufspec = w_type.layout.typedef.buffer
    if bufspec is None and not space.is_w(w_type, space.w_unicode):
        # not a buffer, but let w_unicode be a read buffer
        return
    c_buf = lltype.malloc(PyBufferProcs, flavor='raw', zero=True)
    lltype.render_immortal(c_buf)
    c_buf.c_bf_getsegcount = llslot(space, bf_segcount)
    if space.is_w(w_type, space.w_str):
        # Special case: str doesn't support get_raw_address(), so we have a
        # custom get*buffer that instead gives the address of the char* in the
        # PyBytesObject*!
        c_buf.c_bf_getreadbuffer = llslot(space, str_getreadbuffer)
        c_buf.c_bf_getcharbuffer = llslot(space, str_getcharbuffer)
    elif space.is_w(w_type, space.w_unicode):
        # Special case: unicode doesn't support get_raw_address(), so we have a
        # custom get*buffer that instead gives the address of the char* in the
        # PyUnicodeObject*!
        c_buf.c_bf_getreadbuffer = llslot(space, unicode_getreadbuffer)
    elif space.is_w(w_type, space.w_buffer):
        # Special case: we store a permanent address on the cpyext wrapper,
        # so we'll reuse that.
        # Note: we could instead store a permanent address on the buffer object,
        # and use get_raw_address()
        c_buf.c_bf_getreadbuffer = llslot(space, buf_getreadbuffer)
        c_buf.c_bf_getcharbuffer = llslot(space, buf_getcharbuffer)
    else:
        # use get_raw_address()
        c_buf.c_bf_getreadbuffer = llslot(space, bf_getreadbuffer)
        c_buf.c_bf_getcharbuffer = llslot(space, bf_getcharbuffer)
        if bufspec == 'read-write':
            c_buf.c_bf_getwritebuffer = llslot(space, bf_getwritebuffer)
    pto.c_tp_as_buffer = c_buf
    pto.c_tp_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER
    pto.c_tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER
Beispiel #4
0
def subtype_dealloc(space, obj):
    pto = obj.c_ob_type
    base = pto
    this_func_ptr = llslot(space, subtype_dealloc)
    w_obj = from_ref(space, rffi.cast(PyObject, base))
    # This wrapper is created on a specific type, call it w_A.
    # We wish to call the dealloc function from one of the base classes of w_A,
    # the first of which is not this function itself.
    # w_obj is an instance of w_A or one of its subclasses. So climb up the
    # inheritance chain until base.c_tp_dealloc is exactly this_func, and then
    # continue on up until they differ.
    #print 'subtype_dealloc, start from', rffi.charp2str(base.c_tp_name)
    while base.c_tp_dealloc != this_func_ptr:
        base = base.c_tp_base
        assert base
        #print '                 ne move to', rffi.charp2str(base.c_tp_name)
        w_obj = from_ref(space, rffi.cast(PyObject, base))
    while base.c_tp_dealloc == this_func_ptr:
        base = base.c_tp_base
        assert base
        #print '                 eq move to', rffi.charp2str(base.c_tp_name)
        w_obj = from_ref(space, rffi.cast(PyObject, base))
    #print '                   end with', rffi.charp2str(base.c_tp_name)
    dealloc = base.c_tp_dealloc
    # XXX call tp_del if necessary
    generic_cpy_call(space, dealloc, obj)
Beispiel #5
0
def subtype_dealloc(space, obj):
    pto = obj.c_ob_type
    base = pto
    this_func_ptr = llslot(space, subtype_dealloc)
    while base.c_tp_dealloc == this_func_ptr:
        base = base.c_tp_base
        assert base
    dealloc = base.c_tp_dealloc
    # XXX call tp_del if necessary
    generic_cpy_call(space, dealloc, obj)
Beispiel #6
0
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 = llslot(space, PyObject_GenericSetAttr)

    if not pto.c_tp_getattro:
        from pypy.module.cpyext.object import PyObject_GenericGetAttr
        pto.c_tp_getattro = llslot(space, PyObject_GenericGetAttr)

    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)
Beispiel #7
0
def add_operators(space, dict_w, pto):
    from pypy.module.cpyext.object import PyObject_HashNotImplemented
    hash_not_impl = llslot(space, PyObject_HashNotImplemented)
    for method_name, slot_names, wrapper_class, doc in slotdefs_for_wrappers:
        if method_name in dict_w:
            continue
        offset = [rffi.offsetof(lltype.typeOf(pto).TO, slot_names[0])]
        if len(slot_names) == 1:
            func = getattr(pto, slot_names[0])
            if slot_names[0] == 'c_tp_hash':
                # two special cases where __hash__ is explicitly set to None
                # (which leads to an unhashable type):
                # 1) tp_hash == PyObject_HashNotImplemented
                # 2) tp_hash == NULL and either of tp_compare or tp_richcompare are not NULL
                if hash_not_impl == func or (not func and
                                             (pto.c_tp_compare
                                              or pto.c_tp_richcompare)):
                    dict_w[method_name] = space.w_None
                    continue
        else:
            assert len(slot_names) == 2
            struct = getattr(pto, slot_names[0])
            if not struct:
                continue
            offset.append(
                rffi.offsetof(lltype.typeOf(struct).TO, slot_names[1]))
            func = getattr(struct, slot_names[1])
        func_voidp = rffi.cast(rffi.VOIDP, func)
        if not func:
            continue
        if wrapper_class is None:
            continue

        assert issubclass(wrapper_class, W_PyCWrapperObject)
        w_obj = wrapper_class(space,
                              pto,
                              method_name,
                              doc,
                              func_voidp,
                              offset=offset[:])
        dict_w[method_name] = w_obj
    if pto.c_tp_doc:
        dict_w['__doc__'] = space.newtext(
            rffi.charp2str(cts.cast('char*', pto.c_tp_doc)))
    if pto.c_tp_new:
        add_tp_new_wrapper(space, dict_w, pto)
Beispiel #8
0
def subtype_dealloc(space, obj):
    pto = obj.c_ob_type
    base = pto
    this_func_ptr = llslot(space, subtype_dealloc)
    # This wrapper is created on a specific type, call it w_A.
    # We wish to call the dealloc function from one of the base classes of w_A,
    # the first of which is not this function itself.
    # w_obj is an instance of w_A or one of its subclasses. So climb up the
    # inheritance chain until base.c_tp_dealloc is exactly this_func, and then
    # continue on up until they differ.
    while base.c_tp_dealloc != this_func_ptr:
        base = base.c_tp_base
        assert base
    while base.c_tp_dealloc == this_func_ptr:
        base = base.c_tp_base
        assert base
    dealloc = base.c_tp_dealloc
    # XXX call tp_del if necessary
    generic_cpy_call(space, dealloc, obj)
Beispiel #9
0
def is_tp_new_wrapper(space, ml):
    return ml.c_ml_meth == rffi.cast(PyCFunction,
                                     llslot(space, tp_new_wrapper))
Beispiel #10
0
def setup_new_method_def(space):
    ptr = get_new_method_def(space)
    ptr.c_ml_meth = rffi.cast(PyCFunction, llslot(space, tp_new_wrapper))
Beispiel #11
0
def type_attach(space, py_obj, w_type, w_userdata=None):
    """
    Fills a newly allocated PyTypeObject from an existing type.
    """
    from pypy.module.cpyext.object import PyObject_Free

    assert isinstance(w_type, W_TypeObject)

    pto = rffi.cast(PyTypeObjectPtr, py_obj)

    typedescr = get_typedescr(w_type.layout.typedef)

    if space.is_w(w_type, space.w_bytes):
        pto.c_tp_itemsize = 1
    elif space.is_w(w_type, space.w_tuple):
        pto.c_tp_itemsize = rffi.sizeof(PyObject)
    # buffer protocol
    setup_buffer_procs(space, w_type, pto)

    pto.c_tp_free = llslot(space, PyObject_Free)
    pto.c_tp_alloc = llslot(space, PyType_GenericAlloc)
    builder = space.fromcache(State).builder
    if ((pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE) != 0
            and builder.cpyext_type_init is None):
            # this ^^^ is not None only during startup of cpyext.  At that
            # point we might get into troubles by doing make_ref() when
            # things are not initialized yet.  So in this case, simply use
            # str2charp() and "leak" the string.
        w_typename = space.getattr(w_type, space.newtext('__name__'))
        heaptype = cts.cast('PyHeapTypeObject*', pto)
        heaptype.c_ht_name = make_ref(space, w_typename)
        from pypy.module.cpyext.bytesobject import PyString_AsString
        pto.c_tp_name = cts.cast('const char *',
            PyString_AsString(space, heaptype.c_ht_name))
    else:
        pto.c_tp_name = cts.cast('const char*', rffi.str2charp(w_type.name))
    # uninitialized fields:
    # c_tp_print
    # XXX implement
    # c_tp_compare and more?
    w_base = best_base(space, w_type.bases_w)
    pto.c_tp_base = rffi.cast(PyTypeObjectPtr, make_ref(space, w_base))

    # dealloc
    if space.gettypeobject(w_type.layout.typedef) is w_type:
        # only for the exact type, like 'space.w_tuple' or 'space.w_list'
        pto.c_tp_dealloc = typedescr.get_dealloc(space)
    else:
        # for all subtypes, use base's dealloc (requires sorting in attach_all)
        pto.c_tp_dealloc = pto.c_tp_base.c_tp_dealloc
        if not pto.c_tp_dealloc:
            # strange, but happens (ABCMeta)
            pto.c_tp_dealloc = llslot(space, subtype_dealloc)

    if builder.cpyext_type_init is not None:
        builder.cpyext_type_init.append((pto, w_type))
    else:
        finish_type_1(space, pto, w_type.bases_w)
        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
        if pto.c_tp_itemsize < pto.c_tp_base.c_tp_itemsize:
            pto.c_tp_itemsize = pto.c_tp_base.c_tp_itemsize

    if w_type.is_heaptype():
        update_all_slots(space, w_type, pto)
    else:
        update_all_slots_builtin(space, w_type, pto)
    if not pto.c_tp_new:
        base_object_pyo = make_ref(space, space.w_object)
        base_object_pto = rffi.cast(PyTypeObjectPtr, base_object_pyo)
        flags = rffi.cast(lltype.Signed, pto.c_tp_flags)
        if pto.c_tp_base != base_object_pto or flags & Py_TPFLAGS_HEAPTYPE:
                pto.c_tp_new = pto.c_tp_base.c_tp_new
        Py_DecRef(space, base_object_pyo)
    pto.c_tp_flags |= Py_TPFLAGS_READY
    return pto
Beispiel #12
0
def type_attach(space, py_obj, w_type):
    """
    Fills a newly allocated PyTypeObject from an existing type.
    """
    from pypy.module.cpyext.object import PyObject_Free

    assert isinstance(w_type, W_TypeObject)

    pto = rffi.cast(PyTypeObjectPtr, py_obj)

    typedescr = get_typedescr(w_type.layout.typedef)

    # dealloc
    if space.gettypeobject(w_type.layout.typedef) is w_type:
        # only for the exact type, like 'space.w_tuple' or 'space.w_list'
        pto.c_tp_dealloc = typedescr.get_dealloc().get_llhelper(space)
    else:
        # for all subtypes, use subtype_dealloc()
        pto.c_tp_dealloc = llslot(space, subtype_dealloc)
    if space.is_w(w_type, space.w_str):
        pto.c_tp_itemsize = 1
    elif space.is_w(w_type, space.w_tuple):
        pto.c_tp_itemsize = rffi.sizeof(PyObject)
    # buffer protocol
    setup_buffer_procs(space, w_type, pto)

    pto.c_tp_free = llslot(space, PyObject_Free)
    pto.c_tp_alloc = llslot(space, PyType_GenericAlloc)
    builder = space.fromcache(StaticObjectBuilder)
    if ((pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE) != 0
            and builder.cpyext_type_init is None):
            # this ^^^ is not None only during startup of cpyext.  At that
            # point we might get into troubles by doing make_ref() when
            # things are not initialized yet.  So in this case, simply use
            # str2charp() and "leak" the string.
        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
    # XXX implement
    # c_tp_compare and more?
    w_base = best_base(space, w_type.bases_w)
    pto.c_tp_base = rffi.cast(PyTypeObjectPtr, make_ref(space, w_base))

    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
        if pto.c_tp_itemsize < pto.c_tp_base.c_tp_itemsize:
            pto.c_tp_itemsize = pto.c_tp_base.c_tp_itemsize

    # 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
Beispiel #13
0
def setup_new_method_def(space):
    ptr = get_new_method_def(space)
    ptr.c_ml_meth = rffi.cast(
        PyCFunction_typedef, llslot(space, tp_new_wrapper))