cext: add Python 3.10 support
* Replace "Py_TYPE(obj) = type;" with "Py_SET_TYPE(obj, type);"
* Add pythoncapi_compat.h header file to get Py_SET_TYPE() on Python
2.7-3.8. Header file added to mercurial/ and
contrib/python-zstandard/zstd/common/.
In Python 3.10, Py_TYPE(obj) must not longer be used as an l-value.
pythoncapi_compat.h comes from:
https://github.com/pythoncapi/pythoncapi_compat
Differential Revision: https://phab.mercurial-scm.org/D9825
--- a/contrib/clang-format-ignorelist Wed Jan 20 14:47:13 2021 +0100
+++ b/contrib/clang-format-ignorelist Mon Dec 14 10:44:29 2020 +0100
@@ -9,3 +9,4 @@
hgext/fsmonitor/pywatchman/**.c
mercurial/thirdparty/**.c
mercurial/thirdparty/**.h
+mercurial/pythoncapi_compat.h
--- a/contrib/python-zstandard/c-ext/bufferutil.c Wed Jan 20 14:47:13 2021 +0100
+++ b/contrib/python-zstandard/c-ext/bufferutil.c Mon Dec 14 10:44:29 2020 +0100
@@ -758,7 +758,7 @@
};
void bufferutil_module_init(PyObject* mod) {
- Py_TYPE(&ZstdBufferWithSegmentsType) = &PyType_Type;
+ Py_SET_TYPE(&ZstdBufferWithSegmentsType, &PyType_Type);
if (PyType_Ready(&ZstdBufferWithSegmentsType) < 0) {
return;
}
@@ -766,7 +766,7 @@
Py_INCREF(&ZstdBufferWithSegmentsType);
PyModule_AddObject(mod, "BufferWithSegments", (PyObject*)&ZstdBufferWithSegmentsType);
- Py_TYPE(&ZstdBufferSegmentsType) = &PyType_Type;
+ Py_SET_TYPE(&ZstdBufferSegmentsType, &PyType_Type);
if (PyType_Ready(&ZstdBufferSegmentsType) < 0) {
return;
}
@@ -774,7 +774,7 @@
Py_INCREF(&ZstdBufferSegmentsType);
PyModule_AddObject(mod, "BufferSegments", (PyObject*)&ZstdBufferSegmentsType);
- Py_TYPE(&ZstdBufferSegmentType) = &PyType_Type;
+ Py_SET_TYPE(&ZstdBufferSegmentType, &PyType_Type);
if (PyType_Ready(&ZstdBufferSegmentType) < 0) {
return;
}
@@ -782,7 +782,7 @@
Py_INCREF(&ZstdBufferSegmentType);
PyModule_AddObject(mod, "BufferSegment", (PyObject*)&ZstdBufferSegmentType);
- Py_TYPE(&ZstdBufferWithSegmentsCollectionType) = &PyType_Type;
+ Py_SET_TYPE(&ZstdBufferWithSegmentsCollectionType, &PyType_Type);
if (PyType_Ready(&ZstdBufferWithSegmentsCollectionType) < 0) {
return;
}
--- a/contrib/python-zstandard/c-ext/compressionchunker.c Wed Jan 20 14:47:13 2021 +0100
+++ b/contrib/python-zstandard/c-ext/compressionchunker.c Mon Dec 14 10:44:29 2020 +0100
@@ -348,12 +348,12 @@
};
void compressionchunker_module_init(PyObject* module) {
- Py_TYPE(&ZstdCompressionChunkerIteratorType) = &PyType_Type;
+ Py_SET_TYPE(&ZstdCompressionChunkerIteratorType, &PyType_Type);
if (PyType_Ready(&ZstdCompressionChunkerIteratorType) < 0) {
return;
}
- Py_TYPE(&ZstdCompressionChunkerType) = &PyType_Type;
+ Py_SET_TYPE(&ZstdCompressionChunkerType, &PyType_Type);
if (PyType_Ready(&ZstdCompressionChunkerType) < 0) {
return;
}
--- a/contrib/python-zstandard/c-ext/compressiondict.c Wed Jan 20 14:47:13 2021 +0100
+++ b/contrib/python-zstandard/c-ext/compressiondict.c Mon Dec 14 10:44:29 2020 +0100
@@ -400,7 +400,7 @@
};
void compressiondict_module_init(PyObject* mod) {
- Py_TYPE(&ZstdCompressionDictType) = &PyType_Type;
+ Py_SET_TYPE(&ZstdCompressionDictType, &PyType_Type);
if (PyType_Ready(&ZstdCompressionDictType) < 0) {
return;
}
--- a/contrib/python-zstandard/c-ext/compressionparams.c Wed Jan 20 14:47:13 2021 +0100
+++ b/contrib/python-zstandard/c-ext/compressionparams.c Mon Dec 14 10:44:29 2020 +0100
@@ -556,7 +556,7 @@
};
void compressionparams_module_init(PyObject* mod) {
- Py_TYPE(&ZstdCompressionParametersType) = &PyType_Type;
+ Py_SET_TYPE(&ZstdCompressionParametersType, &PyType_Type);
if (PyType_Ready(&ZstdCompressionParametersType) < 0) {
return;
}
--- a/contrib/python-zstandard/c-ext/compressionreader.c Wed Jan 20 14:47:13 2021 +0100
+++ b/contrib/python-zstandard/c-ext/compressionreader.c Mon Dec 14 10:44:29 2020 +0100
@@ -811,7 +811,7 @@
void compressionreader_module_init(PyObject* mod) {
/* TODO make reader a sub-class of io.RawIOBase */
- Py_TYPE(&ZstdCompressionReaderType) = &PyType_Type;
+ Py_SET_TYPE(&ZstdCompressionReaderType, &PyType_Type);
if (PyType_Ready(&ZstdCompressionReaderType) < 0) {
return;
}
--- a/contrib/python-zstandard/c-ext/compressionwriter.c Wed Jan 20 14:47:13 2021 +0100
+++ b/contrib/python-zstandard/c-ext/compressionwriter.c Mon Dec 14 10:44:29 2020 +0100
@@ -365,7 +365,7 @@
};
void compressionwriter_module_init(PyObject* mod) {
- Py_TYPE(&ZstdCompressionWriterType) = &PyType_Type;
+ Py_SET_TYPE(&ZstdCompressionWriterType, &PyType_Type);
if (PyType_Ready(&ZstdCompressionWriterType) < 0) {
return;
}
--- a/contrib/python-zstandard/c-ext/compressobj.c Wed Jan 20 14:47:13 2021 +0100
+++ b/contrib/python-zstandard/c-ext/compressobj.c Mon Dec 14 10:44:29 2020 +0100
@@ -249,7 +249,7 @@
};
void compressobj_module_init(PyObject* module) {
- Py_TYPE(&ZstdCompressionObjType) = &PyType_Type;
+ Py_SET_TYPE(&ZstdCompressionObjType, &PyType_Type);
if (PyType_Ready(&ZstdCompressionObjType) < 0) {
return;
}
--- a/contrib/python-zstandard/c-ext/compressor.c Wed Jan 20 14:47:13 2021 +0100
+++ b/contrib/python-zstandard/c-ext/compressor.c Mon Dec 14 10:44:29 2020 +0100
@@ -619,7 +619,7 @@
goto finally;
}
- Py_SIZE(output) = outBuffer.pos;
+ Py_SET_SIZE(output, outBuffer.pos);
finally:
PyBuffer_Release(&source);
@@ -1659,7 +1659,7 @@
};
void compressor_module_init(PyObject* mod) {
- Py_TYPE(&ZstdCompressorType) = &PyType_Type;
+ Py_SET_TYPE(&ZstdCompressorType, &PyType_Type);
if (PyType_Ready(&ZstdCompressorType) < 0) {
return;
}
--- a/contrib/python-zstandard/c-ext/compressoriterator.c Wed Jan 20 14:47:13 2021 +0100
+++ b/contrib/python-zstandard/c-ext/compressoriterator.c Mon Dec 14 10:44:29 2020 +0100
@@ -228,7 +228,7 @@
};
void compressoriterator_module_init(PyObject* mod) {
- Py_TYPE(&ZstdCompressorIteratorType) = &PyType_Type;
+ Py_SET_TYPE(&ZstdCompressorIteratorType, &PyType_Type);
if (PyType_Ready(&ZstdCompressorIteratorType) < 0) {
return;
}
--- a/contrib/python-zstandard/c-ext/decompressionreader.c Wed Jan 20 14:47:13 2021 +0100
+++ b/contrib/python-zstandard/c-ext/decompressionreader.c Mon Dec 14 10:44:29 2020 +0100
@@ -774,7 +774,7 @@
void decompressionreader_module_init(PyObject* mod) {
/* TODO make reader a sub-class of io.RawIOBase */
- Py_TYPE(&ZstdDecompressionReaderType) = &PyType_Type;
+ Py_SET_TYPE(&ZstdDecompressionReaderType, &PyType_Type);
if (PyType_Ready(&ZstdDecompressionReaderType) < 0) {
return;
}
--- a/contrib/python-zstandard/c-ext/decompressionwriter.c Wed Jan 20 14:47:13 2021 +0100
+++ b/contrib/python-zstandard/c-ext/decompressionwriter.c Mon Dec 14 10:44:29 2020 +0100
@@ -288,7 +288,7 @@
};
void decompressionwriter_module_init(PyObject* mod) {
- Py_TYPE(&ZstdDecompressionWriterType) = &PyType_Type;
+ Py_SET_TYPE(&ZstdDecompressionWriterType, &PyType_Type);
if (PyType_Ready(&ZstdDecompressionWriterType) < 0) {
return;
}
--- a/contrib/python-zstandard/c-ext/decompressobj.c Wed Jan 20 14:47:13 2021 +0100
+++ b/contrib/python-zstandard/c-ext/decompressobj.c Mon Dec 14 10:44:29 2020 +0100
@@ -195,7 +195,7 @@
};
void decompressobj_module_init(PyObject* module) {
- Py_TYPE(&ZstdDecompressionObjType) = &PyType_Type;
+ Py_SET_TYPE(&ZstdDecompressionObjType, &PyType_Type);
if (PyType_Ready(&ZstdDecompressionObjType) < 0) {
return;
}
--- a/contrib/python-zstandard/c-ext/decompressor.c Wed Jan 20 14:47:13 2021 +0100
+++ b/contrib/python-zstandard/c-ext/decompressor.c Mon Dec 14 10:44:29 2020 +0100
@@ -1811,7 +1811,7 @@
};
void decompressor_module_init(PyObject* mod) {
- Py_TYPE(&ZstdDecompressorType) = &PyType_Type;
+ Py_SET_TYPE(&ZstdDecompressorType, &PyType_Type);
if (PyType_Ready(&ZstdDecompressorType) < 0) {
return;
}
--- a/contrib/python-zstandard/c-ext/decompressoriterator.c Wed Jan 20 14:47:13 2021 +0100
+++ b/contrib/python-zstandard/c-ext/decompressoriterator.c Mon Dec 14 10:44:29 2020 +0100
@@ -242,7 +242,7 @@
};
void decompressoriterator_module_init(PyObject* mod) {
- Py_TYPE(&ZstdDecompressorIteratorType) = &PyType_Type;
+ Py_SET_TYPE(&ZstdDecompressorIteratorType, &PyType_Type);
if (PyType_Ready(&ZstdDecompressorIteratorType) < 0) {
return;
}
--- a/contrib/python-zstandard/c-ext/frameparams.c Wed Jan 20 14:47:13 2021 +0100
+++ b/contrib/python-zstandard/c-ext/frameparams.c Mon Dec 14 10:44:29 2020 +0100
@@ -128,7 +128,7 @@
};
void frameparams_module_init(PyObject* mod) {
- Py_TYPE(&FrameParametersType) = &PyType_Type;
+ Py_SET_TYPE(&FrameParametersType, &PyType_Type);
if (PyType_Ready(&FrameParametersType) < 0) {
return;
}
--- a/contrib/python-zstandard/c-ext/python-zstandard.h Wed Jan 20 14:47:13 2021 +0100
+++ b/contrib/python-zstandard/c-ext/python-zstandard.h Mon Dec 14 10:44:29 2020 +0100
@@ -9,6 +9,7 @@
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include "structmember.h"
+#include <pythoncapi_compat.h>
#define ZSTD_STATIC_LINKING_ONLY
#define ZDICT_STATIC_LINKING_ONLY
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/python-zstandard/zstd/common/pythoncapi_compat.h Mon Dec 14 10:44:29 2020 +0100
@@ -0,0 +1,278 @@
+// Header file providing new functions of the Python C API to old Python
+// versions.
+//
+// File distributed under the MIT license.
+//
+// Homepage:
+// https://github.com/pythoncapi/pythoncapi_compat
+//
+// Latest version:
+// https://raw.githubusercontent.com/pythoncapi/pythoncapi_compat/master/pythoncapi_compat.h
+
+#ifndef PYTHONCAPI_COMPAT
+#define PYTHONCAPI_COMPAT
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <Python.h>
+#include "frameobject.h" // PyFrameObject, PyFrame_GetBack()
+
+
+// Cast argument to PyObject* type.
+#ifndef _PyObject_CAST
+# define _PyObject_CAST(op) ((PyObject*)(op))
+#endif
+
+
+// bpo-42262 added Py_NewRef() to Python 3.10.0a3
+#if PY_VERSION_HEX < 0x030a00A3 && !defined(Py_NewRef)
+static inline PyObject* _Py_NewRef(PyObject *obj)
+{
+ Py_INCREF(obj);
+ return obj;
+}
+#define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj))
+#endif
+
+
+// bpo-42262 added Py_XNewRef() to Python 3.10.0a3
+#if PY_VERSION_HEX < 0x030a00A3 && !defined(Py_XNewRef)
+static inline PyObject* _Py_XNewRef(PyObject *obj)
+{
+ Py_XINCREF(obj);
+ return obj;
+}
+#define Py_XNewRef(obj) _Py_XNewRef(_PyObject_CAST(obj))
+#endif
+
+
+// bpo-39573 added Py_SET_REFCNT() to Python 3.9.0a4
+#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_REFCNT)
+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)
+#endif
+
+
+// bpo-39573 added Py_SET_TYPE() to Python 3.9.0a4
+#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE)
+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)
+#endif
+
+
+// bpo-39573 added Py_SET_SIZE() to Python 3.9.0a4
+#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_SIZE)
+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
+
+
+// bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1
+#if PY_VERSION_HEX < 0x030900B1
+static inline PyCodeObject*
+PyFrame_GetCode(PyFrameObject *frame)
+{
+ PyCodeObject *code;
+ assert(frame != NULL);
+ code = frame->f_code;
+ assert(code != NULL);
+ Py_INCREF(code);
+ return code;
+}
+#endif
+
+static inline PyCodeObject*
+_PyFrame_GetCodeBorrow(PyFrameObject *frame)
+{
+ PyCodeObject *code = PyFrame_GetCode(frame);
+ Py_DECREF(code);
+ return code; // borrowed reference
+}
+
+
+// bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1
+#if PY_VERSION_HEX < 0x030900B1
+static inline PyFrameObject*
+PyFrame_GetBack(PyFrameObject *frame)
+{
+ PyFrameObject *back;
+ assert(frame != NULL);
+ back = frame->f_back;
+ Py_XINCREF(back);
+ return back;
+}
+#endif
+
+static inline PyFrameObject*
+_PyFrame_GetBackBorrow(PyFrameObject *frame)
+{
+ PyFrameObject *back = PyFrame_GetBack(frame);
+ Py_XDECREF(back);
+ return back; // borrowed reference
+}
+
+
+// bpo-39947 added PyThreadState_GetInterpreter() to Python 3.9.0a5
+#if PY_VERSION_HEX < 0x030900A5
+static inline PyInterpreterState *
+PyThreadState_GetInterpreter(PyThreadState *tstate)
+{
+ assert(tstate != NULL);
+ return tstate->interp;
+}
+#endif
+
+
+// bpo-40429 added PyThreadState_GetFrame() to Python 3.9.0b1
+#if PY_VERSION_HEX < 0x030900B1
+static inline PyFrameObject*
+PyThreadState_GetFrame(PyThreadState *tstate)
+{
+ PyFrameObject *frame;
+ assert(tstate != NULL);
+ frame = tstate->frame;
+ Py_XINCREF(frame);
+ return frame;
+}
+#endif
+
+static inline PyFrameObject*
+_PyThreadState_GetFrameBorrow(PyThreadState *tstate)
+{
+ PyFrameObject *frame = PyThreadState_GetFrame(tstate);
+ Py_XDECREF(frame);
+ return frame; // borrowed reference
+}
+
+
+// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a5
+#if PY_VERSION_HEX < 0x030900A5
+static inline PyInterpreterState *
+PyInterpreterState_Get(void)
+{
+ PyThreadState *tstate;
+ PyInterpreterState *interp;
+
+ tstate = PyThreadState_GET();
+ if (tstate == NULL) {
+ Py_FatalError("GIL released (tstate is NULL)");
+ }
+ interp = tstate->interp;
+ if (interp == NULL) {
+ Py_FatalError("no current interpreter");
+ }
+ return interp;
+}
+#endif
+
+
+// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a6
+#if 0x030700A1 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030900A6
+static inline uint64_t
+PyThreadState_GetID(PyThreadState *tstate)
+{
+ assert(tstate != NULL);
+ return tstate->id;
+}
+#endif
+
+
+// bpo-37194 added PyObject_CallNoArgs() to Python 3.9.0a1
+#if PY_VERSION_HEX < 0x030900A1
+static inline PyObject*
+PyObject_CallNoArgs(PyObject *func)
+{
+ return PyObject_CallFunctionObjArgs(func, NULL);
+}
+#endif
+
+
+// bpo-39245 made PyObject_CallOneArg() public (previously called
+// _PyObject_CallOneArg) in Python 3.9.0a4
+#if PY_VERSION_HEX < 0x030900A4
+static inline PyObject*
+PyObject_CallOneArg(PyObject *func, PyObject *arg)
+{
+ return PyObject_CallFunctionObjArgs(func, arg, NULL);
+}
+#endif
+
+
+// bpo-40024 added PyModule_AddType() to Python 3.9.0a5
+#if PY_VERSION_HEX < 0x030900A5
+static inline int
+PyModule_AddType(PyObject *module, PyTypeObject *type)
+{
+ const char *name, *dot;
+
+ if (PyType_Ready(type) < 0) {
+ return -1;
+ }
+
+ // inline _PyType_Name()
+ name = type->tp_name;
+ assert(name != NULL);
+ 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
+
+
+// bpo-40241 added PyObject_GC_IsTracked() to Python 3.9.0a6.
+// bpo-4688 added _PyObject_GC_IS_TRACKED() to Python 2.7.0a2.
+#if PY_VERSION_HEX < 0x030900A6
+static inline int
+PyObject_GC_IsTracked(PyObject* obj)
+{
+ return (PyObject_IS_GC(obj) && _PyObject_GC_IS_TRACKED(obj));
+}
+#endif
+
+// bpo-40241 added PyObject_GC_IsFinalized() to Python 3.9.0a6.
+// bpo-18112 added _PyGCHead_FINALIZED() to Python 3.4.0 final.
+#if PY_VERSION_HEX < 0x030900A6 && PY_VERSION_HEX >= 0x030400F0
+static inline int
+PyObject_GC_IsFinalized(PyObject *obj)
+{
+ return (PyObject_IS_GC(obj) && _PyGCHead_FINALIZED((PyGC_Head *)(obj)-1));
+}
+#endif
+
+
+// bpo-39573 added Py_IS_TYPE() to Python 3.9.0a4
+#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_IS_TYPE)
+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
--- a/mercurial/cext/osutil.c Wed Jan 20 14:47:13 2021 +0100
+++ b/mercurial/cext/osutil.c Mon Dec 14 10:44:29 2020 +0100
@@ -119,7 +119,7 @@
static void listdir_stat_dealloc(PyObject *o)
{
- o->ob_type->tp_free(o);
+ Py_TYPE(o)->tp_free(o);
}
static PyObject *listdir_stat_getitem(PyObject *self, PyObject *key)
--- a/mercurial/cext/pathencode.c Wed Jan 20 14:47:13 2021 +0100
+++ b/mercurial/cext/pathencode.c Mon Dec 14 10:44:29 2020 +0100
@@ -21,6 +21,7 @@
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
+#include "pythoncapi_compat.h"
#include "util.h"
@@ -678,7 +679,7 @@
}
assert(PyBytes_Check(ret));
- Py_SIZE(ret) = destlen;
+ Py_SET_SIZE(ret, destlen);
return ret;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/pythoncapi_compat.h Mon Dec 14 10:44:29 2020 +0100
@@ -0,0 +1,278 @@
+// Header file providing new functions of the Python C API to old Python
+// versions.
+//
+// File distributed under the MIT license.
+//
+// Homepage:
+// https://github.com/pythoncapi/pythoncapi_compat
+//
+// Latest version:
+// https://raw.githubusercontent.com/pythoncapi/pythoncapi_compat/master/pythoncapi_compat.h
+
+#ifndef PYTHONCAPI_COMPAT
+#define PYTHONCAPI_COMPAT
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <Python.h>
+#include "frameobject.h" // PyFrameObject, PyFrame_GetBack()
+
+
+// Cast argument to PyObject* type.
+#ifndef _PyObject_CAST
+# define _PyObject_CAST(op) ((PyObject*)(op))
+#endif
+
+
+// bpo-42262 added Py_NewRef() to Python 3.10.0a3
+#if PY_VERSION_HEX < 0x030a00A3 && !defined(Py_NewRef)
+static inline PyObject* _Py_NewRef(PyObject *obj)
+{
+ Py_INCREF(obj);
+ return obj;
+}
+#define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj))
+#endif
+
+
+// bpo-42262 added Py_XNewRef() to Python 3.10.0a3
+#if PY_VERSION_HEX < 0x030a00A3 && !defined(Py_XNewRef)
+static inline PyObject* _Py_XNewRef(PyObject *obj)
+{
+ Py_XINCREF(obj);
+ return obj;
+}
+#define Py_XNewRef(obj) _Py_XNewRef(_PyObject_CAST(obj))
+#endif
+
+
+// bpo-39573 added Py_SET_REFCNT() to Python 3.9.0a4
+#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_REFCNT)
+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)
+#endif
+
+
+// bpo-39573 added Py_SET_TYPE() to Python 3.9.0a4
+#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE)
+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)
+#endif
+
+
+// bpo-39573 added Py_SET_SIZE() to Python 3.9.0a4
+#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_SIZE)
+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
+
+
+// bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1
+#if PY_VERSION_HEX < 0x030900B1
+static inline PyCodeObject*
+PyFrame_GetCode(PyFrameObject *frame)
+{
+ PyCodeObject *code;
+ assert(frame != NULL);
+ code = frame->f_code;
+ assert(code != NULL);
+ Py_INCREF(code);
+ return code;
+}
+#endif
+
+static inline PyCodeObject*
+_PyFrame_GetCodeBorrow(PyFrameObject *frame)
+{
+ PyCodeObject *code = PyFrame_GetCode(frame);
+ Py_DECREF(code);
+ return code; // borrowed reference
+}
+
+
+// bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1
+#if PY_VERSION_HEX < 0x030900B1
+static inline PyFrameObject*
+PyFrame_GetBack(PyFrameObject *frame)
+{
+ PyFrameObject *back;
+ assert(frame != NULL);
+ back = frame->f_back;
+ Py_XINCREF(back);
+ return back;
+}
+#endif
+
+static inline PyFrameObject*
+_PyFrame_GetBackBorrow(PyFrameObject *frame)
+{
+ PyFrameObject *back = PyFrame_GetBack(frame);
+ Py_XDECREF(back);
+ return back; // borrowed reference
+}
+
+
+// bpo-39947 added PyThreadState_GetInterpreter() to Python 3.9.0a5
+#if PY_VERSION_HEX < 0x030900A5
+static inline PyInterpreterState *
+PyThreadState_GetInterpreter(PyThreadState *tstate)
+{
+ assert(tstate != NULL);
+ return tstate->interp;
+}
+#endif
+
+
+// bpo-40429 added PyThreadState_GetFrame() to Python 3.9.0b1
+#if PY_VERSION_HEX < 0x030900B1
+static inline PyFrameObject*
+PyThreadState_GetFrame(PyThreadState *tstate)
+{
+ PyFrameObject *frame;
+ assert(tstate != NULL);
+ frame = tstate->frame;
+ Py_XINCREF(frame);
+ return frame;
+}
+#endif
+
+static inline PyFrameObject*
+_PyThreadState_GetFrameBorrow(PyThreadState *tstate)
+{
+ PyFrameObject *frame = PyThreadState_GetFrame(tstate);
+ Py_XDECREF(frame);
+ return frame; // borrowed reference
+}
+
+
+// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a5
+#if PY_VERSION_HEX < 0x030900A5
+static inline PyInterpreterState *
+PyInterpreterState_Get(void)
+{
+ PyThreadState *tstate;
+ PyInterpreterState *interp;
+
+ tstate = PyThreadState_GET();
+ if (tstate == NULL) {
+ Py_FatalError("GIL released (tstate is NULL)");
+ }
+ interp = tstate->interp;
+ if (interp == NULL) {
+ Py_FatalError("no current interpreter");
+ }
+ return interp;
+}
+#endif
+
+
+// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a6
+#if 0x030700A1 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030900A6
+static inline uint64_t
+PyThreadState_GetID(PyThreadState *tstate)
+{
+ assert(tstate != NULL);
+ return tstate->id;
+}
+#endif
+
+
+// bpo-37194 added PyObject_CallNoArgs() to Python 3.9.0a1
+#if PY_VERSION_HEX < 0x030900A1
+static inline PyObject*
+PyObject_CallNoArgs(PyObject *func)
+{
+ return PyObject_CallFunctionObjArgs(func, NULL);
+}
+#endif
+
+
+// bpo-39245 made PyObject_CallOneArg() public (previously called
+// _PyObject_CallOneArg) in Python 3.9.0a4
+#if PY_VERSION_HEX < 0x030900A4
+static inline PyObject*
+PyObject_CallOneArg(PyObject *func, PyObject *arg)
+{
+ return PyObject_CallFunctionObjArgs(func, arg, NULL);
+}
+#endif
+
+
+// bpo-40024 added PyModule_AddType() to Python 3.9.0a5
+#if PY_VERSION_HEX < 0x030900A5
+static inline int
+PyModule_AddType(PyObject *module, PyTypeObject *type)
+{
+ const char *name, *dot;
+
+ if (PyType_Ready(type) < 0) {
+ return -1;
+ }
+
+ // inline _PyType_Name()
+ name = type->tp_name;
+ assert(name != NULL);
+ 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
+
+
+// bpo-40241 added PyObject_GC_IsTracked() to Python 3.9.0a6.
+// bpo-4688 added _PyObject_GC_IS_TRACKED() to Python 2.7.0a2.
+#if PY_VERSION_HEX < 0x030900A6
+static inline int
+PyObject_GC_IsTracked(PyObject* obj)
+{
+ return (PyObject_IS_GC(obj) && _PyObject_GC_IS_TRACKED(obj));
+}
+#endif
+
+// bpo-40241 added PyObject_GC_IsFinalized() to Python 3.9.0a6.
+// bpo-18112 added _PyGCHead_FINALIZED() to Python 3.4.0 final.
+#if PY_VERSION_HEX < 0x030900A6 && PY_VERSION_HEX >= 0x030400F0
+static inline int
+PyObject_GC_IsFinalized(PyObject *obj)
+{
+ return (PyObject_IS_GC(obj) && _PyGCHead_FINALIZED((PyGC_Head *)(obj)-1));
+}
+#endif
+
+
+// bpo-39573 added Py_IS_TYPE() to Python 3.9.0a4
+#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_IS_TYPE)
+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
--- a/tests/test-check-code.t Wed Jan 20 14:47:13 2021 +0100
+++ b/tests/test-check-code.t Mon Dec 14 10:44:29 2020 +0100
@@ -11,6 +11,7 @@
> -X contrib/python-zstandard \
> -X hgext/fsmonitor/pywatchman \
> -X mercurial/thirdparty \
+ > -X mercurial/pythoncapi_compat.h \
> | sed 's-\\-/-g' | "$check_code" --warnings --per-file=0 - || false
Skipping contrib/automation/hgautomation/__init__.py it has no-che?k-code (glob)
Skipping contrib/automation/hgautomation/aws.py it has no-che?k-code (glob)