From f26a6cf4853d74c87ff1003c8026be5bad905ab7 Mon Sep 17 00:00:00 2001 From: Mattias Ellert Date: Apr 22 2017 18:12:15 +0000 Subject: Python 3 compatibility fixes (backport from upstream) --- diff --git a/root-python3-support.patch b/root-python3-support.patch new file mode 100644 index 0000000..bd114ce --- /dev/null +++ b/root-python3-support.patch @@ -0,0 +1,409 @@ +diff --git a/bindings/pyroot/JsMVA/DataLoader.py b/bindings/pyroot/JsMVA/DataLoader.py +index 4f5d07e..fa738c0 100644 +--- a/bindings/pyroot/JsMVA/DataLoader.py ++++ b/bindings/pyroot/JsMVA/DataLoader.py +@@ -5,7 +5,12 @@ + + + from ROOT import TH1F, TMVA, TBufferJSON +-import JPyInterface ++import sys ++if sys.version_info >= (3, 0): ++ from JsMVA import JPyInterface ++else: ++ import JPyInterface ++from JsMVA.Utils import xrange + import ROOT + + +diff --git a/bindings/pyroot/JsMVA/Factory.py b/bindings/pyroot/JsMVA/Factory.py +index 3afefbf..13fda56 100644 +--- a/bindings/pyroot/JsMVA/Factory.py ++++ b/bindings/pyroot/JsMVA/Factory.py +@@ -6,7 +6,12 @@ + + import ROOT + from ROOT import TMVA +-import JPyInterface ++import sys ++if sys.version_info >= (3, 0): ++ from JsMVA import JPyInterface ++else: ++ import JPyInterface ++from JsMVA.Utils import xrange + from xml.etree.ElementTree import ElementTree + import json + from IPython.core.display import display, HTML, clear_output +@@ -681,7 +686,12 @@ def ChangeCallOriginal__init__(*args, **kwargs): + hasColor = False + args = list(args) + for arg_idx in xrange(len(args)): +- if isinstance(args[arg_idx], basestring) and args[arg_idx].find(":")!=-1: ++ # basestring==(str, unicode) in Python2, which translates to str in Python3 ++ if sys.version_info >= (3, 0): ++ is_string = isinstance(args[arg_idx], str) ++ else: ++ is_string = isinstance(args[arg_idx], basestring) ++ if is_string and args[arg_idx].find(":")!=-1: + if args[arg_idx].find("Color")!=-1: + hasColor = True + if args[arg_idx].find("!Color")==-1: +@@ -825,4 +835,4 @@ def DrawDNNWeights(fac, datasetName, methodName="DNN"): + button = widgets.Button(description="Draw", font_weight="bold", font_size="16") + button.on_click(drawWrapper) + box = widgets.HBox([selectLayer, button]) +- display(box) +\ No newline at end of file ++ display(box) +diff --git a/bindings/pyroot/JsMVA/JPyInterface.py b/bindings/pyroot/JsMVA/JPyInterface.py +index 51b32f1..068ab45 100644 +--- a/bindings/pyroot/JsMVA/JPyInterface.py ++++ b/bindings/pyroot/JsMVA/JPyInterface.py +@@ -8,10 +8,12 @@ + from IPython.core.display import display, HTML + from string import Template + import ROOT +-import DataLoader +-import Factory +-import types +-import OutputTransformer ++import sys ++if sys.version_info >= (3, 0): ++ from JsMVA import DataLoader, Factory ++else: ++ import DataLoader, Factory ++from JsMVA import OutputTransformer + + + ## Function inserter class +@@ -94,15 +96,15 @@ class functions: + else: + opt = "" + for key in kwargs: +- if type(kwargs[key]) == types.BooleanType: ++ if isinstance(kwargs[key], bool): + if kwargs[key] == True: + opt += key + ":" + else: + opt += "!" + key + ":" +- elif type(kwargs[key]) == types.ListType: ++ elif isinstance(kwargs[key], list): + ss = "" + for o in kwargs[key]: +- if type(o) == types.DictType: ++ if isinstance(o, dict): + sst = "" + for kk in o: + sst += kk + "=" + str(o[kk]) + "," +diff --git a/bindings/pyroot/JsMVA/JsMVAMagic.py b/bindings/pyroot/JsMVA/JsMVAMagic.py +index 436ea41..b2b1edf 100644 +--- a/bindings/pyroot/JsMVA/JsMVAMagic.py ++++ b/bindings/pyroot/JsMVA/JsMVAMagic.py +@@ -23,7 +23,7 @@ class JsMVAMagic(Magics): + @magic_arguments() + @argument('arg', nargs="?", default="on", help='Enable/Disable JavaScript visualisation for TMVA') + def jsmva(self, line): +- from JPyInterface import functions ++ from JsMVA.JPyInterface import functions + args = parse_argstring(self.jsmva, line) + if args.arg == 'on': + functions.register() +@@ -35,4 +35,4 @@ class JsMVAMagic(Magics): + + ## Function for registering the magic class + def load_ipython_extension(ipython): +- ipython.register_magics(JsMVAMagic) +\ No newline at end of file ++ ipython.register_magics(JsMVAMagic) +diff --git a/bindings/pyroot/JsMVA/OutputTransformer.py b/bindings/pyroot/JsMVA/OutputTransformer.py +index 81393a4..7cc10a5 100644 +--- a/bindings/pyroot/JsMVA/OutputTransformer.py ++++ b/bindings/pyroot/JsMVA/OutputTransformer.py +@@ -3,7 +3,8 @@ + # @author Attila Bagoly + # This class will transform the TMVA original output to HTML formated output. + +-import DataLoader ++from JsMVA import DataLoader ++from JsMVA.Utils import xrange + import cgi + import re + +diff --git a/bindings/pyroot/JsMVA/Utils.py b/bindings/pyroot/JsMVA/Utils.py +new file mode 100644 +index 0000000..0abba09 +--- /dev/null ++++ b/bindings/pyroot/JsMVA/Utils.py +@@ -0,0 +1,10 @@ ++# -*- coding: utf-8 -*- ++# @package JsMVA.Utils ++# @author Enric Tejedor ++# Utilities module. ++ ++import sys ++if sys.version_info >= (3, 0): ++ xrange = range ++else: ++ xrange = xrange +diff --git a/bindings/pyroot/JupyROOT/__init__.py b/bindings/pyroot/JupyROOT/__init__.py +index 33e81da..e65acba 100644 +--- a/bindings/pyroot/JupyROOT/__init__.py ++++ b/bindings/pyroot/JupyROOT/__init__.py +@@ -1,4 +1,5 @@ +-import JupyROOT.utils ++from JupyROOT import cppcompleter, utils + + if '__IPYTHON__' in __builtins__ and __IPYTHON__: ++ cppcompleter.load_ipython_extension(get_ipython()) + utils.iPythonize() +diff --git a/bindings/pyroot/JupyROOT/cppcompleter.py b/bindings/pyroot/JupyROOT/cppcompleter.py +index d76fef8..d451409 100644 +--- a/bindings/pyroot/JupyROOT/cppcompleter.py ++++ b/bindings/pyroot/JupyROOT/cppcompleter.py +@@ -5,7 +5,7 @@ + # Author: Enric Tejedor CERN + #----------------------------------------------------------------------------- + +-import utils ++from JupyROOT import utils + import ROOT + + # Jit a wrapper for the ttabcom +@@ -35,7 +35,7 @@ class CppCompleter(object): + >>> comp = CppCompleter() + >>> comp.activate() + >>> for suggestion in comp._completeImpl("TH1"): +- ... print suggestion ++ ... print(suggestion) + TH1 + TH1C + TH1D +@@ -45,7 +45,7 @@ class CppCompleter(object): + TH1K + TH1S + >>> for suggestion in comp._completeImpl("TH2"): +- ... print suggestion ++ ... print(suggestion) + TH2 + TH2C + TH2D +@@ -58,20 +58,20 @@ class CppCompleter(object): + TH2S + >>> garbage = ROOT.gInterpreter.ProcessLine("TH1F* h") + >>> for suggestion in comp._completeImpl("h->GetA"): +- ... print suggestion ++ ... print(suggestion) + h->GetArray + h->GetAsymmetry + h->GetAt + h->GetAxisColor + >>> garbage = ROOT.gInterpreter.ProcessLine("TH1F aa") + >>> for suggestion in comp._completeImpl("aa.Add("): +- ... print suggestion.replace("\\t"," ") ++ ... print(suggestion.replace("\\t"," ")) + + Bool_t Add(TF1* h1, Double_t c1 = 1, Option_t* option = "") + Bool_t Add(const TH1* h, const TH1* h2, Double_t c1 = 1, Double_t c2 = 1) // *MENU* + Bool_t Add(const TH1* h1, Double_t c1 = 1) + >>> for suggestion in comp._completeImpl("TROOT::Is"): +- ... print suggestion ++ ... print(suggestion) + IsA + IsBatch + IsEqual +@@ -89,7 +89,7 @@ class CppCompleter(object): + IsZombie + >>> comp.deactivate() + >>> for suggestion in comp._completeImpl("TG"): +- ... print suggestion ++ ... print(suggestion) + ''' + + def __init__(self): +diff --git a/bindings/pyroot/JupyROOT/handlers.py b/bindings/pyroot/JupyROOT/handlers.py +index a46c404..2181ad3 100644 +--- a/bindings/pyroot/JupyROOT/handlers.py ++++ b/bindings/pyroot/JupyROOT/handlers.py +@@ -48,11 +48,18 @@ class IOHandler(object): + def EndCapture(self): + _lib.JupyROOTExecutorHandler_EndCapture() + ++ def Decode(self, obj): ++ import sys ++ if sys.version_info >= (3, 0): ++ return obj.decode('utf-8') ++ else: ++ return obj ++ + def GetStdout(self): +- return _lib.JupyROOTExecutorHandler_GetStdout() ++ return self.Decode(_lib.JupyROOTExecutorHandler_GetStdout()) + + def GetStderr(self): +- return _lib.JupyROOTExecutorHandler_GetStderr() ++ return self.Decode(_lib.JupyROOTExecutorHandler_GetStderr()) + + def GetStreamsDicts(self): + out = self.GetStdout() +@@ -65,7 +72,7 @@ class Runner(object): + ''' Asynchrously run functions + >>> import time + >>> def f(code): +- ... print code ++ ... print(code) + >>> r= Runner(f) + >>> r.Run("ss") + ss +@@ -73,16 +80,16 @@ class Runner(object): + ss + >>> def g(msg): + ... time.sleep(.5) +- ... print msg ++ ... print(msg) + >>> r= Runner(g) +- >>> r.AsyncRun("Asynchronous");print "Synchronous";time.sleep(1) ++ >>> r.AsyncRun("Asynchronous");print("Synchronous");time.sleep(1) + Synchronous + Asynchronous +- >>> r.AsyncRun("Asynchronous"); print r.HasFinished() ++ >>> r.AsyncRun("Asynchronous"); print(r.HasFinished()) + False + >>> time.sleep(1) + Asynchronous +- >>> print r.HasFinished() ++ >>> print(r.HasFinished()) + True + ''' + def __init__(self, function): +@@ -118,7 +125,7 @@ class JupyROOTDeclarer(Runner): + ''' Asynchrously execute declarations + >>> import ROOT + >>> d = JupyROOTDeclarer() +- >>> d.Run("int f(){return 3;}") ++ >>> d.Run("int f(){return 3;}".encode("utf-8")) + 1 + >>> ROOT.f() + 3 +@@ -130,7 +137,7 @@ class JupyROOTExecutor(Runner): + r''' Asynchrously execute process lines + >>> import ROOT + >>> d = JupyROOTExecutor() +- >>> d.Run('cout << "Here am I" << endl;') ++ >>> d.Run('cout << "Here am I" << endl;'.encode("utf-8")) + 1 + ''' + def __init__(self): +diff --git a/bindings/pyroot/JupyROOT/kernel/utils.py b/bindings/pyroot/JupyROOT/kernel/utils.py +index 300570c..db34847 100644 +--- a/bindings/pyroot/JupyROOT/kernel/utils.py ++++ b/bindings/pyroot/JupyROOT/kernel/utils.py +@@ -12,12 +12,12 @@ + import os + from glob import glob + ++import importlib ++ + from JupyROOT.handlers import IOHandler, JupyROOTDeclarer, JupyROOTExecutor + + import ROOT + +-import __builtin__ +- + _ioHandler = None + _Executor = None + _Declarer = None +@@ -48,7 +48,7 @@ class MagicLoader(object): + if file != magics_path.replace("*.py","__init__.py"): + module_path="JupyROOT.kernel.magics."+file.split("/")[-1].replace(".py","") + try: +- module= __builtin__.__import__(module_path, globals(), locals(), ['register_magics'], -1) ++ module = importlib.import_module(module_path) + module.register_magics(kernel) + except ImportError: + raise Exception("Error importing Magic: %s"%module_path) +diff --git a/bindings/pyroot/JupyROOT/utils.py b/bindings/pyroot/JupyROOT/utils.py +index 6c41980..0a17e85 100644 +--- a/bindings/pyroot/JupyROOT/utils.py ++++ b/bindings/pyroot/JupyROOT/utils.py +@@ -14,7 +14,6 @@ import pty + import itertools + import re + import fnmatch +-import handlers + import time + from hashlib import sha1 + from contextlib import contextmanager +@@ -24,7 +23,7 @@ from IPython.display import HTML + from IPython.core.extensions import ExtensionManager + import IPython.display + import ROOT +-import cppcompleter ++from JupyROOT import handlers + + # We want iPython to take over the graphics + ROOT.gROOT.SetBatch() +@@ -200,7 +199,7 @@ def _codeToFilename(code): + >>> _codeToFilename("int f(i){return i*i;}") + 'dbf7e731.C' + ''' +- fileNameBase = sha1(code).hexdigest()[0:8] ++ fileNameBase = sha1(code.encode('utf-8')).hexdigest()[0:8] + return fileNameBase + ".C" + + def _dumpToUniqueFile(code): +@@ -250,6 +249,9 @@ class StreamCapture(object): + + self.asyncCapturer = handlers.Runner(self.syncCapture) + ++ self.isFirstPreExecute = True ++ self.isFirstPostExecute = True ++ + def syncCapture(self, defout = ''): + self.outString = defout + self.errString = defout +@@ -264,6 +266,9 @@ class StreamCapture(object): + time.sleep(waitTime) + + def pre_execute(self): ++ if self.isFirstPreExecute: ++ self.isFirstPreExecute = False ++ return 0 + # Unify C++ and Python outputs + self.nbOutStream = sys.stdout + sys.stdout = sys.__stdout__ +@@ -276,6 +281,10 @@ class StreamCapture(object): + self.asyncCapturer.AsyncRun('') + + def post_execute(self): ++ if self.isFirstPostExecute: ++ self.isFirstPostExecute = False ++ self.isFirstPreExecute = False ++ return 0 + self.flag = False + self.asyncCapturer.Wait() + self.ioHandler.Poll() +@@ -472,14 +481,13 @@ def setStyle(): + + captures = [] + +-def loadExtensionsAndCapturers(): ++def loadMagicsAndCapturers(): + global captures + extNames = ["JupyROOT.magics." + name for name in ["cppmagic","jsrootmagic"]] + ip = get_ipython() + extMgr = ExtensionManager(ip) + for extName in extNames: + extMgr.load_extension(extName) +- cppcompleter.load_ipython_extension(ip) + captures.append(StreamCapture()) + captures.append(CaptureDrawnPrimitives()) + +@@ -498,7 +506,7 @@ def enableCppHighlighting(): + + def iPythonize(): + setStyle() +- loadExtensionsAndCapturers() ++ loadMagicsAndCapturers() + enableCppHighlighting() + enhanceROOTModule() + welcomeMsg() diff --git a/root.spec b/root.spec index a047ab8..992d59b 100644 --- a/root.spec +++ b/root.spec @@ -23,7 +23,7 @@ Name: root Version: 6.08.06 %global libversion %(cut -d. -f 1-2 <<< %{version}) -Release: 2%{?dist} +Release: 3%{?dist} Summary: Numerical data analysis framework License: LGPLv2+ @@ -107,6 +107,9 @@ Patch20: %{name}-python-install-path.patch # https://sft.its.cern.ch/jira/browse/ROOT-8702 # https://github.com/root-project/root/pull/430 Patch21: %{name}-aarch64.patch +# Python 3 compatibility fixes +# Backported from upstream git (6.08 branch) +Patch22: %{name}-python3-support.patch # s390 is not supported by cling: "error: unknown target # triple 's390-ibm-linux', please use -triple or -arch" @@ -1582,6 +1585,7 @@ ROOT as a Jupyter Notebook. %patch19 -p1 %patch20 -p1 %patch21 -p1 +%patch22 -p1 # Remove bundled sources in order to be sure they are not used # * afterimage @@ -3140,6 +3144,9 @@ fi %{_datadir}/%{name}/notebook %changelog +* Fri Apr 21 2017 Mattias Ellert - 6.08.06-3 +- Python 3 compatibility fixes (backport from upstream) + * Wed Mar 15 2017 Mattias Ellert - 6.08.06-2 - Fix relocation problems on aarch64 - using patch from the llvm package - Re-enable building on aarch64 - works again with the above patch