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
61typedef 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#ifndef Py_TYPE
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
123typedef 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#ifndef PyCFunction_CheckExact
221# define PyCFunction_CheckExact(op) (Py_TYPE(op) == &PyCFunction_Type)
222#endif
223
224#if PY_VERSION_HEX < 0x03090000
225INLINE EXPCL_PYPANDA PyObject *PyObject_CallNoArgs(PyObject *func) {
226 return _PyObject_CallNoArg(func);
227}
228
229INLINE PyObject *PyObject_CallOneArg(PyObject *callable, PyObject *arg) {
230#if PY_VERSION_HEX >= 0x03060000
231 return _PyObject_FastCall(callable, &arg, 1);
232#else
233 return PyObject_CallFunctionObjArgs(callable, arg, nullptr);
234#endif
235}
236
237INLINE PyObject *PyObject_CallMethodNoArgs(PyObject *obj, PyObject *name) {
238 return PyObject_CallMethodObjArgs(obj, name, nullptr);
239}
240
241INLINE PyObject *PyObject_CallMethodOneArg(PyObject *obj, PyObject *name, PyObject *arg) {
242 return PyObject_CallMethodObjArgs(obj, name, arg, nullptr);
243}
244#endif
245
246/* Python 3.12 */
247
248#if PY_VERSION_HEX < 0x030C0000
249# define PyLong_IsNonNegative(value) (Py_SIZE((value)) >= 0)
250#else
251INLINE bool PyLong_IsNonNegative(PyObject *value) {
252 int overflow = 0;
253 long longval = PyLong_AsLongAndOverflow(value, &overflow);
254 return overflow == 1 || longval >= 0;
255}
256#endif
257
258/* Other Python implementations */
259
260// _PyErr_OCCURRED is an undocumented macro version of PyErr_Occurred.
261// Some implementations of the CPython API (e.g. PyPy's cpyext) do not define
262// it, so in these cases we just silently fall back to PyErr_Occurred.
263#ifndef _PyErr_OCCURRED
264# define _PyErr_OCCURRED() PyErr_Occurred()
265#endif
266
267#endif // HAVE_PYTHON
268
269#endif // PY_COMPAT_H
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.