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: 1 addition & 0 deletions bindings/pyroot/pythonizations/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ if(roofit)
ROOT/_pythonization/_roofit/_roojsonfactorywstool.py
ROOT/_pythonization/_roofit/_roomcstudy.py
ROOT/_pythonization/_roofit/_roomsgservice.py
ROOT/_pythonization/_roofit/_rooplot.py
ROOT/_pythonization/_roofit/_rooprodpdf.py
ROOT/_pythonization/_roofit/_roorealvar.py
ROOT/_pythonization/_roofit/_roosimultaneous.py
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,28 @@ def _SetDirectory_SetOwnership(self, dir):
import ROOT

ROOT.SetOwnership(self, False)


def declare_cpp_owned_arg(position, name, positional_args, keyword_args, condition=lambda _: True):
"""
Helper function to drop Python ownership of a specific function argument
with a given position and name, referring to the C++ signature.

positional_args and keyword_args should be the usual args and kwargs passed
to the function, and condition is an optional condition on which the Python
ownership is dropped.
"""
import ROOT

# has to match the C++ argument name
if name in keyword_args:
arg = keyword_args[name]
elif len(positional_args) > position:
arg = positional_args[0]
else:
# This can happen if the function was called with too few arguments.
# In that case we should not do anything.
return

if condition(arg):
ROOT.SetOwnership(arg, False)
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
from ._roojsonfactorywstool import RooJSONFactoryWSTool
from ._roomcstudy import RooMCStudy
from ._roomsgservice import RooMsgService
from ._rooplot import RooPlot
from ._rooprodpdf import RooProdPdf
from ._roorealvar import RooRealVar
from ._roosimultaneous import RooSimultaneous
Expand Down Expand Up @@ -69,6 +70,7 @@
RooJSONFactoryWSTool,
RooMCStudy,
RooMsgService,
RooPlot,
RooProdPdf,
RooRealVar,
RooSimultaneous,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,19 @@ def _pack_cmd_args(*args, **kwargs):
assert len(kwargs) == 0

# Put RooCmdArgs in a RooLinkedList
cmdList = ROOT.RooLinkedList()
cmd_list = ROOT.RooLinkedList()
for cmd in args:
if not isinstance(cmd, ROOT.RooCmdArg):
raise TypeError("This function only takes RooFit command arguments.")
cmdList.Add(cmd)
cmd_list.Add(cmd)

return cmdList
# The RooLinkedList passed to functions like fitTo() is expected to be
# non-owning. To make sure that the RooCmdArgs live long enough, we attach
# them as an attribute of the output list, such that the Python reference
# counter doesn't hit zero.
cmd_list._owning_pylist = args

return cmd_list


class RooAbsPdf(RooAbsReal):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Authors:
# * Jonas Rembser 09/2023
################################################################################
# Copyright (C) 1995-2020, Rene Brun and Fons Rademakers. #
# All rights reserved. #
# #
# For the licensing terms see $ROOTSYS/LICENSE. #
# For the list of contributors see $ROOTSYS/README/CREDITS. #
################################################################################


class RooPlot(object):
def addObject(self, *args, **kwargs):
from ROOT._pythonization._memory_utils import declare_cpp_owned_arg

# Python should transfer the ownership to the RooPlot
declare_cpp_owned_arg(0, "obj", args, kwargs)

return self._addObject(*args, **kwargs)
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,26 @@ def _iter_pyz(self):
yield o


def _TCollection_Add(self, *args, **kwargs):
from ROOT._pythonization._memory_utils import declare_cpp_owned_arg

def condition(_):
return self.IsOwner()

declare_cpp_owned_arg(0, "obj", args, kwargs, condition=condition)

self._Add(*args, **kwargs)


@pythonization('TCollection')
def pythonize_tcollection(klass):
# Parameters:
# klass: class to be pythonized

# Pythonize Add()
klass._Add = klass.Add
klass.Add = _TCollection_Add

# Add Python lists methods
klass.append = klass.Add
klass.remove = _remove_pyz
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@

import ROOT

from . import pythonization


def set_size(self, buf):
# Parameters:
Expand Down Expand Up @@ -214,3 +216,19 @@ def set_size(self, buf):
# Add the composite to the list of pythonizors
ROOT._cppyy.py.add_pythonization(comp)

def _TMultiGraph_Add(self, *args, **kwargs):
"""
The TMultiGraph always takes ownership of the added graphs.
"""
from ROOT._pythonization._memory_utils import declare_cpp_owned_arg

declare_cpp_owned_arg(0, "graph", args, kwargs)

self._Add(*args, **kwargs)


@pythonization("TMultiGraph")
def pythonize_tmultigraph(klass):
# Pythonizations for TMultiGraph::Add
klass._Add = klass.Add
klass.Add = _TMultiGraph_Add
Original file line number Diff line number Diff line change
Expand Up @@ -241,11 +241,30 @@ def _index_pyz(self, val):
return idx


def _TSeqCollection_AddAt(self, *args, **kwargs):
from ROOT._pythonization._memory_utils import declare_cpp_owned_arg

def condition(_):
return self.IsOwner()

declare_cpp_owned_arg(0, "obj", args, kwargs, condition=condition)

self._AddAt(*args, **kwargs)


@pythonization('TSeqCollection')
def pythonize_tseqcollection(klass):
from ROOT._pythonization._tcollection import _TCollection_Add

# Parameters:
# klass: class to be pythonized

# Pythonize Add() methods
klass._Add = klass.Add
klass.Add = _TCollection_Add
klass._AddAt = klass.AddAt
klass.AddAt = _TSeqCollection_AddAt

# Item access methods
klass.__getitem__ = _getitem_pyz
klass.__setitem__ = _setitem_pyz
Expand All @@ -257,3 +276,17 @@ def pythonize_tseqcollection(klass):
klass.reverse = _reverse_pyz
klass.sort = _sort_pyz
klass.index = _index_pyz


@pythonization("TList")
def pythonize_tlist(klass):
from ROOT._pythonization._tcollection import _TCollection_Add

# Parameters:
# klass: class to be pythonized

# Pythonize Add() methods
klass._Add = klass.Add
klass.Add = _TCollection_Add
klass._AddAt = klass.AddAt
klass.AddAt = _TSeqCollection_AddAt
Loading