Skip to content

Commit 45105ec

Browse files
authored
Add Python 3.10 support: use Py_SET_SIZE() (#52)
1 parent 82e5409 commit 45105ec

File tree

2 files changed

+281
-2
lines changed

2 files changed

+281
-2
lines changed

immutables/_map.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <stddef.h> /* For offsetof */
2+
#include "pythoncapi_compat.h"
23
#include "_map.h"
34

45

@@ -571,7 +572,7 @@ map_node_bitmap_new(Py_ssize_t size, uint64_t mutid)
571572
return NULL;
572573
}
573574

574-
Py_SIZE(node) = size;
575+
Py_SET_SIZE(node, size);
575576

576577
for (i = 0; i < size; i++) {
577578
node->b_array[i] = NULL;
@@ -1356,7 +1357,7 @@ map_node_collision_new(int32_t hash, Py_ssize_t size, uint64_t mutid)
13561357
node->c_array[i] = NULL;
13571358
}
13581359

1359-
Py_SIZE(node) = size;
1360+
Py_SET_SIZE(node, size);
13601361
node->c_hash = hash;
13611362

13621363
node->c_mutid = mutid;

immutables/pythoncapi_compat.h

Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
// Header file providing new functions of the Python C API to old Python
2+
// versions.
3+
//
4+
// File distributed under the MIT license.
5+
//
6+
// Homepage:
7+
// https://github.com/pythoncapi/pythoncapi_compat
8+
//
9+
// Latest version:
10+
// https://raw.githubusercontent.com/pythoncapi/pythoncapi_compat/master/pythoncapi_compat.h
11+
12+
#ifndef PYTHONCAPI_COMPAT
13+
#define PYTHONCAPI_COMPAT
14+
15+
#ifdef __cplusplus
16+
extern "C" {
17+
#endif
18+
19+
#include <Python.h>
20+
#include "frameobject.h" // PyFrameObject, PyFrame_GetBack()
21+
22+
23+
// Cast argument to PyObject* type.
24+
#ifndef _PyObject_CAST
25+
# define _PyObject_CAST(op) ((PyObject*)(op))
26+
#endif
27+
28+
29+
// bpo-42262 added Py_NewRef() to Python 3.10.0a3
30+
#if PY_VERSION_HEX < 0x030a00A3 && !defined(Py_NewRef)
31+
static inline PyObject* _Py_NewRef(PyObject *obj)
32+
{
33+
Py_INCREF(obj);
34+
return obj;
35+
}
36+
#define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj))
37+
#endif
38+
39+
40+
// bpo-42262 added Py_XNewRef() to Python 3.10.0a3
41+
#if PY_VERSION_HEX < 0x030a00A3 && !defined(Py_XNewRef)
42+
static inline PyObject* _Py_XNewRef(PyObject *obj)
43+
{
44+
Py_XINCREF(obj);
45+
return obj;
46+
}
47+
#define Py_XNewRef(obj) _Py_XNewRef(_PyObject_CAST(obj))
48+
#endif
49+
50+
51+
// bpo-39573 added Py_SET_REFCNT() to Python 3.9.0a4
52+
#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_REFCNT)
53+
static inline void _Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt)
54+
{
55+
ob->ob_refcnt = refcnt;
56+
}
57+
#define Py_SET_REFCNT(ob, refcnt) _Py_SET_REFCNT((PyObject*)(ob), refcnt)
58+
#endif
59+
60+
61+
// bpo-39573 added Py_SET_TYPE() to Python 3.9.0a4
62+
#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE)
63+
static inline void
64+
_Py_SET_TYPE(PyObject *ob, PyTypeObject *type)
65+
{
66+
ob->ob_type = type;
67+
}
68+
#define Py_SET_TYPE(ob, type) _Py_SET_TYPE((PyObject*)(ob), type)
69+
#endif
70+
71+
72+
// bpo-39573 added Py_SET_SIZE() to Python 3.9.0a4
73+
#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_SIZE)
74+
static inline void
75+
_Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size)
76+
{
77+
ob->ob_size = size;
78+
}
79+
#define Py_SET_SIZE(ob, size) _Py_SET_SIZE((PyVarObject*)(ob), size)
80+
#endif
81+
82+
83+
// bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1
84+
#if PY_VERSION_HEX < 0x030900B1
85+
static inline PyCodeObject*
86+
PyFrame_GetCode(PyFrameObject *frame)
87+
{
88+
PyCodeObject *code;
89+
assert(frame != NULL);
90+
code = frame->f_code;
91+
assert(code != NULL);
92+
Py_INCREF(code);
93+
return code;
94+
}
95+
#endif
96+
97+
static inline PyCodeObject*
98+
_PyFrame_GetCodeBorrow(PyFrameObject *frame)
99+
{
100+
PyCodeObject *code = PyFrame_GetCode(frame);
101+
Py_DECREF(code);
102+
return code; // borrowed reference
103+
}
104+
105+
106+
// bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1
107+
#if PY_VERSION_HEX < 0x030900B1
108+
static inline PyFrameObject*
109+
PyFrame_GetBack(PyFrameObject *frame)
110+
{
111+
PyFrameObject *back;
112+
assert(frame != NULL);
113+
back = frame->f_back;
114+
Py_XINCREF(back);
115+
return back;
116+
}
117+
#endif
118+
119+
static inline PyFrameObject*
120+
_PyFrame_GetBackBorrow(PyFrameObject *frame)
121+
{
122+
PyFrameObject *back = PyFrame_GetBack(frame);
123+
Py_XDECREF(back);
124+
return back; // borrowed reference
125+
}
126+
127+
128+
// bpo-39947 added PyThreadState_GetInterpreter() to Python 3.9.0a5
129+
#if PY_VERSION_HEX < 0x030900A5
130+
static inline PyInterpreterState *
131+
PyThreadState_GetInterpreter(PyThreadState *tstate)
132+
{
133+
assert(tstate != NULL);
134+
return tstate->interp;
135+
}
136+
#endif
137+
138+
139+
// bpo-40429 added PyThreadState_GetFrame() to Python 3.9.0b1
140+
#if PY_VERSION_HEX < 0x030900B1
141+
static inline PyFrameObject*
142+
PyThreadState_GetFrame(PyThreadState *tstate)
143+
{
144+
PyFrameObject *frame;
145+
assert(tstate != NULL);
146+
frame = tstate->frame;
147+
Py_XINCREF(frame);
148+
return frame;
149+
}
150+
#endif
151+
152+
static inline PyFrameObject*
153+
_PyThreadState_GetFrameBorrow(PyThreadState *tstate)
154+
{
155+
PyFrameObject *frame = PyThreadState_GetFrame(tstate);
156+
Py_XDECREF(frame);
157+
return frame; // borrowed reference
158+
}
159+
160+
161+
// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a5
162+
#if PY_VERSION_HEX < 0x030900A5
163+
static inline PyInterpreterState *
164+
PyInterpreterState_Get(void)
165+
{
166+
PyThreadState *tstate;
167+
PyInterpreterState *interp;
168+
169+
tstate = PyThreadState_GET();
170+
if (tstate == NULL) {
171+
Py_FatalError("GIL released (tstate is NULL)");
172+
}
173+
interp = tstate->interp;
174+
if (interp == NULL) {
175+
Py_FatalError("no current interpreter");
176+
}
177+
return interp;
178+
}
179+
#endif
180+
181+
182+
// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a6
183+
#if 0x030700A1 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030900A6
184+
static inline uint64_t
185+
PyThreadState_GetID(PyThreadState *tstate)
186+
{
187+
assert(tstate != NULL);
188+
return tstate->id;
189+
}
190+
#endif
191+
192+
193+
// bpo-37194 added PyObject_CallNoArgs() to Python 3.9.0a1
194+
#if PY_VERSION_HEX < 0x030900A1
195+
static inline PyObject*
196+
PyObject_CallNoArgs(PyObject *func)
197+
{
198+
return PyObject_CallFunctionObjArgs(func, NULL);
199+
}
200+
#endif
201+
202+
203+
// bpo-39245 made PyObject_CallOneArg() public (previously called
204+
// _PyObject_CallOneArg) in Python 3.9.0a4
205+
#if PY_VERSION_HEX < 0x030900A4
206+
static inline PyObject*
207+
PyObject_CallOneArg(PyObject *func, PyObject *arg)
208+
{
209+
return PyObject_CallFunctionObjArgs(func, arg, NULL);
210+
}
211+
#endif
212+
213+
214+
// bpo-40024 added PyModule_AddType() to Python 3.9.0a5
215+
#if PY_VERSION_HEX < 0x030900A5
216+
static inline int
217+
PyModule_AddType(PyObject *module, PyTypeObject *type)
218+
{
219+
const char *name, *dot;
220+
221+
if (PyType_Ready(type) < 0) {
222+
return -1;
223+
}
224+
225+
// inline _PyType_Name()
226+
name = type->tp_name;
227+
assert(name != NULL);
228+
dot = strrchr(name, '.');
229+
if (dot != NULL) {
230+
name = dot + 1;
231+
}
232+
233+
Py_INCREF(type);
234+
if (PyModule_AddObject(module, name, (PyObject *)type) < 0) {
235+
Py_DECREF(type);
236+
return -1;
237+
}
238+
239+
return 0;
240+
}
241+
#endif
242+
243+
244+
// bpo-40241 added PyObject_GC_IsTracked() to Python 3.9.0a6.
245+
// bpo-4688 added _PyObject_GC_IS_TRACKED() to Python 2.7.0a2.
246+
#if PY_VERSION_HEX < 0x030900A6
247+
static inline int
248+
PyObject_GC_IsTracked(PyObject* obj)
249+
{
250+
return (PyObject_IS_GC(obj) && _PyObject_GC_IS_TRACKED(obj));
251+
}
252+
#endif
253+
254+
// bpo-40241 added PyObject_GC_IsFinalized() to Python 3.9.0a6.
255+
// bpo-18112 added _PyGCHead_FINALIZED() to Python 3.4.0 final.
256+
#if PY_VERSION_HEX < 0x030900A6 && PY_VERSION_HEX >= 0x030400F0
257+
static inline int
258+
PyObject_GC_IsFinalized(PyObject *obj)
259+
{
260+
return (PyObject_IS_GC(obj) && _PyGCHead_FINALIZED((PyGC_Head *)(obj)-1));
261+
}
262+
#endif
263+
264+
265+
// bpo-39573 added Py_IS_TYPE() to Python 3.9.0a4
266+
#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_IS_TYPE)
267+
static inline int
268+
_Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) {
269+
return ob->ob_type == type;
270+
}
271+
#define Py_IS_TYPE(ob, type) _Py_IS_TYPE((const PyObject*)(ob), type)
272+
#endif
273+
274+
275+
#ifdef __cplusplus
276+
}
277+
#endif
278+
#endif // PYTHONCAPI_COMPAT

0 commit comments

Comments
 (0)