From d816f8c30cc15b1a7cdc9fa855ff919359069fb3 Mon Sep 17 00:00:00 2001 From: "H. Vetinari" Date: Tue, 13 Oct 2020 16:34:17 +0200 Subject: [PATCH 4/4] compatibility with PEP 620 --- blist/_blist.c | 8 +- blist/pythoncapi_compat.h | 192 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 blist/pythoncapi_compat.h diff --git a/blist/_blist.c b/blist/_blist.c index fee7b1a..9fdf178 100644 --- a/blist/_blist.c +++ b/blist/_blist.c @@ -98,7 +98,7 @@ #endif #endif -/* This macro is defined in Python 3. We need it since calling +/* This macro is defined in Python<3.9. We need it since calling * PyObject_GC_UnTrack twice is unsafe. */ /* True if the object is currently tracked by the GC. */ #define _PyObject_GC_IS_TRACKED(o) \ @@ -122,6 +122,12 @@ #define PyInt_AsLong PyLong_AsLong #define PyInt_AsSsize_t PyLong_AsSsize_t #define PyInt_FromLong PyLong_FromLong +#if PY_MINOR_VERSION > 8 +/* _PyObject_GC_IS_TRACKED was removed from Python 3.9, re-add it; + * see PEP 620 and https://github.com/pythoncapi/pythoncapi_compat */ +#include "pythoncapi_compat.h" +#define _PyObject_GC_IS_TRACKED(o) PyObject_GC_IsTracked((PyObject*)(o)) +#endif #endif #ifndef BLIST_IN_PYTHON diff --git a/blist/pythoncapi_compat.h b/blist/pythoncapi_compat.h new file mode 100644 index 0000000..a255b3a --- /dev/null +++ b/blist/pythoncapi_compat.h @@ -0,0 +1,192 @@ +/* Header file providing new functions of the Python C API + for old Python versions. + + File distributed under the MIT license. + Homepage: https://github.com/pythoncapi/pythoncapi_compat. +*/ + +#ifndef PYTHONCAPI_COMPAT +#define PYTHONCAPI_COMPAT + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "frameobject.h" // PyFrameObject + + +// bpo-39573: Py_TYPE(), Py_REFCNT() and Py_SIZE() can no longer be used +// as l-value in Python 3.10. +#if PY_VERSION_HEX < 0x030900A4 +static inline void _Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) +{ + ob->ob_refcnt = refcnt; +} +#define Py_SET_REFCNT(ob, refcnt) _Py_SET_REFCNT((PyObject*)(ob), refcnt) + + +static inline void +_Py_SET_TYPE(PyObject *ob, PyTypeObject *type) +{ + ob->ob_type = type; +} +#define Py_SET_TYPE(ob, type) _Py_SET_TYPE((PyObject*)(ob), type) + +static inline void +_Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) +{ + ob->ob_size = size; +} +#define Py_SET_SIZE(ob, size) _Py_SET_SIZE((PyVarObject*)(ob), size) + +#endif // PY_VERSION_HEX < 0x030900A4 + + +#if PY_VERSION_HEX < 0x030900B1 +static inline PyCodeObject* +PyFrame_GetCode(PyFrameObject *frame) +{ + assert(frame != NULL); + PyCodeObject *code = frame->f_code; + assert(code != NULL); + Py_INCREF(code); + return code; +} +#endif + + +#if PY_VERSION_HEX < 0x030900B1 +static inline PyFrameObject* +PyFrame_GetBack(PyFrameObject *frame) +{ + assert(frame != NULL); + PyFrameObject *back = frame->f_back; + Py_XINCREF(back); + return back; +} +#endif + + +#if PY_VERSION_HEX < 0x030900A5 +static inline PyInterpreterState * +PyThreadState_GetInterpreter(PyThreadState *tstate) +{ + assert(tstate != NULL); + return tstate->interp; +} +#endif + + +#if PY_VERSION_HEX < 0x030900B1 +static inline PyFrameObject* +PyThreadState_GetFrame(PyThreadState *tstate) +{ + assert(tstate != NULL); + PyFrameObject *frame = tstate->frame; + Py_XINCREF(frame); + return frame; +} +#endif + + +#if PY_VERSION_HEX < 0x030900A5 +static inline PyInterpreterState * +PyInterpreterState_Get(void) +{ + PyThreadState *tstate = PyThreadState_GET(); + if (tstate == NULL) { + Py_FatalError("GIL released (tstate is NULL)"); + } + PyInterpreterState *interp = tstate->interp; + if (interp == NULL) { + Py_FatalError("no current interpreter"); + } + return interp; +} +#endif + + +#if 0x030700A1 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030900A6 +static inline uint64_t +PyThreadState_GetID(PyThreadState *tstate) +{ + assert(tstate != NULL); + return tstate->id; +} +#endif + + +#if PY_VERSION_HEX < 0x030900A1 +static inline PyObject* +PyObject_CallNoArgs(PyObject *func) +{ + return PyObject_CallFunctionObjArgs(func, NULL); +} +#endif + + +#if PY_VERSION_HEX < 0x030900A4 +static inline PyObject* +PyObject_CallOneArg(PyObject *func, PyObject *arg) +{ + return PyObject_CallFunctionObjArgs(func, arg, NULL); +} +#endif + + +#if PY_VERSION_HEX < 0x030900A5 +static inline int +PyModule_AddType(PyObject *module, PyTypeObject *type) +{ + if (PyType_Ready(type) < 0) { + return -1; + } + + // inline _PyType_Name() + const char *name = type->tp_name; + assert(name != NULL); + const char *dot = strrchr(name, '.'); + if (dot != NULL) { + name = dot + 1; + } + + Py_INCREF(type); + if (PyModule_AddObject(module, name, (PyObject *)type) < 0) { + Py_DECREF(type); + return -1; + } + + return 0; +} +#endif + + +#if PY_VERSION_HEX < 0x030900A6 +static inline int +PyObject_GC_IsTracked(PyObject* obj) +{ + return (PyObject_IS_GC(obj) && _PyObject_GC_IS_TRACKED(obj)); +} + +static inline int +PyObject_GC_IsFinalized(PyObject *obj) +{ + return (PyObject_IS_GC(obj) && _PyGCHead_FINALIZED((PyGC_Head *)(obj)-1)); +} +#endif // PY_VERSION_HEX < 0x030900A6 + + +#if PY_VERSION_HEX < 0x030900A4 +static inline int +_Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) { + return ob->ob_type == type; +} +#define Py_IS_TYPE(ob, type) _Py_IS_TYPE((const PyObject*)(ob), type) +#endif + + +#ifdef __cplusplus +} +#endif +#endif // PYTHONCAPI_COMPAT -- 2.26.2.windows.1