From d816f8c30cc15b1a7cdc9fa855ff919359069fb3 Mon Sep 17 00:00:00 2001
From: "H. Vetinari" <h.vetinari@gmx.com>
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 <Python.h>
+#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

