[prev in list] [next in list] [prev in thread] [next in thread] 

List:       python-capi-sig
Subject:    [capi-sig]Experiment Python without Py_TYPE()
From:       Victor Stinner <vstinner () redhat ! com>
Date:       2018-09-05 14:58:48
Message-ID: CA+3bQGHobFn3rc8igrMLFYp5gWUAdhRFo+7i2_5xV_GgKeh=Hg () mail ! gmail ! com
[Download RAW message or body]

Hi,

In my previous "Open questions about borrowed references" thread, I
asked if it's an issue or not that Py_TYPE() returns a borrowed
reference.

It seems like most people say that it's not an issue. If you want to
discuss if Py_TYPE() is an issue, please contribute to the other
thread. Here I only want to share my results. Honestly, I'm still not
100% convinced that Py_TYPE() is an issue :-)

I experimented anyway a C API without Py_TYPE(). I chose to add 3
functions/features:

* ``Py_GetType()``: similar to ``Py_TYPE()`` but returns a strong reference
* ``Py_TYPE_IS(ob, type)``: equivalent to ``Py_TYPE(ob) == type``
* ``%T`` format for ``PyUnicode_FromFormat()``

Most of the usage of Py_TYPE() are the following 5 patterns. For the
last one, I'm not sure that the "N" format of Py_BuildValue() should
stay since it's also based on borrowed reference. Replacing Py_TYPE()
requires a lot of changes, and I made many copy/paste mistakes. If we
chose to remove Py_TYPE(), we really need a tool to automate
refactoring. Otherwise, the risk of introducing a regression is just
too high and send the wrong signals to users.

Dealloc::

    Py_TYPE(self)->tp_free((PyObject *)self);

becomes::

    PyTypeObject *type = Py_GetType(self);
    type->tp_free((PyObject *)self);
    Py_DECREF(type);


Size::

    res = _PyObject_SIZE(Py_TYPE(self)) + self->allocated *
self->ob_descr->itemsize;

becomes::

    PyTypeObject *type = Py_GetType(self);
    res = _PyObject_SIZE(type) + self->allocated * self->ob_descr->itemsize;
    Py_DECREF(type);


Error::

     PyErr_Format(PyExc_TypeError,
         "first argument must be a type object, not %.200s",
         Py_TYPE(arraytype)->tp_name);

becomes::

     PyErr_Format(PyExc_TypeError,
                  "first argument must be a type object, not %T",
                  arraytype);


Py_BuildValue::

     result = Py_BuildValue(
         "N(CO)O", Py_GetType(self), typecode, list, dict);

becomes::

     result = Py_BuildValue(
         "N(CO)O", Py_GetType(self), typecode, list, dict);

Victor
_______________________________________________
capi-sig mailing list -- capi-sig@python.org
To unsubscribe send an email to capi-sig-leave@python.org
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic