Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8e5c3ed

Browse files
committed
Add PyPy support
1 parent a13ed8d commit 8e5c3ed

5 files changed

Lines changed: 54 additions & 22 deletions

File tree

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
matrix:
1414
os: [ubuntu-latest]
1515
# 2020-03-30: use "3.10.0-alpha - 3.10" to get Python 3.10 alpha
16-
python: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9, "3.10.0-alpha - 3.10"]
16+
python: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9, "3.10.0-alpha - 3.10", "pypy2", "pypy3"]
1717
include:
1818
- os: windows-latest
1919
python: 3.6

README.rst

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ The Python C API compatibility project is made of two parts:
1414
Python API without losing support for old Python versions. It relies on
1515
``pythoncapi_compat.h``.
1616

17-
``pythoncapi_compat.h`` supports Python 2.7 to Python 3.10. A C99 subset is
18-
required, like ``static inline`` functions: see `PEP 7
17+
``pythoncapi_compat.h`` supports Python 3.5 to Python 3.10, and Python 2.7.
18+
A C99 subset is required, like ``static inline`` functions: see `PEP 7
1919
<https://www.python.org/dev/peps/pep-0007/>`_. ISO C90 is partially supported
2020
for Python 2.7: avoid mixed declarations and code (GCC
2121
``-Werror=declaration-after-statement`` flag) and support Visual Studio 2008.
@@ -146,6 +146,8 @@ Upgrade Operations
146146
pythoncapi_compat.h functions
147147
=============================
148148

149+
Some functions are not available on PyPy.
150+
149151
Borrow variant
150152
--------------
151153

@@ -311,7 +313,11 @@ Links
311313
Changelog
312314
=========
313315

314-
* 2021-04-01: Add ``Py_SETREF()``, ``Py_XSETREF()`` and ``Py_UNUSED()``.
316+
* 2021-04-01:
317+
318+
* Add ``Py_SETREF()``, ``Py_XSETREF()`` and ``Py_UNUSED()``.
319+
* Add PyPy support.
320+
315321
* 2021-02-16: Add ``_Py_StealRef()`` and ``_Py_XStealRef()`` functions.
316322
* 2021-01-27: Fix compatibility with Visual Studio 2008 for Python 2.7.
317323
* 2020-11-30: Creation of the ``upgrade_pythoncapi.py`` script.

pythoncapi_compat.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ _PyFrame_GetCodeBorrow(PyFrameObject *frame)
154154

155155

156156
// bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1
157-
#if PY_VERSION_HEX < 0x030900B1
157+
#if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION)
158158
static inline PyFrameObject*
159159
PyFrame_GetBack(PyFrameObject *frame)
160160
{
@@ -163,11 +163,13 @@ PyFrame_GetBack(PyFrameObject *frame)
163163
}
164164
#endif
165165

166+
#if !defined(PYPY_VERSION)
166167
static inline PyFrameObject*
167168
_PyFrame_GetBackBorrow(PyFrameObject *frame)
168169
{
169170
return (PyFrameObject *)_Py_XStealRef(PyFrame_GetBack(frame));
170171
}
172+
#endif
171173

172174

173175
// bpo-39947 added PyThreadState_GetInterpreter() to Python 3.9.0a5
@@ -182,7 +184,7 @@ PyThreadState_GetInterpreter(PyThreadState *tstate)
182184

183185

184186
// bpo-40429 added PyThreadState_GetFrame() to Python 3.9.0b1
185-
#if PY_VERSION_HEX < 0x030900B1
187+
#if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION)
186188
static inline PyFrameObject*
187189
PyThreadState_GetFrame(PyThreadState *tstate)
188190
{
@@ -191,11 +193,13 @@ PyThreadState_GetFrame(PyThreadState *tstate)
191193
}
192194
#endif
193195

196+
#if !defined(PYPY_VERSION)
194197
static inline PyFrameObject*
195198
_PyThreadState_GetFrameBorrow(PyThreadState *tstate)
196199
{
197200
return (PyFrameObject *)_Py_XStealRef(PyThreadState_GetFrame(tstate));
198201
}
202+
#endif
199203

200204

201205
// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a5
@@ -292,7 +296,7 @@ PyModule_AddType(PyObject *module, PyTypeObject *type)
292296

293297
// bpo-40241 added PyObject_GC_IsTracked() to Python 3.9.0a6.
294298
// bpo-4688 added _PyObject_GC_IS_TRACKED() to Python 2.7.0a2.
295-
#if PY_VERSION_HEX < 0x030900A6
299+
#if PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION)
296300
static inline int
297301
PyObject_GC_IsTracked(PyObject* obj)
298302
{
@@ -302,7 +306,7 @@ PyObject_GC_IsTracked(PyObject* obj)
302306

303307
// bpo-40241 added PyObject_GC_IsFinalized() to Python 3.9.0a6.
304308
// bpo-18112 added _PyGCHead_FINALIZED() to Python 3.4.0 final.
305-
#if PY_VERSION_HEX < 0x030900A6 && PY_VERSION_HEX >= 0x030400F0
309+
#if PY_VERSION_HEX < 0x030900A6 && PY_VERSION_HEX >= 0x030400F0 && !defined(PYPY_VERSION)
306310
static inline int
307311
PyObject_GC_IsFinalized(PyObject *obj)
308312
{

runtests.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@
3939
"python3.10",
4040
"python3",
4141
"python3-debug",
42+
"pypy",
43+
"pypy2",
44+
"pypy2.7",
45+
"pypy3",
46+
"pypy3.6",
4247
)
4348

4449

tests/test_pythoncapi_compat_cext.c

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,16 @@
1111
# define PYTHON3 1
1212
#endif
1313

14-
static PyObject*
15-
ASSERT_FAILED(const char *err_msg)
16-
{
17-
PyErr_SetString(PyExc_AssertionError, err_msg);
18-
return NULL;
19-
}
14+
// Ignore reference count checks on PyPy
15+
#if !defined(PYPY_VERSION)
16+
# define CHECK_REFCNT
17+
#endif
18+
19+
#ifdef CHECK_REFCNT
20+
# define ASSERT_REFCNT(expr) assert(expr)
21+
#else
22+
# define ASSERT_REFCNT(expr)
23+
#endif
2024

2125
static PyObject *
2226
test_object(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored))
@@ -111,6 +115,7 @@ test_steal_ref(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored))
111115
}
112116

113117

118+
#if !defined(PYPY_VERSION)
114119
static PyObject *
115120
test_frame(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored))
116121
{
@@ -119,7 +124,8 @@ test_frame(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored))
119124
// test PyThreadState_GetFrame()
120125
PyFrameObject *frame = PyThreadState_GetFrame(tstate);
121126
if (frame == NULL) {
122-
return ASSERT_FAILED("PyThreadState_GetFrame failed");
127+
PyErr_SetString(PyExc_AssertionError, "PyThreadState_GetFrame failed");
128+
return NULL;
123129
}
124130

125131
// test _PyThreadState_GetFrameBorrow()
@@ -162,6 +168,7 @@ test_frame(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored))
162168
Py_DECREF(frame);
163169
Py_RETURN_NONE;
164170
}
171+
#endif
165172

166173

167174
static PyObject *
@@ -173,12 +180,14 @@ test_thread_state(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored))
173180
PyInterpreterState *interp = PyThreadState_GetInterpreter(tstate);
174181
assert(interp != NULL);
175182

183+
#if !defined(PYPY_VERSION)
176184
// test PyThreadState_GetFrame()
177185
PyFrameObject *frame = PyThreadState_GetFrame(tstate);
178186
if (frame != NULL) {
179187
assert(PyFrame_Check(frame));
180188
}
181189
Py_XDECREF(frame);
190+
#endif
182191

183192
#if 0x030700A1 <= PY_VERSION_HEX
184193
uint64_t id = PyThreadState_GetID(tstate);
@@ -240,11 +249,13 @@ test_gc(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored))
240249
Py_INCREF(Py_None);
241250
PyTuple_SET_ITEM(tuple, 0, Py_None);
242251

252+
#if !defined(PYPY_VERSION)
243253
// test PyObject_GC_IsTracked()
244254
int tracked = PyObject_GC_IsTracked(tuple);
245255
assert(tracked);
256+
#endif
246257

247-
#if PY_VERSION_HEX >= 0x030400F0
258+
#if PY_VERSION_HEX >= 0x030400F0 && !defined(PYPY_VERSION)
248259
// test PyObject_GC_IsFinalized()
249260
int finalized = PyObject_GC_IsFinalized(tuple);
250261
assert(!finalized);
@@ -265,12 +276,14 @@ test_module_add_type(PyObject *module)
265276
#else
266277
const char *type_name = "unicode";
267278
#endif
279+
#ifdef CHECK_REFCNT
268280
Py_ssize_t refcnt = Py_REFCNT(type);
281+
#endif
269282

270283
if (PyModule_AddType(module, type) < 0) {
271284
return -1;
272285
}
273-
assert(Py_REFCNT(type) == refcnt + 1);
286+
ASSERT_REFCNT(Py_REFCNT(type) == refcnt + 1);
274287

275288
PyObject *attr = PyObject_GetAttrString(module, type_name);
276289
if (attr == NULL) {
@@ -282,7 +295,7 @@ test_module_add_type(PyObject *module)
282295
if (PyObject_DelAttrString(module, type_name) < 0) {
283296
return -1;
284297
}
285-
assert(Py_REFCNT(type) == refcnt);
298+
ASSERT_REFCNT(Py_REFCNT(type) == refcnt);
286299
return 0;
287300
}
288301

@@ -292,19 +305,21 @@ static int
292305
test_module_addobjectref(PyObject *module)
293306
{
294307
PyObject *obj = Py_True;
295-
Py_ssize_t refcnt = Py_REFCNT(obj);
296308
const char *name = "test_module_addobjectref";
309+
#ifdef CHECK_REFCNT
310+
Py_ssize_t refcnt = Py_REFCNT(obj);
311+
#endif
297312

298313
if (PyModule_AddObjectRef(module, name, obj) < 0) {
299-
assert(Py_REFCNT(obj) == refcnt);
314+
ASSERT_REFCNT(Py_REFCNT(obj) == refcnt);
300315
return -1;
301316
}
302-
assert(Py_REFCNT(obj) == refcnt + 1);
317+
ASSERT_REFCNT(Py_REFCNT(obj) == refcnt + 1);
303318

304319
if (PyObject_DelAttrString(module, name) < 0) {
305320
return -1;
306321
}
307-
assert(Py_REFCNT(obj) == refcnt);
322+
ASSERT_REFCNT(Py_REFCNT(obj) == refcnt);
308323

309324
// PyModule_AddObjectRef() with value=NULL must not crash
310325
int res = PyModule_AddObjectRef(module, name, NULL);
@@ -344,7 +359,9 @@ test_module(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored))
344359
static struct PyMethodDef methods[] = {
345360
{"test_object", test_object, METH_NOARGS, NULL},
346361
{"test_steal_ref", test_steal_ref, METH_NOARGS, NULL},
362+
#if !defined(PYPY_VERSION)
347363
{"test_frame", test_frame, METH_NOARGS, NULL},
364+
#endif
348365
{"test_thread_state", test_thread_state, METH_NOARGS, NULL},
349366
{"test_interpreter", test_interpreter, METH_NOARGS, NULL},
350367
{"test_calls", test_calls, METH_NOARGS, NULL},

0 commit comments

Comments
 (0)