1// Header file providing new C API functions to old Python versions.
2//
3// File distributed under the Zero Clause BSD (0BSD) license.
4// Copyright Contributors to the pythoncapi_compat project.
5//
6// Homepage:
7// https://github.com/python/pythoncapi_compat
8//
9// Latest version:
10// https://raw.githubusercontent.com/python/pythoncapi_compat/master/pythoncapi_compat.h
11//
12// SPDX-License-Identifier: 0BSD
13
14#ifndef PYTHONCAPI_COMPAT
15#define PYTHONCAPI_COMPAT
16
17#ifdef __cplusplus
18extern "C" {
19#endif
20
21#include <Python.h>
22#include "frameobject.h" // PyFrameObject, PyFrame_GetBack()
23
24
25// Compatibility with Visual Studio 2013 and older which don't support
26// the inline keyword in C (only in C++): use __inline instead.
27#if (defined(_MSC_VER) && _MSC_VER < 1900 \
28 && !defined(__cplusplus) && !defined(inline))
29# define PYCAPI_COMPAT_STATIC_INLINE(TYPE) static __inline TYPE
30#else
31# define PYCAPI_COMPAT_STATIC_INLINE(TYPE) static inline TYPE
32#endif
33
34
35#ifndef _Py_CAST
36# define _Py_CAST(type, expr) ((type)(expr))
37#endif
38
39// On C++11 and newer, _Py_NULL is defined as nullptr on C++11,
40// otherwise it is defined as NULL.
41#ifndef _Py_NULL
42# if defined(__cplusplus) && __cplusplus >= 201103
43# define _Py_NULL nullptr
44# else
45# define _Py_NULL NULL
46# endif
47#endif
48
49// Cast argument to PyObject* type.
50#ifndef _PyObject_CAST
51# define _PyObject_CAST(op) _Py_CAST(PyObject*, op)
52#endif
53
54
55// bpo-42262 added Py_NewRef() to Python 3.10.0a3
56#if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_NewRef)
57PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
58_Py_NewRef(PyObject *obj)
59{
60 Py_INCREF(obj);
61 return obj;
62}
63#define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj))
64#endif
65
66
67// bpo-42262 added Py_XNewRef() to Python 3.10.0a3
68#if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_XNewRef)
69PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
70_Py_XNewRef(PyObject *obj)
71{
72 Py_XINCREF(obj);
73 return obj;
74}
75#define Py_XNewRef(obj) _Py_XNewRef(_PyObject_CAST(obj))
76#endif
77
78
79// bpo-39573 added Py_SET_REFCNT() to Python 3.9.0a4
80#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_REFCNT)
81PYCAPI_COMPAT_STATIC_INLINE(void)
82_Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt)
83{
84 ob->ob_refcnt = refcnt;
85}
86#define Py_SET_REFCNT(ob, refcnt) _Py_SET_REFCNT(_PyObject_CAST(ob), refcnt)
87#endif
88
89
90// Py_SETREF() and Py_XSETREF() were added to Python 3.5.2.
91// It is excluded from the limited C API.
92#if (PY_VERSION_HEX < 0x03050200 && !defined(Py_SETREF)) && !defined(Py_LIMITED_API)
93#define Py_SETREF(dst, src) \
94 do { \
95 PyObject **_tmp_dst_ptr = _Py_CAST(PyObject**, &(dst)); \
96 PyObject *_tmp_dst = (*_tmp_dst_ptr); \
97 *_tmp_dst_ptr = _PyObject_CAST(src); \
98 Py_DECREF(_tmp_dst); \
99 } while (0)
100
101#define Py_XSETREF(dst, src) \
102 do { \
103 PyObject **_tmp_dst_ptr = _Py_CAST(PyObject**, &(dst)); \
104 PyObject *_tmp_dst = (*_tmp_dst_ptr); \
105 *_tmp_dst_ptr = _PyObject_CAST(src); \
106 Py_XDECREF(_tmp_dst); \
107 } while (0)
108#endif
109
110
111// bpo-43753 added Py_Is(), Py_IsNone(), Py_IsTrue() and Py_IsFalse()
112// to Python 3.10.0b1.
113#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_Is)
114# define Py_Is(x, y) ((x) == (y))
115#endif
116#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_IsNone)
117# define Py_IsNone(x) Py_Is(x, Py_None)
118#endif
119#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_IsTrue)
120# define Py_IsTrue(x) Py_Is(x, Py_True)
121#endif
122#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_IsFalse)
123# define Py_IsFalse(x) Py_Is(x, Py_False)
124#endif
125
126
127// bpo-39573 added Py_SET_TYPE() to Python 3.9.0a4
128#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE)
129PYCAPI_COMPAT_STATIC_INLINE(void)
130_Py_SET_TYPE(PyObject *ob, PyTypeObject *type)
131{
132 ob->ob_type = type;
133}
134#define Py_SET_TYPE(ob, type) _Py_SET_TYPE(_PyObject_CAST(ob), type)
135#endif
136
137
138// bpo-39573 added Py_SET_SIZE() to Python 3.9.0a4
139#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_SIZE)
140PYCAPI_COMPAT_STATIC_INLINE(void)
141_Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size)
142{
143 ob->ob_size = size;
144}
145#define Py_SET_SIZE(ob, size) _Py_SET_SIZE((PyVarObject*)(ob), size)
146#endif
147
148
149// bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1
150#if PY_VERSION_HEX < 0x030900B1 || defined(PYPY_VERSION)
151PYCAPI_COMPAT_STATIC_INLINE(PyCodeObject*)
152PyFrame_GetCode(PyFrameObject *frame)
153{
154 assert(frame != _Py_NULL);
155 assert(frame->f_code != _Py_NULL);
156 return _Py_CAST(PyCodeObject*, Py_NewRef(frame->f_code));
157}
158#endif
159
160PYCAPI_COMPAT_STATIC_INLINE(PyCodeObject*)
161_PyFrame_GetCodeBorrow(PyFrameObject *frame)
162{
163 PyCodeObject *code = PyFrame_GetCode(frame);
164 Py_DECREF(code);
165 return code;
166}
167
168
169// bpo-40421 added PyFrame_GetBack() to Python 3.9.0b1
170#if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION)
171PYCAPI_COMPAT_STATIC_INLINE(PyFrameObject*)
172PyFrame_GetBack(PyFrameObject *frame)
173{
174 assert(frame != _Py_NULL);
175 return _Py_CAST(PyFrameObject*, Py_XNewRef(frame->f_back));
176}
177#endif
178
179#if !defined(PYPY_VERSION)
180PYCAPI_COMPAT_STATIC_INLINE(PyFrameObject*)
181_PyFrame_GetBackBorrow(PyFrameObject *frame)
182{
183 PyFrameObject *back = PyFrame_GetBack(frame);
184 Py_XDECREF(back);
185 return back;
186}
187#endif
188
189
190// bpo-40421 added PyFrame_GetLocals() to Python 3.11.0a7
191#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION)
192PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
193PyFrame_GetLocals(PyFrameObject *frame)
194{
195#if PY_VERSION_HEX >= 0x030400B1
196 if (PyFrame_FastToLocalsWithError(frame) < 0) {
197 return NULL;
198 }
199#else
200 PyFrame_FastToLocals(frame);
201#endif
202 return Py_NewRef(frame->f_locals);
203}
204#endif
205
206
207// bpo-40421 added PyFrame_GetGlobals() to Python 3.11.0a7
208#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION)
209PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
210PyFrame_GetGlobals(PyFrameObject *frame)
211{
212 return Py_NewRef(frame->f_globals);
213}
214#endif
215
216
217// bpo-40421 added PyFrame_GetBuiltins() to Python 3.11.0a7
218#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION)
219PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
220PyFrame_GetBuiltins(PyFrameObject *frame)
221{
222 return Py_NewRef(frame->f_builtins);
223}
224#endif
225
226
227// bpo-40421 added PyFrame_GetLasti() to Python 3.11.0b1
228#if PY_VERSION_HEX < 0x030B00B1 && !defined(PYPY_VERSION)
229PYCAPI_COMPAT_STATIC_INLINE(int)
230PyFrame_GetLasti(PyFrameObject *frame)
231{
232#if PY_VERSION_HEX >= 0x030A00A7
233 // bpo-27129: Since Python 3.10.0a7, f_lasti is an instruction offset,
234 // not a bytes offset anymore. Python uses 16-bit "wordcode" (2 bytes)
235 // instructions.
236 if (frame->f_lasti < 0) {
237 return -1;
238 }
239 return frame->f_lasti * 2;
240#else
241 return frame->f_lasti;
242#endif
243}
244#endif
245
246
247// gh-91248 added PyFrame_GetVar() to Python 3.12.0a2
248#if PY_VERSION_HEX < 0x030C00A2 && !defined(PYPY_VERSION)
249PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
250PyFrame_GetVar(PyFrameObject *frame, PyObject *name)
251{
252 PyObject *locals, *value;
253
254 locals = PyFrame_GetLocals(frame);
255 if (locals == NULL) {
256 return NULL;
257 }
258#if PY_VERSION_HEX >= 0x03000000
259 value = PyDict_GetItemWithError(locals, name);
260#else
261 value = PyDict_GetItem(locals, name);
262#endif
263 Py_DECREF(locals);
264
265 if (value == NULL) {
266 if (PyErr_Occurred()) {
267 return NULL;
268 }
269#if PY_VERSION_HEX >= 0x03000000
270 PyErr_Format(PyExc_NameError, "variable %R does not exist", name);
271#else
272 PyErr_SetString(PyExc_NameError, "variable does not exist");
273#endif
274 return NULL;
275 }
276 return Py_NewRef(value);
277}
278#endif
279
280
281// gh-91248 added PyFrame_GetVarString() to Python 3.12.0a2
282#if PY_VERSION_HEX < 0x030C00A2 && !defined(PYPY_VERSION)
283PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
284PyFrame_GetVarString(PyFrameObject *frame, const char *name)
285{
286 PyObject *name_obj, *value;
287 name_obj = PyUnicode_FromString(name);
288 if (name_obj == NULL) {
289 return NULL;
290 }
291 value = PyFrame_GetVar(frame, name_obj);
292 Py_DECREF(name_obj);
293 return value;
294}
295#endif
296
297
298// bpo-39947 added PyThreadState_GetInterpreter() to Python 3.9.0a5
299#if PY_VERSION_HEX < 0x030900A5 || defined(PYPY_VERSION)
300PYCAPI_COMPAT_STATIC_INLINE(PyInterpreterState *)
301PyThreadState_GetInterpreter(PyThreadState *tstate)
302{
303 assert(tstate != _Py_NULL);
304 return tstate->interp;
305}
306#endif
307
308
309// bpo-40429 added PyThreadState_GetFrame() to Python 3.9.0b1
310#if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION)
311PYCAPI_COMPAT_STATIC_INLINE(PyFrameObject*)
312PyThreadState_GetFrame(PyThreadState *tstate)
313{
314 assert(tstate != _Py_NULL);
315 return _Py_CAST(PyFrameObject *, Py_XNewRef(tstate->frame));
316}
317#endif
318
319#if !defined(PYPY_VERSION)
320PYCAPI_COMPAT_STATIC_INLINE(PyFrameObject*)
321_PyThreadState_GetFrameBorrow(PyThreadState *tstate)
322{
323 PyFrameObject *frame = PyThreadState_GetFrame(tstate);
324 Py_XDECREF(frame);
325 return frame;
326}
327#endif
328
329
330// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a5
331#if PY_VERSION_HEX < 0x030900A5 || defined(PYPY_VERSION)
332PYCAPI_COMPAT_STATIC_INLINE(PyInterpreterState*)
333PyInterpreterState_Get(void)
334{
335 PyThreadState *tstate;
336 PyInterpreterState *interp;
337
338 tstate = PyThreadState_GET();
339 if (tstate == _Py_NULL) {
340 Py_FatalError("GIL released (tstate is NULL)");
341 }
342 interp = tstate->interp;
343 if (interp == _Py_NULL) {
344 Py_FatalError("no current interpreter");
345 }
346 return interp;
347}
348#endif
349
350
351// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a6
352#if 0x030700A1 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION)
353PYCAPI_COMPAT_STATIC_INLINE(uint64_t)
354PyThreadState_GetID(PyThreadState *tstate)
355{
356 assert(tstate != _Py_NULL);
357 return tstate->id;
358}
359#endif
360
361// bpo-43760 added PyThreadState_EnterTracing() to Python 3.11.0a2
362#if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION)
363PYCAPI_COMPAT_STATIC_INLINE(void)
364PyThreadState_EnterTracing(PyThreadState *tstate)
365{
366 tstate->tracing++;
367#if PY_VERSION_HEX >= 0x030A00A1
368 tstate->cframe->use_tracing = 0;
369#else
370 tstate->use_tracing = 0;
371#endif
372}
373#endif
374
375// bpo-43760 added PyThreadState_LeaveTracing() to Python 3.11.0a2
376#if PY_VERSION_HEX < 0x030B00A2 && !defined(PYPY_VERSION)
377PYCAPI_COMPAT_STATIC_INLINE(void)
378PyThreadState_LeaveTracing(PyThreadState *tstate)
379{
380 int use_tracing = (tstate->c_tracefunc != _Py_NULL
381 || tstate->c_profilefunc != _Py_NULL);
382 tstate->tracing--;
383#if PY_VERSION_HEX >= 0x030A00A1
384 tstate->cframe->use_tracing = use_tracing;
385#else
386 tstate->use_tracing = use_tracing;
387#endif
388}
389#endif
390
391
392// bpo-37194 added PyObject_CallNoArgs() to Python 3.9.0a1
393#if PY_VERSION_HEX < 0x030900A1 || defined(PYPY_VERSION)
394PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
395PyObject_CallNoArgs(PyObject *func)
396{
397 return PyObject_CallFunctionObjArgs(func, NULL);
398}
399#endif
400
401
402// bpo-39245 made PyObject_CallOneArg() public (previously called
403// _PyObject_CallOneArg) in Python 3.9.0a4
404#if PY_VERSION_HEX < 0x030900A4 || defined(PYPY_VERSION)
405PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
406PyObject_CallOneArg(PyObject *func, PyObject *arg)
407{
408 return PyObject_CallFunctionObjArgs(func, arg, NULL);
409}
410#endif
411
412
413// bpo-1635741 added PyModule_AddObjectRef() to Python 3.10.0a3
414#if PY_VERSION_HEX < 0x030A00A3
415PYCAPI_COMPAT_STATIC_INLINE(int)
416PyModule_AddObjectRef(PyObject *module, const char *name, PyObject *value)
417{
418 int res;
419 Py_XINCREF(value);
420 res = PyModule_AddObject(module, name, value);
421 if (res < 0) {
422 Py_XDECREF(value);
423 }
424 return res;
425}
426#endif
427
428
429// bpo-40024 added PyModule_AddType() to Python 3.9.0a5
430#if PY_VERSION_HEX < 0x030900A5
431PYCAPI_COMPAT_STATIC_INLINE(int)
432PyModule_AddType(PyObject *module, PyTypeObject *type)
433{
434 const char *name, *dot;
435
436 if (PyType_Ready(type) < 0) {
437 return -1;
438 }
439
440 // inline _PyType_Name()
441 name = type->tp_name;
442 assert(name != _Py_NULL);
443 dot = strrchr(name, '.');
444 if (dot != _Py_NULL) {
445 name = dot + 1;
446 }
447
448 return PyModule_AddObjectRef(module, name, _PyObject_CAST(type));
449}
450#endif
451
452
453// bpo-40241 added PyObject_GC_IsTracked() to Python 3.9.0a6.
454// bpo-4688 added _PyObject_GC_IS_TRACKED() to Python 2.7.0a2.
455#if PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION)
456PYCAPI_COMPAT_STATIC_INLINE(int)
457PyObject_GC_IsTracked(PyObject* obj)
458{
459 return (PyObject_IS_GC(obj) && _PyObject_GC_IS_TRACKED(obj));
460}
461#endif
462
463// bpo-40241 added PyObject_GC_IsFinalized() to Python 3.9.0a6.
464// bpo-18112 added _PyGCHead_FINALIZED() to Python 3.4.0 final.
465#if PY_VERSION_HEX < 0x030900A6 && PY_VERSION_HEX >= 0x030400F0 && !defined(PYPY_VERSION)
466PYCAPI_COMPAT_STATIC_INLINE(int)
467PyObject_GC_IsFinalized(PyObject *obj)
468{
469 PyGC_Head *gc = _Py_CAST(PyGC_Head*, obj) - 1;
470 return (PyObject_IS_GC(obj) && _PyGCHead_FINALIZED(gc));
471}
472#endif
473
474
475// bpo-39573 added Py_IS_TYPE() to Python 3.9.0a4
476#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_IS_TYPE)
477PYCAPI_COMPAT_STATIC_INLINE(int)
478_Py_IS_TYPE(PyObject *ob, PyTypeObject *type) {
479 return Py_TYPE(ob) == type;
480}
481#define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST(ob), type)
482#endif
483
484
485// bpo-46906 added PyFloat_Pack2() and PyFloat_Unpack2() to Python 3.11a7.
486// bpo-11734 added _PyFloat_Pack2() and _PyFloat_Unpack2() to Python 3.6.0b1.
487// Python 3.11a2 moved _PyFloat_Pack2() and _PyFloat_Unpack2() to the internal
488// C API: Python 3.11a2-3.11a6 versions are not supported.
489#if 0x030600B1 <= PY_VERSION_HEX && PY_VERSION_HEX <= 0x030B00A1 && !defined(PYPY_VERSION)
490PYCAPI_COMPAT_STATIC_INLINE(int)
491PyFloat_Pack2(double x, char *p, int le)
492{ return _PyFloat_Pack2(x, (unsigned char*)p, le); }
493
494PYCAPI_COMPAT_STATIC_INLINE(double)
495PyFloat_Unpack2(const char *p, int le)
496{ return _PyFloat_Unpack2((const unsigned char *)p, le); }
497#endif
498
499
500// bpo-46906 added PyFloat_Pack4(), PyFloat_Pack8(), PyFloat_Unpack4() and
501// PyFloat_Unpack8() to Python 3.11a7.
502// Python 3.11a2 moved _PyFloat_Pack4(), _PyFloat_Pack8(), _PyFloat_Unpack4()
503// and _PyFloat_Unpack8() to the internal C API: Python 3.11a2-3.11a6 versions
504// are not supported.
505#if PY_VERSION_HEX <= 0x030B00A1 && !defined(PYPY_VERSION)
506PYCAPI_COMPAT_STATIC_INLINE(int)
507PyFloat_Pack4(double x, char *p, int le)
508{ return _PyFloat_Pack4(x, (unsigned char*)p, le); }
509
510PYCAPI_COMPAT_STATIC_INLINE(int)
511PyFloat_Pack8(double x, char *p, int le)
512{ return _PyFloat_Pack8(x, (unsigned char*)p, le); }
513
514PYCAPI_COMPAT_STATIC_INLINE(double)
515PyFloat_Unpack4(const char *p, int le)
516{ return _PyFloat_Unpack4((const unsigned char *)p, le); }
517
518PYCAPI_COMPAT_STATIC_INLINE(double)
519PyFloat_Unpack8(const char *p, int le)
520{ return _PyFloat_Unpack8((const unsigned char *)p, le); }
521#endif
522
523
524// gh-92154 added PyCode_GetCode() to Python 3.11.0b1
525#if PY_VERSION_HEX < 0x030B00B1 && !defined(PYPY_VERSION)
526PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
527PyCode_GetCode(PyCodeObject *code)
528{
529 return Py_NewRef(code->co_code);
530}
531#endif
532
533
534// gh-95008 added PyCode_GetVarnames() to Python 3.11.0rc1
535#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION)
536PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
537PyCode_GetVarnames(PyCodeObject *code)
538{
539 return Py_NewRef(code->co_varnames);
540}
541#endif
542
543// gh-95008 added PyCode_GetFreevars() to Python 3.11.0rc1
544#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION)
545PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
546PyCode_GetFreevars(PyCodeObject *code)
547{
548 return Py_NewRef(code->co_freevars);
549}
550#endif
551
552// gh-95008 added PyCode_GetCellvars() to Python 3.11.0rc1
553#if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION)
554PYCAPI_COMPAT_STATIC_INLINE(PyObject*)
555PyCode_GetCellvars(PyCodeObject *code)
556{
557 return Py_NewRef(code->co_cellvars);
558}
559#endif
560
561
562// Py_UNUSED() was added to Python 3.4.0b2.
563#if PY_VERSION_HEX < 0x030400B2 && !defined(Py_UNUSED)
564# if defined(__GNUC__) || defined(__clang__)
565# define Py_UNUSED(name) _unused_ ## name __attribute__((unused))
566# else
567# define Py_UNUSED(name) _unused_ ## name
568# endif
569#endif
570
571
572#ifdef __cplusplus
573}
574#endif
575#endif // PYTHONCAPI_COMPAT