Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion bindings/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

if(pyroot)
add_subdirectory(pyroot)
add_subdirectory(jupyroot)

if(dataframe)
message(STATUS "Distributed RDataFrame enabled")
Expand Down
2 changes: 0 additions & 2 deletions bindings/jupyroot/CMakeLists.txt

This file was deleted.

29 changes: 0 additions & 29 deletions bindings/jupyroot/python/CMakeLists.txt

This file was deleted.

16 changes: 16 additions & 0 deletions bindings/pyroot/pythonizations/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,22 @@ set(py_sources
ROOT/_asan.py
ROOT/_facade.py
ROOT/__init__.py
ROOT/_jupyroot/__init__.py
ROOT/_jupyroot/helpers/__init__.py
ROOT/_jupyroot/helpers/cppcompleter.py
ROOT/_jupyroot/helpers/handlers.py
ROOT/_jupyroot/helpers/utils.py
ROOT/_jupyroot/html/__init__.py
ROOT/_jupyroot/html/cpphighlighter.py
ROOT/_jupyroot/kernel/__init__.py
ROOT/_jupyroot/kernel/rootkernel.py
ROOT/_jupyroot/kernel/utils.py
ROOT/_jupyroot/kernel/magics/__init__.py
ROOT/_jupyroot/kernel/magics/cppmagic.py
ROOT/_jupyroot/kernel/magics/jsrootmagic.py
ROOT/_jupyroot/magics/__init__.py
ROOT/_jupyroot/magics/cppmagic.py
ROOT/_jupyroot/magics/jsrootmagic.py
ROOT/_numbadeclare.py
ROOT/_pythonization/__init__.py
ROOT/_pythonization/_cppinstance.py
Expand Down
11 changes: 4 additions & 7 deletions bindings/pyroot/pythonizations/python/ROOT/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,14 @@
# For the list of contributors see $ROOTSYS/README/CREDITS. #
################################################################################

from __future__ import annotations

import builtins
import os
import sys
import types
from importlib.abc import Loader, MetaPathFinder
from importlib.machinery import ModuleSpec
from typing import Optional, Union

import cppyy
import cppyy.ll
import cppyy.types

from . import _asan # noqa: F401 # imported for side effects for setup specific to AddressSanitizer environments
from ._facade import ROOTFacade
Expand Down Expand Up @@ -100,7 +97,7 @@ def _can_be_module(obj) -> bool:
return False


def _lookup_root_module(fullname: str) -> Optional[Union[types.ModuleType, cppyy.types.Scope]]:
def _lookup_root_module(fullname: str) -> Optional[Union[types.ModuleType, cppyy.types.Scope]]: # noqa: F821
"""
Recursively looks up attributes of the ROOT facade, using a full module
name, and return it if it can be used as a ROOT submodule. This is the case
Expand Down Expand Up @@ -168,6 +165,6 @@ def find_spec(self, fullname: str, path, target=None) -> ModuleSpec:

ip = get_ipython()
if hasattr(ip, "kernel"):
import JupyROOT # noqa: F401 # imported the side effect of setting up JupyROOT
from . import _jupyroot # noqa: F401 # imported the side effect of setting up JupyROOT

# from . import JsMVA
61 changes: 41 additions & 20 deletions bindings/pyroot/pythonizations/python/ROOT/_facade.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,14 @@ class _gROOTWrapper(object):

def __init__(self, facade):
self.__dict__["_facade"] = facade
self.__dict__["_gROOT"] = facade._cppyy.gbl.ROOT.GetROOT()

@property
def _gROOT(self):
gROOT = self.__dict__.get("_gROOT")
if gROOT is None:
gROOT = self._facade._cppyy.gbl.ROOT.GetROOT()
self.__dict__["_gROOT"] = gROOT
return gROOT

def __getattr__(self, name):
if name != "SetBatch" and self._facade.__dict__["gROOT"] != self._gROOT:
Expand All @@ -52,8 +59,6 @@ class ROOTFacade(types.ModuleType):
def __init__(self, module, is_ipython):
types.ModuleType.__init__(self, module.__name__)

self._cppyy = module.cppyy

self.__all__ = module.__all__
self.__name__ = module.__name__
self.__file__ = module.__file__
Expand All @@ -66,23 +71,6 @@ def __init__(self, module, is_ipython):
# Inject gROOT global
self.gROOT = _gROOTWrapper(self)

# Expose some functionality from CPyCppyy extension module
self._cppyy_exports = [
"nullptr",
"bind_object",
"as_cobject",
"addressof",
"SetHeuristicMemoryPolicy",
"SetImplicitSmartPointerConversion",
"SetOwnership",
]
for name in self._cppyy_exports:
setattr(self, name, getattr(self._cppyy._backend, name))
# For backwards compatibility
self.MakeNullPointer = partial(self.bind_object, 0)
self.BindObject = self.bind_object
self.AsCObject = self.as_cobject

# Initialize configuration
self.PyConfig = PyROOTConfiguration()

Expand Down Expand Up @@ -157,9 +145,42 @@ def _register_converters_and_executors(self):
CPyCppyyRegisterExecutorAlias(name, target)

def _finalSetup(self):
"""
Perform the final ROOT initialization.

This method is intentionally deferred and is the *only* place where
cppyy is imported and the C++ runtime is initialized. Delaying this
step avoids importing the heavy-weight cppyy machinery unless it is
actually required (for example, when accessing C++ ROOT symbols),
allowing Python-only ROOT submodules to be imported with minimal
overhead.
"""
import cppyy
import cppyy.ll
import cppyy.types

from ._application import PyROOTApplication
from ._pythonization import _register_pythonizations, pythonization

self.__dict__["_cppyy"] = cppyy

# Expose some functionality from CPyCppyy extension module
cppyy_exports = [
"nullptr",
"bind_object",
"as_cobject",
"addressof",
"SetHeuristicMemoryPolicy",
"SetImplicitSmartPointerConversion",
"SetOwnership",
]
for name in cppyy_exports:
self.__dict__[name] = getattr(cppyy._backend, name)
# For backwards compatibility
self.__dict__["MakeNullPointer"] = partial(cppyy._backend.bind_object, 0)
self.__dict__["BindObject"] = cppyy._backend.bind_object
self.__dict__["AsCObject"] = cppyy._backend.as_cobject

# Trigger the addition of the pythonizations
_register_pythonizations()

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#-----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# Author: Danilo Piparo <Danilo.Piparo@cern.ch> CERN
# Author: Enric Tejedor <enric.tejedor.saavedra@cern.ch> CERN
#-----------------------------------------------------------------------------
# -----------------------------------------------------------------------------

################################################################################
# Copyright (C) 1995-2020, Rene Brun and Fons Rademakers. #
Expand All @@ -12,19 +12,22 @@
################################################################################

import sys
from JupyROOT.helpers import utils
if not 'win32' in sys.platform:
from JupyROOT.helpers import cppcompleter

from ROOT._jupyroot.helpers import utils

if "win32" not in sys.platform:
from ROOT._jupyroot.helpers import cppcompleter

# Check if we are in the IPython shell
try:
import builtins
except ImportError:
import __builtin__ as builtins # Py2
_is_ipython = hasattr(builtins, '__IPYTHON__')
import __builtin__ as builtins # Py2
_is_ipython = hasattr(builtins, "__IPYTHON__")

if _is_ipython:
if not 'win32' in sys.platform:
if "win32" not in sys.platform:
from IPython import get_ipython

cppcompleter.load_ipython_extension(get_ipython())
utils.iPythonize()
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#-----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# Author: Danilo Piparo <Danilo.Piparo@cern.ch> CERN
# Author: Enric Tejedor <enric.tejedor.saavedra@cern.ch> CERN
#-----------------------------------------------------------------------------
# -----------------------------------------------------------------------------

################################################################################
# Copyright (C) 1995-2020, Rene Brun and Fons Rademakers. #
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# -*- coding:utf-8 -*-

#-----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# Author: Danilo Piparo <Danilo.Piparo@cern.ch> CERN
# Author: Enric Tejedor <enric.tejedor.saavedra@cern.ch> CERN
#-----------------------------------------------------------------------------
# -----------------------------------------------------------------------------

################################################################################
# Copyright (C) 1995-2020, Rene Brun and Fons Rademakers. #
Expand All @@ -13,9 +13,10 @@
# For the list of contributors see $ROOTSYS/README/CREDITS. #
################################################################################

from JupyROOT.helpers import utils
import platform

import ROOT
from ROOT._jupyroot.helpers import utils

# Jit a wrapper for the ttabcom
_TTabComHookCode = """
Expand Down Expand Up @@ -46,8 +47,9 @@
}
"""


class CppCompleter(object):
'''
"""
Completer which interfaces to the TTabCom of ROOT. It is activated
(deactivated) upon the load(unload) of the load of the extension.

Expand Down Expand Up @@ -95,7 +97,7 @@ class CppCompleter(object):
>>> comp.deactivate()
>>> for suggestion in comp._completeImpl("TG"):
... print(suggestion)
'''
"""

def __init__(self):
self.hook = None
Expand All @@ -106,7 +108,7 @@ def __init__(self):
def activate(self):
self.active = True
if self.firstActivation:
if platform.system() == 'Windows':
if platform.system() == "Windows":
dlOpenRint = 'gInterpreter->LoadFile("libRint.dll");'
else:
utils.declareCppCode('#include "dlfcn.h"')
Expand All @@ -119,35 +121,36 @@ def activate(self):
def deactivate(self):
self.active = False

def _getSuggestions(self,line):
def _getSuggestions(self, line):
if self.active:
return self.hook(line)
return []

def _getLastAccessorPos(self,line):
def _getLastAccessorPos(self, line):
accessorPos = -1
for accessor in self.accessors:
tmpAccessorPos = line.rfind(accessor)
if accessorPos < tmpAccessorPos:
accessorPos = tmpAccessorPos+len(accessor)
accessorPos = tmpAccessorPos + len(accessor)
return accessorPos

def _completeImpl(self, line):
line=line.split()[-1]
suggestions = [ str(s) for s in self._getSuggestions(line) ]
line = line.split()[-1]
suggestions = [str(s) for s in self._getSuggestions(line)]
suggestions = filter(lambda s: len(s.strip()) != 0, suggestions)
suggestions = sorted(suggestions)
if not suggestions: return []
if not suggestions:
return []
# Remove combinations of opening and closing brackets and just opening
# brackets at the end of a line. Jupyter seems to expect functions
# without these brackets to work properly. The brackets of'operator()'
# must not be removed
suggestions = [sugg[:-2] if sugg[-2:] == '()' and sugg != 'operator()' else sugg for sugg in suggestions]
suggestions = [sugg[:-1] if sugg[-1:] == '(' else sugg for sugg in suggestions]
suggestions = [sugg[:-2] if sugg[-2:] == "()" and sugg != "operator()" else sugg for sugg in suggestions]
suggestions = [sugg[:-1] if sugg[-1:] == "(" else sugg for sugg in suggestions]
# If a function signature is encountered, add an empty item to the
# suggestions. Try to guess a function signature by an opening bracket
# ignoring 'operator()'.
are_signatures = "(" in "".join(filter(lambda s: s != 'operator()', suggestions))
are_signatures = "(" in "".join(filter(lambda s: s != "operator()", suggestions))
accessorPos = self._getLastAccessorPos(line)
if are_signatures:
suggestions = [" "] + suggestions
Expand All @@ -156,26 +159,27 @@ def _completeImpl(self, line):
# suggestion already contains the variable name, this can happen if
# e.g. there is only one valid completion
if len(suggestions) > 1 or line[:accessorPos] != suggestions[0][:accessorPos]:
suggestions = [line[:accessorPos]+sugg for sugg in suggestions]
suggestions = [line[:accessorPos] + sugg for sugg in suggestions]
return suggestions

def complete(self, ip, event) :
'''
def complete(self, ip, event):
"""
Autocomplete interfacing to TTabCom. If an accessor of a scope is
present in the line, the suggestions are prepended with the line.
That's how completers work. For example:
myGraph.Set<tab> will return "myGraph.Set+suggestion in the list of
suggestions.
'''
"""
return self._completeImpl(event.line)


_cppCompleter = CppCompleter()


def load_ipython_extension(ipython):
_cppCompleter.activate()
ipython.set_hook('complete_command', _cppCompleter.complete, re_key=r"[(.*)[\.,::,\->](.*)]|(.*)")
ipython.set_hook("complete_command", _cppCompleter.complete, re_key=r"[(.*)[\.,::,\->](.*)]|(.*)")


def unload_ipython_extension(ipython):
_cppCompleter.deactivate()

Loading
Loading