From 702f37dda8fb0e248eed46ec0492e19512ea969a Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Tue, 28 Nov 2017 15:05:32 +0100
Subject: [PATCH 01/56] Use Python 3 compatible `except` syntax.

The forward compatible syntax from 2.6 plus is:

    except SomeException as err

rather than

    except SomeException, err
---
 Gaudi/python/Gaudi/Main.py                            | 2 +-
 GaudiExamples/scripts/ExtendedProperties2.py          | 6 +++---
 GaudiExamples/tests/scripts/test_timing_histo_file.py | 2 +-
 GaudiKernel/python/GaudiKernel/Configurable.py        | 2 +-
 GaudiKernel/python/GaudiKernel/ConfigurableDb.py      | 2 +-
 GaudiKernel/python/GaudiKernel/PropertyProxy.py       | 8 ++++----
 GaudiKernel/scripts/genconfuser.py                    | 4 ++--
 GaudiKernel/tests/nose/test_Configurables.py          | 6 +++---
 GaudiPolicy/python/GaudiTesting/BaseTest.py           | 2 +-
 GaudiPolicy/python/GaudiTesting/Run.py                | 2 +-
 GaudiPolicy/scripts/ZipPythonDir.py                   | 2 +-
 GaudiPython/python/GaudiPython/Bindings.py            | 6 +++---
 12 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/Gaudi/python/Gaudi/Main.py b/Gaudi/python/Gaudi/Main.py
index 85b6884636..5be7378412 100644
--- a/Gaudi/python/Gaudi/Main.py
+++ b/Gaudi/python/Gaudi/Main.py
@@ -430,7 +430,7 @@ class gaudimain(object):
             # It may not be 100% correct, but usually it means a segfault in C++
             self.ip.setProperty('ReturnCode', str(128 + 11))
             statuscode = False
-        except Exception, x:
+        except Exception as x:
             print 'Exception:', x
             # for other exceptions, just set a generic error code
             self.ip.setProperty('ReturnCode', '1')
diff --git a/GaudiExamples/scripts/ExtendedProperties2.py b/GaudiExamples/scripts/ExtendedProperties2.py
index 7b44bf8022..8262b63c4c 100755
--- a/GaudiExamples/scripts/ExtendedProperties2.py
+++ b/GaudiExamples/scripts/ExtendedProperties2.py
@@ -71,18 +71,18 @@ if '__main__' == __name__:
 
     try:
         xp2.SVector5 = [1, 2, 3, 4, 5, 6]
-    except Exception, e:
+    except Exception as e:
         print ' Exception: ', e
 
     try:
         xp2.Point3D = (1, 2, 3, 4)
-    except Exception, e:
+    except Exception as e:
         print ' Exception: ', e
 
     if not isWin:
         try:
             xp2.Vector4D = (1, 2, 3)
-        except Exception, e:
+        except Exception as e:
             print ' Exception: ', e
 
     xp2.Vectors3D = [(1, 2, 3), (4, 5, 6), [7, 8, 9]]
diff --git a/GaudiExamples/tests/scripts/test_timing_histo_file.py b/GaudiExamples/tests/scripts/test_timing_histo_file.py
index 6387d56a37..99ee9013b3 100755
--- a/GaudiExamples/tests/scripts/test_timing_histo_file.py
+++ b/GaudiExamples/tests/scripts/test_timing_histo_file.py
@@ -57,7 +57,7 @@ def test():
 if __name__ == '__main__':
     try:
         test()
-    except AssertionError, a:
+    except AssertionError as a:
         print "FAILURE:", a
         sys.exit(1)
     print "SUCCESS"
diff --git a/GaudiKernel/python/GaudiKernel/Configurable.py b/GaudiKernel/python/GaudiKernel/Configurable.py
index 1f24e8f25e..4de14cb4c5 100644
--- a/GaudiKernel/python/GaudiKernel/Configurable.py
+++ b/GaudiKernel/python/GaudiKernel/Configurable.py
@@ -502,7 +502,7 @@ class Configurable(object):
         if hasattr(cc, 'setParent') and parent:
             try:
                 cc.setParent(parent)
-            except RuntimeError, e:
+            except RuntimeError as e:
                 # temporary backdoor resolution for compatibility
                 log.error(str(e) + '%s', error_explanation)
                 ccbd = cc.configurables[cc.getJobOptName()]
diff --git a/GaudiKernel/python/GaudiKernel/ConfigurableDb.py b/GaudiKernel/python/GaudiKernel/ConfigurableDb.py
index 969265f590..0fab3ee0c9 100644
--- a/GaudiKernel/python/GaudiKernel/ConfigurableDb.py
+++ b/GaudiKernel/python/GaudiKernel/ConfigurableDb.py
@@ -139,7 +139,7 @@ def loadConfigurableDb():
             log.debug("\t-loading [%s]...", confDb)
             try:
                 cfgDb._loadModule(confDb)
-            except Exception, err:
+            except Exception as err:
                 log.warning("Could not load file [%s] !", confDb)
                 log.warning("Reason: %s", err)
             nFiles += 1
diff --git a/GaudiKernel/python/GaudiKernel/PropertyProxy.py b/GaudiKernel/python/GaudiKernel/PropertyProxy.py
index dcae4ab212..58c0ce45d0 100644
--- a/GaudiKernel/python/GaudiKernel/PropertyProxy.py
+++ b/GaudiKernel/python/GaudiKernel/PropertyProxy.py
@@ -143,7 +143,7 @@ class PropertyProxy(object):
                     except AttributeError:
                      # value not yet set
                         pass
-            except ValueError, e:
+            except ValueError as e:
                 if allowcompat:
                     log.error('inconsistent value types for %s.%s (%s)' %
                               (obj.getName(), self.descr.__name__, str(e)))
@@ -195,7 +195,7 @@ class GaudiHandlePropertyProxyBase(PropertyProxy):
                 default = self.convertDefaultToBeSet(obj, default)
                 if default:
                     self.__set__(obj, default)
-            except AttributeError, e:
+            except AttributeError as e:
                 # change type of exception to avoid false error message
                 raise RuntimeError(*e.args)
 
@@ -260,7 +260,7 @@ class GaudiHandlePropertyProxyBase(PropertyProxy):
                     conf = self.getDefaultConfigurable(
                         typeAndName, self.fullPropertyName(obj))
 #               print self.fullPropertyName(obj) + ": Setting default private configurable (from default handle): %r" % conf
-                except AttributeError, e:
+                except AttributeError as e:
                     # change type of exception to avoid false error message
                     raise RuntimeError(*e.args)
                 if conf is None:
@@ -375,7 +375,7 @@ class DataObjectHandleBasePropertyProxy(PropertyProxy):
                 default = self.convertValueToBeSet(obj, default)
                 if default:
                     self.__set__(obj, default)
-            except AttributeError, e:
+            except AttributeError as e:
                 # change type of exception to avoid false error message
                 raise RuntimeError(*e.args)
 
diff --git a/GaudiKernel/scripts/genconfuser.py b/GaudiKernel/scripts/genconfuser.py
index b823474e9e..49722b919f 100755
--- a/GaudiKernel/scripts/genconfuser.py
+++ b/GaudiKernel/scripts/genconfuser.py
@@ -62,7 +62,7 @@ def loadConfigurableDb():
         log.debug("\t-loading [%s]..." % confDb)
         try:
             cfgDb._loadModule(confDb)
-        except Exception, err:
+        except Exception as err:
             # It may happen that the file is found but not completely
             # written, usually during parallel builds, but we do not care.
             log.warning("Could not load file [%s] !", confDb)
@@ -254,7 +254,7 @@ def main():
     try:
         logging.info("Creating directory %r", output_dir)
         os.makedirs(output_dir, 0755)
-    except OSError, err:
+    except OSError as err:
         import errno
         if err.errno == errno.EEXIST:
             # somebody already - perhaps concurrently - created that dir.
diff --git a/GaudiKernel/tests/nose/test_Configurables.py b/GaudiKernel/tests/nose/test_Configurables.py
index 8b132d7291..5b4e2cff78 100644
--- a/GaudiKernel/tests/nose/test_Configurables.py
+++ b/GaudiKernel/tests/nose/test_Configurables.py
@@ -49,7 +49,7 @@ def test_invalid_value():
         raise
     except ValueError:
         pass
-    except Exception, x:
+    except Exception as x:
         assert False, 'ValueError exception expected, got %s' % type(
             x).__name__
 
@@ -60,7 +60,7 @@ def test_invalid_value():
         raise
     except ValueError:
         pass
-    except Exception, x:
+    except Exception as x:
         assert False, 'ValueError exception expected, got %s' % type(
             x).__name__
 
@@ -85,7 +85,7 @@ def test_invalid_key():
         raise
     except AttributeError:
         pass
-    except Exception, x:
+    except Exception as x:
         assert False, 'AttributeError exception expected, got %s' % type(
             x).__name__
 
diff --git a/GaudiPolicy/python/GaudiTesting/BaseTest.py b/GaudiPolicy/python/GaudiTesting/BaseTest.py
index 48cc70c191..1e598ac143 100644
--- a/GaudiPolicy/python/GaudiTesting/BaseTest.py
+++ b/GaudiPolicy/python/GaudiTesting/BaseTest.py
@@ -54,7 +54,7 @@ def kill_tree(ppid, sig):
     try:
         log.debug('killing process %d', ppid)
         os.kill(ppid, sig)
-    except OSError, err:
+    except OSError as err:
         if err.errno != 3:  # No such process
             raise
         log.debug('no such process %d', ppid)
diff --git a/GaudiPolicy/python/GaudiTesting/Run.py b/GaudiPolicy/python/GaudiTesting/Run.py
index 7424e902c6..d7026a3318 100644
--- a/GaudiPolicy/python/GaudiTesting/Run.py
+++ b/GaudiPolicy/python/GaudiTesting/Run.py
@@ -162,7 +162,7 @@ def main():
                 test_module, test_class)
             fileToTest = test_class(filename)
             results = fileToTest.run()
-        except Exception, e:
+        except Exception as e:
             logging.error(
                 'Exception caught when trying to instantiate qmt test python object')
             logging.error(e)
diff --git a/GaudiPolicy/scripts/ZipPythonDir.py b/GaudiPolicy/scripts/ZipPythonDir.py
index b4a4daac33..05e6456e6f 100755
--- a/GaudiPolicy/scripts/ZipPythonDir.py
+++ b/GaudiPolicy/scripts/ZipPythonDir.py
@@ -173,7 +173,7 @@ def zipdir(directory, no_pyc=False):
             log.info("File '%s' closed", filename)
         else:
             log.info("Nothing to do on '%s'", filename)
-    except UnicodeDecodeError, x:
+    except UnicodeDecodeError as x:
         log.error("Wrong encoding in file '%s':", src)
         log.error("    %s", x)
         log.error("Probably you forgot the line '# -*- coding: utf-8 -*-'")
diff --git a/GaudiPython/python/GaudiPython/Bindings.py b/GaudiPython/python/GaudiPython/Bindings.py
index 83c2be7d04..4ab5238dc2 100644
--- a/GaudiPython/python/GaudiPython/Bindings.py
+++ b/GaudiPython/python/GaudiPython/Bindings.py
@@ -107,7 +107,7 @@ class InterfaceCast(object):
                     return ip
                 else:
                     print "ERROR: queryInterface failed for", obj, "interface:", self.type
-            except Exception, e:
+            except Exception as e:
                 print "ERROR: exception", e, "caught when retrieving interface", self.type, "for object", obj
                 import traceback
                 traceback.print_stack()
@@ -347,7 +347,7 @@ class iProperty(object):
             for p in props:
                 try:
                     dct[p.name()] = PropertyEntry(p)
-                except (ValueError, TypeError), e:
+                except (ValueError, TypeError) as e:
                     raise ValueError, "gaudimodule.iProperty.properties(): %s%s processing property %s.%s = %s" % \
                         (e.__class__.__name__, e.args,
                          propsFrom, p.name(), p.value())
@@ -1393,7 +1393,7 @@ def getComponentProperties(name):
                     obj = factory.instantiate(dummysvc)
                 else:
                     obj = factory.instantiate(svcloc)
-            except RuntimeError, text:
+            except RuntimeError as text:
                 print 'Error instantiating', cname, ' from ', name
                 print text
                 continue
-- 
GitLab


From c522ada4797dd391f3e00f28baefb81d9ad9752b Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Tue, 28 Nov 2017 15:07:22 +0100
Subject: [PATCH 02/56] Use Python 3 compatible printing and importing.

---
 GaudiPolicy/scripts/createProjVersHeader.py |  6 +++---
 cmake/cmakeLogToCacheGrind.py               |  6 +++---
 cmake/extract_qmtest_metadata.py            | 16 ++++++++--------
 cmake/modules/scan_dict_deps.py             |  2 +-
 cmake/tests/cmake_coverage.py               | 15 ++++++++-------
 cmake/tests/cmake_test_utils.py             | 10 +++++-----
 cmake/tests/test_crashes.py                 | 18 +++++++++---------
 7 files changed, 37 insertions(+), 36 deletions(-)

diff --git a/GaudiPolicy/scripts/createProjVersHeader.py b/GaudiPolicy/scripts/createProjVersHeader.py
index 5c82c4ce69..c78f1043dd 100755
--- a/GaudiPolicy/scripts/createProjVersHeader.py
+++ b/GaudiPolicy/scripts/createProjVersHeader.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-
+from __future__ import print_function
 import os
 import sys
 import re
@@ -21,7 +21,7 @@ def main():
 
     project, version, outputfile = args
     if not opts.quiet:
-        print "Creating %s for %s %s" % (outputfile, project, version)
+        print("Creating %s for %s %s" % (outputfile, project, version))
 
     for style in [lhcb_ver_style, atlas_ver_style, plain_ver_style]:
         m = re.match(style, version)
@@ -38,7 +38,7 @@ def main():
     outdir = os.path.dirname(outputfile)
     if not os.path.exists(outdir):
         if not opts.quiet:
-            print "Creating directory", outdir
+            print("Creating directory", outdir)
         os.makedirs(outdir)
 
     # Prepare data to be written
diff --git a/cmake/cmakeLogToCacheGrind.py b/cmake/cmakeLogToCacheGrind.py
index b3ae5cdb6a..8617fafa10 100644
--- a/cmake/cmakeLogToCacheGrind.py
+++ b/cmake/cmakeLogToCacheGrind.py
@@ -5,12 +5,12 @@ Gaudi cmake process (See Instrument.cmake) and create an other file
 understandable by kcachegrind for easy visualization of where we spend time in
 cmake.
 '''
+from __future__ import print_function
 import sys
 
 
 def usage():
-    print "Invalid arguments\nProper syntax is :\n  %s <log file> <callgrind file>" % sys.argv[
-        0]
+    print("Invalid arguments\nProper syntax is :\n  %s <log file> <callgrind file>" % sys.argv[0])
 
 
 if len(sys.argv) != 3:
@@ -45,7 +45,7 @@ for line in open(sys.argv[1]).readlines():
     elif key == 'ENDTIME':
         sfunc, stime = callStack.pop()
         if sfunc != func:
-            print 'Mismatch START/END for %s/%s' % (sfunc, func)
+            print('Mismatch START/END for %s/%s' % (sfunc, func))
             sys.exit()
         deltatime = int(time) - stime
         # add time spent to this function
diff --git a/cmake/extract_qmtest_metadata.py b/cmake/extract_qmtest_metadata.py
index 3a7c5bff94..1bcd78d7f3 100755
--- a/cmake/extract_qmtest_metadata.py
+++ b/cmake/extract_qmtest_metadata.py
@@ -81,8 +81,8 @@ def analyze_deps(pkg, rootdir):
         prereqs = [fix_test_name(el.text, pkg)
                    for el in tree.findall(prereq_xpath)]
         if prereqs:
-            print ('set_property(TEST {0} APPEND PROPERTY DEPENDS {1})'
-                   .format(name, ' '.join(prereqs)))
+            print('set_property(TEST {0} APPEND PROPERTY DEPENDS {1})'
+                  .format(name, ' '.join(prereqs)))
 
 
 def analyze_suites(pkg, rootdir):
@@ -110,13 +110,13 @@ def analyze_suites(pkg, rootdir):
 
     # transpose the dictionary of lists
     test_labels = collections.defaultdict(set)
-    for label, tests in labels.iteritems():
+    for label, tests in labels.items():
         for test in tests:
             test_labels[test].add(label)
 
-    for test, labels in test_labels.iteritems():
-        print ('set_property(TEST {0} APPEND PROPERTY LABELS {1})'
-               .format(test, ' '.join(labels)))
+    for test, labels in test_labels.items():
+        print('set_property(TEST {0} APPEND PROPERTY LABELS {1})'
+              .format(test, ' '.join(labels)))
 
 
 def analyze_disabling(pkg, rootdir):
@@ -138,8 +138,8 @@ def analyze_disabling(pkg, rootdir):
                      for el in tree.findall(unsupp_xpath)
                      if re.search(el.text, platform_id)]
         if skip_test:
-            print ('set_property(TEST {0} APPEND PROPERTY LABELS disabled)'
-                   .format(name))
+            print('set_property(TEST {0} APPEND PROPERTY LABELS disabled)'
+                  .format(name))
 
 
 if __name__ == '__main__':
diff --git a/cmake/modules/scan_dict_deps.py b/cmake/modules/scan_dict_deps.py
index c59b6bb3cb..1fe14c8de4 100755
--- a/cmake/modules/scan_dict_deps.py
+++ b/cmake/modules/scan_dict_deps.py
@@ -76,7 +76,7 @@ def main():
     if new_deps != old_deps:  # write it only if it has changed
         open(output, 'w').write(new_deps)
         if old_deps:
-            print 'info: dependencies changed: next build will trigger a reconfigure'
+            print('info: dependencies changed: next build will trigger a reconfigure')
 
 
 if __name__ == '__main__':
diff --git a/cmake/tests/cmake_coverage.py b/cmake/tests/cmake_coverage.py
index fea87d997c..ff3b3fb594 100755
--- a/cmake/tests/cmake_coverage.py
+++ b/cmake/tests/cmake_coverage.py
@@ -1,5 +1,6 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
+from __future__ import print_function
 import os
 import re
 import atexit
@@ -22,7 +23,7 @@ def update_coverage():
     else:
         data = {'lines': {}}
     lines = data['lines']
-    for filename, linenumbers in coverage.iteritems():
+    for filename, linenumbers in coverage.items():
         lines[filename] = sorted(linenumbers.union(lines.get(filename, [])))
     with open(COVERAGE_FILE, 'w') as report:
         cPickle.dump(data, report)
@@ -82,9 +83,9 @@ if __name__ == '__main__':
     lines = data['lines']
     for filename in sorted(lines):
         if not os.path.exists(filename):
-            print 'Unknown file', filename
+            print('Unknown file', filename)
             continue
-        print filename
+        print(filename)
         active_lines = set(get_active_lines(filename))
         touched_lines = set(lines[filename])
         missed_lines = active_lines.difference(touched_lines)
@@ -93,8 +94,8 @@ if __name__ == '__main__':
         touched_count = len(touched_lines)
         active_count = len(active_lines)
         if touched_count == active_count:
-            print '   coverage 100%'
+            print('   coverage 100%')
         else:
-            print ('   coverage %3d%%, missed: %s' %
-                   (float(touched_count) / active_count * 100,
-                    ', '.join(ranges)))
+            print('   coverage %3d%%, missed: %s' %
+                  (float(touched_count) / active_count * 100,
+                   ', '.join(ranges)))
diff --git a/cmake/tests/cmake_test_utils.py b/cmake/tests/cmake_test_utils.py
index 05a914b9ac..36c7ddfe1a 100644
--- a/cmake/tests/cmake_test_utils.py
+++ b/cmake/tests/cmake_test_utils.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-
+from __future__ import print_function
 from cmake_coverage import cmake_script
 from os.path import join, curdir
 
@@ -21,10 +21,10 @@ class CMakeTestScripts(object):
     def run(self, name):
         script_name = join(self.scripts_dir, 'test_%s.cmake' % name)
         out, err, returncode = cmake_script(script_name, cwd=self.base_dir)
-        print "---------- stdout ----------"
-        print out
-        print "---------- stderr ----------"
-        print err
+        print("---------- stdout ----------")
+        print(out)
+        print("---------- stderr ----------")
+        print(err)
         assert returncode == 0
 
     def test_scripts(self):
diff --git a/cmake/tests/test_crashes.py b/cmake/tests/test_crashes.py
index 0181c7ca1e..120ef02a05 100644
--- a/cmake/tests/test_crashes.py
+++ b/cmake/tests/test_crashes.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-
+from __future__ import print_function
 from cmake_coverage import cmake_script
 from os.path import join, dirname
 
@@ -10,10 +10,10 @@ scripts_dir = join(base_dir, 'cmake_scripts')
 def test_loops():
     script_name = join(scripts_dir, 'test_loops.cmake')
     out, err, returncode = cmake_script(script_name, cwd=base_dir)
-    print "---------- stdout ----------"
-    print out
-    print "---------- stderr ----------"
-    print err
+    print("---------- stdout ----------")
+    print(out)
+    print("---------- stderr ----------")
+    print(err)
     assert returncode != 0
     assert 'Infinite recursion detected at project Loop' in err
 
@@ -21,9 +21,9 @@ def test_loops():
 def test_missing_base():
     script_name = join(scripts_dir, 'test_missing_base.cmake')
     out, err, returncode = cmake_script(script_name, cwd=base_dir)
-    print "---------- stdout ----------"
-    print out
-    print "---------- stderr ----------"
-    print err
+    print("---------- stdout ----------")
+    print(out)
+    print("---------- stderr ----------")
+    print(err)
     assert returncode != 0
     assert 'Cannot find project IDoNotExist v0r0' in err
-- 
GitLab


From fb91a36b8551e523b43ae7dfd552b45269345ab5 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Tue, 28 Nov 2017 15:07:43 +0100
Subject: [PATCH 03/56] Use Python 3 compatible map and filter methods.

---
 cmake/modules/scan_dict_deps.py | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/cmake/modules/scan_dict_deps.py b/cmake/modules/scan_dict_deps.py
index 1fe14c8de4..da012c8462 100755
--- a/cmake/modules/scan_dict_deps.py
+++ b/cmake/modules/scan_dict_deps.py
@@ -1,7 +1,12 @@
 #!/usr/bin/env python
 import re
 
-from itertools import imap, ifilter
+try:
+    from itertools import imap, ifilter
+except ImportError:
+    # In Python 3, `map` and `filter` return iterables
+    imap = map
+    ifilter = filter
 from os.path import join, exists, isabs
 
 
@@ -16,8 +21,8 @@ def find_file(filename, searchpath):
     if isabs(filename):
         return filename if exists(filename) else None
     try:
-        return ifilter(exists, imap(lambda x: join(x, filename),
-                                    searchpath)).next()
+        return next(ifilter(exists, imap(lambda x: join(x, filename),
+                                        searchpath)))
     except StopIteration:
         return None
 
-- 
GitLab


From b5d0fb7af10593755ddc32130db5f4ea964e6cb6 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Tue, 28 Nov 2017 15:14:24 +0100
Subject: [PATCH 04/56] Python 3 compatibility for the cPickle module.

---
 GaudiPolicy/qmtest_classes/GaudiTest.py | 5 ++++-
 cmake/tests/cmake_coverage.py           | 5 ++++-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/GaudiPolicy/qmtest_classes/GaudiTest.py b/GaudiPolicy/qmtest_classes/GaudiTest.py
index 12027ad635..d0044c8d1c 100644
--- a/GaudiPolicy/qmtest_classes/GaudiTest.py
+++ b/GaudiPolicy/qmtest_classes/GaudiTest.py
@@ -62,7 +62,10 @@ if sys.platform == "win32":
     import win32pipe
     import win32process
 else:
-    import cPickle
+    try:
+        import cPickle
+    except ImportError:
+        import pickle as cPickle
     import fcntl
     import select
     import qm.sigmask
diff --git a/cmake/tests/cmake_coverage.py b/cmake/tests/cmake_coverage.py
index ff3b3fb594..62e4ced31c 100755
--- a/cmake/tests/cmake_coverage.py
+++ b/cmake/tests/cmake_coverage.py
@@ -4,7 +4,10 @@ from __future__ import print_function
 import os
 import re
 import atexit
-import cPickle
+try:
+    import cPickle
+except ImportError:
+    import pickle as cPickle
 from subprocess import Popen, PIPE
 from collections import defaultdict
 
-- 
GitLab


From f91f4072947530cd752bbb75a1cb285ccd484217 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Tue, 28 Nov 2017 17:45:35 +0100
Subject: [PATCH 05/56] Use *args and **kwargs rather than apply.

apply has been deprecated since 2.3+.
---
 GaudiKernel/scripts/genconfuser.py         | 2 +-
 GaudiKernel/scripts/make_patch.py          | 8 ++++----
 GaudiPolicy/python/GaudiTesting/QMTTest.py | 2 +-
 GaudiPolicy/qmtest_classes/GaudiTest.py    | 2 +-
 GaudiPython/python/GaudiPython/Bindings.py | 6 +++---
 GaudiRelease/svn_tag_release.py            | 4 ++--
 6 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/GaudiKernel/scripts/genconfuser.py b/GaudiKernel/scripts/genconfuser.py
index 49722b919f..1da6e45f7b 100755
--- a/GaudiKernel/scripts/genconfuser.py
+++ b/GaudiKernel/scripts/genconfuser.py
@@ -17,7 +17,7 @@ from GaudiKernel.ConfigurableDb import cfgDb
 logging.VERBOSE = (logging.INFO + logging.DEBUG) / 2
 logging.addLevelName(logging.VERBOSE, "VERBOSE")
 logging.verbose = lambda msg, *args, **kwargs: \
-    apply(logging.log, (logging.VERBOSE, msg) + args, kwargs)
+    logging.log(logging.VERBOSE, msg, *args, **kwargs)
 
 
 def _inheritsfrom(derived, basenames):
diff --git a/GaudiKernel/scripts/make_patch.py b/GaudiKernel/scripts/make_patch.py
index 441f64b99a..3a29dda57f 100755
--- a/GaudiKernel/scripts/make_patch.py
+++ b/GaudiKernel/scripts/make_patch.py
@@ -16,13 +16,13 @@ def command(cmd, *args, **kwargs):
     d.update(kwargs)
     cmd = [cmd] + list(args)
     logging.debug("Execute command: %r %r", " ".join(cmd), kwargs)
-    proc = apply(Popen, (cmd,), d)
+    proc = Popen(cmd, **d)
     return proc.communicate()
 
 
-cmt = lambda *args, **kwargs: apply(command, ("cmt",) + args, kwargs)
-cvs = lambda *args, **kwargs: apply(command, ("cvs",) + args, kwargs)
-svn = lambda *args, **kwargs: apply(command, ("svn",) + args, kwargs)
+cmt = lambda *args, **kwargs: command("cmt", *args, **kwargs)
+cvs = lambda *args, **kwargs: command("cvs", *args, **kwargs)
+svn = lambda *args, **kwargs: command("svn", *args, **kwargs)
 
 
 def broadcast_packages():
diff --git a/GaudiPolicy/python/GaudiTesting/QMTTest.py b/GaudiPolicy/python/GaudiTesting/QMTTest.py
index 6152dbe610..fddddd3ad2 100644
--- a/GaudiPolicy/python/GaudiTesting/QMTTest.py
+++ b/GaudiPolicy/python/GaudiTesting/QMTTest.py
@@ -72,7 +72,7 @@ class QMTTest(BaseTest):
                         # positional or keyword
                         if a not in positional and a not in kwargs:
                             kwargs[a] = self.extra_args[a]
-                    return apply(self.callable, args, kwargs)
+                    return self.callable(*args, **kwargs)
 
             # local names to be exposed in the script
             stdout_ref = self._expandReferenceFileName(self.reference)
diff --git a/GaudiPolicy/qmtest_classes/GaudiTest.py b/GaudiPolicy/qmtest_classes/GaudiTest.py
index d0044c8d1c..2539ee2d94 100644
--- a/GaudiPolicy/qmtest_classes/GaudiTest.py
+++ b/GaudiPolicy/qmtest_classes/GaudiTest.py
@@ -1506,7 +1506,7 @@ class GaudiExeTest(ExecTestBase):
                         # positional or keyword
                         if a not in positional and a not in kwargs:
                             kwargs[a] = self.extra_args[a]
-                    return apply(self.callable, args, kwargs)
+                    return self.callable(*args, **kwargs)
             # local names to be exposed in the script
             exported_symbols = {"self": self,
                                 "stdout": stdout,
diff --git a/GaudiPython/python/GaudiPython/Bindings.py b/GaudiPython/python/GaudiPython/Bindings.py
index 4ab5238dc2..58b6fd4cb4 100644
--- a/GaudiPython/python/GaudiPython/Bindings.py
+++ b/GaudiPython/python/GaudiPython/Bindings.py
@@ -697,7 +697,7 @@ class iHistogramSvc(iDataSvc):
         >>> svc = ...
         >>> histo = svc.book( .... )
         """
-        return apply(self._ihs.book, args)
+        return self._ihs.book(*args)
 
     def bookProf(self, *args):
         """
@@ -705,7 +705,7 @@ class iHistogramSvc(iDataSvc):
         >>> svc = ...
         >>> histo = svc.bookProf( .... )
         """
-        return apply(self._ihs.bookProf, args)
+        return self._ihs.bookProf(*args)
 
     def __getitem__(self, path):
         """
@@ -750,7 +750,7 @@ class iNTupleSvc(iDataSvc):
         iDataSvc.__init__(self, name, ints)
 
     def book(self, *args):
-        return apply(self._ints.book, args)
+        return self._ints.book(*args)
 
     def defineOutput(self, files, typ="Gaudi::RootCnvSvc"):
         """ Defines the mapping between logical names and the output file
diff --git a/GaudiRelease/svn_tag_release.py b/GaudiRelease/svn_tag_release.py
index d9d9b37979..e5981db718 100755
--- a/GaudiRelease/svn_tag_release.py
+++ b/GaudiRelease/svn_tag_release.py
@@ -18,7 +18,7 @@ from ConfigParser import ConfigParser
 
 def svn(*args, **kwargs):
     print "> svn", " ".join(args)
-    return apply(Popen, (["svn"] + list(args),), kwargs)
+    return Popen(["svn"] + list(args), **kwargs)
 
 
 def svn_ls(url):
@@ -42,7 +42,7 @@ def svn_exists(url):
 def checkout_structure(url, proj, branch):
     def checkout_level(base):
         dirs = ["%s/%s" % (base, d) for d in svn_ls(base) if d.endswith("/")]
-        apply(svn, ["up", "-N"] + dirs).wait()
+        svn("up", "-N", *args).wait()
         return dirs
 
     root = basename(url)
-- 
GitLab


From 8ff193589bac6d6d74b91f404b461d271b68d563 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Tue, 28 Nov 2017 18:08:40 +0100
Subject: [PATCH 06/56] Use Python 3 compatible exec.

Python 2 compatible:

    exec "some statement" in globals_dict, locals_dict

Python 2 and 3 compatible:

    exec("some statement", globals_dict, locals_dict)
---
 Gaudi/scripts/gaudirun.py                  | 8 ++++----
 GaudiKernel/scripts/genconfuser.py         | 2 +-
 GaudiMP/scripts/compareOutputFiles.py      | 2 +-
 GaudiPolicy/python/GaudiTesting/QMTTest.py | 2 +-
 GaudiPolicy/python/GaudiTesting/Run.py     | 4 ++--
 GaudiPolicy/qmtest_classes/GaudiTest.py    | 2 +-
 GaudiPython/python/GaudiPython/Bindings.py | 2 +-
 7 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/Gaudi/scripts/gaudirun.py b/Gaudi/scripts/gaudirun.py
index 3661413484..0a706d2a21 100755
--- a/Gaudi/scripts/gaudirun.py
+++ b/Gaudi/scripts/gaudirun.py
@@ -451,10 +451,10 @@ if __name__ == "__main__":
     if options:
         g = {}
         l = {}
-        exec "from Gaudi.Configuration import *" in g, l
+        exec("from Gaudi.Configuration import *", g, l)
         for o in options:
             logging.debug(o)
-            exec o in g, l
+            exec(o, g, l)
 
     import GaudiKernel.Proxy.Configurable
     if opts.no_conf_user_apply:
@@ -473,10 +473,10 @@ if __name__ == "__main__":
     if opts.post_options:
         g = {}
         l = {}
-        exec "from Gaudi.Configuration import *" in g, l
+        exec("from Gaudi.Configuration import *", g, l)
         for o in opts.post_options:
             logging.debug(o)
-            exec o in g, l
+            exec(o, g, l)
 
     if 'GAUDI_TEMP_OPTS_FILE' in os.environ:
         os.remove(os.environ['GAUDI_TEMP_OPTS_FILE'])
diff --git a/GaudiKernel/scripts/genconfuser.py b/GaudiKernel/scripts/genconfuser.py
index 1da6e45f7b..677f19d70b 100755
--- a/GaudiKernel/scripts/genconfuser.py
+++ b/GaudiKernel/scripts/genconfuser.py
@@ -105,7 +105,7 @@ def getConfigurableUsers(modulename, root, mayNotExist=False):
     g, l = {}, {}
     try:
         logging.verbose("importing %s", shortmodname)
-        exec "import %s as mod" % shortmodname in g, l
+        exec("import %s as mod" % shortmodname, g, l)
     finally:
         # restore old sys.path
         logging.verbose("restoring old sys.path")
diff --git a/GaudiMP/scripts/compareOutputFiles.py b/GaudiMP/scripts/compareOutputFiles.py
index 59a4c62cec..d2169a1131 100755
--- a/GaudiMP/scripts/compareOutputFiles.py
+++ b/GaudiMP/scripts/compareOutputFiles.py
@@ -362,7 +362,7 @@ def GetFSRdict(filename, queue):
     options += "LumiFsrReader().Persistency='ROOT'; LumiFsrReader().EvtMax = 1; from Configurables import LHCbApp; LHCbApp().Persistency='ROOT';  from Configurables import CondDB, DDDBConf;"
     options += " CondDB().UseLatestTags=['%s']; DDDBConf(DataType='%s');" % (
         2011, 2011)
-    exec options
+    exec(options)
     app = AppMgr()
     app.run(1)
     fsr = app.filerecordsvc()
diff --git a/GaudiPolicy/python/GaudiTesting/QMTTest.py b/GaudiPolicy/python/GaudiTesting/QMTTest.py
index fddddd3ad2..738b561b82 100644
--- a/GaudiPolicy/python/GaudiTesting/QMTTest.py
+++ b/GaudiPolicy/python/GaudiTesting/QMTTest.py
@@ -112,7 +112,7 @@ class QMTTest(BaseTest):
                                                  "causes": self.causes})
                                 }
             # print self.validator
-            exec self.validator in globals(), exported_symbols
+            exec(self.validator, globals(), exported_symbols)
             return result, self.causes
         else:
             return super(QMTTest, self).ValidateOutput(stdout, stderr, result)
diff --git a/GaudiPolicy/python/GaudiTesting/Run.py b/GaudiPolicy/python/GaudiTesting/Run.py
index d7026a3318..1ed4f219d2 100644
--- a/GaudiPolicy/python/GaudiTesting/Run.py
+++ b/GaudiPolicy/python/GaudiTesting/Run.py
@@ -158,8 +158,8 @@ def main():
             test_module = os.environ.get(
                 'GAUDI_QMTEST_MODULE', 'GaudiTesting.QMTTest')
             test_class = os.environ.get('GAUDI_QMTEST_CLASS', 'QMTTest')
-            exec 'from {} import {} as test_class'.format(
-                test_module, test_class)
+            exec('from {} import {} as test_class'.format(
+                test_module, test_class))
             fileToTest = test_class(filename)
             results = fileToTest.run()
         except Exception as e:
diff --git a/GaudiPolicy/qmtest_classes/GaudiTest.py b/GaudiPolicy/qmtest_classes/GaudiTest.py
index 2539ee2d94..66e921ae31 100644
--- a/GaudiPolicy/qmtest_classes/GaudiTest.py
+++ b/GaudiPolicy/qmtest_classes/GaudiTest.py
@@ -1536,7 +1536,7 @@ class GaudiExeTest(ExecTestBase):
                                                                             "causes": causes}),
 
                                 }
-            exec self.validator in globals(), exported_symbols
+            exec(self.validator, globals(), exported_symbols)
         else:
             self.ValidateWithReference(stdout, stderr, result, causes)
 
diff --git a/GaudiPython/python/GaudiPython/Bindings.py b/GaudiPython/python/GaudiPython/Bindings.py
index 58b6fd4cb4..94a0d47136 100644
--- a/GaudiPython/python/GaudiPython/Bindings.py
+++ b/GaudiPython/python/GaudiPython/Bindings.py
@@ -66,7 +66,7 @@ namespace GaudiPython { namespace Helpers {
 
 # toIntArray, toShortArray, etc.
 for l in [l for l in dir(Helper) if re.match("^to.*Array$", l)]:
-    exec "%s = Helper.%s" % (l, l)
+    exec("%s = Helper.%s" % (l, l))
     __all__.append(l)
 
 # FIXME: (MCl) Hack to handle ROOT 5.18 and ROOT >= 5.20
-- 
GitLab


From b18ec813521cf2fb0289da99993aed5aa3c7c217 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Tue, 28 Nov 2017 18:12:12 +0100
Subject: [PATCH 07/56] Use Python 3 compatible octal notation.

See PEP 3127.
---
 GaudiKernel/scripts/genconfuser.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/GaudiKernel/scripts/genconfuser.py b/GaudiKernel/scripts/genconfuser.py
index 677f19d70b..f8e7cefefb 100755
--- a/GaudiKernel/scripts/genconfuser.py
+++ b/GaudiKernel/scripts/genconfuser.py
@@ -253,7 +253,7 @@ def main():
     output_dir = os.path.dirname(outputfile)
     try:
         logging.info("Creating directory %r", output_dir)
-        os.makedirs(output_dir, 0755)
+        os.makedirs(output_dir, 0o755)
     except OSError as err:
         import errno
         if err.errno == errno.EEXIST:
-- 
GitLab


From a9be3d4d906bd9829d6fcff7d24d5684b3f258e6 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Tue, 28 Nov 2017 18:20:38 +0100
Subject: [PATCH 08/56] Use Python 3 compatible floor division.

---
 GaudiKernel/scripts/genconfuser.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/GaudiKernel/scripts/genconfuser.py b/GaudiKernel/scripts/genconfuser.py
index f8e7cefefb..7098a350d3 100755
--- a/GaudiKernel/scripts/genconfuser.py
+++ b/GaudiKernel/scripts/genconfuser.py
@@ -3,7 +3,7 @@
 """
 Generate _confDb.py files for ConfigurableUser classes.
 """
-
+from __future__ import division
 import os
 import sys
 import time
@@ -14,7 +14,7 @@ from pprint import pformat
 from glob import glob
 from GaudiKernel.ConfigurableDb import cfgDb
 
-logging.VERBOSE = (logging.INFO + logging.DEBUG) / 2
+logging.VERBOSE = (logging.INFO + logging.DEBUG) // 2
 logging.addLevelName(logging.VERBOSE, "VERBOSE")
 logging.verbose = lambda msg, *args, **kwargs: \
     logging.log(logging.VERBOSE, msg, *args, **kwargs)
-- 
GitLab


From 4ea33ad76058e4e22b79c0843cfc048eac3331b3 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Tue, 28 Nov 2017 18:20:59 +0100
Subject: [PATCH 09/56] Use Python 3 compatible maketrans and translate
 methods.

---
 GaudiKernel/python/GaudiKernel/ConfigurableDb.py | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/GaudiKernel/python/GaudiKernel/ConfigurableDb.py b/GaudiKernel/python/GaudiKernel/ConfigurableDb.py
index 0fab3ee0c9..fc1be7cfb1 100644
--- a/GaudiKernel/python/GaudiKernel/ConfigurableDb.py
+++ b/GaudiKernel/python/GaudiKernel/ConfigurableDb.py
@@ -10,7 +10,11 @@ to feed the AthenaEmacs module..."""
 __all__ = ['CfgDb', 'cfgDb', 'loadConfigurableDb', 'getConfigurable']
 
 import string
-_transtable = string.maketrans('<>&*,: ().', '__rp__s___')
+try:
+    _transtable = str.maketrans('<>&*,: ().', '__rp__s___')
+except AttributeError:
+    # Python 2 compatibility
+    _transtable = string.maketrans('<>&*,: ().', '__rp__s___')
 
 import logging
 log = logging.getLogger('ConfigurableDb')
@@ -153,7 +157,11 @@ def getConfigurable(className, requester='', assumeCxxClass=True):
     confClass = className
     if assumeCxxClass:
         # assume className is C++: --> translate to python
-        confClass = string.translate(confClass, _transtable)
+        try:
+            confClass = str.translate(confClass, _transtable)
+        except AttributeError:
+            # Python 2 compatibility
+            confClass = string.translate(confClass, _transtable)
     # see if I have it in my dictionary
     confClassInfo = cfgDb.get(confClass)
     if not confClassInfo:
-- 
GitLab


From aaf2817bc6439490a6abd57eb777f437b52e0324 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Tue, 28 Nov 2017 18:23:49 +0100
Subject: [PATCH 10/56] Hacks to get Gaudi building under Python 3.

---
 GaudiCoreSvc/CMakeLists.txt  | 2 +-
 GaudiExamples/CMakeLists.txt | 2 +-
 toolchain.cmake              | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/GaudiCoreSvc/CMakeLists.txt b/GaudiCoreSvc/CMakeLists.txt
index 3b02be3d8e..eead21f42d 100644
--- a/GaudiCoreSvc/CMakeLists.txt
+++ b/GaudiCoreSvc/CMakeLists.txt
@@ -2,7 +2,7 @@ gaudi_subdir(GaudiCoreSvc)
 
 gaudi_depends_on_subdirs(GaudiKernel)
 
-find_package(Boost COMPONENTS system filesystem regex thread python REQUIRED)
+find_package(Boost COMPONENTS system filesystem regex thread python3 REQUIRED)
 find_package(TBB REQUIRED)
 find_package(PythonLibs REQUIRED)
 find_package(ROOT REQUIRED)
diff --git a/GaudiExamples/CMakeLists.txt b/GaudiExamples/CMakeLists.txt
index 13e62f55d3..13b5ba5b2a 100644
--- a/GaudiExamples/CMakeLists.txt
+++ b/GaudiExamples/CMakeLists.txt
@@ -5,7 +5,7 @@ gaudi_depends_on_subdirs(GaudiKernel GaudiUtils GaudiGSL GaudiAlg RootCnv)
 find_package(AIDA)
 find_package(HepPDT)
 find_package(ROOT COMPONENTS Tree RIO Hist Net REQUIRED)
-find_package(Boost COMPONENTS python REQUIRED)
+find_package(Boost COMPONENTS python3 REQUIRED)
 find_package(CLHEP)
 find_package(GSL)
 find_package(PythonLibs REQUIRED)
diff --git a/toolchain.cmake b/toolchain.cmake
index f907284f95..622ef62ef8 100644
--- a/toolchain.cmake
+++ b/toolchain.cmake
@@ -1,5 +1,5 @@
 # Special wrapper to load the declared version of the heptools toolchain.
-set(heptools_version 94)
+set(heptools_version 94python3)
 
 cmake_minimum_required(VERSION 3.6)
 if($ENV{HEPTOOLS_VERSION})
-- 
GitLab


From 69395ae3f48e77af896053f917430eae6e2c5970 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Wed, 29 Nov 2017 09:06:06 +0100
Subject: [PATCH 11/56] Use Python 3 compatible exception raising syntax.

---
 .../python/GaudiKernel/Configurable.py        | 17 +++++-----
 .../GaudiProfiling/GenerateGaudiOpts.py       |  2 +-
 GaudiPython/python/GaudiPython/Bindings.py    | 32 +++++++++----------
 GaudiPython/python/GaudiPython/GaudiAlgs.py   | 16 +++++-----
 GaudiPython/python/GaudiPython/HistoUtils.py  | 10 +++---
 5 files changed, 39 insertions(+), 38 deletions(-)

diff --git a/GaudiKernel/python/GaudiKernel/Configurable.py b/GaudiKernel/python/GaudiKernel/Configurable.py
index 4de14cb4c5..0a17885038 100644
--- a/GaudiKernel/python/GaudiKernel/Configurable.py
+++ b/GaudiKernel/python/GaudiKernel/Configurable.py
@@ -282,8 +282,8 @@ class Configurable(object):
 
         # this is an abstract class
         if klass == Configurable:
-            raise TypeError, "%s is an ABC and can not be instantiated" % str(
-                Configurable)
+            raise TypeError("%s is an ABC and can not be instantiated" % str(
+                Configurable))
 
         # the following methods require overloading
         # NOT YET  meths = { 'getServices'   : 1,    # retrieve list of services to configure
@@ -296,15 +296,15 @@ class Configurable(object):
             try:
                 f = getattr(klass, meth).im_func
             except AttributeError:
-                raise NotImplementedError, "%s is missing in class %s" % (
-                    meth, str(klass))
+                raise NotImplementedError("%s is missing in class %s" % (
+                    meth, str(klass)))
 
             # in addition, verify the number of arguments w/o defaults
             nargcount = f.func_code.co_argcount
             ndefaults = f.func_defaults and len(f.func_defaults) or 0
             if not nargcount - ndefaults <= nArgs <= nargcount:
-                raise TypeError, "%s.%s requires exactly %d arguments" % (
-                    klass, meth, nArgs)
+                raise TypeError( "%s.%s requires exactly %d arguments" % (
+                    klass, meth, nArgs))
 
         # for using this Configurable as a (Gaudi) sequence
         self.__children = []
@@ -578,8 +578,9 @@ class Configurable(object):
         # make sure base class init has been called
         if not hasattr(self, '_initok') or not self._initok:
             # could check more, but this is the only explanation
-            raise TypeError, \
+            raise TypeError(
                 "Configurable.__init__ not called in %s override" % self.__class__.__name__
+            )
 
 #      log.debug("calling setup() on " + self.getFullJobOptName())
 
@@ -822,7 +823,7 @@ class Configurable(object):
                 classname = tool.__name__
             else:
                 classname = type(tool).__name__
-            raise TypeError, "addTool requires AlgTool configurable. Got %s type" % classname
+            raise TypeError("addTool requires AlgTool configurable. Got %s type" % classname)
         self.__tools[name] = priv_tool
         if name in self.__slots__:
             # this is to avoid that the property hides the tool
diff --git a/GaudiProfiling/python/GaudiProfiling/GenerateGaudiOpts.py b/GaudiProfiling/python/GaudiProfiling/GenerateGaudiOpts.py
index 5f1857ed4e..9e1b74d4f4 100644
--- a/GaudiProfiling/python/GaudiProfiling/GenerateGaudiOpts.py
+++ b/GaudiProfiling/python/GaudiProfiling/GenerateGaudiOpts.py
@@ -175,6 +175,6 @@ def ConvertXmlToDict(root, dictclass=XmlDictObject):
     if type(root) == type(''):
         root = ElementTree.parse(root).getroot()
     elif not isinstance(root, ElementTree.Element):
-        raise TypeError, 'Expected ElementTree.Element or file path string'
+        raise TypeError('Expected ElementTree.Element or file path string')
 
     return dictclass({root.tag: _ConvertXmlToDictRecurse(root, dictclass)})
diff --git a/GaudiPython/python/GaudiPython/Bindings.py b/GaudiPython/python/GaudiPython/Bindings.py
index 94a0d47136..a9960a845d 100644
--- a/GaudiPython/python/GaudiPython/Bindings.py
+++ b/GaudiPython/python/GaudiPython/Bindings.py
@@ -135,7 +135,7 @@ def loaddict(dict):
         try:
             cppyy.loadDict(dict)
         except:
-            raise ImportError, 'Error loading dictionary library'
+            raise ImportError('Error loading dictionary library')
 
 # ---get a class (by loading modules if needed)--------------------------------
 
@@ -258,7 +258,7 @@ class iProperty(object):
         ip = self.getInterface()
         if ip:
             if not gbl.Gaudi.Utils.hasProperty(ip, name):
-                raise AttributeError, 'property %s does not exist' % name
+                raise AttributeError('property %s does not exist' % name)
             prop = ip.getProperty(name)
 
             if ROOT6WorkAroundEnabled('ROOT-7201'):
@@ -271,8 +271,8 @@ class iProperty(object):
 
             if canSetValue:
                 if not prop.setValue(value):
-                    raise AttributeError, 'property %s could not be set from %s' % (
-                        name, value)
+                    raise AttributeError('property %s could not be set from %s' % (
+                        name, value))
             else:
                 if tuple == type(value):
                     value = str(value)
@@ -288,8 +288,8 @@ class iProperty(object):
                 else:
                     sc = prop.fromString(value)
                 if sc.isFailure():
-                    raise AttributeError, 'property %s could not be set from %s' % (
-                        name, value)
+                    raise AttributeError('property %s could not be set from %s' % (
+                        name, value))
         else:
             if type(value) == str:
                 value = '"%s"' % value  # need double quotes
@@ -311,7 +311,7 @@ class iProperty(object):
         ip = self.getInterface()
         if ip:
             if not gbl.Gaudi.Utils.hasProperty(ip, name):
-                raise AttributeError, 'property %s does not exist' % name
+                raise AttributeError('property %s does not exist' % name)
             prop = ip.getProperty(name)
             if StringProperty == type(prop):
                 return prop.value()
@@ -331,7 +331,7 @@ class iProperty(object):
                     return eval(p.value(), {}, {})
                 except:
                     return p.value()
-            raise AttributeError, 'property %s does not exist' % name
+            raise AttributeError('property %s does not exist' % name)
 
     def properties(self):
         dct = {}
@@ -348,9 +348,9 @@ class iProperty(object):
                 try:
                     dct[p.name()] = PropertyEntry(p)
                 except (ValueError, TypeError) as e:
-                    raise ValueError, "gaudimodule.iProperty.properties(): %s%s processing property %s.%s = %s" % \
+                    raise ValueError("gaudimodule.iProperty.properties(): %s%s processing property %s.%s = %s" % \
                         (e.__class__.__name__, e.args,
-                         propsFrom, p.name(), p.value())
+                         propsFrom, p.name(), p.value()))
         return dct
 
     def name(self):
@@ -1192,7 +1192,7 @@ class AppMgr(iService):
         for file in files:
             sc = self.readOptions(file)
             if sc.isFailure():
-                raise RuntimeError, ' Unable to read file "' + file + '" '
+                raise RuntimeError(' Unable to read file "' + file + '" ')
         options = args.get('options', None)
         if options:
             import tempfile
@@ -1213,7 +1213,7 @@ class AppMgr(iService):
             tmpfile.close()
             sc = self.readOptions(tmpfilename)
             if sc.isFailure():
-                raise RuntimeError, ' Unable to read file "' + tmpfilename + '" '
+                raise RuntimeError(' Unable to read file "' + tmpfilename + '" ')
             os.remove(tmpfilename)
         # We need to make sure that the options are taken by the ApplicationMgr
         # The state is already configured, so we need to do something....
@@ -1343,7 +1343,7 @@ class AppMgr(iService):
 def _getFIDandEvents(pfn):
     tfile = gbl.TFile.Open(pfn)
     if not tfile:
-        raise 'Cannot open ROOT file ', pfn
+        raise IOError('Cannot open ROOT file {0}'.format(pfn))
     tree = tfile.Get('##Params')
     tree.GetEvent(0)
     text = tree.db_string
@@ -1363,14 +1363,14 @@ def getComponentProperties(name):
     properties = {}
     if name == 'GaudiCoreSvc':
         if Helper.loadDynamicLib(name) != 1:
-            raise ImportError,  'Error loading component library ' + name
+            raise ImportError('Error loading component library ' + name)
         factorylist = gbl.FactoryTable.instance().getEntries()
         factories = _copyFactoriesFromList(factorylist)
         g = AppMgr(outputlevel=7)
     else:
         g = AppMgr(outputlevel=7)
         if Helper.loadDynamicLib(name) != 1:
-            raise ImportError,  'Error loading component library ' + name
+            raise ImportError('Error loading component library ' + name)
         factorylist = gbl.FactoryTable.instance().getEntries()
         factories = _copyFactoriesFromList(factorylist)
     svcloc = gbl.Gaudi.svcLocator()
@@ -1448,7 +1448,7 @@ class PyAlgorithm (_PyAlgorithm):
         self._algmgr = InterfaceCast(gbl.IAlgManager)(self._svcloc)
         sc = self._algmgr.addAlgorithm(self)
         if sc.isFailure():
-            raise RuntimeError, 'Unable to add Algorithm'
+            raise RuntimeError('Unable to add Algorithm')
 
     def __del__(self):
         sc = self._algmgr.removeAlgorithm(self)
diff --git a/GaudiPython/python/GaudiPython/GaudiAlgs.py b/GaudiPython/python/GaudiPython/GaudiAlgs.py
index 6558cd677b..1937fbcfd9 100644
--- a/GaudiPython/python/GaudiPython/GaudiAlgs.py
+++ b/GaudiPython/python/GaudiPython/GaudiAlgs.py
@@ -209,7 +209,7 @@ def _init_(self, name, **args):
     algMgr = appMgr._algmgr
     status = algMgr.addAlgorithm(self)
     if status.isFailure():
-        raise RuntimeError, 'Unable to add Algorithm "' + name + '"'
+        raise RuntimeError('Unable to add Algorithm "' + name + '"')
     iAlgorithm.__init__(self, name, self)
     for key in args:
         setattr(self, key, args[key])
@@ -492,7 +492,7 @@ def _getProperty_(self, pname):
     Get the property by name
     """
     if not self.hasProperty(pname):
-        raise AttributeError, 'property %s does not exist' % pname
+        raise AttributeError('property %s does not exist' % pname)
     return iAlgorithm.__getattr__(self, pname)
 
 # =============================================================================
@@ -504,7 +504,7 @@ def _setProperty_(self, pname, pvalue):
     Set the property from the value
     """
     if not self.hasProperty(pname):
-        raise AttributeError, 'property %s does not exist' % pname
+        raise AttributeError('property %s does not exist' % pname)
     return iAlgorithm.__setattr__(self, pname, pvalue)
 
 # =============================================================================
@@ -518,7 +518,7 @@ def _get_attr_(self, pname):
     """
     if self.hasProperty(pname):
         return iAlgorithm.__getattr__(self, pname)
-    raise AttributeError, 'attribute/property %s does not exist' % pname
+    raise AttributeError('attribute/property %s does not exist' % pname)
 
 # =============================================================================
 # set the attribute or property
@@ -926,7 +926,7 @@ def _execute_(self):
     """
     The fictive 'execute' method, which MUST be overwitten by user
     """
-    raise RuntimeError, 'Execute method is not implemented for %s' % self.name()
+    raise RuntimeError('Execute method is not implemented for %s' % self.name())
 
 
 GaudiAlgo.execute = _execute_
@@ -1339,7 +1339,7 @@ def _get_all_tools_(self, method):
     _func = getattr(AlgDecorator, method)
     _num = _func(self, _tools)
     if _tools.size() != _num:
-        raise RuntimeError, 'Unable to extract Tools'
+        raise RuntimeError('Unable to extract Tools')
     _res = []
     for _tool in _tools:
         _res += [iAlgTool(_tool.name(), _tool)]
@@ -1397,7 +1397,7 @@ def _get_all_counters_(self, method, name=None):
     _func = getattr(AlgDecorator, method)
     _num = _func(self, _nams, _cnts)
     if _nams.size() != _num or _cnts.size() != _num:
-        raise RuntimeError, 'Unable to extract Counters'
+        raise RuntimeError('Unable to extract Counters')
     _res = {}
     for _i in range(0, _num):
         _nam = _nams[_i]
@@ -1529,7 +1529,7 @@ def _get_all_histos_(component, method, name):
         _fun = getattr(HistoDecorator, method)
         _num = _fun(component, _ids, _his)
         if _ids.size() != _num or _his.size() != _num:
-            raise RuntimeError, 'Unable to extract Histos!'
+            raise RuntimeError('Unable to extract Histos!')
         for _i in range(0, _num):
             _id = _ids[_i]
             if _id.numeric():
diff --git a/GaudiPython/python/GaudiPython/HistoUtils.py b/GaudiPython/python/GaudiPython/HistoUtils.py
index 0e154df172..22d77cc8e8 100644
--- a/GaudiPython/python/GaudiPython/HistoUtils.py
+++ b/GaudiPython/python/GaudiPython/HistoUtils.py
@@ -61,7 +61,7 @@ def _getAppMgr(**kwargs):
     if not gaudi:
         gaudi = AppMgr()
     if not gaudi:
-        raise RuntimeError, 'Unable to get valid ApplicationMgr'
+        raise RuntimeError('Unable to get valid ApplicationMgr')
 
     state = gaudi._isvc.FSMState()
     if state < cpp.Gaudi.StateMachine.CONFIGURED:
@@ -235,7 +235,7 @@ def book(*args, **kwargs):
 
     svc = _getHistoSvc(**kwargs)
     if not svc:
-        raise RuntimeError, 'Unable to get valid HistogramService '
+        raise RuntimeError('Unable to get valid HistogramService ')
     # book the histogram using the service
     return svc.book(*args)  # RETURN
 
@@ -315,7 +315,7 @@ def bookProf(*args, **kwargs):
     """
     svc = _getHistoSvc(**kwargs)
     if not svc:
-        raise RuntimeError, 'Unable to get valid HistogramService '
+        raise RuntimeError('Unable to get valid HistogramService ')
     # book the histogram using the service
     return svc.bookProf(*args)  # RETURN
 
@@ -340,7 +340,7 @@ def getAsAIDA(path, **kwargs):
     """
     svc = _getHistoSvc(**kwargs)
     if not svc:
-        raise RuntimeError, 'Unable to get valid HistogramService '
+        raise RuntimeError('Unable to get valid HistogramService ')
     # return the histogram
     return svc.getAsAIDA(path)  # RETURN
 
@@ -365,7 +365,7 @@ def getAsROOT(path, **kwargs):
     """
     svc = _getHistoSvc(**kwargs)
     if not svc:
-        raise RuntimeError, 'Unable to get valid HistogramService '
+        raise RuntimeError('Unable to get valid HistogramService ')
     # return the histogram
     return svc.getAsROOT(path)  # RETURN
 
-- 
GitLab


From 2c6c49a7a369a6e5f05b3e2b5306a643a6d54f3b Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Wed, 29 Nov 2017 09:40:46 +0100
Subject: [PATCH 12/56] Use Python 3 compatible printing.

---
 Gaudi/python/Gaudi/Main.py                    |  13 +-
 Gaudi/scripts/gaudirun.py                     |  10 +-
 Gaudi/tests/python/Test_confDb.py             |   7 +-
 .../tests/scripts/test_configurable_users.py  |  11 +-
 .../tests/scripts/test_cu_delayed_creation.py |  11 +-
 Gaudi/tests/scripts/test_cu_passive_dep.py    |   3 +-
 Gaudi/tests/scripts/test_export_oldopts.py    |  52 +++---
 .../scripts/test_propagate_properties.py      |   9 +-
 Gaudi/tests/scripts/test_purge.py             |   7 +-
 GaudiExamples/options/ConfigurableUser.py     |   4 +-
 .../options/ControlFlow/AlgSequencer.py       |   9 +-
 .../ControlFlow/SuperAlgDynamicGraph.py       |   7 +-
 .../options/ControlFlow/SuperAlgorithm.py     |   7 +-
 GaudiExamples/options/MyGaudiAlg.py           |   7 +-
 GaudiExamples/scripts/Aida2RootEx.py          |   7 +-
 GaudiExamples/scripts/ArrayProperties.py      |   3 +-
 GaudiExamples/scripts/BoostArrayProperties.py |   3 +-
 GaudiExamples/scripts/CounterEx.py            |   6 +-
 GaudiExamples/scripts/EvtColRead.py           |   3 +-
 GaudiExamples/scripts/EvtColWrite.py          |   2 +-
 GaudiExamples/scripts/ExtendedProperties.py   |  11 +-
 GaudiExamples/scripts/ExtendedProperties2.py  |   9 +-
 GaudiExamples/scripts/HistoDumpEx.py          |  13 +-
 GaudiExamples/scripts/HistoEx.py              |   5 +-
 GaudiExamples/scripts/HistoEx1.py             |   5 +-
 GaudiExamples/scripts/HistoEx2.py             |   7 +-
 GaudiExamples/scripts/HistoUtilsEx.py         |  47 ++---
 GaudiExamples/scripts/Mix.py                  |  13 +-
 GaudiExamples/scripts/Properties.py           |   7 +-
 GaudiExamples/scripts/StringKeyEx.py          |   9 +-
 GaudiExamples/scripts/TupleEx.py              |   3 +-
 GaudiExamples/scripts/TupleEx1.py             |   3 +-
 GaudiExamples/scripts/TupleEx2.py             |   3 +-
 GaudiExamples/scripts/TupleEx3.py             |   3 +-
 GaudiExamples/scripts/bug_38882.py            |   3 +-
 .../tests/scripts/test_timing_histo_file.py   |   5 +-
 GaudiHive/options/graphanalysis.py            |  19 +-
 GaudiHive/options/jsonFromLHCbLog.py          |   3 +-
 GaudiHive/profiling/brunelWrapper.py          |   4 +-
 GaudiHive/profiling/plotBacklogPyRoot.py      |   5 +-
 GaudiHive/profiling/plotClonesPyRoot.py       |   3 +-
 GaudiHive/profiling/plotSpeedup.py            |   9 +-
 GaudiHive/profiling/plotSpeedupsPyRoot.py     |   7 +-
 GaudiHive/profiling/prepareBenchmark.py       |   6 +-
 GaudiHive/python/GaudiHive/precedence.py      |  43 ++---
 GaudiHive/scripts/hivetimeline.py             |   4 +-
 GaudiKernel/python/GaudiConfig/ControlFlow.py |  17 +-
 .../python/GaudiKernel/Configurable.py        |   4 +-
 .../python/GaudiKernel/GaudiHandles.py        |   5 +-
 .../python/GaudiKernel/PropertyProxy.py       |   8 +-
 GaudiKernel/python/GaudiKernel/RootMap.py     |  32 ++--
 GaudiKernel/scripts/gaudiComponentHelp.py     |  24 +--
 GaudiKernel/scripts/root_map_dump.py          |   6 +-
 .../tests/qmtest/scripts/test_bug_87340.py    |  15 +-
 GaudiMP/python/GaudiMP/GMPBase.py             |   7 +-
 GaudiMP/python/GaudiMP/Parallel.py            |  15 +-
 GaudiMP/scripts/compareOutputFiles.py         |  82 ++++-----
 GaudiMP/scripts/compareRootHistos.py          | 167 +++++++++---------
 .../python/GaudiPluginService/cpluginsvc.py   |  17 +-
 GaudiPolicy/python/GaudiTesting/BaseTest.py   |   4 +-
 GaudiPolicy/python/GaudiTesting/QMTTest.py    |   2 +-
 GaudiPolicy/python/GaudiTesting/Run.py        |  19 +-
 GaudiPolicy/qmtest_classes/GaudiTest.py       |   7 +-
 .../GaudiProfiling/GenerateGaudiOpts.py       |   3 +-
 GaudiPython/python/GaudiPython/Bindings.py    |  20 +--
 GaudiPython/python/GaudiPython/GaudiAlgs.py   |  35 ++--
 GaudiPython/python/GaudiPython/HistoUtils.py  |  45 ++---
 .../python/GaudiPython/Pythonizations.py      |  17 +-
 GaudiPython/python/GaudiPython/TupleUtils.py  |  11 +-
 GaudiPython/python/GaudiPython/__init__.py    |   3 +-
 GaudiRelease/prepare_gaudi_release.py         |   4 +-
 GaudiRelease/svn_tag_release.py               |   3 +-
 RootCnv/scripts/IOTest.py                     |  13 +-
 cmake/tests/cmake_coverage.py                 |   2 +-
 74 files changed, 537 insertions(+), 480 deletions(-)

diff --git a/Gaudi/python/Gaudi/Main.py b/Gaudi/python/Gaudi/Main.py
index 5be7378412..4acfead980 100644
--- a/Gaudi/python/Gaudi/Main.py
+++ b/Gaudi/python/Gaudi/Main.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 import sys
 import os
 from time import time
@@ -142,12 +143,12 @@ def toOpt(value):
     '''
     Helper to convert values to old .opts format.
 
-    >>> print toOpt('some "text"')
+    >>> print(toOpt('some "text"'))
     "some \\"text\\""
-    >>> print toOpt('first\\nsecond')
+    >>> print(toOpt('first\\nsecond'))
     "first
     second"
-    >>> print toOpt({'a': [1, 2, '3']})
+    >>> print(toOpt({'a': [1, 2, '3']}))
     {"a": [1, 2, "3"]}
     '''
     if isinstance(value, basestring):
@@ -247,9 +248,9 @@ class gaudimain(object):
         log.info(msg)
         conf_dict = Configuration.configurationDict(all)
         if old_format:
-            print self.generateOptsOutput(all)
+            print(self.generateOptsOutput(all))
         else:
-            print self.generatePyOutput(all)
+            print(self.generatePyOutput(all))
 
     def writeconfig(self, filename, all=False):
         write = {".pkl": lambda filename, all: self._writepickle(filename),
@@ -431,7 +432,7 @@ class gaudimain(object):
             self.ip.setProperty('ReturnCode', str(128 + 11))
             statuscode = False
         except Exception as x:
-            print 'Exception:', x
+            print('Exception:', x)
             # for other exceptions, just set a generic error code
             self.ip.setProperty('ReturnCode', '1')
             statuscode = False
diff --git a/Gaudi/scripts/gaudirun.py b/Gaudi/scripts/gaudirun.py
index 0a706d2a21..4ed1b402ee 100755
--- a/Gaudi/scripts/gaudirun.py
+++ b/Gaudi/scripts/gaudirun.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-
+from __future__ import print_function
 import os
 import sys
 from tempfile import mkstemp
@@ -123,7 +123,7 @@ def getArgsFromQmt(qmtfile):
 if __name__ == "__main__":
     # ensure that we (and the subprocesses) use the C standard localization
     if os.environ.get('LC_ALL') != 'C':
-        print '# setting LC_ALL to "C"'
+        print('# setting LC_ALL to "C"')
         os.environ['LC_ALL'] = 'C'
 
     from optparse import OptionParser
@@ -239,7 +239,7 @@ if __name__ == "__main__":
         else:
             argv.append(a)
     if argv != sys.argv[1:]:
-        print '# Running', sys.argv[0], 'with arguments', argv
+        print('# Running', sys.argv[0], 'with arguments', argv)
 
     opts, args = parser.parse_args(args=argv)
 
@@ -396,9 +396,9 @@ if __name__ == "__main__":
             # now we have all the ingredients to prepare our command
             arglist = [profilerPath] + profilerOptions.split() + args
             arglist = [a for a in arglist if a != '']
-            # print profilerPath
+            # print(profilerPath)
             # for arg in arglist:
-            # print arg
+            # print(arg)
             os.execv(profilerPath, arglist)
         else:
             arglist = [a for a in sys.argv if not a.startswith("--profiler")]
diff --git a/Gaudi/tests/python/Test_confDb.py b/Gaudi/tests/python/Test_confDb.py
index bdb8508058..9612f5abf3 100644
--- a/Gaudi/tests/python/Test_confDb.py
+++ b/Gaudi/tests/python/Test_confDb.py
@@ -1,6 +1,7 @@
 """
 Hand-written confDb file for tests.
 """
+from __future__ import print_function
 
 
 def _fillCfgDb():
@@ -30,6 +31,6 @@ try:
     # house cleaning...
     del _fillCfgDb
 except Exception, err:
-    print "Py:ConfigurableDb   ERROR Problem with [%s] content!" % __name__
-    print "Py:ConfigurableDb   ERROR", err
-    print "Py:ConfigurableDb   ERROR   ==> culprit is package [Test] !"
+    print("Py:ConfigurableDb   ERROR Problem with [%s] content!" % __name__)
+    print("Py:ConfigurableDb   ERROR", err)
+    print("Py:ConfigurableDb   ERROR   ==> culprit is package [Test] !")
diff --git a/Gaudi/tests/scripts/test_configurable_users.py b/Gaudi/tests/scripts/test_configurable_users.py
index ac485718e8..d7a5824cd2 100755
--- a/Gaudi/tests/scripts/test_configurable_users.py
+++ b/Gaudi/tests/scripts/test_configurable_users.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 from Gaudi.Configuration import *
 
 appliedConf = []
@@ -7,8 +8,8 @@ class ConfigurableUserTest(ConfigurableUser):
     __slots__ = {}
 
     def __apply_configuration__(self):
-        print "Applying", self.getName()
-        print self
+        print("Applying", self.getName())
+        print(self)
         appliedConf.append(self.getName())
 
 
@@ -67,12 +68,12 @@ class Action(object):
 
     def __call__(self):
         calledActions.append(self.msg)
-        print self.msg
+        print(self.msg)
 
 
 def ActionFunction():
     calledActions.append("Action Function")
-    print "Action Function"
+    print("Action Function")
 
 
 appendPostConfigAction(Action("Action Object One"))
@@ -121,4 +122,4 @@ for name, (prop, value) in expected.items():
     assert allConfs[name].getProp(
         prop) == value, "%s.%s != %s" % (name, prop, value)
 
-print "Success."
+print("Success.")
diff --git a/Gaudi/tests/scripts/test_cu_delayed_creation.py b/Gaudi/tests/scripts/test_cu_delayed_creation.py
index c5ca5d9f21..4322487388 100755
--- a/Gaudi/tests/scripts/test_cu_delayed_creation.py
+++ b/Gaudi/tests/scripts/test_cu_delayed_creation.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 from Gaudi.Configuration import *
 
 
@@ -6,8 +7,8 @@ class DelayedInstance(ConfigurableUser):
                  "Applied": False}
 
     def __apply_configuration__(self):
-        print "Applying", self.getName()
-        print self
+        print("Applying", self.getName())
+        print(self)
         self.Applied = True
 
 
@@ -17,8 +18,8 @@ class Application(ConfigurableUser):
     __used_configurables__ = []
 
     def __apply_configuration__(self):
-        print "Applying", self.getName()
-        print self
+        print("Applying", self.getName())
+        print(self)
         self.Applied = True
         # This is instantiated late
         DelayedInstance()
@@ -34,4 +35,4 @@ applyConfigurableUsers()
 assert Application().Applied
 assert DelayedInstance().Applied
 
-print "Done."
+print("Done.")
diff --git a/Gaudi/tests/scripts/test_cu_passive_dep.py b/Gaudi/tests/scripts/test_cu_passive_dep.py
index 651936a107..facfaada20 100755
--- a/Gaudi/tests/scripts/test_cu_passive_dep.py
+++ b/Gaudi/tests/scripts/test_cu_passive_dep.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 from GaudiKernel.ProcessJobOptions import InstallRootLoggingHandler
 import logging
 InstallRootLoggingHandler("# ", level=logging.INFO)
@@ -32,7 +33,7 @@ CommonConf()
 # apply all ConfigurableUser instances
 from GaudiKernel.Configurable import applyConfigurableUsers
 applyConfigurableUsers()
-print "Done."
+print("Done.")
 
 expected_order = ["CommonConf", "Application"]
 if applied_order != expected_order:
diff --git a/Gaudi/tests/scripts/test_export_oldopts.py b/Gaudi/tests/scripts/test_export_oldopts.py
index 8e3a1bf205..f14c961930 100755
--- a/Gaudi/tests/scripts/test_export_oldopts.py
+++ b/Gaudi/tests/scripts/test_export_oldopts.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-
+from __future__ import print_function
 import os
 import sys
 import tempfile
@@ -32,53 +32,53 @@ try:
     cmd = ["python", which("gaudirun.py"),
            "-n", "-v", "--output", outname + ".1.py"] + optfiles
     proc = Popen(cmd, stdout=PIPE)
-    print "=========================================="
-    print "======== First pass (python only) ========"
-    print "=========================================="
-    print "= cmd:", " ".join(cmd)
+    print("==========================================")
+    print("======== First pass (python only) ========")
+    print("==========================================")
+    print("= cmd:", " ".join(cmd))
     out, err = proc.communicate()
-    print out
+    print(out)
     if err:
-        print "=== stderr: ==="
-        print err
+        print("=== stderr: ===")
+        print(err)
     expected = eval(open(outname + ".1.py").read())
 
     # parse the option file, export old options, parse again
     cmd = ["python", which("gaudirun.py"),
            "-n", "-v", "--old-opts", "--output", outname + '.opts'] + optfiles
     proc = Popen(cmd, stdout=PIPE, stderr=PIPE)
-    print ""
-    print "=========================================="
-    print "========== Second pass (export) =========="
-    print "=========================================="
-    print "= cmd:", " ".join(cmd)
+    print("")
+    print("==========================================")
+    print("========== Second pass (export) ==========")
+    print("==========================================")
+    print("= cmd:", " ".join(cmd))
     out, err = proc.communicate()
-    print out
+    print(out)
     if err:
-        print "=== stderr: ==="
-        print err
+        print("=== stderr: ===")
+        print(err)
 
     cmd = ["python", which("gaudirun.py"),
            "-n", "-v", "--output", outname + ".2.py", outname + '.opts']
     proc = Popen(cmd, stdout=PIPE, stderr=PIPE)
-    print ""
-    print "=========================================="
-    print "========== Second pass (import) =========="
-    print "=========================================="
-    print "= cmd:", " ".join(cmd)
+    print("")
+    print("==========================================")
+    print("========== Second pass (import) ==========")
+    print("==========================================")
+    print("= cmd:", " ".join(cmd))
     out, err = proc.communicate()
-    print out
+    print(out)
     if err:
-        print "=== stderr: ==="
-        print err
+        print("=== stderr: ===")
+        print(err)
     result = eval(open(outname + ".2.py").read())
 
     if result != expected:
-        print "Configuration from old options differs from the python one"
+        print("Configuration from old options differs from the python one")
         retcode = 1
 
 except RuntimeError, x:
-    print x
+    print(x)
     retcode = 1
 
 sys.exit(retcode)
diff --git a/Gaudi/tests/scripts/test_propagate_properties.py b/Gaudi/tests/scripts/test_propagate_properties.py
index 7238fb7c0d..b7b6e96d1e 100755
--- a/Gaudi/tests/scripts/test_propagate_properties.py
+++ b/Gaudi/tests/scripts/test_propagate_properties.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 from Gaudi.Configuration import *
 
 # use cases:
@@ -102,12 +103,12 @@ def check(conf, prop, exp):
     v = conf.getProp(prop)
     good = v == exp
     if not good:
-        print "ERROR:",
-    print "%s.%s is %r (expected %r)," % (conf.name(), prop, v, exp),
+        print("ERROR:",)
+    print("%s.%s is %r (expected %r)," % (conf.name(), prop, v, exp),)
     if hasattr(conf, prop):
-        print "set"
+        print("set")
     else:
-        print "unset"
+        print("unset")
     return good
 
 
diff --git a/Gaudi/tests/scripts/test_purge.py b/Gaudi/tests/scripts/test_purge.py
index b30ae4cb36..80f93a7c82 100755
--- a/Gaudi/tests/scripts/test_purge.py
+++ b/Gaudi/tests/scripts/test_purge.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 from Gaudi.Configuration import *
 from GaudiKernel.Configurable import purge
 
@@ -15,11 +16,11 @@ second = configurationDict()
 from pprint import PrettyPrinter
 pp = PrettyPrinter()
 
-print "first =",
+print("first =", end=' ')
 pp.pprint(first)
 
-print "purged =",
+print("purged =", end=' ')
 pp.pprint(purged)
 
-print "second =",
+print("second =", end=' ')
 pp.pprint(second)
diff --git a/GaudiExamples/options/ConfigurableUser.py b/GaudiExamples/options/ConfigurableUser.py
index b585bfc8f7..f72e4e8dd8 100644
--- a/GaudiExamples/options/ConfigurableUser.py
+++ b/GaudiExamples/options/ConfigurableUser.py
@@ -62,8 +62,8 @@ def PostConfAction():
     """
     Action printing the result of the configuration of the ApplicationMgr.
     """
-    print "==== Configuration completed ===="
-    print ApplicationMgr()
+    print("==== Configuration completed ====")
+    print(ApplicationMgr())
 
 
 appendPostConfigAction(PostConfAction)
diff --git a/GaudiExamples/options/ControlFlow/AlgSequencer.py b/GaudiExamples/options/ControlFlow/AlgSequencer.py
index 8a5a94e48e..27da202d1f 100644
--- a/GaudiExamples/options/ControlFlow/AlgSequencer.py
+++ b/GaudiExamples/options/ControlFlow/AlgSequencer.py
@@ -1,6 +1,7 @@
 ###############################################################
 # Job options file
-# ==============================================================
+#===============================================================
+from __future__ import print_function
 
 from Gaudi.Configuration import *
 from Configurables import ParentAlg, StopperAlg, Prescaler, HelloWorld, TimingAuditor
@@ -42,9 +43,9 @@ sor = HelloWorld('OR') | EventCounter('ORCounter')
 
 all = ParentAlg() >> StopperAlg(StopCount=20) >> top >> sand >> sor
 
-print '# --- Configured Control Flow Expression:'
-print '#', all
-print '# ---'
+print('# --- Configured Control Flow Expression:')
+print('#', all)
+print('# ---')
 EventLoopMgr(PrintControlFlowExpression=True)
 # -----------------------------------------------------------------
 ApplicationMgr(TopAlg=[all],
diff --git a/GaudiExamples/options/ControlFlow/SuperAlgDynamicGraph.py b/GaudiExamples/options/ControlFlow/SuperAlgDynamicGraph.py
index 338dde2a82..99baa9e4f6 100644
--- a/GaudiExamples/options/ControlFlow/SuperAlgDynamicGraph.py
+++ b/GaudiExamples/options/ControlFlow/SuperAlgDynamicGraph.py
@@ -1,6 +1,7 @@
 ###############################################################
 # Job options file
 ###############################################################
+from __future__ import print_function
 
 from Gaudi.Configuration import *
 from Configurables import TimingAuditor, EventLoopMgr
@@ -56,9 +57,9 @@ top = s1 >> s2
 MySuperAlg('s2', PercentPass=75, OutputLevel=DEBUG, UseHelloWorld=False)
 
 
-print '# --- Configured Control Flow Expression:'
-print '#', top
-print '# ---'
+print('# --- Configured Control Flow Expression:')
+print('#', top)
+print('# ---')
 EventLoopMgr(PrintControlFlowExpression=True)
 
 # -----------------------------------------------------------------
diff --git a/GaudiExamples/options/ControlFlow/SuperAlgorithm.py b/GaudiExamples/options/ControlFlow/SuperAlgorithm.py
index 8ce7b55d12..77e485b842 100644
--- a/GaudiExamples/options/ControlFlow/SuperAlgorithm.py
+++ b/GaudiExamples/options/ControlFlow/SuperAlgorithm.py
@@ -1,6 +1,7 @@
 ###############################################################
 # Job options file
 ###############################################################
+from __future__ import print_function
 
 from Gaudi.Configuration import *
 from Configurables import ParentAlg, StopperAlg, TimingAuditor, HelloWorld
@@ -36,9 +37,9 @@ except AssertionError:
 
 all = ParentAlg() >> StopperAlg(StopCount=20) >> top >> sand >> sor
 
-print '# --- Configured Control Flow Expression:'
-print '#', all
-print '# ---'
+print('# --- Configured Control Flow Expression:')
+print('#', all)
+print('# ---')
 EventLoopMgr(PrintControlFlowExpression=True)
 
 # -----------------------------------------------------------------
diff --git a/GaudiExamples/options/MyGaudiAlg.py b/GaudiExamples/options/MyGaudiAlg.py
index 42989463db..32ae8499da 100644
--- a/GaudiExamples/options/MyGaudiAlg.py
+++ b/GaudiExamples/options/MyGaudiAlg.py
@@ -1,6 +1,7 @@
 ###############################################################
 # Job options file
-# ==============================================================
+#===============================================================
+from __future__ import print_function
 from Gaudi.Configuration import *
 from Configurables import MyGaudiAlgorithm
 
@@ -11,7 +12,7 @@ mygalg = MyGaudiAlgorithm('MyGaudiAlg',
                           OutputLevel=DEBUG)
 mygalg.PrivToolHandle.String = "Is a private tool"
 
-print mygalg
+print(mygalg)
 
 mygalg.tracks.Path = 'BestTracks/Tracks'
 mygalg.hits.Path = 'Rec/Hits'
@@ -19,7 +20,7 @@ mygalg.raw.AlternativePaths = ['/copy/RAW', '/Rec/RAW', '/DAQ/RAW']
 
 mygalg.RootInTES = '/Skim'
 
-print mygalg
+print(mygalg)
 
 ApplicationMgr(EvtMax=10,
                EvtSel='NONE',
diff --git a/GaudiExamples/scripts/Aida2RootEx.py b/GaudiExamples/scripts/Aida2RootEx.py
index 02a41022a9..020d036bc3 100755
--- a/GaudiExamples/scripts/Aida2RootEx.py
+++ b/GaudiExamples/scripts/Aida2RootEx.py
@@ -7,6 +7,7 @@
 #  @date 2007-01-24
 # =============================================================================
 " Simple example to illustrate the usage of aida2root converter "
+from __future__ import print_function
 # =============================================================================
 __author__ = "Vanya BELYAEV ibelyaev@phys.syr.edu"
 # =============================================================================
@@ -141,7 +142,7 @@ def useScript(histos):
     for histo in histos:
         root = hsvc.getAsROOT(histo)
         if not root:
-            print "ERROR in access the histogram '%s' " % histo
+            print("ERROR in access the histogram '%s' " % histo)
             continue
         canvas = ROOT.TCanvas('canvas_%d' % i, histo, 250, 250)
         root.Draw()
@@ -156,7 +157,7 @@ def useScript(histos):
             # strictly speaking, it is not needed, but avoids a message on the stderr
             os.remove(name)
         canvas.Print(name)
-        print "The file name is '%s'" % name
+        print("The file name is '%s'" % name)
         i += 1
 
 # =============================================================================
@@ -166,7 +167,7 @@ def useScript(histos):
 # The actual job execution
 # =============================================================================
 if '__main__' == __name__:
-    print __doc__, __author__
+    print(__doc__, __author__)
 
     from GaudiPython.Bindings import AppMgr
 
diff --git a/GaudiExamples/scripts/ArrayProperties.py b/GaudiExamples/scripts/ArrayProperties.py
index 9b23e6d572..4daba74a80 100755
--- a/GaudiExamples/scripts/ArrayProperties.py
+++ b/GaudiExamples/scripts/ArrayProperties.py
@@ -8,6 +8,7 @@
 *                                                                             *
 *******************************************************************************
 """
+from __future__ import print_function
 # =============================================================================
 __author__ = 'Vanya BELYAEV Ivan.Belyaev@nikhef.nl'
 # =============================================================================
@@ -37,7 +38,7 @@ ApplicationMgr(
 # =============================================================================
 if '__main__' == __name__:
 
-    print __doc__, __author__
+    print(__doc__, __author__)
 
     # make sure cling can generate all required methods in Gaudi::Property
     import cppyy
diff --git a/GaudiExamples/scripts/BoostArrayProperties.py b/GaudiExamples/scripts/BoostArrayProperties.py
index ba7eea3d56..491aa9d38e 100755
--- a/GaudiExamples/scripts/BoostArrayProperties.py
+++ b/GaudiExamples/scripts/BoostArrayProperties.py
@@ -8,6 +8,7 @@
 *                                                                             *
 *******************************************************************************
 """
+from __future__ import print_function
 # =============================================================================
 __author__ = 'Vanya BELYAEV Ivan.Belyaev@nikhef.nl'
 # =============================================================================
@@ -37,7 +38,7 @@ ApplicationMgr(
 # =============================================================================
 if '__main__' == __name__:
 
-    print __doc__, __author__
+    print(__doc__, __author__)
 
     from GaudiPython.Bindings import AppMgr
 
diff --git a/GaudiExamples/scripts/CounterEx.py b/GaudiExamples/scripts/CounterEx.py
index f316d34bb1..d38e18eaee 100755
--- a/GaudiExamples/scripts/CounterEx.py
+++ b/GaudiExamples/scripts/CounterEx.py
@@ -77,11 +77,11 @@ class Counter(GaudiAlgo):
         executed = self.counter('executed')
         prnt = int(executed.flag())
         if 0 == prnt % 1000:
-            print " Event number %s " % prnt
+            print(" Event number %s " % prnt)
             self.printStat()
             bc = self.counter('eff')
             line = "(%s += %s)%s" % (bc.eff() * 100, bc.effErr() * 100, '%')
-            print ' Efficiency (binomial counter "eff"): %s' % line
+            print(' Efficiency (binomial counter "eff"): %s' % line)
 
         return SUCCESS
 
@@ -113,7 +113,7 @@ def configure(gaudi=None):
 # The actual job excution
 # =============================================================================
 if '__main__' == __name__:
-    print __doc__, __author__
+    print(__doc__, __author__)
     gaudi = GaudiPython.AppMgr()
     configure(gaudi)
     gaudi.run(5400)
diff --git a/GaudiExamples/scripts/EvtColRead.py b/GaudiExamples/scripts/EvtColRead.py
index e57202d668..3b1f4769a4 100755
--- a/GaudiExamples/scripts/EvtColRead.py
+++ b/GaudiExamples/scripts/EvtColRead.py
@@ -8,6 +8,7 @@
 *                                                                             *
 *******************************************************************************
 """
+from __future__ import print_function
 # =============================================================================
 __author__ = 'Vanya BELYAEV Ivan.Belyaev@lapp.in2p3.fr'
 # =============================================================================
@@ -44,7 +45,7 @@ def configure(gaudi=None):
 # The actual job excution
 # =============================================================================
 if '__main__' == __name__:
-    print __doc__
+    print(__doc__)
     # configuration (options)
     from Configurables import GaudiPersistency, FileCatalog, ApplicationMgr
     GaudiPersistency()
diff --git a/GaudiExamples/scripts/EvtColWrite.py b/GaudiExamples/scripts/EvtColWrite.py
index 225b967262..cebc014149 100755
--- a/GaudiExamples/scripts/EvtColWrite.py
+++ b/GaudiExamples/scripts/EvtColWrite.py
@@ -126,7 +126,7 @@ def configure(gaudi=None):
 # The actual job excution
 # =============================================================================
 if '__main__' == __name__:
-    print __doc__
+    print(__doc__)
     # configuration (options)
     from Configurables import GaudiPersistency, FileCatalog, ApplicationMgr
     GaudiPersistency()
diff --git a/GaudiExamples/scripts/ExtendedProperties.py b/GaudiExamples/scripts/ExtendedProperties.py
index 87148f7233..e5678f6e0c 100755
--- a/GaudiExamples/scripts/ExtendedProperties.py
+++ b/GaudiExamples/scripts/ExtendedProperties.py
@@ -8,6 +8,7 @@
 *                                                                             *
 *******************************************************************************
 """
+from __future__ import print_function
 # =============================================================================
 __author__ = 'Vanya BELYAEV ibelyaev@physics.syr.edu'
 # =============================================================================
@@ -108,7 +109,7 @@ def configure(gaudi=None):
 # =============================================================================
 if '__main__' == __name__:
 
-    print __doc__, __author__
+    print(__doc__, __author__)
 
     gaudi = gaudimodule.AppMgr()
     configure(gaudi)
@@ -125,20 +126,20 @@ if '__main__' == __name__:
     #
     props = alg.properties()
 
-    print 'All Properties of %s ' % alg.name()
+    print('All Properties of %s ' % alg.name())
     for p in props:
         v = props[p].value()
         t = type(v).__name__
-        print "Python: Name/Value:  '%s' / '%s' " % (p, v)
+        print("Python: Name/Value:  '%s' / '%s' " % (p, v))
 
     # get the properties in the form of python dictionary:
-    print 'All Properties of %s ' % alg.name()
+    print('All Properties of %s ' % alg.name())
     properties = {}
     for p in props:
         properties[p] = props[p].value()
 
     for p in properties:
-        print "Python: Name/Value:  '%s' / '%s' " % (p, properties[p])
+        print("Python: Name/Value:  '%s' / '%s' " % (p, properties[p]))
 
 
 # =============================================================================
diff --git a/GaudiExamples/scripts/ExtendedProperties2.py b/GaudiExamples/scripts/ExtendedProperties2.py
index 8262b63c4c..da3a858de2 100755
--- a/GaudiExamples/scripts/ExtendedProperties2.py
+++ b/GaudiExamples/scripts/ExtendedProperties2.py
@@ -7,6 +7,7 @@
 *                                                                             *
 *******************************************************************************
 """
+from __future__ import print_function
 # =============================================================================
 __author__ = 'Vanya BELYAEV ibelyaev@physics.syr.edu'
 # =============================================================================
@@ -39,7 +40,7 @@ ApplicationMgr(
 # =============================================================================
 if '__main__' == __name__:
 
-    print __doc__, __author__
+    print(__doc__, __author__)
 
     # make sure cling can generate all required methods in Gaudi::Property
     import cppyy
@@ -72,18 +73,18 @@ if '__main__' == __name__:
     try:
         xp2.SVector5 = [1, 2, 3, 4, 5, 6]
     except Exception as e:
-        print ' Exception: ', e
+        print(' Exception: ', e)
 
     try:
         xp2.Point3D = (1, 2, 3, 4)
     except Exception as e:
-        print ' Exception: ', e
+        print(' Exception: ', e)
 
     if not isWin:
         try:
             xp2.Vector4D = (1, 2, 3)
         except Exception as e:
-            print ' Exception: ', e
+            print(' Exception: ', e)
 
     xp2.Vectors3D = [(1, 2, 3), (4, 5, 6), [7, 8, 9]]
     if not isWin:
diff --git a/GaudiExamples/scripts/HistoDumpEx.py b/GaudiExamples/scripts/HistoDumpEx.py
index c1f27e46af..5aa0911f67 100755
--- a/GaudiExamples/scripts/HistoDumpEx.py
+++ b/GaudiExamples/scripts/HistoDumpEx.py
@@ -1,4 +1,5 @@
 #!/usr/bin/env python
+from __future__ import print_function
 
 import ROOT
 
@@ -22,11 +23,11 @@ for i in xrange(0, 1000000):
     p1.Fill(v, -0.1 * v2, 1)
     p2.Fill(v, -0.1 * v2, 1)
 
-print h1 . dump(50, 50, True)
-print h1 . dump(60, 30)
+print(h1 . dump(50, 50, True))
+print(h1 . dump(60, 30))
 
-print histoDump(h1, 10, 10)
-print histoDump(h1, 10, 10, True)
+print(histoDump(h1, 10, 10))
+print(histoDump(h1, 10, 10, True))
 
-print histoDump(p1, 10, 10, True)
-print histoDump(p2, 10, 10, True)
+print(histoDump(p1, 10, 10, True))
+print(histoDump(p2, 10, 10, True))
diff --git a/GaudiExamples/scripts/HistoEx.py b/GaudiExamples/scripts/HistoEx.py
index d75e11edf4..c914d88d05 100755
--- a/GaudiExamples/scripts/HistoEx.py
+++ b/GaudiExamples/scripts/HistoEx.py
@@ -8,6 +8,7 @@
 *                                                                             *
 *******************************************************************************
 """
+from __future__ import print_function
 # =============================================================================
 __author__ = 'Vanya BELYAEV Ivan.Belyaev@lapp.in2p3.fr'
 # =============================================================================
@@ -74,7 +75,7 @@ def configure(gaudi=None):
 # The actual job excution
 # =============================================================================
 if '__main__' == __name__:
-    print __doc__, __author__
+    print(__doc__, __author__)
 
     from GaudiPython.Bindings import AppMgr
     gaudi = AppMgr()
@@ -88,7 +89,7 @@ if '__main__' == __name__:
     for key in histos:
         histo = histos[key]
         if hasattr(histo, 'dump'):
-            print histo.dump(80, 20, True)
+            print(histo.dump(80, 20, True))
 
 # =============================================================================
 # The END
diff --git a/GaudiExamples/scripts/HistoEx1.py b/GaudiExamples/scripts/HistoEx1.py
index 9fdeeb2615..d7b00123ef 100755
--- a/GaudiExamples/scripts/HistoEx1.py
+++ b/GaudiExamples/scripts/HistoEx1.py
@@ -10,6 +10,7 @@
 *                                                                             *
 *******************************************************************************
 """
+from __future__ import print_function
 # =============================================================================
 __author__ = 'Vanya BELYAEV Ivan.Belyaev@lapp.in2p3.fr'
 # =============================================================================
@@ -79,7 +80,7 @@ def configure(gaudi=None):
 # The actual job excution
 # =============================================================================
 if '__main__' == __name__:
-    print __doc__, __author__
+    print(__doc__, __author__)
 
     from GaudiPython.Bindings import AppMgr
     gaudi = AppMgr()
@@ -94,6 +95,6 @@ if '__main__' == __name__:
     for key in histos:
         histo = histos[key]
         if hasattr(histo, 'dump'):
-            print histo.dump(80, 20, True)
+            print(histo.dump(80, 20, True))
 
 # =============================================================================
diff --git a/GaudiExamples/scripts/HistoEx2.py b/GaudiExamples/scripts/HistoEx2.py
index 3b2057fc31..3eb37a5b01 100755
--- a/GaudiExamples/scripts/HistoEx2.py
+++ b/GaudiExamples/scripts/HistoEx2.py
@@ -10,6 +10,7 @@
 *                                                                             *
 *******************************************************************************
 """
+from __future__ import print_function
 # =============================================================================
 __author__ = 'Vanya BELYAEV ibelyaev@physics.syr.edu'
 # =============================================================================
@@ -76,7 +77,7 @@ def configure(gaudi=None):
 # The actual job execution
 # =============================================================================
 if '__main__' == __name__:
-    print __doc__, __author__
+    print(__doc__, __author__)
 
     from GaudiPython.Bindings import AppMgr
     import GaudiPython.HistoUtils
@@ -94,6 +95,6 @@ if '__main__' == __name__:
         histos = alg.Histos()
         for key in histos:
             histo = histos[key]
-            print " Alg='%s', ID='%s' , Histo=%s " % (alg.name(), key, histo)
+            print(" Alg='%s', ID='%s' , Histo=%s " % (alg.name(), key, histo))
             if hasattr(histo, 'dump'):
-                print histo.dump(60, 20, True)
+                print(histo.dump(60, 20, True))
diff --git a/GaudiExamples/scripts/HistoUtilsEx.py b/GaudiExamples/scripts/HistoUtilsEx.py
index 68efc4a8f0..315edd8f3d 100755
--- a/GaudiExamples/scripts/HistoUtilsEx.py
+++ b/GaudiExamples/scripts/HistoUtilsEx.py
@@ -10,6 +10,7 @@
 Simple example to illustrate the usage functions from HistoUtils module
 (Gaudi histograms outside of algorithm-scope in 'script-like' environment)
 """
+from __future__ import print_function
 # =============================================================================
 __author__ = "Vanya BELYAEV  Ivan.Belyaev@nikhef.nl"
 # =============================================================================
@@ -24,7 +25,7 @@ from GaudiPython.HistoUtils import (
     aida2root
 )
 
-print __doc__
+print(__doc__)
 
 # get the application manager   (create if needed)
 gaudi = AppMgr()
@@ -71,8 +72,8 @@ for i in xrange(0, 10000):
     histo2.fill(gauss())
 
 # print them:
-print ' Histo1:        ', histo1
-print ' Histo2:        ', histo2
+print(' Histo1:        ', histo1)
+print(' Histo2:        ', histo2)
 
 # convert to ROOT:
 rhisto1 = aida2root(histo1)
@@ -103,26 +104,26 @@ rhisto1.Print()
 rhisto2.Print()
 
 # get some "extra infomration"
-print ' Histo1 : mean    /err:  %10f +- %10f  ' % (
-    histo1.mean(), histo1.meanErr())
-print ' Histo1 : rms     /err:  %10f +- %10f  ' % (
-    histo1.rms(), histo1.rmsErr())
-print ' Histo1 : skewness/err:  %10f +- %10f  ' % (
-    histo1.skewness(), histo1.skewnessErr())
-print ' Histo1 : kurtosis/err:  %10f +- %10f  ' % (
-    histo1.kurtosis(), histo1.kurtosisErr())
-print ' Histo1 : path in THS : "%s"' % histo1.path()
-
-
-print ' Histo2 : mean    /err:  %10f +- %10f  ' % (
-    histo2.mean(), histo2.meanErr())
-print ' Histo2 : rms     /err:  %10f +- %10f  ' % (
-    histo2.rms(), histo2.rmsErr())
-print ' Histo2 : skewness/err:  %10f +- %10f  ' % (
-    histo2.skewness(), histo2.skewnessErr())
-print ' Histo2 : kurtosis/err:  %10f +- %10f  ' % (
-    histo2.kurtosis(), histo2.kurtosisErr())
-print ' Histo2 : path in THS : "%s"' % histo2.path()
+print(' Histo1 : mean    /err:  %10f +- %10f  ' % (
+    histo1.mean(), histo1.meanErr()))
+print(' Histo1 : rms     /err:  %10f +- %10f  ' % (
+    histo1.rms(), histo1.rmsErr()))
+print(' Histo1 : skewness/err:  %10f +- %10f  ' % (
+    histo1.skewness(), histo1.skewnessErr()))
+print(' Histo1 : kurtosis/err:  %10f +- %10f  ' % (
+    histo1.kurtosis(), histo1.kurtosisErr()))
+print(' Histo1 : path in THS : "%s"' % histo1.path())
+
+
+print(' Histo2 : mean    /err:  %10f +- %10f  ' % (
+    histo2.mean(), histo2.meanErr()))
+print(' Histo2 : rms     /err:  %10f +- %10f  ' % (
+    histo2.rms(), histo2.rmsErr()))
+print(' Histo2 : skewness/err:  %10f +- %10f  ' % (
+    histo2.skewness(), histo2.skewnessErr()))
+print(' Histo2 : kurtosis/err:  %10f +- %10f  ' % (
+    histo2.kurtosis(), histo2.kurtosisErr()))
+print(' Histo2 : path in THS : "%s"' % histo2.path())
 
 
 # =============================================================================
diff --git a/GaudiExamples/scripts/Mix.py b/GaudiExamples/scripts/Mix.py
index 5d8f16dedb..844aa51975 100755
--- a/GaudiExamples/scripts/Mix.py
+++ b/GaudiExamples/scripts/Mix.py
@@ -9,6 +9,7 @@
 Simple example to illustrate the problem for task #13911
 https://savannah.cern.ch/task/?13911
 """
+from __future__ import print_function
 # =============================================================================
 __author__ = "Vanya BELYAEV Ivan.Belyaev@itep.ru"
 __date__ = "2010-04-24"
@@ -32,7 +33,7 @@ class SimpleAlgo(GaudiAlgo):
 
     def execute(self):
 
-        print 'I am SimpleAlgo.execute!  ', self.name()
+        print('I am SimpleAlgo.execute!  ', self.name())
 
         return SUCCESS
 
@@ -78,11 +79,11 @@ def configure():
 if '__main__' == __name__:
 
     # make printout of the own documentations
-    print '*' * 120
-    print __doc__
-    print ' Author  : %s ' % __author__
-    print ' Date    : %s ' % __date__
-    print '*' * 120
+    print('*' * 120)
+    print(__doc__)
+    print(' Author  : %s ' % __author__)
+    print(' Date    : %s ' % __date__)
+    print('*' * 120)
 
     configure()
 
diff --git a/GaudiExamples/scripts/Properties.py b/GaudiExamples/scripts/Properties.py
index 1bc10cb59a..ad06900c08 100755
--- a/GaudiExamples/scripts/Properties.py
+++ b/GaudiExamples/scripts/Properties.py
@@ -8,6 +8,7 @@
 *                                                                             *
 *******************************************************************************
 """
+from __future__ import print_function
 # =============================================================================
 __author__ = 'Vanya BELYAEV ibelyaev@physics.syr.edu'
 # =============================================================================
@@ -97,7 +98,7 @@ def configure(gaudi=None):
 # =============================================================================
 if '__main__' == __name__:
 
-    print __doc__, __author__
+    print(__doc__, __author__)
 
     gaudi = gaudimodule.AppMgr()
     configure(gaudi)
@@ -106,10 +107,10 @@ if '__main__' == __name__:
     alg = gaudi.algorithm('PropertyAlg')
 
     props = alg.properties()
-    print 'Properties of %s ' % alg.name()
+    print('Properties of %s ' % alg.name())
     for p in props:
         v = props[p].value()
-        print "Python: Name/Value:  '%s' / '%s' " % (p, v)
+        print("Python: Name/Value:  '%s' / '%s' " % (p, v))
 
 # =============================================================================
 # The END
diff --git a/GaudiExamples/scripts/StringKeyEx.py b/GaudiExamples/scripts/StringKeyEx.py
index ed9168b6a9..8fd5e71608 100755
--- a/GaudiExamples/scripts/StringKeyEx.py
+++ b/GaudiExamples/scripts/StringKeyEx.py
@@ -7,6 +7,7 @@
 *                                                                             *
 *******************************************************************************
 """
+from __future__ import print_function
 # =============================================================================
 __author__ = 'Vanya BELYAEV Ivan.Belyaev@nikhef.nl'
 # =============================================================================
@@ -38,8 +39,8 @@ ApplicationMgr(
 # =============================================================================
 if '__main__' == __name__:
 
-    print __doc__
-    print __author__
+    print(__doc__)
+    print(__author__)
 
     from GaudiPython.Bindings import AppMgr
 
@@ -57,13 +58,13 @@ if '__main__' == __name__:
 
     key = SK('new Key')
 
-    print 'set new key: ', key
+    print('set new key: ', key)
 
     ske.Key = key
 
     keys = [key, 'rrr', SK('s')]
 
-    print 'set new keys: ', keys
+    print('set new keys: ', keys)
 
     ske.Keys = keys
 
diff --git a/GaudiExamples/scripts/TupleEx.py b/GaudiExamples/scripts/TupleEx.py
index 4cbaf66d27..af32bb31aa 100755
--- a/GaudiExamples/scripts/TupleEx.py
+++ b/GaudiExamples/scripts/TupleEx.py
@@ -16,6 +16,7 @@
 *                                                                             *
 *******************************************************************************
 """
+from __future__ import print_function
 # =============================================================================
 __author__ = 'Vanya BELYAEV Ivan.Belyaev@lapp.in2p3.fr'
 # =============================================================================
@@ -103,7 +104,7 @@ def configure(gaudi=None):
 #  @author Vanya BELYAEV ibelyaev@physics.syr.edu
 #  @date 2006-11-26
 if '__main__' == __name__:
-    print __doc__
+    print(__doc__)
     from GaudiPython.Bindings import AppMgr
     gaudi = AppMgr()
     configure(gaudi)
diff --git a/GaudiExamples/scripts/TupleEx1.py b/GaudiExamples/scripts/TupleEx1.py
index 39b038f8ec..d4eac0169f 100755
--- a/GaudiExamples/scripts/TupleEx1.py
+++ b/GaudiExamples/scripts/TupleEx1.py
@@ -16,6 +16,7 @@
 *                                                                             *
 *******************************************************************************
 """
+from __future__ import print_function
 # =============================================================================
 __author__ = 'Vanya BELYAEV Ivan.Belyaev@lapp.in2p3.fr'
 # =============================================================================
@@ -192,7 +193,7 @@ def configure(gaudi=None):
 #  @author Vanya BELYAEV ibelyaev@physics.syr.edu
 #  @date 2006-11-26
 if '__main__' == __name__:
-    print __doc__
+    print(__doc__)
     gaudi = GaudiPython.AppMgr()
     configure(gaudi)
     gaudi.run(20)
diff --git a/GaudiExamples/scripts/TupleEx2.py b/GaudiExamples/scripts/TupleEx2.py
index e7196d5dce..6c4926e154 100755
--- a/GaudiExamples/scripts/TupleEx2.py
+++ b/GaudiExamples/scripts/TupleEx2.py
@@ -16,6 +16,7 @@
 *                                                                             *
 *******************************************************************************
 """
+from __future__ import print_function
 # =============================================================================
 __author__ = 'Vanya BELYAEV Ivan.Belyaev@lapp.in2p3.fr'
 # =============================================================================
@@ -141,7 +142,7 @@ def configure(gaudi=None):
 #  @author Vanya BELYAEV ibelyaev@physics.syr.edu
 #  @date 2006-11-26
 if '__main__' == __name__:
-    print __doc__
+    print(__doc__)
     gaudi = GaudiPython.AppMgr()
     configure(gaudi)
     gaudi.run(20)
diff --git a/GaudiExamples/scripts/TupleEx3.py b/GaudiExamples/scripts/TupleEx3.py
index e889af80ed..365299e4c5 100755
--- a/GaudiExamples/scripts/TupleEx3.py
+++ b/GaudiExamples/scripts/TupleEx3.py
@@ -16,6 +16,7 @@
 *                                                                             *
 *******************************************************************************
 """
+from __future__ import print_function
 # =============================================================================
 __author__ = 'Vanya BELYAEV ibelyaev@physics.syr.edu'
 # =============================================================================
@@ -229,7 +230,7 @@ def configure(gaudi=None):
 #  @author Vanya BELYAEV ibelyaev@physics.syr.edu
 #  @date 2007-01-24
 if '__main__' == __name__:
-    print __doc__
+    print(__doc__)
     gaudi = GaudiPython.AppMgr()
     configure(gaudi)
     gaudi.run(10)
diff --git a/GaudiExamples/scripts/bug_38882.py b/GaudiExamples/scripts/bug_38882.py
index 27a893488c..12e812eea0 100755
--- a/GaudiExamples/scripts/bug_38882.py
+++ b/GaudiExamples/scripts/bug_38882.py
@@ -1,4 +1,5 @@
 #!/usr/bin/env python
+from __future__ import print_function
 # =============================================================================
 
 # =============================================================================
@@ -25,7 +26,7 @@ class TestAlg(GaudiAlgo):
 
     def execute(self):
         """ The main method 'execute', it is invoked for each event """
-        print "=== %s Execute ===" % self.name()
+        print("=== %s Execute ===" % self.name())
         return SUCCESS
 
 # =============================================================================
diff --git a/GaudiExamples/tests/scripts/test_timing_histo_file.py b/GaudiExamples/tests/scripts/test_timing_histo_file.py
index 99ee9013b3..5fabc86592 100755
--- a/GaudiExamples/tests/scripts/test_timing_histo_file.py
+++ b/GaudiExamples/tests/scripts/test_timing_histo_file.py
@@ -5,6 +5,7 @@ Check the content of the ROOT file generated by the test 'gaudiexamples.timing_h
 
 The file must contain a directory called 'TIMER.TIMER' with 3 well defined histograms inside.
 """
+from __future__ import print_function
 import sys
 
 
@@ -58,6 +59,6 @@ if __name__ == '__main__':
     try:
         test()
     except AssertionError as a:
-        print "FAILURE:", a
+        print("FAILURE:", a)
         sys.exit(1)
-    print "SUCCESS"
+    print("SUCCESS")
diff --git a/GaudiHive/options/graphanalysis.py b/GaudiHive/options/graphanalysis.py
index 326027ff95..32b6e79012 100644
--- a/GaudiHive/options/graphanalysis.py
+++ b/GaudiHive/options/graphanalysis.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 from pygraph.classes.digraph import digraph
 from pygraph.algorithms.cycles import find_cycle
 from pygraph.algorithms.accessibility import connected_components
@@ -40,10 +41,10 @@ def analyze_and_fix_cycles(gr):
             has_loop = False
             continue
         n_cycles += 1
-        print cycle
-        print "Removed loop by deleting edge (%s,%s)" % (cycle[-1], cycle[0])
+        print(cycle)
+        print("Removed loop by deleting edge (%s,%s)" % (cycle[-1], cycle[0]))
         gr.del_edge((cycle[-1], cycle[0]))
-    print "\nIN TOTAL %i CYCLES\n" % (n_cycles)
+    print("\nIN TOTAL %i CYCLES\n" % (n_cycles))
     return n_cycles > 0  # whether it needed to fix cycles
 
 
@@ -54,10 +55,10 @@ def analyze_connected_componets(gr):
         cc_size[i] = 0
     for k, v in cc.iteritems():
         cc_size[v] = cc_size[v] + 1
-    print "Connected components have the following size:"
+    print("Connected components have the following size:")
 #    for k,v in cc_size.iteritems():
-#      print "%i : %i" %(k,v)
-    print "NUMBER OF CONNECTED COMPONENTS: %i" % (len(cc_size.keys()))
+#      print("%i : %i" %(k,v))
+    print("NUMBER OF CONNECTED COMPONENTS: %i" % (len(cc_size.keys())))
 
 
 def analyze_critical_path(gr):
@@ -73,9 +74,9 @@ def analyze_critical_path(gr):
     for edge in edges:
         critical_time += gr.edge_weight(edge)
 
-    print "Total time   : %s" % total_time
-    print "Critical path: %s" % critical_time
-    print "POSSIBLE SPEEDUP: %s" % (total_time / critical_time)
+    print("Total time   : %s" % total_time)
+    print("Critical path: %s" % critical_time)
+    print("POSSIBLE SPEEDUP: %s" % (total_time / critical_time))
 
 
 def print_graph_to_json(gr, filename):
diff --git a/GaudiHive/options/jsonFromLHCbLog.py b/GaudiHive/options/jsonFromLHCbLog.py
index 5cda50229e..11b9df409f 100644
--- a/GaudiHive/options/jsonFromLHCbLog.py
+++ b/GaudiHive/options/jsonFromLHCbLog.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 from pygraph.classes.graph import graph
 
 
@@ -67,4 +68,4 @@ def load_brunel_scenario(filename):
 if __name__ == "__main__":
     json = {}
     json["algorithms"] = load_brunel_scenario("Brunel.TES.trace.log")
-    print json
+    print(json)
diff --git a/GaudiHive/profiling/brunelWrapper.py b/GaudiHive/profiling/brunelWrapper.py
index aabe4941b8..5a77c71a2f 100755
--- a/GaudiHive/profiling/brunelWrapper.py
+++ b/GaudiHive/profiling/brunelWrapper.py
@@ -5,7 +5,7 @@ This script acts as a wrapper in order to generate Gaudi configs for running
 with different parameters in order to perform performance measurements.
 It takes command line arguments.
 """
-
+from __future__ import print_function
 import optparse
 """
 NumberOfEvents = 10
@@ -96,7 +96,7 @@ if __name__ == "__main__":
     if options.bg:
         command += " &"
 
-    print command
+    print(command)
     if options.execbrunel:
         import os
         os.system(command)
diff --git a/GaudiHive/profiling/plotBacklogPyRoot.py b/GaudiHive/profiling/plotBacklogPyRoot.py
index 85bee7683b..b1b327f959 100644
--- a/GaudiHive/profiling/plotBacklogPyRoot.py
+++ b/GaudiHive/profiling/plotBacklogPyRoot.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 from ROOT import *
 import sys
 import re
@@ -79,7 +80,7 @@ def createInFlightGraph(nevts):
     graph.SetLineStyle(2)
     graph.SetTitle(
         "GaudiHive Backlog (Brunel, 100 evts);Events Finished;Event Backlog")
-    print NEventsInFlight
+    print(NEventsInFlight)
     return graph
 
 
@@ -137,6 +138,6 @@ def doPlot(logfilename, logfilename_copy):
 if __name__ == "__main__":
     argc = len(sys.argv)
     if argc != 3:
-        print "Usage: plotBacklogPyRoot.py logfilename logfilename_copy"
+        print("Usage: plotBacklogPyRoot.py logfilename logfilename_copy")
         sys.exit(1)
     doPlot(sys.argv[1], sys.argv[2])
diff --git a/GaudiHive/profiling/plotClonesPyRoot.py b/GaudiHive/profiling/plotClonesPyRoot.py
index b50f1d4f89..c21a41b264 100644
--- a/GaudiHive/profiling/plotClonesPyRoot.py
+++ b/GaudiHive/profiling/plotClonesPyRoot.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 from ROOT import *
 import sys
 import re
@@ -122,6 +123,6 @@ def doPlot(logfilename):
 if __name__ == "__main__":
     argc = len(sys.argv)
     if argc != 2:
-        print "Usage: plotClonesPyRoot.py logfilename"
+        print("Usage: plotClonesPyRoot.py logfilename")
         sys.exit(1)
     doPlot(sys.argv[1])
diff --git a/GaudiHive/profiling/plotSpeedup.py b/GaudiHive/profiling/plotSpeedup.py
index c4d13c820b..b208eccdf9 100644
--- a/GaudiHive/profiling/plotSpeedup.py
+++ b/GaudiHive/profiling/plotSpeedup.py
@@ -1,4 +1,5 @@
 #! /usr/bin/env python
+from __future__ import print_function
 
 """
 Script that fetches all the logfiles from disk and reads the timings.
@@ -24,12 +25,12 @@ filename_scheleton = "timing_measurement_BrunelScenario_n150_eif%s_aif%s_nthread
 def getRuntime(n_algos_in_flight,  n_evts_in_flight, cloneFlag):
     filename = filename_scheleton % (
         n_evts_in_flight, n_algos_in_flight, cloneFlag)
-    print filename
+    print(filename)
     rt = 0.
     for line in open(filename, "r").readlines():
         rt = float(line[:-1])
-        # print filename
-        # print rt
+        # print(filename)
+        # print(rt)
     return rt
 
 
@@ -98,7 +99,7 @@ def make_plot(runtimes, cloneFlag):
     graphs = []
     first = True
     for colour, n_evts_in_flight, line_style in zip(colour_l, n_evts_in_flight_l, line_style_l):
-        print n_evts_in_flight
+        print(n_evts_in_flight)
         graph = getSingleGraph(n_evts_in_flight, cloneFlag,
                                runtimes, colour, line_style)
         opts = "LSame"
diff --git a/GaudiHive/profiling/plotSpeedupsPyRoot.py b/GaudiHive/profiling/plotSpeedupsPyRoot.py
index fdda121c03..7bcd557925 100644
--- a/GaudiHive/profiling/plotSpeedupsPyRoot.py
+++ b/GaudiHive/profiling/plotSpeedupsPyRoot.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 from ROOT import *
 
 '''
@@ -117,10 +118,10 @@ if len(sys.argv) > 1:
 
 # main loop: just printouts
 for neif in neif_l:
-    print "Events in flight: %s" % neif
+    print("Events in flight: %s" % neif)
     for tn in nts:
-        print "%s %s %s" % (tn, xtractTiming(
-            neif, tn, False), xtractTiming(neif, tn, True))
+        print("%s %s %s" % (tn, xtractTiming(
+            neif, tn, False), xtractTiming(neif, tn, True)))
 
 
 len_nt = len(nts) + 1
diff --git a/GaudiHive/profiling/prepareBenchmark.py b/GaudiHive/profiling/prepareBenchmark.py
index 664966c8c0..fc4095312e 100644
--- a/GaudiHive/profiling/prepareBenchmark.py
+++ b/GaudiHive/profiling/prepareBenchmark.py
@@ -1,5 +1,5 @@
 # File to prepare the configs and commands to be executed for the benchmark
-
+from __future__ import print_function
 import commands
 
 
@@ -29,5 +29,5 @@ if __name__ == "__main__":
             config = prepareConfig("../options/BrunelScenario.py", n_threads=n_threads,
                                    n_parallel_events=n_events, n_parallel_algorithms=n_algos)
             # config.replace(".py",".log"))
-            print "/usr/bin/time -f %%S -o %s.time `alias gaudirun` %s > %s" % (
-                config.replace(".py", ""), config, "/dev/null")
+            print("/usr/bin/time -f %%S -o %s.time `alias gaudirun` %s > %s" % (
+                config.replace(".py", ""), config, "/dev/null"))
diff --git a/GaudiHive/python/GaudiHive/precedence.py b/GaudiHive/python/GaudiHive/precedence.py
index eb982b8d9b..0a4d6f37e7 100644
--- a/GaudiHive/python/GaudiHive/precedence.py
+++ b/GaudiHive/python/GaudiHive/precedence.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 import os
 import sys
 import random
@@ -15,7 +16,7 @@ def _buildFilePath(filePath):
         __fullFilePath__ = os.path.realpath(os.path.join(
             os.environ.get('GAUDIHIVEROOT', ''), "data", filePath))
         if not os.path.exists(__fullFilePath__):
-            print "\nERROR: invalid file path '%s'. It must be either absolute, or relative to '$GAUDIHIVEROOT/data/'." % filePath
+            print("\nERROR: invalid file path '%s'. It must be either absolute, or relative to '$GAUDIHIVEROOT/data/'." % filePath)
             sys.exit(1)
     else:
         __fullFilePath__ = filePath
@@ -66,8 +67,8 @@ class RealTimeValue(object):
                 time = float(self.timings[capAlgoName])
             else:
                 time = self.defaultTime
-                print "WARNING: TimiNg for %s (or %s) not found in the provided library, using default one: %s" % (
-                    algoName, capAlgoName, time)
+                print("WARNING: TimiNg for %s (or %s) not found in the provided library, using default one: %s" % (
+                    algoName, capAlgoName, time))
 
         time = time * self.factor
 
@@ -161,28 +162,28 @@ class CruncherSequence(object):
         if showStat:
             import pprint
 
-            print "\n===== Statistics on Algorithms ====="
-            print "Total number of algorithm nodes: ", len(
-                self.unique_algos) + sum([self.dupl_algos[i] - 1 for i in self.dupl_algos])
-            print "Number of unique algorithms: ", len(self.unique_algos)
-            print "  -->", len(self.dupl_algos), "of them being re-used with the following distribution: ", [
-                self.dupl_algos[i] for i in self.dupl_algos]
+            print("\n===== Statistics on Algorithms =====")
+            print("Total number of algorithm nodes: ", len(
+                self.unique_algos) + sum([self.dupl_algos[i] - 1 for i in self.dupl_algos]))
+            print("Number of unique algorithms: ", len(self.unique_algos))
+            print("  -->", len(self.dupl_algos), "of them being re-used with the following distribution: ", [
+                self.dupl_algos[i] for i in self.dupl_algos])
             # pprint.pprint(dupl_algos)
 
-            print "\n===== Statistics on Sequencers ====="
-            print "Total number of sequencers: ", len(
-                self.unique_sequencers) + sum([self.dupl_seqs[i] - 1 for i in self.dupl_seqs])
-            print "Number of unique sequencers: ", len(self.unique_sequencers)
-            print "  -->", len(self.dupl_seqs), "of them being re-used with the following distribution: ", [
-                self.dupl_seqs[i] for i in self.dupl_seqs]
+            print("\n===== Statistics on Sequencers =====")
+            print("Total number of sequencers: ", len(
+                self.unique_sequencers) + sum([self.dupl_seqs[i] - 1 for i in self.dupl_seqs]))
+            print("Number of unique sequencers: ", len(self.unique_sequencers))
+            print("  -->", len(self.dupl_seqs), "of them being re-used with the following distribution: ", [
+                self.dupl_seqs[i] for i in self.dupl_seqs])
             # pprint.pprint(dupl_seqs)
-            print "Number of OR-sequencers: ", len(self.OR_sequencers)
+            print("Number of OR-sequencers: ", len(self.OR_sequencers))
 
-            print "\n===== Statistics on DataObjects ====="
-            print "Number of unique DataObjects: ", len(
-                self.unique_data_objects)
+            print("\n===== Statistics on DataObjects =====")
+            print("Number of unique DataObjects: ", len(
+                self.unique_data_objects))
             # pprint.pprint(self.unique_data_objects)
-            print
+            print()
 
     def get(self):
 
@@ -239,7 +240,7 @@ class CruncherSequence(object):
                     self.OR_sequencers.append(n)
                     seq_daughter.ModeOR = True
                 # if self.cfg.node[n].get('Lazy') == 'False':
-                #    print "Non-Lazy - ", n
+                #    print("Non-Lazy - ", n)
                 seq_daughter.ShortCircuit = False
                 if seq_daughter not in seq.Members:
                     seq.Members += [seq_daughter]
diff --git a/GaudiHive/scripts/hivetimeline.py b/GaudiHive/scripts/hivetimeline.py
index bab2d82d8b..12fb8f520d 100755
--- a/GaudiHive/scripts/hivetimeline.py
+++ b/GaudiHive/scripts/hivetimeline.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 """Plot timeline from TimelineSvc"""
-
+from __future__ import print_function
 __author__ = "Frank Winklmeier"
 
 import sys
@@ -97,7 +97,7 @@ def plot(data, showThreads=True, batch=False, nevtcolors=10, width=1200, height=
         if alg not in colors and len(mycolors) > 0:
             colors[alg] = mycolors.pop(0)
             if len(mycolors) == 0:
-                print "Too many algorithm to show"
+                print("Too many algorithm to show")
 
         if alg in colors:
             t0 = d.start - tmin
diff --git a/GaudiKernel/python/GaudiConfig/ControlFlow.py b/GaudiKernel/python/GaudiConfig/ControlFlow.py
index e57a70be24..13eb284339 100644
--- a/GaudiKernel/python/GaudiConfig/ControlFlow.py
+++ b/GaudiKernel/python/GaudiConfig/ControlFlow.py
@@ -3,6 +3,7 @@ Classes for the implementation of the Control Flow Structure Syntax.
 
 @see: https://github.com/lhcb/scheduling-event-model/tree/master/controlflow_syntax
 '''
+from __future__ import print_function
 
 
 class ControlFlowNode(object):
@@ -205,12 +206,12 @@ class _TestVisitor(object):
 
     def enter(self, visitee):
         self.depths += 1
-        print "%sEntering %s" % (self.depths * " ", type(visitee))
+        print("%sEntering %s" % (self.depths * " ", type(visitee)))
         if isinstance(visitee, ControlFlowLeaf):
-            print "%s Algorithm name: %s" % (" " * self.depths, visitee)
+            print("%s Algorithm name: %s" % (" " * self.depths, visitee))
 
     def leave(self, visitee):
-        print "%sLeaving %s" % (self.depths * " ", type(visitee))
+        print("%sLeaving %s" % (self.depths * " ", type(visitee)))
         self.depths -= 1
 
 
@@ -325,11 +326,11 @@ def test():
     aLine = line("MyTriggerPath", expression)
     visitor = _TestVisitor()
     visitor2 = DotVisitor()
-    print "\nPrinting trigger line:"
-    print aLine
-    print "\nPrinting expression:"
-    print expression
-    print "\nTraversing through expression:\n"
+    print("\nPrinting trigger line:")
+    print(aLine)
+    print("\nPrinting expression:")
+    print(expression)
+    print("\nTraversing through expression:\n")
     expression.visitNode(visitor)
     expression.visitNode(visitor2)
     visitor2.write("out.dot")
diff --git a/GaudiKernel/python/GaudiKernel/Configurable.py b/GaudiKernel/python/GaudiKernel/Configurable.py
index 0a17885038..64254723ef 100644
--- a/GaudiKernel/python/GaudiKernel/Configurable.py
+++ b/GaudiKernel/python/GaudiKernel/Configurable.py
@@ -1146,8 +1146,8 @@ class ConfigurableAlgTool(Configurable):
         return pop + Configurable.getPrintTitle(self)
 
     def setParent(self, parentName):
-        #       print "ConfigurableAlgTool.setParent(%s@%x,%r)" % (self.getName(),id(self),parentName)
-        #       print "Calling stack:"
+        #       print("ConfigurableAlgTool.setParent(%s@%x,%r)" % (self.getName(),id(self),parentName))
+        #       print("Calling stack:")
         #       import traceback
         #       traceback.print_stack()
         # propagate parent to AlgTools in children
diff --git a/GaudiKernel/python/GaudiKernel/GaudiHandles.py b/GaudiKernel/python/GaudiKernel/GaudiHandles.py
index 51929bb862..e9b70ea5a9 100644
--- a/GaudiKernel/python/GaudiKernel/GaudiHandles.py
+++ b/GaudiKernel/python/GaudiKernel/GaudiHandles.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 # explicit list for wildcard imports
 __all__ = [
     "GaudiHandle",
@@ -187,8 +188,8 @@ class GaudiHandleArray(list):
             # not yet there, so add it
             list.append(self, value)
         else:
-            print "%s    WARNING %r with instance name %r already in list. Not adding %r" % \
-                  (self.__class__.__name__, oldValue, oldValue.getName(), value)
+            print("%s    WARNING %r with instance name %r already in list. Not adding %r" % \
+                  (self.__class__.__name__, oldValue, oldValue.getName(), value))
 
     def isPublic(self):
         return self.__class__.handleType.isPublic
diff --git a/GaudiKernel/python/GaudiKernel/PropertyProxy.py b/GaudiKernel/python/GaudiKernel/PropertyProxy.py
index 58c0ce45d0..b034df6548 100644
--- a/GaudiKernel/python/GaudiKernel/PropertyProxy.py
+++ b/GaudiKernel/python/GaudiKernel/PropertyProxy.py
@@ -183,7 +183,7 @@ class GaudiHandlePropertyProxyBase(PropertyProxy):
         PropertyProxy.__init__(self, descr, docString, default)
         self._handleType = handleType
         self._confTypeName = 'Configurable' + handleType.componentType
-#      print "%s: %r (%s)" % (self.__class__.__name__,self._handleType,self._confTypeName)
+#      print("%s: %r (%s)" % (self.__class__.__name__,self._handleType,self._confTypeName))
 
     def __get__(self, obj, type=None):
         try:
@@ -243,7 +243,7 @@ class GaudiHandlePropertyProxyBase(PropertyProxy):
         # turn string into handle
         isString = type(default) == str
         if not isString and self.isConfig(default):
-            #         print self.fullPropertyName(obj) + ": Setting default configurable: %r" % default
+            #         print(self.fullPropertyName(obj) + ": Setting default configurable: %r" % default)
             return default
         elif isString or self.isHandle(default):
             if isString:
@@ -259,7 +259,7 @@ class GaudiHandlePropertyProxyBase(PropertyProxy):
                 try:
                     conf = self.getDefaultConfigurable(
                         typeAndName, self.fullPropertyName(obj))
-#               print self.fullPropertyName(obj) + ": Setting default private configurable (from default handle): %r" % conf
+#               print(self.fullPropertyName(obj) + ": Setting default private configurable (from default handle): %r" % conf)
                 except AttributeError as e:
                     # change type of exception to avoid false error message
                     raise RuntimeError(*e.args)
@@ -403,7 +403,7 @@ class DataObjectHandleBasePropertyProxy(PropertyProxy):
 
 
 def PropertyProxyFactory(descr, doc, default):
-    #   print "PropertyProxyFactory( %s, %r )" % (descr.__name__,default)
+    #   print("PropertyProxyFactory( %s, %r )" % (descr.__name__,default))
 
     if isinstance(default, GaudiHandleArray):
         return GaudiHandleArrayPropertyProxy(descr, doc, default)
diff --git a/GaudiKernel/python/GaudiKernel/RootMap.py b/GaudiKernel/python/GaudiKernel/RootMap.py
index 56ec05667d..8800f23c9a 100644
--- a/GaudiKernel/python/GaudiKernel/RootMap.py
+++ b/GaudiKernel/python/GaudiKernel/RootMap.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-
+from __future__ import print_function
 import os
 import sys
 
@@ -63,7 +63,7 @@ def _procSysRootMap(rtmapdict):
                 else:
                     block = _getBlock(line)
     else:
-        print "WARNING: No ROOTSYS defined!"
+        print("WARNING: No ROOTSYS defined!")
 
 
 def _isRootMap(filename):
@@ -106,12 +106,12 @@ def printMaps(maps, recomp=None):
         kys = filter(recomp.search, kys)
     for k in kys:
         if len(maps[k]) > 1:
-            print "!!!!!!!!!!!! WARNING - More than one entry !!!!!!!!!!"
+            print("!!!!!!!!!!!! WARNING - More than one entry !!!!!!!!!!")
         for l in maps[k]:
-            print frmat % k,
+            print(frmat % k, end=' ')
             for m in l:
-                print m,
-            print " "
+                print(m, end=' ')
+            print(" ")
     return
 
 
@@ -122,13 +122,13 @@ def shortPrintMaps(maps, recomp=None):
         kys = filter(recomp.search, kys)
     for k in kys:
         if len(maps[k]) > 1:
-            print k, "!!!!!!!!!!!! WARNING - More than one entry !!!!!!!!!!"
+            print(k, "!!!!!!!!!!!! WARNING - More than one entry !!!!!!!!!!")
         else:
-            print k
+            print(k)
         for l in maps[k]:
             for m in l:
-                print "\t%s" % m,
-            print " "
+                print("\t%s" % m, end=' ')
+            print(" ")
     return
 
 
@@ -139,9 +139,9 @@ def printKeys(maps, recomp=None):
         kys = filter(recomp.search, kys)
     for k in kys:
         if len(maps[k]) > 1:
-            print "!!!!!!!!!!!! WARNING - More than one entry !!!!!!!!!!"
+            print("!!!!!!!!!!!! WARNING - More than one entry !!!!!!!!!!")
         for l in maps[k]:
-            print k
+            print(k)
     return
 
 
@@ -152,10 +152,10 @@ def checkDict(maps, recomp=None):
         kys = filter(recomp.search, kys)
     for k in kys:
         if len(maps[k]) > 1:
-            print "!!!!!!!!!!!! WARNING - More than one entry !!!!!!!!!!"
-            print k
+            print("!!!!!!!!!!!! WARNING - More than one entry !!!!!!!!!!")
+            print(k)
             for l in maps[k]:
                 for m in l:
-                    print "\t%s" % m,
-                print " "
+                    print("\t%s" % m, end=' ')
+                print(" ")
     return
diff --git a/GaudiKernel/scripts/gaudiComponentHelp.py b/GaudiKernel/scripts/gaudiComponentHelp.py
index abf7d6cace..5a92a9ac46 100644
--- a/GaudiKernel/scripts/gaudiComponentHelp.py
+++ b/GaudiKernel/scripts/gaudiComponentHelp.py
@@ -2,6 +2,8 @@
 """
 Print help messages for gaudi components
 """
+from __future__ import print_function
+
 from Gaudi import Configuration
 import Configurables
 import os
@@ -24,27 +26,27 @@ if __name__ == "__main__":
 
     cfgDb = Configuration.cfgDb
     if opts.list:
-        print "Available components:\n%s" % (21 * "=")
+        print("Available components:\n%s" % (21 * "="))
         for item in sorted(cfgDb):
-            print "  %s (from %s)" % (item, cfgDb[item]["lib"])
+            print("  %s (from %s)" % (item, cfgDb[item]["lib"]))
         sys.exit()
     elif opts.name:
         name = opts.name
         if name not in cfgDb:
-            print "Component %s not found." % (name)
+            print("Component %s not found." % (name))
             sys.exit()
-        print "\nDumping component information for %s:\n%s" % (
-            name, (35 + len(name)) * "=")
-        print "  Library: %s" % (cfgDb[name]["lib"])
-        print "  Package: %s" % (cfgDb[name]["package"])
-        print "\nProperties:\n%s" % (11 * "-")
+        print("\nDumping component information for %s:\n%s" % (
+            name, (35 + len(name)) * "="))
+        print("  Library: %s" % (cfgDb[name]["lib"]))
+        print("  Package: %s" % (cfgDb[name]["package"]))
+        print("\nProperties:\n%s" % (11 * "-"))
         try:
             properties = getattr(Configurables, name)(
             ).getPropertiesWithDescription()
         except AttributeError:
-            print "  Not a configurable component. No properties to show."
+            print("  Not a configurable component. No properties to show.")
             sys.exit()
         for label, (value, desc) in sorted(properties.iteritems()):
-            print ("  %s\t : %s\t (%s) " % (label, value, str(
-                desc).replace("None", " no description "))).expandtabs(30)
+            print(("  %s\t : %s\t (%s) " % (label, value, str(
+                desc).replace("None", " no description "))).expandtabs(30))
         sys.exit()
diff --git a/GaudiKernel/scripts/root_map_dump.py b/GaudiKernel/scripts/root_map_dump.py
index c441f98c5c..6d1d24e42b 100755
--- a/GaudiKernel/scripts/root_map_dump.py
+++ b/GaudiKernel/scripts/root_map_dump.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-
+from __future__ import print_function
 import os.path
 from GaudiKernel.RootMap import getMaps, checkDict
 from GaudiKernel.RootMap import printMaps, shortPrintMaps
@@ -7,7 +7,7 @@ from GaudiKernel.RootMap import printKeys
 
 
 def _help(argv):
-    print """
+    print("""
   %s [-h] [-s|-e|-c] [-r] [-p pattern] [listofpath]
   
      -h: dump this Help
@@ -23,7 +23,7 @@ def _help(argv):
   rootmap file(s) on separate lines. The output is sorted according to
   the name of the entry. A Warning is issued if an entry appears
   several times.
-  """ % os.path.basename(argv[0])
+  """ % os.path.basename(argv[0]))
 
 
 if __name__ == "__main__":
diff --git a/GaudiKernel/tests/qmtest/scripts/test_bug_87340.py b/GaudiKernel/tests/qmtest/scripts/test_bug_87340.py
index 03f04b4783..13875f74c7 100755
--- a/GaudiKernel/tests/qmtest/scripts/test_bug_87340.py
+++ b/GaudiKernel/tests/qmtest/scripts/test_bug_87340.py
@@ -4,6 +4,7 @@ Test that the there is no signature for MsgStream operator<< <char []> in
 GaudiKernel.
 See https://savannah.cern.ch/bugs?87340
 """
+from __future__ import print_function
 import os
 import sys
 import re
@@ -26,24 +27,24 @@ try:
                      for n in searchpath)
            if os.path.exists(p)).next()
 except StopIteration:
-    print >> sys.stderr, 'FAILURE: Cannot find', repr(
-        libname), 'in', searchpath
+    print('FAILURE: Cannot find', repr(libname), 'in', searchpath,
+          file=sys.stderr)
     sys.exit(2)
 
 nm = Popen(["nm", '-C', lib], stdout=PIPE)
 output, _ = nm.communicate()
 
 if nm.returncode:
-    print output
-    print >> sys.stderr, 'FAILURE: nm call failed'
+    print(output)
+    print('FAILURE: nm call failed', file=sys.stderr)
     sys.exit(nm.returncode)
 
 signature = re.compile(r"MsgStream&amp; operator&lt;&lt; &lt;char \[\d+\]&gt;")
 
 lines = filter(signature.search, output.splitlines())
 if lines:
-    print "\n".join(lines)
-    print >> sys.stderr, "FAILURE: found MsgStream operator<< specialization"
+    print("\n".join(lines))
+    print("FAILURE: found MsgStream operator<< specialization", file=sys.stderr)
     sys.exit(1)
 else:
-    print "SUCCESS: no MsgStream operator<< specialization found"
+    print("SUCCESS: no MsgStream operator<< specialization found")
diff --git a/GaudiMP/python/GaudiMP/GMPBase.py b/GaudiMP/python/GaudiMP/GMPBase.py
index 58295473bc..ec118d871e 100644
--- a/GaudiMP/python/GaudiMP/GMPBase.py
+++ b/GaudiMP/python/GaudiMP/GMPBase.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 from Gaudi.Configuration import *
 from GaudiPython import AppMgr, gbl, setOwnership, PyAlgorithm, SUCCESS, FAILURE, InterfaceCast
 from ROOT import TBufferFile, TBuffer
@@ -623,7 +624,7 @@ class GMPComponent(object):
                     objects += 1
                 histDict[n] = o
         else:
-            print 'WARNING : no histograms to recover?'
+            print('WARNING : no histograms to recover?')
         return histDict
 
     def Initialize(self):
@@ -687,9 +688,9 @@ class Reader(GMPComponent):
 
     def DumpEvent(self):
         tb = TBufferFile(TBuffer.kWrite)
-        # print '----Reader dumping Buffer!!!'
+        # print('----Reader dumping Buffer!!!')
         self.ts.dumpBuffer(tb)
-        # print '\tBuffer Dumped, size : %i'%( tb.Length() )
+        # print('\tBuffer Dumped, size : %i'%( tb.Length() ))
         return tb
 
     def DoFirstEvent(self):
diff --git a/GaudiMP/python/GaudiMP/Parallel.py b/GaudiMP/python/GaudiMP/Parallel.py
index 865501a37a..08682236c2 100644
--- a/GaudiMP/python/GaudiMP/Parallel.py
+++ b/GaudiMP/python/GaudiMP/Parallel.py
@@ -1,5 +1,6 @@
 # File: GaudiMP/Parallel.py
 # Author: Pere Mato (pere.mato@cern.ch)
+from __future__ import print_function
 
 """ GaudiMP.Parallel module.
     This module provides 'parallel' processing support for GaudiPyhton.
@@ -181,7 +182,7 @@ class WorkManager(object):
                 self._mergeStatistics(stat)
             end = time.time()
             self._printStatistics()
-            print 'Time elapsed since server creation %f' % (end - start)
+            print('Time elapsed since server creation %f' % (end - start))
         # --- Call the Local Finalize
         task.finalize()
 
@@ -189,11 +190,11 @@ class WorkManager(object):
         njobs = 0
         for stat in self.stats.values():
             njobs += stat.njob
-        print 'Job execution statistics:'
-        print 'job count | % of all jobs | job time sum | time per job | job server'
+        print('Job execution statistics:')
+        print('job count | % of all jobs | job time sum | time per job | job server')
         for name, stat in self.stats.items():
-            print '       %d |        %6.2f |     %8.3f |    %8.3f | %s' % (
-                stat.njob, 100. * stat.njob / njobs, stat.time, stat.time / stat.njob, name)
+            print('       %d |        %6.2f |     %8.3f |    %8.3f | %s' % (
+                stat.njob, 100. * stat.njob / njobs, stat.time, stat.time / stat.njob, name))
 
     def _mergeStatistics(self, stat):
         if stat.name not in self.stats:
@@ -225,8 +226,8 @@ class SshSession(object):
                            (sys.executable, ppprefix, sys.version.split()[0]))
         self.session.read_lazy()
         self.session.read_lazy()
-        print 'started ppserver in ', hostname
+        print('started ppserver in ', hostname)
 
     def __del__(self):
         self.session.close()
-        print 'killed ppserver in ', self.host
+        print('killed ppserver in ', self.host)
diff --git a/GaudiMP/scripts/compareOutputFiles.py b/GaudiMP/scripts/compareOutputFiles.py
index d2169a1131..f8b5474344 100755
--- a/GaudiMP/scripts/compareOutputFiles.py
+++ b/GaudiMP/scripts/compareOutputFiles.py
@@ -1,4 +1,4 @@
-
+from __future__ import print_function
 from Gaudi.Configuration import *
 from GaudiPython import AppMgr, gbl
 from ROOT import TFile, TBufferFile, TBuffer
@@ -71,12 +71,12 @@ def CompareTrees(pname, sname):
     if pMeta == sMeta:
         pass
     else:
-        print 'Meta Data differs'
+        print('Meta Data differs')
 
     if pEvent == sEvent:
         pass
     else:
-        print 'Event data differs'
+        print('Event data differs')
 
     if pOther != sOther:
         pset = set(pOther)
@@ -84,11 +84,11 @@ def CompareTrees(pname, sname):
         pExtra = pset - sset
         sExtra = sset - pset
         if pExtra:
-            print 'Extra Data in parallel file : ', pExtra
+            print('Extra Data in parallel file : ', pExtra)
         if sExtra:
-            print 'Extra Data in serial   file : ', sExtra
+            print('Extra Data in serial   file : ', sExtra)
         if sExtra or pExtra:
-            print 'Files will have different sizes'
+            print('Files will have different sizes')
     pf.Close()
     sf.Close()
 
@@ -101,9 +101,9 @@ def switchDict(d):
     nvals = len(vals)
     for v in vals:
         if vals.count(v) > 1:
-            print 'Dictionary cannot be switched, values not unique'
+            print('Dictionary cannot be switched, values not unique')
             return None
-    print 'Dict has keys/values : %i/%i' % (nkeys, nvals)
+    print('Dict has keys/values : %i/%i' % (nkeys, nvals))
     pairs = d.items()  # returns (key, val) tuples in a list
     newd = {}
     for k, entry in pairs:
@@ -119,11 +119,11 @@ def printDict(d, name='unspecified'):
     #   key     value
     #   ...
     #
-    print '-' * 80
-    print 'Dictionary %s : ' % (name)
+    print('-' * 80)
+    print('Dictionary %s : ' % (name))
     for k in iter(d.keys()):
-        print '\t', k, '\t', d[k]
-    print '-' * 80
+        print('\t', k, '\t', d[k])
+    print('-' * 80)
 
 
 def Reader(readerType, filename, qacross, qToEngine):
@@ -172,7 +172,7 @@ def Reader(readerType, filename, qacross, qToEngine):
             pass
         lsks = len(serOrder.keys())
         lpks = len(order.keys())
-        print 'Events in Files (serial/parallel) : %i / %i' % (lsks, lpks)
+        print('Events in Files (serial/parallel) : %i / %i' % (lsks, lpks))
 
     # now run files in the order specified by the serial ordering
     # and send them one by one to the comparison engine
@@ -188,7 +188,7 @@ def Reader(readerType, filename, qacross, qToEngine):
             [(l, (evt[l].__class__.__name__, evt[l].__repr__())) for l in lst])
         qToEngine.put(ascii)
     qToEngine.put(None)
-    print '%s Reader Finished' % (readerType)
+    print('%s Reader Finished' % (readerType))
 
 
 def ComparisonEngine(pQueue, sQueue):
@@ -205,22 +205,22 @@ def ComparisonEngine(pQueue, sQueue):
         pitem = pQueue.get()
         sitem = sQueue.get()
         if pitem == sitem == None:
-            print 'Termination Signals received ok'
+            print('Termination Signals received ok')
             break
         elif pitem == None:
-            print 'pitem != sitem : ', pitem, sitem
+            print('pitem != sitem : ', pitem, sitem)
             break
         elif sitem == None:
-            print 'pitem != sitem : ', pitem, sitem
+            print('pitem != sitem : ', pitem, sitem)
             break
         results.append(compareEvents(pitem, sitem))
-    print '=' * 80
-    print 'Comparison Engine Finished'
-    print '-' * 80
-    print 'Total Events Checked : %i' % (len(results))
-    print 'Perfect Matches      : %i' % (sum(results))
-    print 'Errors               : %i' % (len(results) - sum(results))
-    print '=' * 80
+    print('=' * 80)
+    print('Comparison Engine Finished')
+    print('-' * 80)
+    print('Total Events Checked : %i' % (len(results)))
+    print('Perfect Matches      : %i' % (sum(results)))
+    print('Errors               : %i' % (len(results) - sum(results)))
+    print('=' * 80)
 
 
 def checkForAddressDifference(a, b):
@@ -264,7 +264,7 @@ def compareEvents(s, p):
             if p[e][0] == 'DataObject':
                 pks.remove(e)
             else:
-                print 'Extra Other thing found!', e, p[e][0]
+                print('Extra Other thing found!', e, p[e][0])
                 return False
 
     # check 2 : same paths?
@@ -300,7 +300,7 @@ def compareEvents(s, p):
 
 def CheckFileRecords(par, ser):
 
-    print "Checking File Records"
+    print("Checking File Records")
 
     parFSR = GetFSRdicts(par)
     serFSR = GetFSRdicts(ser)
@@ -310,15 +310,15 @@ def CheckFileRecords(par, ser):
     diff2 = set(parFSR["EventCountFSR"].iteritems()) - \
         set(serFSR["EventCountFSR"].iteritems())
 
-    print "\nDifferent entries in TimeSpanFSR:  \t" + \
-        str(len(diff1)) + "\nDifferent entries in EventCountFSR:\t" + str(len(diff2))
+    print("\nDifferent entries in TimeSpanFSR:  \t" + \
+        str(len(diff1)) + "\nDifferent entries in EventCountFSR:\t" + str(len(diff2)))
 
     for k in ["LumiFSRBeamCrossing", "LumiFSRBeam2", "LumiFSRNoBeam"]:
         diff3 = set(parFSR[k]["key"]) - set(serFSR[k]["key"])
         diff4 = set(parFSR[k]["incr"]) - set(serFSR[k]["incr"])
         diff5 = set(parFSR[k]["integral"]) - set(serFSR[k]["integral"])
-        print "Different entries in " + str(k) + ": \tkey: " + str(
-            len(diff3)) + " increment: " + str(len(diff4)) + " integral: " + str(len(diff5))
+        print("Different entries in " + str(k) + ": \tkey: " + str(
+            len(diff3)) + " increment: " + str(len(diff4)) + " integral: " + str(len(diff5)))
 
 
 def LumiFSR(lumi):
@@ -409,25 +409,25 @@ def CompareFSR(pout, sout):
     parFSR = pout.get()
     serFSR = sout.get()
 
-    print "Comparing File Records"
+    print("Comparing File Records")
 
     diff1 = set(parFSR["TimeSpanFSR"].iteritems()) - \
         set(serFSR["TimeSpanFSR"].iteritems())
     diff2 = set(parFSR["EventCountFSR"].iteritems()) - \
         set(serFSR["EventCountFSR"].iteritems())
 
-    print "\nDifferent entries in TimeSpanFSR:  \t" + \
-        str(len(diff1)) + "\nDifferent entries in EventCountFSR:\t" + str(len(diff2))
+    print("\nDifferent entries in TimeSpanFSR:  \t" + \
+        str(len(diff1)) + "\nDifferent entries in EventCountFSR:\t" + str(len(diff2)))
 
     for k in ["LumiFSRBeamCrossing", "LumiFSRBeam2", "LumiFSRNoBeam"]:
         diff3 = set(parFSR[k]['key']) - set(serFSR[k]['key'])
         diff4 = set(parFSR[k]['incr']) - set(serFSR[k]['incr'])
         diff5 = set(parFSR[k]['integral']) - set(serFSR[k]["integral"])
-        print "Different entries in " + str(k) + ": \tkey: " + str(
-            len(diff3)) + " increment: " + str(len(diff4)) + " integral: " + str(len(diff5))
+        print("Different entries in " + str(k) + ": \tkey: " + str(
+            len(diff3)) + " increment: " + str(len(diff4)) + " integral: " + str(len(diff5)))
 
-    print "\nParallel: \n" + str(parFSR)
-    print "\nSerial: \n" + str(serFSR)
+    print("\nParallel: \n" + str(parFSR))
+    print("\nSerial: \n" + str(serFSR))
 
 
 if __name__ == '__main__':
@@ -435,13 +435,13 @@ if __name__ == '__main__':
     args = sys.argv
     args.pop(0)  # get rid of script name
     if len(args) != 2:
-        print 'Please supply two arguments : > python loadFile <parallelFile> <serialFile>'
+        print('Please supply two arguments : > python loadFile <parallelFile> <serialFile>')
         sys.exit(0)
     else:
         par = 'PFN:' + args[0]
         ser = 'PFN:' + args[1]
-        print 'Parallel File to be analysed : %s' % (par)
-        print 'Serial   File to be analysed : %s' % (ser)
+        print('Parallel File to be analysed : %s' % (par))
+        print('Serial   File to be analysed : %s' % (ser))
 
     pname = par[4:]  # TFile doesn't need the "PFN:" prefix
     sname = ser[4:]
@@ -459,7 +459,7 @@ if __name__ == '__main__':
 
     #CompareTrees( pname, sname )
 
-    print "Check File Records"
+    print("Check File Records")
 
     ser = sys.argv[0]
     par = sys.argv[1]
diff --git a/GaudiMP/scripts/compareRootHistos.py b/GaudiMP/scripts/compareRootHistos.py
index 2af9b4ed61..aa4f20f6d5 100755
--- a/GaudiMP/scripts/compareRootHistos.py
+++ b/GaudiMP/scripts/compareRootHistos.py
@@ -1,4 +1,5 @@
 #! /usr/bin/env python
+from __future__ import print_function
 from optparse import OptionParser
 import re
 import sys
@@ -88,7 +89,7 @@ def comparePaths(t1, t2):
         ds = t2[1]
         dp = t1[1]
     else:
-        print 'Neither tuple is Reference Root file reference?'
+        print('Neither tuple is Reference Root file reference?')
         return
 
     dsks = ds.keys()
@@ -100,42 +101,42 @@ def comparePaths(t1, t2):
     pset = set(dpks)
     os, hs = composition((ref, ds))
     op, hp = composition((test, dp))
-    print '\n' + '=' * 80
-    print 'Comparison of Paths : Reference vs Test ROOT files'
-    print '-' * 80
-    print 'Number of paths in Reference file : %i (objects, histos) = ( %i, %i )' % (
-        len(dsks), os, hs)
-    print 'Number of paths in Test file : %i (objects, histos) = ( %i, %i )' % (
-        len(dpks), op, hp)
+    print('\n' + '=' * 80)
+    print('Comparison of Paths : Reference vs Test ROOT files')
+    print('-' * 80)
+    print('Number of paths in Reference file : %i (objects, histos) = ( %i, %i )' % (
+        len(dsks), os, hs))
+    print('Number of paths in Test file : %i (objects, histos) = ( %i, %i )' % (
+        len(dpks), op, hp))
     matching = sset.intersection(pset)
     matchingHistos = 0
     for n in matching:
         if ds[n].__class__.__name__ in histos:
             matchingHistos += 1
-    print '\nMatching paths                 : %i' % (len(matching))
+    print('\nMatching paths                 : %i' % (len(matching)))
     uSer = sset - pset
     # work out histos unique to test file
     uniqueReferenceHistos = 0
     for n in uSer:
         if ds[n].__class__.__name__ in histos:
             uniqueReferenceHistos += 1
-    print 'Paths unique to Reference file : %i ( %i Histos )' % (
-        len(uSer), uniqueReferenceHistos)
+    print('Paths unique to Reference file : %i ( %i Histos )' % (
+        len(uSer), uniqueReferenceHistos))
     if uSer:
         for n in uSer:
-            print '\t%s : \t%s' % (ds[n], n)
+            print('\t%s : \t%s' % (ds[n], n))
     uPar = pset - sset
     uniqueTestHistos = 0
     for n in uPar:
         if dp[n].__class__.__name__ in histos:
             uniqueTestHistos += 1
-    print 'Paths unique to Test file : %i ( %i Histos )' % (
-        len(uPar), uniqueTestHistos)
+    print('Paths unique to Test file : %i ( %i Histos )' % (
+        len(uPar), uniqueTestHistos))
     if uPar:
         for n in uPar:
-            print '\t%s : \t%s' % (dp[n], n)
-    print 'Matching Histos to test : %i' % (matchingHistos)
-    print '=' * 80 + '\n'
+            print('\t%s : \t%s' % (dp[n], n))
+    print('Matching Histos to test : %i' % (matchingHistos)
+    print('=' * 80 + '\n')
     return (((os, hs), (op, hp)), (uSer, uniqueReferenceHistos), (uPar, uniqueTestHistos), matchingHistos)
 # =============================================================================
 
@@ -194,7 +195,7 @@ def compareHistos(t1, t2, state, checkBin2BinIdentity):
         ds = t2[1]
         dp = t1[1]
     else:
-        print 'Neither tuple is Reference Root file reference?'
+        print('Neither tuple is Reference Root file reference?')
         return
 
     # histocount, objectcount for test/reference
@@ -275,7 +276,7 @@ def compareHistos(t1, t2, state, checkBin2BinIdentity):
                 if int(kTest):
                     passedKol += 1
                 else:
-                    # ; print 'KTest result : ', kTest
+                    # ; print('KTest result : ', kTest)
                     failedKol += 1
                     diffKols.append(h)
             else:
@@ -290,95 +291,95 @@ def compareHistos(t1, t2, state, checkBin2BinIdentity):
                     xIntegrals += 1
         else:
             notfound += 1
-            print 'not found? ', h
+            print('not found? ', h)
 
     # report on Failed Entry-Checks
-    print '\n\n' + '-' * 80
-    print 'Summary of histos with different Entries'
-    print '-' * 80
+    print('\n\n' + '-' * 80)
+    print('Summary of histos with different Entries')
+    print('-' * 80)
     if diffEntries:
         diffEntries.sort()
         for e in diffEntries:
-            print '\t\t\t%s:\t%i != %i' % (
-                e, int(ds[e].GetEntries()), int(dp[e].GetEntries()))
-    print '-' * 80
+            print('\t\t\t%s:\t%i != %i' % (
+                e, int(ds[e].GetEntries()), int(dp[e].GetEntries())))
+    print('-' * 80)
 
     # report on Failed Kolmogorov Tests
-    print '\n\n' + '-' * 60
-    print 'Summary of histos which failed Kolmogorov Test'
-    print '-' * 60
+    print('\n\n' + '-' * 60)
+    print('Summary of histos which failed Kolmogorov Test')
+    print('-' * 60)
     if diffKols:
         diffKols.sort()
         for e in diffKols:
             result = kTestResults[e]  # DP Calculated twice ARGH!!
-            print '%s\t\t%s :\tK-Test Result :\t %5.16f' % (
-                ds[e].ClassName(), e, result)
-    print '-' * 60
+            print('%s\t\t%s :\tK-Test Result :\t %5.16f' % (
+                ds[e].ClassName(), e, result))
+    print('-' * 60)
 
     # report on Failed Integral Checks
-    print '\n\n' + '-' * 60
-    print 'Summary of histos which failed Integral Check'
-    print '-' * 60
+    print('\n\n' + '-' * 60)
+    print('Summary of histos which failed Integral Check')
+    print('-' * 60)
     if diffIntegrals:
         diffIntegrals.sort()
         for e in diffIntegrals:
             diff = dp[e].Integral() - ds[e].Integral()
             pc = (diff * 100) / ds[e].Integral()
-            print '%s\t\t%s:\t Diff = %5.6f\tPercent Diff to Reference : %5.6f ' % (
-                ds[e].ClassName(), e, diff, pc)
-    print '-' * 60 + '\n'
-    print '=' * 80 + '\n'
+            print('%s\t\t%s:\t Diff = %5.6f\tPercent Diff to Reference : %5.6f ' % (
+                ds[e].ClassName(), e, diff, pc))
+    print('-' * 60 + '\n')
+    print('=' * 80 + '\n')
 
     # Report on failed bin2bin identity
     if checkBin2BinIdentity:
         # report on b2b checks
-        print '\n\n' + '-' * 80
-        print 'Summary of histos with at least one bin with different Entries'
-        print '-' * 80
+        print('\n\n' + '-' * 80)
+        print('Summary of histos with at least one bin with different Entries')
+        print('-' * 80)
         if diffIdentity:
             diffIdentity.sort()
             for e in diffIdentity:
-                print '%s\t\t%s: %i different bins' % (
-                    ds[e].ClassName(), e, identityDiffBins[e])
-            print '-' * 80
-
-    print '\n' + '=' * 80
-    print 'Comparison : Reference/Test ROOT Histo files'
-    print '\n\t\tReference\tTest'
-    print '\tObjects : %i\t%i\t\t( p-s = %i )' % (referenceObjects,
-                                                  parallObjects, parallObjects - referenceObjects)
-    print '\tHistos  : %i\t%i\t\t( p-s = %i )' % (referenceHistos,
-                                                  parallHistos,  parallHistos - referenceHistos)
-    print '\t          __________'
-    print '\tTotal   : %i\t%i\n' % (
-        referenceHistos + referenceObjects,  parallHistos + parallObjects)
-    print 'Objects/Histos unique to Reference File : %i / %i' % (
-        len(uniqueSerPaths) - uniqueSerHistos, uniqueSerHistos)
-    print 'Objects/Histos unique to Test File : %i / %i' % (
-        len(uniqueParPaths) - uniqueParHistos, uniqueParHistos)
-    print '\nMatching Histograms valid for Comparison : %i' % (mh)
-    print '\nOmissions\' patterns : '
+                print('%s\t\t%s: %i different bins' % (
+                    ds[e].ClassName(), e, identityDiffBins[e]))
+            print('-' * 80)
+
+    print('\n' + '=' * 80)
+    print('Comparison : Reference/Test ROOT Histo files')
+    print('\n\t\tReference\tTest')
+    print('\tObjects : %i\t%i\t\t( p-s = %i )' % (referenceObjects,
+                                                  parallObjects, parallObjects - referenceObjects))
+    print('\tHistos  : %i\t%i\t\t( p-s = %i )' % (referenceHistos,
+                                                  parallHistos,  parallHistos - referenceHistos))
+    print('\t          __________')
+    print('\tTotal   : %i\t%i\n' % (
+        referenceHistos + referenceObjects,  parallHistos + parallObjects))
+    print('Objects/Histos unique to Reference File : %i / %i' % (
+        len(uniqueSerPaths) - uniqueSerHistos, uniqueSerHistos))
+    print('Objects/Histos unique to Test File : %i / %i' % (
+        len(uniqueParPaths) - uniqueParHistos, uniqueParHistos))
+    print('\nMatching Histograms valid for Comparison : %i' % (mh))
+    print('\nOmissions\' patterns : ')
     for entry in gRegexBlackList:
-        print '\t%s' % (entry)
-    print '\nHistograms for Comparison (after Omissions) : %i' % (
-        mh - len(gRegexBlackList))
-    print '\n\tHISTOGRAM TESTS : '
-    print '\t\tKOLMOGOROV TEST      : %i' % (kTested)
-    print '\t\tINTEGRAL TEST        : %i' % (otherTest)
-    print '\t\tENTRIES TEST         : %i' % (xEntries)
+        print('\t%s' % (entry))
+    print('\nHistograms for Comparison (after Omissions) : %i' % (
+        mh - len(gRegexBlackList)))
+    print('\n\tHISTOGRAM TESTS : ')
+    print('\t\tKOLMOGOROV TEST      : %i' % (kTested))
+    print('\t\tINTEGRAL TEST        : %i' % (otherTest))
+    print('\t\tENTRIES TEST         : %i' % (xEntries))
     if checkBin2BinIdentity:
-        print '\t\tBIN2BIN TEST         : %i' % (passedIdentity)
-    print '\t\t                       ____'
-    print '\t\tTested               : %i' % (cEntries)
-
-    print '\n\tDISCREPANCIES : '
-    print '\t\tK-Test      : %i' % (failedKol)
-    print '\t\tIntegrals   : %i' % (xIntegrals)
-    print '\t\tEntries     : %i' % (xEntries)
+        print('\t\tBIN2BIN TEST         : %i' % (passedIdentity))
+    print('\t\t                       ____')
+    print('\t\tTested               : %i' % (cEntries))
+
+    print('\n\tDISCREPANCIES : ')
+    print('\t\tK-Test      : %i' % (failedKol))
+    print('\t\tIntegrals   : %i' % (xIntegrals))
+    print('\t\tEntries     : %i' % (xEntries))
     retval = failedKol + xIntegrals + xEntries + failedIdentity
     if retval != 0:
-        print '\nThe two sets of histograms were not identical'
-    print '\n' + '=' * 80
+        print('\nThe two sets of histograms were not identical')
+    print('\n' + '=' * 80)
     return retval
 
 # =============================================================================
@@ -407,8 +408,8 @@ if __name__ == '__main__':
     (options, args) = parser.parse_args()
 
     if len(args) != 2:
-        print "Wrong number of rootfiles. Usage:"
-        print usage
+        print("Wrong number of rootfiles. Usage:")
+        print(usage)
         sys.exit(1)
 
     extractBlacklist(options.blacklist)
@@ -416,9 +417,9 @@ if __name__ == '__main__':
     testFile, referenceFile = args
 
     tfs = TFile(testFile, 'REC')
-    print 'opening Test File : %s' % (testFile)
+    print('opening Test File : %s' % (testFile))
     tfp = TFile(referenceFile, 'REC')
-    print 'opening Reference File : %s' % (referenceFile)
+    print('opening Reference File : %s' % (referenceFile))
 
     # get structure of TFiles in a list of (path, object) tuples
     lref = rec(tfs)
diff --git a/GaudiPluginService/python/GaudiPluginService/cpluginsvc.py b/GaudiPluginService/python/GaudiPluginService/cpluginsvc.py
index e8fd4d8c29..091b5c3691 100644
--- a/GaudiPluginService/python/GaudiPluginService/cpluginsvc.py
+++ b/GaudiPluginService/python/GaudiPluginService/cpluginsvc.py
@@ -1,4 +1,5 @@
 # cpluginsvc is a ctypes-based wrapper for the C-exposed API of GaudiPluginService
+from __future__ import print_function
 __doc__ = '''
 cpluginsvc is a ctypes-based wrapper for the C-API of the GaudiPluginService.
 
@@ -9,11 +10,11 @@ e.g.:
 ...     try:
 ...         f.load()
 ...     except Exception:
-...         print ("** could not load [%s] for factory [%s]" % (f.library, f.name))
+...         print(("** could not load [%s] for factory [%s]" % (f.library, f.name)))
 ...         continue
-...     print f
+...     print(f)
 ...     for k,v in f.properties.iteritems():
-...         print ("\t%s: %s" % (k,v))
+...         print(("\t%s: %s" % (k,v)))
 '''
 
 import ctypes
@@ -225,17 +226,17 @@ for f in _functions_list:
 
 
 if __name__ == "__main__":
-    print ("instance: %s" % registry())
-    print ("factories: %d" % len(factories()))
+    print("instance: %s" % registry())
+    print("factories: %d" % len(factories()))
     for _, f in factories().items():
         try:
             f.load()
         except Exception:
-            print (
+            print(
                 "** could not load [%s] for factory [%s]" % (f.library, f.name))
             continue
-        print f
+        print(f)
         for k, v in f.properties.items():
-            print ("\t%s: %s" % (k, v))
+            print("\t%s: %s" % (k, v))
 
 # EOF
diff --git a/GaudiPolicy/python/GaudiTesting/BaseTest.py b/GaudiPolicy/python/GaudiTesting/BaseTest.py
index 1e598ac143..92872b5e34 100644
--- a/GaudiPolicy/python/GaudiTesting/BaseTest.py
+++ b/GaudiPolicy/python/GaudiTesting/BaseTest.py
@@ -250,9 +250,9 @@ class BaseTest(object):
         resultDict.append(('Working Directory',
                            RationalizePath(os.path.join(os.getcwd(),
                                                         self.workdir))))
-        # print dict(resultDict).keys()
+        # print(dict(resultDict).keys())
         resultDict.extend(self.result.annotations.iteritems())
-        # print self.result.annotations.keys()
+        # print(self.result.annotations.keys())
         return dict(resultDict)
 
     # -------------------------------------------------#
diff --git a/GaudiPolicy/python/GaudiTesting/QMTTest.py b/GaudiPolicy/python/GaudiTesting/QMTTest.py
index 738b561b82..06e17b28cd 100644
--- a/GaudiPolicy/python/GaudiTesting/QMTTest.py
+++ b/GaudiPolicy/python/GaudiTesting/QMTTest.py
@@ -111,7 +111,7 @@ class QMTTest(BaseTest):
                                                  "result": result,
                                                  "causes": self.causes})
                                 }
-            # print self.validator
+            # print(self.validator)
             exec(self.validator, globals(), exported_symbols)
             return result, self.causes
         else:
diff --git a/GaudiPolicy/python/GaudiTesting/Run.py b/GaudiPolicy/python/GaudiTesting/Run.py
index 1ed4f219d2..a832236de5 100644
--- a/GaudiPolicy/python/GaudiTesting/Run.py
+++ b/GaudiPolicy/python/GaudiTesting/Run.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import print_function
 import os
 import sys
 import xml.sax.saxutils as XSS
@@ -14,14 +15,14 @@ def basic_report(results):
     Report function taking the dictionary from BasicTest.run() and display
     stdout and stderr from it.
     '''
-    print '=== stdout ==='
-    print results.get('stdout', '')
-    print '=== stderr ==='
-    print results.get('stderr', '')
-    print '=== result ==='
-    print results.get('Status')
+    print('=== stdout ===')
+    print(results.get('stdout', ''))
+    print('=== stderr ===')
+    print(results.get('stderr', ''))
+    print('=== result ===')
+    print(results.get('Status'))
     if results.get('Status') != 'passed' and 'Causes' in results:
-        print '   ', 'unexpected ' + ', '.join(results['Causes'])
+        print('   ', 'unexpected ' + ', '.join(results['Causes']))
 
 
 def quiet_report(results):
@@ -37,8 +38,8 @@ def ctest_report(results):
     from it in a CTest-friendly way.
     '''
     # It's weird, I know, but it tells CTest not to cut the output.
-    print 'CTEST_FULL_OUTPUT'
-    print results.get('stdout', '')
+    print('CTEST_FULL_OUTPUT')
+    print(results.get('stdout', ''))
     handler = {'Environment': lambda v: '\n'.join('{0}={1}'.format(*item)
                                                   for item in sorted(v.iteritems())),
                'Causes': lambda v: 'unexpected ' + ', '.join(v)}
diff --git a/GaudiPolicy/qmtest_classes/GaudiTest.py b/GaudiPolicy/qmtest_classes/GaudiTest.py
index 66e921ae31..49f7b7efc1 100644
--- a/GaudiPolicy/qmtest_classes/GaudiTest.py
+++ b/GaudiPolicy/qmtest_classes/GaudiTest.py
@@ -2,6 +2,7 @@
 # File:   GaudiTest.py
 # Author: Marco Clemencic CERN/PH-LBC
 ########################################################################
+from __future__ import print_function
 __author__ = 'Marco Clemencic CERN/PH-LBC'
 ########################################################################
 # Imports
@@ -85,7 +86,7 @@ class TemporaryEnvironment:
         Create a temporary environment on top of the one specified
         (it can be another TemporaryEnvironment instance).
         """
-        # print "New environment"
+        # print("New environment")
         self.old_values = {}
         self.env = orig
         self._keep_same = keep_same
@@ -155,7 +156,7 @@ class TemporaryEnvironment:
         """
         Revert the changes on destruction.
         """
-        # print "Restoring the environment"
+        # print("Restoring the environment")
         self.restore()
 
     def gen_script(self, shell_type):
@@ -1892,7 +1893,7 @@ class GaudiExeTest(ExecTestBase):
             # Write the output file
             codecs.open(destfile, "w", encoding='utf-8').write(xml)
         except:
-            print 'WARNING: problem generating Eclipse launcher'
+            print('WARNING: problem generating Eclipse launcher')
 
 
 try:
diff --git a/GaudiProfiling/python/GaudiProfiling/GenerateGaudiOpts.py b/GaudiProfiling/python/GaudiProfiling/GenerateGaudiOpts.py
index 9e1b74d4f4..076107efc1 100644
--- a/GaudiProfiling/python/GaudiProfiling/GenerateGaudiOpts.py
+++ b/GaudiProfiling/python/GaudiProfiling/GenerateGaudiOpts.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 import os
 import sys
 import time
@@ -41,7 +42,7 @@ def generateOptions(counter, cmask, invmask, sampling_period, startatevent, stor
     pfaud.START_AT_EVENT = startatevent
     #pfaud.LEVEL = 5
     AuditorSvc().Auditors.append(pfaud)
-    print pfaud
+    print(pfaud)
 
 
 class XmlDictObject(dict):
diff --git a/GaudiPython/python/GaudiPython/Bindings.py b/GaudiPython/python/GaudiPython/Bindings.py
index a9960a845d..6fc08d04c9 100644
--- a/GaudiPython/python/GaudiPython/Bindings.py
+++ b/GaudiPython/python/GaudiPython/Bindings.py
@@ -1,6 +1,6 @@
 # File: GaudiPython/Bindings.py
 # Author: Pere Mato (pere.mato@cern.ch)
-
+from __future__ import print_function
 """ GaudiPython.Bindings module.
     This module provides the basic bindings of the main Gaudi
     components to Python. It is itself based on the ROOT cppyy
@@ -25,7 +25,7 @@ try:
     import cppyy
 except ImportError:
     # FIXME: backward compatibility
-    print "# WARNING: using PyCintex as cppyy implementation"
+    print("# WARNING: using PyCintex as cppyy implementation")
     import PyCintex as cppyy
 
 if ROOT6WorkAroundEnabled('ROOT-5478'):
@@ -106,9 +106,9 @@ class InterfaceCast(object):
                 if obj.queryInterface(self.type.interfaceID(), ip).isSuccess():
                     return ip
                 else:
-                    print "ERROR: queryInterface failed for", obj, "interface:", self.type
+                    print("ERROR: queryInterface failed for", obj, "interface:", self.type)
             except Exception as e:
-                print "ERROR: exception", e, "caught when retrieving interface", self.type, "for object", obj
+                print("ERROR: exception", e, "caught when retrieving interface", self.type, "for object", obj)
                 import traceback
                 traceback.print_stack()
         return None
@@ -597,7 +597,7 @@ class iDataSvc(iService):
                 node = root.registry()
             else:
                 return
-        print node.identifier()
+        print(node.identifier())
         if node.object():
             for l in self.leaves(node):
                 self.dump(l)
@@ -1164,7 +1164,7 @@ class AppMgr(iService):
         Print the sequence of Algorithms.
         """
         def printAlgo(algName, appMgr, prefix=' '):
-            print prefix + algName
+            print(prefix + algName)
             alg = appMgr.algorithm(algName.split("/")[-1])
             prop = alg.properties()
             if prop.has_key("Members"):
@@ -1173,10 +1173,10 @@ class AppMgr(iService):
                     printAlgo(i.strip('"'), appMgr, prefix + "     ")
         mp = self.properties()
         prefix = 'ApplicationMgr    SUCCESS '
-        print prefix + "****************************** Algorithm Sequence ****************************"
+        print(prefix + "****************************** Algorithm Sequence ****************************")
         for i in mp["TopAlg"].value():
             printAlgo(i, self, prefix)
-        print prefix + "******************************************************************************"
+        print(prefix + "******************************************************************************")
 
     def config(self, **args):
         """
@@ -1394,8 +1394,8 @@ def getComponentProperties(name):
                 else:
                     obj = factory.instantiate(svcloc)
             except RuntimeError as text:
-                print 'Error instantiating', cname, ' from ', name
-                print text
+                print('Error instantiating', cname, ' from ', name)
+                print(text)
                 continue
             prop = iProperty('dummy', obj)
             properties[cname] = [ctype, prop.properties()]
diff --git a/GaudiPython/python/GaudiPython/GaudiAlgs.py b/GaudiPython/python/GaudiPython/GaudiAlgs.py
index 1937fbcfd9..7cd2a5dfb1 100644
--- a/GaudiPython/python/GaudiPython/GaudiAlgs.py
+++ b/GaudiPython/python/GaudiPython/GaudiAlgs.py
@@ -1,4 +1,5 @@
 #!/usr/bin/env python
+from __future__ import print_function
 # =============================================================================
 # @file
 #
@@ -895,7 +896,7 @@ class objectmethod(object):
         self.method = m
 
     def __call__(self, *args):
-        print args
+        print(args)
         return self.method(*args)
 
 
@@ -1355,7 +1356,7 @@ def _Tools_a_(self):
     >>> alg   = ...             ## get the algorithm
     >>> tools = alg.Tools()     ## get the tools
     >>> for tool in tools :
-    ...        print tool
+    ...        print(tool)
 
     """
     _cmp = getattr(self, '_ialg')
@@ -1374,7 +1375,7 @@ def _Tools_t_(self):
     >>> tool  = ...              ## get the tool
     >>> tools = tool.Tools()     ## get the tools
     >>> for t in tools :
-    ...        print t
+    ...        print(t)
 
     """
     _cmp = getattr(self, '_itool')
@@ -1417,14 +1418,14 @@ def _Counters_a_(self, name=None):
     >>> alg  = ...             ## get the algorithm
     >>> cnts = alg.Counters()  ## get the counters
     >>> for key in cnts :
-    ...        print key, cnts[key]
+    ...        print(key, cnts[key])
 
 
     Retrieve the counter, managed GaudiCommon<TYPE> base by name:
 
     >>> alg = ...                        ## get the algorithm
     >>> cnt = alg.Counters('MyCounter')  ## get the counter
-    >>> print cnt
+    >>> print(cnt)
 
     """
     _cmp = getattr(self, '_ialg')
@@ -1442,14 +1443,14 @@ def _Counters_t_(self, name=None):
     >>> tool = ...              ## get the tool
     >>> cnts = tool.Counters()  ## get the counters
     >>> for key in cnts :
-    ...        print key, cnts[key]
+    ...        print(key, cnts[key])
 
 
     Retrieve the counter, managed GaudiCommon<TYPE> base by name:
 
     >>> tool = ...                         ## get the tool
     >>> cnt  = tool.Counters('MyCounter')  ## get the counter
-    >>> print cnt
+    >>> print(cnt)
 
     """
     _cmp = getattr(self, '_itool')
@@ -1477,7 +1478,7 @@ def _Counter_a_(self, name):
 
     >>> alg  = ...                     ## get the algorithm
     >>> cnt  = alg.Counter('#accept')  ## get the counter
-    >>> print cnt
+    >>> print(cnt)
 
     """
     _cmp = getattr(self, '_ialg')
@@ -1494,7 +1495,7 @@ def _Counter_t_(self, name):
 
     >>> tool = ...                      ## get the tool
     >>> cnt  = tool.Counter('#accept')  ## get the counter
-    >>> print cnt
+    >>> print(cnt)
 
     """
     _cmp = getattr(self, '_itool')
@@ -1563,13 +1564,13 @@ def _Histos_a_(self, name=None):
     >>> alg = ...              ## get the algorithm
     >>> histos = alg.Histos()  ## get all histograms & profiles
     >>> for key in histos :
-    ...        print key, histos[key]
+    ...        print(key, histos[key])
 
     Retrive the histogram with the certain ID :
 
     >>> alg = ...                           ## get the algorithm
     >>> histo = alg.Histos('some histo ID') ## get the histo by ID
-    >>> print histo
+    >>> print(histo)
 
     """
     _cmp = getattr(self, '_ialg')
@@ -1587,13 +1588,13 @@ def _Histos_t_(self, name=None):
     >>> tool = ...              ## get the tool
     >>> histos = tool.Histos()  ## get all histograms & profiles
     >>> for key in histos :
-    ...        print key, histos[key]
+    ...        print(key, histos[key])
 
     Retrive the historgam with certain ID :
 
     >>> tool = ...                           ## get the tool
     >>> histo = tool.Histos('some histo ID') ## get the histo by ID
-    >>> print histo
+    >>> print(histo)
 
     """
     _cmp = getattr(self, '_itool')
@@ -1631,10 +1632,10 @@ import GaudiPython.HistoUtils
 
 
 def _help_():
-    print __doc__, __author__
-    print '\t\t\tDoc-string for class GaudiAlgo \n', GaudiAlgo.__doc__
-    print '\t\t\tDoc-string for class HistoAlgo \n', HistoAlgo.__doc__
-    print '\t\t\tDoc-string for class TupleAlgo \n', TupleAlgo.__doc__
+    print(__doc__, __author__)
+    print('\t\t\tDoc-string for class GaudiAlgo \n', GaudiAlgo.__doc__)
+    print('\t\t\tDoc-string for class HistoAlgo \n', HistoAlgo.__doc__)
+    print('\t\t\tDoc-string for class TupleAlgo \n', TupleAlgo.__doc__)
 
 
 # =============================================================================
diff --git a/GaudiPython/python/GaudiPython/HistoUtils.py b/GaudiPython/python/GaudiPython/HistoUtils.py
index 22d77cc8e8..ffb90e65f8 100644
--- a/GaudiPython/python/GaudiPython/HistoUtils.py
+++ b/GaudiPython/python/GaudiPython/HistoUtils.py
@@ -1,4 +1,5 @@
 #!/usr/bin/env python
+from __future__ import print_function
 # =============================================================================
 # This module contains set of simple and useful utilities for booking and
 #   manipulations with Gaudi-AIDA histograms, inspired by Thomas' request
@@ -521,7 +522,7 @@ def _moment_(self, order, value=0):
     for 1D histogram
 
     >>> h1 = ...
-    >>> print h1.moment ( 5 )
+    >>> print(h1.moment ( 5 ))
 
     """
     return HistoStats.moment(self, order, value)
@@ -536,7 +537,7 @@ def _momentErr_(self, order):
     for 1D histogram
 
     >>> h1 = ...
-    >>> print h1.momentErr ( 5 )
+    >>> print(h1.momentErr ( 5 ))
 
     """
     return HistoStats.momentErr(self, order)
@@ -550,7 +551,7 @@ def _centralMoment_(self, order):
     for 1D histogram
 
     >>> h1 = ...
-    >>> print h1.centralMoment ( 5 )
+    >>> print(h1.centralMoment ( 5 ))
 
     """
     return HistoStats.centralMoment(self, order)
@@ -565,7 +566,7 @@ def _centralMomentErr_(self, order):
     for 1D histogram
 
     >>> h1 = ...
-    >>> print h1.centralMomentErr ( 5 )
+    >>> print(h1.centralMomentErr ( 5 ))
 
     """
     return HistoStats.centralMomentErr(self, order)
@@ -579,7 +580,7 @@ def _skewness_(self):
     Evaluate 'bin-by-bin' skewness for 1D AIDA histogram
 
     >>> h1 = ...
-    >>> print h1.skewness()
+    >>> print(h1.skewness())
 
     """
     return HistoStats.skewness(self)
@@ -593,7 +594,7 @@ def _skewnessErr_(self):
     Evaluate error for 'bin-by-bin' skewness
 
     >>> h1 = ...
-    >>> print h1.skewnessErr()
+    >>> print(h1.skewnessErr())
 
     """
     return HistoStats.skewnessErr(self)
@@ -607,7 +608,7 @@ def _kurtosis_(self):
     Evaluate 'bin-by-bin' kurtosis
 
     >>> h1 = ...
-    >>> print h1.kurtosis ()
+    >>> print(h1.kurtosis ())
 
     """
     return HistoStats.kurtosis(self)
@@ -621,7 +622,7 @@ def _kurtosisErr_(self):
     Evaluate error for 'bin-by-bin' kurtotis for 1D AIDA histogram
 
     >>> h1 = ...
-    >>> print h1.kurtotisErr()
+    >>> print(h1.kurtotisErr())
 
     """
     return HistoStats.kurtosisErr(self)
@@ -763,13 +764,13 @@ def _nEntries_(self, i1, i2=-10000000):
     attention: underflow bin is included!
 
     >>> h1
-    >>> print h1.nEntries ( 10 )
+    >>> print(h1.nEntries ( 10 ))
 
     Get number of entries in histogram form the certain
     minimal bin up to the certain maximal bin (not-included)
 
     >>> h1
-    >>> print h1.nEntries ( 10 , 15 )
+    >>> print(h1.nEntries ( 10 , 15 ))
 
     """
     if i2 < i1 or i2 < 0:
@@ -785,13 +786,13 @@ def _nEntriesFrac_(self, i1, i2=-10000000):
     attention: underflow bin is included!
 
     >>> h1
-    >>> print h1.nEntriesFrac ( 10 )
+    >>> print(h1.nEntriesFrac ( 10 ))
 
     Get the fraction of entries in histogram form the certain
     minimal bin up to the certain maximal bin (not-included)
 
     >>> h1
-    >>> print h1.nEntriesFrac ( 10 , 15 )
+    >>> print(h1.nEntriesFrac ( 10 , 15 ))
 
     """
     if i2 < i1 or i2 < 0:
@@ -807,13 +808,13 @@ def _nEntriesFracErr_(self, i1, i2=-10000000):
     attention: underflow bin is included!
 
     >>> h1
-    >>> print h1.nEntriesFracErr( 10 )
+    >>> print(h1.nEntriesFracErr( 10 ))
 
     Get error  fraction of entries in histogram form the certain
     minimal bin up to the certain maximal bin (not-included)
 
     >>> h1
-    >>> print h1.nEntriesFracErr ( 10 , 15 )
+    >>> print(h1.nEntriesFracErr ( 10 , 15 ))
 
     """
     if i2 < i1 or i2 < 0:
@@ -884,7 +885,7 @@ def _path_(self):
     Get the path in THS for the given AIDA object:
 
     >>> aida =
-    >>> print aida.path()
+    >>> print(aida.path())
 
     """
     return cpp.Gaudi.Utils.Histos.path(self)
@@ -906,11 +907,11 @@ def __dumpHisto__(histo, *args):
     Dump the histogram/profile in text format (a'la HBOOK)
 
     >>> histo
-    >>> print dumpHisto ( histo )
+    >>> print(dumpHisto ( histo ))
 
-    >>> print histo.dump()
-    >>> print histo.dump( 20 , 20 )
-    >>> print histo.dump( 20 , 20 , True )
+    >>> print(histo.dump())
+    >>> print(histo.dump( 20 , 20 ))
+    >>> print(histo.dump( 20 , 20 , True ))
 
     Uses:
 
@@ -999,10 +1000,10 @@ class HistoFile:
 # =============================================================================
 if '__main__' == __name__:
     import sys
-    print __doc__
+    print(__doc__)
     for o in __all__:
-        print o
-        print sys.modules[__name__].__dict__[o].__doc__
+        print(o)
+        print(sys.modules[__name__].__dict__[o].__doc__)
 
 
 # =============================================================================
diff --git a/GaudiPython/python/GaudiPython/Pythonizations.py b/GaudiPython/python/GaudiPython/Pythonizations.py
index 648e7f1bc4..6f61f41631 100644
--- a/GaudiPython/python/GaudiPython/Pythonizations.py
+++ b/GaudiPython/python/GaudiPython/Pythonizations.py
@@ -1,5 +1,6 @@
 # File: GaudiPython/Pythonizations.py
 # Author: Pere Mato (pere.mato@cern.ch)
+from __future__ import print_function
 
 """ This Pythonizations module provides a number of useful pythonizations
     of adaptation of some classes.
@@ -11,7 +12,7 @@ try:
     from cppyy import gbl
 except ImportError:
     # FIXME: backward compatibility
-    print "# WARNING: using PyCintex as cppyy implementation"
+    print("# WARNING: using PyCintex as cppyy implementation")
     from PyCintex import gbl
 
 if not hasattr(gbl, 'ostream'):
@@ -155,7 +156,7 @@ if gbl.gROOT.GetVersionInt() <= 51800:
 #  @code
 #
 #    >>> m = ...  ## the map
-#    >>> for key in m : print key , m[key]
+#    >>> for key in m : print(key , m[key])
 #
 #  @endcode
 #  @see Gaudi::Utils::MapBase
@@ -174,7 +175,7 @@ def __mapbase_iter__(self):
     The iterator for MapBase-based containers
 
     >>> m = ...  ## the map
-    >>> for key in m : print key , m[key]
+    >>> for key in m : print(key , m[key])
 
     """
     _size = len(self)
@@ -189,7 +190,7 @@ def __mapbase_iter__(self):
 #  @code
 #
 #    >>> m = ...  ## the map
-#    >>> for key,value in m.iteritems() : print key , value
+#    >>> for key,value in m.iteritems() : print(key , value)
 #
 #  @endcode
 #  @see Gaudi::Utils::MapBase
@@ -211,7 +212,7 @@ def __mapbase_iteritems__(self):
     The iterator for MapBase-based containers
 
     >>> m = ...  ## the map
-    >>> for key,value in m.iteritems() : print key, value
+    >>> for key,value in m.iteritems() : print(key, value)
 
     """
     _size = len(self)
@@ -332,7 +333,7 @@ def __mapbase_values__(self):
 #  @code
 #
 #    >>> m      = ...        ## the map
-#    >>> if 'a' in m : print 'key is in the map!'
+#    >>> if 'a' in m : print('key is in the map!')
 #
 #  @endcode
 #  @see Gaudi::Utils::MapBase
@@ -396,7 +397,7 @@ def __mapbase_get__(self, key, value=None):
 #  @code
 #
 #    >>> m      = ...        ## the map
-#    >>> print m
+#    >>> print(m)
 #
 #  @endcode
 #  @see Gaudi::Utils::MapBase
@@ -412,7 +413,7 @@ def __mapbase_str__(self):
     Representation of MapBase-based maps:
 
     >>> m     = ...        ## the map
-    >>> print map
+    >>> print(map)
 
     """
     _result = ' { '
diff --git a/GaudiPython/python/GaudiPython/TupleUtils.py b/GaudiPython/python/GaudiPython/TupleUtils.py
index ad8a566231..3272075eb2 100644
--- a/GaudiPython/python/GaudiPython/TupleUtils.py
+++ b/GaudiPython/python/GaudiPython/TupleUtils.py
@@ -1,4 +1,5 @@
 #!/usr/bin/env python
+from __future__ import print_function
 # =============================================================================
 # This module contains set of simple and useful utilities to booking and
 #  manipulation with N-Tuples (in the spirit of GaudiTuples<TYPE>)
@@ -198,8 +199,8 @@ def _TupleUtils_AtExit_():
     AtExit function for GaudiPython.TupleUtils module
     """
     if activeTuples():
-        print 'WARNING: the list of local TupleTools is not empty!'
-        print 'WARNING: please use GaudiPython.TupleUtils.releaseTuples() at the end'
+        print('WARNING: the list of local TupleTools is not empty!')
+        print('WARNING: please use GaudiPython.TupleUtils.releaseTuples() at the end')
 
 
 import atexit
@@ -208,10 +209,10 @@ atexit.register(_TupleUtils_AtExit_)
 # =============================================================================
 if "__main__" == __name__:
     import sys
-    print __doc__, __all__
+    print(__doc__, __all__)
     for o in __all__:
-        print "\n\n\t", o, "\n"
-        print sys.modules[__name__].__dict__[o].__doc__
+        print("\n\n\t", o, "\n")
+        print(sys.modules[__name__].__dict__[o].__doc__)
 
 # =============================================================================
 # The end
diff --git a/GaudiPython/python/GaudiPython/__init__.py b/GaudiPython/python/GaudiPython/__init__.py
index 457d8e0850..14c172cd73 100644
--- a/GaudiPython/python/GaudiPython/__init__.py
+++ b/GaudiPython/python/GaudiPython/__init__.py
@@ -1,5 +1,6 @@
 # File: GaudiPython/__init__.py
 # Author: Pere Mato (pere.mato@cern.ch)
+from __future__ import print_function
 
 """
    GaudiPython main module.
@@ -12,7 +13,7 @@
 # ensure that we (and the subprocesses) use the C standard localization
 import os
 if os.environ.get('LC_ALL') != 'C':
-    print '# setting LC_ALL to "C"'
+    print('# setting LC_ALL to "C"')
     os.environ['LC_ALL'] = 'C'
 
 from Bindings import *
diff --git a/GaudiRelease/prepare_gaudi_release.py b/GaudiRelease/prepare_gaudi_release.py
index 5ea0147fc2..e15aa0c07a 100755
--- a/GaudiRelease/prepare_gaudi_release.py
+++ b/GaudiRelease/prepare_gaudi_release.py
@@ -4,7 +4,7 @@ Script to prepare the release of Gaudi.
 
 @author Marco Clemencic
 '''
-
+from __future__ import print_function
 import os
 import sys
 import logging
@@ -130,7 +130,7 @@ def main():
         m = re.match(r'^\s*set\(\s*heptools_version\s+(\S*)\s*\)', l)
         if m:
             HEPToolsVers = m.group(1)
-            print "Using HEPTools", HEPToolsVers
+            print("Using HEPTools", HEPToolsVers)
             break
     else:
         logging.error('Cannot find HEPTools version')
diff --git a/GaudiRelease/svn_tag_release.py b/GaudiRelease/svn_tag_release.py
index e5981db718..44ec04023a 100755
--- a/GaudiRelease/svn_tag_release.py
+++ b/GaudiRelease/svn_tag_release.py
@@ -5,6 +5,7 @@ release of Gaudi.
 See https://twiki.cern.ch/twiki/bin/view/Gaudi/GaudiSVNRepository for a
 description of the repository structure.
 """
+from __future__ import print_function
 __author__ = "Marco Clemencic <Marco.Clemencic@cern.ch>"
 
 import os
@@ -17,7 +18,7 @@ from ConfigParser import ConfigParser
 
 
 def svn(*args, **kwargs):
-    print "> svn", " ".join(args)
+    print("> svn", " ".join(args))
     return Popen(["svn"] + list(args), **kwargs)
 
 
diff --git a/RootCnv/scripts/IOTest.py b/RootCnv/scripts/IOTest.py
index 9e6231ec02..6e9ab417d4 100755
--- a/RootCnv/scripts/IOTest.py
+++ b/RootCnv/scripts/IOTest.py
@@ -10,6 +10,7 @@
    M.Frank  CERN/LHCb
 
 """
+from __future__ import print_function
 import os
 import sys
 import time
@@ -85,16 +86,16 @@ def update():
 def printDelta(s0, s1):
     for s in s1:
         if s == 'time':
-            print '%15s : %10.2F sec' % (s, (s1[s] - s0[s]))
+            print('%15s : %10.2F sec' % (s, (s1[s] - s0[s])))
         else:
-            print '%15s : %10.2F MB' % (s, (s1[s] - s0[s]) / 1.E6)
+            print('%15s : %10.2F MB' % (s, (s1[s] - s0[s]) / 1.E6))
 
 
 import GaudiPython
 appMgr = GaudiPython.AppMgr()
 sel = appMgr.evtsel()
 evt = appMgr.evtsvc()
-print sel.Input
+print(sel.Input)
 
 start = update()
 # test 1
@@ -104,13 +105,13 @@ while 1 > 0:
     if N == 10:
         start = update()
     # if not evt['/Event/DAQ/RawEvent']:
-    #    print 'Failed to access /Event/DAQ/RawEvent'
+    #    print('Failed to access /Event/DAQ/RawEvent')
     if not evt['/Event/Rec/Header']:
-        print 'Failed to access /Event/Rec/Header'
+        print('Failed to access /Event/Rec/Header')
         break
     N += 1
     if N > 100000:
         break
 end = update()
-print 'Read %d events' % N
+print('Read %d events' % N)
 printDelta(start, end)
diff --git a/cmake/tests/cmake_coverage.py b/cmake/tests/cmake_coverage.py
index 62e4ced31c..62e90a68d1 100755
--- a/cmake/tests/cmake_coverage.py
+++ b/cmake/tests/cmake_coverage.py
@@ -18,7 +18,7 @@ coverage = defaultdict(set)
 
 
 def update_coverage():
-    # print 'Updating CMake coverage reports'
+    # print('Updating CMake coverage reports')
     if os.path.exists(COVERAGE_FILE):
         data = cPickle.load(open(COVERAGE_FILE))
         if 'lines' not in data:
-- 
GitLab


From bdba77c7148d687089a0b5332a16e079cd5040da Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Wed, 29 Nov 2017 09:51:42 +0100
Subject: [PATCH 13/56] Only worry about loop variable clean-up in Python 2.

---
 Gaudi/python/Gaudi/CommonGaudiConfigurables.py | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/Gaudi/python/Gaudi/CommonGaudiConfigurables.py b/Gaudi/python/Gaudi/CommonGaudiConfigurables.py
index 7ef419319f..2825caa98e 100644
--- a/Gaudi/python/Gaudi/CommonGaudiConfigurables.py
+++ b/Gaudi/python/Gaudi/CommonGaudiConfigurables.py
@@ -62,4 +62,10 @@ for new in aliases:
 _gbl.update(aliases)
 __all__.extend(aliases)
 # remove temporaries
-del _gbl, new
+del _gbl
+# The `new` var is only scoped in its `for` loop in Python 3, so we only need
+# to 'worry' about cleanup in Python 2
+try:
+    del new
+except NameError:
+    pass
-- 
GitLab


From 8ea553d860460b3c87d3f64afbca3bc4086bebbd Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Wed, 29 Nov 2017 09:52:54 +0100
Subject: [PATCH 14/56] Use Python 3 compatible execfile.

---
 GaudiCoreSvc/src/JobOptionsSvc/PythonConfig.cpp     | 5 ++++-
 GaudiKernel/python/GaudiKernel/ProcessJobOptions.py | 4 +++-
 cmake/GaudiProjectConfig.cmake                      | 7 +++++--
 3 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/GaudiCoreSvc/src/JobOptionsSvc/PythonConfig.cpp b/GaudiCoreSvc/src/JobOptionsSvc/PythonConfig.cpp
index a396ca74c2..d46c609565 100644
--- a/GaudiCoreSvc/src/JobOptionsSvc/PythonConfig.cpp
+++ b/GaudiCoreSvc/src/JobOptionsSvc/PythonConfig.cpp
@@ -25,7 +25,10 @@ StatusCode PythonConfig::evaluateConfig( const std::string& filename, const std:
     // some python helper
     std::string command( preAction );
     command += "\nfor name in '";
-    command += filename + "'.split(','): execfile(name)\n";
+    command += filename + "'.split(','):\n";
+    command += "    with open(name) as f:\n";
+    command += "        code = compile(f.read(), name, 'exec')\n";
+    command += "        exec(code)\n";
     command += "from GaudiKernel.Configurable import expandvars\nfrom GaudiKernel.Proxy.Configurable import "
                "applyConfigurableUsers\napplyConfigurableUsers()\n";
     command += postAction;
diff --git a/GaudiKernel/python/GaudiKernel/ProcessJobOptions.py b/GaudiKernel/python/GaudiKernel/ProcessJobOptions.py
index d6a2745b0c..ae19041c6d 100644
--- a/GaudiKernel/python/GaudiKernel/ProcessJobOptions.py
+++ b/GaudiKernel/python/GaudiKernel/ProcessJobOptions.py
@@ -451,7 +451,9 @@ _parser = JobOptsParser()
 
 
 def _import_python(file):
-    execfile(file, {})
+    with open(file) as f:
+        code = compile(f.read(), file, 'exec')
+        exec(code, {})
 
 
 def _import_pickle(file):
diff --git a/cmake/GaudiProjectConfig.cmake b/cmake/GaudiProjectConfig.cmake
index 313eab30fa..df542ed8c1 100644
--- a/cmake/GaudiProjectConfig.cmake
+++ b/cmake/GaudiProjectConfig.cmake
@@ -735,8 +735,11 @@ __path__ = [d for d in [os.path.join(d, '${pypack}') for d in sys.path if d]
             if (d.startswith('${CMAKE_BINARY_DIR}') or
                 d.startswith('${CMAKE_SOURCE_DIR}')) and
                (os.path.exists(d) or 'python.zip' in d)]
-if os.path.exists('${CMAKE_SOURCE_DIR}/${package}/python/${pypack}/__init__.py'):
-    execfile('${CMAKE_SOURCE_DIR}/${package}/python/${pypack}/__init__.py')
+fname = '${CMAKE_SOURCE_DIR}/${package}/python/${pypack}/__init__.py'
+if os.path.exists(fname):
+    with open(fname) as f:
+        code = compile(f.read(), fname, 'exec')
+        exec(code)
 ")
       endforeach()
     endif()
-- 
GitLab


From 36251f3d1aab4dbaf97f1c339180d660b498b85b Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Wed, 29 Nov 2017 10:39:05 +0100
Subject: [PATCH 15/56] Use more idiomatic check for dictionary key membership.

---
 GaudiKernel/python/GaudiKernel/ConfigurableDb.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/GaudiKernel/python/GaudiKernel/ConfigurableDb.py b/GaudiKernel/python/GaudiKernel/ConfigurableDb.py
index fc1be7cfb1..87d977f75b 100644
--- a/GaudiKernel/python/GaudiKernel/ConfigurableDb.py
+++ b/GaudiKernel/python/GaudiKernel/ConfigurableDb.py
@@ -50,7 +50,7 @@ class _CfgDb(dict):
         cfg = {'package': package,
                'module': module,
                'lib': lib}
-        if self.has_key(configurable):
+        if configurable in self:
             # check if it comes from the same library...
             if cfg['lib'] != self[configurable]['lib']:
                 log.debug("dup!! [%s] p=%s m=%s lib=%s",
-- 
GitLab


From f8e652279ff09f00a7eb31e3e4a7327193b458d9 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Wed, 29 Nov 2017 10:39:18 +0100
Subject: [PATCH 16/56] Use Python 3 compatible string instance checking.

---
 GaudiKernel/scripts/genconfuser.py | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/GaudiKernel/scripts/genconfuser.py b/GaudiKernel/scripts/genconfuser.py
index 7098a350d3..8f2f4bf593 100755
--- a/GaudiKernel/scripts/genconfuser.py
+++ b/GaudiKernel/scripts/genconfuser.py
@@ -28,6 +28,11 @@ def _inheritsfrom(derived, basenames):
 
     'basenames' can be a string or an iterable (of strings).
     """
+    try:
+        basestring
+    except NameError:
+        # Fall back to assuming `str` is the base class in Python 3
+        basestring = str
     if isinstance(basenames, basestring):
         basenames = (basenames,)
     for b in derived.__bases__:
-- 
GitLab


From b096fbd906d8cd3bf79fff5ee3d035ac4ce2fa80 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Wed, 29 Nov 2017 13:42:45 +0100
Subject: [PATCH 17/56] Use Python 3 compatible absolute imports.

---
 Gaudi/python/Gaudi/Configuration.py        | 3 ++-
 GaudiPython/python/GaudiPython/Bindings.py | 8 ++++----
 GaudiPython/python/GaudiPython/__init__.py | 6 +++---
 3 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/Gaudi/python/Gaudi/Configuration.py b/Gaudi/python/Gaudi/Configuration.py
index df8d51c456..08331dcb6d 100644
--- a/Gaudi/python/Gaudi/Configuration.py
+++ b/Gaudi/python/Gaudi/Configuration.py
@@ -1,11 +1,12 @@
 # File: Gaudi/python/Gaudi/Configuration.py
 # Author: Pere Mato (pere.mato@cern.ch)
+from __future__ import absolute_import
 
 from GaudiKernel.Constants import *
 from GaudiKernel.Configurable import *
 from GaudiKernel.ConfigurableDb import loadConfigurableDb, cfgDb
 from GaudiKernel.ConfigurableDb import getConfigurable as confDbGetConfigurable
-from CommonGaudiConfigurables import *
+from Gaudi.CommonGaudiConfigurables import *
 from GaudiKernel.ProcessJobOptions import importOptions, importUnits
 from GaudiKernel.ProcessJobOptions import InstallRootLoggingHandler as _InstallRootLoggingHandler
 
diff --git a/GaudiPython/python/GaudiPython/Bindings.py b/GaudiPython/python/GaudiPython/Bindings.py
index 6fc08d04c9..78fc93f147 100644
--- a/GaudiPython/python/GaudiPython/Bindings.py
+++ b/GaudiPython/python/GaudiPython/Bindings.py
@@ -1,6 +1,6 @@
 # File: GaudiPython/Bindings.py
 # Author: Pere Mato (pere.mato@cern.ch)
-from __future__ import print_function
+from __future__ import absolute_import, print_function
 """ GaudiPython.Bindings module.
     This module provides the basic bindings of the main Gaudi
     components to Python. It is itself based on the ROOT cppyy
@@ -34,7 +34,7 @@ if ROOT6WorkAroundEnabled('ROOT-5478'):
     # Trigger the loading of GaudiPythonDict
     cppyy.gbl.Chrono
 
-import Pythonizations
+from . import Pythonizations
 # Import Configurable from AthenaCommon or GaudiKernel if the first is not
 # available.
 from GaudiKernel.Proxy.Configurable import Configurable, getNeededConfigurables
@@ -757,7 +757,7 @@ class iNTupleSvc(iDataSvc):
             Usage:
               defineOutput({'LUN1':'MyFile1.root', 'LUN2':'Myfile2.root'}, svc='Gaudi::RootCnvSvc')
         """
-        import Persistency as prs
+        from . import Persistency as prs
         helper = prs.get(typ)
         helper.configure(AppMgr())
         self.Output = [helper.formatOutput(
@@ -867,7 +867,7 @@ class iEventSelector(iService):
         self.__dict__['g'] = AppMgr()
 
     def open(self, stream, typ='Gaudi::RootCnvSvc', **kwargs):
-        import Persistency as prs
+        from . import Persistency as prs
         helper = prs.get(typ)
         helper.configure(self.g)
         self.Input = helper.formatInput(stream, **kwargs)
diff --git a/GaudiPython/python/GaudiPython/__init__.py b/GaudiPython/python/GaudiPython/__init__.py
index 14c172cd73..133584c4e5 100644
--- a/GaudiPython/python/GaudiPython/__init__.py
+++ b/GaudiPython/python/GaudiPython/__init__.py
@@ -1,6 +1,6 @@
 # File: GaudiPython/__init__.py
 # Author: Pere Mato (pere.mato@cern.ch)
-from __future__ import print_function
+from __future__ import absolute_import, print_function
 
 """
    GaudiPython main module.
@@ -16,5 +16,5 @@ if os.environ.get('LC_ALL') != 'C':
     print('# setting LC_ALL to "C"')
     os.environ['LC_ALL'] = 'C'
 
-from Bindings import *
-from Pythonizations import *
+from .Bindings import *
+from .Pythonizations import *
-- 
GitLab


From f12247657146b2280c17cc846fa5c01c3007be29 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Wed, 29 Nov 2017 13:43:25 +0100
Subject: [PATCH 18/56] More hacks to get Gaudi building under Python 3.

---
 GaudiExamples/CMakeLists.txt  | 2 +-
 GaudiProfiling/CMakeLists.txt | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/GaudiExamples/CMakeLists.txt b/GaudiExamples/CMakeLists.txt
index 13b5ba5b2a..d571d895c8 100644
--- a/GaudiExamples/CMakeLists.txt
+++ b/GaudiExamples/CMakeLists.txt
@@ -145,7 +145,7 @@ endif()
 
 if(Boost_PYTHON_FOUND)
   gaudi_add_python_module(PyExample src/PythonModule/*.cpp
-                          LINK_LIBRARIES ${Boost_PYTHON_LIBRARY}
+                          LINK_LIBRARIES ${Boost_PYTHON3_LIBRARY}
                           INCLUDE_DIRS Boost PythonLibs)
 endif()
 
diff --git a/GaudiProfiling/CMakeLists.txt b/GaudiProfiling/CMakeLists.txt
index 3def1797cb..150b85566b 100644
--- a/GaudiProfiling/CMakeLists.txt
+++ b/GaudiProfiling/CMakeLists.txt
@@ -4,7 +4,7 @@ gaudi_depends_on_subdirs(GaudiKernel GaudiAlg)
 
 if (CMAKE_SYSTEM_NAME MATCHES Linux)
 
-find_package(Boost COMPONENTS python REQUIRED)
+find_package(Boost COMPONENTS python3 REQUIRED)
 find_package(PythonLibs REQUIRED)
 find_package(unwind)
 find_package(gperftools)
@@ -29,7 +29,7 @@ if(UNWIND_FOUND AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
                    INCLUDE_DIRS unwind ZLIB)
 
   gaudi_add_python_module(PyCPUFamily src/python/CPUFamily.cpp
-                          LINK_LIBRARIES ${Boost_PYTHON_LIBRARY}
+                          LINK_LIBRARIES ${Boost_PYTHON3_LIBRARY}
                           INCLUDE_DIRS PythonLibs)
 
   gaudi_add_executable(GaudiGenProfilingHtml src/app/pfm_gen_analysis.cpp
-- 
GitLab


From 16c5f6c7bb7008c057fa6b1bf83356e62a23f3a9 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Wed, 29 Nov 2017 13:43:55 +0100
Subject: [PATCH 19/56] Be compatible with the CPython's Python 3 API.

---
 GaudiPython/GaudiPython/Helpers.h             | 40 +++++++++++++++++++
 GaudiPython/src/Lib/Algorithm.cpp             | 10 +++++
 .../src/Services/PythonScriptingSvc.cpp       | 13 +++++-
 3 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/GaudiPython/GaudiPython/Helpers.h b/GaudiPython/GaudiPython/Helpers.h
index 7541737878..ec3c3f741f 100644
--- a/GaudiPython/GaudiPython/Helpers.h
+++ b/GaudiPython/GaudiPython/Helpers.h
@@ -3,6 +3,33 @@
 
 #include "Python.h"
 
+// Python 3 compatibility
+#if PY_MAJOR_VERSION >= 3
+
+#define PyInt_FromLong PyLong_FromLong
+
+#define PyBuffer_Type PyMemoryView_Type
+
+// Taken from ROOT's TPyBufferFactory
+static PyObject* PyBuffer_FromReadWriteMemory(void* ptr, int size)
+{
+#if PY_VERSION_HEX > 0x03000000
+  // Python 3 will set an exception if nullptr, just rely on size == 0
+  if (!ptr) {
+    static long dummy[1];
+    ptr = dummy;
+    size = 0;
+  }
+#endif
+  Py_buffer bufinfo = {ptr, NULL, size, 1, 0, 1, NULL, NULL, NULL, NULL,
+#if PY_VERSION_HEX < 0x03030000
+  {0, 0},
+#endif
+  NULL};
+  return PyMemoryView_FromBuffer(&bufinfo);
+}
+#endif
+
 #include "GaudiKernel/DataObject.h"
 #include "GaudiKernel/IAlgManager.h"
 #include "GaudiKernel/IAlgTool.h"
@@ -153,7 +180,14 @@ namespace GaudiPython
       const
 #endif
           char*  buf  = 0;
+          char*  buf  = 0;
+#if PY_MAJOR_VERSION >= 3
+      Py_buffer bufinfo;
+      ( *( self->ob_type->tp_as_buffer->bf_getbuffer ) )( self, &bufinfo, PyBUF_SIMPLE );
+      Py_ssize_t size = bufinfo.len;
+#else
       Py_ssize_t size = ( *( self->ob_type->tp_as_buffer->bf_getcharbuffer ) )( self, 0, &buf );
+#endif
       return size / sizeof( T );
     }
 
@@ -176,7 +210,13 @@ namespace GaudiPython
       const
 #endif
           char*  buf  = nullptr;
+#if PY_MAJOR_VERSION >= 3
+      Py_buffer bufinfo;
+      ( *( self->ob_type->tp_as_buffer->bf_getbuffer ) )( self, &bufinfo, PyBUF_SIMPLE );
+      Py_ssize_t size = bufinfo.len;
+#else
       Py_ssize_t size = ( *( self->ob_type->tp_as_buffer->bf_getcharbuffer ) )( self, 0, &buf );
+#endif
       if ( idx < 0 || idx >= size / int( sizeof( T ) ) ) {
         PyErr_SetString( PyExc_IndexError, "buffer index out of range" );
         return nullptr;
diff --git a/GaudiPython/src/Lib/Algorithm.cpp b/GaudiPython/src/Lib/Algorithm.cpp
index 2c5e6b500c..20bc44aee1 100644
--- a/GaudiPython/src/Lib/Algorithm.cpp
+++ b/GaudiPython/src/Lib/Algorithm.cpp
@@ -2,6 +2,16 @@
 // Include files
 // ============================================================================
 #include "Python.h"
+
+// Python 3 compatibility
+#if PY_MAJOR_VERSION >= 3
+
+#define PyInt_Check PyLong_Check
+
+#define PyInt_AS_LONG PyLong_AS_LONG
+
+#endif
+
 // ============================================================================
 // GaudiKernel
 // ============================================================================
diff --git a/GaudiPython/src/Services/PythonScriptingSvc.cpp b/GaudiPython/src/Services/PythonScriptingSvc.cpp
index 261dcba51c..ced7bff081 100644
--- a/GaudiPython/src/Services/PythonScriptingSvc.cpp
+++ b/GaudiPython/src/Services/PythonScriptingSvc.cpp
@@ -1,5 +1,16 @@
 #include "Python.h"
 
+// Python 3 compatibility
+#if PY_MAJOR_VERSION >= 3
+
+#define PySys_SetArgv_Char_t wchar_t
+
+#else
+
+#define PySys_SetArgv_Char_t char
+
+#endif
+
 // Include Files
 #include "GaudiKernel/ISvcLocator.h"
 #include "GaudiKernel/MsgStream.h"
@@ -55,7 +66,7 @@ StatusCode PythonScriptingSvc::initialize()
     }
   }
 
-  char* progName[] = {const_cast<char*>( "GaudiPython" )};
+  PySys_SetArgv_Char_t* progName[] = {const_cast<PySys_SetArgv_Char_t*>( L"GaudiPython" )};
 
   // Initialize the Python interpreter.  Required.
   Py_Initialize();
-- 
GitLab


From 1717e8f322c1e02d8ec3721a20c6af887e64611d Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Wed, 29 Nov 2017 14:01:36 +0100
Subject: [PATCH 20/56] Avoid unused variable warnings when compiling for
 Python 3.

---
 GaudiPython/GaudiPython/Helpers.h | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/GaudiPython/GaudiPython/Helpers.h b/GaudiPython/GaudiPython/Helpers.h
index ec3c3f741f..d4901fe6cd 100644
--- a/GaudiPython/GaudiPython/Helpers.h
+++ b/GaudiPython/GaudiPython/Helpers.h
@@ -176,16 +176,15 @@ namespace GaudiPython
     template <class T>
     static Py_ssize_t Array_length( PyObject* self )
     {
-#if PY_VERSION_HEX < 0x02050000
-      const
-#endif
-          char*  buf  = 0;
-          char*  buf  = 0;
 #if PY_MAJOR_VERSION >= 3
       Py_buffer bufinfo;
       ( *( self->ob_type->tp_as_buffer->bf_getbuffer ) )( self, &bufinfo, PyBUF_SIMPLE );
       Py_ssize_t size = bufinfo.len;
 #else
+#if PY_VERSION_HEX < 0x02050000
+      const
+#endif
+          char* buf   = 0;
       Py_ssize_t size = ( *( self->ob_type->tp_as_buffer->bf_getcharbuffer ) )( self, 0, &buf );
 #endif
       return size / sizeof( T );
-- 
GitLab


From 0dd8c1610ef0ea201abd2d5d9dbebb93c2bf3007 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Thu, 30 Nov 2017 08:40:22 +0100
Subject: [PATCH 21/56] Use Python 3 compatible printing.

---
 GaudiPolicy/scripts/CTestXML2HTML | 41 +++++++++++++++----------------
 1 file changed, 20 insertions(+), 21 deletions(-)

diff --git a/GaudiPolicy/scripts/CTestXML2HTML b/GaudiPolicy/scripts/CTestXML2HTML
index 69200a240c..034bd6fb4e 100755
--- a/GaudiPolicy/scripts/CTestXML2HTML
+++ b/GaudiPolicy/scripts/CTestXML2HTML
@@ -1,5 +1,6 @@
 #!/usr/bin/env python
 # -*- coding:utf-8 -*-
+from __future__ import print_function
 import os
 import sys
 import json
@@ -34,8 +35,8 @@ def cleanXml(xmlFileName):
     def hexConvert(char):
         return hex(ord(char))
 
-    print " Trying to repair the xml file"
-    print " Replacing invalid char"
+    print(" Trying to repair the xml file")
+    print(" Replacing invalid char")
     xmlFile = open(xmlFileName, 'r')
     data = xmlFile.read()
     xmlFile.close()
@@ -50,7 +51,7 @@ def cleanXml(xmlFileName):
         xmlFile.close()
         del tree
     except:
-        print " Removing invalid char"
+        print(" Removing invalid char")
         xmlFile = open(xmlFileName, 'w')
         xmlFile.write(_illegal_xml_chars_Re.sub("", data))
         xmlFile.close()
@@ -388,7 +389,7 @@ class TestOrganizer:
         else:
             sites = newdataset.getchildren()
         for site in sites:
-            print "    -> Process the site: " + site.get("BuildStamp")
+            print("    -> Process the site: " + site.get("BuildStamp"))
             Testing = site.find("Testing")
             # process each test case
             for Test in Testing.findall("Test"):
@@ -568,7 +569,7 @@ def updateAnnotations(site, Testing, outputTemp, annotationsList):
 def main():
 
     #progStartTime = datetime.now()
-    # print "program launch at "+progStartTime.strftime("%b %d %H:%M %Z")
+    # print("program launch at "+progStartTime.strftime("%b %d %H:%M %Z"))
 
     # parse the command line option
     usage = "usage: %prog [options] Convert CTest like XML into a webpage"
@@ -593,7 +594,7 @@ def main():
     inputs = []
     if options.inputFile is not None:
         if not os.path.isfile(options.inputFile):
-            print " The input file is not a valid file"
+            print(" The input file is not a valid file")
             exit(1)
         else:
             inputs.append(options.inputFile)
@@ -607,11 +608,11 @@ def main():
 
     # close the program if there is no file found
     if inputs == []:
-        print " No file found \n"
+        print(" No file found \n")
         exit()
 
-    print "Converting *Test.xml files from %s to HTML format in %s" % (
-        options.inputDirectory, options.outputDirectory)
+    print("Converting *Test.xml files from %s to HTML format in %s" % (
+        options.inputDirectory, options.outputDirectory))
     # verify or create the output directory
     output = options.outputDirectory
     if not os.path.isdir(output):
@@ -639,7 +640,7 @@ def main():
 
     # process each file
     for fileName in inputs:
-        print "Process the file : " + fileName
+        print("Process the file : " + fileName)
         # read and parse the xml file
         try:
             tree = ET.parse(fileName)
@@ -656,7 +657,7 @@ def main():
         else:
             sites = newdataset.getchildren()
         for site in sites:
-            # print "    -> Process the site : "+site.get("BuildStamp")
+            # print("    -> Process the site : "+site.get("BuildStamp"))
             Testing = site.find("Testing")
             tests = Testing.findall('Test')
             if not tests:
@@ -682,7 +683,7 @@ def main():
                         for d in os.environ.get('DATA_PATH', '').split(os.pathsep)
                         if os.path.isdir(os.path.join(d, 'HTMLTestReportSkel'))][0]
             except IndexError:
-                print "Cannot find skeleton directory in ${DATA_PATH}"
+                print("Cannot find skeleton directory in ${DATA_PATH}")
                 exit(1)
 
             # Copy the template directory (do not overwrite)
@@ -778,12 +779,10 @@ def main():
                     text = formatMeasurementText(text, escape=True)
                     # no "Measurement" or no "Value" or no text
                 except AttributeError as x:
-                    print 'WARNING: {0[id]}: AttributeError: {1}'.format(
-                        summary, x)
+                    print('WARNING: {0[id]}: AttributeError: {1}'.format(summary, x))
                     text = '<i>no stdout</i>'
                 except KeyError as x:
-                    print 'WARNING: {0[id]}: KeyError: {1}'.format(
-                        summary, x)
+                    print('WARNING: {0[id]}: KeyError: {1}'.format(summary, x))
                     # encoding or compressions unknown, keep original text
                     text = formatMeasurementText(value=text, escape=True)
                 with open(os.path.join(testCaseDir, "stdout"), "w") as stdout:
@@ -843,15 +842,15 @@ def main():
             organizer_failed.write()
 
     if sum(failures_count.values()):
-        print 'Some tests failed:'
-        print '\n'.join('  %s: %s' % i for i in failures_count.items())
+        print('Some tests failed:')
+        print('\n'.join('  %s: %s' % i for i in failures_count.items()))
         sys.exit(1)
 
-    # print " End of the program"
+    # print(" End of the program")
     #progEndTime = datetime.now()
     #delta = progEndTime - progStartTime
-    # print "program ended at "+progEndTime.strftime("%b %d %H:%M %Z")
-    # print "Duration : "+str(total_seconds_replacement(delta))+" seconds"
+    # print("program ended at "+progEndTime.strftime("%b %d %H:%M %Z"))
+    # print("Duration : "+str(total_seconds_replacement(delta))+" seconds")
 
 
 if __name__ == '__main__':
-- 
GitLab


From 721622808281a65fad77e1fb2833436e81d49154 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Thu, 30 Nov 2017 08:45:17 +0100
Subject: [PATCH 22/56] Decode `bytes` objects to UTF-8 `str` objects.

In Python 3, methods in the subprocess module that return command
output do so with the `bytes` type (because one does not know a priori
what the encoding of the output of some command might be). In Python 2,
the return type is `str`.

For compatibility, we've just decoded all `bytes` objects to UTF-8
strings. This is an assumption on the output of the commands that are
called, and may not be valid, but it does get the tests passing.
---
 GaudiKernel/tests/nose/test_instructionsetLevel.py | 2 ++
 cmake/get_host_binary_tag.py                       | 4 ++--
 cmake/tests/cmake_coverage.py                      | 1 +
 cmake/tests/test_LBCORE_716.py                     | 4 +++-
 4 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/GaudiKernel/tests/nose/test_instructionsetLevel.py b/GaudiKernel/tests/nose/test_instructionsetLevel.py
index df910a646b..4857b1b527 100644
--- a/GaudiKernel/tests/nose/test_instructionsetLevel.py
+++ b/GaudiKernel/tests/nose/test_instructionsetLevel.py
@@ -5,6 +5,7 @@ from subprocess import Popen, PIPE
 def test():
     out = Popen(['instructionsetLevel.exe', 'all'],
                 stdout=PIPE).communicate()[0]
+    out = out.decode('utf-8')
     known_flags = set(l.strip() for l in out.splitlines())
 
     expected = set()
@@ -14,6 +15,7 @@ def test():
             break
 
     out = Popen(['instructionsetLevel.exe'], stdout=PIPE).communicate()[0]
+    out = out.decode('utf-8')
     found = set(l.strip() for l in out.splitlines())
     # FIXME: these seem not to be reported by Linux
     found -= set(['sse3', 'avx512f'])
diff --git a/cmake/get_host_binary_tag.py b/cmake/get_host_binary_tag.py
index 434ee2c112..52d695c3f9 100755
--- a/cmake/get_host_binary_tag.py
+++ b/cmake/get_host_binary_tag.py
@@ -62,8 +62,8 @@ def _compiler_version(cmd=os.environ.get('CC', 'cc')):
     # prevent interference from localization
     env = dict(os.environ)
     env['LC_ALL'] = 'C'
-    m = re.search(r'(gcc|clang|icc|LLVM) version (\d+)\.(\d+)',
-                  check_output([cmd, '-v'], stderr=STDOUT, env=env))
+    output = check_output([cmd, '-v'], stderr=STDOUT, env=env).decode('utf-8')
+    m = re.search(r'(gcc|clang|icc|LLVM) version (\d+)\.(\d+)', output)
     if not m:  # prevent crashes if the compiler is not supported
         return 'unknown'
     comp = 'clang' if m.group(1) == 'LLVM' else m.group(1)
diff --git a/cmake/tests/cmake_coverage.py b/cmake/tests/cmake_coverage.py
index 62e90a68d1..058840ffe8 100755
--- a/cmake/tests/cmake_coverage.py
+++ b/cmake/tests/cmake_coverage.py
@@ -39,6 +39,7 @@ def cmake_script(name, cwd=None):
     proc = Popen(['cmake', '--trace', '-P', name],
                  stdout=PIPE, stderr=PIPE, cwd=cwd)
     out, err = proc.communicate()
+    out, err = out.decode('utf-8'), err.decode('utf-8')
     trace_line = re.compile(r'^(/.*)\(([0-9]+)\): ')
     new_err = []
     for line in err.splitlines():
diff --git a/cmake/tests/test_LBCORE_716.py b/cmake/tests/test_LBCORE_716.py
index 05dcb3c731..66a881846b 100644
--- a/cmake/tests/test_LBCORE_716.py
+++ b/cmake/tests/test_LBCORE_716.py
@@ -29,6 +29,7 @@ def build():
     build_proc = Popen(['make', 'VERBOSE=1'], cwd=base_dir,
                        stdout=PIPE, stderr=PIPE)
     build_log, build_err = build_proc.communicate()
+    build_log, build_err = build_log.decode('utf-8'), build_err.decode('utf-8')
     build_returncode = build_proc.returncode
 
 
@@ -61,7 +62,8 @@ def test_env():
     getenv = Popen([xenv_cmd, '--xml', envfile,
                     'printenv', 'ROOT_INCLUDE_PATH'],
                    stdout=PIPE, stderr=PIPE)
-    out, _err = getenv.communicate()
+    out, _ = getenv.communicate()
+    out = out.decode('utf-8')
     assert getenv.returncode == 0, getenv.returncode
 
     root_inc_path = [os.path.relpath(l, base_dir)[0]
-- 
GitLab


From bc7a3c7415dc789e38d4853a50c0558e1ca8b093 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Thu, 30 Nov 2017 08:48:33 +0100
Subject: [PATCH 23/56] Use Python 3 compatible iteration methods.

---
 GaudiPolicy/scripts/CTestXML2HTML | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/GaudiPolicy/scripts/CTestXML2HTML b/GaudiPolicy/scripts/CTestXML2HTML
index 034bd6fb4e..2fc6c2e5ee 100755
--- a/GaudiPolicy/scripts/CTestXML2HTML
+++ b/GaudiPolicy/scripts/CTestXML2HTML
@@ -326,7 +326,7 @@ class TestOrganizer:
 
     def _addStatistics(self):  # ,groupContainer,fatherAdresses):
         """ add statistics to the html structure."""
-        for group in self._groups.iteritems():
+        for group in self._groups.items():
             if group[0] not in self.fieldToAvoidList:
                 self._addStatistic(group[1])
 
@@ -349,12 +349,12 @@ class TestOrganizer:
                 stats.clear()
                 stats.set("class", "statistics")
 
-        for stat in group["Statistics"].iteritems():
+        for stat in group["Statistics"].items():
             ET.SubElement(stats, "span", {
                           "class": stat[0]}).text = '  ' + stat[0] + ' = ' + str(stat[1])
 
         # process all the subgroups
-        for grp in group.iteritems():
+        for grp in group.items():
             if grp[0] not in self.fieldToAvoidList:
                 self._addStatistic(grp[1])
 
-- 
GitLab


From f09ff8ca918912e2377e39cfcaca17b29e5e322e Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Thu, 30 Nov 2017 08:52:37 +0100
Subject: [PATCH 24/56] Use Python 2.6+ compatible import.

---
 GaudiPolicy/scripts/ZipPythonDir.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/GaudiPolicy/scripts/ZipPythonDir.py b/GaudiPolicy/scripts/ZipPythonDir.py
index 05e6456e6f..ec8f4edac3 100755
--- a/GaudiPolicy/scripts/ZipPythonDir.py
+++ b/GaudiPolicy/scripts/ZipPythonDir.py
@@ -11,7 +11,7 @@ import stat
 import time
 import re
 import codecs
-from StringIO import StringIO
+from io import StringIO
 
 # Class for generic exception coming from the zipdir() function
 
-- 
GitLab


From 0634cd8d13865d23ce8265b9b3378ff408f08fbc Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Thu, 30 Nov 2017 08:52:49 +0100
Subject: [PATCH 25/56] Use Python 2.6+ compatible lambda syntax.

---
 cmake/tests/cmake_coverage.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cmake/tests/cmake_coverage.py b/cmake/tests/cmake_coverage.py
index 058840ffe8..2d216e893d 100755
--- a/cmake/tests/cmake_coverage.py
+++ b/cmake/tests/cmake_coverage.py
@@ -60,7 +60,7 @@ def get_ranges(numbers):
     from itertools import groupby
     from operator import itemgetter
     for _key, group in groupby(enumerate(numbers),
-                               lambda (index, number): number - index):
+                               lambda index, number: number - index):
         group = map(itemgetter(1), group)
         yield group[0], group[-1]
 
-- 
GitLab


From 78d4c44440d2f6e56c21263d4e4ba91a9731af46 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Thu, 30 Nov 2017 11:43:16 +0100
Subject: [PATCH 26/56] Use Python 3 compatible metaclass syntax and function
 attribute accessors.

---
 .../python/GaudiKernel/Configurable.py        | 20 ++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/GaudiKernel/python/GaudiKernel/Configurable.py b/GaudiKernel/python/GaudiKernel/Configurable.py
index 64254723ef..c74daa5d82 100644
--- a/GaudiKernel/python/GaudiKernel/Configurable.py
+++ b/GaudiKernel/python/GaudiKernel/Configurable.py
@@ -8,6 +8,7 @@ import types
 import os
 import sys
 from inspect import isclass
+import six
 import GaudiKernel.ConfigurableMeta as ConfigurableMeta
 from GaudiKernel.Constants import error_explanation, \
     VERBOSE, DEBUG, INFO, WARNING, ERROR, FATAL
@@ -104,7 +105,7 @@ class PropertyReference(object):
 # base class for configurable Gaudi algorithms/services/algtools/etc. ======
 
 
-class Configurable(object):
+class Configurable(six.with_metaclass(ConfigurableMeta.ConfigurableMeta, object)):
     """Base class for Gaudi components that implement the IProperty interface.
        Provides most of the boilerplate code, but the actual useful classes
        are its derived ConfigurableAlgorithm, ConfigurableService, and
@@ -119,8 +120,6 @@ class Configurable(object):
     printHeaderWidth = 100
     printHeaderPre = 5
 
-    __metaclass__ = ConfigurableMeta.ConfigurableMeta
-
     __slots__ = (
         '__children',           # controlled components, e.g. private AlgTools
         '__tools',              # private AlgTools  (#PM-->)
@@ -143,19 +142,21 @@ class Configurable(object):
            of a type with the same name will return the same instance."""
 
         global log
+        func_code = six.get_function_code(cls.__init__)
+        func_defaults = six.get_function_defaults(cls.__init__)
         # try to get the name of the Configurable (having a name is compulsory)
         if 'name' in kwargs:
             # simple keyword (by far the easiest)
             name = kwargs['name']
-        elif 'name' in cls.__init__.func_code.co_varnames:
+        elif 'name' in func_code.co_varnames:
             # either positional in args, or default
-            index = list(cls.__init__.func_code.co_varnames).index('name')
+            index = list(func_code.co_varnames).index('name')
             try:
              # var names index is offset by one as __init__ is to be called with self
                 name = args[index - 1]
             except IndexError:
              # retrieve default value, then
-                name = cls.__init__.func_defaults[index - (len(args) + 1)]
+                name = func_defaults[index - (len(args) + 1)]
         else:
             # positional index is assumed (will work most of the time)
             try:
@@ -294,14 +295,15 @@ class Configurable(object):
 
         for meth, nArgs in meths.items():
             try:
-                f = getattr(klass, meth).im_func
+                f = six.get_unbound_function(getattr(klass, meth))
             except AttributeError:
                 raise NotImplementedError("%s is missing in class %s" % (
                     meth, str(klass)))
 
             # in addition, verify the number of arguments w/o defaults
-            nargcount = f.func_code.co_argcount
-            ndefaults = f.func_defaults and len(f.func_defaults) or 0
+            nargcount = six.get_function_code(f).co_argcount
+            fdefaults = six.get_function_defaults(f)
+            ndefaults = fdefaults and len(fdefaults) or 0
             if not nargcount - ndefaults <= nArgs <= nargcount:
                 raise TypeError( "%s.%s requires exactly %d arguments" % (
                     klass, meth, nArgs))
-- 
GitLab


From db507905446a019f746643bf1550aedfac169fa3 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Thu, 30 Nov 2017 11:43:27 +0100
Subject: [PATCH 27/56] Define __hash__ on classes that only define __eq__.

In the Python 3 data model, a hashable object object must define both
__eq__ and __hash__. This is in contrast to Python 2, where all
user-defined classes have a default implementation of __hash__
(derived from id).

See and compare:

    https://docs.python.org/2/reference/datamodel.html
    https://docs.python.org/3/reference/datamodel.html
---
 GaudiKernel/python/GaudiConfig/ControlFlow.py  | 9 +++++++++
 GaudiKernel/python/GaudiKernel/Configurable.py | 9 +++++++++
 2 files changed, 18 insertions(+)

diff --git a/GaudiKernel/python/GaudiConfig/ControlFlow.py b/GaudiKernel/python/GaudiConfig/ControlFlow.py
index 13eb284339..59a440c519 100644
--- a/GaudiKernel/python/GaudiConfig/ControlFlow.py
+++ b/GaudiKernel/python/GaudiConfig/ControlFlow.py
@@ -42,6 +42,15 @@ class ControlFlowNode(object):
     def __eq__(self, other):
         return (repr(self) == repr(other))
 
+    def __hash__(self):
+        """Return a unique identifier for this object.
+
+        As we use the `repr` of this object to check for equality, we use it
+        here to define uniqueness.
+        """
+        # The hash of the 1-tuple containing the repr of this object
+        return hash((repr(self),))
+
     def getFullName(self):
         '''
         Allow use of an expression as an algorihtm/sequence in a Gaudi job
diff --git a/GaudiKernel/python/GaudiKernel/Configurable.py b/GaudiKernel/python/GaudiKernel/Configurable.py
index c74daa5d82..a8cd5a7bf7 100644
--- a/GaudiKernel/python/GaudiKernel/Configurable.py
+++ b/GaudiKernel/python/GaudiKernel/Configurable.py
@@ -1089,6 +1089,15 @@ class ConfigurableAlgorithm(Configurable):
     def __eq__(self, other):
         return (repr(self) == repr(other))
 
+    def __hash__(self):
+        """Return a unique identifier for this object.
+
+        As we use the `repr` of this object to check for equality, we use it
+        here to define uniqueness.
+        """
+        # The hash of the 1-tuple containing the repr of this object
+        return hash((repr(self),))
+
 
 class ConfigurableService(Configurable):
     __slots__ = {'OutputLevel': 0,
-- 
GitLab


From a68b2f0c2a63e0002c19845509255d23d23307bb Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Thu, 30 Nov 2017 11:46:13 +0100
Subject: [PATCH 28/56] saxutils requires a str, not a bytes.

---
 GaudiPolicy/scripts/CTestXML2HTML | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/GaudiPolicy/scripts/CTestXML2HTML b/GaudiPolicy/scripts/CTestXML2HTML
index 2fc6c2e5ee..a98a3018cc 100755
--- a/GaudiPolicy/scripts/CTestXML2HTML
+++ b/GaudiPolicy/scripts/CTestXML2HTML
@@ -66,7 +66,7 @@ def formatMeasurementText(txt, escape=False, preformat=True):
     from codecs import encode
     if hasattr(txt, 'decode'):
         txt = txt.decode(errors='ignore')
-    txt = encode(txt, 'utf-8', 'xmlcharrefreplace')
+    txt = encode(txt, 'utf-8', 'xmlcharrefreplace').decode('utf-8')
     if escape:
         txt = escape_xml(txt)
     if preformat:
-- 
GitLab


From 6e684289df24f12cc0952dc78f0ffae5343a2e7f Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Thu, 30 Nov 2017 15:36:18 +0100
Subject: [PATCH 29/56] Do not mutate dictionaries whilst iterating over them.

---
 Gaudi/python/Gaudi/Configuration.py | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/Gaudi/python/Gaudi/Configuration.py b/Gaudi/python/Gaudi/Configuration.py
index 08331dcb6d..f3c53b4c86 100644
--- a/Gaudi/python/Gaudi/Configuration.py
+++ b/Gaudi/python/Gaudi/Configuration.py
@@ -83,10 +83,11 @@ def configurationDict(all=False):
             conf_dict[n][p] = v
     # purge empty configurables
     keys = conf_dict.keys()
+    ret_dict = {}
     for n in keys:
-        if not conf_dict[n]:
-            del conf_dict[n]
-    return conf_dict
+        if conf_dict[n]:
+            ret_dict[n] = conf_dict[n]
+    return ret_dict
 
 
 def getConfigurable(name, defaultType=None):
-- 
GitLab


From 795ce287a2ca6f83c17785300509b38c942917c2 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Mon, 11 Dec 2017 15:54:47 +0100
Subject: [PATCH 30/56] Use Python 3 compatible iteration methods.

---
 Gaudi/python/Gaudi/Main.py                    | 25 +++++++++++--------
 .../tests/qmtest/ExtPropValidator.py          |  2 +-
 GaudiKernel/GaudiKernel/MapBase.h             |  2 +-
 .../python/GaudiKernel/Configurable.py        |  4 +--
 .../tests/qmtest/scripts/test_bug_87340.py    |  6 ++---
 GaudiPolicy/python/GaudiTesting/BaseTest.py   | 22 ++++++++--------
 GaudiPolicy/python/GaudiTesting/Run.py        |  2 +-
 GaudiPython/python/GaudiPython/Bindings.py    |  8 +++---
 .../python/GaudiPython/Pythonizations.py      | 11 +++++---
 GaudiSvc/scripts/dumpMetaData                 |  2 +-
 10 files changed, 48 insertions(+), 36 deletions(-)

diff --git a/Gaudi/python/Gaudi/Main.py b/Gaudi/python/Gaudi/Main.py
index 4acfead980..f3666dea51 100644
--- a/Gaudi/python/Gaudi/Main.py
+++ b/Gaudi/python/Gaudi/Main.py
@@ -155,7 +155,7 @@ def toOpt(value):
         return '"{0}"'.format(value.replace('"', '\\"'))
     elif isinstance(value, dict):
         return '{{{0}}}'.format(', '.join('{0}: {1}'.format(toOpt(k), toOpt(v))
-                                          for k, v in value.iteritems()))
+                                          for k, v in value.items()))
     elif hasattr(value, '__iter__'):
         return '[{0}]'.format(', '.join(map(toOpt, value)))
     else:
@@ -220,10 +220,10 @@ class gaudimain(object):
         from pprint import pformat
         conf_dict = Configuration.configurationDict(all)
         out = []
-        names = conf_dict.keys()
+        names = list(conf_dict.keys())
         names.sort()
         for n in names:
-            props = conf_dict[n].keys()
+            props = list(conf_dict[n].keys())
             props.sort()
             for p in props:
                 out.append('%s.%s = %s;' % (n, p, toOpt(conf_dict[n][p])))
@@ -315,10 +315,13 @@ class gaudimain(object):
 
         # set ApplicationMgr properties
         comp = 'ApplicationMgr'
-        props = Configurable.allConfigurables.get(comp, {})
-        if props:
-            props = expandvars(props.getValuedProperties())
-        for p, v in props.items() + [('JobOptionsType', 'NONE')]:
+        try:
+            appMgr = Configurable.allConfigurables[comp]
+            props = expandvars(appMgr.getValuedProperties())
+        except KeyError:
+            props = {}
+        prop_items = list(props.items()) + [('JobOptionsType', 'NONE')]
+        for p, v in prop_items:
             if not self.g.setProperty(p, str(v)):
                 self.log.error('Cannot set property %s.%s to %s', comp, p, v)
                 sys.exit(10)
@@ -335,9 +338,11 @@ class gaudimain(object):
         if not msp:
             self.log.error('Cannot get service %s', comp)
             sys.exit(10)
-        props = Configurable.allConfigurables.get(comp, {})
-        if props:
-            props = expandvars(props.getValuedProperties())
+        try:
+            msgSvc = Configurable.allConfigurables[comp]
+            props = expandvars(msgSvc.getValuedProperties())
+        except KeyError:
+            props = {}
         for p, v in props.items():
             if not _bootstrap.setProperty(msp, p, str(v)):
                 self.log.error('Cannot set property %s.%s to %s', comp, p, v)
diff --git a/GaudiExamples/tests/qmtest/ExtPropValidator.py b/GaudiExamples/tests/qmtest/ExtPropValidator.py
index f2c2170d58..220782315c 100644
--- a/GaudiExamples/tests/qmtest/ExtPropValidator.py
+++ b/GaudiExamples/tests/qmtest/ExtPropValidator.py
@@ -50,7 +50,7 @@ def validate(stdout, stderr, result, causes):
     output = map(lambda l: l.rstrip(), stdout.splitlines())
     i = output.__iter__()
     try:
-        while not signature.match(i.next()):
+        while not signature.match(next(i)):
             pass
 
         properties = {}
diff --git a/GaudiKernel/GaudiKernel/MapBase.h b/GaudiKernel/GaudiKernel/MapBase.h
index f9895d5eef..35f90de385 100644
--- a/GaudiKernel/GaudiKernel/MapBase.h
+++ b/GaudiKernel/GaudiKernel/MapBase.h
@@ -33,7 +33,7 @@ namespace Gaudi
      *   - <c> items   </c>
      *   - <c> values  </c>
      *   - <c> get     </c>
-     *   - <c> has_key </c>
+     *   - <c> has_key </c> (for Python 2)
      *
      *  Thus it behaves practically identically
      *  with builtin-type <c>dict</c>
diff --git a/GaudiKernel/python/GaudiKernel/Configurable.py b/GaudiKernel/python/GaudiKernel/Configurable.py
index a8cd5a7bf7..dee0b9513f 100644
--- a/GaudiKernel/python/GaudiKernel/Configurable.py
+++ b/GaudiKernel/python/GaudiKernel/Configurable.py
@@ -1497,8 +1497,8 @@ def applyConfigurableUsers():
         # easiest way to fix bug #103803.
         # <https://savannah.cern.ch/bugs/?103803>
         while True:
-            yield (c for c in Configurable.allConfigurables.values()
-                   if c.isApplicable()).next()
+            yield next(c for c in Configurable.allConfigurables.values()
+                       if c.isApplicable())
 
     debugApplyOrder = 'GAUDI_DUBUG_CONF_USER' in os.environ
     for c in applicableConfUsers():
diff --git a/GaudiKernel/tests/qmtest/scripts/test_bug_87340.py b/GaudiKernel/tests/qmtest/scripts/test_bug_87340.py
index 13875f74c7..a060ff22da 100755
--- a/GaudiKernel/tests/qmtest/scripts/test_bug_87340.py
+++ b/GaudiKernel/tests/qmtest/scripts/test_bug_87340.py
@@ -22,10 +22,10 @@ varname = 'LD_LIBRARY_PATH'
 searchpath.extend(os.environ.get(varname, "").split(os.pathsep))
 
 try:
-    lib = (p
+    lib = next(p
            for p in (os.path.join(n, libname)
                      for n in searchpath)
-           if os.path.exists(p)).next()
+           if os.path.exists(p))
 except StopIteration:
     print('FAILURE: Cannot find', repr(libname), 'in', searchpath,
           file=sys.stderr)
@@ -41,7 +41,7 @@ if nm.returncode:
 
 signature = re.compile(r"MsgStream&amp; operator&lt;&lt; &lt;char \[\d+\]&gt;")
 
-lines = filter(signature.search, output.splitlines())
+lines = list(filter(signature.search, output.splitlines()))
 if lines:
     print("\n".join(lines))
     print("FAILURE: found MsgStream operator<< specialization", file=sys.stderr)
diff --git a/GaudiPolicy/python/GaudiTesting/BaseTest.py b/GaudiPolicy/python/GaudiTesting/BaseTest.py
index 92872b5e34..e4ecb26516 100644
--- a/GaudiPolicy/python/GaudiTesting/BaseTest.py
+++ b/GaudiPolicy/python/GaudiTesting/BaseTest.py
@@ -110,7 +110,7 @@ class BaseTest(object):
             self.environment = os.environ
         else:
             self.environment = dict(
-                self.environment.items() + os.environ.items())
+                list(self.environment.items()) + list(os.environ.items()))
 
         platform_id = (os.environ.get('BINARY_TAG') or
                        os.environ.get('CMTCONFIG') or
@@ -145,7 +145,7 @@ class BaseTest(object):
 
             prog = which(prog) or prog
 
-            args = map(RationalizePath, self.args)
+            args = list(map(RationalizePath, self.args))
 
             if prog_ext == ".py":
                 params = ['python', RationalizePath(prog)] + args
@@ -245,13 +245,13 @@ class BaseTest(object):
                          'Unsupported Platforms': 'unsupported_platforms',
                          'Stack Trace': 'stack_trace'}
         resultDict = [(key, getattr(self, attr))
-                      for key, attr in field_mapping.iteritems()
+                      for key, attr in field_mapping.items()
                       if getattr(self, attr)]
         resultDict.append(('Working Directory',
                            RationalizePath(os.path.join(os.getcwd(),
                                                         self.workdir))))
         # print(dict(resultDict).keys())
-        resultDict.extend(self.result.annotations.iteritems())
+        resultDict.extend(self.result.annotations.items())
         # print(self.result.annotations.keys())
         return dict(resultDict)
 
@@ -280,12 +280,12 @@ class BaseTest(object):
         if causes is None:
             causes = self.causes
 
-        reflines = filter(
-            None, map(lambda s: s.rstrip(), reference.splitlines()))
+        reflines = list(filter(
+            None, map(lambda s: s.rstrip(), reference.splitlines())))
         if not reflines:
             raise RuntimeError("Empty (or null) reference")
         # the same on standard output
-        outlines = filter(None, map(lambda s: s.rstrip(), stdout.splitlines()))
+        outlines = list(filter(None, map(lambda s: s.rstrip(), stdout.splitlines())))
 
         res_field = "GaudiTest.RefBlock"
         if id:
@@ -681,7 +681,7 @@ class BasicOutputValidator:
                 r'Warning in <TInterpreter::ReadRootmapFile>: .* is already in .*')
 
             def keep_line(l): return not to_ignore.match(l)
-            return filter(keep_line, s1.splitlines()) == filter(keep_line, s2.splitlines())
+            return list(filter(keep_line, s1.splitlines())) == list(filter(keep_line, s2.splitlines()))
         else:
             return s1.splitlines() == s2.splitlines()
 
@@ -739,7 +739,7 @@ class LineSkipper(FilePreprocessor):
     def __init__(self, strings=[], regexps=[]):
         import re
         self.strings = strings
-        self.regexps = map(re.compile, regexps)
+        self.regexps = list(map(re.compile, regexps))
 
     def __processLine__(self, line):
         for s in self.strings:
@@ -988,8 +988,8 @@ class ReferenceFileValidator:
             new = self.preproc(new)
 
         diffs = difflib.ndiff(orig, new, charjunk=difflib.IS_CHARACTER_JUNK)
-        filterdiffs = map(lambda x: x.strip(), filter(
-            lambda x: x[0] != " ", diffs))
+        filterdiffs = list(map(lambda x: x.strip(), filter(
+            lambda x: x[0] != " ", diffs)))
         if filterdiffs:
             result[self.result_key] = result.Quote("\n".join(filterdiffs))
             result[self.result_key] += result.Quote("""
diff --git a/GaudiPolicy/python/GaudiTesting/Run.py b/GaudiPolicy/python/GaudiTesting/Run.py
index a832236de5..1204de3179 100644
--- a/GaudiPolicy/python/GaudiTesting/Run.py
+++ b/GaudiPolicy/python/GaudiTesting/Run.py
@@ -41,7 +41,7 @@ def ctest_report(results):
     print('CTEST_FULL_OUTPUT')
     print(results.get('stdout', ''))
     handler = {'Environment': lambda v: '\n'.join('{0}={1}'.format(*item)
-                                                  for item in sorted(v.iteritems())),
+                                                  for item in sorted(v.items())),
                'Causes': lambda v: 'unexpected ' + ', '.join(v)}
 
     def id_handler(v): return str(v)
diff --git a/GaudiPython/python/GaudiPython/Bindings.py b/GaudiPython/python/GaudiPython/Bindings.py
index 78fc93f147..6f3333b0a3 100644
--- a/GaudiPython/python/GaudiPython/Bindings.py
+++ b/GaudiPython/python/GaudiPython/Bindings.py
@@ -943,9 +943,11 @@ class AppMgr(iService):
                 GaudiKernel.Proxy.Configurable.applyConfigurableUsers()
             # This is the default and could be overridden with "selfopts"
             self.OutputLevel = 3
-            selfprops = Configurable.allConfigurables.get('ApplicationMgr', {})
-            if selfprops:
-                selfprops = expandvars(selfprops.getValuedProperties())
+            try:
+                appMgr = Configurable.allConfigurables['ApplicationMgr']
+                selfprops = expandvars(appMgr.getValuedProperties())
+            except KeyError:
+                selfprops = {}
             for p, v in selfprops.items():
                 setattr(self, p, v)
             for p, v in selfoptions.items():
diff --git a/GaudiPython/python/GaudiPython/Pythonizations.py b/GaudiPython/python/GaudiPython/Pythonizations.py
index 6f61f41631..af2d650740 100644
--- a/GaudiPython/python/GaudiPython/Pythonizations.py
+++ b/GaudiPython/python/GaudiPython/Pythonizations.py
@@ -497,14 +497,19 @@ gbl.Gaudi.Utils.MapBase . __len__ = lambda s: s.size()
 gbl.Gaudi.Utils.MapBase . __iter__ = __mapbase_iter__
 gbl.Gaudi.Utils.MapBase .   keys = __mapbase_keys__
 gbl.Gaudi.Utils.MapBase . __iteritems__ = __mapbase_iteritems__
-gbl.Gaudi.Utils.MapBase .   iteritems = __mapbase_iteritems__
-gbl.Gaudi.Utils.MapBase .   items = __mapbase_items__
 gbl.Gaudi.Utils.MapBase .   values = __mapbase_values__
 gbl.Gaudi.Utils.MapBase . __contains__ = __mapbase_contains__
-gbl.Gaudi.Utils.MapBase .   has_key = __mapbase_contains__
 gbl.Gaudi.Utils.MapBase .   get = __mapbase_get__
 gbl.Gaudi.Utils.MapBase . __str__ = __mapbase_str__
 gbl.Gaudi.Utils.MapBase . __repr__ = __mapbase_str__
 gbl.Gaudi.Utils.MapBase . __setitem__ = __mapbase_setitem__
 gbl.Gaudi.Utils.MapBase . __delitem__ = __mapbase_delitem__
 gbl.Gaudi.Utils.MapBase . __getitem__ = lambda s, key: s.at(key)
+if six.PY2:
+    # Behaviour is like Python 2 dict
+    gbl.Gaudi.Utils.MapBase .   iteritems = __mapbase_iteritems__
+    gbl.Gaudi.Utils.MapBase .   items = __mapbase_items__
+    gbl.Gaudi.Utils.MapBase .   has_key = __mapbase_contains__
+else:
+    # Behaviour is like Python 3+ dict
+    gbl.Gaudi.Utils.MapBase .   items = __mapbase_iteritems__
diff --git a/GaudiSvc/scripts/dumpMetaData b/GaudiSvc/scripts/dumpMetaData
index bd2b14c764..3d8d2c9560 100755
--- a/GaudiSvc/scripts/dumpMetaData
+++ b/GaudiSvc/scripts/dumpMetaData
@@ -23,5 +23,5 @@ if __name__ == '__main__':
 
     try:
         pprint(getMetaData(filename))
-    except RuntimeError, x:
+    except RuntimeError as x:
         parser.error(str(x))
-- 
GitLab


From 2b3a42695c7079e66f96e85828145b86d8445e1b Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Mon, 11 Dec 2017 16:09:20 +0100
Subject: [PATCH 31/56] Use Python 3 compatible `except` syntax.

---
 Gaudi/tests/python/Test_confDb.py                               | 2 +-
 Gaudi/tests/scripts/test_export_oldopts.py                      | 2 +-
 .../gaudiexamples.qms/chronostatsvc.qms/per_event_file.qmt      | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/Gaudi/tests/python/Test_confDb.py b/Gaudi/tests/python/Test_confDb.py
index 9612f5abf3..a8bfb4a6c6 100644
--- a/Gaudi/tests/python/Test_confDb.py
+++ b/Gaudi/tests/python/Test_confDb.py
@@ -30,7 +30,7 @@ try:
     _fillCfgDb()
     # house cleaning...
     del _fillCfgDb
-except Exception, err:
+except Exception as err:
     print("Py:ConfigurableDb   ERROR Problem with [%s] content!" % __name__)
     print("Py:ConfigurableDb   ERROR", err)
     print("Py:ConfigurableDb   ERROR   ==> culprit is package [Test] !")
diff --git a/Gaudi/tests/scripts/test_export_oldopts.py b/Gaudi/tests/scripts/test_export_oldopts.py
index f14c961930..c0cd278f2b 100755
--- a/Gaudi/tests/scripts/test_export_oldopts.py
+++ b/Gaudi/tests/scripts/test_export_oldopts.py
@@ -77,7 +77,7 @@ try:
         print("Configuration from old options differs from the python one")
         retcode = 1
 
-except RuntimeError, x:
+except RuntimeError as x:
     print(x)
     retcode = 1
 
diff --git a/GaudiExamples/tests/qmtest/gaudiexamples.qms/chronostatsvc.qms/per_event_file.qmt b/GaudiExamples/tests/qmtest/gaudiexamples.qms/chronostatsvc.qms/per_event_file.qmt
index 04fbff25dd..763683a0ac 100644
--- a/GaudiExamples/tests/qmtest/gaudiexamples.qms/chronostatsvc.qms/per_event_file.qmt
+++ b/GaudiExamples/tests/qmtest/gaudiexamples.qms/chronostatsvc.qms/per_event_file.qmt
@@ -51,7 +51,7 @@ try:
     if entries[0] != 'Timing' or len(entries) != 401:
         raise Cause('timing log content')
 
-except Cause, c:
+except Cause as c:
     causes.append(c.msg)
 
 </text></argument>
-- 
GitLab


From 04f6ed4ca7807492e253f42d45049cf91e7b1a11 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Mon, 11 Dec 2017 16:12:47 +0100
Subject: [PATCH 32/56] Use more idiomatic check for dictionary key membership.

Plus, the dict.has_key method was removed in Python 3.
---
 GaudiKernel/python/GaudiKernel/Configurable.py            | 2 +-
 GaudiKernel/python/GaudiKernel/ConfigurableDb.py          | 2 +-
 GaudiKernel/python/GaudiKernel/RootMap.py                 | 6 +++---
 GaudiPolicy/qmtest_classes/GaudiTest.py                   | 2 +-
 GaudiProfiling/python/GaudiProfiling/GenerateGaudiOpts.py | 4 ++--
 GaudiPython/python/GaudiPython/Bindings.py                | 2 +-
 GaudiPython/python/GaudiPython/GaudiAlgs.py               | 2 +-
 7 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/GaudiKernel/python/GaudiKernel/Configurable.py b/GaudiKernel/python/GaudiKernel/Configurable.py
index dee0b9513f..6b77443223 100644
--- a/GaudiKernel/python/GaudiKernel/Configurable.py
+++ b/GaudiKernel/python/GaudiKernel/Configurable.py
@@ -511,7 +511,7 @@ class Configurable(six.with_metaclass(ConfigurableMeta.ConfigurableMeta, object)
 
                 # merge properties, new over pre-existing
                 for proxy in self._properties.values():
-                    if proxy.history.has_key(cc):
+                    if cc in proxy.history:
                         proxy.__set__(ccbd, proxy.__get__(cc))
 
                 # consolidate
diff --git a/GaudiKernel/python/GaudiKernel/ConfigurableDb.py b/GaudiKernel/python/GaudiKernel/ConfigurableDb.py
index 87d977f75b..7cf688e347 100644
--- a/GaudiKernel/python/GaudiKernel/ConfigurableDb.py
+++ b/GaudiKernel/python/GaudiKernel/ConfigurableDb.py
@@ -55,7 +55,7 @@ class _CfgDb(dict):
             if cfg['lib'] != self[configurable]['lib']:
                 log.debug("dup!! [%s] p=%s m=%s lib=%s",
                           configurable, package, module, lib)
-                if self._duplicates.has_key(configurable):
+                if configurable in self._duplicates:
                     self._duplicates[configurable] += [cfg]
                 else:
                     self._duplicates[configurable] = [cfg]
diff --git a/GaudiKernel/python/GaudiKernel/RootMap.py b/GaudiKernel/python/GaudiKernel/RootMap.py
index 8800f23c9a..06bbe4d429 100644
--- a/GaudiKernel/python/GaudiKernel/RootMap.py
+++ b/GaudiKernel/python/GaudiKernel/RootMap.py
@@ -39,7 +39,7 @@ def _procRootMap(rtmpfile, rtmapdict):
         if line:
             if line[0] != '#':
                 entry, lib = _getEntry(line)
-                if not rtmapdict.has_key(entry):
+                if entry not in rtmapdict:
                     rtmapdict[entry] = []
                 rtmapdict[entry].append(
                     (os.path.join(os.path.dirname(rtmpfile), lib), block))
@@ -48,7 +48,7 @@ def _procRootMap(rtmpfile, rtmapdict):
 
 
 def _procSysRootMap(rtmapdict):
-    if os.environ.has_key("ROOTSYS"):
+    if "ROOTSYS" in os.environ:
         rtmpfile = os.path.join(os.environ["ROOTSYS"], "etc", "system.rootmap")
         block = ""
         for line in open(rtmpfile, 'r'):
@@ -56,7 +56,7 @@ def _procSysRootMap(rtmapdict):
             if line:
                 if line[0] != '#':
                     entry, lib = _getEntry(line)
-                    if not rtmapdict.has_key(entry):
+                    if entry not in rtmapdict:
                         rtmapdict[entry] = []
                     rtmapdict[entry].append(
                         (os.path.join(os.environ["ROOTSYS"], "lib", lib), block))
diff --git a/GaudiPolicy/qmtest_classes/GaudiTest.py b/GaudiPolicy/qmtest_classes/GaudiTest.py
index 49f7b7efc1..ba179c4d10 100644
--- a/GaudiPolicy/qmtest_classes/GaudiTest.py
+++ b/GaudiPolicy/qmtest_classes/GaudiTest.py
@@ -2307,7 +2307,7 @@ class XMLResultStream(ResultStream):
             else:
                 value.text = convert_xml_illegal_chars(result[field])
 
-        if result.has_key("ExecTest.stdout"):  # "ExecTest.stdout" in result :
+        if "ExecTest.stdout" in result:  # "ExecTest.stdout" in result :
             Measurement = ET.SubElement(Results, "Measurement")
             value = ET.SubElement(Measurement, "Value")
             if "<pre>" in result["ExecTest.stdout"][0:6]:
diff --git a/GaudiProfiling/python/GaudiProfiling/GenerateGaudiOpts.py b/GaudiProfiling/python/GaudiProfiling/GenerateGaudiOpts.py
index 076107efc1..1216b51603 100644
--- a/GaudiProfiling/python/GaudiProfiling/GenerateGaudiOpts.py
+++ b/GaudiProfiling/python/GaudiProfiling/GenerateGaudiOpts.py
@@ -62,7 +62,7 @@ class XmlDictObject(dict):
         self.__setitem__(item, value)
 
     def __str__(self):
-        if self.has_key('_text'):
+        if '_text' in self:
             return self.__getitem__('_text')
         else:
             return ''
@@ -139,7 +139,7 @@ def _ConvertXmlToDictRecurse(node, dictclass):
     for child in node:
         # recursively add the element's children
         newitem = _ConvertXmlToDictRecurse(child, dictclass)
-        if nodedict.has_key(child.tag):
+        if child.tag in nodedict:
             # found duplicate tag, force a list
             if type(nodedict[child.tag]) is type([]):
                 # append to existing list
diff --git a/GaudiPython/python/GaudiPython/Bindings.py b/GaudiPython/python/GaudiPython/Bindings.py
index 6f3333b0a3..0351bc2328 100644
--- a/GaudiPython/python/GaudiPython/Bindings.py
+++ b/GaudiPython/python/GaudiPython/Bindings.py
@@ -1169,7 +1169,7 @@ class AppMgr(iService):
             print(prefix + algName)
             alg = appMgr.algorithm(algName.split("/")[-1])
             prop = alg.properties()
-            if prop.has_key("Members"):
+            if "Members" in prop:
                 subs = prop["Members"].value()
                 for i in subs:
                     printAlgo(i.strip('"'), appMgr, prefix + "     ")
diff --git a/GaudiPython/python/GaudiPython/GaudiAlgs.py b/GaudiPython/python/GaudiPython/GaudiAlgs.py
index 7cd2a5dfb1..441ff723b2 100644
--- a/GaudiPython/python/GaudiPython/GaudiAlgs.py
+++ b/GaudiPython/python/GaudiPython/GaudiAlgs.py
@@ -215,7 +215,7 @@ def _init_(self, name, **args):
     for key in args:
         setattr(self, key, args[key])
     # take some care about the ownership of the algorithms
-    if not appMgr.__dict__.has_key('GaudiPythonAlgos'):
+    if 'GaudiPythonAlgos' not in appMgr.__dict__:
         appMgr.__dict__['GaudiPythonAlgos'] = []
     appMgr.__dict__['GaudiPythonAlgos'].append(self)
 
-- 
GitLab


From 382392f43e00aa009df397021836968f6c2ee037 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Mon, 11 Dec 2017 16:17:26 +0100
Subject: [PATCH 33/56] Use Python 3 compatible file reading.

file.xreadlines with deprecated in Python 2.3.
---
 GaudiPolicy/python/GaudiTesting/BaseTest.py | 2 +-
 GaudiPolicy/qmtest_classes/GaudiTest.py     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/GaudiPolicy/python/GaudiTesting/BaseTest.py b/GaudiPolicy/python/GaudiTesting/BaseTest.py
index e4ecb26516..b98e0c03be 100644
--- a/GaudiPolicy/python/GaudiTesting/BaseTest.py
+++ b/GaudiPolicy/python/GaudiTesting/BaseTest.py
@@ -976,7 +976,7 @@ class ReferenceFileValidator:
     def __call__(self, stdout, result):
         causes = []
         if os.path.isfile(self.reffile):
-            orig = open(self.reffile).xreadlines()
+            orig = open(self.reffile).readlines()
             if self.preproc:
                 orig = self.preproc(orig)
                 result[self.result_key + '.preproc.orig'] = \
diff --git a/GaudiPolicy/qmtest_classes/GaudiTest.py b/GaudiPolicy/qmtest_classes/GaudiTest.py
index ba179c4d10..69810aa201 100644
--- a/GaudiPolicy/qmtest_classes/GaudiTest.py
+++ b/GaudiPolicy/qmtest_classes/GaudiTest.py
@@ -661,7 +661,7 @@ class ReferenceFileValidator:
     def __call__(self, stdout, result):
         causes = []
         if os.path.isfile(self.reffile):
-            orig = open(self.reffile).xreadlines()
+            orig = open(self.reffile).readlines()
             if self.preproc:
                 orig = self.preproc(orig)
         else:
-- 
GitLab


From 84efd158b9910717d4f6c74ce4bc93f98423f552 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Mon, 11 Dec 2017 16:22:00 +0100
Subject: [PATCH 34/56] Use Python 3 compatible lists of string and number
 types.

---
 Gaudi/python/Gaudi/Main.py                  | 6 ++++--
 GaudiPolicy/python/GaudiTesting/BaseTest.py | 8 +++++---
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/Gaudi/python/Gaudi/Main.py b/Gaudi/python/Gaudi/Main.py
index f3666dea51..6abcef0989 100644
--- a/Gaudi/python/Gaudi/Main.py
+++ b/Gaudi/python/Gaudi/Main.py
@@ -5,6 +5,8 @@ from time import time
 from Gaudi import Configuration
 import logging
 
+import six
+
 log = logging.getLogger(__name__)
 
 
@@ -151,7 +153,7 @@ def toOpt(value):
     >>> print(toOpt({'a': [1, 2, '3']}))
     {"a": [1, 2, "3"]}
     '''
-    if isinstance(value, basestring):
+    if isinstance(value, six.string_types):
         return '"{0}"'.format(value.replace('"', '\\"'))
     elif isinstance(value, dict):
         return '{{{0}}}'.format(', '.join('{0}: {1}'.format(toOpt(k), toOpt(v))
@@ -367,7 +369,7 @@ class gaudimain(object):
                     v = v.__resolve__()
                 if type(v) == str:
                     v = '"%s"' % v  # need double quotes
-                elif type(v) == long:
+                elif type(v) == six.integer_types:
                     v = '%d' % v  # prevent pending 'L'
                 _bootstrap.addPropertyToCatalogue(jos, n, p, str(v))
         if hasattr(Configurable, "_configurationLocked"):
diff --git a/GaudiPolicy/python/GaudiTesting/BaseTest.py b/GaudiPolicy/python/GaudiTesting/BaseTest.py
index b98e0c03be..00249cf71b 100644
--- a/GaudiPolicy/python/GaudiTesting/BaseTest.py
+++ b/GaudiPolicy/python/GaudiTesting/BaseTest.py
@@ -13,6 +13,8 @@ import logging
 
 from subprocess import Popen, PIPE, STDOUT
 
+import six
+
 
 def sanitize_for_xml(data):
     '''
@@ -622,12 +624,12 @@ class Result:
         self.annotations = annotations.copy()
 
     def __getitem__(self, key):
-        assert type(key) in types.StringTypes
+        assert isinstance(key, six.string_types)
         return self.annotations[key]
 
     def __setitem__(self, key, value):
-        assert type(key) in types.StringTypes
-        assert type(value) in types.StringTypes
+        assert isinstance(key, six.string_types)
+        assert isinstance(value, six.string_types)
         self.annotations[key] = value
 
     def Quote(self, string):
-- 
GitLab


From ac98bfbbf4f88d7604ba5a7f660d2b294eb8b71d Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Mon, 11 Dec 2017 16:24:41 +0100
Subject: [PATCH 35/56] Use Python 3 compatible long type.

There is only `int` in Python 3.
---
 GaudiExamples/options/Properties.py        | 6 ++++++
 GaudiKernel/src/Util/genconf.cpp           | 9 +++++++--
 GaudiPython/python/GaudiPython/Bindings.py | 4 ++++
 3 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/GaudiExamples/options/Properties.py b/GaudiExamples/options/Properties.py
index be9d8664bb..05d9d70042 100644
--- a/GaudiExamples/options/Properties.py
+++ b/GaudiExamples/options/Properties.py
@@ -1,3 +1,9 @@
+# Python 2 compatibility
+try:
+    long
+except NameError:
+    long = int
+
 from Gaudi.Configuration import *
 
 # common configuration plus output level threshold
diff --git a/GaudiKernel/src/Util/genconf.cpp b/GaudiKernel/src/Util/genconf.cpp
index a33d8f271d..c71d2cc875 100644
--- a/GaudiKernel/src/Util/genconf.cpp
+++ b/GaudiKernel/src/Util/genconf.cpp
@@ -657,7 +657,12 @@ void configGenerator::genHeader( std::ostream& py, std::ostream& db )
   // python file part
   std::string now = Gaudi::Time::current().format( true );
   py << "#" << now //<< "\n"
-     << "\"\"\"Automatically generated. DO NOT EDIT please\"\"\"\n";
+     << "\"\"\"Automatically generated. DO NOT EDIT please\"\"\"\n"
+     << "import sys\n"
+     << "if sys.version_info >= (3,):\n"
+     << "    # Python 2 compatibility\n"
+     << "    long = int\n";
+
   if ( m_importGaudiHandles ) {
     py << "from GaudiKernel.GaudiHandles import *\n";
   }
@@ -761,7 +766,7 @@ void configGenerator::pythonizeValue( const PropertyBase* p, string& pvalue, str
     pvalue = cvalue;
     ptype  = "int";
   } else if ( ti == typeIndex<long long>() || ti == typeIndex<unsigned long long>() ) {
-    pvalue = cvalue + "L";
+    pvalue = "long(" + cvalue + ")";
     ptype  = "long";
   } else if ( ti == typeIndex<float>() || ti == typeIndex<double>() ) {
     // forces python to handle this as a float: put a dot in there...
diff --git a/GaudiPython/python/GaudiPython/Bindings.py b/GaudiPython/python/GaudiPython/Bindings.py
index 0351bc2328..e793768e5d 100644
--- a/GaudiPython/python/GaudiPython/Bindings.py
+++ b/GaudiPython/python/GaudiPython/Bindings.py
@@ -28,6 +28,10 @@ except ImportError:
     print("# WARNING: using PyCintex as cppyy implementation")
     import PyCintex as cppyy
 
+if sys.version_info >= (3,):
+    # Python 2 compatibility
+    long = int
+
 if ROOT6WorkAroundEnabled('ROOT-5478'):
     # Trigger the loading of GaudiKernelDict
     cppyy.gbl.DataObject
-- 
GitLab


From 4d0a659d149015411407c9b8573fefd5809182a3 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Mon, 11 Dec 2017 16:30:49 +0100
Subject: [PATCH 36/56] Use Python 3 compatible printing.

---
 Gaudi/tests/qmtest/gaudi.qms/bug_61144.qmt          |  2 +-
 Gaudi/tests/qmtest/gaudi.qms/custom_main_loop.qmt   |  3 ++-
 .../qmtest/gaudi.qms/custom_main_loop_parallel.qmt  |  3 ++-
 GaudiProfiling/scripts/GaudiProfiler                | 13 +++++++------
 4 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/Gaudi/tests/qmtest/gaudi.qms/bug_61144.qmt b/Gaudi/tests/qmtest/gaudi.qms/bug_61144.qmt
index 1e2db6e0ac..a4cf7797ed 100644
--- a/Gaudi/tests/qmtest/gaudi.qms/bug_61144.qmt
+++ b/Gaudi/tests/qmtest/gaudi.qms/bug_61144.qmt
@@ -13,7 +13,7 @@ import Test_confDb # only the _merge_confDb.py in InstallArea/python/* are used
 #------------------------------------------------------------------------------\
 # https://savannah.cern.ch/bugs/?61144
 from Configurables import MyTestTool
-print MyTestTool()
+print(MyTestTool())
 #------------------------------------------------------------------------------/
 
 </text></argument>
diff --git a/Gaudi/tests/qmtest/gaudi.qms/custom_main_loop.qmt b/Gaudi/tests/qmtest/gaudi.qms/custom_main_loop.qmt
index e9b596e8fa..1279162aae 100644
--- a/Gaudi/tests/qmtest/gaudi.qms/custom_main_loop.qmt
+++ b/Gaudi/tests/qmtest/gaudi.qms/custom_main_loop.qmt
@@ -5,11 +5,12 @@
   <text>-v</text>
 </set></argument>
 <argument name="options"><text>
+from __future__ import print_function
 # Options of the test job
 from Gaudi.Configuration import *
 
 def myMainLoop(app, nevt):
-    print "=== Custom Main Loop ==="
+    print("=== Custom Main Loop ===")
     from GaudiPython import gbl
     return gbl.StatusCode(gbl.StatusCode.SUCCESS)
 
diff --git a/Gaudi/tests/qmtest/gaudi.qms/custom_main_loop_parallel.qmt b/Gaudi/tests/qmtest/gaudi.qms/custom_main_loop_parallel.qmt
index 7307251aab..4e4590fd78 100644
--- a/Gaudi/tests/qmtest/gaudi.qms/custom_main_loop_parallel.qmt
+++ b/Gaudi/tests/qmtest/gaudi.qms/custom_main_loop_parallel.qmt
@@ -7,11 +7,12 @@
   <text>1</text>
 </set></argument>
 <argument name="options"><text>
+from __future__ import print_function
 # Options of the test job
 from Gaudi.Configuration import *
 
 def myMainLoop(app, nevt):
-    print "=== Custom Main Loop ==="
+    print("=== Custom Main Loop ===")
     from GaudiPython import gbl
     return True
 
diff --git a/GaudiProfiling/scripts/GaudiProfiler b/GaudiProfiling/scripts/GaudiProfiler
index 60a02ed378..f6f4e43dd4 100755
--- a/GaudiProfiling/scripts/GaudiProfiler
+++ b/GaudiProfiling/scripts/GaudiProfiler
@@ -1,4 +1,5 @@
 #!/usr/bin/env python
+from __future__ import print_function
 
 import os
 import sys
@@ -11,11 +12,11 @@ from subprocess import Popen
 if __name__ == '__main__':
     from PyCPUFamily import CPUFamily
     if 'GAUDIPROFILINGROOT' not in os.environ:
-        print """
+        print("""
             **************************************** ERROR *****************************************
             * GaudiProfiler: Environment variable $GAUDIPROFILINGROOT is missing. Process stopped. *
             ****************************************************************************************
-        """
+        """)
         sys.exit()
     if 'GAUDIPROFILERCONFIG' in os.environ:
         configFile = os.environ['GAUDIPROFILERCONFIG']
@@ -25,7 +26,7 @@ if __name__ == '__main__':
     try:
         conf = ConvertXmlToDict(configFile)
     except xml.parsers.expat.ExpatError:
-        print "Invalid xml file: %s" % configFile
+        print("Invalid xml file: %s" % configFile)
         sys.exit()
     #gaudiRunParams = ' '.join(sys.argv[1:])
     storeResultsAt = conf.PFM_CONFIG.PROPERTIES.OUTPUT_DIR
@@ -51,14 +52,14 @@ if __name__ == '__main__':
         res = Popen(['gaudirun.py'] + sys.argv[1:] + ['--option', 'from %s import generateOptions; generateOptions(%s, %s, %s, %s, %s, %r, %r)' %
                                                       (moduleName, counter, cmask, invmask, sampling_period, startAtEvent, storeResultsAt, family)]).wait()
         if res:
-            print """
+            print("""
             ************************************** ERROR ***************************************
             * GaudiProfiler: PerfMonAuditor failed. Is pfm library and kernel patch installed? *
             ************************************************************************************
-            """
+            """)
             sys.exit(res)
     # post-processing
     os.system("GaudiGenProfilingHtml.exe %s --caa" % storeResultsAt)
     shutil.copy2(os.path.sep.join([os.environ['GAUDIPROFILINGROOT'], 'data',
                                    'sorttable.js']), os.path.sep.join([storeResultsAt, 'HTML']))
-    print "Results:", os.path.sep.join([storeResultsAt, 'HTML', 'index.html'])
+    print("Results:", os.path.sep.join([storeResultsAt, 'HTML', 'index.html']))
-- 
GitLab


From a7ffeda025c40ad07a067fd405d5cca34f66a2b2 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Mon, 11 Dec 2017 16:33:10 +0100
Subject: [PATCH 37/56] Ensure prints are flushed when necessary.

These lines are referenced by test references, and so must appear when
the print statement is made. Adding `flush=True` ensures that this is the
case.
---
 Gaudi/python/Gaudi/Main.py                 | 4 ++--
 Gaudi/scripts/gaudirun.py                  | 2 +-
 GaudiPython/python/GaudiPython/__init__.py | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/Gaudi/python/Gaudi/Main.py b/Gaudi/python/Gaudi/Main.py
index 6abcef0989..dc144d5dc9 100644
--- a/Gaudi/python/Gaudi/Main.py
+++ b/Gaudi/python/Gaudi/Main.py
@@ -250,9 +250,9 @@ class gaudimain(object):
         log.info(msg)
         conf_dict = Configuration.configurationDict(all)
         if old_format:
-            print(self.generateOptsOutput(all))
+            print(self.generateOptsOutput(all), flush=True)
         else:
-            print(self.generatePyOutput(all))
+            print(self.generatePyOutput(all), flush=True)
 
     def writeconfig(self, filename, all=False):
         write = {".pkl": lambda filename, all: self._writepickle(filename),
diff --git a/Gaudi/scripts/gaudirun.py b/Gaudi/scripts/gaudirun.py
index 4ed1b402ee..424fe7eca0 100755
--- a/Gaudi/scripts/gaudirun.py
+++ b/Gaudi/scripts/gaudirun.py
@@ -123,7 +123,7 @@ def getArgsFromQmt(qmtfile):
 if __name__ == "__main__":
     # ensure that we (and the subprocesses) use the C standard localization
     if os.environ.get('LC_ALL') != 'C':
-        print('# setting LC_ALL to "C"')
+        print('# setting LC_ALL to "C"', flush=True)
         os.environ['LC_ALL'] = 'C'
 
     from optparse import OptionParser
diff --git a/GaudiPython/python/GaudiPython/__init__.py b/GaudiPython/python/GaudiPython/__init__.py
index 133584c4e5..e52ffb8302 100644
--- a/GaudiPython/python/GaudiPython/__init__.py
+++ b/GaudiPython/python/GaudiPython/__init__.py
@@ -13,7 +13,7 @@ from __future__ import absolute_import, print_function
 # ensure that we (and the subprocesses) use the C standard localization
 import os
 if os.environ.get('LC_ALL') != 'C':
-    print('# setting LC_ALL to "C"')
+    print('# setting LC_ALL to "C"', flush=True)
     os.environ['LC_ALL'] = 'C'
 
 from .Bindings import *
-- 
GitLab


From 7e2bf81b942b6e7827b25cef718f6c2318f75ad4 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Mon, 11 Dec 2017 16:38:15 +0100
Subject: [PATCH 38/56] Use Python 3 compatible absolute imports.

---
 GaudiKernel/python/GaudiKernel/Configurable.py | 3 ++-
 GaudiPolicy/python/GaudiTesting/QMTTest.py     | 2 +-
 GaudiPolicy/python/GaudiTesting/Run.py         | 2 +-
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/GaudiKernel/python/GaudiKernel/Configurable.py b/GaudiKernel/python/GaudiKernel/Configurable.py
index 6b77443223..39ecbdb78c 100644
--- a/GaudiKernel/python/GaudiKernel/Configurable.py
+++ b/GaudiKernel/python/GaudiKernel/Configurable.py
@@ -1,6 +1,7 @@
 # File: AthenaCommon/python/Configurable.py
 # Author: Wim Lavrijsen (WLavrijsen@lbl.gov)
 # Author: Martin Woudstra (Martin.Woudstra@cern.ch)
+from __future__ import absolute_import
 
 import copy
 import string
@@ -1625,7 +1626,7 @@ def purge():
     # FIXME: (MCl) this is needed because instances of ConfigurableGeneric are not
     #        migrated to the correct class when this is known.
     ConfigurableGeneric.configurables.clear()
-    from ProcessJobOptions import _included_files
+    from .ProcessJobOptions import _included_files
     import os.path
     import sys
     for file in _included_files:
diff --git a/GaudiPolicy/python/GaudiTesting/QMTTest.py b/GaudiPolicy/python/GaudiTesting/QMTTest.py
index 06e17b28cd..6f2aba32a7 100644
--- a/GaudiPolicy/python/GaudiTesting/QMTTest.py
+++ b/GaudiPolicy/python/GaudiTesting/QMTTest.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-from BaseTest import *
+from GaudiTesting.BaseTest import *
 import logging
 import os
 import sys
diff --git a/GaudiPolicy/python/GaudiTesting/Run.py b/GaudiPolicy/python/GaudiTesting/Run.py
index 1204de3179..10ab904934 100644
--- a/GaudiPolicy/python/GaudiTesting/Run.py
+++ b/GaudiPolicy/python/GaudiTesting/Run.py
@@ -3,7 +3,7 @@ from __future__ import print_function
 import os
 import sys
 import xml.sax.saxutils as XSS
-import BaseTest as GT
+from GaudiTesting import BaseTest as GT
 import logging
 
 # FIXME: module alias for backward compatibility
-- 
GitLab


From f92746f4fbcb426f4f1f53e5d0fc92119b4d2ee9 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Tue, 12 Dec 2017 12:27:25 +0100
Subject: [PATCH 39/56] Use a more robust dynamic import method.

Plus, using `exec` for importing is not compatible with Python 3.
---
 GaudiPolicy/python/GaudiTesting/Run.py | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/GaudiPolicy/python/GaudiTesting/Run.py b/GaudiPolicy/python/GaudiTesting/Run.py
index 10ab904934..7233d7a180 100644
--- a/GaudiPolicy/python/GaudiTesting/Run.py
+++ b/GaudiPolicy/python/GaudiTesting/Run.py
@@ -1,5 +1,6 @@
 # -*- coding: utf-8 -*-
 from __future__ import print_function
+import importlib
 import os
 import sys
 import xml.sax.saxutils as XSS
@@ -159,8 +160,8 @@ def main():
             test_module = os.environ.get(
                 'GAUDI_QMTEST_MODULE', 'GaudiTesting.QMTTest')
             test_class = os.environ.get('GAUDI_QMTEST_CLASS', 'QMTTest')
-            exec('from {} import {} as test_class'.format(
-                test_module, test_class))
+
+            test_class = getattr(importlib.import_module(test_module), test_class)
             fileToTest = test_class(filename)
             results = fileToTest.run()
         except Exception as e:
-- 
GitLab


From 8e1a56bd3aa6a3648b910c3f5933ccabea844c8a Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Tue, 12 Dec 2017 12:32:00 +0100
Subject: [PATCH 40/56] Decode bytes objects to strings.

---
 Gaudi/python/Gaudi/Main.py                      | 17 +++++++++++------
 Gaudi/scripts/gaudirun.py                       |  2 +-
 .../tests/qmtest/scripts/test_bug_87340.py      |  1 +
 GaudiPolicy/python/GaudiTesting/BaseTest.py     | 13 ++++++++-----
 4 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/Gaudi/python/Gaudi/Main.py b/Gaudi/python/Gaudi/Main.py
index dc144d5dc9..3095c28b90 100644
--- a/Gaudi/python/Gaudi/Main.py
+++ b/Gaudi/python/Gaudi/Main.py
@@ -33,7 +33,7 @@ class BootstrapHelper(object):
             self.value = value
 
         def __str__(self):
-            return str(self.value)
+            return bytes(self.value).decode('utf-8')
         toString = __str__
 
     class AppMgr(object):
@@ -64,13 +64,13 @@ class BootstrapHelper(object):
             return BootstrapHelper.StatusCode(self.lib.py_bootstrap_fsm_terminate(self.ptr))
 
         def getService(self, name):
-            return self.lib.py_bootstrap_getService(self.ptr, name)
+            return self.lib.py_bootstrap_getService(self.ptr, name.encode('utf-8'))
 
         def setProperty(self, name, value):
-            return BootstrapHelper.StatusCode(self.lib.py_bootstrap_setProperty(self.ptr, name, value))
+            return BootstrapHelper.StatusCode(self.lib.py_bootstrap_setProperty(self.ptr, name.encode('utf-8'), value.encode('utf-8')))
 
         def getProperty(self, name):
-            return BootstrapHelper.Property(self.lib.py_bootstrap_getProperty(self.ptr, name))
+            return BootstrapHelper.Property(self.lib.py_bootstrap_getProperty(self.ptr, name.encode('utf-8')))
 
         def printAlgsSequences(self):
             return self.lib.py_helper_printAlgsSequences(self.ptr)
@@ -346,7 +346,9 @@ class gaudimain(object):
         except KeyError:
             props = {}
         for p, v in props.items():
-            if not _bootstrap.setProperty(msp, p, str(v)):
+            if not _bootstrap.setProperty(msp,
+                                          p.encode('utf-8'),
+                                          str(v).encode('utf-8')):
                 self.log.error('Cannot set property %s.%s to %s', comp, p, v)
                 sys.exit(10)
 
@@ -371,7 +373,10 @@ class gaudimain(object):
                     v = '"%s"' % v  # need double quotes
                 elif type(v) == six.integer_types:
                     v = '%d' % v  # prevent pending 'L'
-                _bootstrap.addPropertyToCatalogue(jos, n, p, str(v))
+                _bootstrap.addPropertyToCatalogue(jos,
+                                                  n.encode('utf-8'),
+                                                  p.encode('utf-8'),
+                                                  str(v).encode('utf-8'))
         if hasattr(Configurable, "_configurationLocked"):
             Configurable._configurationLocked = True
         self.log.debug('basicInit: done')
diff --git a/Gaudi/scripts/gaudirun.py b/Gaudi/scripts/gaudirun.py
index 424fe7eca0..7937f1955a 100755
--- a/Gaudi/scripts/gaudirun.py
+++ b/Gaudi/scripts/gaudirun.py
@@ -95,7 +95,7 @@ def getArgsFromQmt(qmtfile):
             tmp_opts = NamedTemporaryFile(suffix='.py')
         else:
             tmp_opts = NamedTemporaryFile(suffix='.opts')
-        tmp_opts.write(options.text)
+        tmp_opts.write(options.text.encode('utf-8'))
         tmp_opts.flush()
         args.append(tmp_opts.name)
         _qmt_tmp_opt_files.append(tmp_opts)
diff --git a/GaudiKernel/tests/qmtest/scripts/test_bug_87340.py b/GaudiKernel/tests/qmtest/scripts/test_bug_87340.py
index a060ff22da..e1625159d5 100755
--- a/GaudiKernel/tests/qmtest/scripts/test_bug_87340.py
+++ b/GaudiKernel/tests/qmtest/scripts/test_bug_87340.py
@@ -33,6 +33,7 @@ except StopIteration:
 
 nm = Popen(["nm", '-C', lib], stdout=PIPE)
 output, _ = nm.communicate()
+output = output.decode('utf-8')
 
 if nm.returncode:
     print(output)
diff --git a/GaudiPolicy/python/GaudiTesting/BaseTest.py b/GaudiPolicy/python/GaudiTesting/BaseTest.py
index 00249cf71b..417b1dd994 100644
--- a/GaudiPolicy/python/GaudiTesting/BaseTest.py
+++ b/GaudiPolicy/python/GaudiTesting/BaseTest.py
@@ -39,7 +39,7 @@ def dumpProcs(name):
     if 'WORKSPACE' in os.environ:
         p = Popen(['ps', '-fH', '-U', getuser()], stdout=PIPE)
         with open(os.path.join(os.environ['WORKSPACE'], name), 'w') as f:
-            f.write(p.communicate()[0])
+            f.write(p.communicate()[0].decode('utf-8'))
 
 
 def kill_tree(ppid, sig):
@@ -50,7 +50,7 @@ def kill_tree(ppid, sig):
     log = logging.getLogger('kill_tree')
     ps_cmd = ['ps', '--no-headers', '-o', 'pid', '--ppid', str(ppid)]
     get_children = Popen(ps_cmd, stdout=PIPE, stderr=PIPE)
-    children = map(int, get_children.communicate()[0].split())
+    children = map(int, get_children.communicate()[0].decode('utf-8').split())
     for child in children:
         kill_tree(child, sig)
     try:
@@ -103,7 +103,7 @@ class BaseTest(object):
                 optionFile = tempfile.NamedTemporaryFile(suffix='.py')
             else:
                 optionFile = tempfile.NamedTemporaryFile(suffix='.opts')
-            optionFile.file.write(self.options)
+            optionFile.file.write(self.options.encode('utf-8'))
             optionFile.seek(0)
             self.args.append(RationalizePath(optionFile.name))
 
@@ -171,7 +171,10 @@ class BaseTest(object):
                 self.proc = Popen(params, stdout=PIPE, stderr=PIPE,
                                   env=self.environment)
                 logging.debug('(pid: %d)', self.proc.pid)
-                self.out, self.err = self.proc.communicate()
+                out, err = self.proc.communicate()
+                # Use `or ''` as the result is None if there was no output
+                self.out = out.decode('utf-8') or ''
+                self.err = err.decode('utf-8') or ''
 
             thread = threading.Thread(target=target)
             thread.start()
@@ -185,7 +188,7 @@ class BaseTest(object):
                 cmd = ['gdb', '--pid', str(self.proc.pid), '--batch',
                        '--eval-command=thread apply all backtrace']
                 gdb = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
-                self.stack_trace = gdb.communicate()[0]
+                self.stack_trace = gdb.communicate()[0].decode('utf-8')
 
                 kill_tree(self.proc.pid, signal.SIGTERM)
                 thread.join(60)
-- 
GitLab


From de4f3233247a6e947a6015ccd3edf6f203e2a546 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Tue, 12 Dec 2017 12:32:29 +0100
Subject: [PATCH 41/56] Nicer exception logging.

---
 GaudiPolicy/python/GaudiTesting/Run.py | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/GaudiPolicy/python/GaudiTesting/Run.py b/GaudiPolicy/python/GaudiTesting/Run.py
index 7233d7a180..6e8f7abe00 100644
--- a/GaudiPolicy/python/GaudiTesting/Run.py
+++ b/GaudiPolicy/python/GaudiTesting/Run.py
@@ -165,9 +165,7 @@ def main():
             fileToTest = test_class(filename)
             results = fileToTest.run()
         except Exception as e:
-            logging.error(
-                'Exception caught when trying to instantiate qmt test python object')
-            logging.error(e)
+            logging.exception('Exception caught when trying to instantiate qmt test python object')
             return 1
 
     report = globals()[opts.report + '_report']
-- 
GitLab


From 2f8282e0863dba0e75cab86f6ad2c3860e00daee Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex.pearce@cern.ch>
Date: Tue, 12 Dec 2017 12:37:31 +0100
Subject: [PATCH 42/56] Handle missing atexit._exithandlers.

This implementation detail is no longer exposed in Python 3.
---
 GaudiPython/python/GaudiPython/Bindings.py | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/GaudiPython/python/GaudiPython/Bindings.py b/GaudiPython/python/GaudiPython/Bindings.py
index e793768e5d..82d7bdd455 100644
--- a/GaudiPython/python/GaudiPython/Bindings.py
+++ b/GaudiPython/python/GaudiPython/Bindings.py
@@ -996,14 +996,25 @@ class AppMgr(iService):
         if hasattr(Configurable, "_configurationLocked"):
             Configurable._configurationLocked = True
 
-        # Ensure that the exit method is called when exiting from Python
+        self._install_exit_handlers()
+
+    def _install_exit_handlers(self):
+        """Ensure that the exit method is called when exiting from Python, and
+        try to ensure that ROOT doesn't intefere too much."""
         import atexit
         atexit.register(self.exit)
 
+        try:
+            exit_handlers = atexit._exithandlers
+        except AttributeError:
+            # Python 3's atext does not expose _exithandlers, so we can't do
+            # anything more
+            return
+
         # ---Hack to avoid bad interactions with the ROOT exit handler
         # Look for an exit handler installed by ROOT
         root_handler_installed = False
-        for h in atexit._exithandlers:
+        for h in exit_handlers:
             func = h[0]
             if hasattr(func, "__module__") and func.__module__ == "ROOT":
                 root_handler_installed = True
-- 
GitLab


From 184365f8494d2a9a2d29f9c533829d11cf0f412b Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex@alexpearce.me>
Date: Tue, 12 Dec 2017 16:29:21 +0100
Subject: [PATCH 43/56] Set Boost Python library name based on found Python
 version.

---
 GaudiCoreSvc/CMakeLists.txt    | 2 +-
 GaudiExamples/CMakeLists.txt   | 4 ++--
 GaudiProfiling/CMakeLists.txt  | 4 ++--
 cmake/GaudiProjectConfig.cmake | 7 +++++++
 4 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/GaudiCoreSvc/CMakeLists.txt b/GaudiCoreSvc/CMakeLists.txt
index eead21f42d..5d97c03167 100644
--- a/GaudiCoreSvc/CMakeLists.txt
+++ b/GaudiCoreSvc/CMakeLists.txt
@@ -2,7 +2,7 @@ gaudi_subdir(GaudiCoreSvc)
 
 gaudi_depends_on_subdirs(GaudiKernel)
 
-find_package(Boost COMPONENTS system filesystem regex thread python3 REQUIRED)
+find_package(Boost COMPONENTS system filesystem regex thread ${BOOST_PYTHON_LIB_NAME} REQUIRED)
 find_package(TBB REQUIRED)
 find_package(PythonLibs REQUIRED)
 find_package(ROOT REQUIRED)
diff --git a/GaudiExamples/CMakeLists.txt b/GaudiExamples/CMakeLists.txt
index d571d895c8..43552a29ae 100644
--- a/GaudiExamples/CMakeLists.txt
+++ b/GaudiExamples/CMakeLists.txt
@@ -5,7 +5,7 @@ gaudi_depends_on_subdirs(GaudiKernel GaudiUtils GaudiGSL GaudiAlg RootCnv)
 find_package(AIDA)
 find_package(HepPDT)
 find_package(ROOT COMPONENTS Tree RIO Hist Net REQUIRED)
-find_package(Boost COMPONENTS python3 REQUIRED)
+find_package(Boost COMPONENTS ${BOOST_PYTHON_LIB_NAME} REQUIRED)
 find_package(CLHEP)
 find_package(GSL)
 find_package(PythonLibs REQUIRED)
@@ -145,7 +145,7 @@ endif()
 
 if(Boost_PYTHON_FOUND)
   gaudi_add_python_module(PyExample src/PythonModule/*.cpp
-                          LINK_LIBRARIES ${Boost_PYTHON3_LIBRARY}
+                          LINK_LIBRARIES Boost
                           INCLUDE_DIRS Boost PythonLibs)
 endif()
 
diff --git a/GaudiProfiling/CMakeLists.txt b/GaudiProfiling/CMakeLists.txt
index 150b85566b..c19ac48f09 100644
--- a/GaudiProfiling/CMakeLists.txt
+++ b/GaudiProfiling/CMakeLists.txt
@@ -4,7 +4,7 @@ gaudi_depends_on_subdirs(GaudiKernel GaudiAlg)
 
 if (CMAKE_SYSTEM_NAME MATCHES Linux)
 
-find_package(Boost COMPONENTS python3 REQUIRED)
+find_package(Boost COMPONENTS ${BOOST_PYTHON_LIB_NAME} REQUIRED)
 find_package(PythonLibs REQUIRED)
 find_package(unwind)
 find_package(gperftools)
@@ -29,7 +29,7 @@ if(UNWIND_FOUND AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
                    INCLUDE_DIRS unwind ZLIB)
 
   gaudi_add_python_module(PyCPUFamily src/python/CPUFamily.cpp
-                          LINK_LIBRARIES ${Boost_PYTHON3_LIBRARY}
+                          LINK_LIBRARIES Boost
                           INCLUDE_DIRS PythonLibs)
 
   gaudi_add_executable(GaudiGenProfilingHtml src/app/pfm_gen_analysis.cpp
diff --git a/cmake/GaudiProjectConfig.cmake b/cmake/GaudiProjectConfig.cmake
index df542ed8c1..5f60c92c7d 100644
--- a/cmake/GaudiProjectConfig.cmake
+++ b/cmake/GaudiProjectConfig.cmake
@@ -200,6 +200,13 @@ include(BinaryTagUtils)
 
 find_package(PythonInterp 2.7)
 
+# Need to use a version-dependent Boost Python library
+if(${PYTHON_VERSION_MAJOR} EQUAL "3")
+  set(BOOST_PYTHON_LIB_NAME "python3")
+else()
+  set(BOOST_PYTHON_LIB_NAME "python2")
+endif()
+
 #-------------------------------------------------------------------------------
 # gaudi_project(project version
 #               [USE proj1 vers1 [proj2 vers2 ...]]
-- 
GitLab


From 18d1b32c0139744bba4e27c308d5c64a2aba11cc Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex@alexpearce.me>
Date: Wed, 13 Dec 2017 14:55:11 +0100
Subject: [PATCH 44/56] Add missing import.

---
 GaudiPython/python/GaudiPython/Pythonizations.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/GaudiPython/python/GaudiPython/Pythonizations.py b/GaudiPython/python/GaudiPython/Pythonizations.py
index af2d650740..53916d43b8 100644
--- a/GaudiPython/python/GaudiPython/Pythonizations.py
+++ b/GaudiPython/python/GaudiPython/Pythonizations.py
@@ -2,6 +2,8 @@
 # Author: Pere Mato (pere.mato@cern.ch)
 from __future__ import print_function
 
+import six
+
 """ This Pythonizations module provides a number of useful pythonizations
     of adaptation of some classes.
 """
-- 
GitLab


From e84824a325a09c6117ef94666f76e4d57b185a4e Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex@alexpearce.me>
Date: Wed, 13 Dec 2017 14:55:19 +0100
Subject: [PATCH 45/56] Do not create __init__.py files in __pycache__/.

In Python 3, .pyc files are created in the __pycache__ directory. The
Gaudi CMake logic of creating __init__.py in any directory under python/
that doesn't already have one then creates __pycache__/__init__.py. This
is copied to the install area and makes folders `import`-able that
should not be.
---
 cmake/GaudiProjectConfig.cmake | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/cmake/GaudiProjectConfig.cmake b/cmake/GaudiProjectConfig.cmake
index 5f60c92c7d..2aa69c9ab7 100644
--- a/cmake/GaudiProjectConfig.cmake
+++ b/cmake/GaudiProjectConfig.cmake
@@ -2717,6 +2717,7 @@ function(gaudi_install_python_modules)
   file(GLOB sub-dir RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} python/*)
   foreach(dir ${sub-dir})
     if(NOT dir STREQUAL python/.svn
+       AND NOT dir MATCHES "__pycache__"
        AND IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${dir}
        AND NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/__init__.py)
       set(pyfile ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/__init__.py)
@@ -2748,6 +2749,7 @@ function(gaudi_install_scripts)
           PATTERN "CVS" EXCLUDE
           PATTERN ".svn" EXCLUDE
           PATTERN "*~" EXCLUDE
+          PATTERN "__pycache__" EXCLUDE
           PATTERN "*.pyc" EXCLUDE)
 endfunction()
 
-- 
GitLab


From d0c6b22ba51f989e9d22993407261ef8e353c2b7 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex@alexpearce.me>
Date: Wed, 13 Dec 2017 15:40:57 +0100
Subject: [PATCH 46/56] Pass UTF-8 encoded bytes to hashlib.sha1.

This is optional in Python 2, but mandatory in Python 3.
---
 Gaudi/tests/scripts/test_export_oldopts.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Gaudi/tests/scripts/test_export_oldopts.py b/Gaudi/tests/scripts/test_export_oldopts.py
index c0cd278f2b..577569f7d6 100755
--- a/Gaudi/tests/scripts/test_export_oldopts.py
+++ b/Gaudi/tests/scripts/test_export_oldopts.py
@@ -26,7 +26,8 @@ try:
         optfiles = sys.argv[1:]
     else:
         optfiles = ["main.py"]
-    outname = 'out-{0}'.format(sha1(str(optfiles)).hexdigest()[:8])
+    hash = sha1(str(optfiles).encode('utf-8')).hexdigest()
+    outname = 'out-{0}'.format(hash[:8])
 
     # parse the option file and cache the configuration (python only)
     cmd = ["python", which("gaudirun.py"),
-- 
GitLab


From b82f4639ed518b564a996083547b2482f24a4202 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex@alexpearce.me>
Date: Fri, 15 Dec 2017 13:45:59 +0100
Subject: [PATCH 47/56] Use Python 3 compatible boolean cast method.

---
 GaudiKernel/python/GaudiKernel/Configurable.py | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/GaudiKernel/python/GaudiKernel/Configurable.py b/GaudiKernel/python/GaudiKernel/Configurable.py
index 39ecbdb78c..0944a1c695 100644
--- a/GaudiKernel/python/GaudiKernel/Configurable.py
+++ b/GaudiKernel/python/GaudiKernel/Configurable.py
@@ -474,9 +474,12 @@ class Configurable(six.with_metaclass(ConfigurableMeta.ConfigurableMeta, object)
         except (AttributeError, KeyError):
             pass
 
-    def __nonzero__(self):
+    def __bool__(self):
         return True
 
+    # Python 2 compatibility
+    __nonzero__ = __bool__
+
     def remove(self, items):
         if type(items) != list and type(items) != tuple:
             items = [items]
-- 
GitLab


From 35f72150431697890eda83ae0c77852ab1f1b814 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex@alexpearce.me>
Date: Fri, 15 Dec 2017 13:49:33 +0100
Subject: [PATCH 48/56] Use Python 3 compatible exception classes.

An object used in a `raise` statement must inherit from BaseException.
---
 .../gaudiexamples.qms/chronostatsvc.qms/per_event_file.qmt      | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/GaudiExamples/tests/qmtest/gaudiexamples.qms/chronostatsvc.qms/per_event_file.qmt b/GaudiExamples/tests/qmtest/gaudiexamples.qms/chronostatsvc.qms/per_event_file.qmt
index 763683a0ac..c4f45119e6 100644
--- a/GaudiExamples/tests/qmtest/gaudiexamples.qms/chronostatsvc.qms/per_event_file.qmt
+++ b/GaudiExamples/tests/qmtest/gaudiexamples.qms/chronostatsvc.qms/per_event_file.qmt
@@ -36,7 +36,7 @@ if not re.search(expected,stdout):
     causes.append("missing regexp match")
     result["GaudiTest.regexp"] = result.Quote(expected.replace("\\n","\n"))
 
-class Cause:
+class Cause(Exception):
     def __init__(self, msg):
         self.msg = msg
 
-- 
GitLab


From 563de9a4a501a632d106a268cad1b55f55aa328d Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex@alexpearce.me>
Date: Fri, 15 Dec 2017 16:08:28 +0100
Subject: [PATCH 49/56] Use version-agnostic Boost Python variable.

---
 GaudiExamples/CMakeLists.txt   | 2 +-
 cmake/GaudiProjectConfig.cmake | 4 +++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/GaudiExamples/CMakeLists.txt b/GaudiExamples/CMakeLists.txt
index 43552a29ae..99099aecb5 100644
--- a/GaudiExamples/CMakeLists.txt
+++ b/GaudiExamples/CMakeLists.txt
@@ -143,7 +143,7 @@ if(NOT StatusCodeHeaderData_previous STREQUAL StatusCodeHeaderData)
   file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/HackedStatusCode.h" "${StatusCodeHeaderData}")
 endif()
 
-if(Boost_PYTHON_FOUND)
+if(BOOST_PYTHON_LIB_FOUND)
   gaudi_add_python_module(PyExample src/PythonModule/*.cpp
                           LINK_LIBRARIES Boost
                           INCLUDE_DIRS Boost PythonLibs)
diff --git a/cmake/GaudiProjectConfig.cmake b/cmake/GaudiProjectConfig.cmake
index 2aa69c9ab7..3d7945160e 100644
--- a/cmake/GaudiProjectConfig.cmake
+++ b/cmake/GaudiProjectConfig.cmake
@@ -203,8 +203,10 @@ find_package(PythonInterp 2.7)
 # Need to use a version-dependent Boost Python library
 if(${PYTHON_VERSION_MAJOR} EQUAL "3")
   set(BOOST_PYTHON_LIB_NAME "python3")
-else()
+  set(BOOST_PYTHON_LIB_FOUND "YES")
+elseif(${PYTHON_VERSION_MAJOR} EQUAL "2")
   set(BOOST_PYTHON_LIB_NAME "python2")
+  set(BOOST_PYTHON_LIB_FOUND "YES")
 endif()
 
 #-------------------------------------------------------------------------------
-- 
GitLab


From f16d9ddf04cc17e2afe55a8c6ac28c25b9c8a621 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex@alexpearce.me>
Date: Fri, 15 Dec 2017 16:10:11 +0100
Subject: [PATCH 50/56] Don't use xrange.

It's no longer available in Python 3 (range is now a special
class that, amongst other things, implements iteration).
---
 GaudiExamples/scripts/HistoDumpEx.py    |  2 +-
 GaudiExamples/scripts/TupleEx1.py       |  8 ++++----
 GaudiExamples/scripts/TupleEx4.py       | 18 +++++++++---------
 GaudiHive/profiling/plotClonesPyRoot.py |  2 +-
 GaudiHive/profiling/prepareBenchmark.py |  4 ++--
 GaudiMP/python/GaudiMP/GMPBase.py       |  8 ++++----
 GaudiMP/python/GaudiMP/pTools.py        |  8 ++++----
 GaudiMP/scripts/compareOutputFiles.py   |  2 +-
 GaudiMP/scripts/compareRootHistos.py    |  6 +++---
 GaudiPolicy/qmtest_classes/GaudiTest.py |  2 +-
 GaudiProfiling/scripts/GaudiProfiler    |  2 +-
 11 files changed, 31 insertions(+), 31 deletions(-)

diff --git a/GaudiExamples/scripts/HistoDumpEx.py b/GaudiExamples/scripts/HistoDumpEx.py
index 5aa0911f67..a8176f8735 100755
--- a/GaudiExamples/scripts/HistoDumpEx.py
+++ b/GaudiExamples/scripts/HistoDumpEx.py
@@ -13,7 +13,7 @@ h1 = ROOT.TH1D("h1", 'title', 200, -4,  4)
 p1 = ROOT.TProfile("p1", 'title', 200, -4,  4, -10, 10, 's')
 p2 = ROOT.TProfile("p2", 'title', 200, -4,  4, -10, 10)
 
-for i in xrange(0, 1000000):
+for i in range(0, 1000000):
     v = r.gauss(0, 2)
     v2 = r.gauss(0, 2)
     if v < 0:
diff --git a/GaudiExamples/scripts/TupleEx1.py b/GaudiExamples/scripts/TupleEx1.py
index d4eac0169f..cee00d95fe 100755
--- a/GaudiExamples/scripts/TupleEx1.py
+++ b/GaudiExamples/scripts/TupleEx1.py
@@ -145,10 +145,10 @@ class TupleEx1(TupleAlgo):
         # =====================================================================
         tuple3 = self.nTuple(3, "Fixed-size arrays/vectors")
 
-        tuple3.array('arflat', vct([flat() for i in xrange(0, 50)]))
-        tuple3.array('arexpo', vct([expo() for i in xrange(0, 62)]))
-        tuple3.array('argau', vct([gauss() for i in xrange(0, 42)]))
-        t = tuple([gauss() for i in xrange(0, 42)])
+        tuple3.array('arflat', vct([flat() for i in range(0, 50)]))
+        tuple3.array('arexpo', vct([expo() for i in range(0, 62)]))
+        tuple3.array('argau', vct([gauss() for i in range(0, 42)]))
+        t = tuple([gauss() for i in range(0, 42)])
         tuple3.array('argau2', vct(t))
 
         tuple3.write()
diff --git a/GaudiExamples/scripts/TupleEx4.py b/GaudiExamples/scripts/TupleEx4.py
index 0e28ffb3c2..8eca977250 100755
--- a/GaudiExamples/scripts/TupleEx4.py
+++ b/GaudiExamples/scripts/TupleEx4.py
@@ -72,7 +72,7 @@ tup1 = TupleUtils.nTuple("path",  # the path
                          "It is a title for my n-tuple",  # the title
                          LUN='MYLUN1')  # logical unit
 # fill it:
-for i in xrange(0, 5000):
+for i in range(0, 5000):
     tup1.column('i', i)  # int
     tup1.column('g1', gauss())  # double
     tup1.column('g2', gauss())  # double
@@ -91,7 +91,7 @@ tup2 = TupleUtils.nTuple("another/path",  # the path
                          LUN='MYLUN1')  # logical unit
 
 # fill it:
-for i in xrange(0, 1000):
+for i in range(0, 1000):
 
     # Lorentz Vector
     lv1 = Math.PxPyPzEVector(gauss(), gauss(), gauss(), gauss())
@@ -107,7 +107,7 @@ tup3 = TupleUtils.nTuple("another/path",  # the path
                          LUN='MYLUN2')  # logical unit
 
 # fill it:
-for i in xrange(0, 1000):
+for i in range(0, 1000):
 
     # 3D-Vector
     v1 = Math.XYZVector(gauss(), gauss(), gauss())
@@ -123,7 +123,7 @@ tup4 = TupleUtils.nTuple("another/path",  # the path
                          LUN='MYLUN3')  # logical unit
 
 # fill it:
-for i in xrange(0, 1000):
+for i in range(0, 1000):
 
     # 3D-Point
     p1 = Math.XYZPoint(gauss(), gauss(), gauss())
@@ -147,7 +147,7 @@ CLHEP = cpp.CLHEP
 vct2 = CLHEP.HepVector
 
 # fill it!
-for i in xrange(0, 100):
+for i in range(0, 100):
 
     # variable size vector:
     v1 = vct1()
@@ -174,7 +174,7 @@ tup6 = TupleUtils.nTuple("another/path",  # the path
 
 Gaudi = cpp.Gaudi
 
-for i in xrange(0, 10):
+for i in range(0, 10):
 
     v1 = vct1()
     for j in range(0, 5):
@@ -210,7 +210,7 @@ tup7 = TupleUtils.nTuple("another/path",  # the path
                          "N-tuple: FixMatrices",  # the title
                          LUN='MYLUN3')  # logical unit
 
-for i in xrange(0, 100):
+for i in range(0, 100):
 
     m2 = Gaudi.Matrix2x2()
     tup7.matrix("m2", m2)  # Gaudi::Matrix2x2
@@ -238,7 +238,7 @@ tup8 = TupleUtils.nTuple("another/path",  # the path
                          "N-tuple: FixSymMatrices",  # the title
                          LUN='MYLUN2')  # logical unit
 
-for i in xrange(0, 100):
+for i in range(0, 100):
 
     m2 = Gaudi.SymMatrix2x2()
     tup8.matrix("m2", m2)  # Gaudi::SymMatrix2x2
@@ -268,7 +268,7 @@ tup9 = TupleUtils.nTuple("another/path2",  # the path
                          LUN='MYLUN2')  # logical unit
 
 
-for i in xrange(0, 100):
+for i in range(0, 100):
 
     t = cpp.Gaudi.Time()
 
diff --git a/GaudiHive/profiling/plotClonesPyRoot.py b/GaudiHive/profiling/plotClonesPyRoot.py
index c21a41b264..8bc783371b 100644
--- a/GaudiHive/profiling/plotClonesPyRoot.py
+++ b/GaudiHive/profiling/plotClonesPyRoot.py
@@ -69,7 +69,7 @@ def getCountLatexes(vals, xmax):
     max_nclones = int(max(vals, key=getNclones)[1])
 
     latexes = []
-    for i in xrange(1, max_nclones + 1):
+    for i in range(1, max_nclones + 1):
         n_algos = len(
             filter(lambda runtime_nclones: runtime_nclones[1] == i, vals))
         latexes.append(getText(xmax * 1.01,
diff --git a/GaudiHive/profiling/prepareBenchmark.py b/GaudiHive/profiling/prepareBenchmark.py
index fc4095312e..a46e725825 100644
--- a/GaudiHive/profiling/prepareBenchmark.py
+++ b/GaudiHive/profiling/prepareBenchmark.py
@@ -24,8 +24,8 @@ def prepareConfig(template_filename, n_threads=10, n_parallel_events=10, n_paral
 if __name__ == "__main__":
 
     n_threads = 10
-    for n_algos in xrange(1, 11):
-        for n_events in xrange(1, n_algos + 1):
+    for n_algos in range(1, 11):
+        for n_events in range(1, n_algos + 1):
             config = prepareConfig("../options/BrunelScenario.py", n_threads=n_threads,
                                    n_parallel_events=n_events, n_parallel_algorithms=n_algos)
             # config.replace(".py",".log"))
diff --git a/GaudiMP/python/GaudiMP/GMPBase.py b/GaudiMP/python/GaudiMP/GMPBase.py
index ec118d871e..9a692bbb67 100644
--- a/GaudiMP/python/GaudiMP/GMPBase.py
+++ b/GaudiMP/python/GaudiMP/GMPBase.py
@@ -216,7 +216,7 @@ class CollectHistograms(PyAlgorithm):
         # send 100 at a time
         chunk = 100
         reps = len(ks) / chunk + 1
-        for i in xrange(reps):
+        for i in range(reps):
             someKeys = ks[i * chunk: (i + 1) * chunk]
             smalld = dict([(key, self._gmpc.hDict[key]) for key in someKeys])
             self._gmpc.hq.put((self._gmpc.nodeID, smalld))
@@ -308,7 +308,7 @@ class EventCommunicator(object):
         elif self._gmpc.nodeType == 'Worker':
             downstream = 1
 
-        for i in xrange(downstream):
+        for i in range(downstream):
             self.qout.put('FINISHED')
         if self._gmpc.nodeType != 'Writer':
             self.qout.join()
@@ -1469,11 +1469,11 @@ class Coord(object):
         # one queue from Reader-Workers
         rwk = JoinableQueue()
         # one queue from each worker to writer
-        workersWriter = [JoinableQueue() for i in xrange(self.nWorkers)]
+        workersWriter = [JoinableQueue() for i in range(self.nWorkers)]
         d = {}
         d[-1] = (None, rwk)              # Reader
         d[-2] = (workersWriter, None)    # Writer
-        for i in xrange(self.nWorkers):
+        for i in range(self.nWorkers):
             d[i] = (rwk, workersWriter[i])
         return d
 
diff --git a/GaudiMP/python/GaudiMP/pTools.py b/GaudiMP/python/GaudiMP/pTools.py
index 497dcd479a..78ee9a450a 100644
--- a/GaudiMP/python/GaudiMP/pTools.py
+++ b/GaudiMP/python/GaudiMP/pTools.py
@@ -379,7 +379,7 @@ class FileRecordsAgent():
             cob = ob2.containedObjects()[0]
             min = cob.earliest()
             max = cob.latest()
-            for j in xrange(sz):
+            for j in range(sz):
                 cob = ob.containedObjects()[j]
                 self.log.debug('Adding TimeSpanFSR')
                 if cob.earliest() < min:
@@ -408,7 +408,7 @@ class FileRecordsAgent():
         baseLumi = LumiFSR(l)
         # Now deal with the argument Non-empty Keyed Container of LumiFSRs
         nCont = keyedC.numberOfObjects()
-        for i in xrange(nCont):
+        for i in range(nCont):
             obj = keyedC.containedObject(i)
             nextLumi = LumiFSR(obj)
             baseLumi.merge(nextLumi)
@@ -594,7 +594,7 @@ class Syncer(object):
         self.d = {}
         self.manyEvents = manyEvents
 
-        for i in xrange(-2, nWorkers):
+        for i in range(-2, nWorkers):
             self.d[i] = SyncMini(Event(), lastEvent=Event())
             if self.manyEvents:
                 self.limitFirst = firstEvent
@@ -612,7 +612,7 @@ class Syncer(object):
             return sc
 
         # Regular version ----------------------------
-        for i in xrange(0, self.limit, self.step):
+        for i in range(0, self.limit, self.step):
             if self.checkAll():
                 self.log.info('%s : All procs done @ %i s' % (step, i))
                 break
diff --git a/GaudiMP/scripts/compareOutputFiles.py b/GaudiMP/scripts/compareOutputFiles.py
index f8b5474344..d5321c07ae 100755
--- a/GaudiMP/scripts/compareOutputFiles.py
+++ b/GaudiMP/scripts/compareOutputFiles.py
@@ -276,7 +276,7 @@ def compareEvents(s, p):
     # check 3 : check the content
     l = len(sks)
     diffs = []
-    for i in xrange(l):
+    for i in range(l):
         key = sks[i]
         # compare class name
         if s[key][0] == p[key][0]:
diff --git a/GaudiMP/scripts/compareRootHistos.py b/GaudiMP/scripts/compareRootHistos.py
index aa4f20f6d5..aa5afaf391 100755
--- a/GaudiMP/scripts/compareRootHistos.py
+++ b/GaudiMP/scripts/compareRootHistos.py
@@ -159,7 +159,7 @@ def bin2binIdentity(h1, h2):
 
     nbins = getNbins(h1)
     diffbins = 0
-    for ibin in xrange(0, nbins):
+    for ibin in range(0, nbins):
         h1bin = h1.GetBinContent(ibin)
         h2bin = h2.GetBinContent(ibin)
         diffbins += (h1bin != h2bin)
@@ -253,9 +253,9 @@ def compareHistos(t1, t2, state, checkBin2BinIdentity):
             # check for (non-zero sum of bin error) && (non-zero integrals) for K-Test
             sBinError = 0.0
             pBinError = 0.0
-            for i in xrange(sh.GetNbinsX()):
+            for i in range(sh.GetNbinsX()):
                 sBinError += sh.GetBinError(i)
-            for i in xrange(ph.GetNbinsX()):
+            for i in range(ph.GetNbinsX()):
                 pBinError += ph.GetBinError(i)
             sint = sh.Integral()
             pint = ph.Integral()
diff --git a/GaudiPolicy/qmtest_classes/GaudiTest.py b/GaudiPolicy/qmtest_classes/GaudiTest.py
index 69810aa201..ccdb435915 100644
--- a/GaudiPolicy/qmtest_classes/GaudiTest.py
+++ b/GaudiPolicy/qmtest_classes/GaudiTest.py
@@ -1089,7 +1089,7 @@ class GaudiFilterExecutable(qm.executable.Filter):
                     max_fds = os.sysconf("SC_OPEN_MAX")
                 except:
                     max_fds = 256
-                for fd in xrange(max_fds):
+                for fd in range(max_fds):
                     try:
                         os.close(fd)
                     except:
diff --git a/GaudiProfiling/scripts/GaudiProfiler b/GaudiProfiling/scripts/GaudiProfiler
index f6f4e43dd4..8b68fbbb46 100755
--- a/GaudiProfiling/scripts/GaudiProfiler
+++ b/GaudiProfiling/scripts/GaudiProfiler
@@ -44,7 +44,7 @@ if __name__ == '__main__':
         sampling_period = []
         if type([]) != type(es.EVENT):
             es.EVENT = [es.EVENT]
-        for x in xrange(len(es.EVENT)):
+        for x in range(len(es.EVENT)):
             counter.append(es.EVENT[x].NAME)
             cmask.append(es.EVENT[x].CMASK)
             invmask.append(es.EVENT[x].INVMASK)
-- 
GitLab


From 31d710f15e5f25a97281819a1a1d6b195fbdd258 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex@alexpearce.me>
Date: Fri, 15 Dec 2017 17:09:56 +0100
Subject: [PATCH 51/56] More useful assertion messages.

---
 .../return_codes.qms/corrupted_input.qmt                  | 2 +-
 .../tests/qmtest/gaudiexamples.qms/timing_histos.qmt      | 2 ++
 .../python/GaudiPluginService/cpluginsvc.py               | 8 ++++----
 GaudiPolicy/python/GaudiTesting/BaseTest.py               | 6 ++++--
 4 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/GaudiExamples/tests/qmtest/gaudiexamples.qms/return_codes.qms/corrupted_input.qmt b/GaudiExamples/tests/qmtest/gaudiexamples.qms/return_codes.qms/corrupted_input.qmt
index cdd4b261b9..b9b34042d0 100644
--- a/GaudiExamples/tests/qmtest/gaudiexamples.qms/return_codes.qms/corrupted_input.qmt
+++ b/GaudiExamples/tests/qmtest/gaudiexamples.qms/return_codes.qms/corrupted_input.qmt
@@ -14,7 +14,7 @@ shutil.copy('ROOTIO.dst', 'ROOTIO_corrupted.dst')
 
 f = open('ROOTIO_corrupted.dst', 'rb+')
 f.seek(1024)
-f.write('corruption!')
+f.write('corruption!'.encode('utf-8'))
 f.close()
 
 esel = EventSelector()
diff --git a/GaudiExamples/tests/qmtest/gaudiexamples.qms/timing_histos.qmt b/GaudiExamples/tests/qmtest/gaudiexamples.qms/timing_histos.qmt
index bedf98d727..bd520ba1ec 100644
--- a/GaudiExamples/tests/qmtest/gaudiexamples.qms/timing_histos.qmt
+++ b/GaudiExamples/tests/qmtest/gaudiexamples.qms/timing_histos.qmt
@@ -16,6 +16,8 @@ testscript = os.path.join(os.environ['GAUDIEXAMPLESROOT'], 'tests', 'scripts', '
 
 test = Popen(['python', testscript], stdout=PIPE, stderr=PIPE)
 out, err = test.communicate()
+out = out.decode('utf-8')
+err = err.decode('utf-8')
 
 result['root_file_check.returncode'] = str(test.returncode)
 if test.returncode:
diff --git a/GaudiPluginService/python/GaudiPluginService/cpluginsvc.py b/GaudiPluginService/python/GaudiPluginService/cpluginsvc.py
index 091b5c3691..3aad2debc6 100644
--- a/GaudiPluginService/python/GaudiPluginService/cpluginsvc.py
+++ b/GaudiPluginService/python/GaudiPluginService/cpluginsvc.py
@@ -102,19 +102,19 @@ class Factory(ctypes.Structure):
 
     @property
     def name(self):
-        return self._id
+        return self._id.decode('utf-8')
 
     @property
     def library(self):
-        return _lib.cgaudi_factory_get_library(self)
+        return _lib.cgaudi_factory_get_library(self).decode('utf-8')
 
     @property
     def type(self):
-        return _lib.cgaudi_factory_get_type(self)
+        return _lib.cgaudi_factory_get_type(self).decode('utf-8')
 
     @property
     def classname(self):
-        return _lib.cgaudi_factory_get_classname(self)
+        return _lib.cgaudi_factory_get_classname(self).decode('utf-8')
 
     @property
     def properties(self):
diff --git a/GaudiPolicy/python/GaudiTesting/BaseTest.py b/GaudiPolicy/python/GaudiTesting/BaseTest.py
index 417b1dd994..8408b16749 100644
--- a/GaudiPolicy/python/GaudiTesting/BaseTest.py
+++ b/GaudiPolicy/python/GaudiTesting/BaseTest.py
@@ -631,8 +631,10 @@ class Result:
         return self.annotations[key]
 
     def __setitem__(self, key, value):
-        assert isinstance(key, six.string_types)
-        assert isinstance(value, six.string_types)
+        assert isinstance(key, six.string_types), \
+               'expected {0!r} to be of string type'.format(key)
+        assert isinstance(value, six.string_types), \
+               'expected {0!r} to be of string type'.format(value)
         self.annotations[key] = value
 
     def Quote(self, string):
-- 
GitLab


From 904582961e3eaaf793eab6eba8d3b65a39abf0ac Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex@alexpearce.me>
Date: Fri, 15 Dec 2017 17:14:27 +0100
Subject: [PATCH 52/56] Use sorting method compatible with both iterators and
 lists.

---
 GaudiExamples/tests/qmtest/gaudiexamples.qms/metadatasvc.qmt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/GaudiExamples/tests/qmtest/gaudiexamples.qms/metadatasvc.qmt b/GaudiExamples/tests/qmtest/gaudiexamples.qms/metadatasvc.qmt
index 1fd67e676f..5646692bcf 100644
--- a/GaudiExamples/tests/qmtest/gaudiexamples.qms/metadatasvc.qmt
+++ b/GaudiExamples/tests/qmtest/gaudiexamples.qms/metadatasvc.qmt
@@ -20,7 +20,7 @@ stdout = filter(str.strip,
                 takewhile(str.strip,
                           islice(dropwhile(lambda l: 'Metadata collected:' not in l,
                                  stdout.splitlines()), 1, None)))
-stdout.sort()
+stdout = sorted(stdout)
 from subprocess import check_output, CalledProcessError
 try:
     info = eval(check_output(['dumpMetaData', 'TupleEx.root']))
-- 
GitLab


From d8ba8f074fd8379f0ad0574f6924564edf28dc91 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex@alexpearce.me>
Date: Fri, 15 Dec 2017 17:14:53 +0100
Subject: [PATCH 53/56] Use Python 3 compatible __new__ call.

Consider the following class definition:

    >>> class Foo(object):
    ...     def __new__(cls, name, **kwargs):
    ...         return super(Foo, cls).__new__(cls, name, **kwargs)
    ...
    ...     def __init__(self, name, **kwargs):
    ...         print(name, kwargs)
    ...

In Python 2, this works:

    >>> _ = Foo('MyFoo)'
    ('MyFoo', {})

It doesn't in Python 3:

    >>> _ = Foo('MyFoo')
    Traceback (most recent call last):
    File "tst.py", line 8, in <module>
      Foo('MyFoo')
    File "tst.py", line 3, in __new__
      return super(Foo, cls).__new__(cls, name, **kwargs)
    TypeError: object() takes no parameters

What does work is to not explicitly forward the `name, **kwargs`
arguments to the `super` class's `__new__` method, as this is done
implicitly.

    >>> class Foo(object):
    ...     def __new__(cls, name, **kwargs):
    ...         return super(Foo, cls).__new__(cls)
    ...
    ...     def __init__(self, name, **kwargs):
    ...         print(name, kwargs)
    ...

In Python 2 (2.6 and 2.7, at least):

    >>> _ = Foo('MyFoo)'
    ('MyFoo', {})

In Python 3:

    >>> _ = Foo('MyFoo)'
    'MyFoo' {}
---
 GaudiKernel/python/GaudiKernel/Configurable.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/GaudiKernel/python/GaudiKernel/Configurable.py b/GaudiKernel/python/GaudiKernel/Configurable.py
index 0944a1c695..cb844fb259 100644
--- a/GaudiKernel/python/GaudiKernel/Configurable.py
+++ b/GaudiKernel/python/GaudiKernel/Configurable.py
@@ -1724,7 +1724,7 @@ class SuperAlgorithm(ControlFlowNode):
                      type(instance).__name__)
             return instance
         else:
-            instance = super(SuperAlgorithm, cls).__new__(cls, name, **kwargs)
+            instance = super(SuperAlgorithm, cls).__new__(cls)
             Configurable.allConfigurables[name] = instance
             return instance
 
-- 
GitLab


From 8d00715f78b823c5ceee63fdbaccda72df52a406 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex@alexpearce.me>
Date: Mon, 18 Dec 2017 07:32:32 +0100
Subject: [PATCH 54/56] Treat files as byte streams.

---
 GaudiPolicy/scripts/ZipPythonDir.py | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/GaudiPolicy/scripts/ZipPythonDir.py b/GaudiPolicy/scripts/ZipPythonDir.py
index ec8f4edac3..fe87e57eac 100755
--- a/GaudiPolicy/scripts/ZipPythonDir.py
+++ b/GaudiPolicy/scripts/ZipPythonDir.py
@@ -11,7 +11,7 @@ import stat
 import time
 import re
 import codecs
-from io import StringIO
+from io import BytesIO
 
 # Class for generic exception coming from the zipdir() function
 
@@ -106,7 +106,7 @@ def checkEncoding(fileObj):
     # find the encoding of the file, if specified (in the first two lines)
     enc_exp = re.compile(r"coding[:=]\s*([-\w.]+)")
     for l in islice(fileObj, 2):
-        m = enc_exp.search(l)
+        m = enc_exp.search(l.decode('ascii'))
         if m:
             enc = m.group(1)
             break
@@ -151,7 +151,7 @@ def zipdir(directory, no_pyc=False):
             infolist = []
         (added, modified, untouched, removed) = _zipChanges(directory, infolist)
         if added or modified or removed:
-            tempBuf = StringIO()
+            tempBuf = BytesIO()
             z = zipfile.PyZipFile(tempBuf, "w", zipfile.ZIP_DEFLATED)
             for f in added + modified + untouched:
                 src = os.path.join(directory, f)
-- 
GitLab


From 651b67f92d66694effb466547056eeaaa4b52ef2 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex@alexpearce.me>
Date: Thu, 5 Apr 2018 10:05:18 +0200
Subject: [PATCH 55/56] Don't require Python 2.7.

---
 cmake/GaudiProjectConfig.cmake | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cmake/GaudiProjectConfig.cmake b/cmake/GaudiProjectConfig.cmake
index 3d7945160e..3c85bd8b4d 100644
--- a/cmake/GaudiProjectConfig.cmake
+++ b/cmake/GaudiProjectConfig.cmake
@@ -198,7 +198,7 @@ include(CMakeParseArguments)
 include(CMakeFunctionalUtils)
 include(BinaryTagUtils)
 
-find_package(PythonInterp 2.7)
+find_package(PythonInterp)
 
 # Need to use a version-dependent Boost Python library
 if(${PYTHON_VERSION_MAJOR} EQUAL "3")
-- 
GitLab


From ee3245efad0df70262bfbca12eb59858a1cbcb96 Mon Sep 17 00:00:00 2001
From: Alex Pearce <alex@alexpearce.me>
Date: Wed, 24 Oct 2018 15:19:20 +0200
Subject: [PATCH 56/56] TEST: Don't require RELAX.

RELAX isn't available in LGC_93python3, only LCG_93. Of course!
---
 GaudiExamples/CMakeLists.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/GaudiExamples/CMakeLists.txt b/GaudiExamples/CMakeLists.txt
index 99099aecb5..9f7f0c4319 100644
--- a/GaudiExamples/CMakeLists.txt
+++ b/GaudiExamples/CMakeLists.txt
@@ -9,7 +9,7 @@ find_package(Boost COMPONENTS ${BOOST_PYTHON_LIB_NAME} REQUIRED)
 find_package(CLHEP)
 find_package(GSL)
 find_package(PythonLibs REQUIRED)
-find_package(RELAX REQUIRED)
+find_package(RELAX)
 find_package(TBB REQUIRED)
 # ROOT runtime
 find_package(PNG REQUIRED)
-- 
GitLab