Blob Blame History Raw
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