Description: Use 2to3 to port from Python2 to Python3
Bug-Debian: https://bugs.debian.org/937262
Author: Andreas Tille <tille@debian.org>
Last-Update: Thu, 12 Dec 2019 15:41:47 +0100

--- a/SConscript-error.py
+++ b/SConscript-error.py
@@ -67,11 +67,11 @@
     
     status, failures_message = build_status()
     if status == 'failed':
-        print
-        print "FAILED!!!!"  # could display alert, ring bell, etc.
+        print()
+        print("FAILED!!!!")  # could display alert, ring bell, etc.
     elif status == 'ok':
-        print
-        print "Build succeeded."
-    print failures_message
+        print()
+        print("Build succeeded.")
+    print(failures_message)
 
 atexit.register(display_build_status)
\ No newline at end of file
--- a/SConscript-install.py
+++ b/SConscript-install.py
@@ -102,7 +102,7 @@
 	
 Alias('install', env.Command(env['PREFIX']+'tmp', None,
 							[Mkdir('$TARGET'),
-			 				Chmod('$TARGET', 0777)]))
+			 				Chmod('$TARGET', 0o777)]))
 
 #Testing stuff to test installed pdb2pqr	
 for dir_name in ('tests/',
--- a/SConscript-main.py
+++ b/SConscript-main.py
@@ -166,13 +166,13 @@
 #Set up regex to alternately clear tags or wipe sections
 if env['OPAL'] == '':
     #Not using opal for pdb2pqr.
-    print "not using opal", env['OPAL']
+    print("not using opal", env['OPAL'])
     withOpalRegex = r'@WITHOPAL@.*?@WITHOPAL@'
     withoutOpalRegex = '@WITHOUTOPAL@'
 
 else:
     #Using opal for pdb2pqr.
-    print "using opal", env['OPAL']
+    print("using opal", env['OPAL'])
     withOpalRegex = '@WITHOPAL@'
     withoutOpalRegex = r'@WITHOUTOPAL@.*?@WITHOUTOPAL@'
 
@@ -184,7 +184,7 @@
                   withOpalRegex:'',
                   withoutOpalRegex:''}
 
-chmodAction = Chmod('$TARGET', 0755)
+chmodAction = Chmod('$TARGET', 0o755)
 serverHtmlCopySub = CopySub('$TARGET', '$SOURCE', serverHtmlDict, useRegex=True)
 normalCopySub = CopySub('$TARGET', '$SOURCE', replacementDict, useRegex=False)
 
@@ -217,7 +217,7 @@
     try:
         import numpy
     except ImportError:
-        print 'WARNING: PDB2PKA build skipped, numpy not installed. Ligand support will not be available.'
+        print('WARNING: PDB2PKA build skipped, numpy not installed. Ligand support will not be available.')
         numpy_error = True
 
     if not numpy_error:
@@ -234,9 +234,9 @@
         compile_targets.append(algorithms_pyc)
 
         if os.name == 'nt':
-            alg_msvs_env = env.Clone(MSVSBUILDCOM='cd .. && '+pythonBin+' scons/scons.py algorithms DEBUG=True',
-                                     MSVSCLEANCOM='cd .. && '+pythonBin+' scons/scons.py -c algorithms',
-                                     MSVSREBUILDCOM='cd .. && '+pythonBin+' scons/scons.py -c algorithms && '+pythonBin+' scons/scons.py algorithms DEBUG=True')
+            alg_msvs_env = env.Clone(MSVSBUILDCOM='cd .. && scons algorithms DEBUG=True',
+                                     MSVSCLEANCOM='cd .. && scons -c algorithms',
+                                     MSVSREBUILDCOM='cd .. && scons -c algorithms && scons algorithms DEBUG=True')
 
             algorithms_project = alg_msvs_env.MSVSProject(target = 'msvs/Algorithms' + env['MSVSPROJECTSUFFIX'],
                                                           auto_build_solution=0,
@@ -259,9 +259,9 @@
         compile_targets.append(pmc_pyc)
 
         if os.name == 'nt':
-            pmc_msvs_env = env.Clone(MSVSBUILDCOM='cd .. && '+pythonBin+' scons/scons.py pmc_mult DEBUG=True'+build_swig,
-                                     MSVSCLEANCOM='cd .. && '+pythonBin+' scons/scons.py -c pmc_mult',
-                                     MSVSREBUILDCOM='cd .. && '+pythonBin+' scons/scons.py -c pmc_mult && '+pythonBin+' scons/scons.py pmc_mult DEBUG=True'+build_swig)
+            pmc_msvs_env = env.Clone(MSVSBUILDCOM='cd .. && scons pmc_mult DEBUG=True'+build_swig,
+                                     MSVSCLEANCOM='cd .. && scons -c pmc_mult',
+                                     MSVSREBUILDCOM='cd .. && scons -c pmc_mult && scons pmc_mult DEBUG=True'+build_swig)
 
             pmc_mult_project = pmc_msvs_env.MSVSProject(target = 'msvs/pMC_mult' + env['MSVSPROJECTSUFFIX'],
                                                         auto_build_solution=0,
@@ -285,65 +285,65 @@
 SConscript('SConscript-error.py')
 
 def print_default_message(target_list):
-    target_list = map(str, target_list)
+    target_list = list(map(str, target_list))
     if any('test' in x for x in target_list):
         return
     if GetOption("clean"):
         return
     if not GetOption("help"):
 
-        print
-        print 'TARGETS:', target_list
-        print
-        print '========================'
-        print 'Configuration Parameters'
-        print '========================'
-        print
-        print 'Version:', productVersion
-        print 'Install directory:', env['PREFIX']
+        print()
+        print('TARGETS:', target_list)
+        print()
+        print('========================')
+        print('Configuration Parameters')
+        print('========================')
+        print()
+        print('Version:', productVersion)
+        print('Install directory:', env['PREFIX'])
         if numpy_error:
-            print
-            print 'WARNING: PDB2PKA build skipped, numpy not installed. Ligand support will not be available.'
-            print
+            print()
+            print('WARNING: PDB2PKA build skipped, numpy not installed. Ligand support will not be available.')
+            print()
         else:
-            print 'pdb2pka and ligand support:', env['BUILD_PDB2PKA']
-        print 'Path to the website directory:', url
+            print('pdb2pka and ligand support:', env['BUILD_PDB2PKA'])
+        print('Path to the website directory:', url)
         if env['OPAL'] == '':
-            print 'PDB2PQR jobs run via the web interface will be forked on the server.'
+            print('PDB2PQR jobs run via the web interface will be forked on the server.')
         else:
-            print 'PDB2PQR jobs run via the web interface will be run via opal at', env['OPAL']
+            print('PDB2PQR jobs run via the web interface will be run via opal at', env['OPAL'])
     else:
-        print
-        print 'Run "python scons/scons.py" to build pdb2pqr.'
+        print()
+        print('Run "scons" to build pdb2pqr.')
 
-    print
-    print 'The preferred way to configure the build is by editing the file', config_file
-    print
-    print 'Run scons with the python that you intend to use with pdb2pqr.'
-    print 'For example: "/opt/bin/python scons/scons.py" will setup pdb2pqr to be run with /opt/bin/python'
+    print()
+    print('The preferred way to configure the build is by editing the file', config_file)
+    print()
+    print('Run scons with the python3 that you intend to use with pdb2pqr.')
+    print('For example: "scons" will setup pdb2pqr to be run with Debian default Python3 interpreter')
 
     if 'install' not in target_list:
-        print
-        print 'Run "python scons/scons.py install" to install pdb2pqr in', env['PREFIX']
+        print()
+        print('Run "scons install" to install pdb2pqr in', env['PREFIX'])
 
-    print
-    print 'Run "python scons/scons.py basic-test" for a basic functionality test'
-    print 'Run "python scons/scons.py advanced-test" for a single test of ligand and PROPKA support. Requires numpy and PDB2PKA support compiled.'
-    print 'Run "python scons/scons.py complete-test" for a complete test of all functionality EXCEPT PDB2PKA. Requires numpy and PDB2PKA support compiled.'
-    print 'Run "python scons/scons.py pdb2pka-test" for a test of PDB2PKA functionality.'
-    print '    Requires numpy, PDB2PKA support compiled AND the APBS python libraries compiled and installed in the pdb2pka directory.'
-
-    print
-    print 'To setup a web service create a symbolic link to', env['PREFIX'], 'that enables you to view', env['URL'],'after running "scons/scons.py install"'
-    print
-    print 'Run "python scons/scons.py msvs" to build Visual Studio projects for the Algorithms and pMC_mult modules.'
-    print 'VS project generation is not well supported in scons. Resulting projects should build using NMAKE but cannot be used for debugging.'
-    print 'The resulting projects will need to modified to use VS natively to compile the code or debug.'
+    print()
+    print('Run "scons basic-test" for a basic functionality test')
+    print('Run "scons advanced-test" for a single test of ligand and PROPKA support. Requires numpy and PDB2PKA support compiled.')
+    print('Run "scons complete-test" for a complete test of all functionality EXCEPT PDB2PKA. Requires numpy and PDB2PKA support compiled.')
+    print('Run "scons pdb2pka-test" for a test of PDB2PKA functionality.')
+    print('    Requires numpy, PDB2PKA support compiled AND the APBS python3 libraries compiled and installed in the pdb2pka directory.')
+
+    print()
+    print('To setup a web service create a symbolic link to', env['PREFIX'], 'that enables you to view', env['URL'],'after running "scons install"')
+    print()
+    print('Run "scons msvs" to build Visual Studio projects for the Algorithms and pMC_mult modules.')
+    print('VS project generation is not well supported in scons. Resulting projects should build using NMAKE but cannot be used for debugging.')
+    print('The resulting projects will need to modified to use VS natively to compile the code or debug.')
 
 
     if 'install' in target_list:
-        print
-        print 'pdb2pqr installed in', env['PREFIX']
+        print()
+        print('pdb2pqr installed in', env['PREFIX'])
 
 
 atexit.register(print_default_message, BUILD_TARGETS)
--- a/fabfile.py
+++ b/fabfile.py
@@ -51,7 +51,7 @@
                 arcname = os.path.join(self.prefix, name)
 
         self.tar.add(name, arcname)
-        print('Packing file: ' + name if arcname is None else arcname)
+        print(('Packing file: ' + name if arcname is None else arcname))
 
     def close(self):
         self.tar.close()
@@ -97,7 +97,7 @@
     local("move pdb2pqr-src-"+pv+'.tar.gz dist_files\\')
 
 def deploy():
-    python = 'python2.7'
+    python = 'python3'
 
     put('pdb2pqr.tgz', '~/')
     with settings(warn_only=True):
@@ -106,15 +106,15 @@
 
     with cd('~/tmp/'):
         run('tar -zxvf ~/pdb2pqr.tgz')
-        run(python+' scons/scons.py')
+        run('scons')
 
         if run_tests:
-            run(python+' scons/scons.py -j 4 pdb2pka-test')
-            run(python+' scons/scons.py -j 4 complete-test')
+            run('scons -j 4 pdb2pka-test')
+            run('scons -j 4 complete-test')
 
 
 def install_on_deployed():
-    python = 'python2.7'
+    python = 'python3'
 
     with settings(warn_only=True):
         with cd('~/www/pdb2pqr'):
@@ -147,8 +147,8 @@
 #             configopts += ' PREFIX=/Users/d3k084/www/pdb2pqr/'
 #             configopts += ' URL=http://PT24098/d3k084/pdb2pqr'
 
-        run(python+' scons/scons.py ' + configopts)
-        run(python+' scons/scons.py install ' + configopts)
+        run('scons ' + configopts)
+        run('scons install ' + configopts)
 
 def build_binary_from_deploy():
     create_dist_folder()
@@ -190,11 +190,11 @@
 @runs_once
 def build_windows():
     local(r'copy apbs_libs\windows\* pdb2pka\\')
-    local(r'python scons\scons.py -c')
-    local(r'python scons\scons.py')
+    local(r'python3 scons\scons.py -c')
+    local(r'python3 scons\scons.py')
     if run_tests:
-        local(r'python scons\scons.py -j 4 pdb2pka-test')
-        local(r'python scons\scons.py -j 7 complete-test')
+        local(r'python3 scons\scons.py -j 4 pdb2pka-test')
+        local(r'python3 scons\scons.py -j 7 complete-test')
 
     build_windows_binary()
     if run_tests:
@@ -219,12 +219,12 @@
     zip_file = zipfile.ZipFile(name + '.zip', 'w', zipfile.ZIP_DEFLATED)
     for root, _, files in os.walk(r'dist\\'+name):
         new_root = root.split('/', 1)[-1]
-        print root
+        print(root)
         for f in files:
             zip_file_path = os.path.join(new_root,f)
             real_file_path = os.path.join(root,f)
             zip_file.write(real_file_path, zip_file_path)
-            print 'Zipping ' + zip_file_path
+            print('Zipping ' + zip_file_path)
     zip_file.close()
     create_dist_folder()
     local('move /Y ' + name + '.zip' + r' dist_files\\' + name + '.zip')
--- a/scons/scons-time.py
+++ b/scons/scons-time.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/python3
 #
 # scons-time - run SCons timings and collect statistics
 #
@@ -29,8 +29,8 @@
 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-from __future__ import division
-from __future__ import nested_scopes
+
+
 
 __revision__ = "src/script/scons-time.py  2014/08/24 12:12:31 garyo"
 
@@ -109,8 +109,8 @@
     internal functions.
     '''
     if not args:          exec(cmd)
-    elif len(args) == 1:  exec cmd in args[0]
-    else:                 exec cmd in args[0], args[1]
+    elif len(args) == 1:  exec(cmd, args[0])
+    else:                 exec(cmd, args[0], args[1])
 
 class Plotter(object):
     def increment_size(self, largest):
@@ -146,7 +146,7 @@
 
     def print_label(self, inx, x, y):
         if self.label:
-            print 'set label %s "%s" at %s,%s right' % (inx, self.label, x, y)
+            print('set label %s "%s" at %s,%s right' % (inx, self.label, x, y))
 
     def plot_string(self):
         if self.title:
@@ -159,15 +159,15 @@
         if fmt is None:
             fmt = self.fmt
         if self.comment:
-            print '# %s' % self.comment
+            print('# %s' % self.comment)
         for x, y in self.points:
             # If y is None, it usually represents some kind of break
             # in the line's index number.  We might want to represent
             # this some way rather than just drawing the line straight
             # between the two points on either side.
             if not y is None:
-                print fmt % (x, y)
-        print 'e'
+                print(fmt % (x, y))
+        print('e')
 
     def get_x_values(self):
         return [ p[0] for p in self.points ]
@@ -253,8 +253,8 @@
             return
 
         if self.title:
-            print 'set title "%s"' % self.title
-        print 'set key %s' % self.key_location
+            print('set title "%s"' % self.title)
+        print('set key %s' % self.key_location)
 
         min_y = self.get_min_y()
         max_y = self.max_graph_value(self.get_max_y())
@@ -269,7 +269,7 @@
             inx += 1
 
         plot_strings = [ self.plot_string(l) for l in self.lines ]
-        print 'plot ' + ', \\\n     '.join(plot_strings)
+        print('plot ' + ', \\\n     '.join(plot_strings))
 
         for line in self.lines:
             line.print_points()
@@ -540,7 +540,7 @@
         header_fmt = ' '.join(['%12s'] * len(columns))
         line_fmt = header_fmt + '    %s'
 
-        print header_fmt % columns
+        print(header_fmt % columns)
 
         for file in files:
             t = line_function(file, *args, **kw)
@@ -550,7 +550,7 @@
             if diff > 0:
                 t += [''] * diff
             t.append(file_function(file))
-            print line_fmt % tuple(t)
+            print(line_fmt % tuple(t))
 
     def collect_results(self, files, function, *args, **kw):
         results = {}
@@ -690,13 +690,13 @@
         """
         try:
             import pstats
-        except ImportError, e:
+        except ImportError as e:
             sys.stderr.write('%s: func: %s\n' % (self.name, e))
             sys.stderr.write('%s  This version of Python is missing the profiler.\n' % self.name_spaces)
             sys.stderr.write('%s  Cannot use the "func" subcommand.\n' % self.name_spaces)
             sys.exit(1)
         statistics = pstats.Stats(file).stats
-        matches = [ e for e in statistics.items() if e[0][2] == function ]
+        matches = [ e for e in list(statistics.items()) if e[0][2] == function ]
         r = matches[0]
         return r[0][0], r[0][1], r[0][2], r[1][3]
 
@@ -751,7 +751,7 @@
             return self.default(argv)
         try:
             return func(argv)
-        except TypeError, e:
+        except TypeError as e:
             sys.stderr.write("%s %s: %s\n" % (self.name, cmdName, e))
             import traceback
             traceback.print_exc(file=sys.stderr)
@@ -856,7 +856,7 @@
                 self.title = a
 
         if self.config_file:
-            exec open(self.config_file, 'rU').read() in self.__dict__
+            exec(open(self.config_file, 'rU').read(), self.__dict__)
 
         if self.chdir:
             os.chdir(self.chdir)
@@ -889,13 +889,13 @@
                 try:
                     f, line, func, time = \
                             self.get_function_profile(file, function_name)
-                except ValueError, e:
+                except ValueError as e:
                     sys.stderr.write("%s: func: %s: %s\n" %
                                      (self.name, file, e))
                 else:
                     if f.startswith(cwd_):
                         f = f[len(cwd_):]
-                    print "%.3f %s:%d(%s)" % (time, f, line, func)
+                    print("%.3f %s:%d(%s)" % (time, f, line, func))
 
         elif format == 'gnuplot':
 
@@ -1233,7 +1233,7 @@
             sys.exit(1)
 
         if self.config_file:
-            exec open(self.config_file, 'rU').read() in self.__dict__
+            exec(open(self.config_file, 'rU').read(), self.__dict__)
 
         if args:
             self.archive_list = args
@@ -1466,7 +1466,7 @@
             elif o in ('--title',):
                 self.title = a
             elif o in ('--which',):
-                if not a in self.time_strings.keys():
+                if not a in list(self.time_strings.keys()):
                     sys.stderr.write('%s: time: Unrecognized timer "%s".\n' % (self.name, a))
                     sys.stderr.write('%s  Type "%s help time" for help.\n' % (self.name_spaces, self.name))
                     sys.exit(1)
--- a/scons/scons.py
+++ b/scons/scons.py
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#!/usr/bin/python3
 #
 # SCons - a Software Constructor
 #
@@ -191,7 +191,7 @@
     except:
         print("Import failed. Unable to find SCons files in:")
         for path in libs:
-          print "  %s" % path
+          print("  %s" % path)
         raise
 
     # this does all the work, and calls sys.exit
--- a/scons/sconsign.py
+++ b/scons/sconsign.py
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#!/usr/bin/python3
 #
 # SCons - a Software Constructor
 #
@@ -171,7 +171,7 @@
 
 import SCons.compat   # so pickle will import cPickle instead
 
-import whichdb
+import dbm
 import time
 import pickle
 import imp
@@ -189,8 +189,8 @@
         pass
     return _orig_whichdb(filename)
 
-_orig_whichdb = whichdb.whichdb
-whichdb.whichdb = my_whichdb
+_orig_whichdb = dbm.whichdb
+dbm.whichdb = my_whichdb
 
 def my_import(mname):
     if '.' in mname:
@@ -310,14 +310,14 @@
     outlist = field("implicit", entry, 0)
     if outlist:
         if Verbose:
-            print "    implicit:"
-        print "        " + outlist
+            print("    implicit:")
+        print("        " + outlist)
     outact = field("action", entry, 0)
     if outact:
         if Verbose:
-            print "    action: " + outact
+            print("    action: " + outact)
         else:
-            print "        " + outact
+            print("        " + outact)
 
 def printentries(entries, location):
     if Print_Entries:
@@ -330,9 +330,9 @@
                 try:
                     ninfo = entry.ninfo
                 except AttributeError:
-                    print name + ":"
+                    print(name + ":")
                 else:
-                    print nodeinfo_string(name, entry.ninfo)
+                    print(nodeinfo_string(name, entry.ninfo))
                 printfield(name, entry.binfo)
     else:
         for name in sorted(entries.keys()):
@@ -340,9 +340,9 @@
             try:
                 ninfo = entry.ninfo
             except AttributeError:
-                print name + ":"
+                print(name + ":")
             else:
-                print nodeinfo_string(name, entry.ninfo)
+                print(nodeinfo_string(name, entry.ninfo))
             printfield(name, entry.binfo)
 
 class Do_SConsignDB(object):
@@ -361,7 +361,7 @@
             #   .sconsign               => .sconsign.dblite
             #   .sconsign.dblite        => .sconsign.dblite.dblite
             db = self.dbm.open(fname, "r")
-        except (IOError, OSError), e:
+        except (IOError, OSError) as e:
             print_e = e
             try:
                 # That didn't work, so try opening the base name,
@@ -375,7 +375,7 @@
                 # suffix-mangling).
                 try:
                     open(fname, "r")
-                except (IOError, OSError), e:
+                except (IOError, OSError) as e:
                     # Nope, that file doesn't even exist, so report that
                     # fact back.
                     print_e = e
@@ -386,7 +386,7 @@
         except pickle.UnpicklingError:
             sys.stderr.write("sconsign: ignoring invalid `%s' file `%s'\n" % (self.dbm_name, fname))
             return
-        except Exception, e:
+        except Exception as e:
             sys.stderr.write("sconsign: ignoring invalid `%s' file `%s': %s\n" % (self.dbm_name, fname, e))
             return
 
@@ -403,13 +403,13 @@
                 self.printentries(dir, db[dir])
 
     def printentries(self, dir, val):
-        print '=== ' + dir + ':'
+        print('=== ' + dir + ':')
         printentries(pickle.loads(val), dir)
 
 def Do_SConsignDir(name):
     try:
         fp = open(name, 'rb')
-    except (IOError, OSError), e:
+    except (IOError, OSError) as e:
         sys.stderr.write("sconsign: %s\n" % (e))
         return
     try:
@@ -419,7 +419,7 @@
     except pickle.UnpicklingError:
         sys.stderr.write("sconsign: ignoring invalid .sconsign file `%s'\n" % (name))
         return
-    except Exception, e:
+    except Exception as e:
         sys.stderr.write("sconsign: ignoring invalid .sconsign file `%s': %s\n" % (name, e))
         return
     printentries(sconsign.entries, args[0])
@@ -471,13 +471,13 @@
                 dbm = my_import(dbm_name)
             except:
                 sys.stderr.write("sconsign: illegal file format `%s'\n" % a)
-                print helpstr
+                print(helpstr)
                 sys.exit(2)
             Do_Call = Do_SConsignDB(a, dbm)
         else:
             Do_Call = Do_SConsignDir
     elif o in ('-h', '--help'):
-        print helpstr
+        print(helpstr)
         sys.exit(0)
     elif o in ('-i', '--implicit'):
         Print_Flags['implicit'] = 1
@@ -497,7 +497,7 @@
         Do_Call(a)
 else:
     for a in args:
-        dbm_name = whichdb.whichdb(a)
+        dbm_name = dbm.whichdb(a)
         if dbm_name:
             Map_Module = {'SCons.dblite' : 'dblite'}
             dbm = my_import(dbm_name)
--- a/site_scons/site_init.py
+++ b/site_scons/site_init.py
@@ -48,35 +48,35 @@
             contents = f.read()
             f.close()
         except:
-            raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
+            raise SCons.Errors.UserError("Can't read source file %s"%sourcefile)
         if useRegex:
-            for (k,v) in dict.items():
+            for (k,v) in list(dict.items()):
                 #In 2.6 re.sub has no "flags" argument.
                 mo = re.compile(k, flags=re.DOTALL)
                 contents = mo.sub(v, contents)
         else:
-            for (k,v) in dict.items():
+            for (k,v) in list(dict.items()):
                 contents = contents.replace(k, v)
         try:
             f = open(targetfile, 'wb')
             f.write(contents)
             f.close()
         except:
-            raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
+            raise SCons.Errors.UserError("Can't write target file %s"%targetfile)
         return 0 # success
 
     def subst_in_file(target, source, env):
         useRegex = env['SUBST_USE_REGEX'] if 'SUBST_USE_REGEX' in env else False
         if 'SUBST_DICT' not in env:
-            raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
+            raise SCons.Errors.UserError("SubstInFile requires SUBST_DICT to be set.")
         d = dict(env['SUBST_DICT']) # copy it
-        for (k,v) in d.items():
+        for (k,v) in list(d.items()):
             if callable(v):
                 d[k] = env.subst(v())
             elif SCons.Util.is_String(v):
                 d[k]=env.subst(v)
             else:
-                raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
+                raise SCons.Errors.UserError("SubstInFile: key %s: %s must be a string or callable"%(k, repr(v)))
         for (t,s) in zip(target, source):
             return do_subst_in_file(str(t), str(s), d, useRegex)
 
@@ -90,7 +90,7 @@
         Returns original target, source tuple unchanged.
         """
         d = env['SUBST_DICT'].copy() # copy it
-        for (k,v) in d.items():
+        for (k,v) in list(d.items()):
             if callable(v):
                 d[k] = env.subst(v())
             elif SCons.Util.is_String(v):
@@ -108,25 +108,25 @@
     1.2345 etc.
     """
     try:
-        f = open(sourcefile, 'rb')
+        f = open(sourcefile, 'r')
         contents = f.read()
         f.close()
     except:
-        raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
+        raise SCons.Errors.UserError("Can't read source file %s"%sourcefile)
     if useRegex:
-        for (k,v) in dict.items():
+        for (k,v) in list(dict.items()):
             #In 2.6 re.sub has no "flags" argument.
             mo = re.compile(k, flags=re.DOTALL)
             contents = mo.sub(v, contents)
     else:
-        for (k,v) in dict.items():
+        for (k,v) in list(dict.items()):
             contents = contents.replace(k, v)
     try:
-        f = open(targetfile, 'wb')
+        f = open(targetfile, 'w')
         f.write(contents)
         f.close()
     except:
-        raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
+        raise SCons.Errors.UserError("Can't write target file %s"%targetfile)
     return 0 # success
 
 def CopySubActionStringFunc(targetfile, sourcefile, dict, useRegex):
@@ -138,12 +138,12 @@
     try:
         import py_compile
     except ImportError:
-        raise SCons.Errors.InternalError, "Couldn't import py_compile module"
+        raise SCons.Errors.InternalError("Couldn't import py_compile module")
 
     try:
         py_compile.compile(sourcefile, targetfile, doraise=True)
     except py_compile.PyCompileError:
-        raise SCons.Errors.InternalError, "Couldn't compile {0}".format(sourcefile)
+        raise SCons.Errors.InternalError("Couldn't compile {0}".format(sourcefile))
 
 
 
--- a/site_scons/test_tools.py
+++ b/site_scons/test_tools.py
@@ -1,4 +1,4 @@
-from itertools import ifilter, izip_longest, izip
+from itertools import zip_longest
 from glob import glob
 from os import path
 import csv
@@ -31,19 +31,19 @@
     return strings,ints,floats
 
 def compareParsedAtoms(atom1, atom2):
-    return atom1[0:1] == atom2[0:1] and all(abs(x-y)<0.1 for x,y in izip(atom1[2],atom2[2]))
+    return atom1[0:1] == atom2[0:1] and all(abs(x-y)<0.1 for x,y in zip(atom1[2],atom2[2]))
 
 def ComparePQRAction(outputFileName, testFileName, correctFileName, has_chain=False):
     failure = False
     results = []
     with open(testFileName) as testFile:
         with open(correctFileName) as correctFile:
-            testAtoms = ifilter(isAtomLine, testFile)
-            correctAtoms = ifilter(isAtomLine, correctFile)
+            testAtoms = filter(isAtomLine, testFile)
+            correctAtoms = filter(isAtomLine, correctFile)
             check_error = False
             correct_total = 0.0
             test_total = 0.0
-            for testAtom, correctAtom in izip_longest(testAtoms, correctAtoms, fillvalue=None):
+            for testAtom, correctAtom in zip_longest(testAtoms, correctAtoms, fillvalue=None):
                 if testAtom is None or correctAtom is None:
                     results.append('TEST ERROR: Result file is the wrong length!\n')
                     failure = True
@@ -99,7 +99,7 @@
         else:
             combined[ph][1] = value
 
-    keys = combined.keys()
+    keys = list(combined.keys())
     keys.sort()
 
     combined_list = [(combined[ph][0], combined[ph][1]) for ph in keys]
@@ -166,12 +166,12 @@
 
 
 def getSummaryLines(sourceFile):
-    while 'SUMMARY' not in sourceFile.next():
+    while 'SUMMARY' not in next(sourceFile):
         pass
 
     #Skip header
-    sourceFile.next()
-    line = sourceFile.next()
+    next(sourceFile)
+    line = next(sourceFile)
 
     results = []
 
@@ -184,7 +184,7 @@
 
         results.append((strings,floats))
 
-        line = sourceFile.next()
+        line = next(sourceFile)
 
     return results
 
@@ -197,7 +197,7 @@
             correctPKAs = getSummaryLines(correctFile)
             correct_total = 0.0
             test_total = 0.0
-            for testPKA, correctPKA in izip_longest(testPKAs, correctPKAs, fillvalue=None):
+            for testPKA, correctPKA in zip_longest(testPKAs, correctPKAs, fillvalue=None):
                 if testPKA is None or correctPKA is None:
                     results.append('TEST ERROR: Result file is the wrong length!')
                     failure = True
--- a/tests/complete-test/SConscript
+++ b/tests/complete-test/SConscript
@@ -108,7 +108,7 @@
 		  '--ff=AMBER --ligand=${SOURCES[1]} --whitespace')
 		  
 #Test ph and ligand	  
-for ph in xrange(1,14):
+for ph in range(1,14):
 
 	out_file_name = 'test-output-1HPX-ligand-ph{0}.pqr'.format(ph)
 	correct_file_name = 'test-output-1HPX-ligand-ph{0}-correct.pqr'.format(ph)
@@ -169,4 +169,4 @@
 					  'test-misc-options',
 					  '--ff=AMBER --apbs-input --whitespace --typemap --include-header')
 		  
-Alias('complete-test', testList)
\ No newline at end of file
+Alias('complete-test', testList)
