Panda3D

Loading...
Searching...
No Matches
py_compat.h
Go to the documentation of this file.
1/**
2 * @file py_compat.h
3 * @author rdb
4 * @date 2017-12-02
5 */
6
7#ifndef PY_COMPAT_H
8#define PY_COMPAT_H
9
10#include "dtoolbase.h"
11
12#ifdef HAVE_PYTHON
13
14// The contents of this file were originally part of py_panda.h. It
15// specifically contains polyfills that are required to maintain compatibility
16// with Python 2 and older versions of Python 3.
17
18// These compatibility hacks are sorted by Python version that removes the
19// need for the respective hack.
20
21#ifdef _POSIX_C_SOURCE
22# undef _POSIX_C_SOURCE
23#endif
24
25#ifdef _XOPEN_SOURCE
26# undef _XOPEN_SOURCE
27#endif
28
29// See PEP 353
30#define PY_SSIZE_T_CLEAN 1
31
32#include <Python.h>
33
34#ifndef LINK_ALL_STATIC
35# define EXPCL_PYPANDA
36#elif defined(__GNUC__)
37# define EXPCL_PYPANDA __attribute__((weak))
38#else
39# define EXPCL_PYPANDA extern inline
40#endif
41
42/* Python 2.4 */
43
44// 2.4 macros which aren't available in 2.3
45#ifndef Py_RETURN_NONE
46# define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
47#endif
48
49#ifndef Py_RETURN_TRUE
50# define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
51#endif
52
53#ifndef Py_RETURN_FALSE
54# define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
55#endif
56
57/* Python 2.5 */
58
59// Prior to Python 2.5, we didn't have Py_ssize_t.
60#if PY_VERSION_HEX < 0x02050000
61 typedef int Py_ssize_t;
62# define PyInt_FromSsize_t PyInt_FromLong
63# define PyInt_AsSsize_t PyInt_AsLong
64#endif
65
66/* Python 2.6 */
67
68#if PY_VERSION_HEX < 0x02060000
69# define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
70#endif
71
72/* Python 2.7, 3.1 */
73
74#ifndef PyVarObject_HEAD_INIT
75 #define PyVarObject_HEAD_INIT(type, size) \
76 PyObject_HEAD_INIT(type) size,
77#endif
78
79/* Python 2.7, 3.2 */
80
81#if PY_VERSION_HEX < 0x03020000
82# define PyErr_NewExceptionWithDoc(name, doc, base, dict) \
83 PyErr_NewException(name, base, dict)
84#endif
85
86/* Python 3.0 */
87
88// Always on in Python 3
89#ifndef Py_TPFLAGS_CHECKTYPES
90# define Py_TPFLAGS_CHECKTYPES 0
91#endif
92
93// Macros for writing code that will compile in both versions.
94#if PY_MAJOR_VERSION >= 3
95# define nb_nonzero nb_bool
96# define nb_divide nb_true_divide
97# define nb_inplace_divide nb_inplace_true_divide
98
99# define PyLongOrInt_Check(x) PyLong_Check(x)
100# define PyLongOrInt_AS_LONG PyLong_AS_LONG
101# define PyInt_Check PyLong_Check
102# define PyInt_AsLong PyLong_AsLong
103# define PyInt_AS_LONG PyLong_AS_LONG
104# define PyLongOrInt_AsSize_t PyLong_AsSize_t
105#else
106# define PyLongOrInt_Check(x) (PyInt_Check(x) || PyLong_Check(x))
107// PyInt_FromSize_t automatically picks the right type.
108# define PyLongOrInt_AS_LONG PyInt_AsLong
109
110EXPCL_PYPANDA size_t PyLongOrInt_AsSize_t(PyObject *);
111#endif
112
113// Which character to use in PyArg_ParseTuple et al for a byte string.
114#if PY_MAJOR_VERSION >= 3
115# define FMTCHAR_BYTES "y"
116#else
117# define FMTCHAR_BYTES "s"
118#endif
119
120/* Python 3.2 */
121
122#if PY_VERSION_HEX < 0x03020000
123 typedef long Py_hash_t;
124#endif
125
126/* Python 3.3 */
127
128#if PY_MAJOR_VERSION >= 3
129// Python 3 versions before 3.3.3 defined this incorrectly.
130# if PY_VERSION_HEX < 0x03030300
131# undef _PyErr_OCCURRED
132# define _PyErr_OCCURRED() (PyThreadState_GET()->curexc_type)
133# endif
134
135// Python versions before 3.3 did not define this.
136# if PY_VERSION_HEX < 0x03030000
137# define PyUnicode_AsUTF8 _PyUnicode_AsString
138# define PyUnicode_AsUTF8AndSize _PyUnicode_AsStringAndSize
139# endif
140#endif
141
142/* Python 3.4 */
143#if PY_VERSION_HEX < 0x03040000
144#define PyGILState_Check() (PyGILState_GetThisThreadState() == _PyThreadState_Current)
145#endif
146
147/* Python 3.6 */
148
149#if PY_VERSION_HEX < 0x03080000 && !defined(_PyObject_CallNoArg)
150INLINE PyObject *_PyObject_CallNoArg(PyObject *func) {
151 static PyObject *empty_tuple = PyTuple_New(0);
152 return PyObject_Call(func, empty_tuple, nullptr);
153}
154# define _PyObject_CallNoArg _PyObject_CallNoArg
155#endif
156
157#if PY_VERSION_HEX < 0x03080000 && !defined(_PyObject_FastCall)
158INLINE PyObject *_PyObject_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs) {
159 PyObject *tuple = PyTuple_New(nargs);
160 for (Py_ssize_t i = 0; i < nargs; ++i) {
161 PyTuple_SET_ITEM(tuple, i, args[i]);
162 Py_INCREF(args[i]);
163 }
164 PyObject *result = PyObject_Call(func, tuple, nullptr);
165 Py_DECREF(tuple);
166 return result;
167}
168# define _PyObject_FastCall _PyObject_FastCall
169#endif
170
171// Python versions before 3.6 didn't require longlong support to be enabled.
172#ifndef HAVE_LONG_LONG
173# define PyLong_FromLongLong(x) PyLong_FromLong((long) (x))
174# define PyLong_FromUnsignedLongLong(x) PyLong_FromUnsignedLong((unsigned long) (x))
175# define PyLong_AsLongLong(x) PyLong_AsLong(x)
176# define PyLong_AsUnsignedLongLong(x) PyLong_AsUnsignedLong(x)
177# define PyLong_AsUnsignedLongLongMask(x) PyLong_AsUnsignedLongMask(x)
178# define PyLong_AsLongLongAndOverflow(x) PyLong_AsLongAndOverflow(x)
179#endif
180
181/* Python 3.7 */
182
183#ifndef PyDict_GET_SIZE
184# define PyDict_GET_SIZE(mp) (((PyDictObject *)mp)->ma_used)
185#endif
186
187#ifndef Py_RETURN_RICHCOMPARE
188# define Py_RETURN_RICHCOMPARE(val1, val2, op) \
189 do { \
190 switch (op) { \
191 NODEFAULT \
192 case Py_EQ: if ((val1) == (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
193 case Py_NE: if ((val1) != (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
194 case Py_LT: if ((val1) < (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
195 case Py_GT: if ((val1) > (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
196 case Py_LE: if ((val1) <= (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
197 case Py_GE: if ((val1) >= (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
198 } \
199 } while (0)
200#endif
201
202/* Python 3.8 */
203#if PY_VERSION_HEX < 0x03080000
204INLINE PyObject *_PyLong_Rshift(PyObject *a, size_t shiftby) {
205 PyObject *b = PyLong_FromLong(shiftby);
206 PyObject *result = PyNumber_Rshift(a, b);
207 Py_DECREF(b);
208 return result;
209}
210INLINE PyObject *_PyLong_Lshift(PyObject *a, size_t shiftby) {
211 PyObject *b = PyLong_FromLong(shiftby);
212 PyObject *result = PyNumber_Lshift(a, b);
213 Py_DECREF(b);
214 return result;
215}
216#endif
217
218/* Python 3.9 */
219
220#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_IS_TYPE)
221# define Py_IS_TYPE(ob, type) (Py_TYPE((PyObject *)ob) == type)
222#endif
223
224#ifndef PyCFunction_CheckExact
225# define PyCFunction_CheckExact(op) (Py_IS_TYPE(op, &PyCFunction_Type))
226#endif
227
228#if PY_VERSION_HEX < 0x03090000
229INLINE EXPCL_PYPANDA PyObject *PyObject_CallNoArgs(PyObject *func) {
230 return _PyObject_CallNoArg(func);
231}
232
233INLINE PyObject *PyObject_CallOneArg(PyObject *callable, PyObject *arg) {
234#if PY_VERSION_HEX >= 0x03060000
235 return _PyObject_FastCall(callable, &arg, 1);
236#else
237 return PyObject_CallFunctionObjArgs(callable, arg, nullptr);
238#endif
239}
240
241INLINE PyObject *PyObject_CallMethodNoArgs(PyObject *obj, PyObject *name) {
242 return PyObject_CallMethodObjArgs(obj, name, nullptr);
243}
244
245INLINE PyObject *PyObject_CallMethodOneArg(PyObject *obj, PyObject *name, PyObject *arg) {
246 return PyObject_CallMethodObjArgs(obj, name, arg, nullptr);
247}
248#endif
249
250/* Python 3.10 */
251
252#if PY_VERSION_HEX < 0x030A0000
253INLINE int PyModule_AddObjectRef(PyObject *module, const char *name, PyObject *value) {
254 int ret = PyModule_AddObject(module, name, value);
255 if (ret == 0) {
256 Py_INCREF(value);
257 }
258 return ret;
259}
260
261ALWAYS_INLINE PyObject *Py_NewRef(PyObject *obj) {
262 Py_INCREF(obj);
263 return obj;
264}
265
266ALWAYS_INLINE PyObject *Py_XNewRef(PyObject *obj) {
267 Py_XINCREF(obj);
268 return obj;
269}
270#endif
271
272/* Python 3.12 */
273
274#if PY_VERSION_HEX < 0x030C0000
275# define PyLong_IsNonNegative(value) (Py_SIZE((value)) >= 0)
276#else
277INLINE bool PyLong_IsNonNegative(PyObject *value) {
278 int overflow = 0;
279 long longval = PyLong_AsLongAndOverflow(value, &overflow);
280 return overflow == 1 || longval >= 0;
281}
282#endif
283
284/* Python 3.13 */
285
286#if PY_VERSION_HEX < 0x030D00A1
287# define PyLong_AsInt(x) (_PyLong_AsInt(x))
288#endif
289
290#if PY_VERSION_HEX < 0x030D00A1
291ALWAYS_INLINE int
292PyModule_Add(PyObject *mod, const char *name, PyObject *value) {
293 int res = PyModule_AddObjectRef(mod, name, value);
294 Py_XDECREF(value);
295 return res;
296}
297#endif
298
299#if PY_VERSION_HEX < 0x030D00A1
300INLINE int
301PyDict_GetItemRef(PyObject *mp, PyObject *key, PyObject **result) {
302#if PY_MAJOR_VERSION >= 3
303 PyObject *item = PyDict_GetItemWithError(mp, key);
304#else
305 PyObject *item = _PyDict_GetItemWithError(mp, key);
306#endif
307 if (item != nullptr) {
308 *result = Py_NewRef(item);
309 return 1;
310 }
311 *result = nullptr;
312 return PyErr_Occurred() ? -1 : 0;
313}
314
315INLINE int
316PyDict_GetItemStringRef(PyObject *mp, const char *key, PyObject **result) {
317 PyObject *item = nullptr;
318#if PY_MAJOR_VERSION >= 3
319 PyObject *key_obj = PyUnicode_FromString(key);
320 item = key_obj ? PyDict_GetItemWithError(mp, key_obj) : nullptr;
321#else
322 PyObject *key_obj = PyString_FromString(key);
323 item = key_obj ? _PyDict_GetItemWithError(mp, key_obj) : nullptr;
324#endif
325 Py_DECREF(key_obj);
326 if (item != nullptr) {
327 *result = Py_NewRef(item);
328 return 1;
329 }
330 *result = nullptr;
331 return PyErr_Occurred() ? -1 : 0;
332}
333#endif
334
335#if PY_VERSION_HEX >= 0x03050200 && PY_VERSION_HEX < 0x030D00A1
336# define PyThreadState_GetUnchecked() (_PyThreadState_UncheckedGet())
337#endif
338
339#if PY_VERSION_HEX < 0x030D00A2
340# define PyList_Extend(list, iterable) (PyList_SetSlice((list), PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, (iterable)))
341# define PyList_Clear(list) (PyList_SetSlice((list), 0, PY_SSIZE_T_MAX, nullptr))
342#endif
343
344#if PY_VERSION_HEX < 0x030D00A4
345# define PyList_GetItemRef(op, index) (Py_XNewRef(PyList_GetItem((op), (index))))
346#endif
347
348#if PY_VERSION_HEX < 0x030D00B3
349# define Py_BEGIN_CRITICAL_SECTION(op) {
350# define Py_END_CRITICAL_SECTION() }
351# define Py_BEGIN_CRITICAL_SECTION2(a, b) {
352# define Py_END_CRITICAL_SECTION2() }
353#endif
354
355/* Python 3.14 */
356
357#if PY_VERSION_HEX < 0x030E00A8
358# define PyUnstable_Object_IsUniquelyReferenced(op) (Py_REFCNT((op)) == 1)
359#endif
360
361/* Other Python implementations */
362
363// _PyErr_OCCURRED is an undocumented macro version of PyErr_Occurred.
364// Some implementations of the CPython API (e.g. PyPy's cpyext) do not define
365// it, so in these cases we just silently fall back to PyErr_Occurred.
366#ifndef _PyErr_OCCURRED
367# define _PyErr_OCCURRED() PyErr_Occurred()
368#endif
369
370#endif // HAVE_PYTHON
371
372#endif // PY_COMPAT_H
dtoolbase.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.