Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update pythoncapi_compat.h #93

Merged
merged 1 commit into from
Sep 14, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Update pythoncapi_compat.h
  • Loading branch information
elprans committed Sep 14, 2022
commit 4cab4038b99c6f93ea28882962074dcdc3db972a
208 changes: 142 additions & 66 deletions immutables/pythoncapi_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,29 @@ extern "C" {
// the inline keyword in C (only in C++): use __inline instead.
#if (defined(_MSC_VER) && _MSC_VER < 1900 \
&& !defined(__cplusplus) && !defined(inline))
# define PYCAPI_COMPAT_INLINE(TYPE static __inline TYPE
# define PYCAPI_COMPAT_STATIC_INLINE(TYPE) static __inline TYPE
#else
# define PYCAPI_COMPAT_STATIC_INLINE(TYPE) static inline TYPE
#endif


// C++ compatibility
#ifdef __cplusplus
# define PYCAPI_COMPAT_CAST(TYPE, EXPR) reinterpret_cast<TYPE>(EXPR)
# define PYCAPI_COMPAT_NULL nullptr
#else
# define PYCAPI_COMPAT_CAST(TYPE, EXPR) ((TYPE)(EXPR))
# define PYCAPI_COMPAT_NULL NULL
#ifndef _Py_CAST
# define _Py_CAST(type, expr) ((type)(expr))
#endif

// On C++11 and newer, _Py_NULL is defined as nullptr on C++11,
// otherwise it is defined as NULL.
#ifndef _Py_NULL
# if defined(__cplusplus) && __cplusplus >= 201103
# define _Py_NULL nullptr
# else
# define _Py_NULL NULL
# endif
#endif

// Cast argument to PyObject* type.
#ifndef _PyObject_CAST
# define _PyObject_CAST(op) PYCAPI_COMPAT_CAST(PyObject*, op)
#endif
#ifndef _PyObject_CAST_CONST
# define _PyObject_CAST_CONST(op) PYCAPI_COMPAT_CAST(const PyObject*, op)
# define _PyObject_CAST(op) _Py_CAST(PyObject*, op)
#endif


Expand Down Expand Up @@ -74,30 +76,6 @@ _Py_XNewRef(PyObject *obj)
#endif


// See https://bugs.python.org/issue42522
#if !defined(_Py_StealRef)
PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
__Py_StealRef(PyObject *obj)
{
Py_DECREF(obj);
return obj;
}
#define _Py_StealRef(obj) __Py_StealRef(_PyObject_CAST(obj))
#endif


// See https://bugs.python.org/issue42522
#if !defined(_Py_XStealRef)
PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
__Py_XStealRef(PyObject *obj)
{
Py_XDECREF(obj);
return obj;
}
#define _Py_XStealRef(obj) __Py_XStealRef(_PyObject_CAST(obj))
#endif


// bpo-39573 added Py_SET_REFCNT() to Python 3.9.0a4
#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_REFCNT)
PYCAPI_COMPAT_STATIC_INLINE(void)
Expand Down Expand Up @@ -171,36 +149,95 @@ _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size)
PYCAPI_COMPAT_STATIC_INLINE(PyCodeObject*)
PyFrame_GetCode(PyFrameObject *frame)
{
assert(frame != PYCAPI_COMPAT_NULL);
assert(frame->f_code != PYCAPI_COMPAT_NULL);
return PYCAPI_COMPAT_CAST(PyCodeObject*, Py_NewRef(frame->f_code));
assert(frame != _Py_NULL);
assert(frame->f_code != _Py_NULL);
return _Py_CAST(PyCodeObject*, Py_NewRef(frame->f_code));
}
#endif

PYCAPI_COMPAT_STATIC_INLINE(PyCodeObject*)
_PyFrame_GetCodeBorrow(PyFrameObject *frame)
{
return PYCAPI_COMPAT_CAST(PyCodeObject *,
_Py_StealRef(PyFrame_GetCode(frame)));
PyCodeObject *code = PyFrame_GetCode(frame);
Py_DECREF(code);
return code;
}


// bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1
// bpo-40421 added PyFrame_GetBack() to Python 3.9.0b1
#if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION)
PYCAPI_COMPAT_STATIC_INLINE(PyFrameObject*)
PyFrame_GetBack(PyFrameObject *frame)
{
assert(frame != PYCAPI_COMPAT_NULL);
return PYCAPI_COMPAT_CAST(PyFrameObject*, Py_XNewRef(frame->f_back));
assert(frame != _Py_NULL);
return _Py_CAST(PyFrameObject*, Py_XNewRef(frame->f_back));
}
#endif

#if !defined(PYPY_VERSION)
PYCAPI_COMPAT_STATIC_INLINE(PyFrameObject*)
_PyFrame_GetBackBorrow(PyFrameObject *frame)
{
return PYCAPI_COMPAT_CAST(PyFrameObject *,
_Py_XStealRef(PyFrame_GetBack(frame)));
PyFrameObject *back = PyFrame_GetBack(frame);
Py_XDECREF(back);
return back;
}
#endif


// bpo-40421 added PyFrame_GetLocals() to Python 3.11.0a7
#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION)
PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
PyFrame_GetLocals(PyFrameObject *frame)
{
#if PY_VERSION_HEX >= 0x030400B1
if (PyFrame_FastToLocalsWithError(frame) < 0) {
return NULL;
}
#else
PyFrame_FastToLocals(frame);
#endif
return Py_NewRef(frame->f_locals);
}
#endif


// bpo-40421 added PyFrame_GetGlobals() to Python 3.11.0a7
#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION)
PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
PyFrame_GetGlobals(PyFrameObject *frame)
{
return Py_NewRef(frame->f_globals);
}
#endif


// bpo-40421 added PyFrame_GetBuiltins() to Python 3.11.0a7
#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION)
PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
PyFrame_GetBuiltins(PyFrameObject *frame)
{
return Py_NewRef(frame->f_builtins);
}
#endif


// bpo-40421 added PyFrame_GetLasti() to Python 3.11.0b1
#if PY_VERSION_HEX < 0x030B00B1 && !defined(PYPY_VERSION)
PYCAPI_COMPAT_STATIC_INLINE(int)
PyFrame_GetLasti(PyFrameObject *frame)
{
#if PY_VERSION_HEX >= 0x030A00A7
// bpo-27129: Since Python 3.10.0a7, f_lasti is an instruction offset,
// not a bytes offset anymore. Python uses 16-bit "wordcode" (2 bytes)
// instructions.
if (frame->f_lasti < 0) {
return -1;
}
return frame->f_lasti * 2;
#else
return frame->f_lasti;
#endif
}
#endif

Expand All @@ -210,7 +247,7 @@ _PyFrame_GetBackBorrow(PyFrameObject *frame)
PYCAPI_COMPAT_STATIC_INLINE(PyInterpreterState *)
PyThreadState_GetInterpreter(PyThreadState *tstate)
{
assert(tstate != PYCAPI_COMPAT_NULL);
assert(tstate != _Py_NULL);
return tstate->interp;
}
#endif
Expand All @@ -221,17 +258,18 @@ PyThreadState_GetInterpreter(PyThreadState *tstate)
PYCAPI_COMPAT_STATIC_INLINE(PyFrameObject*)
PyThreadState_GetFrame(PyThreadState *tstate)
{
assert(tstate != PYCAPI_COMPAT_NULL);
return PYCAPI_COMPAT_CAST(PyFrameObject *, Py_XNewRef(tstate->frame));
assert(tstate != _Py_NULL);
return _Py_CAST(PyFrameObject *, Py_XNewRef(tstate->frame));
}
#endif

#if !defined(PYPY_VERSION)
PYCAPI_COMPAT_STATIC_INLINE(PyFrameObject*)
_PyThreadState_GetFrameBorrow(PyThreadState *tstate)
{
return PYCAPI_COMPAT_CAST(PyFrameObject*,
_Py_XStealRef(PyThreadState_GetFrame(tstate)));
PyFrameObject *frame = PyThreadState_GetFrame(tstate);
Py_XDECREF(frame);
return frame;
}
#endif

Expand All @@ -245,11 +283,11 @@ PyInterpreterState_Get(void)
PyInterpreterState *interp;

tstate = PyThreadState_GET();
if (tstate == PYCAPI_COMPAT_NULL) {
if (tstate == _Py_NULL) {
Py_FatalError("GIL released (tstate is NULL)");
}
interp = tstate->interp;
if (interp == PYCAPI_COMPAT_NULL) {
if (interp == _Py_NULL) {
Py_FatalError("no current interpreter");
}
return interp;
Expand All @@ -262,7 +300,7 @@ PyInterpreterState_Get(void)
PYCAPI_COMPAT_STATIC_INLINE(uint64_t)
PyThreadState_GetID(PyThreadState *tstate)
{
assert(tstate != PYCAPI_COMPAT_NULL);
assert(tstate != _Py_NULL);
return tstate->id;
}
#endif
Expand All @@ -286,8 +324,8 @@ PyThreadState_EnterTracing(PyThreadState *tstate)
PYCAPI_COMPAT_STATIC_INLINE(void)
PyThreadState_LeaveTracing(PyThreadState *tstate)
{
int use_tracing = (tstate->c_tracefunc != PYCAPI_COMPAT_NULL
|| tstate->c_profilefunc != PYCAPI_COMPAT_NULL);
int use_tracing = (tstate->c_tracefunc != _Py_NULL
|| tstate->c_profilefunc != _Py_NULL);
tstate->tracing--;
#if PY_VERSION_HEX >= 0x030A00A1
tstate->cframe->use_tracing = use_tracing;
Expand Down Expand Up @@ -322,11 +360,11 @@ PyObject_CallOneArg(PyObject *func, PyObject *arg)
// bpo-1635741 added PyModule_AddObjectRef() to Python 3.10.0a3
#if PY_VERSION_HEX < 0x030A00A3
PYCAPI_COMPAT_STATIC_INLINE(int)
PyModule_AddObjectRef(PyObject *mod, const char *name, PyObject *value)
PyModule_AddObjectRef(PyObject *module, const char *name, PyObject *value)
{
int res;
Py_XINCREF(value);
res = PyModule_AddObject(mod, name, value);
res = PyModule_AddObject(module, name, value);
if (res < 0) {
Py_XDECREF(value);
}
Expand All @@ -338,7 +376,7 @@ PyModule_AddObjectRef(PyObject *mod, const char *name, PyObject *value)
// bpo-40024 added PyModule_AddType() to Python 3.9.0a5
#if PY_VERSION_HEX < 0x030900A5
PYCAPI_COMPAT_STATIC_INLINE(int)
PyModule_AddType(PyObject *mod, PyTypeObject *type)
PyModule_AddType(PyObject *module, PyTypeObject *type)
{
const char *name, *dot;

Expand All @@ -348,13 +386,13 @@ PyModule_AddType(PyObject *mod, PyTypeObject *type)

// inline _PyType_Name()
name = type->tp_name;
assert(name != PYCAPI_COMPAT_NULL);
assert(name != _Py_NULL);
dot = strrchr(name, '.');
if (dot != PYCAPI_COMPAT_NULL) {
if (dot != _Py_NULL) {
name = dot + 1;
}

return PyModule_AddObjectRef(mod, name, _PyObject_CAST(type));
return PyModule_AddObjectRef(module, name, _PyObject_CAST(type));
}
#endif

Expand All @@ -375,7 +413,7 @@ PyObject_GC_IsTracked(PyObject* obj)
PYCAPI_COMPAT_STATIC_INLINE(int)
PyObject_GC_IsFinalized(PyObject *obj)
{
PyGC_Head *gc = PYCAPI_COMPAT_CAST(PyGC_Head *, obj) - 1;
PyGC_Head *gc = _Py_CAST(PyGC_Head*, obj) - 1;
return (PyObject_IS_GC(obj) && _PyGCHead_FINALIZED(gc));
}
#endif
Expand All @@ -384,10 +422,10 @@ PyObject_GC_IsFinalized(PyObject *obj)
// bpo-39573 added Py_IS_TYPE() to Python 3.9.0a4
#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_IS_TYPE)
PYCAPI_COMPAT_STATIC_INLINE(int)
_Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) {
return ob->ob_type == type;
_Py_IS_TYPE(PyObject *ob, PyTypeObject *type) {
return Py_TYPE(ob) == type;
}
#define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST_CONST(ob), type)
#define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST(ob), type)
#endif


Expand Down Expand Up @@ -430,6 +468,44 @@ PyFloat_Unpack8(const char *p, int le)
#endif


// gh-92154 added PyCode_GetCode() to Python 3.11.0b1
#if PY_VERSION_HEX < 0x030B00B1 && !defined(PYPY_VERSION)
PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
PyCode_GetCode(PyCodeObject *code)
{
return Py_NewRef(code->co_code);
}
#endif


// gh-95008 added PyCode_GetVarnames() to Python 3.11.0rc1
#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION)
PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
PyCode_GetVarnames(PyCodeObject *code)
{
return Py_NewRef(code->co_varnames);
}
#endif

// gh-95008 added PyCode_GetFreevars() to Python 3.11.0rc1
#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION)
PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
PyCode_GetFreevars(PyCodeObject *code)
{
return Py_NewRef(code->co_freevars);
}
#endif

// gh-95008 added PyCode_GetCellvars() to Python 3.11.0rc1
#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION)
PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
PyCode_GetCellvars(PyCodeObject *code)
{
return Py_NewRef(code->co_cellvars);
}
#endif


// Py_UNUSED() was added to Python 3.4.0b2.
#if PY_VERSION_HEX < 0x030400B2 && !defined(Py_UNUSED)
# if defined(__GNUC__) || defined(__clang__)
Expand Down