From 07693d05ad785d495a9c1d5af27399481b43c3f5 Mon Sep 17 00:00:00 2001
From: Mattias Ellert <mattias.ellert@physics.uu.se>
Date: Fri, 1 Jul 2022 06:50:31 +0200
Subject: [PATCH] Python 3.11 support - backported from CPyCppyy
---
bindings/pyroot/cppyy/CPyCppyy/src/API.cxx | 11 ++++++++++-
.../pyroot/cppyy/CPyCppyy/src/CPPInstance.cxx | 1 -
.../pyroot/cppyy/CPyCppyy/src/CPPOverload.cxx | 8 +++++---
bindings/pyroot/cppyy/CPyCppyy/src/CPyCppyy.h | 5 ++++-
.../cppyy/CPyCppyy/src/CPyCppyyModule.cxx | 19 +++++++++++++++++++
.../cppyy/CPyCppyy/src/MemoryRegulator.cxx | 2 +-
.../pyroot/cppyy/CPyCppyy/src/Utility.cxx | 2 ++
bindings/pyroot/cppyy/CPyCppyy/src/Utility.h | 2 ++
8 files changed, 43 insertions(+), 7 deletions(-)
diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/API.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/API.cxx
index 0cc4c8247b..4c17f54bb0 100644
--- a/bindings/pyroot/cppyy/CPyCppyy/src/API.cxx
+++ b/bindings/pyroot/cppyy/CPyCppyy/src/API.cxx
@@ -49,7 +49,14 @@ static bool Initialize()
#if PY_VERSION_HEX < 0x03020000
PyEval_InitThreads();
#endif
+#if PY_VERSION_HEX < 0x03080000
Py_Initialize();
+#else
+ PyConfig config;
+ PyConfig_InitPythonConfig(&config);
+ PyConfig_SetString(&config, &config.program_name, L"cppyy");
+ Py_InitializeFromConfig(&config);
+#endif
#if PY_VERSION_HEX >= 0x03020000
#if PY_VERSION_HEX < 0x03090000
PyEval_InitThreads();
@@ -66,10 +73,12 @@ static bool Initialize()
// set the command line arguments on python's sys.argv
#if PY_VERSION_HEX < 0x03000000
char* argv[] = {const_cast<char*>("cppyy")};
-#else
+#elif PY_VERSION_HEX < 0x03080000
wchar_t* argv[] = {const_cast<wchar_t*>(L"cppyy")};
#endif
+#if PY_VERSION_HEX < 0x03080000
PySys_SetArgv(sizeof(argv)/sizeof(argv[0]), argv);
+#endif
// force loading of the cppyy module
PyRun_SimpleString(const_cast<char*>("import cppyy"));
diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/CPPInstance.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/CPPInstance.cxx
index 73fb8099b5..f2eea396af 100644
--- a/bindings/pyroot/cppyy/CPyCppyy/src/CPPInstance.cxx
+++ b/bindings/pyroot/cppyy/CPyCppyy/src/CPPInstance.cxx
@@ -764,7 +764,6 @@ PyTypeObject CPPInstance_Type = {
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT |
Py_TPFLAGS_BASETYPE |
- Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_CHECKTYPES, // tp_flags
(char*)"cppyy object proxy (internal)", // tp_doc
0, // tp_traverse
diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/CPPOverload.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/CPPOverload.cxx
index 28bbd635c2..7eb2de8b01 100644
--- a/bindings/pyroot/cppyy/CPyCppyy/src/CPPOverload.cxx
+++ b/bindings/pyroot/cppyy/CPyCppyy/src/CPPOverload.cxx
@@ -1,11 +1,13 @@
// Bindings
#include "CPyCppyy.h"
#include "structmember.h" // from Python
-#if PY_VERSION_HEX < 0x02050000
-#include "compile.h" // from Python
-#elif PY_VERSION_HEX < 0x030b0000
+#if PY_VERSION_HEX >= 0x02050000
+#if PY_VERSION_HEX < 0x030b0000
#include "code.h" // from Python
#endif
+#else
+#include "compile.h" // from Python
+#endif
#ifndef CO_NOFREE
// python2.2 does not have CO_NOFREE defined
#define CO_NOFREE 0x0040
diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/CPyCppyy.h b/bindings/pyroot/cppyy/CPyCppyy/src/CPyCppyy.h
index 11221cd7ef..35af3c8a56 100644
--- a/bindings/pyroot/cppyy/CPyCppyy/src/CPyCppyy.h
+++ b/bindings/pyroot/cppyy/CPyCppyy/src/CPyCppyy.h
@@ -68,7 +68,10 @@ typedef dim_t* dims_t;
#if PY_VERSION_HEX < 0x03030000
typedef PyDictEntry* (*dict_lookup_func)(PyDictObject*, PyObject*, long);
#else
-#if PY_VERSION_HEX >= 0x03060000
+#if PY_VERSION_HEX >= 0x030b0000
+ typedef Py_ssize_t (*dict_lookup_func)(
+ PyDictObject*, PyObject*, Py_hash_t, PyObject**);
+#elif PY_VERSION_HEX >= 0x03060000
typedef Py_ssize_t (*dict_lookup_func)(
PyDictObject*, PyObject*, Py_hash_t, PyObject***, Py_ssize_t*);
#else
diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/CPyCppyyModule.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/CPyCppyyModule.cxx
index 411a57a862..7a32ab365f 100644
--- a/bindings/pyroot/cppyy/CPyCppyy/src/CPyCppyyModule.cxx
+++ b/bindings/pyroot/cppyy/CPyCppyy/src/CPyCppyyModule.cxx
@@ -26,6 +26,11 @@
#include <vector>
+// Note: as of py3.11, dictionary objects no longer carry a function pointer for
+// the lookup, so it can no longer be shimmed and "from cppyy.interactive import *"
+// thus no longer works.
+#if PY_VERSION_HEX < 0x030b0000
+
//- from Python's dictobject.c -------------------------------------------------
#if PY_VERSION_HEX >= 0x03030000
typedef struct PyDictKeyEntry {
@@ -65,6 +70,8 @@
#endif
+#endif // PY_VERSION_HEX < 0x030b0000
+
//- data -----------------------------------------------------------------------
static PyObject* nullptr_repr(PyObject*)
{
@@ -177,7 +184,9 @@ namespace {
using namespace CPyCppyy;
+
//----------------------------------------------------------------------------
+#if PY_VERSION_HEX < 0x030b0000
namespace {
class GblGetter {
@@ -330,9 +339,12 @@ PyDictEntry* CPyCppyyLookDictString(PyDictObject* mp, PyObject* key, long hash)
return ep;
}
+#endif // PY_VERSION_HEX < 0x030b0000
+
//----------------------------------------------------------------------------
static PyObject* SetCppLazyLookup(PyObject*, PyObject* args)
{
+#if PY_VERSION_HEX < 0x030b0000
// Modify the given dictionary to install the lookup function that also
// tries the global C++ namespace before failing. Called on a module's dictionary,
// this allows for lazy lookups. This works fine for p3.2 and earlier, but should
@@ -343,6 +355,11 @@ static PyObject* SetCppLazyLookup(PyObject*, PyObject* args)
return nullptr;
CPYCPPYY_GET_DICT_LOOKUP(dict) = CPyCppyyLookDictString;
+#else
+// As of py3.11, there is no longer a lookup function pointer in the dict object
+// to replace. Since this feature is not widely advertised, it's simply droped
+ PyErr_Warn(PyExc_RuntimeWarning, (char*)"lazy lookup is no longer supported");
+#endif
Py_RETURN_NONE;
}
@@ -813,6 +830,7 @@ LIBCPPYY_INIT_FUNCTION(extern "C" void initlibcppyy, PY_MAJOR_VERSION, _, PY_MIN
PyEval_InitThreads();
#endif
+#if PY_VERSION_HEX < 0x030b0000
// prepare for lazyness (the insert is needed to capture the most generic lookup
// function, just in case ...)
PyObject* dict = PyDict_New();
@@ -825,6 +843,7 @@ LIBCPPYY_INIT_FUNCTION(extern "C" void initlibcppyy, PY_MAJOR_VERSION, _, PY_MIN
gDictLookupOrg = (dict_lookup_func)((PyDictObject*)dict)->ma_lookup;
#endif
Py_DECREF(dict);
+#endif // PY_VERSION_HEX < 0x030b0000
// setup this module
#if PY_VERSION_HEX >= 0x03000000
diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/MemoryRegulator.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/MemoryRegulator.cxx
index f9e92f9c8c..5da48364ac 100644
--- a/bindings/pyroot/cppyy/CPyCppyy/src/MemoryRegulator.cxx
+++ b/bindings/pyroot/cppyy/CPyCppyy/src/MemoryRegulator.cxx
@@ -45,7 +45,7 @@ struct InitCPyCppyy_NoneType_t {
((PyVarObject&)CPyCppyy_NoneType).ob_size = 0;
CPyCppyy_NoneType.tp_name = const_cast<char*>("CPyCppyy_NoneType");
- CPyCppyy_NoneType.tp_flags = Py_TPFLAGS_HAVE_RICHCOMPARE | Py_TPFLAGS_HAVE_GC;
+ CPyCppyy_NoneType.tp_flags = Py_TPFLAGS_HAVE_RICHCOMPARE;
CPyCppyy_NoneType.tp_traverse = (traverseproc)0;
CPyCppyy_NoneType.tp_clear = (inquiry)0;
diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/Utility.cxx b/bindings/pyroot/cppyy/CPyCppyy/src/Utility.cxx
index 14ea1b83e8..1cf8f89bd2 100644
--- a/bindings/pyroot/cppyy/CPyCppyy/src/Utility.cxx
+++ b/bindings/pyroot/cppyy/CPyCppyy/src/Utility.cxx
@@ -24,8 +24,10 @@
//- data _____________________________________________________________________
+#if PY_VERSION_HEX < 0x030b0000
dict_lookup_func CPyCppyy::gDictLookupOrg = 0;
bool CPyCppyy::gDictLookupActive = false;
+#endif
typedef std::map<std::string, std::string> TC2POperatorMapping_t;
static TC2POperatorMapping_t gC2POperatorMapping;
diff --git a/bindings/pyroot/cppyy/CPyCppyy/src/Utility.h b/bindings/pyroot/cppyy/CPyCppyy/src/Utility.h
index 6bc9314b99..2db76b31b0 100644
--- a/bindings/pyroot/cppyy/CPyCppyy/src/Utility.h
+++ b/bindings/pyroot/cppyy/CPyCppyy/src/Utility.h
@@ -10,8 +10,10 @@ namespace CPyCppyy {
class PyCallable;
+#if PY_VERSION_HEX < 0x030b0000
extern dict_lookup_func gDictLookupOrg;
extern bool gDictLookupActive;
+#endif
// additional converter functions
unsigned long PyLongOrInt_AsULong(PyObject* pyobject);
--
2.36.1