diff --git a/Tools/PyUtils/python/AthFile/impl.py b/Tools/PyUtils/python/AthFile/impl.py
index 8f48be83dc92a8386ea260fdc4c535add380503c..da4ae92c8469b19e7edd570a7e40e4818d787f7a 100644
--- a/Tools/PyUtils/python/AthFile/impl.py
+++ b/Tools/PyUtils/python/AthFile/impl.py
@@ -1280,14 +1280,14 @@ class FilePeeker(object):
         beam_type   = '<beam-type N/A>'
         try:
             beam_type = data_reader.beamType()
-        except Exception as err:
+        except Exception:
             msg.warning ("problem while extracting beam-type information")
             pass
 
         beam_energy = '<beam-energy N/A>'
         try:
             beam_energy = data_reader.beamEnergy()
-        except Exception as err:
+        except Exception:
             msg.warning ("problem while extracting beam-type information")
             pass
 
diff --git a/Tools/PyUtils/python/AthFileLite.py b/Tools/PyUtils/python/AthFileLite.py
index 5f76fceb26dd22fdd556938f37de62b5ddfbe605..c70736871065f5acd71bfcf63640c82d4b1b7489 100644
--- a/Tools/PyUtils/python/AthFileLite.py
+++ b/Tools/PyUtils/python/AthFileLite.py
@@ -198,13 +198,13 @@ class AthBSFile(object):
         beam_type   = '<beam-type N/A>'
         try:
             beam_type = data_reader.beamType()
-        except Exception as err:
+        except Exception:
             msg.warning ("problem while extracting beam-type information")
 
         beam_energy = '<beam-energy N/A>'
         try:
             beam_energy = data_reader.beamEnergy()
-        except Exception as err:
+        except Exception:
             msg.warning ("problem while extracting beam-type information")
 
         bs = ef.istream(fname)
diff --git a/Tools/PyUtils/python/Logging.py b/Tools/PyUtils/python/Logging.py
index 974b9462c373fd170b36af7115761432dc1d7270..5459479b4db34a8e5bff7a9841073fb256fa4271 100644
--- a/Tools/PyUtils/python/Logging.py
+++ b/Tools/PyUtils/python/Logging.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 
 ## @author: Sebastien Binet
 ## @file :  PyUtils/python/Logging.py
@@ -27,7 +27,7 @@ except ImportError:
         if self.manager.disable >= logging.VERBOSE:
             return
         if logging.VERBOSE >= self.getEffectiveLevel():
-            apply(self._log, (logging.VERBOSE, msg, args), kwargs)
+            self._log(logging.VERBOSE, msg, args, **kwargs)
     cls.verbose = verbose
     del verbose
     
diff --git a/Tools/PyUtils/python/MetaReader.py b/Tools/PyUtils/python/MetaReader.py
index 588fa40ef7d5373665d8decd9979fce0e5220062..3d6992790a3104f43876cd607c0f1139bb2770ba 100644
--- a/Tools/PyUtils/python/MetaReader.py
+++ b/Tools/PyUtils/python/MetaReader.py
@@ -500,9 +500,9 @@ def _extract_fields_iovpc(value):
         elif type_idx == 8:
             attr_value = int(value.m_unsignedLong[obj_idx])
         elif type_idx == 9:
-            attr_value = long(value.m_longLong[obj_idx])
+            attr_value = int(value.m_longLong[obj_idx])
         elif type_idx == 10:
-            attr_value = long(value.m_unsignedLongLong[obj_idx])
+            attr_value = int(value.m_unsignedLongLong[obj_idx])
         elif type_idx == 11:
             attr_value = float(value.m_float[obj_idx])
         elif type_idx == 12:
@@ -519,9 +519,9 @@ def _extract_fields_iovpc(value):
                 attr_value = attr_value.replace('_', '/')
             # Now it is clean
         elif type_idx == 15:
-            attr_value = long(value.m_date[obj_idx])
+            attr_value = int(value.m_date[obj_idx])
         elif type_idx == 16:
-            attr_value = long(value.m_timeStamp[obj_idx])
+            attr_value = int(value.m_timeStamp[obj_idx])
         else:
             raise ValueError('Unknown type id {0} for attribute {1}'.format(type_idx, attr_name))
 
diff --git a/Tools/PyUtils/python/PoolFile.py b/Tools/PyUtils/python/PoolFile.py
index 371e686ade1c04f21c26350ba3747b8f5ab03eb2..50d6e1262bfd8c212af65913cf08438c6458c086 100644
--- a/Tools/PyUtils/python/PoolFile.py
+++ b/Tools/PyUtils/python/PoolFile.py
@@ -27,6 +27,7 @@ __all__ = [
 import sys
 import os
 import shelve
+from builtins import range
 
 if six.PY2:
     from whichdb import whichdb
@@ -65,10 +66,10 @@ class PoolFileCatalog(object):
             # chase poolfilecatalog location
             catalog = os.environ.get("POOL_CATALOG", self.DefaultCatalog)
 
-        if isinstance(catalog, basestring):
+        if isinstance(catalog, str):
             catalog = [catalog]
             
-        if not isinstance (catalog, (basestring, list)):
+        if not isinstance (catalog, (str, list)):
             raise TypeError(
                 "catalog contact string should be a string or a list thereof! (got %r)"%
                 type(catalog))
@@ -367,12 +368,12 @@ def extract_streams_from_tag (fname,
     #  [CLID=72FBBC6F-C8BE-4122-8790-DC627696C176]\
     #  [TECH=00000202]\
     #  [OID=0000008C-000002BA]'
-    token = re.compile (r'[[]DB=(?P<FID>.*?)[]]'\
-                        r'[[]CNT=(?P<CNT>.*?)[]]'\
-                        r'[[]CLID=(?P<CLID>.*?)[]]'\
-                        r'[[]TECH=(?P<TECH>.*?)[]]'\
+    token = re.compile (r'[[]DB=(?P<FID>.*?)[]]'
+                        r'[[]CNT=(?P<CNT>.*?)[]]'
+                        r'[[]CLID=(?P<CLID>.*?)[]]'
+                        r'[[]TECH=(?P<TECH>.*?)[]]'
                         r'[[]OID=(?P<OID>.*?)[]]')
-    for i in xrange(nentries):
+    for i in range(nentries):
         t.GetEntry (i)
         for ref in stream_refs:
             try:
diff --git a/Tools/PyUtils/python/scripts/ath_dump.py b/Tools/PyUtils/python/scripts/ath_dump.py
index 175df4e6aa7a05bb3a712b53eda09aef29ef1f79..24614a71c1ce6c9a927f4ef61ac2d3b4085dddd3 100644
--- a/Tools/PyUtils/python/scripts/ath_dump.py
+++ b/Tools/PyUtils/python/scripts/ath_dump.py
@@ -31,7 +31,7 @@ def main(args):
     """
     exitcode = 0
     fnames = args.files
-    if isinstance(fnames, basestring):
+    if isinstance(fnames, str):
         fnames = [fnames]
 
     import sys
diff --git a/Tools/PyUtils/python/scripts/check_file.py b/Tools/PyUtils/python/scripts/check_file.py
index 1ec1321bc5f5121b6af72fee54035189d1b94087..1e80db1102af116e41709915100bfd8451f688aa 100644
--- a/Tools/PyUtils/python/scripts/check_file.py
+++ b/Tools/PyUtils/python/scripts/check_file.py
@@ -43,7 +43,7 @@ def main(args):
     """read a POOL file and dump its content.
     """
     files = args.files
-    if isinstance(files, basestring):
+    if isinstance(files, str):
         files=[files]
 
     import sys
diff --git a/Tools/PyUtils/python/scripts/check_sg.py b/Tools/PyUtils/python/scripts/check_sg.py
index e9b49c24cac6809bccf450aad504d801ca929b78..26c4265ed3431c70ffaff118f8d3de51da4b8ae6 100644
--- a/Tools/PyUtils/python/scripts/check_sg.py
+++ b/Tools/PyUtils/python/scripts/check_sg.py
@@ -35,7 +35,7 @@ def main(args):
      $ check-sg LFN:ttbar.pool
     """
     files = args.files
-    if isinstance(files, basestring):
+    if isinstance(files, str):
         files = [files]
 
     import os
diff --git a/Tools/PyUtils/python/scripts/cmake_depends.py b/Tools/PyUtils/python/scripts/cmake_depends.py
index 44da437d98c0caeeede96e23134f0bd1fc536e46..b0ab8de345e6727afe86b2971639be0f6bdeca8d 100644
--- a/Tools/PyUtils/python/scripts/cmake_depends.py
+++ b/Tools/PyUtils/python/scripts/cmake_depends.py
@@ -20,7 +20,10 @@ import argparse
 try:
    import pygraphviz
 except ImportError:
-   sys.path.append('/cvmfs/sft.cern.ch/lcg/nightlies/dev4/Tue/pygraphviz/1.5/x86_64-centos7-gcc8-opt/lib/python2.7/site-packages/')
+   if sys.version_info[0]==2:
+      sys.path.append('/cvmfs/sft.cern.ch/lcg/nightlies/dev4/Tue/pygraphviz/1.5/x86_64-centos7-gcc8-opt/lib/python2.7/site-packages/')
+   else:
+      sys.path.append('/cvmfs/sft.cern.ch/lcg/nightlies/dev3python3/Tue/pygraphviz/1.5/x86_64-centos7-gcc8-opt/lib/python3.7/site-packages')
    import pygraphviz
 
 #
diff --git a/Tools/PyUtils/python/scripts/filter_files.py b/Tools/PyUtils/python/scripts/filter_files.py
index ad9336e5fa6961651d4c6c64877460ebbff94678..4c93e976cb0d92708209a647f045af2fb1cf74c9 100644
--- a/Tools/PyUtils/python/scripts/filter_files.py
+++ b/Tools/PyUtils/python/scripts/filter_files.py
@@ -62,9 +62,9 @@ def main(args):
                     continue
                 l = line.strip().split()
                 if len(l)==1: # assume this is only the event number
-                    runnbr, evtnbr = None, long(l[0])
+                    runnbr, evtnbr = None, int(l[0])
                 elif len(l)==2: # a pair (run,evt) number
-                    runnbr, evtnbr = long(l[0]), long(l[1])
+                    runnbr, evtnbr = int(l[0]), int(l[1])
                 else:
                     raise RuntimeError(
                         'file [%s] has invalid format at line:\n%r' %
@@ -83,21 +83,21 @@ def main(args):
         
         selection = []
         for item in args.selection:
-            if not isinstance(item, (tuple, list, int, long)):
+            if not isinstance(item, (tuple, list, int, int)):
                 raise TypeError('type: %r' % type(item))
 
             if isinstance(item, (tuple, list)):
                 if len(item) == 1:
-                    runnbr, evtnbr = None, long(item[0])
+                    runnbr, evtnbr = None, int(item[0])
                 elif len(item) == 2:
-                    runnbr, evtnbr = long(item[0]), long(item[1])
+                    runnbr, evtnbr = int(item[0]), int(item[1])
                 else:
                     raise RuntimeError(
                         'item [%s] has invalid arity (%s)' %
                         (item, len(item))
                         )
             else:
-                runnbr, evtnbr = None, long(item)
+                runnbr, evtnbr = None, int(item)
             selection.append((runnbr, evtnbr))
 
     # put back the massaged selection into our workspace
diff --git a/Tools/PyUtils/python/scripts/jira_issues.py b/Tools/PyUtils/python/scripts/jira_issues.py
index c5fa55d513a21788eb6f56295c7f0672a9fba9b1..e4286531613ecf283ad3fb3308d23a51bdcdfe71 100644
--- a/Tools/PyUtils/python/scripts/jira_issues.py
+++ b/Tools/PyUtils/python/scripts/jira_issues.py
@@ -60,7 +60,7 @@ def main(args):
 
     #authentication
     try: 
-        cookiesFile = file(args.cookies, 'r')
+        cookiesFile = open(args.cookies, 'r')
         cookies = {}
         for line in cookiesFile:
             text = line.split()
diff --git a/Tools/PyUtils/python/xmldict.py b/Tools/PyUtils/python/xmldict.py
index df8b48e2201c96198c1c075698482d8759017a7a..9d2a6a01448113f49ef6f18486a1c4a8df2bca54 100644
--- a/Tools/PyUtils/python/xmldict.py
+++ b/Tools/PyUtils/python/xmldict.py
@@ -57,12 +57,12 @@ class XmlDictObject(dict):
     
     ## def __getitem__(self, item):
     ##     o = dict.__getitem__(self, item)
-    ##     if isinstance(o, basestring):
+    ##     if isinstance(o, str):
     ##         return _xml_unescape(o)
     ##     return o
 
     ## def __setitem__(self, item, value):
-    ##     if isinstance(value, basestring):
+    ##     if isinstance(value, str):
     ##         value = _xml_unescape(value)
     ##     dict.__setitem__(self, item, value)
         
@@ -100,7 +100,7 @@ def _dict2xml_recurse(parent, dictitem):
 
     if isinstance(dictitem, dict):
         for (tag, child) in dictitem.iteritems():
-            if isinstance(child, basestring):
+            if isinstance(child, str):
                 child = _xml_escape(child)
             if str(tag) == '_text':
                 parent.text = str(child)
@@ -128,13 +128,13 @@ def _xml2dict_recurse (node, dictclass):
     
     if len(node.items()) > 0:
         # if we have attributes, set them
-        nodedict.update(dict((k, _xml_unescape(v) if isinstance(v, basestring) else v)
+        nodedict.update(dict((k, _xml_unescape(v) if isinstance(v, str) else v)
                              for k,v in node.items()))
     
     for child in node:
         # recursively add the element's children
         newitem = _xml2dict_recurse (child, dictclass)
-        if isinstance(newitem, basestring):
+        if isinstance(newitem, str):
             newitem = _xml_unescape(newitem)
         if child.tag in nodedict:
             # found duplicate tag, force a list
diff --git a/Tools/PyUtils/share/flake8_OutputLevel.ref b/Tools/PyUtils/share/flake8_OutputLevel.ref
deleted file mode 100644
index e48d4980e4e4795ae1911a6ee313887ccc7d6366..0000000000000000000000000000000000000000
--- a/Tools/PyUtils/share/flake8_OutputLevel.ref
+++ /dev/null
@@ -1,3 +0,0 @@
-flake8_OutputLevel.py:10:7: ATL900: Do not assign an explicit OutputLevel
-flake8_OutputLevel.py:14:1: ATL900: Do not assign an explicit OutputLevel
-flake8_OutputLevel.py:16:1: ATL900: Do not assign an explicit OutputLevel
diff --git a/Tools/PyUtils/share/flake8_logging.ref b/Tools/PyUtils/share/flake8_logging.ref
deleted file mode 100644
index 11d7905ec8e6d7c01b71800fbfb8353c3d79b560..0000000000000000000000000000000000000000
--- a/Tools/PyUtils/share/flake8_logging.ref
+++ /dev/null
@@ -1,6 +0,0 @@
-flake8_logging.py:11:39: ATL100: use lazy string formatting in logging calls (',' instead of '%')
-flake8_logging.py:13:37: ATL100: use lazy string formatting in logging calls (',' instead of '%')
-flake8_logging.py:15:43: ATL100: use lazy string formatting in logging calls (',' instead of '%')
-flake8_logging.py:19:1: ATL901: use 'AthenaCommon.Logging' instead of 'print'
-flake8_logging.py:21:1: ATL233: Python 3.x incompatible use of non function-like print statement
-flake8_logging.py:21:1: ATL901: use 'AthenaCommon.Logging' instead of 'print'
diff --git a/Tools/PyUtils/share/flake8_print_statement.ref b/Tools/PyUtils/share/flake8_print_statement.ref
deleted file mode 100644
index 7edfb3be9a1c52986df545ff924ed8a8c06798ac..0000000000000000000000000000000000000000
--- a/Tools/PyUtils/share/flake8_print_statement.ref
+++ /dev/null
@@ -1,3 +0,0 @@
-flake8_print_statement.py:6:1: ATL233: Python 3.x incompatible use of non function-like print statement
-flake8_print_statement.py:8:1: ATL232: Python 3.x incompatible use of print statement
-flake8_print_statement.py:11:1: ATL232: Python 3.x incompatible use of print statement
diff --git a/Tools/PyUtils/test/PyUtils.xml b/Tools/PyUtils/test/PyUtils.xml
deleted file mode 100644
index c05d27a91bf1531035262d7425695991c2b5e77d..0000000000000000000000000000000000000000
--- a/Tools/PyUtils/test/PyUtils.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0"?>
-<atn>
-    <TEST name="PyUtilsTest" type="makecheck" suite="Tests">
-       <package>Tools/PyUtils</package>
-       <author> scott snyder </author>
-       <mailto> snyder@bnl.gov </mailto>
-       <expectations>
-          <errorMessage>Athena exited abnormally</errorMessage>
-          <errorMessage>differ</errorMessage>
-          <warningMessage> # WARNING_MESSAGE : post.sh> ERROR</warningMessage>
-          <successMessage>check ok</successMessage>
-          <returnValue>0</returnValue>
-       </expectations>
-    </TEST>
-</atn>