Revert "Prepare for Python "Limited API" in PL/Python"
authorPeter Eisentraut <[email protected]>
Wed, 26 Feb 2025 20:58:38 +0000 (21:58 +0100)
committerPeter Eisentraut <[email protected]>
Wed, 26 Feb 2025 20:58:38 +0000 (21:58 +0100)
This reverts commit c47e8df815c1c45f4e4fc90d5817d67ab088279f.

That commit makes the plpython tests crash with Python 3.6.* and
3.7.*.  It will need further investigation and testing, so revert for
now.

src/pl/plpython/plpy_cursorobject.c
src/pl/plpython/plpy_planobject.c
src/pl/plpython/plpy_procedure.c
src/pl/plpython/plpy_resultobject.c
src/pl/plpython/plpy_subxactobject.c
src/pl/plpython/plpy_typeio.c

index 2a370157f90fb2ea75df47b2827cf27f208a9ca9..bb3fa8a390990b002ffe256b97b90c8b8d72e2fe 100644 (file)
@@ -20,7 +20,7 @@
 #include "utils/memutils.h"
 
 static PyObject *PLy_cursor_query(const char *query);
-static void PLy_cursor_dealloc(PLyCursorObject *self);
+static void PLy_cursor_dealloc(PyObject *arg);
 static PyObject *PLy_cursor_iternext(PyObject *self);
 static PyObject *PLy_cursor_fetch(PyObject *self, PyObject *args);
 static PyObject *PLy_cursor_close(PyObject *self, PyObject *unused);
@@ -33,43 +33,22 @@ static PyMethodDef PLy_cursor_methods[] = {
    {NULL, NULL, 0, NULL}
 };
 
-static PyType_Slot PLyCursor_slots[] =
-{
-   {
-       Py_tp_dealloc, PLy_cursor_dealloc
-   },
-   {
-       Py_tp_doc, (char *) PLy_cursor_doc
-   },
-   {
-       Py_tp_iter, PyObject_SelfIter
-   },
-   {
-       Py_tp_iternext, PLy_cursor_iternext
-   },
-   {
-       Py_tp_methods, PLy_cursor_methods
-   },
-   {
-       0, NULL
-   }
+static PyTypeObject PLy_CursorType = {
+   PyVarObject_HEAD_INIT(NULL, 0)
+   .tp_name = "PLyCursor",
+   .tp_basicsize = sizeof(PLyCursorObject),
+   .tp_dealloc = PLy_cursor_dealloc,
+   .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+   .tp_doc = PLy_cursor_doc,
+   .tp_iter = PyObject_SelfIter,
+   .tp_iternext = PLy_cursor_iternext,
+   .tp_methods = PLy_cursor_methods,
 };
 
-static PyType_Spec PLyCursor_spec =
-{
-   .name = "PLyCursor",
-       .basicsize = sizeof(PLyCursorObject),
-       .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
-       .slots = PLyCursor_slots,
-};
-
-static PyTypeObject *PLy_CursorType;
-
 void
 PLy_cursor_init_type(void)
 {
-   PLy_CursorType = (PyTypeObject *) PyType_FromSpec(&PLyCursor_spec);
-   if (!PLy_CursorType)
+   if (PyType_Ready(&PLy_CursorType) < 0)
        elog(ERROR, "could not initialize PLy_CursorType");
 }
 
@@ -101,7 +80,7 @@ PLy_cursor_query(const char *query)
    volatile MemoryContext oldcontext;
    volatile ResourceOwner oldowner;
 
-   if ((cursor = PyObject_New(PLyCursorObject, PLy_CursorType)) == NULL)
+   if ((cursor = PyObject_New(PLyCursorObject, &PLy_CursorType)) == NULL)
        return NULL;
    cursor->portalname = NULL;
    cursor->closed = false;
@@ -198,7 +177,7 @@ PLy_cursor_plan(PyObject *ob, PyObject *args)
        return NULL;
    }
 
-   if ((cursor = PyObject_New(PLyCursorObject, PLy_CursorType)) == NULL)
+   if ((cursor = PyObject_New(PLyCursorObject, &PLy_CursorType)) == NULL)
        return NULL;
    cursor->portalname = NULL;
    cursor->closed = false;
@@ -293,30 +272,30 @@ PLy_cursor_plan(PyObject *ob, PyObject *args)
 }
 
 static void
-PLy_cursor_dealloc(PLyCursorObject *self)
+PLy_cursor_dealloc(PyObject *arg)
 {
-   PyTypeObject *tp = Py_TYPE(self);
+   PLyCursorObject *cursor;
    Portal      portal;
 
-   if (!self->closed)
+   cursor = (PLyCursorObject *) arg;
+
+   if (!cursor->closed)
    {
-       portal = GetPortalByName(self->portalname);
+       portal = GetPortalByName(cursor->portalname);
 
        if (PortalIsValid(portal))
        {
            UnpinPortal(portal);
            SPI_cursor_close(portal);
        }
-       self->closed = true;
+       cursor->closed = true;
    }
-   if (self->mcxt)
+   if (cursor->mcxt)
    {
-       MemoryContextDelete(self->mcxt);
-       self->mcxt = NULL;
+       MemoryContextDelete(cursor->mcxt);
+       cursor->mcxt = NULL;
    }
-
-   PyObject_Free(self);
-   Py_DECREF(tp);
+   arg->ob_type->tp_free(arg);
 }
 
 static PyObject *
index 1b97b5cbd2ad8416e3e979dd40f8b7f883f35a1f..9427674d2f4a6506ad7f6fb6f80d046e18eac903 100644 (file)
@@ -12,7 +12,7 @@
 #include "plpython.h"
 #include "utils/memutils.h"
 
-static void PLy_plan_dealloc(PLyPlanObject *self);
+static void PLy_plan_dealloc(PyObject *arg);
 static PyObject *PLy_plan_cursor(PyObject *self, PyObject *args);
 static PyObject *PLy_plan_execute(PyObject *self, PyObject *args);
 static PyObject *PLy_plan_status(PyObject *self, PyObject *args);
@@ -26,37 +26,20 @@ static PyMethodDef PLy_plan_methods[] = {
    {NULL, NULL, 0, NULL}
 };
 
-static PyType_Slot PLyPlan_slots[] =
-{
-   {
-       Py_tp_dealloc, PLy_plan_dealloc
-   },
-   {
-       Py_tp_doc, (char *) PLy_plan_doc
-   },
-   {
-       Py_tp_methods, PLy_plan_methods
-   },
-   {
-       0, NULL
-   }
+static PyTypeObject PLy_PlanType = {
+   PyVarObject_HEAD_INIT(NULL, 0)
+   .tp_name = "PLyPlan",
+   .tp_basicsize = sizeof(PLyPlanObject),
+   .tp_dealloc = PLy_plan_dealloc,
+   .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+   .tp_doc = PLy_plan_doc,
+   .tp_methods = PLy_plan_methods,
 };
 
-static PyType_Spec PLyPlan_spec =
-{
-   .name = "PLyPlan",
-       .basicsize = sizeof(PLyPlanObject),
-       .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
-       .slots = PLyPlan_slots,
-};
-
-static PyTypeObject *PLy_PlanType;
-
 void
 PLy_plan_init_type(void)
 {
-   PLy_PlanType = (PyTypeObject *) PyType_FromSpec(&PLyPlan_spec);
-   if (!PLy_PlanType)
+   if (PyType_Ready(&PLy_PlanType) < 0)
        elog(ERROR, "could not initialize PLy_PlanType");
 }
 
@@ -65,7 +48,7 @@ PLy_plan_new(void)
 {
    PLyPlanObject *ob;
 
-   if ((ob = PyObject_New(PLyPlanObject, PLy_PlanType)) == NULL)
+   if ((ob = PyObject_New(PLyPlanObject, &PLy_PlanType)) == NULL)
        return NULL;
 
    ob->plan = NULL;
@@ -80,27 +63,25 @@ PLy_plan_new(void)
 bool
 is_PLyPlanObject(PyObject *ob)
 {
-   return ob->ob_type == PLy_PlanType;
+   return ob->ob_type == &PLy_PlanType;
 }
 
 static void
-PLy_plan_dealloc(PLyPlanObject *self)
+PLy_plan_dealloc(PyObject *arg)
 {
-   PyTypeObject *tp = Py_TYPE(self);
+   PLyPlanObject *ob = (PLyPlanObject *) arg;
 
-   if (self->plan)
+   if (ob->plan)
    {
-       SPI_freeplan(self->plan);
-       self->plan = NULL;
+       SPI_freeplan(ob->plan);
+       ob->plan = NULL;
    }
-   if (self->mcxt)
+   if (ob->mcxt)
    {
-       MemoryContextDelete(self->mcxt);
-       self->mcxt = NULL;
+       MemoryContextDelete(ob->mcxt);
+       ob->mcxt = NULL;
    }
-
-   PyObject_Free(self);
-   Py_DECREF(tp);
+   arg->ob_type->tp_free(arg);
 }
 
 
index b494eeb474f36e0f2d51747b0564fe299eb88e48..c35a3b801abbfd7672fd735f2406ff6531cd57f5 100644 (file)
@@ -350,7 +350,6 @@ PLy_procedure_compile(PLyProcedure *proc, const char *src)
 {
    PyObject   *crv = NULL;
    char       *msrc;
-   PyObject   *code0;
 
    proc->globals = PyDict_Copy(PLy_interp_globals);
 
@@ -369,9 +368,7 @@ PLy_procedure_compile(PLyProcedure *proc, const char *src)
    msrc = PLy_procedure_munge_source(proc->pyname, src);
    /* Save the mangled source for later inclusion in tracebacks */
    proc->src = MemoryContextStrdup(proc->mcxt, msrc);
-   code0 = Py_CompileString(msrc, "<string>", Py_file_input);
-   if (code0)
-       crv = PyEval_EvalCode(code0, proc->globals, NULL);
+   crv = PyRun_String(msrc, Py_file_input, proc->globals, NULL);
    pfree(msrc);
 
    if (crv != NULL)
index f2628205669052f5d5fc9d7c891263ef670178cc..95acce654935c8743b544535402bb0c92c3f0165 100644 (file)
@@ -10,7 +10,7 @@
 #include "plpy_resultobject.h"
 #include "plpython.h"
 
-static void PLy_result_dealloc(PLyResultObject *self);
+static void PLy_result_dealloc(PyObject *arg);
 static PyObject *PLy_result_colnames(PyObject *self, PyObject *unused);
 static PyObject *PLy_result_coltypes(PyObject *self, PyObject *unused);
 static PyObject *PLy_result_coltypmods(PyObject *self, PyObject *unused);
@@ -24,6 +24,17 @@ static int   PLy_result_ass_subscript(PyObject *arg, PyObject *item, PyObject *val
 
 static char PLy_result_doc[] = "Results of a PostgreSQL query";
 
+static PySequenceMethods PLy_result_as_sequence = {
+   .sq_length = PLy_result_length,
+   .sq_item = PLy_result_item,
+};
+
+static PyMappingMethods PLy_result_as_mapping = {
+   .mp_length = PLy_result_length,
+   .mp_subscript = PLy_result_subscript,
+   .mp_ass_subscript = PLy_result_ass_subscript,
+};
+
 static PyMethodDef PLy_result_methods[] = {
    {"colnames", PLy_result_colnames, METH_NOARGS, NULL},
    {"coltypes", PLy_result_coltypes, METH_NOARGS, NULL},
@@ -33,55 +44,23 @@ static PyMethodDef PLy_result_methods[] = {
    {NULL, NULL, 0, NULL}
 };
 
-static PyType_Slot PLyResult_slots[] =
-{
-   {
-       Py_tp_dealloc, PLy_result_dealloc
-   },
-   {
-       Py_sq_length, PLy_result_length
-   },
-   {
-       Py_sq_item, PLy_result_item
-   },
-   {
-       Py_mp_length, PLy_result_length
-   },
-   {
-       Py_mp_subscript, PLy_result_subscript
-   },
-   {
-       Py_mp_ass_subscript, PLy_result_ass_subscript
-   },
-   {
-       Py_tp_str, PLy_result_str
-   },
-   {
-       Py_tp_doc, (char *) PLy_result_doc
-   },
-   {
-       Py_tp_methods, PLy_result_methods
-   },
-   {
-       0, NULL
-   }
+static PyTypeObject PLy_ResultType = {
+   PyVarObject_HEAD_INIT(NULL, 0)
+   .tp_name = "PLyResult",
+   .tp_basicsize = sizeof(PLyResultObject),
+   .tp_dealloc = PLy_result_dealloc,
+   .tp_as_sequence = &PLy_result_as_sequence,
+   .tp_as_mapping = &PLy_result_as_mapping,
+   .tp_str = &PLy_result_str,
+   .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+   .tp_doc = PLy_result_doc,
+   .tp_methods = PLy_result_methods,
 };
 
-static PyType_Spec PLyResult_spec =
-{
-   .name = "PLyResult",
-       .basicsize = sizeof(PLyResultObject),
-       .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
-       .slots = PLyResult_slots,
-};
-
-static PyTypeObject *PLy_ResultType;
-
 void
 PLy_result_init_type(void)
 {
-   PLy_ResultType = (PyTypeObject *) PyType_FromSpec(&PLyResult_spec);
-   if (!PLy_ResultType)
+   if (PyType_Ready(&PLy_ResultType) < 0)
        elog(ERROR, "could not initialize PLy_ResultType");
 }
 
@@ -90,7 +69,7 @@ PLy_result_new(void)
 {
    PLyResultObject *ob;
 
-   if ((ob = PyObject_New(PLyResultObject, PLy_ResultType)) == NULL)
+   if ((ob = PyObject_New(PLyResultObject, &PLy_ResultType)) == NULL)
        return NULL;
 
    /* ob->tuples = NULL; */
@@ -110,21 +89,20 @@ PLy_result_new(void)
 }
 
 static void
-PLy_result_dealloc(PLyResultObject *self)
+PLy_result_dealloc(PyObject *arg)
 {
-   PyTypeObject *tp = Py_TYPE(self);
+   PLyResultObject *ob = (PLyResultObject *) arg;
 
-   Py_XDECREF(self->nrows);
-   Py_XDECREF(self->rows);
-   Py_XDECREF(self->status);
-   if (self->tupdesc)
+   Py_XDECREF(ob->nrows);
+   Py_XDECREF(ob->rows);
+   Py_XDECREF(ob->status);
+   if (ob->tupdesc)
    {
-       FreeTupleDesc(self->tupdesc);
-       self->tupdesc = NULL;
+       FreeTupleDesc(ob->tupdesc);
+       ob->tupdesc = NULL;
    }
 
-   PyObject_Free(self);
-   Py_DECREF(tp);
+   arg->ob_type->tp_free(arg);
 }
 
 static PyObject *
@@ -147,7 +125,7 @@ PLy_result_colnames(PyObject *self, PyObject *unused)
    {
        Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
 
-       PyList_SetItem(list, i, PLyUnicode_FromString(NameStr(attr->attname)));
+       PyList_SET_ITEM(list, i, PLyUnicode_FromString(NameStr(attr->attname)));
    }
 
    return list;
@@ -173,7 +151,7 @@ PLy_result_coltypes(PyObject *self, PyObject *unused)
    {
        Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
 
-       PyList_SetItem(list, i, PyLong_FromLong(attr->atttypid));
+       PyList_SET_ITEM(list, i, PyLong_FromLong(attr->atttypid));
    }
 
    return list;
@@ -199,7 +177,7 @@ PLy_result_coltypmods(PyObject *self, PyObject *unused)
    {
        Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
 
-       PyList_SetItem(list, i, PyLong_FromLong(attr->atttypmod));
+       PyList_SET_ITEM(list, i, PyLong_FromLong(attr->atttypmod));
    }
 
    return list;
@@ -249,7 +227,7 @@ PLy_result_str(PyObject *arg)
    PLyResultObject *ob = (PLyResultObject *) arg;
 
    return PyUnicode_FromFormat("<%s status=%S nrows=%S rows=%S>",
-                               "PLyResult",
+                               Py_TYPE(ob)->tp_name,
                                ob->status,
                                ob->nrows,
                                ob->rows);
index cc7ff3f9df7c2ef5cf3b68f19b640a878f930e5f..5c92a0e089a1b214e61178328047ceaa534286d0 100644 (file)
@@ -15,6 +15,7 @@
 List      *explicit_subtransactions = NIL;
 
 
+static void PLy_subtransaction_dealloc(PyObject *subxact);
 static PyObject *PLy_subtransaction_enter(PyObject *self, PyObject *unused);
 static PyObject *PLy_subtransaction_exit(PyObject *self, PyObject *args);
 
@@ -30,35 +31,21 @@ static PyMethodDef PLy_subtransaction_methods[] = {
    {NULL, NULL, 0, NULL}
 };
 
-static PyType_Slot PLySubtransaction_slots[] =
-{
-   {
-       Py_tp_doc, (char *) PLy_subtransaction_doc
-   },
-   {
-       Py_tp_methods, PLy_subtransaction_methods
-   },
-   {
-       0, NULL
-   }
-};
-
-static PyType_Spec PLySubtransaction_spec =
-{
-   .name = "PLySubtransaction",
-       .basicsize = sizeof(PLySubtransactionObject),
-       .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
-       .slots = PLySubtransaction_slots,
+static PyTypeObject PLy_SubtransactionType = {
+   PyVarObject_HEAD_INIT(NULL, 0)
+   .tp_name = "PLySubtransaction",
+   .tp_basicsize = sizeof(PLySubtransactionObject),
+   .tp_dealloc = PLy_subtransaction_dealloc,
+   .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+   .tp_doc = PLy_subtransaction_doc,
+   .tp_methods = PLy_subtransaction_methods,
 };
 
-static PyTypeObject *PLy_SubtransactionType;
-
 
 void
 PLy_subtransaction_init_type(void)
 {
-   PLy_SubtransactionType = (PyTypeObject *) PyType_FromSpec(&PLySubtransaction_spec);
-   if (!PLy_SubtransactionType)
+   if (PyType_Ready(&PLy_SubtransactionType) < 0)
        elog(ERROR, "could not initialize PLy_SubtransactionType");
 }
 
@@ -68,7 +55,7 @@ PLy_subtransaction_new(PyObject *self, PyObject *unused)
 {
    PLySubtransactionObject *ob;
 
-   ob = PyObject_New(PLySubtransactionObject, PLy_SubtransactionType);
+   ob = PyObject_New(PLySubtransactionObject, &PLy_SubtransactionType);
 
    if (ob == NULL)
        return NULL;
@@ -79,6 +66,12 @@ PLy_subtransaction_new(PyObject *self, PyObject *unused)
    return (PyObject *) ob;
 }
 
+/* Python requires a dealloc function to be defined */
+static void
+PLy_subtransaction_dealloc(PyObject *subxact)
+{
+}
+
 /*
  * subxact.__enter__() or subxact.enter()
  *
index 1d127ae3ffe37c7c697f4344d6854459523ba22e..51e1d610259d4f2083540321120474ab69dddd2b 100644 (file)
@@ -723,7 +723,7 @@ PLyList_FromArray_recurse(PLyDatumToOb *elm, int *dims, int ndim, int dim,
 
            sublist = PLyList_FromArray_recurse(elm, dims, ndim, dim + 1,
                                                dataptr_p, bitmap_p, bitmask_p);
-           PyList_SetItem(list, i, sublist);
+           PyList_SET_ITEM(list, i, sublist);
        }
    }
    else
@@ -742,14 +742,14 @@ PLyList_FromArray_recurse(PLyDatumToOb *elm, int *dims, int ndim, int dim,
            if (bitmap && (*bitmap & bitmask) == 0)
            {
                Py_INCREF(Py_None);
-               PyList_SetItem(list, i, Py_None);
+               PyList_SET_ITEM(list, i, Py_None);
            }
            else
            {
                Datum       itemvalue;
 
                itemvalue = fetch_att(dataptr, elm->typbyval, elm->typlen);
-               PyList_SetItem(list, i, elm->func(elm, itemvalue));
+               PyList_SET_ITEM(list, i, elm->func(elm, itemvalue));
                dataptr = att_addlength_pointer(dataptr, elm->typlen, dataptr);
                dataptr = (char *) att_align_nominal(dataptr, elm->typalign);
            }