From c72baf40b613d7f328b918ba2094ad72b0087655 Mon Sep 17 00:00:00 2001 From: Jonas Rembser Date: Sat, 7 Feb 2026 21:24:21 +0100 Subject: [PATCH 1/2] [Python] Don't take extra reference to libROOTPythonizations module It's better if the initalization function doesn't get too different from the default, so that there are no unexpected initialization and garbage collection effects. In fact, the extra reference directly contradicted a comment a few lines further up: > keep gRootModule, but do not increase its reference count --- bindings/pyroot/pythonizations/src/PyROOTModule.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/bindings/pyroot/pythonizations/src/PyROOTModule.cxx b/bindings/pyroot/pythonizations/src/PyROOTModule.cxx index dfb400658e628..489903d2794e3 100644 --- a/bindings/pyroot/pythonizations/src/PyROOTModule.cxx +++ b/bindings/pyroot/pythonizations/src/PyROOTModule.cxx @@ -212,6 +212,5 @@ extern "C" PyObject *PyInit_libROOTPythonizations() // signal policy: don't abort interpreter in interactive mode CallContext::SetGlobalPolicy(CallContext::kProtected, !gROOT->IsBatch()); - Py_INCREF(gRootModule); return gRootModule; } From 3e33c35b2ad497b2ab0c240527383b93e265d26f Mon Sep 17 00:00:00 2001 From: Jonas Rembser Date: Sat, 7 Feb 2026 21:19:11 +0100 Subject: [PATCH 2/2] [Python] Avoid side effects in libROOTPythonizations initialization There are some side effects when importing the ROOT CPython extension that we should better avoid, so that all active initialization is centralized in `ROOTFacade._finalSetup()`. Like this, it will be easier for us and our users to keep track of what the differences between the base cppyy and the ROOT C++ runtime are. That should help explaining to our users that they usually don't need to import cppyy directly, --- bindings/pyroot/pythonizations/python/ROOT/_facade.py | 3 +++ bindings/pyroot/pythonizations/src/PyROOTModule.cxx | 8 -------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/bindings/pyroot/pythonizations/python/ROOT/_facade.py b/bindings/pyroot/pythonizations/python/ROOT/_facade.py index b745e08b49f06..5b1f064e56b7c 100644 --- a/bindings/pyroot/pythonizations/python/ROOT/_facade.py +++ b/bindings/pyroot/pythonizations/python/ROOT/_facade.py @@ -162,6 +162,9 @@ def _finalSetup(self): from ._application import PyROOTApplication from ._pythonization import _register_pythonizations, pythonization + # signal policy: don't abort interpreter in interactive mode + cppyy._backend.SetGlobalSignalPolicy(not cppyy.gbl.ROOT.GetROOT().IsBatch()) + self.__dict__["_cppyy"] = cppyy # Expose some functionality from CPyCppyy extension module diff --git a/bindings/pyroot/pythonizations/src/PyROOTModule.cxx b/bindings/pyroot/pythonizations/src/PyROOTModule.cxx index 489903d2794e3..dff7f6f09ad5f 100644 --- a/bindings/pyroot/pythonizations/src/PyROOTModule.cxx +++ b/bindings/pyroot/pythonizations/src/PyROOTModule.cxx @@ -172,8 +172,6 @@ struct module_state { PyObject *error; }; -using namespace CPyCppyy; - #define GETSTATE(m) ((struct module_state *)PyModule_GetState(m)) static int rootmodule_traverse(PyObject *m, visitproc visit, void *arg) @@ -206,11 +204,5 @@ extern "C" PyObject *PyInit_libROOTPythonizations() // keep gRootModule, but do not increase its reference count even as it is borrowed, // or a self-referencing cycle would be created - // Make sure the interpreter is initialized once gROOT has been initialized - TInterpreter::Instance(); - - // signal policy: don't abort interpreter in interactive mode - CallContext::SetGlobalPolicy(CallContext::kProtected, !gROOT->IsBatch()); - return gRootModule; }