Skip to content

Commit

Permalink
Python 3.11 compatibility (#96)
Browse files Browse the repository at this point in the history
See https://docs.python.org/3.11/whatsnew/3.11.html#whatsnew311-c-api-porting

Added Py_SET_TYPE compatibility
Added Py_SET_SIZE compatibility
Added PyFrame_GetCode compatibility
Added explicit patchelf dependency instead of relying on system binary, not included by default (see pypa/auditwheel#386, pypa/auditwheel#403)
Added Python 3.11 CI logic

Fixes #95
  • Loading branch information
devinrsmith authored Nov 4, 2022
1 parent 488fd4c commit 3eff72b
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 17 deletions.
3 changes: 2 additions & 1 deletion .github/env/Linux/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
wheel
auditwheel
auditwheel
patchelf
3 changes: 3 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,19 @@ jobs:
- { machine: 'ubuntu-20.04', python: '3.8', pythonArchitecture: 'x64', arch: 'amd64', cmd: '.github/env/Linux/bdist-wheel.sh' }
- { machine: 'ubuntu-20.04', python: '3.9', pythonArchitecture: 'x64', arch: 'amd64', cmd: '.github/env/Linux/bdist-wheel.sh' }
- { machine: 'ubuntu-20.04', python: '3.10', pythonArchitecture: 'x64', arch: 'amd64', cmd: '.github/env/Linux/bdist-wheel.sh' }
- { machine: 'ubuntu-20.04', python: '3.11', pythonArchitecture: 'x64', arch: 'amd64', cmd: '.github/env/Linux/bdist-wheel.sh' }
- { machine: 'windows-2022', python: '3.6', pythonArchitecture: 'x64', arch: 'amd64', cmd: '.\.github\env\Windows\bdist-wheel.ps1' }
- { machine: 'windows-2022', python: '3.7', pythonArchitecture: 'x64', arch: 'amd64', cmd: '.\.github\env\Windows\bdist-wheel.ps1' }
- { machine: 'windows-2022', python: '3.8', pythonArchitecture: 'x64', arch: 'amd64', cmd: '.\.github\env\Windows\bdist-wheel.ps1' }
- { machine: 'windows-2022', python: '3.9', pythonArchitecture: 'x64', arch: 'amd64', cmd: '.\.github\env\Windows\bdist-wheel.ps1' }
- { machine: 'windows-2022', python: '3.10', pythonArchitecture: 'x64', arch: 'amd64', cmd: '.\.github\env\Windows\bdist-wheel.ps1' }
- { machine: 'windows-2022', python: '3.11', pythonArchitecture: 'x64', arch: 'amd64', cmd: '.\.github\env\Windows\bdist-wheel.ps1' }
- { machine: 'macos-11', python: '3.6', pythonArchitecture: 'x64', arch: 'amd64', cmd: '.github/env/macOS/bdist-wheel.sh' }
- { machine: 'macos-11', python: '3.7', pythonArchitecture: 'x64', arch: 'amd64', cmd: '.github/env/macOS/bdist-wheel.sh' }
- { machine: 'macos-11', python: '3.8', pythonArchitecture: 'x64', arch: 'amd64', cmd: '.github/env/macOS/bdist-wheel.sh' }
- { machine: 'macos-11', python: '3.9', pythonArchitecture: 'x64', arch: 'amd64', cmd: '.github/env/macOS/bdist-wheel.sh' }
- { machine: 'macos-11', python: '3.10', pythonArchitecture: 'x64', arch: 'amd64', cmd: '.github/env/macOS/bdist-wheel.sh' }
- { machine: 'macos-11', python: '3.11', pythonArchitecture: 'x64', arch: 'amd64', cmd: '.github/env/macOS/bdist-wheel.sh' }

steps:
- uses: actions/checkout@v3
Expand Down
30 changes: 18 additions & 12 deletions src/main/c/jni/org_jpy_PyLib.c
Original file line number Diff line number Diff line change
Expand Up @@ -2485,12 +2485,12 @@ void PyLib_HandlePythonException(JNIEnv* jenv)
pyTraceback = pyTraceback->tb_next;

if (pyTraceback != NULL) {
PyObject* pyFrame = NULL;
PyObject* pyCode = NULL;
PyFrameObject* pyFrame = NULL;
PyCodeObject* pyCode = NULL;
linenoChars = PyLib_ObjToChars(PyObject_GetAttrString(pyTraceback, "tb_lineno"), &pyLinenoUtf8);
pyFrame = PyObject_GetAttrString(pyTraceback, "tb_frame");
if (pyFrame != NULL) {
pyCode = PyObject_GetAttrString(pyFrame, "f_code");
pyCode = PyFrame_GetCode(pyFrame);
if (pyCode != NULL) {
filenameChars = PyLib_ObjToChars(PyObject_GetAttrString(pyCode, "co_filename"), &pyFilenameUtf8);
namespaceChars = PyLib_ObjToChars(PyObject_GetAttrString(pyCode, "co_name"), &pyNamespaceUtf8);
Expand Down Expand Up @@ -2739,31 +2739,37 @@ static int format_python_traceback(PyTracebackObject *tb, char **buf, int *bufLe
tb = tb->tb_next;
}
while (tb != NULL && err == 0) {
PyCodeObject* co = PyFrame_GetCode(tb->tb_frame);
if (last_file == NULL ||
tb->tb_frame->f_code->co_filename != last_file ||
co->co_filename != last_file ||
last_line == -1 || tb->tb_lineno != last_line ||
last_name == NULL || tb->tb_frame->f_code->co_name != last_name) {
last_name == NULL || co->co_name != last_name) {
if (cnt > PYLIB_RECURSIVE_CUTOFF) {
pyObjUtf8 = format_line_repeated(cnt);
err = append_to_java_message(pyObjUtf8, buf, bufLen);
if (err != 0)
return err;
if (err != 0) {
JPy_DECREF(co);
return err;
}
}
last_file = tb->tb_frame->f_code->co_filename;
last_file = co->co_filename;
last_line = tb->tb_lineno;
last_name = tb->tb_frame->f_code->co_name;
last_name = co->co_name;
cnt = 0;
}
cnt++;
if (err == 0 && cnt <= PYLIB_RECURSIVE_CUTOFF) {
pyObjUtf8 = format_displayline(
tb->tb_frame->f_code->co_filename,
co->co_filename,
tb->tb_lineno,
tb->tb_frame->f_code->co_name);
co->co_name);
err = append_to_java_message(pyObjUtf8, buf, bufLen);
if (err != 0)
if (err != 0) {
JPy_DECREF(co);
return err;
}
}
JPy_DECREF(co);
tb = tb->tb_next;
}
if (err == 0 && cnt > PYLIB_RECURSIVE_CUTOFF) {
Expand Down
23 changes: 23 additions & 0 deletions src/main/c/jpy_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ extern "C" {
#endif

#include <Python.h>
#include "frameobject.h"

#define JPY_VERSION_ERROR "jpy requires either Python 2.7 or Python 3.3+"

Expand Down Expand Up @@ -81,6 +82,28 @@ wchar_t* JPy_AsWideCharString_PriorToPy33(PyObject *unicode, Py_ssize_t *size);

#endif

// As recommended by https://docs.python.org/3.11/whatsnew/3.11.html#whatsnew311-c-api-porting
#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE)
static inline void _Py_SET_TYPE(PyObject *ob, PyTypeObject *type)
{ ob->ob_type = type; }
#define Py_SET_TYPE(ob, type) _Py_SET_TYPE((PyObject*)(ob), type)
#endif

// As recommended by https://docs.python.org/3.11/whatsnew/3.11.html#whatsnew311-c-api-porting
#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_SIZE)
static inline void _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size)
{ ob->ob_size = size; }
#define Py_SET_SIZE(ob, size) _Py_SET_SIZE((PyVarObject*)(ob), size)
#endif

// As recommended by https://docs.python.org/3.11/whatsnew/3.11.html#pyframeobject-3-11-hiding
#if PY_VERSION_HEX < 0x030900B1
static inline PyCodeObject* PyFrame_GetCode(PyFrameObject *frame)
{
Py_INCREF(frame->f_code);
return frame->f_code;
}
#endif

#ifdef __cplusplus
} /* extern "C" */
Expand Down
8 changes: 4 additions & 4 deletions src/main/c/jpy_jobj.c
Original file line number Diff line number Diff line change
Expand Up @@ -718,14 +718,14 @@ int JType_InitSlots(JPy_JType* type)
#else
Py_REFCNT(typeObj) = 1;
#endif
Py_TYPE(typeObj) = NULL;
Py_SIZE(typeObj) = 0;
Py_SET_TYPE(typeObj, NULL);
Py_SET_SIZE(typeObj, 0);
// todo: The following lines are actually correct, but setting Py_TYPE(type) = &JType_Type results in an interpreter crash. Why?
// This is still a problem because all the JType slots are actually never called (especially JType_getattro is
// needed to resolve unresolved JTypes and to recognize static field and methods access)
//JPy_INCREF(&JType_Type);
//Py_TYPE(type) = &JType_Type;
//Py_SIZE(type) = sizeof (JPy_JType);
//Py_SET_TYPE(type, &JType_Type);
//Py_SET_SIZE(type, sizeof (JPy_JType));

typeObj->tp_basicsize = isPrimitiveArray ? sizeof (JPy_JArray) : sizeof (JPy_JObj);
typeObj->tp_itemsize = 0;
Expand Down

0 comments on commit 3eff72b

Please sign in to comment.