Skip to content
Snippets Groups Projects
Commit 02517118 authored by Enric Tejedor Saavedra's avatar Enric Tejedor Saavedra
Browse files

[Exp PyROOT] Create an RPyROOTApplication when importing ROOT

The RPyROOTApplication is a TApplication that sets up the nuts
and bolts for interactive ROOT use from Python, closely
following TRint.
parent a98d98cf
No related branches found
No related tags found
No related merge requests found
......@@ -4,6 +4,7 @@
set(py_sources
ROOT/__init__.py
ROOT/_application.py
ROOT/_facade.py
ROOT/pythonization/__init__.py
ROOT/pythonization/_generic.py
......@@ -34,6 +35,7 @@ set(sources
src/PyROOTModule.cxx
src/PyROOTStrings.cxx
src/PyROOTWrapper.cxx
src/RPyROOTApplication.cxx
src/GenericPyz.cxx
src/RDataFramePyz.cxx
src/RVecPyz.cxx
......
......@@ -54,6 +54,10 @@ def pythonization(lazy = True):
for _, module_name, _ in pkgutil.walk_packages(pyz.__path__):
module = importlib.import_module(pyz.__name__ + '.' + module_name)
# Setup interactive usage from Python
from ._application import create_application
create_application()
# Configure ROOT facade module
import sys
from ._facade import ROOTFacade
......
# Author: Enric Tejedor CERN 04/2019
################################################################################
# Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. #
# All rights reserved. #
# #
# For the licensing terms see $ROOTSYS/LICENSE. #
# For the list of contributors see $ROOTSYS/README/CREDITS. #
################################################################################
from libROOTPython import InitApplication
def create_application():
InitApplication()
......@@ -13,6 +13,7 @@
#include "PyROOTPythonize.h"
#include "PyROOTStrings.h"
#include "PyROOTWrapper.h"
#include "RPyROOTApplication.h"
// Cppyy
#include "CPyCppyy.h"
......@@ -67,6 +68,8 @@ static PyMethodDef gPyROOTMethods[] = {{(char *)"AddDirectoryWritePyz", (PyCFunc
(char *)"Get object with array interface as RVec"},
{(char *)"MakeNumpyDataFrame", (PyCFunction)PyROOT::MakeNumpyDataFrame, METH_O,
(char *)"Make RDataFrame from dictionary of numpy arrays"},
{(char *)"InitApplication", (PyCFunction)PyROOT::RPyROOTApplication::InitApplication, METH_NOARGS,
(char *)"Initialize interactive ROOT use from Python"},
{NULL, NULL, 0, NULL}};
#if PY_VERSION_HEX >= 0x03000000
......
// Author: Enric Tejedor CERN 04/2019
// Original PyROOT code by Wim Lavrijsen, LBL
/*************************************************************************
* Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
// Bindings
#include "Python.h"
#include "RPyROOTApplication.h"
// ROOT
#include "TInterpreter.h"
#include "TSystem.h"
#include "TBenchmark.h"
#include "TStyle.h"
#include "TError.h"
#include "Getline.h"
#include "TVirtualMutex.h"
#ifdef R__WIN32
#include "TVirtualX.h"
#endif
////////////////////////////////////////////////////////////////////////////
/// \brief Create an RPyROOTApplication.
/// \return false if gApplication is not null, true otherwise.
bool PyROOT::RPyROOTApplication::CreateApplication()
{
if (!gApplication) {
int argc = 1;
char **argv = new char *[argc];
// TODO: Consider parsing arguments for the RPyROOTApplication here
#if PY_VERSION_HEX < 0x03000000
if (Py_GetProgramName() && strlen(Py_GetProgramName()) != 0)
argv[0] = Py_GetProgramName();
else
argv[0] = (char *)"python";
#else
argv[0] = (char *)"python";
#endif
gApplication = new RPyROOTApplication("PyROOT", &argc, argv);
delete[] argv; // TApplication ctor has copied argv, so done with it
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////////////
/// \brief Setup the basic ROOT globals gBenchmark, gStyle and gProgname,
/// if not already set.
void PyROOT::RPyROOTApplication::InitROOTGlobals()
{
if (!gBenchmark)
gBenchmark = new TBenchmark();
if (!gStyle)
gStyle = new TStyle();
if (!gProgName) // should have been set by TApplication
#if PY_VERSION_HEX < 0x03000000
gSystem->SetProgname(Py_GetProgramName());
#else
gSystem->SetProgname("python");
#endif
}
////////////////////////////////////////////////////////////////////////////
/// \brief Translate ROOT error/warning to Python.
static void ErrMsgHandler(int level, Bool_t abort, const char *location, const char *msg)
{
// Initialization from gEnv (the default handler will return w/o msg b/c level too low)
if (gErrorIgnoreLevel == kUnset)
::DefaultErrorHandler(kUnset - 1, kFALSE, "", "");
if (level < gErrorIgnoreLevel)
return;
// Turn warnings into Python warnings
if (level >= kError) {
::DefaultErrorHandler(level, abort, location, msg);
} else if (level >= kWarning) {
static const char *emptyString = "";
if (!location)
location = emptyString;
// This warning might be triggered while holding the ROOT lock, while
// some other thread is holding the GIL and waiting for the ROOT lock.
// That will trigger a deadlock.
// So if ROOT is in MT mode, use ROOT's error handler that doesn't take
// the GIL.
if (!gGlobalMutex) {
// Either printout or raise exception, depending on user settings
PyErr_WarnExplicit(NULL, (char *)msg, (char *)location, 0, (char *)"ROOT", NULL);
} else {
::DefaultErrorHandler(level, abort, location, msg);
}
} else {
::DefaultErrorHandler(level, abort, location, msg);
}
}
////////////////////////////////////////////////////////////////////////////
/// \brief Install the ROOT message handler which will turn ROOT error
/// messages into Python exceptions.
void PyROOT::RPyROOTApplication::InitROOTMessageCallback()
{
SetErrorHandler((ErrorHandlerFunc_t)&ErrMsgHandler);
}
////////////////////////////////////////////////////////////////////////////
/// \brief Initialize an RPyROOTApplication.
PyObject *PyROOT::RPyROOTApplication::InitApplication()
{
if (CreateApplication()) {
InitROOTGlobals();
InitROOTMessageCallback();
}
Py_RETURN_NONE;
}
////////////////////////////////////////////////////////////////////////////
/// \brief Construct a TApplication for PyROOT.
/// \param[in] acn Application class name.
/// \param[in] argc Number of arguments.
/// \param[in] argv Arguments.
PyROOT::RPyROOTApplication::RPyROOTApplication(const char *acn, int *argc, char **argv) : TApplication(acn, argc, argv)
{
#ifdef WIN32
// Switch win32 proxy main thread id
if (gVirtualX)
ProcessLine("((TGWin32 *)gVirtualX)->SetUserThreadId(0);", true);
#endif
// Save current interpreter context
gInterpreter->SaveContext();
gInterpreter->SaveGlobalsContext();
// Prevent crashes on accessing history
Gl_histinit((char *)"-");
// Prevent ROOT from exiting python
SetReturnFromRun(true);
}
// Author: Enric Tejedor CERN 04/2019
// Original PyROOT code by Wim Lavrijsen, LBL
/*************************************************************************
* Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
#ifndef ROOT_PyROOTApplication
#define ROOT_PyROOTApplication
// ROOT
#include "TApplication.h"
namespace PyROOT {
// clang-format off
/**
\class PyROOT::RPyROOTApplication
\brief Interactive application for Python.
The RPyROOTApplication sets up the nuts and bolts for interactive ROOT use
from Python, closely following TRint. Note that not everything is done here,
some bits (such as e.g. the use of exception hook for shell escapes) are more
easily done in Python.
*/
// clang-format on
class RPyROOTApplication : public TApplication {
public:
static PyObject *InitApplication();
RPyROOTApplication(const char *acn, int *argc, char **argv);
virtual ~RPyROOTApplication() {}
private:
static bool CreateApplication();
static void InitROOTGlobals();
static void InitROOTMessageCallback();
};
} // namespace PyROOT
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment