From 953dc41b8b720fdcec7955de67d23206214e5125 Mon Sep 17 00:00:00 2001 From: Gary Oberbrunner Date: Sun, 22 Sep 2013 13:08:12 -0400 Subject: Result of raw 2to3 run (2to3-2.7); checkpoint for python3 conversion. --- QMTest/TestCmd.py | 32 +- QMTest/TestCmdTests.py | 136 +- QMTest/TestCommon.py | 66 +- QMTest/TestSCons.py | 52 +- QMTest/TestSConsMSVS.py | 2 +- QMTest/TestSCons_time.py | 4 +- QMTest/TestSConsign.py | 2 +- QMTest/scons_tdb.py | 18 +- bench/bench.py | 8 +- bench/env.__setitem__.py | 16 +- bench/is_types.py | 12 +- bench/timeit.py | 24 +- bin/Command.py | 6 +- bin/SConsDoc.py | 28 +- bin/SConsExamples.py | 20 +- bin/calibrate.py | 8 +- bin/caller-tree.py | 10 +- bin/docs-create-example-outputs.py | 6 +- bin/docs-update-generated.py | 2 +- bin/docs-validate.py | 8 +- bin/install_python.py | 6 +- bin/install_scons.py | 10 +- bin/linecount.py | 30 +- bin/memlogs.py | 8 +- bin/memoicmp.py | 24 +- bin/objcounts.py | 13 +- bin/scons-diff.py | 14 +- bin/scons-proc.py | 14 +- bin/scons-test.py | 60 +- bin/scons-unzip.py | 2 +- bin/scons_dev_master.py | 6 +- bin/svn-bisect.py | 14 +- bin/update-release-info.py | 30 +- bin/xmlagenda.py | 2 +- review.py | 3611 ++++++++++---------- runtest.py | 24 +- src/engine/SCons/Action.py | 47 +- src/engine/SCons/ActionTests.py | 12 +- src/engine/SCons/Builder.py | 20 +- src/engine/SCons/BuilderTests.py | 28 +- src/engine/SCons/CacheDirTests.py | 2 +- src/engine/SCons/Debug.py | 4 +- src/engine/SCons/Defaults.py | 11 +- src/engine/SCons/DefaultsTests.py | 2 +- src/engine/SCons/Environment.py | 59 +- src/engine/SCons/EnvironmentTests.py | 44 +- src/engine/SCons/ErrorsTests.py | 12 +- src/engine/SCons/ExecutorTests.py | 2 +- src/engine/SCons/Job.py | 4 +- src/engine/SCons/Memoize.py | 4 +- src/engine/SCons/MemoizeTests.py | 4 +- src/engine/SCons/Node/FS.py | 23 +- src/engine/SCons/Node/FSTests.py | 34 +- src/engine/SCons/Node/__init__.py | 12 +- src/engine/SCons/Options/__init__.py | 10 +- src/engine/SCons/Platform/__init__.py | 4 +- src/engine/SCons/Platform/aix.py | 2 +- src/engine/SCons/Platform/cygwin.py | 2 +- src/engine/SCons/Platform/darwin.py | 2 +- src/engine/SCons/Platform/hpux.py | 2 +- src/engine/SCons/Platform/irix.py | 2 +- src/engine/SCons/Platform/os2.py | 2 +- src/engine/SCons/Platform/posix.py | 9 +- src/engine/SCons/Platform/sunos.py | 2 +- src/engine/SCons/Platform/win32.py | 4 +- src/engine/SCons/SConf.py | 10 +- src/engine/SCons/SConfTests.py | 2 +- src/engine/SCons/SConsign.py | 16 +- src/engine/SCons/Scanner/C.py | 2 +- src/engine/SCons/Scanner/Fortran.py | 3 +- src/engine/SCons/Scanner/LaTeX.py | 4 +- src/engine/SCons/Scanner/Prog.py | 3 +- src/engine/SCons/Scanner/ProgTests.py | 4 +- src/engine/SCons/Scanner/ScannerTests.py | 2 +- src/engine/SCons/Scanner/__init__.py | 5 +- src/engine/SCons/Script/Interactive.py | 12 +- src/engine/SCons/Script/Main.py | 61 +- src/engine/SCons/Script/SConsOptions.py | 8 +- src/engine/SCons/Script/SConscript.py | 22 +- src/engine/SCons/Script/__init__.py | 8 +- src/engine/SCons/Subst.py | 8 +- src/engine/SCons/SubstTests.py | 48 +- src/engine/SCons/Taskmaster.py | 44 +- src/engine/SCons/TaskmasterTests.py | 10 +- src/engine/SCons/Tool/FortranCommon.py | 2 +- src/engine/SCons/Tool/GettextCommon.py | 12 +- src/engine/SCons/Tool/MSCommon/common.py | 6 +- src/engine/SCons/Tool/MSCommon/netframework.py | 4 +- src/engine/SCons/Tool/MSCommon/sdk.py | 8 +- src/engine/SCons/Tool/MSCommon/vc.py | 24 +- src/engine/SCons/Tool/MSCommon/vs.py | 6 +- src/engine/SCons/Tool/__init__.py | 36 +- src/engine/SCons/Tool/aixcc.py | 2 +- src/engine/SCons/Tool/aixf77.py | 2 +- src/engine/SCons/Tool/aixlink.py | 4 +- src/engine/SCons/Tool/applelink.py | 2 +- src/engine/SCons/Tool/cvf.py | 2 +- src/engine/SCons/Tool/cyglink.py | 2 +- .../docbook-xsl-1.76.1/extensions/docbook.py | 10 +- .../docbook/docbook-xsl-1.76.1/extensions/xslt.py | 12 +- src/engine/SCons/Tool/dvipdf.py | 2 +- src/engine/SCons/Tool/f03.py | 2 +- src/engine/SCons/Tool/f95.py | 2 +- src/engine/SCons/Tool/filesystem.py | 2 +- src/engine/SCons/Tool/gcc.py | 2 +- src/engine/SCons/Tool/gfortran.py | 2 +- src/engine/SCons/Tool/gnulink.py | 2 +- src/engine/SCons/Tool/gs.py | 2 +- src/engine/SCons/Tool/hpcc.py | 2 +- src/engine/SCons/Tool/hplink.py | 2 +- src/engine/SCons/Tool/icc.py | 2 +- src/engine/SCons/Tool/ifl.py | 2 +- src/engine/SCons/Tool/ifort.py | 2 +- src/engine/SCons/Tool/install.py | 26 +- src/engine/SCons/Tool/intelc.py | 19 +- src/engine/SCons/Tool/latex.py | 4 +- src/engine/SCons/Tool/link.py | 18 +- src/engine/SCons/Tool/midl.py | 2 +- src/engine/SCons/Tool/msgfmt.py | 2 +- src/engine/SCons/Tool/msginit.py | 4 +- src/engine/SCons/Tool/msgmerge.py | 2 +- src/engine/SCons/Tool/mslib.py | 2 +- src/engine/SCons/Tool/mslink.py | 12 +- src/engine/SCons/Tool/mssdk.py | 2 +- src/engine/SCons/Tool/msvc.py | 2 +- src/engine/SCons/Tool/msvs.py | 44 +- src/engine/SCons/Tool/msvsTests.py | 2 +- src/engine/SCons/Tool/packaging/__init__.py | 10 +- src/engine/SCons/Tool/packaging/ipk.py | 2 +- src/engine/SCons/Tool/packaging/msi.py | 8 +- src/engine/SCons/Tool/packaging/rpm.py | 12 +- src/engine/SCons/Tool/pdflatex.py | 2 +- src/engine/SCons/Tool/pdftex.py | 2 +- src/engine/SCons/Tool/qt.py | 12 +- src/engine/SCons/Tool/rpmutils.py | 6 +- src/engine/SCons/Tool/sgicc.py | 2 +- src/engine/SCons/Tool/sgilink.py | 2 +- src/engine/SCons/Tool/suncc.py | 2 +- src/engine/SCons/Tool/sunf77.py | 2 +- src/engine/SCons/Tool/sunf90.py | 2 +- src/engine/SCons/Tool/sunf95.py | 2 +- src/engine/SCons/Tool/sunlink.py | 2 +- src/engine/SCons/Tool/tex.py | 94 +- src/engine/SCons/Tool/textfile.py | 5 +- src/engine/SCons/Tool/xgettext.py | 8 +- src/engine/SCons/Util.py | 39 +- src/engine/SCons/UtilTests.py | 28 +- src/engine/SCons/Variables/EnumVariableTests.py | 4 +- src/engine/SCons/Variables/PathVariableTests.py | 16 +- src/engine/SCons/Variables/VariablesTests.py | 2 +- src/engine/SCons/Variables/__init__.py | 18 +- src/engine/SCons/compat/__init__.py | 2 +- src/engine/SCons/compat/_scons_subprocess.py | 48 +- src/engine/SCons/cpp.py | 11 +- src/engine/SCons/cppTests.py | 2 +- src/engine/SCons/dblite.py | 42 +- src/script/scons-time.py | 47 +- src/script/sconsign.py | 40 +- src/test_files.py | 10 +- src/test_interrupts.py | 6 +- src/test_pychecker.py | 2 +- src/test_setup.py | 6 +- src/test_strings.py | 8 +- test/AS/nasm.py | 2 +- test/Actions/unicode-signature.py | 2 +- test/AddOption/help.py | 16 +- test/Batch/action-changed.py | 4 +- test/Chmod.py | 78 +- test/Configure/ConfigureDryRunError.py | 2 +- test/Configure/config-h.py | 52 +- test/Configure/implicit-cache.py | 10 +- test/Copy-Action.py | 4 +- test/Deprecated/Options/Options.py | 2 +- test/Deprecated/SourceCode/BitKeeper/BitKeeper.py | 6 +- test/Deprecated/SourceCode/Subversion.py | 2 +- test/GetBuildFailures/parallel.py | 8 +- test/Glob/glob-libpath.py | 4 +- test/Install/Install.py | 2 +- test/Interactive/version.py | 2 +- test/Java/multi-step.py | 2 +- test/MSVC/batch-longlines.py | 122 +- test/MSVC/msvc.py | 6 +- test/QT/QTFLAGS.py | 2 +- test/QT/copied-env.py | 4 +- test/QT/warnings.py | 4 +- test/SConsignFile/use-dbhash.py | 2 +- test/SConsignFile/use-dbm.py | 2 +- test/SConsignFile/use-dumbdbm.py | 2 +- test/SConsignFile/use-gdbm.py | 2 +- test/SHELL.py | 2 +- test/Scanner/unicode.py | 10 +- test/TEMPFILEPREFIX.py | 2 +- test/TEX/TEX.py | 8 +- test/Value.py | 2 +- test/Variables/Variables.py | 2 +- test/WhereIs.py | 4 +- test/Win32/bad-drive.py | 4 +- test/Win32/default-drive.py | 2 +- test/ZIP/ZIP.py | 2 +- test/ZIP/ZIPROOT.py | 196 +- test/gnutools.py | 2 +- test/import.py | 4 +- test/long-lines/signature.py | 2 +- test/option--random.py | 4 +- test/option-v.py | 4 +- test/option/debug-count.py | 8 +- test/option/debug-time.py | 10 +- test/option/help-options.py | 4 +- test/option/profile.py | 2 +- test/scons-time/run/config/python.py | 2 +- test/scons-time/run/option/python.py | 2 +- test/sconsign/nonwritable.py | 4 +- test/sconsign/script/SConsignFile.py | 4 +- test/sconsign/script/Signatures.py | 4 +- test/sconsign/script/no-SConsignFile.py | 4 +- test/site_scons/sysdirs.py | 142 +- test/spaces.py | 2 +- test/subdivide.py | 4 +- test/update-release-info/update-release-info.py | 2 +- timings/ElectricCloud/TimeSCons-run.py | 2 +- www/gen_sched_table.py | 12 +- 221 files changed, 3292 insertions(+), 3282 deletions(-) diff --git a/QMTest/TestCmd.py b/QMTest/TestCmd.py index 38e9cd3..4f08d1f 100644 --- a/QMTest/TestCmd.py +++ b/QMTest/TestCmd.py @@ -285,7 +285,7 @@ version. # PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, # AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. -from __future__ import division + __author__ = "Steven Knight " __revision__ = "TestCmd.py 1.3.D001 2010/06/03 12:58:27 knight" @@ -355,7 +355,7 @@ except NameError: return isinstance(e, (str, UserString)) else: def is_String(e): - return isinstance(e, (str, unicode, UserString)) + return isinstance(e, (str, UserString)) tempfile.template = 'testcmd.' if os.name in ('posix', 'nt'): @@ -490,17 +490,17 @@ def match_re(lines = None, res = None): if not is_List(res): res = res.split("\n") if len(lines) != len(res): - print "match_re: expected %d lines, found %d"%(len(res), len(lines)) + print("match_re: expected %d lines, found %d"%(len(res), len(lines))) return for i in range(len(lines)): s = "^" + res[i] + "$" try: expr = re.compile(s) - except re.error, e: + except re.error as e: msg = "Regular expression error in %s: %s" raise re.error(msg % (repr(s), e.args[0])) if not expr.search(lines[i]): - print "match_re: mismatch at line %d:\n search re='%s'\n line='%s'"%(i,s,lines[i]) + print("match_re: mismatch at line %d:\n search re='%s'\n line='%s'"%(i,s,lines[i])) return return 1 @@ -514,7 +514,7 @@ def match_re_dotall(lines = None, res = None): s = "^" + res + "$" try: expr = re.compile(s, re.DOTALL) - except re.error, e: + except re.error as e: msg = "Regular expression error in %s: %s" raise re.error(msg % (repr(s), e.args[0])) return expr.match(lines) @@ -564,7 +564,7 @@ def diff_re(a, b, fromfile='', tofile='', s = "^" + aline + "$" try: expr = re.compile(s) - except re.error, e: + except re.error as e: msg = "Regular expression error in %s: %s" raise re.error(msg % (repr(s), e.args[0])) if not expr.search(bline): @@ -640,7 +640,7 @@ else: st = os.stat(f) except OSError: continue - if stat.S_IMODE(st[stat.ST_MODE]) & 0111: + if stat.S_IMODE(st[stat.ST_MODE]) & 0o111: return f return None @@ -716,7 +716,7 @@ class Popen(subprocess.Popen): (errCode, written) = WriteFile(x, input) except ValueError: return self._close('stdin') - except (subprocess.pywintypes.error, Exception), why: + except (subprocess.pywintypes.error, Exception) as why: if why.args[0] in (109, errno.ESHUTDOWN): return self._close('stdin') raise @@ -737,7 +737,7 @@ class Popen(subprocess.Popen): (errCode, read) = ReadFile(x, nAvail, None) except ValueError: return self._close(which) - except (subprocess.pywintypes.error, Exception), why: + except (subprocess.pywintypes.error, Exception) as why: if why.args[0] in (109, errno.ESHUTDOWN): return self._close(which) raise @@ -756,7 +756,7 @@ class Popen(subprocess.Popen): try: written = os.write(self.stdin.fileno(), input) - except OSError, why: + except OSError as why: if why.args[0] == errno.EPIPE: #broken pipe return self._close('stdin') raise @@ -950,7 +950,7 @@ class TestCmd(object): condition = self.condition if self._preserve[condition]: for dir in self._dirlist: - print unicode("Preserved directory " + dir + "\n"), + print(str("Preserved directory " + dir + "\n"), end=' ') else: list = self._dirlist[:] list.reverse() @@ -1016,10 +1016,10 @@ class TestCmd(object): if diff_function is None: diff_function = self.simple_diff if name is not None: - print self.banner(name) + print(self.banner(name)) args = (a.splitlines(), b.splitlines()) + args for line in diff_function(*args, **kw): - print line + print(line) def diff_stderr(self, a, b, *args, **kw): """Compare actual and expected file contents. @@ -1645,12 +1645,12 @@ class TestCmd(object): def do_chmod(fname): try: st = os.stat(fname) except OSError: pass - else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]|0200)) + else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]|0o200)) else: def do_chmod(fname): try: st = os.stat(fname) except OSError: pass - else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]&~0200)) + else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]&~0o200)) if os.path.isfile(top): do_chmod(top) diff --git a/QMTest/TestCmdTests.py b/QMTest/TestCmdTests.py index 1044ed1..96e0cbf 100644 --- a/QMTest/TestCmdTests.py +++ b/QMTest/TestCmdTests.py @@ -26,13 +26,13 @@ import os import shutil import signal import stat -import StringIO +import io import sys import tempfile import time import types import unittest -import UserList +import collections # Strip the current directory so we get the right TestCmd.py module. sys.path = sys.path[1:] @@ -131,11 +131,11 @@ class TestCmdTestCase(unittest.TestCase): run_env.write(t.scriptout_path, textout) run_env.write(t.scripterr_path, texterr) - os.chmod(t.script_path, 0644) # XXX UNIX-specific - os.chmod(t.scriptx_path, 0755) # XXX UNIX-specific - os.chmod(t.script1_path, 0644) # XXX UNIX-specific - os.chmod(t.scriptout_path, 0644) # XXX UNIX-specific - os.chmod(t.scripterr_path, 0644) # XXX UNIX-specific + os.chmod(t.script_path, 0o644) # XXX UNIX-specific + os.chmod(t.scriptx_path, 0o755) # XXX UNIX-specific + os.chmod(t.script1_path, 0o644) # XXX UNIX-specific + os.chmod(t.scriptout_path, 0o644) # XXX UNIX-specific + os.chmod(t.scripterr_path, 0o644) # XXX UNIX-specific t.orig_cwd = os.getcwd() @@ -220,8 +220,8 @@ class cleanup_TestCase(TestCmdTestCase): test = TestCmd.TestCmd(workdir = '') wdir = test.workdir test.write('file2', "Test file #2\n") - os.chmod(test.workpath('file2'), 0400) - os.chmod(wdir, 0500) + os.chmod(test.workpath('file2'), 0o400) + os.chmod(wdir, 0o500) test.cleanup() assert not os.path.exists(wdir) @@ -286,35 +286,35 @@ class chmod_TestCase(TestCmdTestCase): test.chmod(['sub', 'file2'], stat.S_IWRITE) file1_mode = stat.S_IMODE(os.stat(wdir_file1)[stat.ST_MODE]) - assert file1_mode == 0444, '0%o' % file1_mode + assert file1_mode == 0o444, '0%o' % file1_mode file2_mode = stat.S_IMODE(os.stat(wdir_sub_file2)[stat.ST_MODE]) - assert file2_mode == 0666, '0%o' % file2_mode + assert file2_mode == 0o666, '0%o' % file2_mode test.chmod('file1', stat.S_IWRITE) test.chmod(wdir_sub_file2, stat.S_IREAD) file1_mode = stat.S_IMODE(os.stat(wdir_file1)[stat.ST_MODE]) - assert file1_mode == 0666, '0%o' % file1_mode + assert file1_mode == 0o666, '0%o' % file1_mode file2_mode = stat.S_IMODE(os.stat(wdir_sub_file2)[stat.ST_MODE]) - assert file2_mode == 0444, '0%o' % file2_mode + assert file2_mode == 0o444, '0%o' % file2_mode else: - test.chmod(wdir_file1, 0700) - test.chmod(['sub', 'file2'], 0760) + test.chmod(wdir_file1, 0o700) + test.chmod(['sub', 'file2'], 0o760) file1_mode = stat.S_IMODE(os.stat(wdir_file1)[stat.ST_MODE]) - assert file1_mode == 0700, '0%o' % file1_mode + assert file1_mode == 0o700, '0%o' % file1_mode file2_mode = stat.S_IMODE(os.stat(wdir_sub_file2)[stat.ST_MODE]) - assert file2_mode == 0760, '0%o' % file2_mode + assert file2_mode == 0o760, '0%o' % file2_mode - test.chmod('file1', 0765) - test.chmod(wdir_sub_file2, 0567) + test.chmod('file1', 0o765) + test.chmod(wdir_sub_file2, 0o567) file1_mode = stat.S_IMODE(os.stat(wdir_file1)[stat.ST_MODE]) - assert file1_mode == 0765, '0%o' % file1_mode + assert file1_mode == 0o765, '0%o' % file1_mode file2_mode = stat.S_IMODE(os.stat(wdir_sub_file2)[stat.ST_MODE]) - assert file2_mode == 0567, '0%o' % file2_mode + assert file2_mode == 0o567, '0%o' % file2_mode @@ -1032,14 +1032,14 @@ class match_exact_TestCase(TestCmdTestCase): assert test.match_exact("abcde\n", "abcde\n") assert not test.match_exact(["12345\n", "abcde\n"], ["1[0-9]*5\n", "a.*e\n"]) assert test.match_exact(["12345\n", "abcde\n"], ["12345\n", "abcde\n"]) - assert not test.match_exact(UserList.UserList(["12345\n", "abcde\n"]), + assert not test.match_exact(collections.UserList(["12345\n", "abcde\n"]), ["1[0-9]*5\n", "a.*e\n"]) - assert test.match_exact(UserList.UserList(["12345\n", "abcde\n"]), + assert test.match_exact(collections.UserList(["12345\n", "abcde\n"]), ["12345\n", "abcde\n"]) assert not test.match_exact(["12345\n", "abcde\n"], - UserList.UserList(["1[0-9]*5\n", "a.*e\n"])) + collections.UserList(["1[0-9]*5\n", "a.*e\n"])) assert test.match_exact(["12345\n", "abcde\n"], - UserList.UserList(["12345\n", "abcde\n"])) + collections.UserList(["12345\n", "abcde\n"])) assert not test.match_exact("12345\nabcde\n", "1[0-9]*5\na.*e\n") assert test.match_exact("12345\nabcde\n", "12345\nabcde\n") lines = ["vwxyz\n", "67890\n"] @@ -1098,26 +1098,26 @@ sys.exit(0) ["1.*j\n"]) assert test.match_re_dotall(["12345\n", "abcde\n", "fghij\n"], ["12345\n", "abcde\n", "fghij\n"]) - assert test.match_re_dotall(UserList.UserList(["12345\n", + assert test.match_re_dotall(collections.UserList(["12345\n", "abcde\n", "fghij\n"]), ["1[0-9]*5\n", "a.*e\n", "f.*j\n"]) - assert test.match_re_dotall(UserList.UserList(["12345\n", + assert test.match_re_dotall(collections.UserList(["12345\n", "abcde\n", "fghij\n"]), ["1.*j\n"]) - assert test.match_re_dotall(UserList.UserList(["12345\n", + assert test.match_re_dotall(collections.UserList(["12345\n", "abcde\n", "fghij\n"]), ["12345\n", "abcde\n", "fghij\n"]) assert test.match_re_dotall(["12345\n", "abcde\n", "fghij\n"], - UserList.UserList(["1[0-9]*5\n", + collections.UserList(["1[0-9]*5\n", "a.*e\n", "f.*j\n"])) assert test.match_re_dotall(["12345\n", "abcde\n", "fghij\n"], - UserList.UserList(["1.*j\n"])) + collections.UserList(["1.*j\n"])) assert test.match_re_dotall(["12345\n", "abcde\n", "fghij\n"], - UserList.UserList(["12345\n", + collections.UserList(["12345\n", "abcde\n", "fghij\n"])) assert test.match_re_dotall("12345\nabcde\nfghij\n", @@ -1176,14 +1176,14 @@ sys.exit(0) assert test.match_re("abcde\n", "abcde\n") assert test.match_re(["12345\n", "abcde\n"], ["1[0-9]*5\n", "a.*e\n"]) assert test.match_re(["12345\n", "abcde\n"], ["12345\n", "abcde\n"]) - assert test.match_re(UserList.UserList(["12345\n", "abcde\n"]), + assert test.match_re(collections.UserList(["12345\n", "abcde\n"]), ["1[0-9]*5\n", "a.*e\n"]) - assert test.match_re(UserList.UserList(["12345\n", "abcde\n"]), + assert test.match_re(collections.UserList(["12345\n", "abcde\n"]), ["12345\n", "abcde\n"]) assert test.match_re(["12345\n", "abcde\n"], - UserList.UserList(["1[0-9]*5\n", "a.*e\n"])) + collections.UserList(["1[0-9]*5\n", "a.*e\n"])) assert test.match_re(["12345\n", "abcde\n"], - UserList.UserList(["12345\n", "abcde\n"])) + collections.UserList(["12345\n", "abcde\n"])) assert test.match_re("12345\nabcde\n", "1[0-9]*5\na.*e\n") assert test.match_re("12345\nabcde\n", "12345\nabcde\n") lines = ["vwxyz\n", "67890\n"] @@ -1463,7 +1463,7 @@ class preserve_TestCase(TestCmdTestCase): def test_preserve(self): """Test preserve()""" def cleanup_test(test, cond=None, stdout=""): - io = StringIO.StringIO() + io = io.StringIO() save = sys.stdout sys.stdout = io try: @@ -1603,7 +1603,7 @@ class read_TestCase(TestCmdTestCase): _file_matches(wdir_foo_file3, test.read(['foo', 'file3']), "Test\nfile\n#3.\n") _file_matches(wdir_foo_file3, - test.read(UserList.UserList(['foo', 'file3'])), + test.read(collections.UserList(['foo', 'file3'])), "Test\nfile\n#3.\n") _file_matches(wdir_file4, test.read('file4', mode = 'r'), "Test\nfile\n#4.\n") @@ -1862,8 +1862,8 @@ class run_verbose_TestCase(TestCmdTestCase): workdir = '', verbose = 1) - sys.stdout = StringIO.StringIO() - sys.stderr = StringIO.StringIO() + sys.stdout = io.StringIO() + sys.stderr = io.StringIO() test.run(arguments = ['arg1 arg2']) o = sys.stdout.getvalue() @@ -1876,8 +1876,8 @@ class run_verbose_TestCase(TestCmdTestCase): workdir = '', verbose = 1) - sys.stdout = StringIO.StringIO() - sys.stderr = StringIO.StringIO() + sys.stdout = io.StringIO() + sys.stderr = io.StringIO() testx.run(arguments = ['arg1 arg2']) expect = '"%s" "arg1 arg2"\n' % t.scriptx_path @@ -1913,8 +1913,8 @@ class run_verbose_TestCase(TestCmdTestCase): workdir = '', verbose = 2) - sys.stdout = StringIO.StringIO() - sys.stderr = StringIO.StringIO() + sys.stdout = io.StringIO() + sys.stderr = io.StringIO() test.run(arguments = ['arg1 arg2']) @@ -1934,8 +1934,8 @@ class run_verbose_TestCase(TestCmdTestCase): workdir = '', verbose = 2) - sys.stdout = StringIO.StringIO() - sys.stderr = StringIO.StringIO() + sys.stdout = io.StringIO() + sys.stderr = io.StringIO() testx.run(arguments = ['arg1 arg2']) @@ -1958,8 +1958,8 @@ class run_verbose_TestCase(TestCmdTestCase): workdir = '', verbose = 2) - sys.stdout = StringIO.StringIO() - sys.stderr = StringIO.StringIO() + sys.stdout = io.StringIO() + sys.stderr = io.StringIO() test.run(arguments = ['arg1 arg2']) @@ -1978,8 +1978,8 @@ class run_verbose_TestCase(TestCmdTestCase): workdir = '', verbose = 3) - sys.stdout = StringIO.StringIO() - sys.stderr = StringIO.StringIO() + sys.stdout = io.StringIO() + sys.stderr = io.StringIO() test.run(arguments = ['arg1 arg2']) @@ -2002,8 +2002,8 @@ class run_verbose_TestCase(TestCmdTestCase): interpreter = 'python', workdir = '') - sys.stdout = StringIO.StringIO() - sys.stderr = StringIO.StringIO() + sys.stdout = io.StringIO() + sys.stderr = io.StringIO() test.run(arguments = ['arg1 arg2']) @@ -2022,8 +2022,8 @@ class run_verbose_TestCase(TestCmdTestCase): testx = TestCmd.TestCmd(program = t.scriptx, workdir = '') - sys.stdout = StringIO.StringIO() - sys.stderr = StringIO.StringIO() + sys.stdout = io.StringIO() + sys.stderr = io.StringIO() testx.run(arguments = ['arg1 arg2']) @@ -2048,8 +2048,8 @@ class run_verbose_TestCase(TestCmdTestCase): workdir = '', verbose = 1) - sys.stdout = StringIO.StringIO() - sys.stderr = StringIO.StringIO() + sys.stdout = io.StringIO() + sys.stderr = io.StringIO() test.run(arguments = ['arg1 arg2']) o = sys.stdout.getvalue() @@ -2062,8 +2062,8 @@ class run_verbose_TestCase(TestCmdTestCase): workdir = '', verbose = 1) - sys.stdout = StringIO.StringIO() - sys.stderr = StringIO.StringIO() + sys.stdout = io.StringIO() + sys.stderr = io.StringIO() testx.run(arguments = ['arg1 arg2']) expect = '"%s" "arg1 arg2"\n' % t.scriptx_path @@ -2347,7 +2347,7 @@ while 1: logfp.close() """ % t.recv_out_path t.run_env.write(t.recv_script_path, text) - os.chmod(t.recv_script_path, 0644) # XXX UNIX-specific + os.chmod(t.recv_script_path, 0o644) # XXX UNIX-specific return t def test_start(self): @@ -2765,11 +2765,11 @@ class subdir_TestCase(TestCmdTestCase): assert test.subdir('bar') == 1 assert test.subdir(['foo', 'succeed']) == 1 if os.name != "nt": - os.chmod(test.workpath('foo'), 0500) + os.chmod(test.workpath('foo'), 0o500) assert test.subdir(['foo', 'fail']) == 0 assert test.subdir(['sub', 'dir', 'ectory'], 'sub') == 1 assert test.subdir('one', - UserList.UserList(['one', 'two']), + collections.UserList(['one', 'two']), ['one', 'two', 'three']) == 3 assert os.path.isdir(test.workpath('foo')) assert os.path.isdir(test.workpath('bar')) @@ -2962,7 +2962,7 @@ class unlink_TestCase(TestCmdTestCase): test.unlink(['foo', 'file3a']) assert not os.path.exists(wdir_foo_file3a) - test.unlink(UserList.UserList(['foo', 'file3b'])) + test.unlink(collections.UserList(['foo', 'file3b'])) assert not os.path.exists(wdir_foo_file3b) test.unlink([test.workdir, 'foo', 'file4']) @@ -2971,8 +2971,8 @@ class unlink_TestCase(TestCmdTestCase): # Make it so we can't unlink file5. # For UNIX, remove write permission from the dir and the file. # For Windows, open the file. - os.chmod(test.workdir, 0500) - os.chmod(wdir_file5, 0400) + os.chmod(test.workdir, 0o500) + os.chmod(wdir_file5, 0o400) f = open(wdir_file5, 'r') try: @@ -2983,8 +2983,8 @@ class unlink_TestCase(TestCmdTestCase): except: raise finally: - os.chmod(test.workdir, 0700) - os.chmod(wdir_file5, 0600) + os.chmod(test.workdir, 0o700) + os.chmod(wdir_file5, 0o600) f.close() @@ -3208,11 +3208,11 @@ class executable_TestCase(TestCmdTestCase): def make_executable(fname): st = os.stat(fname) - os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]|0100)) + os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]|0o100)) def make_non_executable(fname): st = os.stat(fname) - os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]&~0100)) + os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]&~0o100)) test.executable(test.workdir, 0) # XXX skip these tests if euid == 0? @@ -3282,7 +3282,7 @@ class write_TestCase(TestCmdTestCase): test.write('file9', "Test file #9.\r\n", mode = 'wb') if os.name != "nt": - os.chmod(test.workdir, 0500) + os.chmod(test.workdir, 0o500) try: test.write('file10', "Test file #10 (should not get created).\n") except IOError: # expect "Permission denied" diff --git a/QMTest/TestCommon.py b/QMTest/TestCommon.py index 4e90e16..5a397ff 100644 --- a/QMTest/TestCommon.py +++ b/QMTest/TestCommon.py @@ -281,9 +281,9 @@ class TestCommon(TestCmd): existing, missing = separate_files(files) unwritable = [x for x in existing if not is_writable(x)] if missing: - print "Missing files: `%s'" % "', `".join(missing) + print("Missing files: `%s'" % "', `".join(missing)) if unwritable: - print "Unwritable files: `%s'" % "', `".join(unwritable) + print("Unwritable files: `%s'" % "', `".join(unwritable)) self.fail_test(missing + unwritable) def must_contain(self, file, required, mode = 'rb', find = None): @@ -298,11 +298,11 @@ class TestCommon(TestCmd): return None contains = find(file_contents, required) if not contains: - print "File `%s' does not contain required string." % file - print self.banner('Required string ') - print required - print self.banner('%s contents ' % file) - print file_contents + print("File `%s' does not contain required string." % file) + print(self.banner('Required string ')) + print(required) + print(self.banner('%s contents ' % file)) + print(file_contents) self.fail_test(not contains) def must_contain_all_lines(self, output, lines, title=None, find=None): @@ -437,7 +437,7 @@ class TestCommon(TestCmd): files = [is_List(x) and os.path.join(*x) or x for x in files] missing = [x for x in files if not os.path.exists(x) and not os.path.islink(x) ] if missing: - print "Missing files: `%s'" % "', `".join(missing) + print("Missing files: `%s'" % "', `".join(missing)) self.fail_test(missing) def must_exist_one_of(self, files): @@ -457,7 +457,7 @@ class TestCommon(TestCmd): if glob.glob(xpath): return missing.append(xpath) - print "Missing one of: `%s'" % "', `".join(missing) + print("Missing one of: `%s'" % "', `".join(missing)) self.fail_test(missing) def must_match(self, file, expect, mode = 'rb', match=None): @@ -474,7 +474,7 @@ class TestCommon(TestCmd): except KeyboardInterrupt: raise except: - print "Unexpected contents of `%s'" % file + print("Unexpected contents of `%s'" % file) self.diff(expect, file_contents, 'contents ') raise @@ -490,11 +490,11 @@ class TestCommon(TestCmd): return None contains = find(file_contents, banned) if contains: - print "File `%s' contains banned string." % file - print self.banner('Banned string ') - print banned - print self.banner('%s contents ' % file) - print file_contents + print("File `%s' contains banned string." % file) + print(self.banner('Banned string ')) + print(banned) + print(self.banner('%s contents ' % file)) + print(file_contents) self.fail_test(contains) def must_not_contain_any_line(self, output, lines, title=None, find=None): @@ -541,7 +541,7 @@ class TestCommon(TestCmd): files = [is_List(x) and os.path.join(*x) or x for x in files] existing = [x for x in files if os.path.exists(x) or os.path.islink(x)] if existing: - print "Unexpected files exist: `%s'" % "', `".join(existing) + print("Unexpected files exist: `%s'" % "', `".join(existing)) self.fail_test(existing) def must_not_exist_any_of(self, files): @@ -561,7 +561,7 @@ class TestCommon(TestCmd): if glob.glob(xpath): existing.append(xpath) if existing: - print "Unexpected files exist: `%s'" % "', `".join(existing) + print("Unexpected files exist: `%s'" % "', `".join(existing)) self.fail_test(existing) def must_not_be_writable(self, *files): @@ -575,9 +575,9 @@ class TestCommon(TestCmd): existing, missing = separate_files(files) writable = list(filter(is_writable, existing)) if missing: - print "Missing files: `%s'" % "', `".join(missing) + print("Missing files: `%s'" % "', `".join(missing)) if writable: - print "Writable files: `%s'" % "', `".join(writable) + print("Writable files: `%s'" % "', `".join(writable)) self.fail_test(missing + writable) def _complete(self, actual_stdout, expected_stdout, @@ -590,23 +590,23 @@ class TestCommon(TestCmd): expect = '' if status != 0: expect = " (expected %s)" % str(status) - print "%s returned %s%s" % (self.program, _status(self), expect) - print self.banner('STDOUT ') - print actual_stdout - print self.banner('STDERR ') - print actual_stderr + print("%s returned %s%s" % (self.program, _status(self), expect)) + print(self.banner('STDOUT ')) + print(actual_stdout) + print(self.banner('STDERR ')) + print(actual_stderr) self.fail_test() if (expected_stdout is not None and not match(actual_stdout, expected_stdout)): self.diff(expected_stdout, actual_stdout, 'STDOUT ') if actual_stderr: - print self.banner('STDERR ') - print actual_stderr + print(self.banner('STDERR ')) + print(actual_stderr) self.fail_test() if (expected_stderr is not None and not match(actual_stderr, expected_stderr)): - print self.banner('STDOUT ') - print actual_stdout + print(self.banner('STDOUT ')) + print(actual_stdout) self.diff(expected_stderr, actual_stderr, 'STDERR ') self.fail_test() @@ -626,15 +626,15 @@ class TestCommon(TestCmd): universal_newlines, **kw) except KeyboardInterrupt: raise - except Exception, e: - print self.banner('STDOUT ') + except Exception as e: + print(self.banner('STDOUT ')) try: - print self.stdout() + print(self.stdout()) except IndexError: pass - print self.banner('STDERR ') + print(self.banner('STDERR ')) try: - print self.stderr() + print(self.stderr()) except IndexError: pass cmd_args = self.command_args(program, interpreter, arguments) diff --git a/QMTest/TestSCons.py b/QMTest/TestSCons.py index 84cc60f..72624e6 100644 --- a/QMTest/TestSCons.py +++ b/QMTest/TestSCons.py @@ -13,7 +13,7 @@ attributes defined in this subclass. """ # __COPYRIGHT__ -from __future__ import division + __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -356,7 +356,7 @@ class TestSCons(TestCommon): # raised so as to not mask possibly serious disk or # network issues. continue - if stat.S_IMODE(st[stat.ST_MODE]) & 0111: + if stat.S_IMODE(st[stat.ST_MODE]) & 0o111: return os.path.normpath(f) else: import SCons.Environment @@ -503,9 +503,9 @@ class TestSCons(TestCommon): self.pass_test() else: # test failed; have to do this by hand... - print self.banner('STDOUT ') - print self.stdout() - print self.diff(warning, stderr, 'STDERR ') + print(self.banner('STDOUT ')) + print(self.stdout()) + print(self.diff(warning, stderr, 'STDERR ')) self.fail_test() return warning @@ -574,7 +574,7 @@ class TestSCons(TestCommon): We stick the requested file name and line number in the right places, abstracting out the version difference. """ - exec 'import traceback; x = traceback.format_stack()[-1]' + exec('import traceback; x = traceback.format_stack()[-1]') x = x.lstrip() x = x.replace('', file) x = x.replace('line 1,', 'line %s,' % line) @@ -721,7 +721,7 @@ class TestSCons(TestCommon): home = os.path.normpath('%s/..'%jar) if os.path.isdir(home): return home - print("Could not determine JAVA_HOME: %s is not a directory" % home) + print(("Could not determine JAVA_HOME: %s is not a directory" % home)) self.fail_test() def java_where_jar(self, version=None): @@ -1087,27 +1087,27 @@ SConscript( sconscript ) if doCheckLog and lastEnd != len(logfile): raise NoMatch(lastEnd) - except NoMatch, m: - print "Cannot match log file against log regexp." - print "log file: " - print "------------------------------------------------------" - print logfile[m.pos:] - print "------------------------------------------------------" - print "log regexp: " - print "------------------------------------------------------" - print log - print "------------------------------------------------------" + except NoMatch as m: + print("Cannot match log file against log regexp.") + print("log file: ") + print("------------------------------------------------------") + print(logfile[m.pos:]) + print("------------------------------------------------------") + print("log regexp: ") + print("------------------------------------------------------") + print(log) + print("------------------------------------------------------") self.fail_test() if doCheckStdout: exp_stdout = self.wrap_stdout(".*", rdstr) if not self.match_re_dotall(self.stdout(), exp_stdout): - print "Unexpected stdout: " - print "-----------------------------------------------------" - print repr(self.stdout()) - print "-----------------------------------------------------" - print repr(exp_stdout) - print "-----------------------------------------------------" + print("Unexpected stdout: ") + print("-----------------------------------------------------") + print(repr(self.stdout())) + print("-----------------------------------------------------") + print(repr(exp_stdout)) + print("-----------------------------------------------------") self.fail_test() def get_python_version(self): @@ -1241,7 +1241,7 @@ class TimeSCons(TestSCons): self.variables = kw.get('variables') default_calibrate_variables = [] if self.variables is not None: - for variable, value in self.variables.items(): + for variable, value in list(self.variables.items()): value = os.environ.get(variable, value) try: value = int(value) @@ -1297,7 +1297,7 @@ class TimeSCons(TestSCons): """ if 'options' not in kw and self.variables: options = [] - for variable, value in self.variables.items(): + for variable, value in list(self.variables.items()): options.append('%s=%s' % (variable, value)) kw['options'] = ' '.join(options) if self.calibrate: @@ -1323,7 +1323,7 @@ class TimeSCons(TestSCons): self.elapsed_time(), "seconds", sort=0) - for name, args in stats.items(): + for name, args in list(stats.items()): self.trace(name, trace, **args) def uptime(self): diff --git a/QMTest/TestSConsMSVS.py b/QMTest/TestSConsMSVS.py index c78b452..478438a 100644 --- a/QMTest/TestSConsMSVS.py +++ b/QMTest/TestSConsMSVS.py @@ -1039,7 +1039,7 @@ print "self._msvs_versions =", str(SCons.Tool.MSCommon.query_versions()) try: host = _ARCH_TO_CANONICAL[host_platform] - except KeyError, e: + except KeyError as e: # Default to x86 for all other platforms host = 'x86' diff --git a/QMTest/TestSCons_time.py b/QMTest/TestSCons_time.py index abe8ccf..ba7fbd8 100644 --- a/QMTest/TestSCons_time.py +++ b/QMTest/TestSCons_time.py @@ -225,7 +225,7 @@ class TestSCons_time(TestCommon): def write_fake_aegis_py(self, name): name = self.workpath(name) self.write(name, aegis_py) - os.chmod(name, 0755) + os.chmod(name, 0o755) return name def write_fake_scons_py(self): @@ -235,7 +235,7 @@ class TestSCons_time(TestCommon): def write_fake_svn_py(self, name): name = self.workpath(name) self.write(name, svn_py) - os.chmod(name, 0755) + os.chmod(name, 0o755) return name def write_sample_directory(self, archive, dir, files): diff --git a/QMTest/TestSConsign.py b/QMTest/TestSConsign.py index 700c242..665059c 100644 --- a/QMTest/TestSConsign.py +++ b/QMTest/TestSConsign.py @@ -68,7 +68,7 @@ class TestSConsign(TestSCons): elif os.path.exists(self.script_path('sconsign')): sconsign = 'sconsign' else: - print "Can find neither 'sconsign.py' nor 'sconsign' scripts." + print("Can find neither 'sconsign.py' nor 'sconsign' scripts.") self.no_result() self.set_sconsign(sconsign) diff --git a/QMTest/scons_tdb.py b/QMTest/scons_tdb.py index 6be4696..845e99c 100644 --- a/QMTest/scons_tdb.py +++ b/QMTest/scons_tdb.py @@ -20,7 +20,7 @@ # 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 + """ QMTest classes to support SCons' testing and Aegis-inspired workflow. @@ -92,7 +92,7 @@ def get_explicit_arguments(e): # Determine which subset of the 'arguments' have been set # explicitly. explicit_arguments = {} - for name, field in arguments.items(): + for name, field in list(arguments.items()): # Do not record computed fields. if field.IsComputed(): continue @@ -337,14 +337,14 @@ class AegisChangeStream(AegisStream): # We'd like to use the _FormatStatistics() method to do # this, but it's wrapped around the list in Result.outcomes, # so it's simpler to just do it ourselves. - print " %6d tests total\n" % self._num_tests + print(" %6d tests total\n" % self._num_tests) for outcome in AegisTest.aegis_outcomes: if self._outcome_counts[outcome] != 0: - print " %6d (%3.0f%%) tests %s" % ( + print(" %6d (%3.0f%%) tests %s" % ( self._outcome_counts[outcome], self._percent(outcome), outcome - ) + )) class AegisBaselineStream(AegisStream): def WriteResult(self, result): @@ -368,19 +368,19 @@ class AegisBaselineStream(AegisStream): # this, but it's wrapped around the list in Result.outcomes, # so it's simpler to just do it ourselves. if self._outcome_counts[AegisTest.FAIL]: - print " %6d (%3.0f%%) tests as expected" % ( + print(" %6d (%3.0f%%) tests as expected" % ( self._outcome_counts[AegisTest.FAIL], self._percent(AegisTest.FAIL), - ) + )) non_fail_outcomes = list(AegisTest.aegis_outcomes[:]) non_fail_outcomes.remove(AegisTest.FAIL) for outcome in non_fail_outcomes: if self._outcome_counts[outcome] != 0: - print " %6d (%3.0f%%) tests unexpected %s" % ( + print(" %6d (%3.0f%%) tests unexpected %s" % ( self._outcome_counts[outcome], self._percent(outcome), outcome, - ) + )) class AegisBatchStream(FileResultStream): def __init__(self, arguments): diff --git a/bench/bench.py b/bench/bench.py index 74dbf12..1a98d8c 100644 --- a/bench/bench.py +++ b/bench/bench.py @@ -23,7 +23,7 @@ # # This will allow (as much as possible) us to time just the code itself, # not Python function call overhead. -from __future__ import division + import getopt import sys @@ -94,7 +94,7 @@ exec(open(args[0], 'rU').read()) try: FunctionList except NameError: - function_names = sorted([x for x in locals().keys() if x[:4] == FunctionPrefix]) + function_names = sorted([x for x in list(locals().keys()) if x[:4] == FunctionPrefix]) l = [locals()[f] for f in function_names] FunctionList = [f for f in l if isinstance(f, types.FunctionType)] @@ -113,12 +113,12 @@ def display(label, results): total = 0.0 for r in results: total += r - print " %8.3f" % ((total * 1e6) / len(results)), ':', label + print(" %8.3f" % ((total * 1e6) / len(results)), ':', label) for func in FunctionList: if func.__doc__: d = ' (' + func.__doc__ + ')' else: d = '' - print func.__name__ + d + ':' + print(func.__name__ + d + ':') for label, args, kw in Data: r = timer(func, *args, **kw) diff --git a/bench/env.__setitem__.py b/bench/env.__setitem__.py index b17b59e..284653e 100644 --- a/bench/env.__setitem__.py +++ b/bench/env.__setitem__.py @@ -33,15 +33,15 @@ class Timing(object): def times(num=1000000, init='', title='Results:', **statements): # time each statement timings = [] - for n, s in statements.items(): + for n, s in list(statements.items()): t = Timing(n, num, init, s) t.timeit() timings.append(t) - print - print title + print() + print(title) for i in sorted([(i.getResult(),i.name) for i in timings]): - print " %9.3f s %s" % i + print(" %9.3f s %s" % i) # Import the necessary local SCons.* modules used by some of our # alternative implementations below, first manipulating sys.path so @@ -287,7 +287,7 @@ else: # that the timer will use to get at these classes. class_names = [] -for n in locals().keys(): +for n in list(locals().keys()): #if n.startswith('env_'): if n[:4] == 'env_': class_names.append(n) @@ -339,9 +339,9 @@ def run_it(title, init): s['init'] = init times(**s) -print 'Environment __setitem__ benchmark using', -print 'Python', sys.version.split()[0], -print 'on', sys.platform, os.name +print('Environment __setitem__ benchmark using', end=' ') +print('Python', sys.version.split()[0], end=' ') +print('on', sys.platform, os.name) run_it('Results for re-adding an existing variable name 100 times:', common_imports + """ diff --git a/bench/is_types.py b/bench/is_types.py index 69c029f..b6da0d2 100644 --- a/bench/is_types.py +++ b/bench/is_types.py @@ -17,11 +17,11 @@ InstanceType = types.InstanceType DictType = dict ListType = list StringType = str -try: unicode +try: str except NameError: UnicodeType = None else: - UnicodeType = unicode + UnicodeType = str # The original implementations, pretty straightforward checks for the @@ -36,7 +36,7 @@ def original_is_List(e): if UnicodeType is not None: def original_is_String(e): - return isinstance(e, (str,unicode,UserString)) + return isinstance(e, (str,UserString)) else: def original_is_String(e): return isinstance(e, (str,UserString)) @@ -58,7 +58,7 @@ def checkInstanceType_is_List(e): if UnicodeType is not None: def checkInstanceType_is_String(e): return isinstance(e, str) \ - or isinstance(e, unicode) \ + or isinstance(e, str) \ or (isinstance(e, types.InstanceType) and isinstance(e, UserString)) else: def checkInstanceType_is_String(e): @@ -84,7 +84,7 @@ if UnicodeType is not None: def cache_type_e_is_String(e): t = type(e) return t is str \ - or t is unicode \ + or t is str \ or (t is types.InstanceType and isinstance(e, UserString)) else: def cache_type_e_is_String(e): @@ -136,7 +136,7 @@ if UnicodeType is not None: t = type(obj) if t is types.InstanceType: t = instanceTypeMap.get(obj.__class__, t) - elif t is unicode: + elif t is str: t = str return t else: diff --git a/bench/timeit.py b/bench/timeit.py index c5fef12..2840010 100644 --- a/bench/timeit.py +++ b/bench/timeit.py @@ -46,7 +46,7 @@ be aware of it. The baseline overhead can be measured by invoking the program without arguments. The baseline overhead differs between Python versions! """ -from __future__ import division + try: import gc @@ -122,7 +122,7 @@ class Timer(object): self.src = src # Save for traceback display code = compile(src, dummy_src_name, "exec") ns = {} - exec code in globals(), ns + exec(code, globals(), ns) self.inner = ns["inner"] def print_exc(self, file=None): @@ -216,9 +216,9 @@ def main(args=None): opts, args = getopt.getopt(args, "n:s:r:tcvh", ["number=", "setup=", "repeat=", "time", "clock", "verbose", "help"]) - except getopt.error, err: - print err - print "use -h/--help for command line help" + except getopt.error as err: + print(err) + print("use -h/--help for command line help") return 2 timer = default_timer stmt = "\n".join(args) or "pass" @@ -245,7 +245,7 @@ def main(args=None): precision = precision + 1 verbose = precision + 1 if o in ("-h", "--help"): - print __doc__, + print(__doc__, end=' ') return 0 setup = "\n".join(setup) or "pass" # Include the current directory, so that local imports work (sys.path @@ -264,7 +264,7 @@ def main(args=None): t.print_exc() return 1 if verbose: - print "%d loops -> %.*g secs" % (number, precision, x) + print("%d loops -> %.*g secs" % (number, precision, x)) if x >= 0.2: break try: @@ -274,18 +274,18 @@ def main(args=None): return 1 best = min(r) if verbose: - print "raw times:", ' '.join(["%.*g" % (precision, x) for x in r]) - print "%d loops," % number, + print("raw times:", ' '.join(["%.*g" % (precision, x) for x in r])) + print("%d loops," % number, end=' ') usec = best * 1e6 / number if usec < 1000: - print "best of %d: %.*g usec per loop" % (repeat, precision, usec) + print("best of %d: %.*g usec per loop" % (repeat, precision, usec)) else: msec = usec / 1000 if msec < 1000: - print "best of %d: %.*g msec per loop" % (repeat, precision, msec) + print("best of %d: %.*g msec per loop" % (repeat, precision, msec)) else: sec = msec / 1000 - print "best of %d: %.*g sec per loop" % (repeat, precision, sec) + print("best of %d: %.*g sec per loop" % (repeat, precision, sec)) return None if __name__ == "__main__": diff --git a/bin/Command.py b/bin/Command.py index 8702f51..768caed 100644 --- a/bin/Command.py +++ b/bin/Command.py @@ -109,18 +109,18 @@ Usage: script-template.py [-hnq] try: try: opts, args = getopt.getopt(argv[1:], short_options, long_options) - except getopt.error, msg: + except getopt.error as msg: raise Usage(msg) for o, a in opts: if o in ('-h', '--help'): - print helpstr + print(helpstr) sys.exit(0) elif o in ('-n', '--no-exec'): Command.execute = Command.do_not_execute elif o in ('-q', '--quiet'): Command.display = Command.do_not_display - except Usage, err: + except Usage as err: sys.stderr.write(err.msg) sys.stderr.write('use -h to get help') return 2 diff --git a/bin/SConsDoc.py b/bin/SConsDoc.py index dc9d161..453e241 100644 --- a/bin/SConsDoc.py +++ b/bin/SConsDoc.py @@ -210,12 +210,12 @@ class Libxml2ValidityHandler: def error(self, msg, data): if data != ARG: - raise Exception, "Error handler did not receive correct argument" + raise Exception("Error handler did not receive correct argument") self.errors.append(msg) def warning(self, msg, data): if data != ARG: - raise Exception, "Warning handler did not receive correct argument" + raise Exception("Warning handler did not receive correct argument") self.warnings.append(msg) @@ -332,16 +332,16 @@ if not has_libxml2: xmlschema = etree.XMLSchema(xmlschema_context) try: doc = etree.parse(fpath) - except Exception, e: - print "ERROR: %s fails to parse:"%fpath - print e + except Exception as e: + print("ERROR: %s fails to parse:"%fpath) + print(e) return False doc.xinclude() try: xmlschema.assertValid(doc) - except Exception, e: - print "ERROR: %s fails to validate:" % fpath - print e + except Exception as e: + print("ERROR: %s fails to validate:" % fpath) + print(e) return False return True @@ -477,8 +477,8 @@ else: if err or eh.errors: for e in eh.errors: - print e.rstrip("\n") - print "%s fails to validate" % fpath + print(e.rstrip("\n")) + print("%s fails to validate" % fpath) return False return True @@ -599,7 +599,7 @@ class SConsDocTree: # Create xpath context self.xpath_context = self.doc.xpathNewContext() # Register namespaces - for key, val in self.nsmap.iteritems(): + for key, val in self.nsmap.items(): self.xpath_context.xpathRegisterNs(key, val) def __del__(self): @@ -637,8 +637,8 @@ def validate_all_xml(dpaths, xsdfile=default_xsd): fails = [] for idx, fp in enumerate(fpaths): fpath = os.path.join(path, fp) - print "%.2f%s (%d/%d) %s" % (float(idx+1)*100.0/float(len(fpaths)), - perc, idx+1, len(fpaths),fp) + print("%.2f%s (%d/%d) %s" % (float(idx+1)*100.0/float(len(fpaths)), + perc, idx+1, len(fpaths),fp)) if not tf.validateXml(fp, xmlschema_context): fails.append(fp) @@ -810,7 +810,7 @@ def importfile(path): file = open(path, 'r') try: module = imp.load_module(name, file, path, (ext, 'r', kind)) - except ImportError, e: + except ImportError as e: sys.stderr.write("Could not import %s: %s\n" % (path, e)) return None file.close() diff --git a/bin/SConsExamples.py b/bin/SConsExamples.py index 9823a05..e3a7502 100644 --- a/bin/SConsExamples.py +++ b/bin/SConsExamples.py @@ -265,7 +265,7 @@ def ensureExampleOutputsExist(dpath): os.mkdir(generated_examples) examples = readAllExampleInfos(dpath) - for key, value in examples.iteritems(): + for key, value in examples.items(): # Process all scons_output tags for o in value.outputs: cpath = os.path.join(generated_examples, @@ -303,10 +303,10 @@ def createAllExampleOutputs(dpath): examples = readAllExampleInfos(dpath) total = len(examples) idx = 0 - for key, value in examples.iteritems(): + for key, value in examples.items(): # Process all scons_output tags - print "%.2f%s (%d/%d) %s" % (float(idx + 1) * 100.0 / float(total), - perc, idx + 1, total, key) + print("%.2f%s (%d/%d) %s" % (float(idx + 1) * 100.0 / float(total), + perc, idx + 1, total, key)) create_scons_output(value) # Process all scons_example_file tags @@ -344,7 +344,7 @@ def collectSConsExampleNames(fpath): if n not in suffixes: suffixes[n] = [] else: - print "Error: Example in file '%s' is missing a name!" % fpath + print("Error: Example in file '%s' is missing a name!" % fpath) failed_suffixes = True for o in stf.findAll(t.root, "scons_output", SConsDoc.dbxid, @@ -353,11 +353,11 @@ def collectSConsExampleNames(fpath): if stf.hasAttribute(o, 'example'): n = stf.getAttribute(o, 'example') else: - print "Error: scons_output in file '%s' is missing an example name!" % fpath + print("Error: scons_output in file '%s' is missing an example name!" % fpath) failed_suffixes = True if n not in suffixes: - print "Error: scons_output in file '%s' is referencing non-existent example '%s'!" % (fpath, n) + print("Error: scons_output in file '%s' is referencing non-existent example '%s'!" % (fpath, n)) failed_suffixes = True continue @@ -365,13 +365,13 @@ def collectSConsExampleNames(fpath): if stf.hasAttribute(o, 'suffix'): s = stf.getAttribute(o, 'suffix') else: - print "Error: scons_output in file '%s' (example '%s') is missing a suffix!" % (fpath, n) + print("Error: scons_output in file '%s' (example '%s') is missing a suffix!" % (fpath, n)) failed_suffixes = True if s not in suffixes[n]: suffixes[n].append(s) else: - print "Error: scons_output in file '%s' (example '%s') is using a duplicate suffix '%s'!" % (fpath, n, s) + print("Error: scons_output in file '%s' (example '%s') is using a duplicate suffix '%s'!" % (fpath, n, s)) failed_suffixes = True return names, failed_suffixes @@ -392,7 +392,7 @@ def exampleNamesAreUnique(dpath): unique = False i = allnames.intersection(names) if i: - print "Not unique in %s are: %s" % (fpath, ', '.join(i)) + print("Not unique in %s are: %s" % (fpath, ', '.join(i))) unique = False allnames |= names diff --git a/bin/calibrate.py b/bin/calibrate.py index 8ed2ece..31c04e8 100644 --- a/bin/calibrate.py +++ b/bin/calibrate.py @@ -20,7 +20,7 @@ # 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 + import optparse import os @@ -48,7 +48,7 @@ def main(argv=None): for arg in args: if len(args) > 1: - print arg + ':' + print(arg + ':') command = [sys.executable, 'runtest.py'] if opts.package: @@ -67,9 +67,9 @@ def main(argv=None): try: elapsed = float(em.group(1)) except AttributeError: - print output + print(output) raise - print "run %3d: %7.3f: %s" % (run, elapsed, ' '.join(vm.groups())) + print("run %3d: %7.3f: %s" % (run, elapsed, ' '.join(vm.groups()))) if opts.min < elapsed and elapsed < opts.max: good += 1 else: diff --git a/bin/caller-tree.py b/bin/caller-tree.py index 03c1616..327e6a1 100644 --- a/bin/caller-tree.py +++ b/bin/caller-tree.py @@ -74,19 +74,19 @@ for line in sys.stdin.readlines(): stack = [] def print_entry(e, level, calls): - print '%-72s%6s' % ((' '*2*level) + e.file_line_func, calls) + print('%-72s%6s' % ((' '*2*level) + e.file_line_func, calls)) if e in stack: - print (' '*2*(level+1))+'RECURSION' - print + print((' '*2*(level+1))+'RECURSION') + print() elif e.called_by: stack.append(e) for c in e.called_by: print_entry(c[0], level+1, c[1]) stack.pop() else: - print + print() -for e in [ e for e in AllCalls.values() if not e.calls ]: +for e in [ e for e in list(AllCalls.values()) if not e.calls ]: print_entry(e, 0, '') # Local Variables: diff --git a/bin/docs-create-example-outputs.py b/bin/docs-create-example-outputs.py index 30dc0ee..b2dfbea 100644 --- a/bin/docs-create-example-outputs.py +++ b/bin/docs-create-example-outputs.py @@ -9,11 +9,11 @@ import sys import SConsExamples if __name__ == "__main__": - print "Checking whether all example names are unique..." + print("Checking whether all example names are unique...") if SConsExamples.exampleNamesAreUnique(os.path.join('doc','user')): - print "OK" + print("OK") else: - print "Not all example names and suffixes are unique! Please correct the errors listed above and try again." + print("Not all example names and suffixes are unique! Please correct the errors listed above and try again.") sys.exit(0) SConsExamples.createAllExampleOutputs(os.path.join('doc','user')) diff --git a/bin/docs-update-generated.py b/bin/docs-update-generated.py index 66b22c0..2b419a4 100644 --- a/bin/docs-update-generated.py +++ b/bin/docs-update-generated.py @@ -38,7 +38,7 @@ def generate_all(): try: os.makedirs(gen_folder) except: - print "Couldn't create destination folder %s! Exiting..." % gen_folder + print("Couldn't create destination folder %s! Exiting..." % gen_folder) return # Call scons-proc.py os.system('python %s -b %s -f %s -t %s -v %s %s' % diff --git a/bin/docs-validate.py b/bin/docs-validate.py index c445c3f..e5d0659 100644 --- a/bin/docs-validate.py +++ b/bin/docs-validate.py @@ -10,9 +10,9 @@ import SConsDoc if __name__ == "__main__": if len(sys.argv)>1: if SConsDoc.validate_all_xml((sys.argv[1],)): - print "OK" + print("OK") else: - print "Validation failed! Please correct the errors above and try again." + print("Validation failed! Please correct the errors above and try again.") else: if SConsDoc.validate_all_xml(['src', os.path.join('doc','design'), @@ -22,6 +22,6 @@ if __name__ == "__main__": os.path.join('doc','reference'), os.path.join('doc','user') ]): - print "OK" + print("OK") else: - print "Validation failed! Please correct the errors above and try again." + print("Validation failed! Please correct the errors above and try again.") diff --git a/bin/install_python.py b/bin/install_python.py index 86807af..dca37d0 100644 --- a/bin/install_python.py +++ b/bin/install_python.py @@ -48,7 +48,7 @@ Usage: install_python.py [-ahnq] [-d DIR] [-p PREFIX] [VERSION ...] try: try: opts, args = getopt.getopt(argv[1:], short_options, long_options) - except getopt.error, msg: + except getopt.error as msg: raise Usage(msg) for o, a in opts: @@ -57,7 +57,7 @@ Usage: install_python.py [-ahnq] [-d DIR] [-p PREFIX] [VERSION ...] elif o in ('-d', '--downloads'): downloads_dir = a elif o in ('-h', '--help'): - print helpstr + print(helpstr) sys.exit(0) elif o in ('-n', '--no-exec'): CommandRunner.execute = CommandRunner.do_not_execute @@ -65,7 +65,7 @@ Usage: install_python.py [-ahnq] [-d DIR] [-p PREFIX] [VERSION ...] prefix = a elif o in ('-q', '--quiet'): CommandRunner.display = CommandRunner.do_not_display - except Usage, err: + except Usage as err: sys.stderr.write(str(err.msg) + '\n') sys.stderr.write('use -h to get help\n') return 2 diff --git a/bin/install_scons.py b/bin/install_scons.py index 00129f6..b732193 100644 --- a/bin/install_scons.py +++ b/bin/install_scons.py @@ -23,7 +23,7 @@ import os import shutil import sys import tarfile -import urllib +import urllib.request, urllib.parse, urllib.error from Command import CommandRunner, Usage @@ -129,7 +129,7 @@ Usage: install_scons.py [-ahnq] [-d DIR] [-p PREFIX] [VERSION ...] try: try: opts, args = getopt.getopt(argv[1:], short_options, long_options) - except getopt.error, msg: + except getopt.error as msg: raise Usage(msg) for o, a in opts: @@ -138,7 +138,7 @@ Usage: install_scons.py [-ahnq] [-d DIR] [-p PREFIX] [VERSION ...] elif o in ('-d', '--downloads'): downloads_dir = a elif o in ('-h', '--help'): - print helpstr + print(helpstr) sys.exit(0) elif o in ('-n', '--no-exec'): CommandRunner.execute = CommandRunner.do_not_execute @@ -146,7 +146,7 @@ Usage: install_scons.py [-ahnq] [-d DIR] [-p PREFIX] [VERSION ...] prefix = a elif o in ('-q', '--quiet'): CommandRunner.display = CommandRunner.do_not_display - except Usage, err: + except Usage as err: sys.stderr.write(str(err.msg) + '\n') sys.stderr.write('use -h to get help\n') return 2 @@ -171,7 +171,7 @@ Usage: install_scons.py [-ahnq] [-d DIR] [-p PREFIX] [VERSION ...] if not os.path.exists(tar_gz): if not os.path.exists(downloads_dir): cmd.run('mkdir %(downloads_dir)s') - cmd.run((urllib.urlretrieve, tar_gz_url, tar_gz), + cmd.run((urllib.request.urlretrieve, tar_gz_url, tar_gz), 'wget -O %(tar_gz)s %(tar_gz_url)s') def extract(tar_gz): diff --git a/bin/linecount.py b/bin/linecount.py index 6f49dca..2d478f0 100644 --- a/bin/linecount.py +++ b/bin/linecount.py @@ -21,7 +21,7 @@ # in each category, the number of non-blank lines, and the number of # non-comment lines. The last figure (non-comment) lines is the most # interesting one for most purposes. -from __future__ import division + __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -98,23 +98,23 @@ all_tests = Collection('all tests', src_tests.files + test_tests.files) def ratio(over, under): return "%.2f" % (float(len(over)) / float(len(under))) -print fmt % ('', '', '', '', '', 'non-blank') -print fmt % ('', 'files', 'lines', 'non-blank', 'non-comment', 'non-comment') -print -print fmt % src_Tests_py_tests.printables() -print fmt % src_test_tests.printables() -print -print fmt % src_tests.printables() -print fmt % test_tests.printables() -print -print fmt % all_tests.printables() -print fmt % sources.printables() -print -print fmt % ('ratio:', +print(fmt % ('', '', '', '', '', 'non-blank')) +print(fmt % ('', 'files', 'lines', 'non-blank', 'non-comment', 'non-comment')) +print() +print(fmt % src_Tests_py_tests.printables()) +print(fmt % src_test_tests.printables()) +print() +print(fmt % src_tests.printables()) +print(fmt % test_tests.printables()) +print() +print(fmt % all_tests.printables()) +print(fmt % sources.printables()) +print() +print(fmt % ('ratio:', ratio(all_tests, sources), ratio(all_tests.lines(), sources.lines()), ratio(all_tests.non_blank(), sources.non_blank()), ratio(all_tests.non_comment(), sources.non_comment()), ratio(all_tests.non_blank_non_comment(), sources.non_blank_non_comment()) - ) + )) diff --git a/bin/memlogs.py b/bin/memlogs.py index 9d957c9..0409dfe 100644 --- a/bin/memlogs.py +++ b/bin/memlogs.py @@ -27,20 +27,20 @@ import sys filenames = sys.argv[1:] if not filenames: - print """Usage: memlogs.py file [...] + print("""Usage: memlogs.py file [...] Summarizes the --debug=memory numbers from one or more build logs. -""" +""") sys.exit(0) fmt = "%12s %12s %12s %12s %s" -print fmt % ("pre-read", "post-read", "pre-build", "post-build", "") +print(fmt % ("pre-read", "post-read", "pre-build", "post-build", "")) for fname in sys.argv[1:]: lines = [l for l in open(fname).readlines() if l[:7] == 'Memory '] t = tuple([l.split()[-1] for l in lines]) + (fname,) - print fmt % t + print(fmt % t) # Local Variables: # tab-width:4 diff --git a/bin/memoicmp.py b/bin/memoicmp.py index 812af66..5021c41 100644 --- a/bin/memoicmp.py +++ b/bin/memoicmp.py @@ -23,20 +23,20 @@ def memoize_cmp(filea, fileb): ma = memoize_output(filea) mb = memoize_output(fileb) - print 'All output: %s / %s [delta]'%(filea, fileb) - print '----------HITS---------- ---------MISSES---------' + print('All output: %s / %s [delta]'%(filea, fileb)) + print('----------HITS---------- ---------MISSES---------') cfmt='%7d/%-7d [%d]' ma_o = [] mb_o = [] mab = [] - for k in ma.keys(): - if k in mb.keys(): + for k in list(ma.keys()): + if k in list(mb.keys()): if k not in mab: mab.append(k) else: ma_o.append(k) - for k in mb.keys(): - if k in ma.keys(): + for k in list(mb.keys()): + if k in list(ma.keys()): if k not in mab: mab.append(k) else: @@ -49,26 +49,26 @@ def memoize_cmp(filea, fileb): for k in mab: hits = cfmt%(ma[k][0], mb[k][0], mb[k][0]-ma[k][0]) miss = cfmt%(ma[k][1], mb[k][1], mb[k][1]-ma[k][1]) - print '%-24s %-24s %s'%(hits, miss, k) + print('%-24s %-24s %s'%(hits, miss, k)) for k in ma_o: hits = '%7d/ --'%(ma[k][0]) miss = '%7d/ --'%(ma[k][1]) - print '%-24s %-24s %s'%(hits, miss, k) + print('%-24s %-24s %s'%(hits, miss, k)) for k in mb_o: hits = ' -- /%-7d'%(mb[k][0]) miss = ' -- /%-7d'%(mb[k][1]) - print '%-24s %-24s %s'%(hits, miss, k) + print('%-24s %-24s %s'%(hits, miss, k)) - print '-'*(24+24+1+20) + print('-'*(24+24+1+20)) if __name__ == "__main__": if len(sys.argv) != 3: - print """Usage: %s file1 file2 + print("""Usage: %s file1 file2 -Compares --debug=memomize output from file1 against file2."""%sys.argv[0] +Compares --debug=memomize output from file1 against file2."""%sys.argv[0]) sys.exit(1) memoize_cmp(sys.argv[1], sys.argv[2]) diff --git a/bin/objcounts.py b/bin/objcounts.py index 0662012..25b985b 100644 --- a/bin/objcounts.py +++ b/bin/objcounts.py @@ -27,10 +27,10 @@ import sys filenames = sys.argv[1:] if len(sys.argv) != 3: - print """Usage: objcounts.py file1 file2 + print("""Usage: objcounts.py file1 file2 Compare the --debug=object counts from two build logs. -""" +""") sys.exit(0) def fetch_counts(fname): @@ -47,7 +47,7 @@ c1 = fetch_counts(sys.argv[1]) c2 = fetch_counts(sys.argv[2]) common = {} -for k in c1.keys(): +for k in list(c1.keys()): try: common[k] = (c1[k], c2[k]) except KeyError: @@ -58,7 +58,7 @@ for k in c1.keys(): if not '.' in k: s = '.'+k l = len(s) - for k2 in c2.keys(): + for k2 in list(c2.keys()): if k2[-l:] == s: common[k2] = (c1[k], c2[k2]) del c1[k] @@ -81,10 +81,9 @@ def diffstr(c1, c2): return " %5s/%-5s %-8s" % (c1, c2, d) def printline(c1, c2, classname): - print \ - diffstr(c1[2], c2[2]) + \ + print(diffstr(c1[2], c2[2]) + \ diffstr(c1[3], c2[3]) + \ - ' ' + classname + ' ' + classname) for k in sorted(common.keys()): c = common[k] diff --git a/bin/scons-diff.py b/bin/scons-diff.py index 52bd51b..5181fa1 100644 --- a/bin/scons-diff.py +++ b/bin/scons-diff.py @@ -43,7 +43,7 @@ def diff_line(left, right): opts = ' ' + ' '.join(diff_options) else: opts = '' - print 'diff%s %s %s' % (opts, left, right) + print('diff%s %s %s' % (opts, left, right)) for o, a in opts: if o in ('-c', '-u'): @@ -51,7 +51,7 @@ for o, a in opts: context = int(a) diff_options.append(o) elif o in ('-h', '--help'): - print Usage + print(Usage) sys.exit(0) elif o in ('-n'): diff_options.append(o) @@ -161,9 +161,9 @@ def diff_file(left, right): else: if text: diff_line(left, right) - print text, + print(text, end=' ') elif report_same: - print 'Files %s and %s are identical' % (left, right) + print('Files %s and %s are identical' % (left, right)) def diff_dir(left, right): llist = os.listdir(left) @@ -173,16 +173,16 @@ def diff_dir(left, right): u[l] = 1 for r in rlist: u[r] = 1 - for x in sorted([ x for x in u.keys() if x[-4:] != '.pyc' ]): + for x in sorted([ x for x in list(u.keys()) if x[-4:] != '.pyc' ]): if x in llist: if x in rlist: do_diff(os.path.join(left, x), os.path.join(right, x), recursive) else: - print 'Only in %s: %s' % (left, x) + print('Only in %s: %s' % (left, x)) else: - print 'Only in %s: %s' % (right, x) + print('Only in %s: %s' % (right, x)) do_diff(left, right, True) diff --git a/bin/scons-proc.py b/bin/scons-proc.py index 9567db8..19be4c3 100644 --- a/bin/scons-proc.py +++ b/bin/scons-proc.py @@ -106,7 +106,7 @@ Link_Entities_Header = """\ class SCons_XML(object): def __init__(self, entries, **kw): self.values = entries - for k, v in kw.items(): + for k, v in list(kw.items()): setattr(self, k, v) def fopen(self, name): @@ -344,25 +344,25 @@ def write_output_files(h, buildersfiles, functionsfiles, processor_class = SCons_XML # Step 1: Creating entity files for builders, functions,... -print "Generating entity files..." +print("Generating entity files...") h = parse_docs(args, False) write_output_files(h, buildersfiles, functionsfiles, toolsfiles, variablesfiles, SCons_XML.write_mod) # Step 2: Validating all input files -print "Validating files against SCons XSD..." +print("Validating files against SCons XSD...") if SConsDoc.validate_all_xml(['src']): - print "OK" + print("OK") else: - print "Validation failed! Please correct the errors above and try again." + print("Validation failed! Please correct the errors above and try again.") # Step 3: Creating actual documentation snippets, using the # fully resolved and updated entities from the *.mod files. -print "Updating documentation for builders, tools and functions..." +print("Updating documentation for builders, tools and functions...") h = parse_docs(args, True) write_output_files(h, buildersfiles, functionsfiles, toolsfiles, variablesfiles, SCons_XML.write) -print "Done" +print("Done") # Local Variables: # tab-width:4 diff --git a/bin/scons-test.py b/bin/scons-test.py index 046cf4b..788fc6d 100644 --- a/bin/scons-test.py +++ b/bin/scons-test.py @@ -60,7 +60,7 @@ for o, a in opts: outdir = a elif o == '-v' or o == '--verbose': def printname(x): - print x + print(x) elif o == '--xml': format = o @@ -148,34 +148,34 @@ else: if format == '--xml': - print "" - print " " + print("") + print(" ") sys_keys = ['byteorder', 'exec_prefix', 'executable', 'maxint', 'maxunicode', 'platform', 'prefix', 'version', 'version_info'] for k in sys_keys: - print " <%s>%s" % (k, sys.__dict__[k], k) - print " " + print(" <%s>%s" % (k, sys.__dict__[k], k)) + print(" ") fmt = '%a %b %d %H:%M:%S %Y' - print " " + print(" ") - print " %s" % tempdir + print(" %s" % tempdir) def print_version_info(tag, module): - print " <%s>" % tag - print " %s" % module.__version__ - print " %s" % module.__build__ - print " %s" % module.__buildsys__ - print " %s" % module.__date__ - print " %s" % module.__developer__ - print " " % tag - - print " " + print(" <%s>" % tag) + print(" %s" % module.__version__) + print(" %s" % module.__build__) + print(" %s" % module.__buildsys__) + print(" %s" % module.__date__) + print(" %s" % module.__developer__) + print(" " % tag) + + print(" ") print_version_info("script", scons) print_version_info("engine", SCons) - print " " + print(" ") environ_keys = [ 'PATH', @@ -213,32 +213,32 @@ if format == '--xml': 'USER', ] - print " " + print(" ") for key in sorted(environ_keys): value = os.environ.get(key) if value: - print " " - print " %s" % key - print " %s" % value - print " " - print " " + print(" ") + print(" %s" % key) + print(" %s" % value) + print(" ") + print(" ") command = '"%s" runtest.py -q -o - --xml %s' % (sys.executable, runtest_args) #print command os.system(command) - print "" + print("") else: def print_version_info(tag, module): - print "\t%s: v%s.%s, %s, by %s on %s" % (tag, + print("\t%s: v%s.%s, %s, by %s on %s" % (tag, module.__version__, module.__build__, module.__date__, module.__developer__, - module.__buildsys__) + module.__buildsys__)) - print "SCons by Steven Knight et al.:" + print("SCons by Steven Knight et al.:") print_version_info("script", scons) print_version_info("engine", SCons) diff --git a/bin/scons-unzip.py b/bin/scons-unzip.py index d4ec4bf..75d3281 100644 --- a/bin/scons-unzip.py +++ b/bin/scons-unzip.py @@ -32,7 +32,7 @@ for o, a in opts: outdir = a elif o == '-v' or o == '--verbose': def printname(x): - print x + print(x) if len(args) != 1: sys.stderr.write("scons-unzip.py: \n") diff --git a/bin/scons_dev_master.py b/bin/scons_dev_master.py index 3c41ac0..71034ad 100644 --- a/bin/scons_dev_master.py +++ b/bin/scons_dev_master.py @@ -131,12 +131,12 @@ Usage: scons_dev_master.py [-hnqy] [--password PASSWORD] [--username USER] try: try: opts, args = getopt.getopt(argv[1:], short_options, long_options) - except getopt.error, msg: + except getopt.error as msg: raise Usage(msg) for o, a in opts: if o in ('-h', '--help'): - print helpstr + print(helpstr) sys.exit(0) elif o in ('-n', '--no-exec'): CommandRunner.execute = CommandRunner.do_not_execute @@ -148,7 +148,7 @@ Usage: scons_dev_master.py [-hnqy] [--password PASSWORD] [--username USER] username = a elif o in ('-y', '--yes', '--assume-yes'): yesflag = o - except Usage, err: + except Usage as err: sys.stderr.write(str(err.msg) + '\n') sys.stderr.write('use -h to get help\n') return 2 diff --git a/bin/svn-bisect.py b/bin/svn-bisect.py index 77bda58..f262366 100755 --- a/bin/svn-bisect.py +++ b/bin/svn-bisect.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- Python -*- -from __future__ import division + import sys from math import log, ceil @@ -28,22 +28,22 @@ script = script_args[2:] # print an error message and quit def error(s): - print >>sys.stderr, "******", s, "******" + print("******", s, "******", file=sys.stderr) sys.exit(1) # update to the specified version and run test def testfail(revision): "Return true if test fails" - print "Updating to revision", revision + print("Updating to revision", revision) if subprocess.call(["svn","up","-qr",str(revision)]) != 0: m = "SVN did not update properly to revision %d" raise RuntimeError(m % revision) return subprocess.call(script,shell=False) != 0 # confirm that the endpoints are different -print "****** Checking upper bracket", upper +print("****** Checking upper bracket", upper) upperfails = testfail(upper) -print "****** Checking lower bracket", lower +print("****** Checking lower bracket", lower) lowerfails = testfail(lower) if upperfails == lowerfails: error("Upper and lower revisions must bracket the failure") @@ -51,7 +51,7 @@ if upperfails == lowerfails: # binary search for transition msg = "****** max %d revisions to test (bug bracketed by [%d,%d])" while upper-lower > 1: - print msg % (ceil(log(upper-lower,2)), lower, upper) + print(msg % (ceil(log(upper-lower,2)), lower, upper)) mid = (lower + upper)//2 midfails = testfail(mid) @@ -64,7 +64,7 @@ while upper-lower > 1: # show which revision was first to fail if upperfails != lowerfails: lower = upper -print "The error was caused by revision", lower +print("The error was caused by revision", lower) # Local Variables: # tab-width:4 diff --git a/bin/update-release-info.py b/bin/update-release-info.py index 338bba9..f60c187 100644 --- a/bin/update-release-info.py +++ b/bin/update-release-info.py @@ -73,14 +73,14 @@ if len(sys.argv) < 2: else: mode = sys.argv[1] if mode not in ['develop', 'release', 'post']: - print("""ERROR: `%s' as a parameter is invalid; it must be one of -\tdevelop, release, or post. The default is develop.""" % mode) + print(("""ERROR: `%s' as a parameter is invalid; it must be one of +\tdevelop, release, or post. The default is develop.""" % mode)) sys.exit(1) # Get configuration information config = dict() -exec open('ReleaseConfig').read() in globals(), config +exec(open('ReleaseConfig').read(), globals(), config) try: version_tuple = config['version_tuple'] @@ -90,9 +90,9 @@ except KeyError: print('''ERROR: Config file must contain at least version_tuple, \tunsupported_python_version, and deprecated_python_version.''') sys.exit(1) -if DEBUG: print 'version tuple', version_tuple -if DEBUG: print 'unsupported Python version', unsupported_version -if DEBUG: print 'deprecated Python version', deprecated_version +if DEBUG: print('version tuple', version_tuple) +if DEBUG: print('unsupported Python version', unsupported_version) +if DEBUG: print('deprecated Python version', deprecated_version) try: release_date = config['release_date'] @@ -102,9 +102,9 @@ else: if len(release_date) == 3: release_date = release_date + time.localtime()[3:6] if len(release_date) != 6: - print '''ERROR: Invalid release date''', release_date + print('''ERROR: Invalid release date''', release_date) sys.exit(1) -if DEBUG: print 'release date', release_date +if DEBUG: print('release date', release_date) if mode == 'develop' and version_tuple[3] != 'alpha': version_tuple == version_tuple[:3] + ('alpha', 0) @@ -119,11 +119,11 @@ if len(version_tuple) > 3: version_type = version_tuple[3] else: version_type = 'final' -if DEBUG: print 'version string', version_string +if DEBUG: print('version string', version_string) if version_type not in ['alpha', 'beta', 'candidate', 'final']: - print("""ERROR: `%s' is not a valid release type in version tuple; -\tit must be one of alpha, beta, candidate, or final""" % version_type) + print(("""ERROR: `%s' is not a valid release type in version tuple; +\tit must be one of alpha, beta, candidate, or final""" % version_type)) sys.exit(1) try: @@ -133,13 +133,13 @@ except KeyError: month_year = 'MONTH YEAR' else: month_year = time.strftime('%B %Y', release_date + (0,0,0)) -if DEBUG: print 'month year', month_year +if DEBUG: print('month year', month_year) try: copyright_years = config['copyright_years'] except KeyError: copyright_years = ', '.join(map(str, list(range(2001, release_date[0] + 1)))) -if DEBUG: print 'copyright years', copyright_years +if DEBUG: print('copyright years', copyright_years) class UpdateFile(object): """ @@ -218,7 +218,7 @@ class UpdateFile(object): XXX ''' if self.file is not None and self.content != self.orig: - print 'Updating ' + self.file + '...' + print('Updating ' + self.file + '...') open(self.file, 'w').write(self.content) if mode == 'post': @@ -332,7 +332,7 @@ t.replace_assign('deprecated_python_version', str(deprecated_version)) # Update doc/user/main.{in,xml} -docyears = ', '.join(map(str, iter(range(2004, release_date[0] + 1)))) +docyears = ', '.join(map(str, iter(list(range(2004, release_date[0] + 1))))) t = UpdateFile(os.path.join('doc', 'user', 'main.in')) if DEBUG: t.file = '/tmp/main.in' ## TODO debug these diff --git a/bin/xmlagenda.py b/bin/xmlagenda.py index b3cd520..40f5ca1 100755 --- a/bin/xmlagenda.py +++ b/bin/xmlagenda.py @@ -89,7 +89,7 @@ for issue in issues: writer.writerow(['','','','','','','']) for member in team: writer.writerow(['','',member,'','','','']) -print "Exported %d issues to editlist.csv. Ready to upload to Google."%len(issues) +print("Exported %d issues to editlist.csv. Ready to upload to Google."%len(issues)) # Local Variables: # tab-width:4 diff --git a/review.py b/review.py index 23e4b10..72e187e 100644 --- a/review.py +++ b/review.py @@ -1,1805 +1,1806 @@ -#!/usr/bin/env python -# -# Copyright 2007 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Tool for uploading diffs from a version control system to the codereview app. - -Usage summary: upload.py [options] [-- diff_options] [path...] - -Diff options are passed to the diff command of the underlying system. - -Supported version control systems: - Git - Mercurial - Subversion - -It is important for Git/Mercurial users to specify a tree/node/branch to diff -against by using the '--rev' option. -""" -# This code is derived from appcfg.py in the App Engine SDK (open source), -# and from ASPN recipe #146306. - -import ConfigParser -import cookielib -import fnmatch -import getpass -import logging -import mimetypes -import optparse -import os -import re -import socket -import subprocess -import sys -import urllib -import urllib2 -import urlparse - -# The md5 module was deprecated in Python 2.5. -try: - from hashlib import md5 -except ImportError: - from md5 import md5 - -try: - import readline -except ImportError: - pass - -try: - import keyring -except ImportError: - keyring = None - -# The logging verbosity: -# 0: Errors only. -# 1: Status messages. -# 2: Info logs. -# 3: Debug logs. -verbosity = 1 - -# The account type used for authentication. -# This line could be changed by the review server (see handler for -# upload.py). -AUTH_ACCOUNT_TYPE = "GOOGLE" - -# URL of the default review server. As for AUTH_ACCOUNT_TYPE, this line could be -# changed by the review server (see handler for upload.py). -DEFAULT_REVIEW_SERVER = "codereview.appspot.com" - -# Max size of patch or base file. -MAX_UPLOAD_SIZE = 900 * 1024 - -# Constants for version control names. Used by GuessVCSName. -VCS_GIT = "Git" -VCS_MERCURIAL = "Mercurial" -VCS_SUBVERSION = "Subversion" -VCS_UNKNOWN = "Unknown" - -# whitelist for non-binary filetypes which do not start with "text/" -# .mm (Objective-C) shows up as application/x-freemind on my Linux box. -TEXT_MIMETYPES = ['application/javascript', 'application/x-javascript', - 'application/xml', 'application/x-freemind', - 'application/x-sh'] - -VCS_ABBREVIATIONS = { - VCS_MERCURIAL.lower(): VCS_MERCURIAL, - "hg": VCS_MERCURIAL, - VCS_SUBVERSION.lower(): VCS_SUBVERSION, - "svn": VCS_SUBVERSION, - VCS_GIT.lower(): VCS_GIT, -} - -# The result of parsing Subversion's [auto-props] setting. -svn_auto_props_map = None - -def GetEmail(prompt): - """Prompts the user for their email address and returns it. - - The last used email address is saved to a file and offered up as a suggestion - to the user. If the user presses enter without typing in anything the last - used email address is used. If the user enters a new address, it is saved - for next time we prompt. - - """ - last_email_file_name = os.path.expanduser("~/.last_codereview_email_address") - last_email = "" - if os.path.exists(last_email_file_name): - try: - last_email_file = open(last_email_file_name, "r") - last_email = last_email_file.readline().strip("\n") - last_email_file.close() - prompt += " [%s]" % last_email - except IOError, e: - pass - email = raw_input(prompt + ": ").strip() - if email: - try: - last_email_file = open(last_email_file_name, "w") - last_email_file.write(email) - last_email_file.close() - except IOError, e: - pass - else: - email = last_email - return email - - -def StatusUpdate(msg): - """Print a status message to stdout. - - If 'verbosity' is greater than 0, print the message. - - Args: - msg: The string to print. - """ - if verbosity > 0: - print msg - - -def ErrorExit(msg): - """Print an error message to stderr and exit.""" - print >>sys.stderr, msg - sys.exit(1) - - -class ClientLoginError(urllib2.HTTPError): - """Raised to indicate there was an error authenticating with ClientLogin.""" - - def __init__(self, url, code, msg, headers, args): - urllib2.HTTPError.__init__(self, url, code, msg, headers, None) - self.args = args - self.reason = args["Error"] - self.info = args.get("Info", None) - - -class AbstractRpcServer(object): - """Provides a common interface for a simple RPC server.""" - - def __init__(self, host, auth_function, host_override=None, extra_headers={}, - save_cookies=False, account_type=AUTH_ACCOUNT_TYPE): - """Creates a new HttpRpcServer. - - Args: - host: The host to send requests to. - auth_function: A function that takes no arguments and returns an - (email, password) tuple when called. Will be called if authentication - is required. - host_override: The host header to send to the server (defaults to host). - extra_headers: A dict of extra headers to append to every request. - save_cookies: If True, save the authentication cookies to local disk. - If False, use an in-memory cookiejar instead. Subclasses must - implement this functionality. Defaults to False. - account_type: Account type used for authentication. Defaults to - AUTH_ACCOUNT_TYPE. - """ - self.host = host - if (not self.host.startswith("http://") and - not self.host.startswith("https://")): - self.host = "http://" + self.host - self.host_override = host_override - self.auth_function = auth_function - self.authenticated = False - self.extra_headers = extra_headers - self.save_cookies = save_cookies - self.account_type = account_type - self.opener = self._GetOpener() - if self.host_override: - logging.info("Server: %s; Host: %s", self.host, self.host_override) - else: - logging.info("Server: %s", self.host) - - def _GetOpener(self): - """Returns an OpenerDirector for making HTTP requests. - - Returns: - A urllib2.OpenerDirector object. - """ - raise NotImplementedError() - - def _CreateRequest(self, url, data=None): - """Creates a new urllib request.""" - logging.debug("Creating request for: '%s' with payload:\n%s", url, data) - req = urllib2.Request(url, data=data) - if self.host_override: - req.add_header("Host", self.host_override) - for key, value in self.extra_headers.iteritems(): - req.add_header(key, value) - return req - - def _GetAuthToken(self, email, password): - """Uses ClientLogin to authenticate the user, returning an auth token. - - Args: - email: The user's email address - password: The user's password - - Raises: - ClientLoginError: If there was an error authenticating with ClientLogin. - HTTPError: If there was some other form of HTTP error. - - Returns: - The authentication token returned by ClientLogin. - """ - account_type = self.account_type - if self.host.endswith(".google.com"): - # Needed for use inside Google. - account_type = "HOSTED" - req = self._CreateRequest( - url="https://www.google.com/accounts/ClientLogin", - data=urllib.urlencode({ - "Email": email, - "Passwd": password, - "service": "ah", - "source": "rietveld-codereview-upload", - "accountType": account_type, - }), - ) - try: - response = self.opener.open(req) - response_body = response.read() - response_dict = dict(x.split("=") - for x in response_body.split("\n") if x) - return response_dict["Auth"] - except urllib2.HTTPError, e: - if e.code == 403: - body = e.read() - response_dict = dict(x.split("=", 1) for x in body.split("\n") if x) - raise ClientLoginError(req.get_full_url(), e.code, e.msg, - e.headers, response_dict) - else: - raise - - def _GetAuthCookie(self, auth_token): - """Fetches authentication cookies for an authentication token. - - Args: - auth_token: The authentication token returned by ClientLogin. - - Raises: - HTTPError: If there was an error fetching the authentication cookies. - """ - # This is a dummy value to allow us to identify when we're successful. - continue_location = "http://localhost/" - args = {"continue": continue_location, "auth": auth_token} - req = self._CreateRequest("%s/_ah/login?%s" % - (self.host, urllib.urlencode(args))) - try: - response = self.opener.open(req) - except urllib2.HTTPError, e: - response = e - if (response.code != 302 or - response.info()["location"] != continue_location): - raise urllib2.HTTPError(req.get_full_url(), response.code, response.msg, - response.headers, response.fp) - self.authenticated = True - - def _Authenticate(self): - """Authenticates the user. - - The authentication process works as follows: - 1) We get a username and password from the user - 2) We use ClientLogin to obtain an AUTH token for the user - (see http://code.google.com/apis/accounts/AuthForInstalledApps.html). - 3) We pass the auth token to /_ah/login on the server to obtain an - authentication cookie. If login was successful, it tries to redirect - us to the URL we provided. - - If we attempt to access the upload API without first obtaining an - authentication cookie, it returns a 401 response (or a 302) and - directs us to authenticate ourselves with ClientLogin. - """ - for i in range(3): - credentials = self.auth_function() - try: - auth_token = self._GetAuthToken(credentials[0], credentials[1]) - except ClientLoginError, e: - print >>sys.stderr, '' - if e.reason == "BadAuthentication": - if e.info == "InvalidSecondFactor": - print >>sys.stderr, ( - "Use an application-specific password instead " - "of your regular account password.\n" - "See http://www.google.com/" - "support/accounts/bin/answer.py?answer=185833") - else: - print >>sys.stderr, "Invalid username or password." - elif e.reason == "CaptchaRequired": - print >>sys.stderr, ( - "Please go to\n" - "https://www.google.com/accounts/DisplayUnlockCaptcha\n" - "and verify you are a human. Then try again.\n" - "If you are using a Google Apps account the URL is:\n" - "https://www.google.com/a/yourdomain.com/UnlockCaptcha") - elif e.reason == "NotVerified": - print >>sys.stderr, "Account not verified." - elif e.reason == "TermsNotAgreed": - print >>sys.stderr, "User has not agreed to TOS." - elif e.reason == "AccountDeleted": - print >>sys.stderr, "The user account has been deleted." - elif e.reason == "AccountDisabled": - print >>sys.stderr, "The user account has been disabled." - break - elif e.reason == "ServiceDisabled": - print >>sys.stderr, ("The user's access to the service has been " - "disabled.") - elif e.reason == "ServiceUnavailable": - print >>sys.stderr, "The service is not available; try again later." - else: - # Unknown error. - raise - print >>sys.stderr, '' - continue - self._GetAuthCookie(auth_token) - return - - def Send(self, request_path, payload=None, - content_type="application/octet-stream", - timeout=None, - extra_headers=None, - **kwargs): - """Sends an RPC and returns the response. - - Args: - request_path: The path to send the request to, eg /api/appversion/create. - payload: The body of the request, or None to send an empty request. - content_type: The Content-Type header to use. - timeout: timeout in seconds; default None i.e. no timeout. - (Note: for large requests on OS X, the timeout doesn't work right.) - extra_headers: Dict containing additional HTTP headers that should be - included in the request (string header names mapped to their values), - or None to not include any additional headers. - kwargs: Any keyword arguments are converted into query string parameters. - - Returns: - The response body, as a string. - """ - # TODO: Don't require authentication. Let the server say - # whether it is necessary. - if not self.authenticated: - self._Authenticate() - - old_timeout = socket.getdefaulttimeout() - socket.setdefaulttimeout(timeout) - try: - tries = 0 - while True: - tries += 1 - args = dict(kwargs) - url = "%s%s" % (self.host, request_path) - if args: - url += "?" + urllib.urlencode(args) - req = self._CreateRequest(url=url, data=payload) - req.add_header("Content-Type", content_type) - if extra_headers: - for header, value in extra_headers.items(): - req.add_header(header, value) - try: - f = self.opener.open(req) - response = f.read() - f.close() - return response - except urllib2.HTTPError, e: - if tries > 3: - raise - elif e.code == 401 or e.code == 302: - self._Authenticate() -## elif e.code >= 500 and e.code < 600: -## # Server Error - try again. -## continue - elif e.code == 301: - # Handle permanent redirect manually. - url = e.info()["location"] - url_loc = urlparse.urlparse(url) - self.host = '%s://%s' % (url_loc[0], url_loc[1]) - else: - raise - finally: - socket.setdefaulttimeout(old_timeout) - - -class HttpRpcServer(AbstractRpcServer): - """Provides a simplified RPC-style interface for HTTP requests.""" - - def _Authenticate(self): - """Save the cookie jar after authentication.""" - super(HttpRpcServer, self)._Authenticate() - if self.save_cookies: - StatusUpdate("Saving authentication cookies to %s" % self.cookie_file) - self.cookie_jar.save() - - def _GetOpener(self): - """Returns an OpenerDirector that supports cookies and ignores redirects. - - Returns: - A urllib2.OpenerDirector object. - """ - opener = urllib2.OpenerDirector() - opener.add_handler(urllib2.ProxyHandler()) - opener.add_handler(urllib2.UnknownHandler()) - opener.add_handler(urllib2.HTTPHandler()) - opener.add_handler(urllib2.HTTPDefaultErrorHandler()) - opener.add_handler(urllib2.HTTPSHandler()) - opener.add_handler(urllib2.HTTPErrorProcessor()) - if self.save_cookies: - self.cookie_file = os.path.expanduser("~/.codereview_upload_cookies") - self.cookie_jar = cookielib.MozillaCookieJar(self.cookie_file) - if os.path.exists(self.cookie_file): - try: - self.cookie_jar.load() - self.authenticated = True - StatusUpdate("Loaded authentication cookies from %s" % - self.cookie_file) - except (cookielib.LoadError, IOError): - # Failed to load cookies - just ignore them. - pass - else: - # Create an empty cookie file with mode 600 - fd = os.open(self.cookie_file, os.O_CREAT, 0600) - os.close(fd) - # Always chmod the cookie file - os.chmod(self.cookie_file, 0600) - else: - # Don't save cookies across runs of update.py. - self.cookie_jar = cookielib.CookieJar() - opener.add_handler(urllib2.HTTPCookieProcessor(self.cookie_jar)) - return opener - - -parser = optparse.OptionParser( - usage="%prog [options] [-- diff_options] [path...]") -parser.add_option("-y", "--assume_yes", action="store_true", - dest="assume_yes", default=False, - help="Assume that the answer to yes/no questions is 'yes'.") -# Logging -group = parser.add_option_group("Logging options") -group.add_option("-q", "--quiet", action="store_const", const=0, - dest="verbose", help="Print errors only.") -group.add_option("-v", "--verbose", action="store_const", const=2, - dest="verbose", default=1, - help="Print info level logs.") -group.add_option("--noisy", action="store_const", const=3, - dest="verbose", help="Print all logs.") -# Review server -group = parser.add_option_group("Review server options") -group.add_option("-s", "--server", action="store", dest="server", - default=DEFAULT_REVIEW_SERVER, - metavar="SERVER", - help=("The server to upload to. The format is host[:port]. " - "Defaults to '%default'.")) -group.add_option("-e", "--email", action="store", dest="email", - metavar="EMAIL", default=None, - help="The username to use. Will prompt if omitted.") -group.add_option("-H", "--host", action="store", dest="host", - metavar="HOST", default=None, - help="Overrides the Host header sent with all RPCs.") -group.add_option("--no_cookies", action="store_false", - dest="save_cookies", default=True, - help="Do not save authentication cookies to local disk.") -group.add_option("--account_type", action="store", dest="account_type", - metavar="TYPE", default=AUTH_ACCOUNT_TYPE, - choices=["GOOGLE", "HOSTED"], - help=("Override the default account type " - "(defaults to '%default', " - "valid choices are 'GOOGLE' and 'HOSTED').")) -# Issue -group = parser.add_option_group("Issue options") -group.add_option("-d", "--description", action="store", dest="description", - metavar="DESCRIPTION", default=None, - help="Optional description when creating an issue.") -group.add_option("-f", "--description_file", action="store", - dest="description_file", metavar="DESCRIPTION_FILE", - default=None, - help="Optional path of a file that contains " - "the description when creating an issue.") -group.add_option("-r", "--reviewers", action="store", dest="reviewers", - metavar="REVIEWERS", default=None, - help="Add reviewers (comma separated email addresses).") -group.add_option("--cc", action="store", dest="cc", - metavar="CC", default="dev@scons.tigris.org", - help="Add CC (comma separated email addresses).") -group.add_option("--private", action="store_true", dest="private", - default=False, - help="Make the issue restricted to reviewers and those CCed") -# Upload options -group = parser.add_option_group("Patch options") -group.add_option("-m", "--message", action="store", dest="message", - metavar="MESSAGE", default=None, - help="A message to identify the patch. " - "Will prompt if omitted.") -group.add_option("-i", "--issue", type="int", action="store", - metavar="ISSUE", default=None, - help="Issue number to which to add. Defaults to new issue.") -group.add_option("--base_url", action="store", dest="base_url", default=None, - help="Base repository URL (listed as \"Base URL\" when " - "viewing issue). If omitted, will be guessed automatically " - "for SVN repos and left blank for others.") -group.add_option("--download_base", action="store_true", - dest="download_base", default=False, - help="Base files will be downloaded by the server " - "(side-by-side diffs may not work on files with CRs).") -group.add_option("--rev", action="store", dest="revision", - metavar="REV", default=None, - help="Base revision/branch/tree to diff against. Use " - "rev1:rev2 range to review already committed changeset.") -group.add_option("--send_mail", action="store_true", - dest="send_mail", default=True, - help="Send notification email to reviewers.") -group.add_option("--vcs", action="store", dest="vcs", - metavar="VCS", default="svn", - help=("Version control system (optional, usually upload.py " - "already guesses the right VCS).")) -group.add_option("--emulate_svn_auto_props", action="store_true", - dest="emulate_svn_auto_props", default=False, - help=("Emulate Subversion's auto properties feature.")) - - -def GetRpcServer(server, email=None, host_override=None, save_cookies=True, - account_type=AUTH_ACCOUNT_TYPE): - """Returns an instance of an AbstractRpcServer. - - Args: - server: String containing the review server URL. - email: String containing user's email address. - host_override: If not None, string containing an alternate hostname to use - in the host header. - save_cookies: Whether authentication cookies should be saved to disk. - account_type: Account type for authentication, either 'GOOGLE' - or 'HOSTED'. Defaults to AUTH_ACCOUNT_TYPE. - - Returns: - A new AbstractRpcServer, on which RPC calls can be made. - """ - - rpc_server_class = HttpRpcServer - - # If this is the dev_appserver, use fake authentication. - host = (host_override or server).lower() - if re.match(r'(http://)?localhost([:/]|$)', host): - if email is None: - email = "test@example.com" - logging.info("Using debug user %s. Override with --email" % email) - server = rpc_server_class( - server, - lambda: (email, "password"), - host_override=host_override, - extra_headers={"Cookie": - 'dev_appserver_login="%s:False"' % email}, - save_cookies=save_cookies, - account_type=account_type) - # Don't try to talk to ClientLogin. - server.authenticated = True - return server - - def GetUserCredentials(): - """Prompts the user for a username and password.""" - # Create a local alias to the email variable to avoid Python's crazy - # scoping rules. - local_email = email - if local_email is None: - local_email = GetEmail("Email (login for uploading to %s)" % server) - password = None - if keyring: - password = keyring.get_password(host, local_email) - if password is not None: - print "Using password from system keyring." - else: - password = getpass.getpass("Password for %s: " % local_email) - if keyring: - answer = raw_input("Store password in system keyring?(y/N) ").strip() - if answer == "y": - keyring.set_password(host, local_email, password) - return (local_email, password) - - return rpc_server_class(server, - GetUserCredentials, - host_override=host_override, - save_cookies=save_cookies) - - -def EncodeMultipartFormData(fields, files): - """Encode form fields for multipart/form-data. - - Args: - fields: A sequence of (name, value) elements for regular form fields. - files: A sequence of (name, filename, value) elements for data to be - uploaded as files. - Returns: - (content_type, body) ready for httplib.HTTP instance. - - Source: - http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306 - """ - BOUNDARY = '-M-A-G-I-C---B-O-U-N-D-A-R-Y-' - CRLF = '\r\n' - lines = [] - for (key, value) in fields: - lines.append('--' + BOUNDARY) - lines.append('Content-Disposition: form-data; name="%s"' % key) - lines.append('') - if isinstance(value, unicode): - value = value.encode('utf-8') - lines.append(value) - for (key, filename, value) in files: - lines.append('--' + BOUNDARY) - lines.append('Content-Disposition: form-data; name="%s"; filename="%s"' % - (key, filename)) - lines.append('Content-Type: %s' % GetContentType(filename)) - lines.append('') - if isinstance(value, unicode): - value = value.encode('utf-8') - lines.append(value) - lines.append('--' + BOUNDARY + '--') - lines.append('') - body = CRLF.join(lines) - content_type = 'multipart/form-data; boundary=%s' % BOUNDARY - return content_type, body - - -def GetContentType(filename): - """Helper to guess the content-type from the filename.""" - return mimetypes.guess_type(filename)[0] or 'application/octet-stream' - - -# Use a shell for subcommands on Windows to get a PATH search. -use_shell = sys.platform.startswith("win") - -def RunShellWithReturnCodeAndStderr(command, print_output=False, - universal_newlines=True, - env=os.environ): - """Executes a command and returns the output from stdout, stderr and the return code. - - Args: - command: Command to execute. - print_output: If True, the output is printed to stdout. - If False, both stdout and stderr are ignored. - universal_newlines: Use universal_newlines flag (default: True). - - Returns: - Tuple (stdout, stderr, return code) - """ - logging.info("Running %s", command) - env = env.copy() - env['LC_MESSAGES'] = 'C' - p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - shell=use_shell, universal_newlines=universal_newlines, - env=env) - if print_output: - output_array = [] - while True: - line = p.stdout.readline() - if not line: - break - print line.strip("\n") - output_array.append(line) - output = "".join(output_array) - else: - output = p.stdout.read() - p.wait() - errout = p.stderr.read() - if print_output and errout: - print >>sys.stderr, errout - p.stdout.close() - p.stderr.close() - return output, errout, p.returncode - -def RunShellWithReturnCode(command, print_output=False, - universal_newlines=True, - env=os.environ): - """Executes a command and returns the output from stdout and the return code.""" - out, err, retcode = RunShellWithReturnCodeAndStderr(command, print_output, - universal_newlines, env) - return out, retcode - -def RunShell(command, silent_ok=False, universal_newlines=True, - print_output=False, env=os.environ): - data, retcode = RunShellWithReturnCode(command, print_output, - universal_newlines, env) - if retcode: - ErrorExit("Got error status from %s:\n%s" % (command, data)) - if not silent_ok and not data: - ErrorExit("No output from %s" % command) - return data - - -class VersionControlSystem(object): - """Abstract base class providing an interface to the VCS.""" - - def __init__(self, options): - """Constructor. - - Args: - options: Command line options. - """ - self.options = options - - def PostProcessDiff(self, diff): - """Return the diff with any special post processing this VCS needs, e.g. - to include an svn-style "Index:".""" - return diff - - def GenerateDiff(self, args): - """Return the current diff as a string. - - Args: - args: Extra arguments to pass to the diff command. - """ - raise NotImplementedError( - "abstract method -- subclass %s must override" % self.__class__) - - def GetUnknownFiles(self): - """Return a list of files unknown to the VCS.""" - raise NotImplementedError( - "abstract method -- subclass %s must override" % self.__class__) - - def CheckForUnknownFiles(self): - """Show an "are you sure?" prompt if there are unknown files.""" - unknown_files = self.GetUnknownFiles() - if unknown_files: - print "The following files are not added to version control:" - for line in unknown_files: - print line - prompt = "Are you sure to continue?(y/N) " - answer = raw_input(prompt).strip() - if answer != "y": - ErrorExit("User aborted") - - def GetBaseFile(self, filename): - """Get the content of the upstream version of a file. - - Returns: - A tuple (base_content, new_content, is_binary, status) - base_content: The contents of the base file. - new_content: For text files, this is empty. For binary files, this is - the contents of the new file, since the diff output won't contain - information to reconstruct the current file. - is_binary: True iff the file is binary. - status: The status of the file. - """ - - raise NotImplementedError( - "abstract method -- subclass %s must override" % self.__class__) - - - def GetBaseFiles(self, diff): - """Helper that calls GetBase file for each file in the patch. - - Returns: - A dictionary that maps from filename to GetBaseFile's tuple. Filenames - are retrieved based on lines that start with "Index:" or - "Property changes on:". - """ - files = {} - for line in diff.splitlines(True): - if line.startswith('Index:') or line.startswith('Property changes on:'): - unused, filename = line.split(':', 1) - # On Windows if a file has property changes its filename uses '\' - # instead of '/'. - filename = filename.strip().replace('\\', '/') - files[filename] = self.GetBaseFile(filename) - return files - - - def UploadBaseFiles(self, issue, rpc_server, patch_list, patchset, options, - files): - """Uploads the base files (and if necessary, the current ones as well).""" - - def UploadFile(filename, file_id, content, is_binary, status, is_base): - """Uploads a file to the server.""" - file_too_large = False - if is_base: - type = "base" - else: - type = "current" - if len(content) > MAX_UPLOAD_SIZE: - print ("Not uploading the %s file for %s because it's too large." % - (type, filename)) - file_too_large = True - content = "" - checksum = md5(content).hexdigest() - if options.verbose > 0 and not file_too_large: - print "Uploading %s file for %s" % (type, filename) - url = "/%d/upload_content/%d/%d" % (int(issue), int(patchset), file_id) - form_fields = [("filename", filename), - ("status", status), - ("checksum", checksum), - ("is_binary", str(is_binary)), - ("is_current", str(not is_base)), - ] - if file_too_large: - form_fields.append(("file_too_large", "1")) - if options.email: - form_fields.append(("user", options.email)) - ctype, body = EncodeMultipartFormData(form_fields, - [("data", filename, content)]) - response_body = rpc_server.Send(url, body, - content_type=ctype) - if not response_body.startswith("OK"): - StatusUpdate(" --> %s" % response_body) - sys.exit(1) - - patches = dict() - [patches.setdefault(v, k) for k, v in patch_list] - for filename in patches.keys(): - base_content, new_content, is_binary, status = files[filename] - file_id_str = patches.get(filename) - if file_id_str.find("nobase") != -1: - base_content = None - file_id_str = file_id_str[file_id_str.rfind("_") + 1:] - file_id = int(file_id_str) - if base_content != None: - UploadFile(filename, file_id, base_content, is_binary, status, True) - if new_content != None: - UploadFile(filename, file_id, new_content, is_binary, status, False) - - def IsImage(self, filename): - """Returns true if the filename has an image extension.""" - mimetype = mimetypes.guess_type(filename)[0] - if not mimetype: - return False - return mimetype.startswith("image/") - - def IsBinary(self, filename): - """Returns true if the guessed mimetyped isnt't in text group.""" - mimetype = mimetypes.guess_type(filename)[0] - if not mimetype: - return False # e.g. README, "real" binaries usually have an extension - # special case for text files which don't start with text/ - if mimetype in TEXT_MIMETYPES: - return False - return not mimetype.startswith("text/") - - -class SubversionVCS(VersionControlSystem): - """Implementation of the VersionControlSystem interface for Subversion.""" - - def __init__(self, options): - super(SubversionVCS, self).__init__(options) - if self.options.revision: - match = re.match(r"(\d+)(:(\d+))?", self.options.revision) - if not match: - ErrorExit("Invalid Subversion revision %s." % self.options.revision) - self.rev_start = match.group(1) - self.rev_end = match.group(3) - else: - self.rev_start = self.rev_end = None - # Cache output from "svn list -r REVNO dirname". - # Keys: dirname, Values: 2-tuple (ouput for start rev and end rev). - self.svnls_cache = {} - # Base URL is required to fetch files deleted in an older revision. - # Result is cached to not guess it over and over again in GetBaseFile(). - required = self.options.download_base or self.options.revision is not None - self.svn_base = self._GuessBase(required) - - def GuessBase(self, required): - """Wrapper for _GuessBase.""" - return self.svn_base - - def _GuessBase(self, required): - """Returns base URL for current diff. - - Args: - required: If true, exits if the url can't be guessed, otherwise None is - returned. - """ - info = RunShell(["svn", "info"]) - for line in info.splitlines(): - if line.startswith("URL: "): - url = line.split()[1] - scheme, netloc, path, params, query, fragment = urlparse.urlparse(url) - guess = "" - if netloc == "svn.python.org" and scheme == "svn+ssh": - path = "projects" + path - scheme = "http" - guess = "Python " - elif netloc.endswith(".googlecode.com"): - scheme = "http" - guess = "Google Code " - path = path + "/" - base = urlparse.urlunparse((scheme, netloc, path, params, - query, fragment)) - logging.info("Guessed %sbase = %s", guess, base) - return base - if required: - ErrorExit("Can't find URL in output from svn info") - return None - - def GenerateDiff(self, args): - cmd = ["svn", "diff"] - if self.options.revision: - cmd += ["-r", self.options.revision] - cmd.extend(args) - data = RunShell(cmd) - count = 0 - for line in data.splitlines(): - if line.startswith("Index:") or line.startswith("Property changes on:"): - count += 1 - logging.info(line) - if not count: - ErrorExit("No valid patches found in output from svn diff") - return data - - def _CollapseKeywords(self, content, keyword_str): - """Collapses SVN keywords.""" - # svn cat translates keywords but svn diff doesn't. As a result of this - # behavior patching.PatchChunks() fails with a chunk mismatch error. - # This part was originally written by the Review Board development team - # who had the same problem (http://reviews.review-board.org/r/276/). - # Mapping of keywords to known aliases - svn_keywords = { - # Standard keywords - 'Date': ['Date', 'LastChangedDate'], - 'Revision': ['Revision', 'LastChangedRevision', 'Rev'], - 'Author': ['Author', 'LastChangedBy'], - 'HeadURL': ['HeadURL', 'URL'], - 'Id': ['Id'], - - # Aliases - 'LastChangedDate': ['LastChangedDate', 'Date'], - 'LastChangedRevision': ['LastChangedRevision', 'Rev', 'Revision'], - 'LastChangedBy': ['LastChangedBy', 'Author'], - 'URL': ['URL', 'HeadURL'], - } - - def repl(m): - if m.group(2): - return "$%s::%s$" % (m.group(1), " " * len(m.group(3))) - return "$%s$" % m.group(1) - keywords = [keyword - for name in keyword_str.split(" ") - for keyword in svn_keywords.get(name, [])] - return re.sub(r"\$(%s):(:?)([^\$]+)\$" % '|'.join(keywords), repl, content) - - def GetUnknownFiles(self): - status = RunShell(["svn", "status", "--ignore-externals"], silent_ok=True) - unknown_files = [] - for line in status.split("\n"): - if line and line[0] == "?": - unknown_files.append(line) - return unknown_files - - def ReadFile(self, filename): - """Returns the contents of a file.""" - file = open(filename, 'rb') - result = "" - try: - result = file.read() - finally: - file.close() - return result - - def GetStatus(self, filename): - """Returns the status of a file.""" - if not self.options.revision: - status = RunShell(["svn", "status", "--ignore-externals", filename]) - if not status: - ErrorExit("svn status returned no output for %s" % filename) - status_lines = status.splitlines() - # If file is in a cl, the output will begin with - # "\n--- Changelist 'cl_name':\n". See - # http://svn.collab.net/repos/svn/trunk/notes/changelist-design.txt - if (len(status_lines) == 3 and - not status_lines[0] and - status_lines[1].startswith("--- Changelist")): - status = status_lines[2] - else: - status = status_lines[0] - # If we have a revision to diff against we need to run "svn list" - # for the old and the new revision and compare the results to get - # the correct status for a file. - else: - dirname, relfilename = os.path.split(filename) - if dirname not in self.svnls_cache: - cmd = ["svn", "list", "-r", self.rev_start, dirname or "."] - out, err, returncode = RunShellWithReturnCodeAndStderr(cmd) - if returncode: - # Directory might not yet exist at start revison - # svn: Unable to find repository location for 'abc' in revision nnn - if re.match('^svn: Unable to find repository location for .+ in revision \d+', err): - old_files = () - else: - ErrorExit("Failed to get status for %s:\n%s" % (filename, err)) - else: - old_files = out.splitlines() - args = ["svn", "list"] - if self.rev_end: - args += ["-r", self.rev_end] - cmd = args + [dirname or "."] - out, returncode = RunShellWithReturnCode(cmd) - if returncode: - ErrorExit("Failed to run command %s" % cmd) - self.svnls_cache[dirname] = (old_files, out.splitlines()) - old_files, new_files = self.svnls_cache[dirname] - if relfilename in old_files and relfilename not in new_files: - status = "D " - elif relfilename in old_files and relfilename in new_files: - status = "M " - else: - status = "A " - return status - - def GetBaseFile(self, filename): - status = self.GetStatus(filename) - base_content = None - new_content = None - - # If a file is copied its status will be "A +", which signifies - # "addition-with-history". See "svn st" for more information. We need to - # upload the original file or else diff parsing will fail if the file was - # edited. - if status[0] == "A" and status[3] != "+": - # We'll need to upload the new content if we're adding a binary file - # since diff's output won't contain it. - mimetype = RunShell(["svn", "propget", "svn:mime-type", filename], - silent_ok=True) - base_content = "" - is_binary = bool(mimetype) and not mimetype.startswith("text/") - if is_binary and self.IsImage(filename): - new_content = self.ReadFile(filename) - elif (status[0] in ("M", "D", "R") or - (status[0] == "A" and status[3] == "+") or # Copied file. - (status[0] == " " and status[1] == "M")): # Property change. - args = [] - if self.options.revision: - url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start) - else: - # Don't change filename, it's needed later. - url = filename - args += ["-r", "BASE"] - cmd = ["svn"] + args + ["propget", "svn:mime-type", url] - mimetype, returncode = RunShellWithReturnCode(cmd) - if returncode: - # File does not exist in the requested revision. - # Reset mimetype, it contains an error message. - mimetype = "" - else: - mimetype = mimetype.strip() - get_base = False - is_binary = (bool(mimetype) and - not mimetype.startswith("text/") and - not mimetype in TEXT_MIMETYPES) - if status[0] == " ": - # Empty base content just to force an upload. - base_content = "" - elif is_binary: - if self.IsImage(filename): - get_base = True - if status[0] == "M": - if not self.rev_end: - new_content = self.ReadFile(filename) - else: - url = "%s/%s@%s" % (self.svn_base, filename, self.rev_end) - new_content = RunShell(["svn", "cat", url], - universal_newlines=True, silent_ok=True) - else: - base_content = "" - else: - get_base = True - - if get_base: - if is_binary: - universal_newlines = False - else: - universal_newlines = True - if self.rev_start: - # "svn cat -r REV delete_file.txt" doesn't work. cat requires - # the full URL with "@REV" appended instead of using "-r" option. - url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start) - base_content = RunShell(["svn", "cat", url], - universal_newlines=universal_newlines, - silent_ok=True) - else: - base_content, ret_code = RunShellWithReturnCode( - ["svn", "cat", filename], universal_newlines=universal_newlines) - if ret_code and status[0] == "R": - # It's a replaced file without local history (see issue208). - # The base file needs to be fetched from the server. - url = "%s/%s" % (self.svn_base, filename) - base_content = RunShell(["svn", "cat", url], - universal_newlines=universal_newlines, - silent_ok=True) - elif ret_code: - ErrorExit("Got error status from 'svn cat %s'" % filename) - if not is_binary: - args = [] - if self.rev_start: - url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start) - else: - url = filename - args += ["-r", "BASE"] - cmd = ["svn"] + args + ["propget", "svn:keywords", url] - keywords, returncode = RunShellWithReturnCode(cmd) - if keywords and not returncode: - base_content = self._CollapseKeywords(base_content, keywords) - else: - StatusUpdate("svn status returned unexpected output: %s" % status) - sys.exit(1) - return base_content, new_content, is_binary, status[0:5] - - -class GitVCS(VersionControlSystem): - """Implementation of the VersionControlSystem interface for Git.""" - - def __init__(self, options): - super(GitVCS, self).__init__(options) - # Map of filename -> (hash before, hash after) of base file. - # Hashes for "no such file" are represented as None. - self.hashes = {} - # Map of new filename -> old filename for renames. - self.renames = {} - - def PostProcessDiff(self, gitdiff): - """Converts the diff output to include an svn-style "Index:" line as well - as record the hashes of the files, so we can upload them along with our - diff.""" - # Special used by git to indicate "no such content". - NULL_HASH = "0"*40 - - def IsFileNew(filename): - return filename in self.hashes and self.hashes[filename][0] is None - - def AddSubversionPropertyChange(filename): - """Add svn's property change information into the patch if given file is - new file. - - We use Subversion's auto-props setting to retrieve its property. - See http://svnbook.red-bean.com/en/1.1/ch07.html#svn-ch-7-sect-1.3.2 for - Subversion's [auto-props] setting. - """ - if self.options.emulate_svn_auto_props and IsFileNew(filename): - svnprops = GetSubversionPropertyChanges(filename) - if svnprops: - svndiff.append("\n" + svnprops + "\n") - - svndiff = [] - filecount = 0 - filename = None - for line in gitdiff.splitlines(): - match = re.match(r"diff --git a/(.*) b/(.*)$", line) - if match: - # Add auto property here for previously seen file. - if filename is not None: - AddSubversionPropertyChange(filename) - filecount += 1 - # Intentionally use the "after" filename so we can show renames. - filename = match.group(2) - svndiff.append("Index: %s\n" % filename) - if match.group(1) != match.group(2): - self.renames[match.group(2)] = match.group(1) - else: - # The "index" line in a git diff looks like this (long hashes elided): - # index 82c0d44..b2cee3f 100755 - # We want to save the left hash, as that identifies the base file. - match = re.match(r"index (\w+)\.\.(\w+)", line) - if match: - before, after = (match.group(1), match.group(2)) - if before == NULL_HASH: - before = None - if after == NULL_HASH: - after = None - self.hashes[filename] = (before, after) - svndiff.append(line + "\n") - if not filecount: - ErrorExit("No valid patches found in output from git diff") - # Add auto property for the last seen file. - assert filename is not None - AddSubversionPropertyChange(filename) - return "".join(svndiff) - - def GenerateDiff(self, extra_args): - extra_args = extra_args[:] - if self.options.revision: - if ":" in self.options.revision: - extra_args = self.options.revision.split(":", 1) + extra_args - else: - extra_args = [self.options.revision] + extra_args - - # --no-ext-diff is broken in some versions of Git, so try to work around - # this by overriding the environment (but there is still a problem if the - # git config key "diff.external" is used). - env = os.environ.copy() - if 'GIT_EXTERNAL_DIFF' in env: del env['GIT_EXTERNAL_DIFF'] - return RunShell(["git", "diff", "--no-ext-diff", "--full-index", "-M"] - + extra_args, env=env) - - def GetUnknownFiles(self): - status = RunShell(["git", "ls-files", "--exclude-standard", "--others"], - silent_ok=True) - return status.splitlines() - - def GetFileContent(self, file_hash, is_binary): - """Returns the content of a file identified by its git hash.""" - data, retcode = RunShellWithReturnCode(["git", "show", file_hash], - universal_newlines=not is_binary) - if retcode: - ErrorExit("Got error status from 'git show %s'" % file_hash) - return data - - def GetBaseFile(self, filename): - hash_before, hash_after = self.hashes.get(filename, (None,None)) - base_content = None - new_content = None - is_binary = self.IsBinary(filename) - status = None - - if filename in self.renames: - status = "A +" # Match svn attribute name for renames. - if filename not in self.hashes: - # If a rename doesn't change the content, we never get a hash. - base_content = RunShell(["git", "show", "HEAD:" + filename]) - elif not hash_before: - status = "A" - base_content = "" - elif not hash_after: - status = "D" - else: - status = "M" - - is_image = self.IsImage(filename) - - # Grab the before/after content if we need it. - # We should include file contents if it's text or it's an image. - if not is_binary or is_image: - # Grab the base content if we don't have it already. - if base_content is None and hash_before: - base_content = self.GetFileContent(hash_before, is_binary) - # Only include the "after" file if it's an image; otherwise it - # it is reconstructed from the diff. - if is_image and hash_after: - new_content = self.GetFileContent(hash_after, is_binary) - - return (base_content, new_content, is_binary, status) - - -class MercurialVCS(VersionControlSystem): - """Implementation of the VersionControlSystem interface for Mercurial.""" - - def __init__(self, options, repo_dir): - super(MercurialVCS, self).__init__(options) - # Absolute path to repository (we can be in a subdir) - self.repo_dir = os.path.normpath(repo_dir) - # Compute the subdir - cwd = os.path.normpath(os.getcwd()) - assert cwd.startswith(self.repo_dir) - self.subdir = cwd[len(self.repo_dir):].lstrip(r"\/") - if self.options.revision: - self.base_rev = self.options.revision - else: - self.base_rev = RunShell(["hg", "parent", "-q"]).split(':')[1].strip() - - def _GetRelPath(self, filename): - """Get relative path of a file according to the current directory, - given its logical path in the repo.""" - assert filename.startswith(self.subdir), (filename, self.subdir) - return filename[len(self.subdir):].lstrip(r"\/") - - def GenerateDiff(self, extra_args): - cmd = ["hg", "diff", "--git", "-r", self.base_rev] + extra_args - data = RunShell(cmd, silent_ok=True) - svndiff = [] - filecount = 0 - for line in data.splitlines(): - m = re.match("diff --git a/(\S+) b/(\S+)", line) - if m: - # Modify line to make it look like as it comes from svn diff. - # With this modification no changes on the server side are required - # to make upload.py work with Mercurial repos. - # NOTE: for proper handling of moved/copied files, we have to use - # the second filename. - filename = m.group(2) - svndiff.append("Index: %s" % filename) - svndiff.append("=" * 67) - filecount += 1 - logging.info(line) - else: - svndiff.append(line) - if not filecount: - ErrorExit("No valid patches found in output from hg diff") - return "\n".join(svndiff) + "\n" - - def GetUnknownFiles(self): - """Return a list of files unknown to the VCS.""" - args = [] - status = RunShell(["hg", "status", "--rev", self.base_rev, "-u", "."], - silent_ok=True) - unknown_files = [] - for line in status.splitlines(): - st, fn = line.split(" ", 1) - if st == "?": - unknown_files.append(fn) - return unknown_files - - def GetBaseFile(self, filename): - # "hg status" and "hg cat" both take a path relative to the current subdir - # rather than to the repo root, but "hg diff" has given us the full path - # to the repo root. - base_content = "" - new_content = None - is_binary = False - oldrelpath = relpath = self._GetRelPath(filename) - # "hg status -C" returns two lines for moved/copied files, one otherwise - out = RunShell(["hg", "status", "-C", "--rev", self.base_rev, relpath]) - out = out.splitlines() - # HACK: strip error message about missing file/directory if it isn't in - # the working copy - if out[0].startswith('%s: ' % relpath): - out = out[1:] - status, _ = out[0].split(' ', 1) - if len(out) > 1 and status == "A": - # Moved/copied => considered as modified, use old filename to - # retrieve base contents - oldrelpath = out[1].strip() - status = "M" - if ":" in self.base_rev: - base_rev = self.base_rev.split(":", 1)[0] - else: - base_rev = self.base_rev - if status != "A": - base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath], - silent_ok=True) - is_binary = "\0" in base_content # Mercurial's heuristic - if status != "R": - new_content = open(relpath, "rb").read() - is_binary = is_binary or "\0" in new_content - if is_binary and base_content: - # Fetch again without converting newlines - base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath], - silent_ok=True, universal_newlines=False) - if not is_binary or not self.IsImage(relpath): - new_content = None - return base_content, new_content, is_binary, status - - -# NOTE: The SplitPatch function is duplicated in engine.py, keep them in sync. -def SplitPatch(data): - """Splits a patch into separate pieces for each file. - - Args: - data: A string containing the output of svn diff. - - Returns: - A list of 2-tuple (filename, text) where text is the svn diff output - pertaining to filename. - """ - patches = [] - filename = None - diff = [] - for line in data.splitlines(True): - new_filename = None - if line.startswith('Index:'): - unused, new_filename = line.split(':', 1) - new_filename = new_filename.strip() - elif line.startswith('Property changes on:'): - unused, temp_filename = line.split(':', 1) - # When a file is modified, paths use '/' between directories, however - # when a property is modified '\' is used on Windows. Make them the same - # otherwise the file shows up twice. - temp_filename = temp_filename.strip().replace('\\', '/') - if temp_filename != filename: - # File has property changes but no modifications, create a new diff. - new_filename = temp_filename - if new_filename: - if filename and diff: - patches.append((filename, ''.join(diff))) - filename = new_filename - diff = [line] - continue - if diff is not None: - diff.append(line) - if filename and diff: - patches.append((filename, ''.join(diff))) - return patches - - -def UploadSeparatePatches(issue, rpc_server, patchset, data, options): - """Uploads a separate patch for each file in the diff output. - - Returns a list of [patch_key, filename] for each file. - """ - patches = SplitPatch(data) - rv = [] - for patch in patches: - if len(patch[1]) > MAX_UPLOAD_SIZE: - print ("Not uploading the patch for " + patch[0] + - " because the file is too large.") - continue - form_fields = [("filename", patch[0])] - if not options.download_base: - form_fields.append(("content_upload", "1")) - files = [("data", "data.diff", patch[1])] - ctype, body = EncodeMultipartFormData(form_fields, files) - url = "/%d/upload_patch/%d" % (int(issue), int(patchset)) - print "Uploading patch for " + patch[0] - response_body = rpc_server.Send(url, body, content_type=ctype) - lines = response_body.splitlines() - if not lines or lines[0] != "OK": - StatusUpdate(" --> %s" % response_body) - sys.exit(1) - rv.append([lines[1], patch[0]]) - return rv - - -def GuessVCSName(): - """Helper to guess the version control system. - - This examines the current directory, guesses which VersionControlSystem - we're using, and returns an string indicating which VCS is detected. - - Returns: - A pair (vcs, output). vcs is a string indicating which VCS was detected - and is one of VCS_GIT, VCS_MERCURIAL, VCS_SUBVERSION, or VCS_UNKNOWN. - output is a string containing any interesting output from the vcs - detection routine, or None if there is nothing interesting. - """ - def RunDetectCommand(vcs_type, command): - """Helper to detect VCS by executing command. - - Returns: - A pair (vcs, output) or None. Throws exception on error. - """ - try: - out, returncode = RunShellWithReturnCode(command) - if returncode == 0: - return (vcs_type, out.strip()) - except OSError, (errcode, message): - if errcode != errno.ENOENT: # command not found code - raise - - # Mercurial has a command to get the base directory of a repository - # Try running it, but don't die if we don't have hg installed. - # NOTE: we try Mercurial first as it can sit on top of an SVN working copy. - res = RunDetectCommand(VCS_MERCURIAL, ["hg", "root"]) - if res != None: - return res - - # Subversion has a .svn in all working directories. - if os.path.isdir('.svn'): - logging.info("Guessed VCS = Subversion") - return (VCS_SUBVERSION, None) - - # Git has a command to test if you're in a git tree. - # Try running it, but don't die if we don't have git installed. - res = RunDetectCommand(VCS_GIT, ["git", "rev-parse", - "--is-inside-work-tree"]) - if res != None: - return res - - return (VCS_UNKNOWN, None) - - -def GuessVCS(options): - """Helper to guess the version control system. - - This verifies any user-specified VersionControlSystem (by command line - or environment variable). If the user didn't specify one, this examines - the current directory, guesses which VersionControlSystem we're using, - and returns an instance of the appropriate class. Exit with an error - if we can't figure it out. - - Returns: - A VersionControlSystem instance. Exits if the VCS can't be guessed. - """ - vcs = options.vcs - if not vcs: - vcs = os.environ.get("CODEREVIEW_VCS") - if vcs: - v = VCS_ABBREVIATIONS.get(vcs.lower()) - if v is None: - ErrorExit("Unknown version control system %r specified." % vcs) - (vcs, extra_output) = (v, None) - else: - (vcs, extra_output) = GuessVCSName() - - if vcs == VCS_MERCURIAL: - if extra_output is None: - extra_output = RunShell(["hg", "root"]).strip() - return MercurialVCS(options, extra_output) - elif vcs == VCS_SUBVERSION: - return SubversionVCS(options) - elif vcs == VCS_GIT: - return GitVCS(options) - - ErrorExit(("Could not guess version control system. " - "Are you in a working copy directory?")) - - -def CheckReviewer(reviewer): - """Validate a reviewer -- either a nickname or an email addres. - - Args: - reviewer: A nickname or an email address. - - Calls ErrorExit() if it is an invalid email address. - """ - if "@" not in reviewer: - return # Assume nickname - parts = reviewer.split("@") - if len(parts) > 2: - ErrorExit("Invalid email address: %r" % reviewer) - assert len(parts) == 2 - if "." not in parts[1]: - ErrorExit("Invalid email address: %r" % reviewer) - - -def LoadSubversionAutoProperties(): - """Returns the content of [auto-props] section of Subversion's config file as - a dictionary. - - Returns: - A dictionary whose key-value pair corresponds the [auto-props] section's - key-value pair. - In following cases, returns empty dictionary: - - config file doesn't exist, or - - 'enable-auto-props' is not set to 'true-like-value' in [miscellany]. - """ - if os.name == 'nt': - subversion_config = os.environ.get("APPDATA") + "\\Subversion\\config" - else: - subversion_config = os.path.expanduser("~/.subversion/config") - if not os.path.exists(subversion_config): - return {} - config = ConfigParser.ConfigParser() - config.read(subversion_config) - if (config.has_section("miscellany") and - config.has_option("miscellany", "enable-auto-props") and - config.getboolean("miscellany", "enable-auto-props") and - config.has_section("auto-props")): - props = {} - for file_pattern in config.options("auto-props"): - props[file_pattern] = ParseSubversionPropertyValues( - config.get("auto-props", file_pattern)) - return props - else: - return {} - -def ParseSubversionPropertyValues(props): - """Parse the given property value which comes from [auto-props] section and - returns a list whose element is a (svn_prop_key, svn_prop_value) pair. - - See the following doctest for example. - - >>> ParseSubversionPropertyValues('svn:eol-style=LF') - [('svn:eol-style', 'LF')] - >>> ParseSubversionPropertyValues('svn:mime-type=image/jpeg') - [('svn:mime-type', 'image/jpeg')] - >>> ParseSubversionPropertyValues('svn:eol-style=LF;svn:executable') - [('svn:eol-style', 'LF'), ('svn:executable', '*')] - """ - key_value_pairs = [] - for prop in props.split(";"): - key_value = prop.split("=") - assert len(key_value) <= 2 - if len(key_value) == 1: - # If value is not given, use '*' as a Subversion's convention. - key_value_pairs.append((key_value[0], "*")) - else: - key_value_pairs.append((key_value[0], key_value[1])) - return key_value_pairs - - -def GetSubversionPropertyChanges(filename): - """Return a Subversion's 'Property changes on ...' string, which is used in - the patch file. - - Args: - filename: filename whose property might be set by [auto-props] config. - - Returns: - A string like 'Property changes on |filename| ...' if given |filename| - matches any entries in [auto-props] section. None, otherwise. - """ - global svn_auto_props_map - if svn_auto_props_map is None: - svn_auto_props_map = LoadSubversionAutoProperties() - - all_props = [] - for file_pattern, props in svn_auto_props_map.items(): - if fnmatch.fnmatch(filename, file_pattern): - all_props.extend(props) - if all_props: - return FormatSubversionPropertyChanges(filename, all_props) - return None - - -def FormatSubversionPropertyChanges(filename, props): - """Returns Subversion's 'Property changes on ...' strings using given filename - and properties. - - Args: - filename: filename - props: A list whose element is a (svn_prop_key, svn_prop_value) pair. - - Returns: - A string which can be used in the patch file for Subversion. - - See the following doctest for example. - - >>> print FormatSubversionPropertyChanges('foo.cc', [('svn:eol-style', 'LF')]) - Property changes on: foo.cc - ___________________________________________________________________ - Added: svn:eol-style - + LF - - """ - prop_changes_lines = [ - "Property changes on: %s" % filename, - "___________________________________________________________________"] - for key, value in props: - prop_changes_lines.append("Added: " + key) - prop_changes_lines.append(" + " + value) - return "\n".join(prop_changes_lines) + "\n" - - -def RealMain(argv, data=None): - """The real main function. - - Args: - argv: Command line arguments. - data: Diff contents. If None (default) the diff is generated by - the VersionControlSystem implementation returned by GuessVCS(). - - Returns: - A 2-tuple (issue id, patchset id). - The patchset id is None if the base files are not uploaded by this - script (applies only to SVN checkouts). - """ - options, args = parser.parse_args(argv[1:]) - global verbosity - verbosity = options.verbose - if verbosity >= 3: - logging.getLogger().setLevel(logging.DEBUG) - elif verbosity >= 2: - logging.getLogger().setLevel(logging.INFO) - - vcs = GuessVCS(options) - - base = options.base_url - if isinstance(vcs, SubversionVCS): - # Guessing the base field is only supported for Subversion. - # Note: Fetching base files may become deprecated in future releases. - guessed_base = vcs.GuessBase(options.download_base) - if base: - if guessed_base and base != guessed_base: - print "Using base URL \"%s\" from --base_url instead of \"%s\"" % \ - (base, guessed_base) - else: - base = guessed_base - - if not base and options.download_base: - options.download_base = True - logging.info("Enabled upload of base file") - if not options.assume_yes: - vcs.CheckForUnknownFiles() - if data is None: - data = vcs.GenerateDiff(args) - data = vcs.PostProcessDiff(data) - files = vcs.GetBaseFiles(data) - if verbosity >= 1: - print "Upload server:", options.server, "(change with -s/--server)" - if options.issue: - prompt = "Message describing this patch set: " - else: - prompt = "New issue subject: " - message = options.message or raw_input(prompt).strip() - if not message: - ErrorExit("A non-empty message is required") - rpc_server = GetRpcServer(options.server, - options.email, - options.host, - options.save_cookies, - options.account_type) - form_fields = [("subject", message)] - if base: - b = urlparse.urlparse(base) - username, netloc = urllib.splituser(b.netloc) - if username: - logging.info("Removed username from base URL") - base = urlparse.urlunparse((b.scheme, netloc, b.path, b.params, - b.query, b.fragment)) - form_fields.append(("base", base)) - if options.issue: - form_fields.append(("issue", str(options.issue))) - if options.email: - form_fields.append(("user", options.email)) - if options.reviewers: - for reviewer in options.reviewers.split(','): - CheckReviewer(reviewer) - form_fields.append(("reviewers", options.reviewers)) - if options.cc: - for cc in options.cc.split(','): - CheckReviewer(cc) - form_fields.append(("cc", options.cc)) - description = options.description - if options.description_file: - if options.description: - ErrorExit("Can't specify description and description_file") - file = open(options.description_file, 'r') - description = file.read() - file.close() - if description: - form_fields.append(("description", description)) - # Send a hash of all the base file so the server can determine if a copy - # already exists in an earlier patchset. - base_hashes = "" - for file, info in files.iteritems(): - if not info[0] is None: - checksum = md5(info[0]).hexdigest() - if base_hashes: - base_hashes += "|" - base_hashes += checksum + ":" + file - form_fields.append(("base_hashes", base_hashes)) - if options.private: - if options.issue: - print "Warning: Private flag ignored when updating an existing issue." - else: - form_fields.append(("private", "1")) - # If we're uploading base files, don't send the email before the uploads, so - # that it contains the file status. - if options.send_mail and options.download_base: - form_fields.append(("send_mail", "1")) - if not options.download_base: - form_fields.append(("content_upload", "1")) - if len(data) > MAX_UPLOAD_SIZE: - print "Patch is large, so uploading file patches separately." - uploaded_diff_file = [] - form_fields.append(("separate_patches", "1")) - else: - uploaded_diff_file = [("data", "data.diff", data)] - ctype, body = EncodeMultipartFormData(form_fields, uploaded_diff_file) - response_body = rpc_server.Send("/upload", body, content_type=ctype) - patchset = None - if not options.download_base or not uploaded_diff_file: - lines = response_body.splitlines() - if len(lines) >= 2: - msg = lines[0] - patchset = lines[1].strip() - patches = [x.split(" ", 1) for x in lines[2:]] - else: - msg = response_body - else: - msg = response_body - StatusUpdate(msg) - if not response_body.startswith("Issue created.") and \ - not response_body.startswith("Issue updated."): - sys.exit(0) - issue = msg[msg.rfind("/")+1:] - - if not uploaded_diff_file: - result = UploadSeparatePatches(issue, rpc_server, patchset, data, options) - if not options.download_base: - patches = result - - if not options.download_base: - vcs.UploadBaseFiles(issue, rpc_server, patches, patchset, options, files) - if options.send_mail: - rpc_server.Send("/" + issue + "/mail", payload="") - return issue, patchset - - -def main(): - try: - logging.basicConfig(format=("%(asctime).19s %(levelname)s %(filename)s:" - "%(lineno)s %(message)s ")) - os.environ['LC_ALL'] = 'C' - RealMain(sys.argv) - except KeyboardInterrupt: - print - StatusUpdate("Interrupted.") - sys.exit(1) - - -if __name__ == "__main__": - main() - +#!/usr/bin/env python +# +# Copyright 2007 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Tool for uploading diffs from a version control system to the codereview app. + +Usage summary: upload.py [options] [-- diff_options] [path...] + +Diff options are passed to the diff command of the underlying system. + +Supported version control systems: + Git + Mercurial + Subversion + +It is important for Git/Mercurial users to specify a tree/node/branch to diff +against by using the '--rev' option. +""" +# This code is derived from appcfg.py in the App Engine SDK (open source), +# and from ASPN recipe #146306. + +import configparser +import http.cookiejar +import fnmatch +import getpass +import logging +import mimetypes +import optparse +import os +import re +import socket +import subprocess +import sys +import urllib.request, urllib.parse, urllib.error +import urllib.request, urllib.error, urllib.parse +import urllib.parse + +# The md5 module was deprecated in Python 2.5. +try: + from hashlib import md5 +except ImportError: + from md5 import md5 + +try: + import readline +except ImportError: + pass + +try: + import keyring +except ImportError: + keyring = None + +# The logging verbosity: +# 0: Errors only. +# 1: Status messages. +# 2: Info logs. +# 3: Debug logs. +verbosity = 1 + +# The account type used for authentication. +# This line could be changed by the review server (see handler for +# upload.py). +AUTH_ACCOUNT_TYPE = "GOOGLE" + +# URL of the default review server. As for AUTH_ACCOUNT_TYPE, this line could be +# changed by the review server (see handler for upload.py). +DEFAULT_REVIEW_SERVER = "codereview.appspot.com" + +# Max size of patch or base file. +MAX_UPLOAD_SIZE = 900 * 1024 + +# Constants for version control names. Used by GuessVCSName. +VCS_GIT = "Git" +VCS_MERCURIAL = "Mercurial" +VCS_SUBVERSION = "Subversion" +VCS_UNKNOWN = "Unknown" + +# whitelist for non-binary filetypes which do not start with "text/" +# .mm (Objective-C) shows up as application/x-freemind on my Linux box. +TEXT_MIMETYPES = ['application/javascript', 'application/x-javascript', + 'application/xml', 'application/x-freemind', + 'application/x-sh'] + +VCS_ABBREVIATIONS = { + VCS_MERCURIAL.lower(): VCS_MERCURIAL, + "hg": VCS_MERCURIAL, + VCS_SUBVERSION.lower(): VCS_SUBVERSION, + "svn": VCS_SUBVERSION, + VCS_GIT.lower(): VCS_GIT, +} + +# The result of parsing Subversion's [auto-props] setting. +svn_auto_props_map = None + +def GetEmail(prompt): + """Prompts the user for their email address and returns it. + + The last used email address is saved to a file and offered up as a suggestion + to the user. If the user presses enter without typing in anything the last + used email address is used. If the user enters a new address, it is saved + for next time we prompt. + + """ + last_email_file_name = os.path.expanduser("~/.last_codereview_email_address") + last_email = "" + if os.path.exists(last_email_file_name): + try: + last_email_file = open(last_email_file_name, "r") + last_email = last_email_file.readline().strip("\n") + last_email_file.close() + prompt += " [%s]" % last_email + except IOError as e: + pass + email = input(prompt + ": ").strip() + if email: + try: + last_email_file = open(last_email_file_name, "w") + last_email_file.write(email) + last_email_file.close() + except IOError as e: + pass + else: + email = last_email + return email + + +def StatusUpdate(msg): + """Print a status message to stdout. + + If 'verbosity' is greater than 0, print the message. + + Args: + msg: The string to print. + """ + if verbosity > 0: + print(msg) + + +def ErrorExit(msg): + """Print an error message to stderr and exit.""" + print(msg, file=sys.stderr) + sys.exit(1) + + +class ClientLoginError(urllib.error.HTTPError): + """Raised to indicate there was an error authenticating with ClientLogin.""" + + def __init__(self, url, code, msg, headers, args): + urllib.error.HTTPError.__init__(self, url, code, msg, headers, None) + self.args = args + self.reason = args["Error"] + self.info = args.get("Info", None) + + +class AbstractRpcServer(object): + """Provides a common interface for a simple RPC server.""" + + def __init__(self, host, auth_function, host_override=None, extra_headers={}, + save_cookies=False, account_type=AUTH_ACCOUNT_TYPE): + """Creates a new HttpRpcServer. + + Args: + host: The host to send requests to. + auth_function: A function that takes no arguments and returns an + (email, password) tuple when called. Will be called if authentication + is required. + host_override: The host header to send to the server (defaults to host). + extra_headers: A dict of extra headers to append to every request. + save_cookies: If True, save the authentication cookies to local disk. + If False, use an in-memory cookiejar instead. Subclasses must + implement this functionality. Defaults to False. + account_type: Account type used for authentication. Defaults to + AUTH_ACCOUNT_TYPE. + """ + self.host = host + if (not self.host.startswith("http://") and + not self.host.startswith("https://")): + self.host = "http://" + self.host + self.host_override = host_override + self.auth_function = auth_function + self.authenticated = False + self.extra_headers = extra_headers + self.save_cookies = save_cookies + self.account_type = account_type + self.opener = self._GetOpener() + if self.host_override: + logging.info("Server: %s; Host: %s", self.host, self.host_override) + else: + logging.info("Server: %s", self.host) + + def _GetOpener(self): + """Returns an OpenerDirector for making HTTP requests. + + Returns: + A urllib2.OpenerDirector object. + """ + raise NotImplementedError() + + def _CreateRequest(self, url, data=None): + """Creates a new urllib request.""" + logging.debug("Creating request for: '%s' with payload:\n%s", url, data) + req = urllib.request.Request(url, data=data) + if self.host_override: + req.add_header("Host", self.host_override) + for key, value in self.extra_headers.items(): + req.add_header(key, value) + return req + + def _GetAuthToken(self, email, password): + """Uses ClientLogin to authenticate the user, returning an auth token. + + Args: + email: The user's email address + password: The user's password + + Raises: + ClientLoginError: If there was an error authenticating with ClientLogin. + HTTPError: If there was some other form of HTTP error. + + Returns: + The authentication token returned by ClientLogin. + """ + account_type = self.account_type + if self.host.endswith(".google.com"): + # Needed for use inside Google. + account_type = "HOSTED" + req = self._CreateRequest( + url="https://www.google.com/accounts/ClientLogin", + data=urllib.parse.urlencode({ + "Email": email, + "Passwd": password, + "service": "ah", + "source": "rietveld-codereview-upload", + "accountType": account_type, + }), + ) + try: + response = self.opener.open(req) + response_body = response.read() + response_dict = dict(x.split("=") + for x in response_body.split("\n") if x) + return response_dict["Auth"] + except urllib.error.HTTPError as e: + if e.code == 403: + body = e.read() + response_dict = dict(x.split("=", 1) for x in body.split("\n") if x) + raise ClientLoginError(req.get_full_url(), e.code, e.msg, + e.headers, response_dict) + else: + raise + + def _GetAuthCookie(self, auth_token): + """Fetches authentication cookies for an authentication token. + + Args: + auth_token: The authentication token returned by ClientLogin. + + Raises: + HTTPError: If there was an error fetching the authentication cookies. + """ + # This is a dummy value to allow us to identify when we're successful. + continue_location = "http://localhost/" + args = {"continue": continue_location, "auth": auth_token} + req = self._CreateRequest("%s/_ah/login?%s" % + (self.host, urllib.parse.urlencode(args))) + try: + response = self.opener.open(req) + except urllib.error.HTTPError as e: + response = e + if (response.code != 302 or + response.info()["location"] != continue_location): + raise urllib.error.HTTPError(req.get_full_url(), response.code, response.msg, + response.headers, response.fp) + self.authenticated = True + + def _Authenticate(self): + """Authenticates the user. + + The authentication process works as follows: + 1) We get a username and password from the user + 2) We use ClientLogin to obtain an AUTH token for the user + (see http://code.google.com/apis/accounts/AuthForInstalledApps.html). + 3) We pass the auth token to /_ah/login on the server to obtain an + authentication cookie. If login was successful, it tries to redirect + us to the URL we provided. + + If we attempt to access the upload API without first obtaining an + authentication cookie, it returns a 401 response (or a 302) and + directs us to authenticate ourselves with ClientLogin. + """ + for i in range(3): + credentials = self.auth_function() + try: + auth_token = self._GetAuthToken(credentials[0], credentials[1]) + except ClientLoginError as e: + print('', file=sys.stderr) + if e.reason == "BadAuthentication": + if e.info == "InvalidSecondFactor": + print(( + "Use an application-specific password instead " + "of your regular account password.\n" + "See http://www.google.com/" + "support/accounts/bin/answer.py?answer=185833"), file=sys.stderr) + else: + print("Invalid username or password.", file=sys.stderr) + elif e.reason == "CaptchaRequired": + print(( + "Please go to\n" + "https://www.google.com/accounts/DisplayUnlockCaptcha\n" + "and verify you are a human. Then try again.\n" + "If you are using a Google Apps account the URL is:\n" + "https://www.google.com/a/yourdomain.com/UnlockCaptcha"), file=sys.stderr) + elif e.reason == "NotVerified": + print("Account not verified.", file=sys.stderr) + elif e.reason == "TermsNotAgreed": + print("User has not agreed to TOS.", file=sys.stderr) + elif e.reason == "AccountDeleted": + print("The user account has been deleted.", file=sys.stderr) + elif e.reason == "AccountDisabled": + print("The user account has been disabled.", file=sys.stderr) + break + elif e.reason == "ServiceDisabled": + print(("The user's access to the service has been " + "disabled."), file=sys.stderr) + elif e.reason == "ServiceUnavailable": + print("The service is not available; try again later.", file=sys.stderr) + else: + # Unknown error. + raise + print('', file=sys.stderr) + continue + self._GetAuthCookie(auth_token) + return + + def Send(self, request_path, payload=None, + content_type="application/octet-stream", + timeout=None, + extra_headers=None, + **kwargs): + """Sends an RPC and returns the response. + + Args: + request_path: The path to send the request to, eg /api/appversion/create. + payload: The body of the request, or None to send an empty request. + content_type: The Content-Type header to use. + timeout: timeout in seconds; default None i.e. no timeout. + (Note: for large requests on OS X, the timeout doesn't work right.) + extra_headers: Dict containing additional HTTP headers that should be + included in the request (string header names mapped to their values), + or None to not include any additional headers. + kwargs: Any keyword arguments are converted into query string parameters. + + Returns: + The response body, as a string. + """ + # TODO: Don't require authentication. Let the server say + # whether it is necessary. + if not self.authenticated: + self._Authenticate() + + old_timeout = socket.getdefaulttimeout() + socket.setdefaulttimeout(timeout) + try: + tries = 0 + while True: + tries += 1 + args = dict(kwargs) + url = "%s%s" % (self.host, request_path) + if args: + url += "?" + urllib.parse.urlencode(args) + req = self._CreateRequest(url=url, data=payload) + req.add_header("Content-Type", content_type) + if extra_headers: + for header, value in list(extra_headers.items()): + req.add_header(header, value) + try: + f = self.opener.open(req) + response = f.read() + f.close() + return response + except urllib.error.HTTPError as e: + if tries > 3: + raise + elif e.code == 401 or e.code == 302: + self._Authenticate() +## elif e.code >= 500 and e.code < 600: +## # Server Error - try again. +## continue + elif e.code == 301: + # Handle permanent redirect manually. + url = e.info()["location"] + url_loc = urllib.parse.urlparse(url) + self.host = '%s://%s' % (url_loc[0], url_loc[1]) + else: + raise + finally: + socket.setdefaulttimeout(old_timeout) + + +class HttpRpcServer(AbstractRpcServer): + """Provides a simplified RPC-style interface for HTTP requests.""" + + def _Authenticate(self): + """Save the cookie jar after authentication.""" + super(HttpRpcServer, self)._Authenticate() + if self.save_cookies: + StatusUpdate("Saving authentication cookies to %s" % self.cookie_file) + self.cookie_jar.save() + + def _GetOpener(self): + """Returns an OpenerDirector that supports cookies and ignores redirects. + + Returns: + A urllib2.OpenerDirector object. + """ + opener = urllib.request.OpenerDirector() + opener.add_handler(urllib.request.ProxyHandler()) + opener.add_handler(urllib.request.UnknownHandler()) + opener.add_handler(urllib.request.HTTPHandler()) + opener.add_handler(urllib.request.HTTPDefaultErrorHandler()) + opener.add_handler(urllib.request.HTTPSHandler()) + opener.add_handler(urllib2.HTTPErrorProcessor()) + if self.save_cookies: + self.cookie_file = os.path.expanduser("~/.codereview_upload_cookies") + self.cookie_jar = http.cookiejar.MozillaCookieJar(self.cookie_file) + if os.path.exists(self.cookie_file): + try: + self.cookie_jar.load() + self.authenticated = True + StatusUpdate("Loaded authentication cookies from %s" % + self.cookie_file) + except (http.cookiejar.LoadError, IOError): + # Failed to load cookies - just ignore them. + pass + else: + # Create an empty cookie file with mode 600 + fd = os.open(self.cookie_file, os.O_CREAT, 0o600) + os.close(fd) + # Always chmod the cookie file + os.chmod(self.cookie_file, 0o600) + else: + # Don't save cookies across runs of update.py. + self.cookie_jar = http.cookiejar.CookieJar() + opener.add_handler(urllib.request.HTTPCookieProcessor(self.cookie_jar)) + return opener + + +parser = optparse.OptionParser( + usage="%prog [options] [-- diff_options] [path...]") +parser.add_option("-y", "--assume_yes", action="store_true", + dest="assume_yes", default=False, + help="Assume that the answer to yes/no questions is 'yes'.") +# Logging +group = parser.add_option_group("Logging options") +group.add_option("-q", "--quiet", action="store_const", const=0, + dest="verbose", help="Print errors only.") +group.add_option("-v", "--verbose", action="store_const", const=2, + dest="verbose", default=1, + help="Print info level logs.") +group.add_option("--noisy", action="store_const", const=3, + dest="verbose", help="Print all logs.") +# Review server +group = parser.add_option_group("Review server options") +group.add_option("-s", "--server", action="store", dest="server", + default=DEFAULT_REVIEW_SERVER, + metavar="SERVER", + help=("The server to upload to. The format is host[:port]. " + "Defaults to '%default'.")) +group.add_option("-e", "--email", action="store", dest="email", + metavar="EMAIL", default=None, + help="The username to use. Will prompt if omitted.") +group.add_option("-H", "--host", action="store", dest="host", + metavar="HOST", default=None, + help="Overrides the Host header sent with all RPCs.") +group.add_option("--no_cookies", action="store_false", + dest="save_cookies", default=True, + help="Do not save authentication cookies to local disk.") +group.add_option("--account_type", action="store", dest="account_type", + metavar="TYPE", default=AUTH_ACCOUNT_TYPE, + choices=["GOOGLE", "HOSTED"], + help=("Override the default account type " + "(defaults to '%default', " + "valid choices are 'GOOGLE' and 'HOSTED').")) +# Issue +group = parser.add_option_group("Issue options") +group.add_option("-d", "--description", action="store", dest="description", + metavar="DESCRIPTION", default=None, + help="Optional description when creating an issue.") +group.add_option("-f", "--description_file", action="store", + dest="description_file", metavar="DESCRIPTION_FILE", + default=None, + help="Optional path of a file that contains " + "the description when creating an issue.") +group.add_option("-r", "--reviewers", action="store", dest="reviewers", + metavar="REVIEWERS", default=None, + help="Add reviewers (comma separated email addresses).") +group.add_option("--cc", action="store", dest="cc", + metavar="CC", default="dev@scons.tigris.org", + help="Add CC (comma separated email addresses).") +group.add_option("--private", action="store_true", dest="private", + default=False, + help="Make the issue restricted to reviewers and those CCed") +# Upload options +group = parser.add_option_group("Patch options") +group.add_option("-m", "--message", action="store", dest="message", + metavar="MESSAGE", default=None, + help="A message to identify the patch. " + "Will prompt if omitted.") +group.add_option("-i", "--issue", type="int", action="store", + metavar="ISSUE", default=None, + help="Issue number to which to add. Defaults to new issue.") +group.add_option("--base_url", action="store", dest="base_url", default=None, + help="Base repository URL (listed as \"Base URL\" when " + "viewing issue). If omitted, will be guessed automatically " + "for SVN repos and left blank for others.") +group.add_option("--download_base", action="store_true", + dest="download_base", default=False, + help="Base files will be downloaded by the server " + "(side-by-side diffs may not work on files with CRs).") +group.add_option("--rev", action="store", dest="revision", + metavar="REV", default=None, + help="Base revision/branch/tree to diff against. Use " + "rev1:rev2 range to review already committed changeset.") +group.add_option("--send_mail", action="store_true", + dest="send_mail", default=True, + help="Send notification email to reviewers.") +group.add_option("--vcs", action="store", dest="vcs", + metavar="VCS", default="svn", + help=("Version control system (optional, usually upload.py " + "already guesses the right VCS).")) +group.add_option("--emulate_svn_auto_props", action="store_true", + dest="emulate_svn_auto_props", default=False, + help=("Emulate Subversion's auto properties feature.")) + + +def GetRpcServer(server, email=None, host_override=None, save_cookies=True, + account_type=AUTH_ACCOUNT_TYPE): + """Returns an instance of an AbstractRpcServer. + + Args: + server: String containing the review server URL. + email: String containing user's email address. + host_override: If not None, string containing an alternate hostname to use + in the host header. + save_cookies: Whether authentication cookies should be saved to disk. + account_type: Account type for authentication, either 'GOOGLE' + or 'HOSTED'. Defaults to AUTH_ACCOUNT_TYPE. + + Returns: + A new AbstractRpcServer, on which RPC calls can be made. + """ + + rpc_server_class = HttpRpcServer + + # If this is the dev_appserver, use fake authentication. + host = (host_override or server).lower() + if re.match(r'(http://)?localhost([:/]|$)', host): + if email is None: + email = "test@example.com" + logging.info("Using debug user %s. Override with --email" % email) + server = rpc_server_class( + server, + lambda: (email, "password"), + host_override=host_override, + extra_headers={"Cookie": + 'dev_appserver_login="%s:False"' % email}, + save_cookies=save_cookies, + account_type=account_type) + # Don't try to talk to ClientLogin. + server.authenticated = True + return server + + def GetUserCredentials(): + """Prompts the user for a username and password.""" + # Create a local alias to the email variable to avoid Python's crazy + # scoping rules. + local_email = email + if local_email is None: + local_email = GetEmail("Email (login for uploading to %s)" % server) + password = None + if keyring: + password = keyring.get_password(host, local_email) + if password is not None: + print("Using password from system keyring.") + else: + password = getpass.getpass("Password for %s: " % local_email) + if keyring: + answer = input("Store password in system keyring?(y/N) ").strip() + if answer == "y": + keyring.set_password(host, local_email, password) + return (local_email, password) + + return rpc_server_class(server, + GetUserCredentials, + host_override=host_override, + save_cookies=save_cookies) + + +def EncodeMultipartFormData(fields, files): + """Encode form fields for multipart/form-data. + + Args: + fields: A sequence of (name, value) elements for regular form fields. + files: A sequence of (name, filename, value) elements for data to be + uploaded as files. + Returns: + (content_type, body) ready for httplib.HTTP instance. + + Source: + http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306 + """ + BOUNDARY = '-M-A-G-I-C---B-O-U-N-D-A-R-Y-' + CRLF = '\r\n' + lines = [] + for (key, value) in fields: + lines.append('--' + BOUNDARY) + lines.append('Content-Disposition: form-data; name="%s"' % key) + lines.append('') + if isinstance(value, str): + value = value.encode('utf-8') + lines.append(value) + for (key, filename, value) in files: + lines.append('--' + BOUNDARY) + lines.append('Content-Disposition: form-data; name="%s"; filename="%s"' % + (key, filename)) + lines.append('Content-Type: %s' % GetContentType(filename)) + lines.append('') + if isinstance(value, str): + value = value.encode('utf-8') + lines.append(value) + lines.append('--' + BOUNDARY + '--') + lines.append('') + body = CRLF.join(lines) + content_type = 'multipart/form-data; boundary=%s' % BOUNDARY + return content_type, body + + +def GetContentType(filename): + """Helper to guess the content-type from the filename.""" + return mimetypes.guess_type(filename)[0] or 'application/octet-stream' + + +# Use a shell for subcommands on Windows to get a PATH search. +use_shell = sys.platform.startswith("win") + +def RunShellWithReturnCodeAndStderr(command, print_output=False, + universal_newlines=True, + env=os.environ): + """Executes a command and returns the output from stdout, stderr and the return code. + + Args: + command: Command to execute. + print_output: If True, the output is printed to stdout. + If False, both stdout and stderr are ignored. + universal_newlines: Use universal_newlines flag (default: True). + + Returns: + Tuple (stdout, stderr, return code) + """ + logging.info("Running %s", command) + env = env.copy() + env['LC_MESSAGES'] = 'C' + p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + shell=use_shell, universal_newlines=universal_newlines, + env=env) + if print_output: + output_array = [] + while True: + line = p.stdout.readline() + if not line: + break + print(line.strip("\n")) + output_array.append(line) + output = "".join(output_array) + else: + output = p.stdout.read() + p.wait() + errout = p.stderr.read() + if print_output and errout: + print(errout, file=sys.stderr) + p.stdout.close() + p.stderr.close() + return output, errout, p.returncode + +def RunShellWithReturnCode(command, print_output=False, + universal_newlines=True, + env=os.environ): + """Executes a command and returns the output from stdout and the return code.""" + out, err, retcode = RunShellWithReturnCodeAndStderr(command, print_output, + universal_newlines, env) + return out, retcode + +def RunShell(command, silent_ok=False, universal_newlines=True, + print_output=False, env=os.environ): + data, retcode = RunShellWithReturnCode(command, print_output, + universal_newlines, env) + if retcode: + ErrorExit("Got error status from %s:\n%s" % (command, data)) + if not silent_ok and not data: + ErrorExit("No output from %s" % command) + return data + + +class VersionControlSystem(object): + """Abstract base class providing an interface to the VCS.""" + + def __init__(self, options): + """Constructor. + + Args: + options: Command line options. + """ + self.options = options + + def PostProcessDiff(self, diff): + """Return the diff with any special post processing this VCS needs, e.g. + to include an svn-style "Index:".""" + return diff + + def GenerateDiff(self, args): + """Return the current diff as a string. + + Args: + args: Extra arguments to pass to the diff command. + """ + raise NotImplementedError( + "abstract method -- subclass %s must override" % self.__class__) + + def GetUnknownFiles(self): + """Return a list of files unknown to the VCS.""" + raise NotImplementedError( + "abstract method -- subclass %s must override" % self.__class__) + + def CheckForUnknownFiles(self): + """Show an "are you sure?" prompt if there are unknown files.""" + unknown_files = self.GetUnknownFiles() + if unknown_files: + print("The following files are not added to version control:") + for line in unknown_files: + print(line) + prompt = "Are you sure to continue?(y/N) " + answer = input(prompt).strip() + if answer != "y": + ErrorExit("User aborted") + + def GetBaseFile(self, filename): + """Get the content of the upstream version of a file. + + Returns: + A tuple (base_content, new_content, is_binary, status) + base_content: The contents of the base file. + new_content: For text files, this is empty. For binary files, this is + the contents of the new file, since the diff output won't contain + information to reconstruct the current file. + is_binary: True iff the file is binary. + status: The status of the file. + """ + + raise NotImplementedError( + "abstract method -- subclass %s must override" % self.__class__) + + + def GetBaseFiles(self, diff): + """Helper that calls GetBase file for each file in the patch. + + Returns: + A dictionary that maps from filename to GetBaseFile's tuple. Filenames + are retrieved based on lines that start with "Index:" or + "Property changes on:". + """ + files = {} + for line in diff.splitlines(True): + if line.startswith('Index:') or line.startswith('Property changes on:'): + unused, filename = line.split(':', 1) + # On Windows if a file has property changes its filename uses '\' + # instead of '/'. + filename = filename.strip().replace('\\', '/') + files[filename] = self.GetBaseFile(filename) + return files + + + def UploadBaseFiles(self, issue, rpc_server, patch_list, patchset, options, + files): + """Uploads the base files (and if necessary, the current ones as well).""" + + def UploadFile(filename, file_id, content, is_binary, status, is_base): + """Uploads a file to the server.""" + file_too_large = False + if is_base: + type = "base" + else: + type = "current" + if len(content) > MAX_UPLOAD_SIZE: + print(("Not uploading the %s file for %s because it's too large." % + (type, filename))) + file_too_large = True + content = "" + checksum = md5(content).hexdigest() + if options.verbose > 0 and not file_too_large: + print("Uploading %s file for %s" % (type, filename)) + url = "/%d/upload_content/%d/%d" % (int(issue), int(patchset), file_id) + form_fields = [("filename", filename), + ("status", status), + ("checksum", checksum), + ("is_binary", str(is_binary)), + ("is_current", str(not is_base)), + ] + if file_too_large: + form_fields.append(("file_too_large", "1")) + if options.email: + form_fields.append(("user", options.email)) + ctype, body = EncodeMultipartFormData(form_fields, + [("data", filename, content)]) + response_body = rpc_server.Send(url, body, + content_type=ctype) + if not response_body.startswith("OK"): + StatusUpdate(" --> %s" % response_body) + sys.exit(1) + + patches = dict() + [patches.setdefault(v, k) for k, v in patch_list] + for filename in list(patches.keys()): + base_content, new_content, is_binary, status = files[filename] + file_id_str = patches.get(filename) + if file_id_str.find("nobase") != -1: + base_content = None + file_id_str = file_id_str[file_id_str.rfind("_") + 1:] + file_id = int(file_id_str) + if base_content != None: + UploadFile(filename, file_id, base_content, is_binary, status, True) + if new_content != None: + UploadFile(filename, file_id, new_content, is_binary, status, False) + + def IsImage(self, filename): + """Returns true if the filename has an image extension.""" + mimetype = mimetypes.guess_type(filename)[0] + if not mimetype: + return False + return mimetype.startswith("image/") + + def IsBinary(self, filename): + """Returns true if the guessed mimetyped isnt't in text group.""" + mimetype = mimetypes.guess_type(filename)[0] + if not mimetype: + return False # e.g. README, "real" binaries usually have an extension + # special case for text files which don't start with text/ + if mimetype in TEXT_MIMETYPES: + return False + return not mimetype.startswith("text/") + + +class SubversionVCS(VersionControlSystem): + """Implementation of the VersionControlSystem interface for Subversion.""" + + def __init__(self, options): + super(SubversionVCS, self).__init__(options) + if self.options.revision: + match = re.match(r"(\d+)(:(\d+))?", self.options.revision) + if not match: + ErrorExit("Invalid Subversion revision %s." % self.options.revision) + self.rev_start = match.group(1) + self.rev_end = match.group(3) + else: + self.rev_start = self.rev_end = None + # Cache output from "svn list -r REVNO dirname". + # Keys: dirname, Values: 2-tuple (ouput for start rev and end rev). + self.svnls_cache = {} + # Base URL is required to fetch files deleted in an older revision. + # Result is cached to not guess it over and over again in GetBaseFile(). + required = self.options.download_base or self.options.revision is not None + self.svn_base = self._GuessBase(required) + + def GuessBase(self, required): + """Wrapper for _GuessBase.""" + return self.svn_base + + def _GuessBase(self, required): + """Returns base URL for current diff. + + Args: + required: If true, exits if the url can't be guessed, otherwise None is + returned. + """ + info = RunShell(["svn", "info"]) + for line in info.splitlines(): + if line.startswith("URL: "): + url = line.split()[1] + scheme, netloc, path, params, query, fragment = urllib.parse.urlparse(url) + guess = "" + if netloc == "svn.python.org" and scheme == "svn+ssh": + path = "projects" + path + scheme = "http" + guess = "Python " + elif netloc.endswith(".googlecode.com"): + scheme = "http" + guess = "Google Code " + path = path + "/" + base = urllib.parse.urlunparse((scheme, netloc, path, params, + query, fragment)) + logging.info("Guessed %sbase = %s", guess, base) + return base + if required: + ErrorExit("Can't find URL in output from svn info") + return None + + def GenerateDiff(self, args): + cmd = ["svn", "diff"] + if self.options.revision: + cmd += ["-r", self.options.revision] + cmd.extend(args) + data = RunShell(cmd) + count = 0 + for line in data.splitlines(): + if line.startswith("Index:") or line.startswith("Property changes on:"): + count += 1 + logging.info(line) + if not count: + ErrorExit("No valid patches found in output from svn diff") + return data + + def _CollapseKeywords(self, content, keyword_str): + """Collapses SVN keywords.""" + # svn cat translates keywords but svn diff doesn't. As a result of this + # behavior patching.PatchChunks() fails with a chunk mismatch error. + # This part was originally written by the Review Board development team + # who had the same problem (http://reviews.review-board.org/r/276/). + # Mapping of keywords to known aliases + svn_keywords = { + # Standard keywords + 'Date': ['Date', 'LastChangedDate'], + 'Revision': ['Revision', 'LastChangedRevision', 'Rev'], + 'Author': ['Author', 'LastChangedBy'], + 'HeadURL': ['HeadURL', 'URL'], + 'Id': ['Id'], + + # Aliases + 'LastChangedDate': ['LastChangedDate', 'Date'], + 'LastChangedRevision': ['LastChangedRevision', 'Rev', 'Revision'], + 'LastChangedBy': ['LastChangedBy', 'Author'], + 'URL': ['URL', 'HeadURL'], + } + + def repl(m): + if m.group(2): + return "$%s::%s$" % (m.group(1), " " * len(m.group(3))) + return "$%s$" % m.group(1) + keywords = [keyword + for name in keyword_str.split(" ") + for keyword in svn_keywords.get(name, [])] + return re.sub(r"\$(%s):(:?)([^\$]+)\$" % '|'.join(keywords), repl, content) + + def GetUnknownFiles(self): + status = RunShell(["svn", "status", "--ignore-externals"], silent_ok=True) + unknown_files = [] + for line in status.split("\n"): + if line and line[0] == "?": + unknown_files.append(line) + return unknown_files + + def ReadFile(self, filename): + """Returns the contents of a file.""" + file = open(filename, 'rb') + result = "" + try: + result = file.read() + finally: + file.close() + return result + + def GetStatus(self, filename): + """Returns the status of a file.""" + if not self.options.revision: + status = RunShell(["svn", "status", "--ignore-externals", filename]) + if not status: + ErrorExit("svn status returned no output for %s" % filename) + status_lines = status.splitlines() + # If file is in a cl, the output will begin with + # "\n--- Changelist 'cl_name':\n". See + # http://svn.collab.net/repos/svn/trunk/notes/changelist-design.txt + if (len(status_lines) == 3 and + not status_lines[0] and + status_lines[1].startswith("--- Changelist")): + status = status_lines[2] + else: + status = status_lines[0] + # If we have a revision to diff against we need to run "svn list" + # for the old and the new revision and compare the results to get + # the correct status for a file. + else: + dirname, relfilename = os.path.split(filename) + if dirname not in self.svnls_cache: + cmd = ["svn", "list", "-r", self.rev_start, dirname or "."] + out, err, returncode = RunShellWithReturnCodeAndStderr(cmd) + if returncode: + # Directory might not yet exist at start revison + # svn: Unable to find repository location for 'abc' in revision nnn + if re.match('^svn: Unable to find repository location for .+ in revision \d+', err): + old_files = () + else: + ErrorExit("Failed to get status for %s:\n%s" % (filename, err)) + else: + old_files = out.splitlines() + args = ["svn", "list"] + if self.rev_end: + args += ["-r", self.rev_end] + cmd = args + [dirname or "."] + out, returncode = RunShellWithReturnCode(cmd) + if returncode: + ErrorExit("Failed to run command %s" % cmd) + self.svnls_cache[dirname] = (old_files, out.splitlines()) + old_files, new_files = self.svnls_cache[dirname] + if relfilename in old_files and relfilename not in new_files: + status = "D " + elif relfilename in old_files and relfilename in new_files: + status = "M " + else: + status = "A " + return status + + def GetBaseFile(self, filename): + status = self.GetStatus(filename) + base_content = None + new_content = None + + # If a file is copied its status will be "A +", which signifies + # "addition-with-history". See "svn st" for more information. We need to + # upload the original file or else diff parsing will fail if the file was + # edited. + if status[0] == "A" and status[3] != "+": + # We'll need to upload the new content if we're adding a binary file + # since diff's output won't contain it. + mimetype = RunShell(["svn", "propget", "svn:mime-type", filename], + silent_ok=True) + base_content = "" + is_binary = bool(mimetype) and not mimetype.startswith("text/") + if is_binary and self.IsImage(filename): + new_content = self.ReadFile(filename) + elif (status[0] in ("M", "D", "R") or + (status[0] == "A" and status[3] == "+") or # Copied file. + (status[0] == " " and status[1] == "M")): # Property change. + args = [] + if self.options.revision: + url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start) + else: + # Don't change filename, it's needed later. + url = filename + args += ["-r", "BASE"] + cmd = ["svn"] + args + ["propget", "svn:mime-type", url] + mimetype, returncode = RunShellWithReturnCode(cmd) + if returncode: + # File does not exist in the requested revision. + # Reset mimetype, it contains an error message. + mimetype = "" + else: + mimetype = mimetype.strip() + get_base = False + is_binary = (bool(mimetype) and + not mimetype.startswith("text/") and + not mimetype in TEXT_MIMETYPES) + if status[0] == " ": + # Empty base content just to force an upload. + base_content = "" + elif is_binary: + if self.IsImage(filename): + get_base = True + if status[0] == "M": + if not self.rev_end: + new_content = self.ReadFile(filename) + else: + url = "%s/%s@%s" % (self.svn_base, filename, self.rev_end) + new_content = RunShell(["svn", "cat", url], + universal_newlines=True, silent_ok=True) + else: + base_content = "" + else: + get_base = True + + if get_base: + if is_binary: + universal_newlines = False + else: + universal_newlines = True + if self.rev_start: + # "svn cat -r REV delete_file.txt" doesn't work. cat requires + # the full URL with "@REV" appended instead of using "-r" option. + url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start) + base_content = RunShell(["svn", "cat", url], + universal_newlines=universal_newlines, + silent_ok=True) + else: + base_content, ret_code = RunShellWithReturnCode( + ["svn", "cat", filename], universal_newlines=universal_newlines) + if ret_code and status[0] == "R": + # It's a replaced file without local history (see issue208). + # The base file needs to be fetched from the server. + url = "%s/%s" % (self.svn_base, filename) + base_content = RunShell(["svn", "cat", url], + universal_newlines=universal_newlines, + silent_ok=True) + elif ret_code: + ErrorExit("Got error status from 'svn cat %s'" % filename) + if not is_binary: + args = [] + if self.rev_start: + url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start) + else: + url = filename + args += ["-r", "BASE"] + cmd = ["svn"] + args + ["propget", "svn:keywords", url] + keywords, returncode = RunShellWithReturnCode(cmd) + if keywords and not returncode: + base_content = self._CollapseKeywords(base_content, keywords) + else: + StatusUpdate("svn status returned unexpected output: %s" % status) + sys.exit(1) + return base_content, new_content, is_binary, status[0:5] + + +class GitVCS(VersionControlSystem): + """Implementation of the VersionControlSystem interface for Git.""" + + def __init__(self, options): + super(GitVCS, self).__init__(options) + # Map of filename -> (hash before, hash after) of base file. + # Hashes for "no such file" are represented as None. + self.hashes = {} + # Map of new filename -> old filename for renames. + self.renames = {} + + def PostProcessDiff(self, gitdiff): + """Converts the diff output to include an svn-style "Index:" line as well + as record the hashes of the files, so we can upload them along with our + diff.""" + # Special used by git to indicate "no such content". + NULL_HASH = "0"*40 + + def IsFileNew(filename): + return filename in self.hashes and self.hashes[filename][0] is None + + def AddSubversionPropertyChange(filename): + """Add svn's property change information into the patch if given file is + new file. + + We use Subversion's auto-props setting to retrieve its property. + See http://svnbook.red-bean.com/en/1.1/ch07.html#svn-ch-7-sect-1.3.2 for + Subversion's [auto-props] setting. + """ + if self.options.emulate_svn_auto_props and IsFileNew(filename): + svnprops = GetSubversionPropertyChanges(filename) + if svnprops: + svndiff.append("\n" + svnprops + "\n") + + svndiff = [] + filecount = 0 + filename = None + for line in gitdiff.splitlines(): + match = re.match(r"diff --git a/(.*) b/(.*)$", line) + if match: + # Add auto property here for previously seen file. + if filename is not None: + AddSubversionPropertyChange(filename) + filecount += 1 + # Intentionally use the "after" filename so we can show renames. + filename = match.group(2) + svndiff.append("Index: %s\n" % filename) + if match.group(1) != match.group(2): + self.renames[match.group(2)] = match.group(1) + else: + # The "index" line in a git diff looks like this (long hashes elided): + # index 82c0d44..b2cee3f 100755 + # We want to save the left hash, as that identifies the base file. + match = re.match(r"index (\w+)\.\.(\w+)", line) + if match: + before, after = (match.group(1), match.group(2)) + if before == NULL_HASH: + before = None + if after == NULL_HASH: + after = None + self.hashes[filename] = (before, after) + svndiff.append(line + "\n") + if not filecount: + ErrorExit("No valid patches found in output from git diff") + # Add auto property for the last seen file. + assert filename is not None + AddSubversionPropertyChange(filename) + return "".join(svndiff) + + def GenerateDiff(self, extra_args): + extra_args = extra_args[:] + if self.options.revision: + if ":" in self.options.revision: + extra_args = self.options.revision.split(":", 1) + extra_args + else: + extra_args = [self.options.revision] + extra_args + + # --no-ext-diff is broken in some versions of Git, so try to work around + # this by overriding the environment (but there is still a problem if the + # git config key "diff.external" is used). + env = os.environ.copy() + if 'GIT_EXTERNAL_DIFF' in env: del env['GIT_EXTERNAL_DIFF'] + return RunShell(["git", "diff", "--no-ext-diff", "--full-index", "-M"] + + extra_args, env=env) + + def GetUnknownFiles(self): + status = RunShell(["git", "ls-files", "--exclude-standard", "--others"], + silent_ok=True) + return status.splitlines() + + def GetFileContent(self, file_hash, is_binary): + """Returns the content of a file identified by its git hash.""" + data, retcode = RunShellWithReturnCode(["git", "show", file_hash], + universal_newlines=not is_binary) + if retcode: + ErrorExit("Got error status from 'git show %s'" % file_hash) + return data + + def GetBaseFile(self, filename): + hash_before, hash_after = self.hashes.get(filename, (None,None)) + base_content = None + new_content = None + is_binary = self.IsBinary(filename) + status = None + + if filename in self.renames: + status = "A +" # Match svn attribute name for renames. + if filename not in self.hashes: + # If a rename doesn't change the content, we never get a hash. + base_content = RunShell(["git", "show", "HEAD:" + filename]) + elif not hash_before: + status = "A" + base_content = "" + elif not hash_after: + status = "D" + else: + status = "M" + + is_image = self.IsImage(filename) + + # Grab the before/after content if we need it. + # We should include file contents if it's text or it's an image. + if not is_binary or is_image: + # Grab the base content if we don't have it already. + if base_content is None and hash_before: + base_content = self.GetFileContent(hash_before, is_binary) + # Only include the "after" file if it's an image; otherwise it + # it is reconstructed from the diff. + if is_image and hash_after: + new_content = self.GetFileContent(hash_after, is_binary) + + return (base_content, new_content, is_binary, status) + + +class MercurialVCS(VersionControlSystem): + """Implementation of the VersionControlSystem interface for Mercurial.""" + + def __init__(self, options, repo_dir): + super(MercurialVCS, self).__init__(options) + # Absolute path to repository (we can be in a subdir) + self.repo_dir = os.path.normpath(repo_dir) + # Compute the subdir + cwd = os.path.normpath(os.getcwd()) + assert cwd.startswith(self.repo_dir) + self.subdir = cwd[len(self.repo_dir):].lstrip(r"\/") + if self.options.revision: + self.base_rev = self.options.revision + else: + self.base_rev = RunShell(["hg", "parent", "-q"]).split(':')[1].strip() + + def _GetRelPath(self, filename): + """Get relative path of a file according to the current directory, + given its logical path in the repo.""" + assert filename.startswith(self.subdir), (filename, self.subdir) + return filename[len(self.subdir):].lstrip(r"\/") + + def GenerateDiff(self, extra_args): + cmd = ["hg", "diff", "--git", "-r", self.base_rev] + extra_args + data = RunShell(cmd, silent_ok=True) + svndiff = [] + filecount = 0 + for line in data.splitlines(): + m = re.match("diff --git a/(\S+) b/(\S+)", line) + if m: + # Modify line to make it look like as it comes from svn diff. + # With this modification no changes on the server side are required + # to make upload.py work with Mercurial repos. + # NOTE: for proper handling of moved/copied files, we have to use + # the second filename. + filename = m.group(2) + svndiff.append("Index: %s" % filename) + svndiff.append("=" * 67) + filecount += 1 + logging.info(line) + else: + svndiff.append(line) + if not filecount: + ErrorExit("No valid patches found in output from hg diff") + return "\n".join(svndiff) + "\n" + + def GetUnknownFiles(self): + """Return a list of files unknown to the VCS.""" + args = [] + status = RunShell(["hg", "status", "--rev", self.base_rev, "-u", "."], + silent_ok=True) + unknown_files = [] + for line in status.splitlines(): + st, fn = line.split(" ", 1) + if st == "?": + unknown_files.append(fn) + return unknown_files + + def GetBaseFile(self, filename): + # "hg status" and "hg cat" both take a path relative to the current subdir + # rather than to the repo root, but "hg diff" has given us the full path + # to the repo root. + base_content = "" + new_content = None + is_binary = False + oldrelpath = relpath = self._GetRelPath(filename) + # "hg status -C" returns two lines for moved/copied files, one otherwise + out = RunShell(["hg", "status", "-C", "--rev", self.base_rev, relpath]) + out = out.splitlines() + # HACK: strip error message about missing file/directory if it isn't in + # the working copy + if out[0].startswith('%s: ' % relpath): + out = out[1:] + status, _ = out[0].split(' ', 1) + if len(out) > 1 and status == "A": + # Moved/copied => considered as modified, use old filename to + # retrieve base contents + oldrelpath = out[1].strip() + status = "M" + if ":" in self.base_rev: + base_rev = self.base_rev.split(":", 1)[0] + else: + base_rev = self.base_rev + if status != "A": + base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath], + silent_ok=True) + is_binary = "\0" in base_content # Mercurial's heuristic + if status != "R": + new_content = open(relpath, "rb").read() + is_binary = is_binary or "\0" in new_content + if is_binary and base_content: + # Fetch again without converting newlines + base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath], + silent_ok=True, universal_newlines=False) + if not is_binary or not self.IsImage(relpath): + new_content = None + return base_content, new_content, is_binary, status + + +# NOTE: The SplitPatch function is duplicated in engine.py, keep them in sync. +def SplitPatch(data): + """Splits a patch into separate pieces for each file. + + Args: + data: A string containing the output of svn diff. + + Returns: + A list of 2-tuple (filename, text) where text is the svn diff output + pertaining to filename. + """ + patches = [] + filename = None + diff = [] + for line in data.splitlines(True): + new_filename = None + if line.startswith('Index:'): + unused, new_filename = line.split(':', 1) + new_filename = new_filename.strip() + elif line.startswith('Property changes on:'): + unused, temp_filename = line.split(':', 1) + # When a file is modified, paths use '/' between directories, however + # when a property is modified '\' is used on Windows. Make them the same + # otherwise the file shows up twice. + temp_filename = temp_filename.strip().replace('\\', '/') + if temp_filename != filename: + # File has property changes but no modifications, create a new diff. + new_filename = temp_filename + if new_filename: + if filename and diff: + patches.append((filename, ''.join(diff))) + filename = new_filename + diff = [line] + continue + if diff is not None: + diff.append(line) + if filename and diff: + patches.append((filename, ''.join(diff))) + return patches + + +def UploadSeparatePatches(issue, rpc_server, patchset, data, options): + """Uploads a separate patch for each file in the diff output. + + Returns a list of [patch_key, filename] for each file. + """ + patches = SplitPatch(data) + rv = [] + for patch in patches: + if len(patch[1]) > MAX_UPLOAD_SIZE: + print(("Not uploading the patch for " + patch[0] + + " because the file is too large.")) + continue + form_fields = [("filename", patch[0])] + if not options.download_base: + form_fields.append(("content_upload", "1")) + files = [("data", "data.diff", patch[1])] + ctype, body = EncodeMultipartFormData(form_fields, files) + url = "/%d/upload_patch/%d" % (int(issue), int(patchset)) + print("Uploading patch for " + patch[0]) + response_body = rpc_server.Send(url, body, content_type=ctype) + lines = response_body.splitlines() + if not lines or lines[0] != "OK": + StatusUpdate(" --> %s" % response_body) + sys.exit(1) + rv.append([lines[1], patch[0]]) + return rv + + +def GuessVCSName(): + """Helper to guess the version control system. + + This examines the current directory, guesses which VersionControlSystem + we're using, and returns an string indicating which VCS is detected. + + Returns: + A pair (vcs, output). vcs is a string indicating which VCS was detected + and is one of VCS_GIT, VCS_MERCURIAL, VCS_SUBVERSION, or VCS_UNKNOWN. + output is a string containing any interesting output from the vcs + detection routine, or None if there is nothing interesting. + """ + def RunDetectCommand(vcs_type, command): + """Helper to detect VCS by executing command. + + Returns: + A pair (vcs, output) or None. Throws exception on error. + """ + try: + out, returncode = RunShellWithReturnCode(command) + if returncode == 0: + return (vcs_type, out.strip()) + except OSError as xxx_todo_changeme: + (errcode, message) = xxx_todo_changeme.args + if errcode != errno.ENOENT: # command not found code + raise + + # Mercurial has a command to get the base directory of a repository + # Try running it, but don't die if we don't have hg installed. + # NOTE: we try Mercurial first as it can sit on top of an SVN working copy. + res = RunDetectCommand(VCS_MERCURIAL, ["hg", "root"]) + if res != None: + return res + + # Subversion has a .svn in all working directories. + if os.path.isdir('.svn'): + logging.info("Guessed VCS = Subversion") + return (VCS_SUBVERSION, None) + + # Git has a command to test if you're in a git tree. + # Try running it, but don't die if we don't have git installed. + res = RunDetectCommand(VCS_GIT, ["git", "rev-parse", + "--is-inside-work-tree"]) + if res != None: + return res + + return (VCS_UNKNOWN, None) + + +def GuessVCS(options): + """Helper to guess the version control system. + + This verifies any user-specified VersionControlSystem (by command line + or environment variable). If the user didn't specify one, this examines + the current directory, guesses which VersionControlSystem we're using, + and returns an instance of the appropriate class. Exit with an error + if we can't figure it out. + + Returns: + A VersionControlSystem instance. Exits if the VCS can't be guessed. + """ + vcs = options.vcs + if not vcs: + vcs = os.environ.get("CODEREVIEW_VCS") + if vcs: + v = VCS_ABBREVIATIONS.get(vcs.lower()) + if v is None: + ErrorExit("Unknown version control system %r specified." % vcs) + (vcs, extra_output) = (v, None) + else: + (vcs, extra_output) = GuessVCSName() + + if vcs == VCS_MERCURIAL: + if extra_output is None: + extra_output = RunShell(["hg", "root"]).strip() + return MercurialVCS(options, extra_output) + elif vcs == VCS_SUBVERSION: + return SubversionVCS(options) + elif vcs == VCS_GIT: + return GitVCS(options) + + ErrorExit(("Could not guess version control system. " + "Are you in a working copy directory?")) + + +def CheckReviewer(reviewer): + """Validate a reviewer -- either a nickname or an email addres. + + Args: + reviewer: A nickname or an email address. + + Calls ErrorExit() if it is an invalid email address. + """ + if "@" not in reviewer: + return # Assume nickname + parts = reviewer.split("@") + if len(parts) > 2: + ErrorExit("Invalid email address: %r" % reviewer) + assert len(parts) == 2 + if "." not in parts[1]: + ErrorExit("Invalid email address: %r" % reviewer) + + +def LoadSubversionAutoProperties(): + """Returns the content of [auto-props] section of Subversion's config file as + a dictionary. + + Returns: + A dictionary whose key-value pair corresponds the [auto-props] section's + key-value pair. + In following cases, returns empty dictionary: + - config file doesn't exist, or + - 'enable-auto-props' is not set to 'true-like-value' in [miscellany]. + """ + if os.name == 'nt': + subversion_config = os.environ.get("APPDATA") + "\\Subversion\\config" + else: + subversion_config = os.path.expanduser("~/.subversion/config") + if not os.path.exists(subversion_config): + return {} + config = configparser.ConfigParser() + config.read(subversion_config) + if (config.has_section("miscellany") and + config.has_option("miscellany", "enable-auto-props") and + config.getboolean("miscellany", "enable-auto-props") and + config.has_section("auto-props")): + props = {} + for file_pattern in config.options("auto-props"): + props[file_pattern] = ParseSubversionPropertyValues( + config.get("auto-props", file_pattern)) + return props + else: + return {} + +def ParseSubversionPropertyValues(props): + """Parse the given property value which comes from [auto-props] section and + returns a list whose element is a (svn_prop_key, svn_prop_value) pair. + + See the following doctest for example. + + >>> ParseSubversionPropertyValues('svn:eol-style=LF') + [('svn:eol-style', 'LF')] + >>> ParseSubversionPropertyValues('svn:mime-type=image/jpeg') + [('svn:mime-type', 'image/jpeg')] + >>> ParseSubversionPropertyValues('svn:eol-style=LF;svn:executable') + [('svn:eol-style', 'LF'), ('svn:executable', '*')] + """ + key_value_pairs = [] + for prop in props.split(";"): + key_value = prop.split("=") + assert len(key_value) <= 2 + if len(key_value) == 1: + # If value is not given, use '*' as a Subversion's convention. + key_value_pairs.append((key_value[0], "*")) + else: + key_value_pairs.append((key_value[0], key_value[1])) + return key_value_pairs + + +def GetSubversionPropertyChanges(filename): + """Return a Subversion's 'Property changes on ...' string, which is used in + the patch file. + + Args: + filename: filename whose property might be set by [auto-props] config. + + Returns: + A string like 'Property changes on |filename| ...' if given |filename| + matches any entries in [auto-props] section. None, otherwise. + """ + global svn_auto_props_map + if svn_auto_props_map is None: + svn_auto_props_map = LoadSubversionAutoProperties() + + all_props = [] + for file_pattern, props in list(svn_auto_props_map.items()): + if fnmatch.fnmatch(filename, file_pattern): + all_props.extend(props) + if all_props: + return FormatSubversionPropertyChanges(filename, all_props) + return None + + +def FormatSubversionPropertyChanges(filename, props): + """Returns Subversion's 'Property changes on ...' strings using given filename + and properties. + + Args: + filename: filename + props: A list whose element is a (svn_prop_key, svn_prop_value) pair. + + Returns: + A string which can be used in the patch file for Subversion. + + See the following doctest for example. + + >>> print FormatSubversionPropertyChanges('foo.cc', [('svn:eol-style', 'LF')]) + Property changes on: foo.cc + ___________________________________________________________________ + Added: svn:eol-style + + LF + + """ + prop_changes_lines = [ + "Property changes on: %s" % filename, + "___________________________________________________________________"] + for key, value in props: + prop_changes_lines.append("Added: " + key) + prop_changes_lines.append(" + " + value) + return "\n".join(prop_changes_lines) + "\n" + + +def RealMain(argv, data=None): + """The real main function. + + Args: + argv: Command line arguments. + data: Diff contents. If None (default) the diff is generated by + the VersionControlSystem implementation returned by GuessVCS(). + + Returns: + A 2-tuple (issue id, patchset id). + The patchset id is None if the base files are not uploaded by this + script (applies only to SVN checkouts). + """ + options, args = parser.parse_args(argv[1:]) + global verbosity + verbosity = options.verbose + if verbosity >= 3: + logging.getLogger().setLevel(logging.DEBUG) + elif verbosity >= 2: + logging.getLogger().setLevel(logging.INFO) + + vcs = GuessVCS(options) + + base = options.base_url + if isinstance(vcs, SubversionVCS): + # Guessing the base field is only supported for Subversion. + # Note: Fetching base files may become deprecated in future releases. + guessed_base = vcs.GuessBase(options.download_base) + if base: + if guessed_base and base != guessed_base: + print("Using base URL \"%s\" from --base_url instead of \"%s\"" % \ + (base, guessed_base)) + else: + base = guessed_base + + if not base and options.download_base: + options.download_base = True + logging.info("Enabled upload of base file") + if not options.assume_yes: + vcs.CheckForUnknownFiles() + if data is None: + data = vcs.GenerateDiff(args) + data = vcs.PostProcessDiff(data) + files = vcs.GetBaseFiles(data) + if verbosity >= 1: + print("Upload server:", options.server, "(change with -s/--server)") + if options.issue: + prompt = "Message describing this patch set: " + else: + prompt = "New issue subject: " + message = options.message or input(prompt).strip() + if not message: + ErrorExit("A non-empty message is required") + rpc_server = GetRpcServer(options.server, + options.email, + options.host, + options.save_cookies, + options.account_type) + form_fields = [("subject", message)] + if base: + b = urllib.parse.urlparse(base) + username, netloc = urllib.parse.splituser(b.netloc) + if username: + logging.info("Removed username from base URL") + base = urllib.parse.urlunparse((b.scheme, netloc, b.path, b.params, + b.query, b.fragment)) + form_fields.append(("base", base)) + if options.issue: + form_fields.append(("issue", str(options.issue))) + if options.email: + form_fields.append(("user", options.email)) + if options.reviewers: + for reviewer in options.reviewers.split(','): + CheckReviewer(reviewer) + form_fields.append(("reviewers", options.reviewers)) + if options.cc: + for cc in options.cc.split(','): + CheckReviewer(cc) + form_fields.append(("cc", options.cc)) + description = options.description + if options.description_file: + if options.description: + ErrorExit("Can't specify description and description_file") + file = open(options.description_file, 'r') + description = file.read() + file.close() + if description: + form_fields.append(("description", description)) + # Send a hash of all the base file so the server can determine if a copy + # already exists in an earlier patchset. + base_hashes = "" + for file, info in files.items(): + if not info[0] is None: + checksum = md5(info[0]).hexdigest() + if base_hashes: + base_hashes += "|" + base_hashes += checksum + ":" + file + form_fields.append(("base_hashes", base_hashes)) + if options.private: + if options.issue: + print("Warning: Private flag ignored when updating an existing issue.") + else: + form_fields.append(("private", "1")) + # If we're uploading base files, don't send the email before the uploads, so + # that it contains the file status. + if options.send_mail and options.download_base: + form_fields.append(("send_mail", "1")) + if not options.download_base: + form_fields.append(("content_upload", "1")) + if len(data) > MAX_UPLOAD_SIZE: + print("Patch is large, so uploading file patches separately.") + uploaded_diff_file = [] + form_fields.append(("separate_patches", "1")) + else: + uploaded_diff_file = [("data", "data.diff", data)] + ctype, body = EncodeMultipartFormData(form_fields, uploaded_diff_file) + response_body = rpc_server.Send("/upload", body, content_type=ctype) + patchset = None + if not options.download_base or not uploaded_diff_file: + lines = response_body.splitlines() + if len(lines) >= 2: + msg = lines[0] + patchset = lines[1].strip() + patches = [x.split(" ", 1) for x in lines[2:]] + else: + msg = response_body + else: + msg = response_body + StatusUpdate(msg) + if not response_body.startswith("Issue created.") and \ + not response_body.startswith("Issue updated."): + sys.exit(0) + issue = msg[msg.rfind("/")+1:] + + if not uploaded_diff_file: + result = UploadSeparatePatches(issue, rpc_server, patchset, data, options) + if not options.download_base: + patches = result + + if not options.download_base: + vcs.UploadBaseFiles(issue, rpc_server, patches, patchset, options, files) + if options.send_mail: + rpc_server.Send("/" + issue + "/mail", payload="") + return issue, patchset + + +def main(): + try: + logging.basicConfig(format=("%(asctime).19s %(levelname)s %(filename)s:" + "%(lineno)s %(message)s ")) + os.environ['LC_ALL'] = 'C' + RealMain(sys.argv) + except KeyboardInterrupt: + print() + StatusUpdate("Interrupted.") + sys.exit(1) + + +if __name__ == "__main__": + main() + diff --git a/runtest.py b/runtest.py index 6beb4ba..65d7851 100755 --- a/runtest.py +++ b/runtest.py @@ -92,10 +92,10 @@ import time try: import threading - import Queue # 2to3: rename to queue + import queue # 2to3: rename to queue threading_ok = True except ImportError: - print "Can't import threading or queue" + print("Can't import threading or queue") threading_ok = False cwd = os.getcwd() @@ -187,12 +187,12 @@ class PassThroughOptionParser(OptionParser): def _process_long_opt(self, rargs, values): try: OptionParser._process_long_opt(self, rargs, values) - except BadOptionError, err: + except BadOptionError as err: self.largs.append(err.opt_str) def _process_short_opts(self, rargs, values): try: OptionParser._process_short_opts(self, rargs, values) - except BadOptionError, err: + except BadOptionError as err: self.largs.append(err.opt_str) parser = PassThroughOptionParser(add_help_option=False) @@ -240,7 +240,7 @@ for o, a in opts: a = os.path.join(cwd, a) testlistfile = a elif o in ['-h', '--help']: - print helpstr + print(helpstr) sys.exit(0) elif o in ['-j', '--jobs']: jobs = int(a) @@ -343,7 +343,7 @@ else: st = os.stat(f) except OSError: continue - if stat.S_IMODE(st[stat.ST_MODE]) & 0111: + if stat.S_IMODE(st[stat.ST_MODE]) & 0o111: return f return None @@ -590,7 +590,7 @@ else: base = os.path.join(base, os.path.split(url)[1]) if printcommand: - print command + print(command) if execute_tests: os.system(command) else: @@ -843,9 +843,9 @@ def run_test(t, io_lock, async=True): if suppress_stdout or suppress_stderr: sys.stdout.write(header) if not suppress_stdout and t.stdout: - print t.stdout + print(t.stdout) if not suppress_stderr and t.stderr: - print t.stderr + print(t.stderr) print_time_func("Test execution time: %.1f seconds\n", t.test_time) if io_lock: io_lock.release() @@ -863,9 +863,9 @@ class RunTest(threading.Thread): self.queue.task_done() if jobs > 1 and threading_ok: - print "Running tests using %d jobs"%jobs + print("Running tests using %d jobs"%jobs) # Start worker threads - queue = Queue.Queue() + queue = queue.Queue() io_lock = threading.Lock() for i in range(1, jobs): t = RunTest(queue, io_lock) @@ -878,7 +878,7 @@ if jobs > 1 and threading_ok: else: # Run tests serially if jobs > 1: - print "Ignoring -j%d option; no python threading module available."%jobs + print("Ignoring -j%d option; no python threading module available."%jobs) for t in tests: run_test(t, None, False) diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index c1eef75..e8574cb 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -114,6 +114,7 @@ import SCons.Errors import SCons.Executor import SCons.Util import SCons.Subst +import collections # we use these a lot, so try to optimize them is_String = SCons.Util.is_String @@ -165,12 +166,12 @@ def _callable_contents(obj): """ try: # Test if obj is a method. - return _function_contents(obj.im_func) + return _function_contents(obj.__func__) except AttributeError: try: # Test if obj is a callable object. - return _function_contents(obj.__call__.im_func) + return _function_contents(obj.__call__.__func__) except AttributeError: try: @@ -190,12 +191,12 @@ def _object_contents(obj): """ try: # Test if obj is a method. - return _function_contents(obj.im_func) + return _function_contents(obj.__func__) except AttributeError: try: # Test if obj is a callable object. - return _function_contents(obj.__call__.im_func) + return _function_contents(obj.__call__.__func__) except AttributeError: try: @@ -269,17 +270,17 @@ def _code_contents(code): def _function_contents(func): """Return the signature contents of a function.""" - contents = [_code_contents(func.func_code)] + contents = [_code_contents(func.__code__)] # The function contents depends on the value of defaults arguments - if func.func_defaults: - contents.append(',(' + ','.join(map(_object_contents,func.func_defaults)) + ')') + if func.__defaults__: + contents.append(',(' + ','.join(map(_object_contents,func.__defaults__)) + ')') else: contents.append(',()') # The function contents depends on the closure captured cell values. try: - closure = func.func_closure or [] + closure = func.__closure__ or [] except AttributeError: # Older versions of Python do not support closures. closure = [] @@ -328,7 +329,7 @@ def _do_create_keywords(args, kw): cmdstrfunc = args[0] if cmdstrfunc is None or is_String(cmdstrfunc): kw['cmdstr'] = cmdstrfunc - elif callable(cmdstrfunc): + elif isinstance(cmdstrfunc, collections.Callable): kw['strfunction'] = cmdstrfunc else: raise SCons.Errors.UserError( @@ -359,7 +360,7 @@ def _do_create_action(act, kw): if is_List(act): return CommandAction(act, **kw) - if callable(act): + if isinstance(act, collections.Callable): try: gen = kw['generator'] del kw['generator'] @@ -492,7 +493,7 @@ class _ActionAction(ActionBase): self.targets = targets if batch_key: - if not callable(batch_key): + if not isinstance(batch_key, collections.Callable): # They have set batch_key, but not to their own # callable. The default behavior here will batch # *all* targets+sources using this action, separated @@ -512,7 +513,7 @@ class _ActionAction(ActionBase): # This code assumes s is a regular string, but should # work if it's unicode too. try: - sys.stdout.write(unicode(s + "\n")) + sys.stdout.write(str(s + "\n")) except UnicodeDecodeError: sys.stdout.write(s + "\n") @@ -553,7 +554,7 @@ class _ActionAction(ActionBase): source = executor.get_all_sources() t = ' and '.join(map(str, target)) l = '\n '.join(self.presub_lines(env)) - out = u"Building %s with action:\n %s\n" % (t, l) + out = "Building %s with action:\n %s\n" % (t, l) sys.stdout.write(out) cmd = None if show and self.strfunction: @@ -653,7 +654,7 @@ def _subproc(scons_env, cmd, error = 'ignore', **kw): # Ensure that the ENV values are all strings: new_env = {} - for key, value in ENV.items(): + for key, value in list(ENV.items()): if is_List(value): # If the value is a list, then we assume it is a path list, # because that's a pretty common list-like value to stick @@ -672,7 +673,7 @@ def _subproc(scons_env, cmd, error = 'ignore', **kw): try: return subprocess.Popen(cmd, **kw) - except EnvironmentError, e: + except EnvironmentError as e: if error == 'raise': raise # return a dummy Popen instance that only returns error class dummyPopen(object): @@ -779,7 +780,7 @@ class CommandAction(_ActionAction): ENV = get_default_ENV(env) # Ensure that the ENV values are all strings: - for key, value in ENV.items(): + for key, value in list(ENV.items()): if not is_String(value): if is_List(value): # If the value is a list, then we assume it is a @@ -1038,7 +1039,7 @@ class FunctionAction(_ActionAction): else: if strfunc is None: return None - if callable(strfunc): + if isinstance(strfunc, collections.Callable): return strfunc(target, source, env) name = self.function_name() tstr = array(target) @@ -1060,11 +1061,11 @@ class FunctionAction(_ActionAction): rsources = list(map(rfile, source)) try: result = self.execfunction(target=target, source=rsources, env=env) - except KeyboardInterrupt, e: + except KeyboardInterrupt as e: raise - except SystemExit, e: + except SystemExit as e: raise - except Exception, e: + except Exception as e: result = e exc_info = sys.exc_info() @@ -1179,11 +1180,11 @@ class ActionCaller(object): actfunc = self.parent.actfunc try: # "self.actfunc" is a function. - contents = str(actfunc.func_code.co_code) + contents = str(actfunc.__code__.co_code) except AttributeError: # "self.actfunc" is a callable object. try: - contents = str(actfunc.__call__.im_func.func_code.co_code) + contents = str(actfunc.__call__.__func__.__code__.co_code) except AttributeError: # No __call__() method, so it might be a builtin # or something like that. Do the best we can. @@ -1214,7 +1215,7 @@ class ActionCaller(object): def subst_kw(self, target, source, env): kw = {} - for key in self.kw.keys(): + for key in list(self.kw.keys()): kw[key] = self.subst(self.kw[key], target, source, env) return kw diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py index 13c3b6c..6edf373 100644 --- a/src/engine/SCons/ActionTests.py +++ b/src/engine/SCons/ActionTests.py @@ -133,7 +133,7 @@ class Environment(object): self.d['SPAWN'] = scons_env['SPAWN'] self.d['PSPAWN'] = scons_env['PSPAWN'] self.d['ESCAPE'] = scons_env['ESCAPE'] - for k, v in kw.items(): + for k, v in list(kw.items()): self.d[k] = v # Just use the underlying scons_subst*() utility methods. def subst(self, strSubst, raw=0, target=[], source=[], conv=None): @@ -158,12 +158,12 @@ class Environment(object): def Clone(self, **kw): res = Environment() res.d = SCons.Util.semi_deepcopy(self.d) - for k, v in kw.items(): + for k, v in list(kw.items()): res.d[k] = v return res def sig_dict(self): d = {} - for k,v in self.items(): d[k] = v + for k,v in list(self.items()): d[k] = v d['TARGETS'] = ['__t1__', '__t2__', '__t3__', '__t4__', '__t5__', '__t6__'] d['TARGET'] = d['TARGETS'][0] d['SOURCES'] = ['__s1__', '__s2__', '__s3__', '__s4__', '__s5__', '__s6__'] @@ -270,7 +270,7 @@ def test_positional_args(pos_callback, cmd, **kw): try: #FUTURE a = SCons.Action.Action(cmd, [], **kw) a = SCons.Action.Action(cmd, [], **kw) - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: s = str(e) m = 'Invalid command display variable' assert s.find(m) != -1, 'Unexpected string: %s' % s @@ -305,7 +305,7 @@ class ActionTestCase(unittest.TestCase): # a singleton list returns the contained action test_positional_args(cmd_action, ["string"]) - try: unicode + try: str except NameError: pass else: a2 = eval("SCons.Action.Action(u'string')") @@ -493,7 +493,7 @@ class _ActionActionTestCase(unittest.TestCase): def func(): pass try: a = SCons.Action.Action('foo', cmdstr='string', strfunction=func) - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: s = str(e) m = 'Cannot have both strfunction and cmdstr args to Action()' assert s.find(m) != -1, 'Unexpected string: %s' % s diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py index 6dc9e17..6abcbcf 100644 --- a/src/engine/SCons/Builder.py +++ b/src/engine/SCons/Builder.py @@ -167,7 +167,7 @@ class DictCmdGenerator(SCons.Util.Selector): try: ret = SCons.Util.Selector.__call__(self, env, source, ext) - except KeyError, e: + except KeyError as e: raise UserError("Ambiguous suffixes after environment substitution: %s == %s == %s" % (e.args[0], e.args[1], e.args[2])) if ret is None: raise UserError("While building `%s' from `%s': Don't know how to build from a source file with suffix `%s'. Expected a suffix in this list: %s." % \ @@ -179,7 +179,7 @@ class CallableSelector(SCons.Util.Selector): finds if it can.""" def __call__(self, env, source): value = SCons.Util.Selector.__call__(self, env, source) - if callable(value): + if isinstance(value, collections.Callable): value = value(env, source) return value @@ -230,7 +230,7 @@ class OverrideWarner(collections.UserDict): def warn(self): if self.already_warned: return - for k in self.keys(): + for k in list(self.keys()): if k in misleading_keywords: alt = misleading_keywords[k] msg = "Did you mean to use `%s' instead of `%s'?" % (alt, k) @@ -336,7 +336,7 @@ class EmitterProxy(object): # in strings. Maybe we should change that? while SCons.Util.is_String(emitter) and emitter in env: emitter = env[emitter] - if callable(emitter): + if isinstance(emitter, collections.Callable): target, source = emitter(target, source, env) elif SCons.Util.is_List(emitter): for e in emitter: @@ -426,7 +426,7 @@ class BuilderBase(object): src_builder = [ src_builder ] self.src_builder = src_builder - def __nonzero__(self): + def __bool__(self): raise InternalError("Do not test for the Node.builder attribute directly; use Node.has_builder() instead") def get_name(self, env): @@ -638,18 +638,18 @@ class BuilderBase(object): def get_prefix(self, env, sources=[]): prefix = self.prefix - if callable(prefix): + if isinstance(prefix, collections.Callable): prefix = prefix(env, sources) return env.subst(prefix) def set_suffix(self, suffix): - if not callable(suffix): + if not isinstance(suffix, collections.Callable): suffix = self.adjust_suffix(suffix) self.suffix = suffix def get_suffix(self, env, sources=[]): suffix = self.suffix - if callable(suffix): + if isinstance(suffix, collections.Callable): suffix = suffix(env, sources) return env.subst(suffix) @@ -658,7 +658,7 @@ class BuilderBase(object): src_suffix = [] elif not SCons.Util.is_List(src_suffix): src_suffix = [ src_suffix ] - self.src_suffix = [callable(suf) and suf or self.adjust_suffix(suf) for suf in src_suffix] + self.src_suffix = [isinstance(suf, collections.Callable) and suf or self.adjust_suffix(suf) for suf in src_suffix] def get_src_suffix(self, env): """Get the first src_suffix in the list of src_suffixes.""" @@ -868,7 +868,7 @@ def is_a_Builder(obj): """ return (isinstance(obj, BuilderBase) or isinstance(obj, CompositeBuilder) - or callable(obj)) + or isinstance(obj, collections.Callable)) # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py index 766b8fe..da03a3c 100644 --- a/src/engine/SCons/BuilderTests.py +++ b/src/engine/SCons/BuilderTests.py @@ -77,7 +77,7 @@ class Environment(object): self.d['SHELL'] = scons_env['SHELL'] self.d['SPAWN'] = scons_env['SPAWN'] self.d['ESCAPE'] = scons_env['ESCAPE'] - for k, v in kw.items(): + for k, v in list(kw.items()): self.d[k] = v global env_arg2nodes_called env_arg2nodes_called = None @@ -138,7 +138,7 @@ class Environment(object): return list(self.d.items()) def sig_dict(self): d = {} - for k,v in self.items(): d[k] = v + for k,v in list(self.items()): d[k] = v d['TARGETS'] = ['__t1__', '__t2__', '__t3__', '__t4__', '__t5__', '__t6__'] d['TARGET'] = d['TARGETS'][0] d['SOURCES'] = ['__s1__', '__s2__', '__s3__', '__s4__', '__s5__', '__s6__'] @@ -305,11 +305,11 @@ class BuilderTestCase(unittest.TestCase): #be = target.get_build_env() #assert be['VAR'] == 'foo', be['VAR'] - try: unicode + try: str except NameError: uni = str else: - uni = unicode + uni = str target = builder(env, target = uni('n12 n13'), source = [uni('n14 n15')])[0] @@ -325,7 +325,7 @@ class BuilderTestCase(unittest.TestCase): flag = 0 try: target = builder(env, None, source=n20) - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: flag = 1 assert flag, "UserError should be thrown if a source node can't create a target." @@ -341,7 +341,7 @@ class BuilderTestCase(unittest.TestCase): suffix = '.s') try: builder(env, target = 'n22', source = 'n22') - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: pass else: raise Exception("Did not catch expected UserError.") @@ -1497,7 +1497,7 @@ class CompositeBuilderTestCase(unittest.TestCase): flag = 0 try: builder(env, target='test3', source=['test2.bar', 'test1.foo'])[0] - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: flag = 1 assert flag, "UserError should be thrown when we call a builder with files of different suffixes." expect = "While building `['test3']' from `test1.foo': Cannot build multiple sources with different extensions: .bar, .foo" @@ -1528,8 +1528,8 @@ class CompositeBuilderTestCase(unittest.TestCase): try: tgt.build() flag = 1 - except SCons.Errors.UserError, e: - print e + except SCons.Errors.UserError as e: + print(e) flag = 0 assert flag, "It should be possible to define actions in composite builders using variables." env['FOO_SUFFIX'] = '.BAR2' @@ -1581,7 +1581,7 @@ class CompositeBuilderTestCase(unittest.TestCase): flag = 0 try: builder(env, target='t5', source=['test5a.foo', 'test5b.inb'])[0] - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: flag = 1 assert flag, "UserError should be thrown when we call a builder with files of different suffixes." expect = "While building `['t5']' from `test5b.bar': Cannot build multiple sources with different extensions: .foo, .bar" @@ -1590,7 +1590,7 @@ class CompositeBuilderTestCase(unittest.TestCase): flag = 0 try: builder(env, target='t6', source=['test6a.bar', 'test6b.ina'])[0] - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: flag = 1 assert flag, "UserError should be thrown when we call a builder with files of different suffixes." expect = "While building `['t6']' from `test6b.foo': Cannot build multiple sources with different extensions: .bar, .foo" @@ -1599,7 +1599,7 @@ class CompositeBuilderTestCase(unittest.TestCase): flag = 0 try: builder(env, target='t4', source=['test4a.ina', 'test4b.inb'])[0] - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: flag = 1 assert flag, "UserError should be thrown when we call a builder with files of different suffixes." expect = "While building `['t4']' from `test4b.bar': Cannot build multiple sources with different extensions: .foo, .bar" @@ -1608,7 +1608,7 @@ class CompositeBuilderTestCase(unittest.TestCase): flag = 0 try: builder(env, target='t7', source=[env.fs.File('test7')])[0] - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: flag = 1 assert flag, "UserError should be thrown when we call a builder with files of different suffixes." expect = "While building `['t7']': Cannot deduce file extension from source files: ['test7']" @@ -1617,7 +1617,7 @@ class CompositeBuilderTestCase(unittest.TestCase): flag = 0 try: builder(env, target='t8', source=['test8.unknown'])[0] - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: flag = 1 assert flag, "UserError should be thrown when we call a builder target with an unknown suffix." expect = "While building `['t8']' from `['test8.unknown']': Don't know how to build from a source file with suffix `.unknown'. Expected a suffix in this list: ['.foo', '.bar']." diff --git a/src/engine/SCons/CacheDirTests.py b/src/engine/SCons/CacheDirTests.py index 21b435a..269040d 100644 --- a/src/engine/SCons/CacheDirTests.py +++ b/src/engine/SCons/CacheDirTests.py @@ -241,7 +241,7 @@ class FileTestCase(BaseTestCase): warn_caught = 0 try: f7.push_to_cache() - except SCons.Errors.BuildError, e: + except SCons.Errors.BuildError as e: assert e.exc_info[0] == SCons.Warnings.CacheWriteErrorWarning warn_caught = 1 assert warn_caught diff --git a/src/engine/SCons/Debug.py b/src/engine/SCons/Debug.py index 1c0c638..363c8b7 100644 --- a/src/engine/SCons/Debug.py +++ b/src/engine/SCons/Debug.py @@ -73,7 +73,7 @@ def dumpLoggedInstances(classes, file=sys.stdout): obj = ref() if obj is not None: file.write(' %s:\n' % obj) - for key, value in obj.__dict__.items(): + for key, value in list(obj.__dict__.items()): file.write(' %20s : %s\n' % (key, value)) @@ -143,7 +143,7 @@ def caller_trace(back=0): # print a single caller and its callers, if any def _dump_one_caller(key, file, level=0): leader = ' '*level - for v,c in sorted([(-v,c) for c,v in caller_dicts[key].items()]): + for v,c in sorted([(-v,c) for c,v in list(caller_dicts[key].items())]): file.write("%s %6d %s:%d(%s)\n" % ((leader,-v) + func_shorten(c[-3:]))) if c in caller_dicts: _dump_one_caller(c, file, level+1) diff --git a/src/engine/SCons/Defaults.py b/src/engine/SCons/Defaults.py index a99bcc7..fe1f87b 100644 --- a/src/engine/SCons/Defaults.py +++ b/src/engine/SCons/Defaults.py @@ -31,7 +31,7 @@ from distutils.msvccompiler. # 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 + __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -50,6 +50,7 @@ import SCons.Environment import SCons.PathList import SCons.Subst import SCons.Tool +import collections # A placeholder for a default Environment (for fetching source files # from source code management systems and the like). This must be @@ -221,7 +222,7 @@ def mkdir_func(dest): for entry in dest: try: os.makedirs(str(entry)) - except os.error, e: + except os.error as e: p = str(entry) if (e.args[0] == errno.EEXIST or (sys.platform=='win32' and e.args[0]==183)) \ @@ -325,9 +326,9 @@ def _stripixes(prefix, itms, suffix, stripprefixes, stripsuffixes, env, c=None): if not itms: return itms - if not callable(c): + if not isinstance(c, collections.Callable): env_c = env['_concat'] - if env_c != _concat and callable(env_c): + if env_c != _concat and isinstance(env_c, collections.Callable): # There's a custom _concat() method in the construction # environment, and we've allowed people to set that in # the past (see test/custom-concat.py), so preserve the @@ -381,7 +382,7 @@ def processDefines(defs): else: l.append(str(d[0])) elif SCons.Util.is_Dict(d): - for macro,value in d.iteritems(): + for macro,value in d.items(): if value is not None: l.append(str(macro) + '=' + str(value)) else: diff --git a/src/engine/SCons/DefaultsTests.py b/src/engine/SCons/DefaultsTests.py index fd10c12..a36ca7c 100644 --- a/src/engine/SCons/DefaultsTests.py +++ b/src/engine/SCons/DefaultsTests.py @@ -69,7 +69,7 @@ class DefaultsTestCase(unittest.TestCase): test.write(file, "test\n") try: mkdir_func(file) - except os.error, e: + except os.error as e: pass else: fail("expected os.error") diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 55a8206..88b0553 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -58,6 +58,7 @@ import SCons.Subst import SCons.Tool import SCons.Util import SCons.Warnings +import collections class _Null(object): pass @@ -127,7 +128,7 @@ future_reserved_construction_var_names = [ def copy_non_reserved_keywords(dict): result = semi_deepcopy(dict) - for k in result.keys(): + for k in list(result.keys()): if k in reserved_construction_var_names: msg = "Ignoring attempt to set reserved variable `$%s'" SCons.Warnings.warn(SCons.Warnings.ReservedVariableWarning, msg % k) @@ -146,12 +147,12 @@ def _set_future_reserved(env, key, value): def _set_BUILDERS(env, key, value): try: bd = env._dict[key] - for k in bd.keys(): + for k in list(bd.keys()): del bd[k] except KeyError: bd = BuilderDict(kwbd, env) env._dict[key] = bd - for k, v in value.items(): + for k, v in list(value.items()): if not SCons.Builder.is_a_Builder(v): raise SCons.Errors.UserError('%s is not a Builder.' % repr(v)) bd.update(value) @@ -323,7 +324,7 @@ class BuilderDict(UserDict): delattr(self.env, item) def update(self, dict): - for i, v in dict.items(): + for i, v in list(dict.items()): self.__setitem__(i, v) @@ -517,7 +518,7 @@ class SubstitutionEnvironment(object): def subst_kw(self, kw, raw=0, target=None, source=None): nkw = {} - for k, v in kw.items(): + for k, v in list(kw.items()): k = self.subst(k, raw, target, source) if SCons.Util.is_String(v): v = self.subst(v, raw, target, source) @@ -591,7 +592,7 @@ class SubstitutionEnvironment(object): out,err = p.communicate() status = p.wait() if err: - sys.stderr.write(unicode(err)) + sys.stderr.write(str(err)) if status: raise OSError("'%s' exited %d" % (command, status)) return out @@ -629,7 +630,7 @@ class SubstitutionEnvironment(object): if not o: return self overrides = {} merges = None - for key, value in o.items(): + for key, value in list(o.items()): if key == 'parse_flags': merges = value else: @@ -814,7 +815,7 @@ class SubstitutionEnvironment(object): if not unique: self.Append(**args) return self - for key, value in args.items(): + for key, value in list(args.items()): if not value: continue try: @@ -1004,7 +1005,7 @@ class Base(SubstitutionEnvironment): # Now restore the passed-in and customized variables # to the environment, since the values the user set explicitly # should override any values set by the tools. - for key, val in save.items(): + for key, val in list(save.items()): self._dict[key] = val # Finally, apply any flags to be merged in @@ -1152,7 +1153,7 @@ class Base(SubstitutionEnvironment): in an Environment. """ kw = copy_non_reserved_keywords(kw) - for key, val in kw.items(): + for key, val in list(kw.items()): # It would be easier on the eyes to write this using # "continue" statements whenever we finish processing an item, # but Python 1.5.2 apparently doesn't let you use "continue" @@ -1205,7 +1206,7 @@ class Base(SubstitutionEnvironment): # based on what we think the value looks like. if SCons.Util.is_List(val): if key == 'CPPDEFINES': - orig = orig.items() + orig = list(orig.items()) orig += val self._dict[key] = orig else: @@ -1216,7 +1217,7 @@ class Base(SubstitutionEnvironment): update_dict(val) except (AttributeError, TypeError, ValueError): if SCons.Util.is_Dict(val): - for k, v in val.items(): + for k, v in list(val.items()): orig[k] = v else: orig[val] = None @@ -1262,7 +1263,7 @@ class Base(SubstitutionEnvironment): values move to end. """ kw = copy_non_reserved_keywords(kw) - for key, val in kw.items(): + for key, val in list(kw.items()): if SCons.Util.is_List(val): val = _delete_duplicates(val, delete_existing) if key not in self._dict or self._dict[key] in ('', None): @@ -1286,7 +1287,7 @@ class Base(SubstitutionEnvironment): tmp.append((i,)) val = tmp if SCons.Util.is_Dict(dk): - dk = dk.items() + dk = list(dk.items()) elif SCons.Util.is_String(dk): dk = [(dk,)] else: @@ -1327,11 +1328,11 @@ class Base(SubstitutionEnvironment): tmp.append((i,)) dk = tmp if SCons.Util.is_Dict(val): - val = val.items() + val = list(val.items()) elif SCons.Util.is_String(val): val = [(val,)] if delete_existing: - dk = filter(lambda x, val=val: x not in val, dk) + dk = list(filter(lambda x, val=val: x not in val, dk)) self._dict[key] = dk + val else: dk = [x for x in dk if x not in val] @@ -1340,7 +1341,7 @@ class Base(SubstitutionEnvironment): # By elimination, val is not a list. Since dk is a # list, wrap val in a list first. if delete_existing: - dk = filter(lambda x, val=val: x not in val, dk) + dk = list(filter(lambda x, val=val: x not in val, dk)) self._dict[key] = dk + [val] else: if not val in dk: @@ -1350,7 +1351,7 @@ class Base(SubstitutionEnvironment): if SCons.Util.is_String(dk): dk = [dk] elif SCons.Util.is_Dict(dk): - dk = dk.items() + dk = list(dk.items()) if SCons.Util.is_String(val): if val in dk: val = [] @@ -1358,7 +1359,7 @@ class Base(SubstitutionEnvironment): val = [val] elif SCons.Util.is_Dict(val): tmp = [] - for i,j in val.iteritems(): + for i,j in val.items(): if j is not None: tmp.append((i,j)) else: @@ -1402,7 +1403,7 @@ class Base(SubstitutionEnvironment): # so the tools can use the new variables kw = copy_non_reserved_keywords(kw) new = {} - for key, value in kw.items(): + for key, value in list(kw.items()): new[key] = SCons.Subst.scons_subst_once(value, self, key) clone.Replace(**new) @@ -1469,7 +1470,7 @@ class Base(SubstitutionEnvironment): copy_function = self._copy_from_cache elif function == 'timestamp-match': function = self._changed_timestamp_match - elif not callable(function): + elif not isinstance(function, collections.Callable): raise UserError("Unknown Decider value %s" % repr(function)) # We don't use AddMethod because we don't want to turn the @@ -1602,7 +1603,7 @@ class Base(SubstitutionEnvironment): in an Environment. """ kw = copy_non_reserved_keywords(kw) - for key, val in kw.items(): + for key, val in list(kw.items()): # It would be easier on the eyes to write this using # "continue" statements whenever we finish processing an item, # but Python 1.5.2 apparently doesn't let you use "continue" @@ -1656,7 +1657,7 @@ class Base(SubstitutionEnvironment): update_dict(val) except (AttributeError, TypeError, ValueError): if SCons.Util.is_Dict(val): - for k, v in val.items(): + for k, v in list(val.items()): orig[k] = v else: orig[val] = None @@ -1693,7 +1694,7 @@ class Base(SubstitutionEnvironment): values move to front. """ kw = copy_non_reserved_keywords(kw) - for key, val in kw.items(): + for key, val in list(kw.items()): if SCons.Util.is_List(val): val = _delete_duplicates(val, not delete_existing) if key not in self._dict or self._dict[key] in ('', None): @@ -1768,7 +1769,7 @@ class Base(SubstitutionEnvironment): return os.path.join(dir, new_prefix+name+new_suffix) def SetDefault(self, **kw): - for k in kw.keys(): + for k in list(kw.keys()): if k in self._dict: del kw[k] self.Replace(**kw) @@ -1830,7 +1831,7 @@ class Base(SubstitutionEnvironment): uniq = {} for executor in [n.get_executor() for n in nodes]: uniq[executor] = 1 - for executor in uniq.keys(): + for executor in list(uniq.keys()): executor.add_pre_action(action) return nodes @@ -1840,7 +1841,7 @@ class Base(SubstitutionEnvironment): uniq = {} for executor in [n.get_executor() for n in nodes]: uniq[executor] = 1 - for executor in uniq.keys(): + for executor in list(uniq.keys()): executor.add_post_action(action) return nodes @@ -2235,7 +2236,7 @@ class Base(SubstitutionEnvironment): while (node != node.srcnode()): node = node.srcnode() return node - sources = map( final_source, sources ); + sources = list(map( final_source, sources )); # remove duplicates return list(set(sources)) @@ -2378,7 +2379,7 @@ def NoSubstitutionProxy(subject): def __setattr__(self, name, value): return setattr(self.__dict__['__subject'], name, value) def executor_to_lvars(self, kwdict): - if kwdict.has_key('executor'): + if 'executor' in kwdict: kwdict['lvars'] = kwdict['executor'].get_lvars() del kwdict['executor'] else: diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index 45cf876..3af879a 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -160,7 +160,7 @@ class TestEnvironmentFixture(object): default_keys = { 'CC' : 'cc', 'CCFLAGS' : '-DNDEBUG', 'ENV' : { 'TMP' : '/tmp' } } - for key, value in default_keys.items(): + for key, value in list(default_keys.items()): if key not in kw: kw[key] = value if 'BUILDERS' not in kw: @@ -263,7 +263,7 @@ class SubstitutionTestCase(unittest.TestCase): assert isinstance(nodes[0], X) assert nodes[0].name == "Util.py UtilTests.py" - try: unicode + try: str except NameError: pass else: code = """if 1: @@ -272,7 +272,7 @@ class SubstitutionTestCase(unittest.TestCase): assert isinstance(nodes[0], X) assert nodes[0].name == u"Util.py UtilTests.py" \n""" - exec code in globals(), locals() + exec(code, globals(), locals()) nodes = env.arg2nodes(["Util.py", "UtilTests.py"], Factory) assert len(nodes) == 2, nodes @@ -655,7 +655,7 @@ sys.exit(0) cmd = '%s %s' % (python, test.workpath('fail.py')) try: env.backtick(cmd) - except OSError, e: + except OSError as e: assert str(e) == "'%s' exited 1" % cmd, str(e) else: self.fail("did not catch expected OSError") @@ -1586,17 +1586,17 @@ def exists(env): env['XXX'] = copy.copy(input) try: env.Append(XXX = append) - except Exception, e: - if failed == 0: print - print " %s Append %s exception: %s" % \ - (repr(input), repr(append), e) + except Exception as e: + if failed == 0: print() + print(" %s Append %s exception: %s" % \ + (repr(input), repr(append), e)) failed = failed + 1 else: result = env['XXX'] if result != expect: - if failed == 0: print - print " %s Append %s => %s did not match %s" % \ - (repr(input), repr(append), repr(result), repr(expect)) + if failed == 0: print() + print(" %s Append %s => %s did not match %s" % \ + (repr(input), repr(append), repr(result), repr(expect))) failed = failed + 1 del cases[:3] assert failed == 0, "%d Append() cases failed" % failed @@ -1935,7 +1935,7 @@ def generate(env): assert x is None, x sub2_xxx_exe = test.workpath('sub2', 'xxx.exe') - os.chmod(sub2_xxx_exe, 0755) + os.chmod(sub2_xxx_exe, 0o755) env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] }) @@ -1943,7 +1943,7 @@ def generate(env): assert x == 'xxx.exe', x sub1_xxx_exe = test.workpath('sub1', 'xxx.exe') - os.chmod(sub1_xxx_exe, 0755) + os.chmod(sub1_xxx_exe, 0o755) x = env.Detect('xxx.exe') assert x == 'xxx.exe', x @@ -2258,17 +2258,17 @@ f5: \ env['XXX'] = copy.copy(input) try: env.Prepend(XXX = prepend) - except Exception, e: - if failed == 0: print - print " %s Prepend %s exception: %s" % \ - (repr(input), repr(prepend), e) + except Exception as e: + if failed == 0: print() + print(" %s Prepend %s exception: %s" % \ + (repr(input), repr(prepend), e)) failed = failed + 1 else: result = env['XXX'] if result != expect: - if failed == 0: print - print " %s Prepend %s => %s did not match %s" % \ - (repr(input), repr(prepend), repr(result), repr(expect)) + if failed == 0: print() + print(" %s Prepend %s => %s did not match %s" % \ + (repr(input), repr(prepend), repr(result), repr(expect))) failed = failed + 1 del cases[:3] assert failed == 0, "%d Prepend() cases failed" % failed @@ -2506,10 +2506,10 @@ def generate(env): os.mkdir(sub2_xxx_exe) test.write(sub3_xxx_exe, "\n") - os.chmod(sub3_xxx_exe, 0777) + os.chmod(sub3_xxx_exe, 0o777) test.write(sub4_xxx_exe, "\n") - os.chmod(sub4_xxx_exe, 0777) + os.chmod(sub4_xxx_exe, 0o777) env_path = os.environ['PATH'] diff --git a/src/engine/SCons/ErrorsTests.py b/src/engine/SCons/ErrorsTests.py index 9c8b925..97c9d55 100644 --- a/src/engine/SCons/ErrorsTests.py +++ b/src/engine/SCons/ErrorsTests.py @@ -35,7 +35,7 @@ class ErrorsTestCase(unittest.TestCase): raise SCons.Errors.BuildError( errstr = "foo", status=57, filename="file", exc_info=(1,2,3), node = "n", executor="e", action="a", command="c") - except SCons.Errors.BuildError, e: + except SCons.Errors.BuildError as e: assert e.errstr == "foo" assert e.status == 57 assert e.exitstatus == 2, e.exitstatus @@ -50,7 +50,7 @@ class ErrorsTestCase(unittest.TestCase): try: raise SCons.Errors.BuildError("n", "foo", 57, 3, "file", "e", "a", "c", (1,2,3)) - except SCons.Errors.BuildError, e: + except SCons.Errors.BuildError as e: assert e.errstr == "foo", e.errstr assert e.status == 57, e.status assert e.exitstatus == 3, e.exitstatus @@ -64,7 +64,7 @@ class ErrorsTestCase(unittest.TestCase): try: raise SCons.Errors.BuildError() - except SCons.Errors.BuildError, e: + except SCons.Errors.BuildError as e: assert e.errstr == "Unknown error" assert e.status == 2 assert e.exitstatus == 2 @@ -80,21 +80,21 @@ class ErrorsTestCase(unittest.TestCase): """Test the InternalError exception.""" try: raise SCons.Errors.InternalError("test internal error") - except SCons.Errors.InternalError, e: + except SCons.Errors.InternalError as e: assert e.args == ("test internal error",) def test_UserError(self): """Test the UserError exception.""" try: raise SCons.Errors.UserError("test user error") - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: assert e.args == ("test user error",) def test_ExplicitExit(self): """Test the ExplicitExit exception.""" try: raise SCons.Errors.ExplicitExit("node") - except SCons.Errors.ExplicitExit, e: + except SCons.Errors.ExplicitExit as e: assert e.node == "node" if __name__ == "__main__": diff --git a/src/engine/SCons/ExecutorTests.py b/src/engine/SCons/ExecutorTests.py index 6268984..3bc5bee 100644 --- a/src/engine/SCons/ExecutorTests.py +++ b/src/engine/SCons/ExecutorTests.py @@ -307,7 +307,7 @@ class ExecutorTestCase(unittest.TestCase): try: r = x.prepare() - except SCons.Errors.StopError, e: + except SCons.Errors.StopError as e: assert str(e) == "Source `s2' not found, needed by target `t1'.", e else: raise AssertionError("did not catch expected StopError: %s" % r) diff --git a/src/engine/SCons/Job.py b/src/engine/SCons/Job.py index 184f5ba..226a34e 100644 --- a/src/engine/SCons/Job.py +++ b/src/engine/SCons/Job.py @@ -278,14 +278,14 @@ else: try: prev_size = threading.stack_size(stack_size*1024) - except AttributeError, e: + except AttributeError as e: # Only print a warning if the stack size has been # explicitly set. if not explicit_stack_size is None: msg = "Setting stack size is unsupported by this version of Python:\n " + \ e.args[0] SCons.Warnings.warn(SCons.Warnings.StackSizeWarning, msg) - except ValueError, e: + except ValueError as e: msg = "Setting stack size failed:\n " + str(e) SCons.Warnings.warn(SCons.Warnings.StackSizeWarning, msg) diff --git a/src/engine/SCons/Memoize.py b/src/engine/SCons/Memoize.py index e77aacf..9fe6851 100644 --- a/src/engine/SCons/Memoize.py +++ b/src/engine/SCons/Memoize.py @@ -143,7 +143,7 @@ class Counter(object): CounterList.append(self) def display(self): fmt = " %7d hits %7d misses %s()" - print fmt % (self.hit, self.miss, self.name) + print(fmt % (self.hit, self.miss, self.name)) def __cmp__(self, other): try: return cmp(self.name, other.name) @@ -215,7 +215,7 @@ class Memoizer(object): def Dump(title=None): if title: - print title + print(title) CounterList.sort() for counter in CounterList: counter.display() diff --git a/src/engine/SCons/MemoizeTests.py b/src/engine/SCons/MemoizeTests.py index 9876c27..b6750e0 100644 --- a/src/engine/SCons/MemoizeTests.py +++ b/src/engine/SCons/MemoizeTests.py @@ -30,9 +30,7 @@ import SCons.Memoize -class FakeObject(object): - - __metaclass__ = SCons.Memoize.Memoized_Metaclass +class FakeObject(object, metaclass=SCons.Memoize.Memoized_Metaclass): memoizer_counters = [] diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index f31ca83..22dca1f 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -54,6 +54,7 @@ import SCons.Util import SCons.Warnings from SCons.Debug import Trace +import collections do_store_info = True print_duplicate = 0 @@ -550,7 +551,7 @@ class EntryProxy(SCons.Util.Proxy): except KeyError: try: attr = SCons.Util.Proxy.__getattr__(self, name) - except AttributeError, e: + except AttributeError as e: # Raise our own AttributeError subclass with an # overridden __str__() method that identifies the # name of the entry that caused the exception. @@ -1508,7 +1509,7 @@ class Dir(Base): This clears any cached information that is invalidated by changing the repository.""" - for node in self.entries.values(): + for node in list(self.entries.values()): if node != self.dir: if node != self and isinstance(node, Dir): node.__clearRepositoryCache(duplicate) @@ -2055,7 +2056,7 @@ class Dir(Base): # We use the .name attribute from the Node because the keys of # the dir.entries dictionary are normalized (that is, all upper # case) on case-insensitive systems like Windows. - node_names = [ v.name for k, v in dir.entries.items() + node_names = [ v.name for k, v in list(dir.entries.items()) if k not in ('.', '..') ] names.extend(node_names) if not strings: @@ -2420,7 +2421,7 @@ class File(Base): fname = self.rfile().abspath try: contents = open(fname, "rb").read() - except EnvironmentError, e: + except EnvironmentError as e: if not e.filename: e.filename = fname raise @@ -2455,7 +2456,7 @@ class File(Base): try: cs = SCons.Util.MD5filesignature(fname, chunksize=SCons.Node.FS.File.md5_chunksize*1024) - except EnvironmentError, e: + except EnvironmentError as e: if not e.filename: e.filename = fname raise @@ -2793,7 +2794,7 @@ class File(Base): def _rmv_existing(self): self.clear_memoized_values() if print_duplicate: - print "dup: removing existing target %s"%self + print("dup: removing existing target %s"%self) e = Unlink(self, [], None) if isinstance(e, SCons.Errors.BuildError): raise e @@ -2817,7 +2818,7 @@ class File(Base): else: try: self._createDir() - except SCons.Errors.StopError, drive: + except SCons.Errors.StopError as drive: desc = "No drive `%s' for target `%s'." % (drive, self) raise SCons.Errors.StopError(desc) @@ -2835,7 +2836,7 @@ class File(Base): def do_duplicate(self, src): self._createDir() if print_duplicate: - print "dup: relinking variant '%s' from '%s'"%(self, src) + print("dup: relinking variant '%s' from '%s'"%(self, src)) Unlink(self, None, None) e = Link(self, src, None) if isinstance(e, SCons.Errors.BuildError): @@ -2870,7 +2871,7 @@ class File(Base): # The source file does not exist. Make sure no old # copy remains in the variant directory. if print_duplicate: - print "dup: no src for %s, unlinking old variant copy"%self + print("dup: no src for %s, unlinking old variant copy"%self) if Base.exists(self) or self.islink(): self.fs.unlink(self.path) # Return None explicitly because the Base.exists() call @@ -3196,10 +3197,10 @@ class FileFinder(object): except KeyError: pass - if verbose and not callable(verbose): + if verbose and not isinstance(verbose, collections.Callable): if not SCons.Util.is_String(verbose): verbose = "find_file" - _verbose = u' %s: ' % verbose + _verbose = ' %s: ' % verbose verbose = lambda s: sys.stdout.write(_verbose + s) filedir, filename = os.path.split(filename) diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index a60b8a4..e8442e9 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -20,7 +20,7 @@ # 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 + __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -567,13 +567,13 @@ class VariantDirTestCase(unittest.TestCase): dp = dnode.srcnode().path expect = os.path.normpath(srcnode_map.get(dir, dir)) if dp != expect: - print "Dir `%s' srcnode() `%s' != expected `%s'" % (dir, dp, expect) + print("Dir `%s' srcnode() `%s' != expected `%s'" % (dir, dp, expect)) errors = errors + 1 fp = fnode.srcnode().path expect = os.path.normpath(srcnode_map.get(f, f)) if fp != expect: - print "File `%s' srcnode() `%s' != expected `%s'" % (f, fp, expect) + print("File `%s' srcnode() `%s' != expected `%s'" % (f, fp, expect)) errors = errors + 1 for dir in dir_list: @@ -585,14 +585,14 @@ class VariantDirTestCase(unittest.TestCase): tp = t[0].path expect = os.path.normpath(alter_map.get(dir, dir)) if tp != expect: - print "Dir `%s' alter_targets() `%s' != expected `%s'" % (dir, tp, expect) + print("Dir `%s' alter_targets() `%s' != expected `%s'" % (dir, tp, expect)) errors = errors + 1 t, m = fnode.alter_targets() tp = t[0].path expect = os.path.normpath(alter_map.get(f, f)) if tp != expect: - print "File `%s' alter_targets() `%s' != expected `%s'" % (f, tp, expect) + print("File `%s' alter_targets() `%s' != expected `%s'" % (f, tp, expect)) errors = errors + 1 self.failIf(errors) @@ -1088,7 +1088,7 @@ class FSTestCase(_tempdirTestCase): try: f2 = fs.File(sep.join(['f1', 'f2']), directory = d1) - except TypeError, x: + except TypeError as x: assert str(x) == ("Tried to lookup File '%s' as a Dir." % d1_f1), x except: @@ -1096,7 +1096,7 @@ class FSTestCase(_tempdirTestCase): try: dir = fs.Dir(sep.join(['d1', 'f1'])) - except TypeError, x: + except TypeError as x: assert str(x) == ("Tried to lookup File '%s' as a Dir." % d1_f1), x except: @@ -1104,7 +1104,7 @@ class FSTestCase(_tempdirTestCase): try: f2 = fs.File('d1') - except TypeError, x: + except TypeError as x: assert str(x) == ("Tried to lookup Dir '%s' as a File." % 'd1'), x except: @@ -1305,7 +1305,7 @@ class FSTestCase(_tempdirTestCase): assert f1.get_contents() == "Foo\x1aBar", f1.get_contents() # This tests to make sure we can decode UTF-8 text files. - test_string = u"Foo\x1aBar" + test_string = "Foo\x1aBar" test.write("utf8_file", test_string.encode('utf-8')) f1 = fs.File(test.workpath("utf8_file")) assert eval('f1.get_text_contents() == u"Foo\x1aBar"'), \ @@ -1645,7 +1645,7 @@ class FSTestCase(_tempdirTestCase): def unc_workpath(dirs, test=test): import ntpath - x = apply(test.workpath, dirs) + x = test.workpath(*dirs) drive, path = ntpath.splitdrive(x) unc, path = ntpath.splitunc(path) path = strip_slash(path) @@ -1911,9 +1911,9 @@ class FSTestCase(_tempdirTestCase): del cases[:3] result = dir.rel_path(other) if result != expect: - if failed == 0: print + if failed == 0: print() fmt = " dir_path(%(dir)s, %(other)s) => '%(result)s' did not match '%(expect)s'" - print fmt % locals() + print(fmt % locals()) failed = failed + 1 assert failed == 0, "%d rel_path() cases failed" % failed @@ -2520,9 +2520,9 @@ class GlobTestCase(_tempdirTestCase): fmt = lambda n: n if r != result: import pprint - print "Glob(%s) expected:" % repr(input) + print("Glob(%s) expected:" % repr(input)) pprint.pprint(list(map(fmt, result))) - print "Glob(%s) got:" % repr(input) + print("Glob(%s) got:" % repr(input)) pprint.pprint(list(map(fmt, r))) self.fail() @@ -3621,7 +3621,7 @@ class SpecialAttrTestCase(unittest.TestCase): caught = None try: fs.Dir('ddd').get_subst_proxy().no_such_attr - except AttributeError, e: + except AttributeError as e: assert str(e) == "Dir instance 'ddd' has no attribute 'no_such_attr'", e caught = 1 assert caught, "did not catch expected AttributeError" @@ -3629,7 +3629,7 @@ class SpecialAttrTestCase(unittest.TestCase): caught = None try: fs.Entry('eee').get_subst_proxy().no_such_attr - except AttributeError, e: + except AttributeError as e: # Gets disambiguated to File instance by get_subst_proxy(). assert str(e) == "File instance 'eee' has no attribute 'no_such_attr'", e caught = 1 @@ -3638,7 +3638,7 @@ class SpecialAttrTestCase(unittest.TestCase): caught = None try: fs.File('fff').get_subst_proxy().no_such_attr - except AttributeError, e: + except AttributeError as e: assert str(e) == "File instance 'fff' has no attribute 'no_such_attr'", e caught = 1 assert caught, "did not catch expected AttributeError" diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 992284d..8f48d86 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -371,7 +371,7 @@ class Node(object): """ try: self.get_executor()(self, **kw) - except SCons.Errors.BuildError, e: + except SCons.Errors.BuildError as e: e.node = self raise @@ -827,7 +827,7 @@ class Node(object): """Adds dependencies.""" try: self._add_child(self.depends, self.depends_set, depend) - except TypeError, e: + except TypeError as e: e = e.args[0] if SCons.Util.is_List(e): s = list(map(str, e)) @@ -844,7 +844,7 @@ class Node(object): """Adds dependencies to ignore.""" try: self._add_child(self.ignore, self.ignore_set, depend) - except TypeError, e: + except TypeError as e: e = e.args[0] if SCons.Util.is_List(e): s = list(map(str, e)) @@ -858,7 +858,7 @@ class Node(object): return try: self._add_child(self.sources, self.sources_set, source) - except TypeError, e: + except TypeError as e: e = e.args[0] if SCons.Util.is_List(e): s = list(map(str, e)) @@ -1197,8 +1197,8 @@ class Node(object): new_bkids = new.bsources + new.bdepends + new.bimplicit new_bkidsigs = new.bsourcesigs + new.bdependsigs + new.bimplicitsigs - osig = dict(zip(old_bkids, old_bkidsigs)) - nsig = dict(zip(new_bkids, new_bkidsigs)) + osig = dict(list(zip(old_bkids, old_bkidsigs))) + nsig = dict(list(zip(new_bkids, new_bkidsigs))) # The sources and dependencies we'll want to report are all stored # as relative paths to this target's directory, but we want to diff --git a/src/engine/SCons/Options/__init__.py b/src/engine/SCons/Options/__init__.py index f6c8483..2544aec 100644 --- a/src/engine/SCons/Options/__init__.py +++ b/src/engine/SCons/Options/__init__.py @@ -33,11 +33,11 @@ and will then be removed entirely (some day). import SCons.Variables import SCons.Warnings -from BoolOption import BoolOption # okay -from EnumOption import EnumOption # okay -from ListOption import ListOption # naja -from PackageOption import PackageOption # naja -from PathOption import PathOption # okay +from .BoolOption import BoolOption # okay +from .EnumOption import EnumOption # okay +from .ListOption import ListOption # naja +from .PackageOption import PackageOption # naja +from .PathOption import PathOption # okay warned = False diff --git a/src/engine/SCons/Platform/__init__.py b/src/engine/SCons/Platform/__init__.py index 81a49e7..6ef8b05 100644 --- a/src/engine/SCons/Platform/__init__.py +++ b/src/engine/SCons/Platform/__init__.py @@ -223,8 +223,8 @@ class TempFileMunge(object): # purity get in the way of just being helpful, so we'll # reach into SCons.Action directly. if SCons.Action.print_actions: - print("Using tempfile "+native_tmp+" for command line:\n"+ - str(cmd[0]) + " " + " ".join(args)) + print(("Using tempfile "+native_tmp+" for command line:\n"+ + str(cmd[0]) + " " + " ".join(args))) return [ cmd[0], prefix + native_tmp + '\n' + rm, native_tmp ] def Platform(name = platform_default()): diff --git a/src/engine/SCons/Platform/aix.py b/src/engine/SCons/Platform/aix.py index 0229112..f6853b5 100644 --- a/src/engine/SCons/Platform/aix.py +++ b/src/engine/SCons/Platform/aix.py @@ -34,7 +34,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os -import posix +from . import posix def get_xlc(env, xlc=None, xlc_r=None, packages=[]): # Use the AIX package installer tool lslpp to figure out where a diff --git a/src/engine/SCons/Platform/cygwin.py b/src/engine/SCons/Platform/cygwin.py index a012682..e7c8b8a 100644 --- a/src/engine/SCons/Platform/cygwin.py +++ b/src/engine/SCons/Platform/cygwin.py @@ -32,7 +32,7 @@ selection method. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import posix +from . import posix from SCons.Platform import TempFileMunge def generate(env): diff --git a/src/engine/SCons/Platform/darwin.py b/src/engine/SCons/Platform/darwin.py index 005673b..1cf4aeb 100644 --- a/src/engine/SCons/Platform/darwin.py +++ b/src/engine/SCons/Platform/darwin.py @@ -32,7 +32,7 @@ selection method. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import posix +from . import posix import os def generate(env): diff --git a/src/engine/SCons/Platform/hpux.py b/src/engine/SCons/Platform/hpux.py index 43d284b..0e0bbcf 100644 --- a/src/engine/SCons/Platform/hpux.py +++ b/src/engine/SCons/Platform/hpux.py @@ -32,7 +32,7 @@ selection method. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import posix +from . import posix def generate(env): posix.generate(env) diff --git a/src/engine/SCons/Platform/irix.py b/src/engine/SCons/Platform/irix.py index 2baee0b..2e5f217 100644 --- a/src/engine/SCons/Platform/irix.py +++ b/src/engine/SCons/Platform/irix.py @@ -32,7 +32,7 @@ selection method. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import posix +from . import posix def generate(env): posix.generate(env) diff --git a/src/engine/SCons/Platform/os2.py b/src/engine/SCons/Platform/os2.py index 0fa4553..5ca26bc 100644 --- a/src/engine/SCons/Platform/os2.py +++ b/src/engine/SCons/Platform/os2.py @@ -31,7 +31,7 @@ selection method. # __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import win32 +from . import win32 def generate(env): if 'ENV' not in env: diff --git a/src/engine/SCons/Platform/posix.py b/src/engine/SCons/Platform/posix.py index ece48d7..d1f6c78 100644 --- a/src/engine/SCons/Platform/posix.py +++ b/src/engine/SCons/Platform/posix.py @@ -77,7 +77,7 @@ def exec_fork(l, env): exitval = 127 try: os.execvpe(l[0], l, env) - except OSError, e: + except OSError as e: exitval = exitvalmap.get(e[0], e[0]) sys.stderr.write("scons: %s: %s\n" % (l[0], e[1])) os._exit(exitval) @@ -92,7 +92,7 @@ def _get_env_command(sh, escape, cmd, args, env): s = ' '.join(args) if env: l = ['env', '-'] + \ - [escape(t[0])+'='+escape(t[1]) for t in env.items()] + \ + [escape(t[0])+'='+escape(t[1]) for t in list(env.items())] + \ [sh, '-c', escape(s)] s = ' '.join(l) return s @@ -125,7 +125,8 @@ def process_cmd_output(cmd_stdout, cmd_stderr, stdout, stderr): else: #sys.__stderr__.write( "str(stderr) = %s\n" % str ) stderr.write(str) - except select.error, (_errno, _strerror): + except select.error as xxx_todo_changeme: + (_errno, _strerror) = xxx_todo_changeme.args if _errno != errno.EINTR: raise @@ -164,7 +165,7 @@ def exec_piped_fork(l, env, stdout, stderr): exitval = 127 try: os.execvpe(l[0], l, env) - except OSError, e: + except OSError as e: exitval = exitvalmap.get(e[0], e[0]) stderr.write("scons: %s: %s\n" % (l[0], e[1])) os._exit(exitval) diff --git a/src/engine/SCons/Platform/sunos.py b/src/engine/SCons/Platform/sunos.py index d23d65c..057fddf 100644 --- a/src/engine/SCons/Platform/sunos.py +++ b/src/engine/SCons/Platform/sunos.py @@ -32,7 +32,7 @@ selection method. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import posix +from . import posix def generate(env): posix.generate(env) diff --git a/src/engine/SCons/Platform/win32.py b/src/engine/SCons/Platform/win32.py index 5f20685..879817d 100644 --- a/src/engine/SCons/Platform/win32.py +++ b/src/engine/SCons/Platform/win32.py @@ -155,7 +155,7 @@ def piped_spawn(sh, escape, cmd, args, env, stdout, stderr): try: args = [sh, '/C', escape(' '.join(args)) ] ret = spawnve(os.P_WAIT, sh, args, env) - except OSError, e: + except OSError as e: # catch any error try: ret = exitvalmap[e[0]] @@ -183,7 +183,7 @@ def piped_spawn(sh, escape, cmd, args, env, stdout, stderr): def exec_spawn(l, env): try: result = spawnve(os.P_WAIT, l[0], l, env) - except OSError, e: + except OSError as e: try: result = exitvalmap[e[0]] sys.stderr.write("scons: %s: %s\n" % (l[0], e[1])) diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index f3a3545..987f88d 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -118,7 +118,7 @@ def CreateConfigHBuilder(env): _stringConfigH) sconfigHBld = SCons.Builder.Builder(action=action) env.Append( BUILDERS={'SConfigHBuilder':sconfigHBld} ) - for k in _ac_config_hs.keys(): + for k in list(_ac_config_hs.keys()): env.SConfigHBuilder(k, env.Value(_ac_config_hs[k])) class SConfWarning(SCons.Warnings.Warning): @@ -239,7 +239,7 @@ class SConfBuildTask(SCons.Taskmaster.AlwaysTask): # Earlier versions of Python don't have sys.excepthook... def excepthook(type, value, tb): traceback.print_tb(tb) - print type, value + print(type, value) excepthook(*self.exc_info()) return SCons.Taskmaster.Task.failed(self) @@ -318,7 +318,7 @@ class SConfBuildTask(SCons.Taskmaster.AlwaysTask): env_decider=env.decide_source): env_decider(dependency, target, prev_ni) return True - if env.decide_source.func_code is not force_build.func_code: + if env.decide_source.__code__ is not force_build.__code__: env.Decider(force_build) env['PSTDOUT'] = env['PSTDERR'] = s try: @@ -332,7 +332,7 @@ class SConfBuildTask(SCons.Taskmaster.AlwaysTask): except SystemExit: exc_value = sys.exc_info()[1] raise SCons.Errors.ExplicitExit(self.targets[0],exc_value.code) - except Exception, e: + except Exception as e: for t in self.targets: binfo = t.get_binfo() binfo.__class__ = SConfBuildInfo @@ -652,7 +652,7 @@ class SConfBase(object): """Adds all the tests given in the tests dictionary to this SConf instance """ - for name in tests.keys(): + for name in list(tests.keys()): self.AddTest(name, tests[name]) def _createDir( self, node ): diff --git a/src/engine/SCons/SConfTests.py b/src/engine/SCons/SConfTests.py index e604886..ba524fd 100644 --- a/src/engine/SCons/SConfTests.py +++ b/src/engine/SCons/SConfTests.py @@ -60,7 +60,7 @@ class SConfTestCase(unittest.TestCase): # We try to reset scons' state (including all global variables) import SCons.SConsign SCons.SConsign.write() # simulate normal scons-finish - for n in sys.modules.keys(): + for n in list(sys.modules.keys()): if n.split('.')[0] == 'SCons' and n[:12] != 'SCons.compat': m = sys.modules[n] if isinstance(m, ModuleType): diff --git a/src/engine/SCons/SConsign.py b/src/engine/SCons/SConsign.py index 6555fcb..5ce61be 100644 --- a/src/engine/SCons/SConsign.py +++ b/src/engine/SCons/SConsign.py @@ -84,7 +84,7 @@ def Get_DataBase(dir): DB_sync_list.append(db) return db, "c" except TypeError: - print "DataBase =", DataBase + print("DataBase =", DataBase) raise def Reset(): @@ -172,7 +172,7 @@ class Base(object): pass def merge(self): - for key, node in self.to_be_merged.items(): + for key, node in list(self.to_be_merged.items()): entry = node.get_stored_info() try: ninfo = entry.ninfo @@ -215,10 +215,10 @@ class DB(Base): raise TypeError except KeyboardInterrupt: raise - except Exception, e: + except Exception as e: SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning, "Ignoring corrupt sconsign entry : %s (%s)\n"%(self.dir.tpath, e)) - for key, entry in self.entries.items(): + for key, entry in list(self.entries.items()): entry.convert_from_sconsign(dir, key) if mode == "r": @@ -245,7 +245,7 @@ class DB(Base): # the Repository; we only write to our own .sconsign file, # not to .sconsign files in Repositories. path = normcase(self.dir.path) - for key, entry in self.entries.items(): + for key, entry in list(self.entries.items()): entry.convert_to_sconsign() db[path] = pickle.dumps(self.entries, 1) @@ -274,7 +274,7 @@ class Dir(Base): raise TypeError if dir: - for key, entry in self.entries.items(): + for key, entry in list(self.entries.items()): entry.convert_from_sconsign(dir, key) class DirFile(Dir): @@ -333,14 +333,14 @@ class DirFile(Dir): fname = self.sconsign except IOError: return - for key, entry in self.entries.items(): + for key, entry in list(self.entries.items()): entry.convert_to_sconsign() pickle.dump(self.entries, file, 1) file.close() if fname != self.sconsign: try: mode = os.stat(self.sconsign)[0] - os.chmod(self.sconsign, 0666) + os.chmod(self.sconsign, 0o666) os.unlink(self.sconsign) except (IOError, OSError): # Try to carry on in the face of either OSError diff --git a/src/engine/SCons/Scanner/C.py b/src/engine/SCons/Scanner/C.py index 3311a09..74b01a4 100644 --- a/src/engine/SCons/Scanner/C.py +++ b/src/engine/SCons/Scanner/C.py @@ -59,7 +59,7 @@ class SConsCPPScanner(SCons.cpp.PreProcessor): def read_file(self, file): try: fp = open(str(file.rfile())) - except EnvironmentError, e: + except EnvironmentError as e: self.missing.append((file, self.current_file)) return '' else: diff --git a/src/engine/SCons/Scanner/Fortran.py b/src/engine/SCons/Scanner/Fortran.py index 1b55130..5339ab2 100644 --- a/src/engine/SCons/Scanner/Fortran.py +++ b/src/engine/SCons/Scanner/Fortran.py @@ -35,6 +35,7 @@ import SCons.Node.FS import SCons.Scanner import SCons.Util import SCons.Warnings +import collections class F90Scanner(SCons.Scanner.Classic): """ @@ -109,7 +110,7 @@ class F90Scanner(SCons.Scanner.Classic): # is actually found in a Repository or locally. nodes = [] source_dir = node.get_dir() - if callable(path): + if isinstance(path, collections.Callable): path = path() for dep in mods_and_includes: n, i = self.find_include(dep, source_dir, path) diff --git a/src/engine/SCons/Scanner/LaTeX.py b/src/engine/SCons/Scanner/LaTeX.py index 2cb1ed5..1e0fea1 100644 --- a/src/engine/SCons/Scanner/LaTeX.py +++ b/src/engine/SCons/Scanner/LaTeX.py @@ -200,14 +200,14 @@ class LaTeX(SCons.Scanner.Base): """ def __init__(self, dictionary): self.dictionary = {} - for k,n in dictionary.items(): + for k,n in list(dictionary.items()): self.dictionary[k] = ( SCons.Scanner.FindPathDirs(n), FindENVPathDirs(n) ) def __call__(self, env, dir=None, target=None, source=None, argument=None): di = {} - for k,(c,cENV) in self.dictionary.items(): + for k,(c,cENV) in list(self.dictionary.items()): di[k] = ( c(env, dir=None, target=None, source=None, argument=None) , cENV(env, dir=None, target=None, source=None, diff --git a/src/engine/SCons/Scanner/Prog.py b/src/engine/SCons/Scanner/Prog.py index 49e93a5..6e2da21 100644 --- a/src/engine/SCons/Scanner/Prog.py +++ b/src/engine/SCons/Scanner/Prog.py @@ -27,6 +27,7 @@ import SCons.Node import SCons.Node.FS import SCons.Scanner import SCons.Util +import collections # global, set by --debug=findlibs print_find_libs = None @@ -76,7 +77,7 @@ def scan(node, env, libpath = ()): result = [] - if callable(libpath): + if isinstance(libpath, collections.Callable): libpath = libpath() find_file = SCons.Node.FS.find_file diff --git a/src/engine/SCons/Scanner/ProgTests.py b/src/engine/SCons/Scanner/ProgTests.py index 411e035..f564c91 100644 --- a/src/engine/SCons/Scanner/ProgTests.py +++ b/src/engine/SCons/Scanner/ProgTests.py @@ -230,7 +230,7 @@ def suite(): suite.addTest(ProgramScannerTestCase6()) suite.addTest(ProgramScannerTestCase7()) suite.addTest(ProgramScannerTestCase8()) - try: unicode + try: str except NameError: pass else: code = """if 1: @@ -245,7 +245,7 @@ def suite(): assert deps_match(deps, ['d1/l2.lib', 'd1/d2/l3.lib']), map(str, deps) suite.addTest(ProgramScannerTestCase4()) \n""" - exec code + exec(code) return suite if __name__ == "__main__": diff --git a/src/engine/SCons/Scanner/ScannerTests.py b/src/engine/SCons/Scanner/ScannerTests.py index ee26922..5a4639d 100644 --- a/src/engine/SCons/Scanner/ScannerTests.py +++ b/src/engine/SCons/Scanner/ScannerTests.py @@ -569,7 +569,7 @@ class ClassicCPPTestCase(unittest.TestCase): assert n == 'path/bbb', n assert i == 'bbb', i - n, i = s.find_include(('<', u'ccc'), 'foo', ('path',)) + n, i = s.find_include(('<', 'ccc'), 'foo', ('path',)) assert n == 'path/ccc', n assert i == 'ccc', i diff --git a/src/engine/SCons/Scanner/__init__.py b/src/engine/SCons/Scanner/__init__.py index 562a361..6ec8df9 100644 --- a/src/engine/SCons/Scanner/__init__.py +++ b/src/engine/SCons/Scanner/__init__.py @@ -33,6 +33,7 @@ import re import SCons.Node.FS import SCons.Util +import collections class _Null(object): @@ -178,7 +179,7 @@ class Base(object): self.node_class = node_class self.node_factory = node_factory self.scan_check = scan_check - if callable(recursive): + if isinstance(recursive, collections.Callable): self.recurse_nodes = recursive elif recursive: self.recurse_nodes = self._recurse_all_nodes @@ -369,7 +370,7 @@ class Classic(Current): # is actually found in a Repository or locally. nodes = [] source_dir = node.get_dir() - if callable(path): + if isinstance(path, collections.Callable): path = path() for include in includes: n, i = self.find_include(include, source_dir, path) diff --git a/src/engine/SCons/Script/Interactive.py b/src/engine/SCons/Script/Interactive.py index ffb5096..87fe1cf 100644 --- a/src/engine/SCons/Script/Interactive.py +++ b/src/engine/SCons/Script/Interactive.py @@ -120,7 +120,7 @@ class SConsInteractiveCmd(cmd.Cmd): def __init__(self, **kw): cmd.Cmd.__init__(self) - for key, val in kw.items(): + for key, val in list(kw.items()): setattr(self, key, val) if sys.platform == 'win32': @@ -129,12 +129,12 @@ class SConsInteractiveCmd(cmd.Cmd): self.shell_variable = 'SHELL' def default(self, argv): - print "*** Unknown command: %s" % argv[0] + print("*** Unknown command: %s" % argv[0]) def onecmd(self, line): line = line.strip() if not line: - print self.lastcmd + print(self.lastcmd) return self.emptyline() self.lastcmd = line if line[0] == '!': @@ -249,7 +249,7 @@ class SConsInteractiveCmd(cmd.Cmd): while n: n = walker.get_next() - for node in seen_nodes.keys(): + for node in list(seen_nodes.keys()): # Call node.clear() to clear most of the state node.clear() # node.clear() doesn't reset node.state, so call @@ -274,7 +274,7 @@ class SConsInteractiveCmd(cmd.Cmd): return self.do_build(['build', '--clean'] + argv[1:]) def do_EOF(self, argv): - print + print() self.do_exit(argv) def _do_one_help(self, arg): @@ -357,7 +357,7 @@ class SConsInteractiveCmd(cmd.Cmd): # Doing the right thing with an argument list currently # requires different shell= values on Windows and Linux. p = subprocess.Popen(argv, shell=(sys.platform=='win32')) - except EnvironmentError, e: + except EnvironmentError as e: sys.stderr.write('scons: %s: %s\n' % (argv[0], e.strerror)) else: p.wait() diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index 837c103..9a52937 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -68,6 +68,7 @@ import SCons.Util import SCons.Warnings import SCons.Script.Interactive +import collections def fetch_win32_parallel_msg(): # A subsidiary function that exists solely to isolate this import @@ -104,7 +105,7 @@ class Progressor(object): self.interval = interval self.overwrite = overwrite - if callable(obj): + if isinstance(obj, collections.Callable): self.func = obj elif SCons.Util.is_List(obj): self.func = self.spinner @@ -224,7 +225,7 @@ class BuildTask(SCons.Taskmaster.OutOfDateTask): self.exception_set() self.do_failed() else: - print "scons: Nothing to be done for `%s'." % t + print("scons: Nothing to be done for `%s'." % t) SCons.Taskmaster.OutOfDateTask.executed(self) else: SCons.Taskmaster.OutOfDateTask.executed(self) @@ -290,8 +291,8 @@ class BuildTask(SCons.Taskmaster.OutOfDateTask): if self.options.debug_includes: tree = t.render_include_tree() if tree: - print - print tree + print() + print(tree) SCons.Taskmaster.OutOfDateTask.postprocess(self) def make_ready(self): @@ -326,10 +327,10 @@ class CleanTask(SCons.Taskmaster.AlwaysTask): else: errstr = "Path '%s' exists but isn't a file or directory." raise SCons.Errors.UserError(errstr % (pathstr)) - except SCons.Errors.UserError, e: - print e - except (IOError, OSError), e: - print "scons: Could not remove '%s':" % pathstr, e.strerror + except SCons.Errors.UserError as e: + print(e) + except (IOError, OSError) as e: + print("scons: Could not remove '%s':" % pathstr, e.strerror) def show(self): target = self.targets[0] @@ -348,13 +349,13 @@ class CleanTask(SCons.Taskmaster.AlwaysTask): for t in self.targets: try: removed = t.remove() - except OSError, e: + except OSError as e: # An OSError may indicate something like a permissions # issue, an IOError would indicate something like # the file not existing. In either case, print a # message and keep going to try to remove as many # targets aa possible. - print "scons: Could not remove '%s':" % str(t), e.strerror + print("scons: Could not remove '%s':" % str(t), e.strerror) else: if removed: display("Removed " + str(t)) @@ -595,7 +596,7 @@ def _scons_internal_error(): """Handle all errors but user errors. Print out a message telling the user what to do in this case and print a normal trace. """ - print 'internal error' + print('internal error') traceback.print_exc() sys.exit(2) @@ -707,7 +708,7 @@ def _load_site_scons_dir(topdir, site_dir_name=None): # the error checking makes it longer. try: m = sys.modules['SCons.Script'] - except Exception, e: + except Exception as e: fmt = 'cannot import site_init.py: missing SCons.Script module %s' raise SCons.Errors.InternalError(fmt % repr(e)) try: @@ -715,15 +716,15 @@ def _load_site_scons_dir(topdir, site_dir_name=None): modname = os.path.basename(pathname)[:-len(sfx)] site_m = {"__file__": pathname, "__name__": modname, "__doc__": None} re_special = re.compile("__[^_]+__") - for k in m.__dict__.keys(): + for k in list(m.__dict__.keys()): if not re_special.match(k): site_m[k] = m.__dict__[k] # This is the magic. - exec fp in site_m + exec(fp, site_m) except KeyboardInterrupt: raise - except Exception, e: + except Exception as e: fmt = '*** Error loading site_init file %s:\n' sys.stderr.write(fmt % repr(site_init_file)) raise @@ -733,7 +734,7 @@ def _load_site_scons_dir(topdir, site_dir_name=None): m.__dict__[k] = site_m[k] except KeyboardInterrupt: raise - except ImportError, e: + except ImportError as e: fmt = '*** cannot import site init file %s:\n' sys.stderr.write(fmt % repr(site_init_file)) raise @@ -785,7 +786,7 @@ def _load_all_site_scons_dirs(topdir, verbose=None): dirs=sysdirs + [topdir] for d in dirs: if verbose: # this is used by unit tests. - print "Loading site dir ", d + print("Loading site dir ", d) _load_site_scons_dir(d) def test_load_all_site_scons_dirs(d): @@ -977,7 +978,7 @@ def _main(parser): try: for script in scripts: SCons.Script._SConscript._SConscript(fs, script) - except SCons.Errors.StopError, e: + except SCons.Errors.StopError as e: # We had problems reading an SConscript file, such as it # couldn't be copied in to the VariantDir. Since we're just # reading SConscript files and haven't started building @@ -1034,8 +1035,8 @@ def _main(parser): # SConscript files. Give them the options usage. raise SConsPrintHelpException else: - print help_text - print "Use scons -H for help about command-line options." + print(help_text) + print("Use scons -H for help about command-line options.") exit_status = 0 return @@ -1298,7 +1299,7 @@ def _exec_main(parser, values): prof = Profile() try: prof.runcall(_main, parser) - except SConsPrintHelpException, e: + except SConsPrintHelpException as e: prof.dump_stats(options.profile_file) raise e except SystemExit: @@ -1334,7 +1335,7 @@ def main(): parts.append("__COPYRIGHT__") version = ''.join(parts) - import SConsOptions + from . import SConsOptions parser = SConsOptions.Parser(version) values = SConsOptions.SConsValues(parser.get_default_values()) @@ -1342,22 +1343,22 @@ def main(): try: _exec_main(parser, values) - except SystemExit, s: + except SystemExit as s: if s: exit_status = s except KeyboardInterrupt: print("scons: Build interrupted.") sys.exit(2) - except SyntaxError, e: + except SyntaxError as e: _scons_syntax_error(e) except SCons.Errors.InternalError: _scons_internal_error() - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: _scons_user_error(e) except SConsPrintHelpException: parser.print_help() exit_status = 0 - except SCons.Errors.BuildError, e: + except SCons.Errors.BuildError as e: exit_status = e.exitstatus except: # An exception here is likely a builtin Python exception Python @@ -1393,10 +1394,10 @@ def main(): else: ct = last_command_end - first_command_start scons_time = total_time - sconscript_time - ct - print "Total build time: %f seconds"%total_time - print "Total SConscript file execution time: %f seconds"%sconscript_time - print "Total SCons execution time: %f seconds"%scons_time - print "Total command execution time: %f seconds"%ct + print("Total build time: %f seconds"%total_time) + print("Total SConscript file execution time: %f seconds"%sconscript_time) + print("Total SCons execution time: %f seconds"%scons_time) + print("Total command execution time: %f seconds"%ct) sys.exit(exit_status) diff --git a/src/engine/SCons/Script/SConsOptions.py b/src/engine/SCons/Script/SConsOptions.py index 645ab11..559db97 100644 --- a/src/engine/SCons/Script/SConsOptions.py +++ b/src/engine/SCons/Script/SConsOptions.py @@ -161,7 +161,7 @@ class SConsValues(optparse.Values): elif name == 'diskcheck': try: value = diskcheck_convert(value) - except ValueError, v: + except ValueError as v: raise SCons.Errors.UserError("Not a valid diskcheck value: %s"%v) if 'diskcheck' not in self.__dict__: # No --diskcheck= option was specified on the command line. @@ -611,7 +611,7 @@ def Parser(version): deprecated_debug_options=deprecated_debug_options): if value in debug_options: parser.values.debug.append(value) - elif value in deprecated_debug_options.keys(): + elif value in list(deprecated_debug_options.keys()): parser.values.debug.append(value) try: parser.values.delayed_warnings @@ -635,7 +635,7 @@ def Parser(version): def opt_diskcheck(option, opt, value, parser): try: diskcheck_value = diskcheck_convert(value) - except ValueError, e: + except ValueError as e: raise OptionValueError("`%s' is not a valid diskcheck type" % e) setattr(parser.values, option.dest, diskcheck_value) @@ -802,7 +802,7 @@ def Parser(version): tree_options = ["all", "derived", "prune", "status"] def opt_tree(option, opt, value, parser, tree_options=tree_options): - import Main + from . import Main tp = Main.TreePrinter() for o in value.split(','): if o == 'all': diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py index bd515d2..fefffef 100644 --- a/src/engine/SCons/Script/SConscript.py +++ b/src/engine/SCons/Script/SConscript.py @@ -26,7 +26,7 @@ files. # 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 + __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -113,7 +113,7 @@ def compute_exports(exports): retval[export] = loc[export] except KeyError: retval[export] = glob[export] - except KeyError, x: + except KeyError as x: raise SCons.Errors.UserError("Export of non-existent variable '%s'"%x) return retval @@ -145,7 +145,7 @@ def Return(*vars, **kw): for var in fvars: for v in var.split(): retval.append(call_stack[-1].globals[v]) - except KeyError, x: + except KeyError as x: raise SCons.Errors.UserError("Return of non-existent variable '%s'"%x) if len(retval) == 1: @@ -174,7 +174,7 @@ def _SConscript(fs, *files, **kw): try: SCons.Script.sconscript_reading = SCons.Script.sconscript_reading + 1 if fn == "-": - exec sys.stdin in call_stack[-1].globals + exec(sys.stdin, call_stack[-1].globals) else: if isinstance(fn, SCons.Node.Node): f = fn @@ -257,7 +257,7 @@ def _SConscript(fs, *files, **kw): pass try: try: - exec _file_ in call_stack[-1].globals + exec(_file_, call_stack[-1].globals) except SConscriptReturn: pass finally: @@ -282,7 +282,7 @@ def _SConscript(fs, *files, **kw): rdir._create() # Make sure there's a directory there. try: os.chdir(rdir.get_abspath()) - except OSError, e: + except OSError as e: # We still couldn't chdir there, so raise the error, # but only if actions are being executed. # @@ -467,15 +467,15 @@ class SConsEnvironment(SCons.Environment.Base): scons_ver_string = '%d.%d.%d' % (major, minor, revision) else: scons_ver_string = '%d.%d' % (major, minor) - print "SCons %s or greater required, but you have SCons %s" % \ - (scons_ver_string, SCons.__version__) + print("SCons %s or greater required, but you have SCons %s" % \ + (scons_ver_string, SCons.__version__)) sys.exit(2) def EnsurePythonVersion(self, major, minor): """Exit abnormally if the Python version is not late enough.""" if sys.version_info < (major, minor): v = sys.version.split()[0] - print "Python %d.%d or greater required, but you have Python %s" %(major,minor,v) + print("Python %d.%d or greater required, but you have Python %s" %(major,minor,v)) sys.exit(2) def Exit(self, value=0): @@ -514,7 +514,7 @@ class SConsEnvironment(SCons.Environment.Base): globals[v] = exports[v] else: globals[v] = global_exports[v] - except KeyError,x: + except KeyError as x: raise SCons.Errors.UserError("Import of non-existent variable '%s'"%x) def SConscript(self, *ls, **kw): @@ -529,7 +529,7 @@ class SConsEnvironment(SCons.Environment.Base): return x ls = list(map(subst_element, ls)) subst_kw = {} - for key, val in kw.items(): + for key, val in list(kw.items()): if SCons.Util.is_String(val): val = self.subst(val) elif SCons.Util.is_List(val): diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py index bb7b632..9f2837c 100644 --- a/src/engine/SCons/Script/__init__.py +++ b/src/engine/SCons/Script/__init__.py @@ -66,7 +66,7 @@ if "--debug=memoizer" in _args: except SCons.Warnings.Warning: # Some warning was thrown. Arrange for it to be displayed # or not after warnings are configured. - import Main + from . import Main exc_type, exc_value, tb = sys.exc_info() Main.delayed_warnings.append((exc_type, exc_value)) del _args @@ -85,7 +85,7 @@ import SCons.Util import SCons.Variables import SCons.Defaults -import Main +from . import Main main = Main.main @@ -128,7 +128,7 @@ GetBuildFailures = Main.GetBuildFailures #repositories = Main.repositories # -import SConscript +from . import SConscript _SConscript = SConscript call_stack = _SConscript.call_stack @@ -364,7 +364,7 @@ GlobalDefaultBuilders = [ ] for name in GlobalDefaultEnvironmentFunctions + GlobalDefaultBuilders: - exec "%s = _SConscript.DefaultEnvironmentCall(%s)" % (name, repr(name)) + exec("%s = _SConscript.DefaultEnvironmentCall(%s)" % (name, repr(name))) del name # There are a handful of variables that used to live in the diff --git a/src/engine/SCons/Subst.py b/src/engine/SCons/Subst.py index 98097dc..cca9bbc 100644 --- a/src/engine/SCons/Subst.py +++ b/src/engine/SCons/Subst.py @@ -438,7 +438,7 @@ def scons_subst(strSubst, env, mode=SUBST_RAW, target=None, source=None, gvars={ s = eval(key, self.gvars, lvars) except KeyboardInterrupt: raise - except Exception, e: + except Exception as e: if e.__class__ in AllowableExceptions: return '' raise_exception(e, lvars['TARGETS'], s) @@ -472,7 +472,7 @@ def scons_subst(strSubst, env, mode=SUBST_RAW, target=None, source=None, gvars={ def func(l, conv=self.conv, substitute=self.substitute, lvars=lvars): return conv(substitute(l, lvars)) return list(map(func, s)) - elif callable(s): + elif isinstance(s, collections.Callable): try: s = s(target=lvars['TARGETS'], source=lvars['SOURCES'], @@ -653,7 +653,7 @@ def scons_subst_list(strSubst, env, mode=SUBST_RAW, target=None, source=None, gv s = eval(key, self.gvars, lvars) except KeyboardInterrupt: raise - except Exception, e: + except Exception as e: if e.__class__ in AllowableExceptions: return raise_exception(e, lvars['TARGETS'], s) @@ -681,7 +681,7 @@ def scons_subst_list(strSubst, env, mode=SUBST_RAW, target=None, source=None, gv for a in s: self.substitute(a, lvars, 1) self.next_word() - elif callable(s): + elif isinstance(s, collections.Callable): try: s = s(target=lvars['TARGETS'], source=lvars['SOURCES'], diff --git a/src/engine/SCons/SubstTests.py b/src/engine/SCons/SubstTests.py index 420fd73..da21020 100644 --- a/src/engine/SCons/SubstTests.py +++ b/src/engine/SCons/SubstTests.py @@ -241,14 +241,14 @@ class SubstTestCase(unittest.TestCase): expect = convert(expect) try: result = function(input, env, **kwargs) - except Exception, e: + except Exception as e: fmt = " input %s generated %s (%s)" - print fmt % (repr(input), e.__class__.__name__, repr(e)) + print(fmt % (repr(input), e.__class__.__name__, repr(e))) failed = failed + 1 else: if result != expect: - if failed == 0: print - print " input %s => %s did not match %s" % (repr(input), repr(result), repr(expect)) + if failed == 0: print() + print(" input %s => %s did not match %s" % (repr(input), repr(result), repr(expect))) failed = failed + 1 del cases[:2] fmt = "%d %s() cases failed" @@ -460,18 +460,18 @@ class scons_subst_TestCase(SubstTestCase): input, eraw, ecmd, esig = subst_cases[:4] result = scons_subst(input, env, mode=SUBST_RAW, gvars=gvars) if result != eraw: - if failed == 0: print - print " input %s => RAW %s did not match %s" % (repr(input), repr(result), repr(eraw)) + if failed == 0: print() + print(" input %s => RAW %s did not match %s" % (repr(input), repr(result), repr(eraw))) failed = failed + 1 result = scons_subst(input, env, mode=SUBST_CMD, gvars=gvars) if result != ecmd: - if failed == 0: print - print " input %s => CMD %s did not match %s" % (repr(input), repr(result), repr(ecmd)) + if failed == 0: print() + print(" input %s => CMD %s did not match %s" % (repr(input), repr(result), repr(ecmd))) failed = failed + 1 result = scons_subst(input, env, mode=SUBST_SIG, gvars=gvars) if result != esig: - if failed == 0: print - print " input %s => SIG %s did not match %s" % (repr(input), repr(result), repr(esig)) + if failed == 0: print() + print(" input %s => SIG %s did not match %s" % (repr(input), repr(result), repr(esig))) failed = failed + 1 del subst_cases[:4] assert failed == 0, "%d subst() mode cases failed" % failed @@ -514,7 +514,7 @@ class scons_subst_TestCase(SubstTestCase): class Foo(object): pass scons_subst('${foo.bar}', env, gvars={'foo':Foo()}) - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: expect = [ "AttributeError `bar' trying to evaluate `${foo.bar}'", "AttributeError `Foo instance has no attribute 'bar'' trying to evaluate `${foo.bar}'", @@ -530,7 +530,7 @@ class scons_subst_TestCase(SubstTestCase): env = DummyEnv(self.loc) try: scons_subst('$foo.bar.3.0', env) - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: expect = [ # Python 2.3, 2.4 "SyntaxError `invalid syntax (line 1)' trying to evaluate `$foo.bar.3.0'", @@ -546,7 +546,7 @@ class scons_subst_TestCase(SubstTestCase): env = DummyEnv(self.loc) try: scons_subst("${NONE[2]}", env, gvars={'NONE':None}) - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: expect = [ # Python 2.3, 2.4 "TypeError `unsubscriptable object' trying to evaluate `${NONE[2]}'", @@ -565,7 +565,7 @@ class scons_subst_TestCase(SubstTestCase): def func(a, b, c): pass scons_subst("${func(1)}", env, gvars={'func':func}) - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: expect = [ # Python 2.3, 2.4, 2.5 "TypeError `func() takes exactly 3 arguments (1 given)' trying to evaluate `${func(1)}'" @@ -946,18 +946,18 @@ class scons_subst_list_TestCase(SubstTestCase): input, eraw, ecmd, esig = subst_list_cases[:4] result = scons_subst_list(input, env, mode=SUBST_RAW, gvars=gvars) if result != eraw: - if failed == 0: print - print " input %s => RAW %s did not match %s" % (repr(input), repr(result), repr(eraw)) + if failed == 0: print() + print(" input %s => RAW %s did not match %s" % (repr(input), repr(result), repr(eraw))) failed = failed + 1 result = scons_subst_list(input, env, mode=SUBST_CMD, gvars=gvars) if result != ecmd: - if failed == 0: print - print " input %s => CMD %s did not match %s" % (repr(input), repr(result), repr(ecmd)) + if failed == 0: print() + print(" input %s => CMD %s did not match %s" % (repr(input), repr(result), repr(ecmd))) failed = failed + 1 result = scons_subst_list(input, env, mode=SUBST_SIG, gvars=gvars) if result != esig: - if failed == 0: print - print " input %s => SIG %s did not match %s" % (repr(input), repr(result), repr(esig)) + if failed == 0: print() + print(" input %s => SIG %s did not match %s" % (repr(input), repr(result), repr(esig))) failed = failed + 1 del subst_list_cases[:4] assert failed == 0, "%d subst() mode cases failed" % failed @@ -969,7 +969,7 @@ class scons_subst_list_TestCase(SubstTestCase): class Foo(object): pass scons_subst_list('${foo.bar}', env, gvars={'foo':Foo()}) - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: expect = [ "AttributeError `bar' trying to evaluate `${foo.bar}'", "AttributeError `Foo instance has no attribute 'bar'' trying to evaluate `${foo.bar}'", @@ -985,7 +985,7 @@ class scons_subst_list_TestCase(SubstTestCase): env = DummyEnv() try: scons_subst_list('$foo.bar.3.0', env) - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: expect = [ "SyntaxError `invalid syntax' trying to evaluate `$foo.bar.3.0'", "SyntaxError `invalid syntax (line 1)' trying to evaluate `$foo.bar.3.0'", @@ -1093,8 +1093,8 @@ class scons_subst_once_TestCase(unittest.TestCase): input, key, expect = cases[:3] result = scons_subst_once(input, env, key) if result != expect: - if failed == 0: print - print " input %s (%s) => %s did not match %s" % (repr(input), repr(key), repr(result), repr(expect)) + if failed == 0: print() + print(" input %s (%s) => %s did not match %s" % (repr(input), repr(key), repr(result), repr(expect))) failed = failed + 1 del cases[:3] assert failed == 0, "%d subst() cases failed" % failed diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py index 64ab84d..54d04a8 100644 --- a/src/engine/SCons/Taskmaster.py +++ b/src/engine/SCons/Taskmaster.py @@ -107,7 +107,7 @@ fmt = "%(considered)3d "\ def dump_stats(): for n in sorted(StatsNodes, key=lambda a: str(a)): - print (fmt % n.stats.__dict__) + str(n) + print((fmt % n.stats.__dict__) + str(n)) @@ -164,7 +164,7 @@ class Task(object): """ global print_prepare T = self.tm.trace - if T: T.write(self.trace_message(u'Task.prepare()', self.node)) + if T: T.write(self.trace_message('Task.prepare()', self.node)) # Now that it's the appropriate time, give the TaskMaster a # chance to raise any exceptions it encountered while preparing @@ -189,13 +189,13 @@ class Task(object): executor.prepare() for t in executor.get_action_targets(): if print_prepare: - print "Preparing target %s..."%t + print("Preparing target %s..."%t) for s in t.side_effects: - print "...with side-effect %s..."%s + print("...with side-effect %s..."%s) t.prepare() for s in t.side_effects: if print_prepare: - print "...Preparing side-effect %s..."%s + print("...Preparing side-effect %s..."%s) s.prepare() def get_target(self): @@ -224,7 +224,7 @@ class Task(object): prepare(), executed() or failed(). """ T = self.tm.trace - if T: T.write(self.trace_message(u'Task.execute()', self.node)) + if T: T.write(self.trace_message('Task.execute()', self.node)) try: cached_targets = [] @@ -254,7 +254,7 @@ class Task(object): raise except SCons.Errors.BuildError: raise - except Exception, e: + except Exception as e: buildError = SCons.Errors.convert_to_BuildError(e) buildError.node = self.targets[0] buildError.exc_info = sys.exc_info() @@ -383,7 +383,7 @@ class Task(object): This is the default behavior for building only what's necessary. """ T = self.tm.trace - if T: T.write(self.trace_message(u'Task.make_ready_current()', + if T: T.write(self.trace_message('Task.make_ready_current()', self.node)) self.out_of_date = [] @@ -393,7 +393,7 @@ class Task(object): t.disambiguate().make_ready() is_up_to_date = not t.has_builder() or \ (not t.always_build and t.is_up_to_date()) - except EnvironmentError, e: + except EnvironmentError as e: raise SCons.Errors.BuildError(node=t, errstr=e.strerror, filename=e.filename) if not is_up_to_date: @@ -428,7 +428,7 @@ class Task(object): that can be put back on the candidates list. """ T = self.tm.trace - if T: T.write(self.trace_message(u'Task.postprocess()', self.node)) + if T: T.write(self.trace_message('Task.postprocess()', self.node)) # We may have built multiple targets, some of which may have # common parents waiting for this build. Count up how many @@ -445,7 +445,7 @@ class Task(object): # A node can only be in the pending_children set if it has # some waiting_parents. if t.waiting_parents: - if T: T.write(self.trace_message(u'Task.postprocess()', + if T: T.write(self.trace_message('Task.postprocess()', t, 'removing')) pending_children.discard(t) @@ -462,9 +462,9 @@ class Task(object): if p.ref_count == 0: self.tm.candidates.append(p) - for p, subtract in parents.items(): + for p, subtract in list(parents.items()): p.ref_count = p.ref_count - subtract - if T: T.write(self.trace_message(u'Task.postprocess()', + if T: T.write(self.trace_message('Task.postprocess()', p, 'adjusted parent ref count')) if p.ref_count == 0: @@ -524,7 +524,7 @@ class Task(object): except ValueError: exc_type, exc_value = exc exc_traceback = None - raise exc_type, exc_value, exc_traceback + raise exc_type(exc_value).with_traceback(exc_traceback) class AlwaysTask(Task): def needs_execute(self): @@ -748,12 +748,12 @@ class Taskmaster(object): self.ready_exc = None T = self.trace - if T: T.write(u'\n' + self.trace_message('Looking for a node to evaluate')) + if T: T.write('\n' + self.trace_message('Looking for a node to evaluate')) while True: node = self.next_candidate() if node is None: - if T: T.write(self.trace_message('No candidate anymore.') + u'\n') + if T: T.write(self.trace_message('No candidate anymore.') + '\n') return None node = node.disambiguate() @@ -776,7 +776,7 @@ class Taskmaster(object): else: S = None - if T: T.write(self.trace_message(u' Considering node %s and its children:' % self.trace_node(node))) + if T: T.write(self.trace_message(' Considering node %s and its children:' % self.trace_node(node))) if state == NODE_NO_STATE: # Mark this node as being on the execution stack: @@ -784,7 +784,7 @@ class Taskmaster(object): elif state > NODE_PENDING: # Skip this node if it has already been evaluated: if S: S.already_handled = S.already_handled + 1 - if T: T.write(self.trace_message(u' already handled (executed)')) + if T: T.write(self.trace_message(' already handled (executed)')) continue executor = node.get_executor() @@ -797,7 +797,7 @@ class Taskmaster(object): self.ready_exc = (SCons.Errors.ExplicitExit, e) if T: T.write(self.trace_message(' SystemExit')) return node - except Exception, e: + except Exception as e: # We had a problem just trying to figure out the # children (like a child couldn't be linked in to a # VariantDir, or a Scanner threw something). Arrange to @@ -815,7 +815,7 @@ class Taskmaster(object): for child in chain(executor.get_all_prerequisites(), children): childstate = child.get_state() - if T: T.write(self.trace_message(u' ' + self.trace_node(child))) + if T: T.write(self.trace_message(' ' + self.trace_node(child))) if childstate == NODE_NO_STATE: children_not_visited.append(child) @@ -874,7 +874,7 @@ class Taskmaster(object): # count so we can be put back on the list for # re-evaluation when they've all finished. node.ref_count = node.ref_count + child.add_to_waiting_parents(node) - if T: T.write(self.trace_message(u' adjusted ref count: %s, child %s' % + if T: T.write(self.trace_message(' adjusted ref count: %s, child %s' % (self.trace_node(node), repr(str(child))))) if T: @@ -900,7 +900,7 @@ class Taskmaster(object): # The default when we've gotten through all of the checks above: # this node is ready to be built. if S: S.build = S.build + 1 - if T: T.write(self.trace_message(u'Evaluating %s\n' % + if T: T.write(self.trace_message('Evaluating %s\n' % self.trace_node(node))) # For debugging only: diff --git a/src/engine/SCons/TaskmasterTests.py b/src/engine/SCons/TaskmasterTests.py index 85ade8d..0140278 100644 --- a/src/engine/SCons/TaskmasterTests.py +++ b/src/engine/SCons/TaskmasterTests.py @@ -20,7 +20,7 @@ # 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 + __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -692,7 +692,7 @@ class TaskmasterTestCase(unittest.TestCase): tm = SCons.Taskmaster.Taskmaster([n3]) try: t = tm.next_task() - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: assert str(e) == "Dependency cycle: n3 -> n1 -> n2 -> n3", str(e) else: assert 'Did not catch expected UserError' @@ -846,7 +846,7 @@ class TaskmasterTestCase(unittest.TestCase): exc_caught = None try: t.prepare() - except MyException, e: + except MyException as e: exc_caught = 1 except: pass @@ -899,7 +899,7 @@ class TaskmasterTestCase(unittest.TestCase): t = tm.next_task() try: t.prepare() - except Exception, e: + except Exception as e: assert str(e) == "Executor.prepare() exception", e else: raise AssertionError("did not catch expected exception") @@ -953,7 +953,7 @@ class TaskmasterTestCase(unittest.TestCase): t = tm.next_task() try: t.execute() - except SCons.Errors.BuildError, e: + except SCons.Errors.BuildError as e: assert e.node == n4, e.node assert e.errstr == "OtherError : ", e.errstr assert len(e.exc_info) == 3, e.exc_info diff --git a/src/engine/SCons/Tool/FortranCommon.py b/src/engine/SCons/Tool/FortranCommon.py index 4c5730c..c21128e 100644 --- a/src/engine/SCons/Tool/FortranCommon.py +++ b/src/engine/SCons/Tool/FortranCommon.py @@ -61,7 +61,7 @@ def isfortran(env, source): def _fortranEmitter(target, source, env): node = source[0].rfile() if not node.exists() and not node.is_derived(): - print "Could not locate " + str(node.name) + print("Could not locate " + str(node.name)) return ([], []) mod_regex = """(?i)^\s*MODULE\s+(?!PROCEDURE)(\w+)""" cre = re.compile(mod_regex,re.M) diff --git a/src/engine/SCons/Tool/GettextCommon.py b/src/engine/SCons/Tool/GettextCommon.py index cd2f306..ea81f0d 100644 --- a/src/engine/SCons/Tool/GettextCommon.py +++ b/src/engine/SCons/Tool/GettextCommon.py @@ -196,7 +196,7 @@ class _POFileBuilder(BuilderBase): import SCons.Util import SCons.Node linguas_files = None - if env.has_key('LINGUAS_FILE') and env['LINGUAS_FILE']: + if 'LINGUAS_FILE' in env and env['LINGUAS_FILE']: linguas_files = env['LINGUAS_FILE'] # This prevents endless recursion loop (we'll be invoked once for # each target appended here, we must not extend the list again). @@ -341,7 +341,7 @@ class RPaths(object): def _init_po_files(target, source, env): """ Action function for `POInit` builder. """ nop = lambda target, source, env : 0 - if env.has_key('POAUTOINIT'): + if 'POAUTOINIT' in env: autoinit = env['POAUTOINIT'] else: autoinit = False @@ -365,7 +365,7 @@ def _init_po_files(target, source, env): ############################################################################# def _detect_xgettext(env): """ Detects *xgettext(1)* binary """ - if env.has_key('XGETTEXT'): + if 'XGETTEXT' in env: return env['XGETTEXT'] xgettext = env.Detect('xgettext'); if xgettext: @@ -380,7 +380,7 @@ def _xgettext_exists(env): ############################################################################# def _detect_msginit(env): """ Detects *msginit(1)* program. """ - if env.has_key('MSGINIT'): + if 'MSGINIT' in env: return env['MSGINIT'] msginit = env.Detect('msginit'); if msginit: @@ -395,7 +395,7 @@ def _msginit_exists(env): ############################################################################# def _detect_msgmerge(env): """ Detects *msgmerge(1)* program. """ - if env.has_key('MSGMERGE'): + if 'MSGMERGE' in env: return env['MSGMERGE'] msgmerge = env.Detect('msgmerge'); if msgmerge: @@ -410,7 +410,7 @@ def _msgmerge_exists(env): ############################################################################# def _detect_msgfmt(env): """ Detects *msgmfmt(1)* program. """ - if env.has_key('MSGFMT'): + if 'MSGFMT' in env: return env['MSGFMT'] msgfmt = env.Detect('msgfmt'); if msgfmt: diff --git a/src/engine/SCons/Tool/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py index caf2b37..dcf69c8 100644 --- a/src/engine/SCons/Tool/MSCommon/common.py +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -38,7 +38,7 @@ import SCons.Util logfile = os.environ.get('SCONS_MSCOMMON_DEBUG') if logfile == '-': def debug(x): - print x + print(x) elif logfile: try: import logging @@ -113,7 +113,7 @@ def normalize_env(env, keys, force=False): Note: the environment is copied.""" normenv = {} if env: - for k in env.keys(): + for k in list(env.keys()): normenv[k] = copy.deepcopy(env[k]).encode('mbcs') for k in keys: @@ -217,7 +217,7 @@ def parse_output(output, keep = ("INCLUDE", "LIB", "LIBPATH", "PATH")): dkeep[key].append(p) for line in output.splitlines(): - for k,v in rdk.items(): + for k,v in list(rdk.items()): m = v.match(line) if m: add_env(m, k) diff --git a/src/engine/SCons/Tool/MSCommon/netframework.py b/src/engine/SCons/Tool/MSCommon/netframework.py index 6124e5b..1a6478f 100644 --- a/src/engine/SCons/Tool/MSCommon/netframework.py +++ b/src/engine/SCons/Tool/MSCommon/netframework.py @@ -28,7 +28,7 @@ __doc__ = """ import os import re -from common import read_reg, debug +from .common import read_reg, debug # Original value recorded by dcournapeau _FRAMEWORKDIR_HKEY_ROOT = r'Software\Microsoft\.NETFramework\InstallRoot' @@ -40,7 +40,7 @@ def find_framework_root(): try: froot = read_reg(_FRAMEWORKDIR_HKEY_ROOT) debug("Found framework install root in registry: %s" % froot) - except WindowsError, e: + except WindowsError as e: debug("Could not read reg key %s" % _FRAMEWORKDIR_HKEY_ROOT) return None diff --git a/src/engine/SCons/Tool/MSCommon/sdk.py b/src/engine/SCons/Tool/MSCommon/sdk.py index 2bf5eef..f71035b 100644 --- a/src/engine/SCons/Tool/MSCommon/sdk.py +++ b/src/engine/SCons/Tool/MSCommon/sdk.py @@ -33,7 +33,7 @@ import os import SCons.Errors import SCons.Util -import common +from . import common debug = common.debug @@ -80,7 +80,7 @@ class SDKDefinition(object): try: sdk_dir = common.read_reg(hkey) - except WindowsError, e: + except WindowsError as e: debug('find_sdk_dir(): no SDK registry key %s' % repr(hkey)) return None @@ -299,7 +299,7 @@ def get_cur_sdk_dir_from_reg(): try: val = common.read_reg(_CURINSTALLED_SDK_HKEY_ROOT) debug("Found current sdk dir in registry: %s" % val) - except WindowsError, e: + except WindowsError as e: debug("Did not find current sdk in registry") return None @@ -350,7 +350,7 @@ def mssdk_setup_env(env): debug('sdk.py:mssdk_setup_env thinks msvs_version is None') return msvs_version = env.subst(msvs_version) - import vs + from . import vs msvs = vs.get_vs_by_version(msvs_version) debug('sdk.py:mssdk_setup_env:msvs is :%s'%msvs) if not msvs: diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index 1266ee8..35b95d5 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -42,11 +42,11 @@ from string import digits as string_digits import SCons.Warnings -import common +from . import common debug = common.debug -import sdk +from . import sdk get_installed_sdks = sdk.get_installed_sdks @@ -119,14 +119,14 @@ def get_host_target(env): try: host = _ARCH_TO_CANONICAL[host_platform.lower()] - except KeyError, e: + except KeyError as e: msg = "Unrecognized host architecture %s" raise ValueError(msg % repr(host_platform)) try: target = _ARCH_TO_CANONICAL[target_platform.lower()] - except KeyError, e: - all_archs = str(_ARCH_TO_CANONICAL.keys()) + except KeyError as e: + all_archs = str(list(_ARCH_TO_CANONICAL.keys())) raise ValueError("Unrecognized target architecture %s\n\tValid architectures: %s" % (target_platform, all_archs)) return (host, target,req_target_platform) @@ -168,7 +168,7 @@ def msvc_version_to_maj_min(msvc_version): maj = int(t[0]) min = int(t[1]) return maj, min - except ValueError, e: + except ValueError as e: raise ValueError("Unrecognized version %s (%s)" % (msvc_version,msvc_version_numeric)) def is_host_target_supported(host_target, msvc_version): @@ -217,7 +217,7 @@ def find_vc_pdir(msvc_version): key = root + key try: comps = common.read_reg(key) - except WindowsError, e: + except WindowsError as e: debug('find_vc_dir(): no VC registry key %s' % repr(key)) else: debug('find_vc_dir(): found VC in registry: %s' % comps) @@ -289,7 +289,7 @@ def get_installed_vcs(): installed_versions.append(ver) else: debug('find_vc_pdir return None for ver %s' % ver) - except VisualCException, e: + except VisualCException as e: debug('did not find VC %s: caught exception %s' % (ver, str(e))) return installed_versions @@ -393,7 +393,7 @@ def msvc_find_valid_batch_script(env,version): try: (vc_script,sdk_script) = find_batch_file(env,version,host_platform,tp) debug('vc.py:msvc_find_valid_batch_script() vc_script:%s sdk_script:%s'%(vc_script,sdk_script)) - except VisualCException, e: + except VisualCException as e: msg = str(e) debug('Caught exception while looking for batch file (%s)' % msg) warn_msg = "VC version %s not installed. " + \ @@ -408,7 +408,7 @@ def msvc_find_valid_batch_script(env,version): if vc_script: try: d = script_env(vc_script, args=arg) - except BatchFileExecutionError, e: + except BatchFileExecutionError as e: debug('vc.py:msvc_find_valid_batch_script() use_script 3: failed running VC script %s: %s: Error:%s'%(repr(vc_script),arg,e)) vc_script=None continue @@ -416,7 +416,7 @@ def msvc_find_valid_batch_script(env,version): debug('vc.py:msvc_find_valid_batch_script() use_script 4: trying sdk script: %s'%(sdk_script)) try: d = script_env(sdk_script,args=[]) - except BatchFileExecutionError,e: + except BatchFileExecutionError as e: debug('vc.py:msvc_find_valid_batch_script() use_script 5: failed running SDK script %s: Error:%s'%(repr(sdk_script),e)) continue elif not vc_script and not sdk_script: @@ -468,7 +468,7 @@ def msvc_setup_env(env): SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg) return None - for k, v in d.items(): + for k, v in list(d.items()): debug('vc.py:msvc_setup_env() env:%s -> %s'%(k,v)) env.PrependENVPath(k, v, delete_existing=True) diff --git a/src/engine/SCons/Tool/MSCommon/vs.py b/src/engine/SCons/Tool/MSCommon/vs.py index d5bf2c3..3219719 100644 --- a/src/engine/SCons/Tool/MSCommon/vs.py +++ b/src/engine/SCons/Tool/MSCommon/vs.py @@ -31,7 +31,7 @@ import os import SCons.Errors import SCons.Util -from common import debug, \ +from .common import debug, \ get_output, \ is_win64, \ normalize_env, \ @@ -85,7 +85,7 @@ class VisualStudio(object): key = root + key try: comps = read_reg(key) - except WindowsError, e: + except WindowsError as e: debug('find_vs_dir_by_reg(): no VS registry key %s' % repr(key)) else: debug('find_vs_dir_by_reg(): found VS in registry: %s' % comps) @@ -536,7 +536,7 @@ def msvs_setup_env(env): env['ENV'] = save_ENV vars = parse_output(output, vars) - for k, v in vars.items(): + for k, v in list(vars.items()): env.PrependENVPath(k, v, delete_existing=1) def query_versions(): diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index b80d6e4..ac180a9 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -113,7 +113,7 @@ class Tool(object): finally: if file: file.close() - except ImportError, e: + except ImportError as e: if str(e)!="No module named %s"%self.name: raise SCons.Errors.EnvironmentError(e) try: @@ -125,7 +125,7 @@ class Tool(object): try: importer = zipimport.zipimporter(aPath) return importer.load_module(self.name) - except ImportError, e: + except ImportError as e: pass finally: sys.path = oldpythonpath @@ -143,7 +143,7 @@ class Tool(object): if file: file.close() return module - except ImportError, e: + except ImportError as e: if str(e)!="No module named %s"%self.name: raise SCons.Errors.EnvironmentError(e) try: @@ -152,10 +152,10 @@ class Tool(object): module = importer.load_module(full_name) setattr(SCons.Tool, self.name, module) return module - except ImportError, e: + except ImportError as e: m = "No tool named '%s': %s" % (self.name, e) raise SCons.Errors.EnvironmentError(m) - except ImportError, e: + except ImportError as e: m = "No tool named '%s': %s" % (self.name, e) raise SCons.Errors.EnvironmentError(m) @@ -254,7 +254,7 @@ def VersionShLibLinkNames(version, libname, env): suffix_re = re.escape('.' + version + shlib_suffix) linkname = re.sub(suffix_re, shlib_suffix, libname) if Verbose: - print "VersionShLibLinkNames: linkname = ",linkname + print("VersionShLibLinkNames: linkname = ",linkname) linknames.append(linkname) elif platform == 'posix': # For libfoo.so.x.y.z, linknames libfoo.so libfoo.so.x.y libfoo.so.x @@ -262,7 +262,7 @@ def VersionShLibLinkNames(version, libname, env): # First linkname has no version number linkname = re.sub(suffix_re, shlib_suffix, libname) if Verbose: - print "VersionShLibLinkNames: linkname = ",linkname + print("VersionShLibLinkNames: linkname = ",linkname) linknames.append(linkname) versionparts = version.split('.') major_name = linkname + "." + versionparts[0] @@ -271,7 +271,7 @@ def VersionShLibLinkNames(version, libname, env): #for linkname in [major_name, minor_name]: for linkname in [major_name, ]: if Verbose: - print "VersionShLibLinkNames: linkname ",linkname, ", target ",libname + print("VersionShLibLinkNames: linkname ",linkname, ", target ",libname) linknames.append(linkname) # note: no Windows case here (win32 or cygwin); # MSVC doesn't support this type of versioned shared libs. @@ -294,10 +294,10 @@ symlinks for the platform we are on""" shlib_suffix = env.subst('$SHLIBSUFFIX') shlink_flags = SCons.Util.CLVar(env.subst('$SHLINKFLAGS')) if Verbose: - print "VersionShLib: libname = ",libname - print "VersionShLib: platform = ",platform - print "VersionShLib: shlib_suffix = ",shlib_suffix - print "VersionShLib: target = ",str(target[0]) + print("VersionShLib: libname = ",libname) + print("VersionShLib: platform = ",platform) + print("VersionShLib: shlib_suffix = ",shlib_suffix) + print("VersionShLib: target = ",str(target[0])) if version: # set the shared library link flags @@ -308,7 +308,7 @@ symlinks for the platform we are on""" soname = re.sub(suffix_re, shlib_suffix, libname) + '.' + major shlink_flags += [ '-Wl,-Bsymbolic', '-Wl,-soname=%s' % soname ] if Verbose: - print " soname ",soname,", shlink_flags ",shlink_flags + print(" soname ",soname,", shlink_flags ",shlink_flags) elif platform == 'cygwin': shlink_flags += [ '-Wl,-Bsymbolic', '-Wl,--out-implib,${TARGET.base}.a' ] @@ -317,7 +317,7 @@ symlinks for the platform we are on""" '-compatibility_version', '%s' % version, '-undefined', 'dynamic_lookup' ] if Verbose: - print "VersionShLib: shlink_flags = ",shlink_flags + print("VersionShLib: shlink_flags = ",shlink_flags) envlink = env.Clone() envlink['SHLINKFLAGS'] = shlink_flags else: @@ -330,7 +330,7 @@ symlinks for the platform we are on""" libname = target[0].path linknames = VersionShLibLinkNames(version, libname, env) if Verbose: - print "VerShLib: linknames ",linknames + print("VerShLib: linknames ",linknames) # Here we just need the file name w/o path as the target of the link lib_ver = target[0].name # make symlink of adjacent names in linknames @@ -343,7 +343,7 @@ symlinks for the platform we are on""" pass os.symlink(os.path.basename(linkname),lastlinkname) if Verbose: - print "VerShLib: made sym link of %s -> %s" % (lastlinkname,linkname) + print("VerShLib: made sym link of %s -> %s" % (lastlinkname,linkname)) lastlinkname = linkname # finish chain of sym links with link to the actual library if len(linknames)>0: @@ -353,7 +353,7 @@ symlinks for the platform we are on""" pass os.symlink(lib_ver,lastlinkname) if Verbose: - print "VerShLib: made sym link of %s -> %s" % (linkname, lib_ver) + print("VerShLib: made sym link of %s -> %s" % (linkname, lib_ver)) return result ShLibAction = SCons.Action.Action(VersionedSharedLibrary, None) @@ -631,7 +631,7 @@ class ToolInitializer(object): so we no longer copy and re-bind them when the construction environment gets cloned. """ - for method in self.methods.values(): + for method in list(self.methods.values()): env.RemoveMethod(method) def apply_tools(self, env): diff --git a/src/engine/SCons/Tool/aixcc.py b/src/engine/SCons/Tool/aixcc.py index 9668f79..b1da31e 100644 --- a/src/engine/SCons/Tool/aixcc.py +++ b/src/engine/SCons/Tool/aixcc.py @@ -36,7 +36,7 @@ import os.path import SCons.Platform.aix -import cc +from . import cc packages = ['vac.C', 'ibmcxx.cmp'] diff --git a/src/engine/SCons/Tool/aixf77.py b/src/engine/SCons/Tool/aixf77.py index a667e84..21786ee 100644 --- a/src/engine/SCons/Tool/aixf77.py +++ b/src/engine/SCons/Tool/aixf77.py @@ -36,7 +36,7 @@ import os.path #import SCons.Platform.aix -import f77 +from . import f77 # It would be good to look for the AIX F77 package the same way we're now # looking for the C and C++ packages. This should be as easy as supplying diff --git a/src/engine/SCons/Tool/aixlink.py b/src/engine/SCons/Tool/aixlink.py index 3512522..fc65afb 100644 --- a/src/engine/SCons/Tool/aixlink.py +++ b/src/engine/SCons/Tool/aixlink.py @@ -37,8 +37,8 @@ import os.path import SCons.Util -import aixcc -import link +from . import aixcc +from . import link cplusplus = __import__('c++', globals(), locals(), []) diff --git a/src/engine/SCons/Tool/applelink.py b/src/engine/SCons/Tool/applelink.py index 1939098..ba955a4 100644 --- a/src/engine/SCons/Tool/applelink.py +++ b/src/engine/SCons/Tool/applelink.py @@ -37,7 +37,7 @@ import SCons.Util # Even though the Mac is based on the GNU toolchain, it doesn't understand # the -rpath option, so we use the "link" tool instead of "gnulink". -import link +from . import link def generate(env): """Add Builders and construction variables for applelink to an diff --git a/src/engine/SCons/Tool/cvf.py b/src/engine/SCons/Tool/cvf.py index 2a28e6a..da2c910 100644 --- a/src/engine/SCons/Tool/cvf.py +++ b/src/engine/SCons/Tool/cvf.py @@ -29,7 +29,7 @@ Tool-specific initialization for the Compaq Visual Fortran compiler. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import fortran +from . import fortran compilers = ['f90'] diff --git a/src/engine/SCons/Tool/cyglink.py b/src/engine/SCons/Tool/cyglink.py index 87716cf..1685d7f 100644 --- a/src/engine/SCons/Tool/cyglink.py +++ b/src/engine/SCons/Tool/cyglink.py @@ -11,7 +11,7 @@ selection method. import SCons.Action import SCons.Util -import gnulink +from . import gnulink def shlib_generator(target, source, env, for_signature): cmd = SCons.Util.CLVar(['$SHLINK']) diff --git a/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py b/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py index c070602..ef03206 100644 --- a/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py +++ b/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py @@ -82,7 +82,7 @@ def adjustColumnWidths(ctx, nodeset): relParts.append(relPart) absParts.append(pixels) - col = col.next + col = col.__next__ # Ok, now we have the relative widths and absolute widths in # two parallel arrays. @@ -116,7 +116,7 @@ def adjustColumnWidths(ctx, nodeset): pixelWidth = convertLength(tableWidth) if pixelWidth <= absTotal: - print "Table is wider than table width" + print("Table is wider than table width") else: pixelWidth = pixelWidth - absTotal @@ -151,7 +151,7 @@ def adjustColumnWidths(ctx, nodeset): col.setProp("width", widths[count]) count = count+1 - col = col.next + col = col.__next__ return nodeset @@ -163,10 +163,10 @@ def convertLength(length): m = re.search('([+-]?[\d\.]+)(\S+)', length) if m != None and m.lastindex > 1: unit = pixelsPerInch - if unitHash.has_key(m.group(2)): + if m.group(2) in unitHash: unit = unitHash[m.group(2)] else: - print "Unrecognized length: " + m.group(2) + print("Unrecognized length: " + m.group(2)) pixels = unit * float(m.group(1)) else: diff --git a/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/xslt.py b/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/xslt.py index c712f65..8554dd1 100644 --- a/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/xslt.py +++ b/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/xslt.py @@ -18,7 +18,7 @@ try: xmlfile = sys.argv[1] xslfile = sys.argv[2] except IndexError: - print usage + print(usage) sys.exit(1) def quote(astring): @@ -38,12 +38,12 @@ try: while (sys.argv[count]): try: name, value = sys.argv[count].split("=", 2) - if params.has_key(name): - print "Warning: '%s' re-specified; replacing value" % name + if name in params: + print("Warning: '%s' re-specified; replacing value" % name) params[name] = quote(value) except ValueError: - print "Invalid parameter specification: '" + sys.argv[count] + "'" - print usage + print("Invalid parameter specification: '" + sys.argv[count] + "'") + print(usage) sys.exit(1) count = count+1 except IndexError: @@ -70,7 +70,7 @@ result = style.applyStylesheet(doc, params) if outfile: style.saveResultToFilename(outfile, result, 0) else: - print result + print(result) # Free things up style.freeStylesheet() diff --git a/src/engine/SCons/Tool/dvipdf.py b/src/engine/SCons/Tool/dvipdf.py index 7c41e9c..374b9c5 100644 --- a/src/engine/SCons/Tool/dvipdf.py +++ b/src/engine/SCons/Tool/dvipdf.py @@ -100,7 +100,7 @@ def generate(env): if DVIPDFAction is None: DVIPDFAction = SCons.Action.Action(DviPdfFunction, strfunction = DviPdfStrFunction) - import pdf + from . import pdf pdf.generate(env) bld = env['BUILDERS']['PDF'] diff --git a/src/engine/SCons/Tool/f03.py b/src/engine/SCons/Tool/f03.py index 3aab1c0..6c30971 100644 --- a/src/engine/SCons/Tool/f03.py +++ b/src/engine/SCons/Tool/f03.py @@ -36,7 +36,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Defaults import SCons.Tool import SCons.Util -import fortran +from . import fortran from SCons.Tool.FortranCommon import add_all_to_env, add_f03_to_env compilers = ['f03'] diff --git a/src/engine/SCons/Tool/f95.py b/src/engine/SCons/Tool/f95.py index 5ce5e57..5baa31e 100644 --- a/src/engine/SCons/Tool/f95.py +++ b/src/engine/SCons/Tool/f95.py @@ -36,7 +36,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Defaults import SCons.Tool import SCons.Util -import fortran +from . import fortran from SCons.Tool.FortranCommon import add_all_to_env, add_f95_to_env compilers = ['f95'] diff --git a/src/engine/SCons/Tool/filesystem.py b/src/engine/SCons/Tool/filesystem.py index 31c8abc..3b8ee4c 100644 --- a/src/engine/SCons/Tool/filesystem.py +++ b/src/engine/SCons/Tool/filesystem.py @@ -66,7 +66,7 @@ def generate(env): try: env['BUILDERS']['CopyTo'] env['BUILDERS']['CopyAs'] - except KeyError, e: + except KeyError as e: global copyToBuilder if copyToBuilder is None: copyToBuilder = SCons.Builder.Builder( diff --git a/src/engine/SCons/Tool/gcc.py b/src/engine/SCons/Tool/gcc.py index 71f60a3..4f87b24 100644 --- a/src/engine/SCons/Tool/gcc.py +++ b/src/engine/SCons/Tool/gcc.py @@ -33,7 +33,7 @@ selection method. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import cc +from . import cc import os import re import subprocess diff --git a/src/engine/SCons/Tool/gfortran.py b/src/engine/SCons/Tool/gfortran.py index 4f3e7e4..7b05e68 100644 --- a/src/engine/SCons/Tool/gfortran.py +++ b/src/engine/SCons/Tool/gfortran.py @@ -36,7 +36,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Util -import fortran +from . import fortran def generate(env): """Add Builders and construction variables for gfortran to an diff --git a/src/engine/SCons/Tool/gnulink.py b/src/engine/SCons/Tool/gnulink.py index bf71270..ea8d7bd 100644 --- a/src/engine/SCons/Tool/gnulink.py +++ b/src/engine/SCons/Tool/gnulink.py @@ -35,7 +35,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Util -import link +from . import link linkers = ['g++', 'gcc'] diff --git a/src/engine/SCons/Tool/gs.py b/src/engine/SCons/Tool/gs.py index ada169a..c5506ce 100644 --- a/src/engine/SCons/Tool/gs.py +++ b/src/engine/SCons/Tool/gs.py @@ -57,7 +57,7 @@ def generate(env): if GhostscriptAction is None: GhostscriptAction = SCons.Action.Action('$GSCOM', '$GSCOMSTR') - import pdf + from . import pdf pdf.generate(env) bld = env['BUILDERS']['PDF'] diff --git a/src/engine/SCons/Tool/hpcc.py b/src/engine/SCons/Tool/hpcc.py index 30f4964..51d2e38 100644 --- a/src/engine/SCons/Tool/hpcc.py +++ b/src/engine/SCons/Tool/hpcc.py @@ -34,7 +34,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Util -import cc +from . import cc def generate(env): """Add Builders and construction variables for aCC & cc to an Environment.""" diff --git a/src/engine/SCons/Tool/hplink.py b/src/engine/SCons/Tool/hplink.py index 17dbe05..10ef30b 100644 --- a/src/engine/SCons/Tool/hplink.py +++ b/src/engine/SCons/Tool/hplink.py @@ -37,7 +37,7 @@ import os.path import SCons.Util -import link +from . import link ccLinker = None diff --git a/src/engine/SCons/Tool/icc.py b/src/engine/SCons/Tool/icc.py index db15642..11ea075 100644 --- a/src/engine/SCons/Tool/icc.py +++ b/src/engine/SCons/Tool/icc.py @@ -33,7 +33,7 @@ selection method. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import cc +from . import cc def generate(env): """Add Builders and construction variables for the OS/2 to an Environment.""" diff --git a/src/engine/SCons/Tool/ifl.py b/src/engine/SCons/Tool/ifl.py index 30b3672..865d2ba 100644 --- a/src/engine/SCons/Tool/ifl.py +++ b/src/engine/SCons/Tool/ifl.py @@ -35,7 +35,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Defaults from SCons.Scanner.Fortran import FortranScan -from FortranCommon import add_all_to_env +from .FortranCommon import add_all_to_env def generate(env): """Add Builders and construction variables for ifl to an Environment.""" diff --git a/src/engine/SCons/Tool/ifort.py b/src/engine/SCons/Tool/ifort.py index 4b2fd65..638bd12 100644 --- a/src/engine/SCons/Tool/ifort.py +++ b/src/engine/SCons/Tool/ifort.py @@ -36,7 +36,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Defaults from SCons.Scanner.Fortran import FortranScan -from FortranCommon import add_all_to_env +from .FortranCommon import add_all_to_env def generate(env): """Add Builders and construction variables for ifort to an Environment.""" diff --git a/src/engine/SCons/Tool/install.py b/src/engine/SCons/Tool/install.py index 0c81d05..4236e81 100644 --- a/src/engine/SCons/Tool/install.py +++ b/src/engine/SCons/Tool/install.py @@ -82,21 +82,21 @@ def scons_copytree(src, dst, symlinks=False): else: shutil.copy2(srcname, dstname) # XXX What about devices, sockets etc.? - except (IOError, os.error), why: + except (IOError, os.error) as why: errors.append((srcname, dstname, str(why))) # catch the CopytreeError from the recursive copytree so that we can # continue with other files - except CopytreeError, err: + except CopytreeError as err: errors.extend(err.args[0]) try: shutil.copystat(src, dst) except WindowsError: # can't copy file access times on Windows pass - except OSError, why: + except OSError as why: errors.extend((src, dst, str(why))) if errors: - raise CopytreeError, errors + raise CopytreeError(errors) # @@ -174,7 +174,7 @@ def versionedLibVersion(dest, env): version_File = version_re.findall(versioned_re.findall(libname)[-1])[-1] if Verbose: - print "install: version_File ", version_File + print("install: version_File ", version_File) # result is False if we did not find a versioned shared library name, so return and empty list if not result: return (None, libname, install_dir) @@ -188,7 +188,7 @@ def versionedLibVersion(dest, env): if version != version_File: #raise SCons.Errors.UserError("SHLIBVERSION '%s' does not match the version # '%s' in the filename" % (version, version_File) ) - print "SHLIBVERSION '%s' does not match the version # '%s' in the filename, proceeding based on file name" % (version, version_File) + print("SHLIBVERSION '%s' does not match the version # '%s' in the filename, proceeding based on file name" % (version, version_File)) version = version_File return (version, libname, install_dir) @@ -202,7 +202,7 @@ def versionedLibLinks(dest, source, env): # libname includes the version number if one was given linknames = SCons.Tool.VersionShLibLinkNames(version,libname,env) if Verbose: - print "versionedLibLinks: linknames ",linknames + print("versionedLibLinks: linknames ",linknames) # Here we just need the file name w/o path as the target of the link lib_ver = libname # make symlink of adjacent names in linknames @@ -210,7 +210,7 @@ def versionedLibLinks(dest, source, env): linkname = linknames[count] fulllinkname = os.path.join(install_dir, linkname) if Verbose: - print "full link name ",fulllinkname + print("full link name ",fulllinkname) if count > 0: try: os.remove(lastlinkname) @@ -218,7 +218,7 @@ def versionedLibLinks(dest, source, env): pass os.symlink(os.path.basename(fulllinkname),lastlinkname) if Verbose: - print "versionedLibLinks: made sym link of %s -> %s" % (lastlinkname,os.path.basename(fulllinkname)) + print("versionedLibLinks: made sym link of %s -> %s" % (lastlinkname,os.path.basename(fulllinkname))) lastlinkname = fulllinkname # finish chain of sym links with link to the actual library if len(linknames)>0: @@ -228,7 +228,7 @@ def versionedLibLinks(dest, source, env): pass os.symlink(lib_ver,lastlinkname) if Verbose: - print "versionedLibLinks: made sym link of %s -> %s" % (lib_ver,lastlinkname) + print("versionedLibLinks: made sym link of %s -> %s" % (lib_ver,lastlinkname)) return def installFunc(target, source, env): @@ -298,7 +298,7 @@ def add_versioned_targets_to_INSTALLED_FILES(target, source, env): Verbose = False _INSTALLED_FILES.extend(target) if Verbose: - print "ver lib emitter ",repr(target) + print("ver lib emitter ",repr(target)) # see if we have a versioned shared library, if so generate side effects version, libname, install_dir = versionedLibVersion(target[0].path, env) @@ -307,13 +307,13 @@ def add_versioned_targets_to_INSTALLED_FILES(target, source, env): linknames = SCons.Tool.VersionShLibLinkNames(version,libname,env) for linkname in linknames: if Verbose: - print "make side effect of %s" % os.path.join(install_dir, linkname) + print("make side effect of %s" % os.path.join(install_dir, linkname)) fulllinkname = os.path.join(install_dir, linkname) env.SideEffect(fulllinkname,target[0]) env.Clean(target[0],fulllinkname) _INSTALLED_FILES.append(fulllinkname) if Verbose: - print "installed list ", _INSTALLED_FILES + print("installed list ", _INSTALLED_FILES) _UNIQUE_INSTALLED_FILES = None return (target, source) diff --git a/src/engine/SCons/Tool/intelc.py b/src/engine/SCons/Tool/intelc.py index 4201092..8b178a7 100644 --- a/src/engine/SCons/Tool/intelc.py +++ b/src/engine/SCons/Tool/intelc.py @@ -30,7 +30,7 @@ selection method. # 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 + __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -206,17 +206,16 @@ def get_all_compiler_versions(): # Registry points to nonexistent dir. Ignore this # version. value = get_intel_registry_value('ProductDir', subkey, 'IA32') - except MissingRegistryError, e: + except MissingRegistryError as e: # Registry key is left dangling (potentially # after uninstalling). - print \ - "scons: *** Ignoring the registry key for the Intel compiler version %s.\n" \ + print("scons: *** Ignoring the registry key for the Intel compiler version %s.\n" \ "scons: *** It seems that the compiler was uninstalled and that the registry\n" \ - "scons: *** was not cleaned up properly.\n" % subkey + "scons: *** was not cleaned up properly.\n" % subkey) else: - print "scons: *** Ignoring "+str(value) + print("scons: *** Ignoring "+str(value)) i = i + 1 except EnvironmentError: @@ -424,8 +423,8 @@ def generate(env, version=None, abi=None, topdir=None, verbose=0): bindir="bin" libdir="lib" if verbose: - print "Intel C compiler: using version %s (%g), abi %s, in '%s/%s'"%\ - (repr(version), linux_ver_normalize(version),abi,topdir,bindir) + print("Intel C compiler: using version %s (%g), abi %s, in '%s/%s'"%\ + (repr(version), linux_ver_normalize(version),abi,topdir,bindir)) if is_linux: # Show the actual compiler version by running the compiler. os.system('%s/%s/icc --version'%(topdir,bindir)) @@ -439,14 +438,14 @@ def generate(env, version=None, abi=None, topdir=None, verbose=0): 'LIB' : libdir, 'PATH' : bindir, 'LD_LIBRARY_PATH' : libdir} - for p in paths.keys(): + for p in list(paths.keys()): env.PrependENVPath(p, os.path.join(topdir, paths[p])) if is_mac: paths={'INCLUDE' : 'include', 'LIB' : libdir, 'PATH' : bindir, 'LD_LIBRARY_PATH' : libdir} - for p in paths.keys(): + for p in list(paths.keys()): env.PrependENVPath(p, os.path.join(topdir, paths[p])) if is_windows: # env key reg valname default subdir of top diff --git a/src/engine/SCons/Tool/latex.py b/src/engine/SCons/Tool/latex.py index 1c71743..f30356b 100644 --- a/src/engine/SCons/Tool/latex.py +++ b/src/engine/SCons/Tool/latex.py @@ -55,10 +55,10 @@ def generate(env): env.AppendUnique(LATEXSUFFIXES=SCons.Tool.LaTeXSuffixes) - import dvi + from . import dvi dvi.generate(env) - import pdf + from . import pdf pdf.generate(env) bld = env['BUILDERS']['DVI'] diff --git a/src/engine/SCons/Tool/link.py b/src/engine/SCons/Tool/link.py index 3f20fe0..5539f62 100644 --- a/src/engine/SCons/Tool/link.py +++ b/src/engine/SCons/Tool/link.py @@ -81,7 +81,7 @@ def shlib_emitter(target, source, env): env.SideEffect(name, target[0]) env.Clean(target[0], name) if Verbose: - print "shlib_emitter: add side effect - ",name + print("shlib_emitter: add side effect - ",name) except KeyError: version = None return (target, source) @@ -104,16 +104,16 @@ def shlib_emitter_names(target, source, env): # generate library name with the version number version_name = target[0].name + '.' + version if Verbose: - print "shlib_emitter_names: target is ", version_name - print "shlib_emitter_names: side effect: ", name + print("shlib_emitter_names: target is ", version_name) + print("shlib_emitter_names: side effect: ", name) # add version_name to list of names to be a Side effect version_names.append(version_name) if Verbose: - print "shlib_emitter_names: versionparts ",versionparts + print("shlib_emitter_names: versionparts ",versionparts) for ver in versionparts[0:-1]: name = name + '.' + ver if Verbose: - print "shlib_emitter_names: side effect: ", name + print("shlib_emitter_names: side effect: ", name) # add name to list of names to be a Side effect version_names.append(name) elif platform == 'darwin': @@ -123,8 +123,8 @@ def shlib_emitter_names(target, source, env): suffix_re = re.escape(shlib_suffix) version_name = re.sub(suffix_re, '.' + version + shlib_suffix, name) if Verbose: - print "shlib_emitter_names: target is ", version_name - print "shlib_emitter_names: side effect: ", name + print("shlib_emitter_names: target is ", version_name) + print("shlib_emitter_names: side effect: ", name) # add version_name to list of names to be a Side effect version_names.append(version_name) elif platform == 'cygwin': @@ -134,8 +134,8 @@ def shlib_emitter_names(target, source, env): suffix_re = re.escape(shlib_suffix) version_name = re.sub(suffix_re, '-' + re.sub('\.', '-', version) + shlib_suffix, name) if Verbose: - print "shlib_emitter_names: target is ", version_name - print "shlib_emitter_names: side effect: ", name + print("shlib_emitter_names: target is ", version_name) + print("shlib_emitter_names: side effect: ", name) # add version_name to list of names to be a Side effect version_names.append(version_name) diff --git a/src/engine/SCons/Tool/midl.py b/src/engine/SCons/Tool/midl.py index 64b927a..7a59e33 100644 --- a/src/engine/SCons/Tool/midl.py +++ b/src/engine/SCons/Tool/midl.py @@ -39,7 +39,7 @@ import SCons.Defaults import SCons.Scanner.IDL import SCons.Util -from MSCommon import msvc_exists +from .MSCommon import msvc_exists def midl_emitter(target, source, env): """Produces a list of outputs from the MIDL compiler""" diff --git a/src/engine/SCons/Tool/msgfmt.py b/src/engine/SCons/Tool/msgfmt.py index 352ba77..4fe6afd 100644 --- a/src/engine/SCons/Tool/msgfmt.py +++ b/src/engine/SCons/Tool/msgfmt.py @@ -41,7 +41,7 @@ class _MOFileBuilder(BuilderBase): import SCons.Util from SCons.Tool.GettextCommon import _read_linguas_from_files linguas_files = None - if env.has_key('LINGUAS_FILE') and env['LINGUAS_FILE'] is not None: + if 'LINGUAS_FILE' in env and env['LINGUAS_FILE'] is not None: linguas_files = env['LINGUAS_FILE'] # This should prevent from endless recursion. env['LINGUAS_FILE'] = None diff --git a/src/engine/SCons/Tool/msginit.py b/src/engine/SCons/Tool/msginit.py index 5e9c0e4..39f460d 100644 --- a/src/engine/SCons/Tool/msginit.py +++ b/src/engine/SCons/Tool/msginit.py @@ -35,7 +35,7 @@ def _optional_no_translator_flag(env): """ Return '--no-translator' flag if we run *msginit(1)* in non-interactive mode.""" import SCons.Util - if env.has_key('POAUTOINIT'): + if 'POAUTOINIT' in env: autoinit = env['POAUTOINIT'] else: autoinit = False @@ -66,7 +66,7 @@ def _POInitBuilderWrapper(env, target=None, source=_null, **kw): if source is _null: if 'POTDOMAIN' in kw: domain = kw['POTDOMAIN'] - elif env.has_key('POTDOMAIN'): + elif 'POTDOMAIN' in env: domain = env['POTDOMAIN'] else: domain = 'messages' diff --git a/src/engine/SCons/Tool/msgmerge.py b/src/engine/SCons/Tool/msgmerge.py index f3710ab..11d7b48 100644 --- a/src/engine/SCons/Tool/msgmerge.py +++ b/src/engine/SCons/Tool/msgmerge.py @@ -58,7 +58,7 @@ def _POUpdateBuilderWrapper(env, target=None, source=_null, **kw): if source is _null: if 'POTDOMAIN' in kw: domain = kw['POTDOMAIN'] - elif env.has_key('POTDOMAIN') and env['POTDOMAIN']: + elif 'POTDOMAIN' in env and env['POTDOMAIN']: domain = env['POTDOMAIN'] else: domain = 'messages' diff --git a/src/engine/SCons/Tool/mslib.py b/src/engine/SCons/Tool/mslib.py index 8a4af57..df8d877 100644 --- a/src/engine/SCons/Tool/mslib.py +++ b/src/engine/SCons/Tool/mslib.py @@ -39,7 +39,7 @@ import SCons.Tool.msvs import SCons.Tool.msvc import SCons.Util -from MSCommon import msvc_exists, msvc_setup_env_once +from .MSCommon import msvc_exists, msvc_setup_env_once def generate(env): """Add Builders and construction variables for lib to an Environment.""" diff --git a/src/engine/SCons/Tool/mslink.py b/src/engine/SCons/Tool/mslink.py index 40f112b..b56d34a 100644 --- a/src/engine/SCons/Tool/mslink.py +++ b/src/engine/SCons/Tool/mslink.py @@ -44,7 +44,7 @@ import SCons.Tool.msvc import SCons.Tool.msvs import SCons.Util -from MSCommon import msvc_setup_env_once, msvc_exists +from .MSCommon import msvc_setup_env_once, msvc_exists def pdbGenerator(env, target, source, for_signature): try: @@ -195,7 +195,7 @@ def RegServerFunc(target, source, env): if ret: raise SCons.Errors.UserError("Unable to register %s" % target[0]) else: - print "Registered %s sucessfully" % target[0] + print("Registered %s sucessfully" % target[0]) return ret return 0 @@ -212,10 +212,10 @@ def embedManifestDllCheck(target, source, env): if os.path.exists(manifestSrc): ret = (embedManifestDllAction) ([target[0]],None,env) if ret: - raise SCons.Errors.UserError, "Unable to embed manifest into %s" % (target[0]) + raise SCons.Errors.UserError("Unable to embed manifest into %s" % (target[0])) return ret else: - print '(embed: no %s.manifest found; not embedding.)'%str(target[0]) + print('(embed: no %s.manifest found; not embedding.)'%str(target[0])) return 0 def embedManifestExeCheck(target, source, env): @@ -226,10 +226,10 @@ def embedManifestExeCheck(target, source, env): if os.path.exists(manifestSrc): ret = (embedManifestExeAction) ([target[0]],None,env) if ret: - raise SCons.Errors.UserError, "Unable to embed manifest into %s" % (target[0]) + raise SCons.Errors.UserError("Unable to embed manifest into %s" % (target[0])) return ret else: - print '(embed: no %s.manifest found; not embedding.)'%str(target[0]) + print('(embed: no %s.manifest found; not embedding.)'%str(target[0])) return 0 embedManifestDllCheckAction = SCons.Action.Action(embedManifestDllCheck, None) diff --git a/src/engine/SCons/Tool/mssdk.py b/src/engine/SCons/Tool/mssdk.py index 6103f30..f373002 100644 --- a/src/engine/SCons/Tool/mssdk.py +++ b/src/engine/SCons/Tool/mssdk.py @@ -33,7 +33,7 @@ It will usually be imported through the generic SCons.Tool.Tool() selection method. """ -from MSCommon import mssdk_exists, \ +from .MSCommon import mssdk_exists, \ mssdk_setup_env def generate(env): diff --git a/src/engine/SCons/Tool/msvc.py b/src/engine/SCons/Tool/msvc.py index d42c257..0bc296f 100644 --- a/src/engine/SCons/Tool/msvc.py +++ b/src/engine/SCons/Tool/msvc.py @@ -47,7 +47,7 @@ import SCons.Util import SCons.Warnings import SCons.Scanner.RC -from MSCommon import msvc_exists, msvc_setup_env_once +from .MSCommon import msvc_exists, msvc_setup_env_once CSuffixes = ['.c', '.C'] CXXSuffixes = ['.cc', '.cpp', '.cxx', '.c++', '.C++'] diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py index 06ce486..0879a28 100644 --- a/src/engine/SCons/Tool/msvs.py +++ b/src/engine/SCons/Tool/msvs.py @@ -51,7 +51,7 @@ import SCons.PathList import SCons.Util import SCons.Warnings -from MSCommon import msvc_exists, msvc_setup_env_once +from .MSCommon import msvc_exists, msvc_setup_env_once from SCons.Defaults import processDefines ############################################################################## @@ -351,13 +351,13 @@ class _DSPGenerator(object): config.platform = 'Win32' self.configs[variant] = config - print "Adding '" + self.name + ' - ' + config.variant + '|' + config.platform + "' to '" + str(dspfile) + "'" + print("Adding '" + self.name + ' - ' + config.variant + '|' + config.platform + "' to '" + str(dspfile) + "'") for i in range(len(variants)): AddConfig(self, variants[i], buildtarget[i], outdir[i], runfile[i], cmdargs) self.platforms = [] - for key in self.configs.keys(): + for key in list(self.configs.keys()): platform = self.configs[key].platform if not platform in self.platforms: self.platforms.append(platform) @@ -480,7 +480,7 @@ class _GenerateV6DSP(_DSPGenerator): 'Resource Files': 'r|rc|ico|cur|bmp|dlg|rc2|rct|bin|cnt|rtf|gif|jpg|jpeg|jpe', 'Other Files': ''} - for kind in sorted(categories.keys(), key=lambda a: a.lower()): + for kind in sorted(list(categories.keys()), key=lambda a: a.lower()): if not self.sources[kind]: continue # skip empty groups @@ -551,7 +551,7 @@ class _GenerateV6DSP(_DSPGenerator): def Build(self): try: self.file = open(self.dspabs,'w') - except IOError, detail: + except IOError as detail: raise SCons.Errors.InternalError('Unable to open "' + self.dspabs + '" for writing:' + str(detail)) else: self.PrintHeader() @@ -744,7 +744,7 @@ class _GenerateV7DSP(_DSPGenerator): self.file.write(pdata + '-->\n') def printSources(self, hierarchy, commonprefix): - sorteditems = sorted(hierarchy.items(), key=lambda a: a[0].lower()) + sorteditems = sorted(list(hierarchy.items()), key=lambda a: a[0].lower()) # First folders, then files for key, value in sorteditems: @@ -774,7 +774,7 @@ class _GenerateV7DSP(_DSPGenerator): self.file.write('\t\n') - cats = sorted([k for k in categories.keys() if self.sources[k]], + cats = sorted([k for k in list(categories.keys()) if self.sources[k]], key=lambda a: a.lower()) for kind in cats: if len(cats) > 1: @@ -861,7 +861,7 @@ class _GenerateV7DSP(_DSPGenerator): def Build(self): try: self.file = open(self.dspabs,'w') - except IOError, detail: + except IOError as detail: raise SCons.Errors.InternalError('Unable to open "' + self.dspabs + '" for writing:' + str(detail)) else: self.PrintHeader() @@ -1029,7 +1029,7 @@ class _GenerateV10DSP(_DSPGenerator): self.filtersabs = self.dspabs + '.filters' try: self.filters_file = open(self.filtersabs, 'w') - except IOError, detail: + except IOError as detail: raise SCons.Errors.InternalError('Unable to open "' + self.filtersabs + '" for writing:' + str(detail)) self.filters_file.write('\n' @@ -1055,7 +1055,7 @@ class _GenerateV10DSP(_DSPGenerator): self.file.write(pdata + '-->\n') def printFilters(self, hierarchy, name): - sorteditems = sorted(hierarchy.items(), key = lambda a: a[0].lower()) + sorteditems = sorted(list(hierarchy.items()), key = lambda a: a[0].lower()) for key, value in sorteditems: if SCons.Util.is_Dict(value): @@ -1072,7 +1072,7 @@ class _GenerateV10DSP(_DSPGenerator): 'Resource Files': 'None', 'Other Files': 'None'} - sorteditems = sorted(hierarchy.items(), key = lambda a: a[0].lower()) + sorteditems = sorted(list(hierarchy.items()), key = lambda a: a[0].lower()) # First folders, then files for key, value in sorteditems: @@ -1098,7 +1098,7 @@ class _GenerateV10DSP(_DSPGenerator): 'Resource Files': 'r;rc;ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe', 'Other Files': ''} - cats = sorted([k for k in categories.keys() if self.sources[k]], + cats = sorted([k for k in list(categories.keys()) if self.sources[k]], key = lambda a: a.lower()) # print vcxproj.filters file first @@ -1158,12 +1158,12 @@ class _GenerateV10DSP(_DSPGenerator): '\t\n' % str(self.sconscript)) def Parse(self): - print "_GenerateV10DSP.Parse()" + print("_GenerateV10DSP.Parse()") def Build(self): try: self.file = open(self.dspabs, 'w') - except IOError, detail: + except IOError as detail: raise SCons.Errors.InternalError('Unable to open "' + self.dspabs + '" for writing:' + str(detail)) else: self.PrintHeader() @@ -1242,7 +1242,7 @@ class _GenerateV7DSW(_DSWGenerator): config.platform = 'Win32' self.configs[variant] = config - print "Adding '" + self.name + ' - ' + config.variant + '|' + config.platform + "' to '" + str(dswfile) + "'" + print("Adding '" + self.name + ' - ' + config.variant + '|' + config.platform + "' to '" + str(dswfile) + "'") if 'variant' not in env: raise SCons.Errors.InternalError("You must specify a 'variant' argument (i.e. 'Debug' or " +\ @@ -1254,7 +1254,7 @@ class _GenerateV7DSW(_DSWGenerator): AddConfig(self, variant) self.platforms = [] - for key in self.configs.keys(): + for key in list(self.configs.keys()): platform = self.configs[key].platform if not platform in self.platforms: self.platforms.append(platform) @@ -1424,7 +1424,7 @@ class _GenerateV7DSW(_DSWGenerator): def Build(self): try: self.file = open(self.dswfile,'w') - except IOError, detail: + except IOError as detail: raise SCons.Errors.InternalError('Unable to open "' + self.dswfile + '" for writing:' + str(detail)) else: self.PrintSolution() @@ -1473,7 +1473,7 @@ class _GenerateV6DSW(_DSWGenerator): def Build(self): try: self.file = open(self.dswfile,'w') - except IOError, detail: + except IOError as detail: raise SCons.Errors.InternalError('Unable to open "' + self.dswfile + '" for writing:' + str(detail)) else: self.PrintWorkspace() @@ -1530,8 +1530,8 @@ def GenerateProject(target, source, env): if not dspfile is builddspfile: try: bdsp = open(str(builddspfile), "w+") - except IOError, detail: - print 'Unable to open "' + str(dspfile) + '" for writing:',detail,'\n' + except IOError as detail: + print('Unable to open "' + str(dspfile) + '" for writing:',detail,'\n') raise bdsp.write("This is just a placeholder file.\nThe real project file is here:\n%s\n" % dspfile.get_abspath()) @@ -1546,8 +1546,8 @@ def GenerateProject(target, source, env): try: bdsw = open(str(builddswfile), "w+") - except IOError, detail: - print 'Unable to open "' + str(dspfile) + '" for writing:',detail,'\n' + except IOError as detail: + print('Unable to open "' + str(dspfile) + '" for writing:',detail,'\n') raise bdsw.write("This is just a placeholder file.\nThe real workspace file is here:\n%s\n" % dswfile.get_abspath()) diff --git a/src/engine/SCons/Tool/msvsTests.py b/src/engine/SCons/Tool/msvsTests.py index 7d966c1..1466db6 100644 --- a/src/engine/SCons/Tool/msvsTests.py +++ b/src/engine/SCons/Tool/msvsTests.py @@ -743,7 +743,7 @@ if __name__ == "__main__": ] for test_class in test_classes: - print "TEST: ", test_class.__doc__ + print("TEST: ", test_class.__doc__) back_osenv = copy.deepcopy(os.environ) try: # XXX: overriding the os.environ is bad, but doing it diff --git a/src/engine/SCons/Tool/packaging/__init__.py b/src/engine/SCons/Tool/packaging/__init__.py index 95311a2..c3de2aa 100644 --- a/src/engine/SCons/Tool/packaging/__init__.py +++ b/src/engine/SCons/Tool/packaging/__init__.py @@ -72,7 +72,7 @@ def Tag(env, target, source, *more_tags, **kw_tags): target=env.Flatten(target) for t in target: - for (k,v) in kw_tags.items(): + for (k,v) in list(kw_tags.items()): # all file tags have to start with PACKAGING_, so we can later # differentiate between "normal" object attributes and the # packaging attributes. As the user should not be bothered with @@ -120,7 +120,7 @@ def Package(env, target=None, source=None, **kw): try: file,path,desc=imp.find_module(type, __path__) return imp.load_module(type, file, path, desc) - except ImportError, e: + except ImportError as e: raise EnvironmentError("packager %s not available: %s"%(type,str(e))) packagers=list(map(load_packager, PACKAGETYPE)) @@ -141,7 +141,7 @@ def Package(env, target=None, source=None, **kw): if 'PACKAGEROOT' not in kw: kw['PACKAGEROOT'] = default_name%kw - except KeyError, e: + except KeyError as e: raise SCons.Errors.UserError( "Missing Packagetag '%s'"%e.args[0] ) # setup the source files @@ -157,10 +157,10 @@ def Package(env, target=None, source=None, **kw): assert( len(target) == 0 ) - except KeyError, e: + except KeyError as e: raise SCons.Errors.UserError( "Missing Packagetag '%s' for %s packager"\ % (e.args[0],packager.__name__) ) - except TypeError, e: + except TypeError as e: # this exception means that a needed argument for the packager is # missing. As our packagers get their "tags" as named function # arguments we need to find out which one is missing. diff --git a/src/engine/SCons/Tool/packaging/ipk.py b/src/engine/SCons/Tool/packaging/ipk.py index 6549445..ad27a62 100644 --- a/src/engine/SCons/Tool/packaging/ipk.py +++ b/src/engine/SCons/Tool/packaging/ipk.py @@ -169,7 +169,7 @@ Description: $X_IPK_DESCRIPTION # # close all opened files - for f in opened_files.values(): + for f in list(opened_files.values()): f.close() # call a user specified function diff --git a/src/engine/SCons/Tool/packaging/msi.py b/src/engine/SCons/Tool/packaging/msi.py index fe78c9c..70fdc48 100644 --- a/src/engine/SCons/Tool/packaging/msi.py +++ b/src/engine/SCons/Tool/packaging/msi.py @@ -172,7 +172,7 @@ def generate_guids(root): # find all XMl nodes matching the key, retrieve their attribute, hash their # subtree, convert hash to string and add as a attribute to the xml node. - for (key,value) in needs_id.items(): + for (key,value) in list(needs_id.items()): node_list = root.getElementsByTagName(key) attribute = value for node in node_list: @@ -216,7 +216,7 @@ def build_wxsfile(target, source, env): if 'CHANGE_SPECFILE' in env: env['CHANGE_SPECFILE'](target, source) - except KeyError, e: + except KeyError as e: raise SCons.Errors.UserError( '"%s" package field for MSI is missing.' % e.args[0] ) # @@ -335,7 +335,7 @@ def build_wxsfile_file_section(root, files, NAME, VERSION, VENDOR, filename_set, } # fill in the default tags given above. - for k,v in [ (k, v) for (k,v) in h.items() if not hasattr(file, k) ]: + for k,v in [ (k, v) for (k,v) in list(h.items()) if not hasattr(file, k) ]: setattr( file, k, v ) File = factory.createElement( 'File' ) @@ -382,7 +382,7 @@ def build_wxsfile_features_section(root, files, NAME, VERSION, SUMMARY, id_set): Feature.attributes['Description'] = escape( SUMMARY ) Feature.attributes['Display'] = 'expand' - for (feature, files) in create_feature_dict(files).items(): + for (feature, files) in list(create_feature_dict(files).items()): SubFeature = factory.createElement('Feature') SubFeature.attributes['Level'] = '1' diff --git a/src/engine/SCons/Tool/packaging/rpm.py b/src/engine/SCons/Tool/packaging/rpm.py index 07857d1..4958065 100644 --- a/src/engine/SCons/Tool/packaging/rpm.py +++ b/src/engine/SCons/Tool/packaging/rpm.py @@ -107,7 +107,7 @@ def collectintargz(target, source, env): try: #tarball = env['SOURCE_URL'].split('/')[-1] tarball = env['SOURCE_URL'].split('/')[-1] - except KeyError, e: + except KeyError as e: raise SCons.Errors.UserError( "Missing PackageTag '%s' for RPM packager" % e.args[0] ) tarball = src_targz.package(env, source=sources, target=tarball, @@ -143,7 +143,7 @@ def build_specfile(target, source, env): if 'CHANGE_SPECFILE' in env: env['CHANGE_SPECFILE'](target, source) - except KeyError, e: + except KeyError as e: raise SCons.Errors.UserError( '"%s" package field for RPM is missing.' % e.args[0] ) @@ -277,7 +277,7 @@ def build_specfile_filesection(spec, files): for file in files: # build the tagset tags = {} - for k in supported_tags.keys(): + for k in list(supported_tags.keys()): try: tags[k]=getattr(file, k) except AttributeError: @@ -331,7 +331,7 @@ class SimpleTagCompiler(object): for key, replacement in domestic: try: str = str + replacement % values[key] - except KeyError, e: + except KeyError as e: if self.mandatory: raise e @@ -340,11 +340,11 @@ class SimpleTagCompiler(object): for key, replacement in international: try: #int_values_for_key = [ (get_country_code(k),v) for k,v in values.items() if strip_country_code(k) == key ] - x = [t for t in values.items() if strip_country_code(t[0]) == key] + x = [t for t in list(values.items()) if strip_country_code(t[0]) == key] int_values_for_key = [(get_country_code(t[0]),t[1]) for t in x] for v in int_values_for_key: str = str + replacement % v - except KeyError, e: + except KeyError as e: if self.mandatory: raise e diff --git a/src/engine/SCons/Tool/pdflatex.py b/src/engine/SCons/Tool/pdflatex.py index 922e718..fbffb23 100644 --- a/src/engine/SCons/Tool/pdflatex.py +++ b/src/engine/SCons/Tool/pdflatex.py @@ -62,7 +62,7 @@ def generate(env): env.AppendUnique(LATEXSUFFIXES=SCons.Tool.LaTeXSuffixes) - import pdf + from . import pdf pdf.generate(env) bld = env['BUILDERS']['PDF'] diff --git a/src/engine/SCons/Tool/pdftex.py b/src/engine/SCons/Tool/pdftex.py index 30c56af..e9a0bda 100644 --- a/src/engine/SCons/Tool/pdftex.py +++ b/src/engine/SCons/Tool/pdftex.py @@ -85,7 +85,7 @@ def generate(env): env.AppendUnique(LATEXSUFFIXES=SCons.Tool.LaTeXSuffixes) - import pdf + from . import pdf pdf.generate(env) bld = env['BUILDERS']['PDF'] diff --git a/src/engine/SCons/Tool/qt.py b/src/engine/SCons/Tool/qt.py index 716c7d5..fdfdd26 100644 --- a/src/engine/SCons/Tool/qt.py +++ b/src/engine/SCons/Tool/qt.py @@ -130,12 +130,12 @@ class _Automoc(object): if not obj.has_builder(): # binary obj file provided if debug: - print "scons: qt: '%s' seems to be a binary. Discarded." % str(obj) + print("scons: qt: '%s' seems to be a binary. Discarded." % str(obj)) continue cpp = obj.sources[0] if not splitext(str(cpp))[1] in cxx_suffixes: if debug: - print "scons: qt: '%s' is no cxx file. Discarded." % str(cpp) + print("scons: qt: '%s' is no cxx file. Discarded." % str(cpp)) # c or fortran source continue #cpp_contents = comment.sub('', cpp.get_text_contents()) @@ -148,12 +148,12 @@ class _Automoc(object): h = find_file(hname, (cpp.get_dir(),), env.File) if h: if debug: - print "scons: qt: Scanning '%s' (header of '%s')" % (str(h), str(cpp)) + print("scons: qt: Scanning '%s' (header of '%s')" % (str(h), str(cpp))) #h_contents = comment.sub('', h.get_text_contents()) h_contents = h.get_text_contents() break if not h and debug: - print "scons: qt: no header for '%s'." % (str(cpp)) + print("scons: qt: no header for '%s'." % (str(cpp))) if h and q_object_search.search(h_contents): # h file with the Q_OBJECT macro found -> add moc_cpp moc_cpp = env.Moc(h) @@ -161,14 +161,14 @@ class _Automoc(object): out_sources.append(moc_o) #moc_cpp.target_scanner = SCons.Defaults.CScan if debug: - print "scons: qt: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(h), str(moc_cpp)) + print("scons: qt: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(h), str(moc_cpp))) if cpp and q_object_search.search(cpp_contents): # cpp file with Q_OBJECT macro found -> add moc # (to be included in cpp) moc = env.Moc(cpp) env.Ignore(moc, moc) if debug: - print "scons: qt: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(cpp), str(moc)) + print("scons: qt: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(cpp), str(moc))) #moc.source_scanner = SCons.Defaults.CScan # restore the original env attributes (FIXME) objBuilder.env = objBuilderEnv diff --git a/src/engine/SCons/Tool/rpmutils.py b/src/engine/SCons/Tool/rpmutils.py index 90e3d74..e96c54c 100644 --- a/src/engine/SCons/Tool/rpmutils.py +++ b/src/engine/SCons/Tool/rpmutils.py @@ -491,7 +491,7 @@ def updateRpmDicts(rpmrc, pyfile): key = tokens[0] if key in sections: # Have we met this section before? - if not data.has_key(tokens[0]): + if tokens[0] not in data: # No, so insert it data[key] = {} # Insert data @@ -509,7 +509,7 @@ def updateRpmDicts(rpmrc, pyfile): if l.startswith('# Start of rpmrc dictionaries'): pm = 1 # Write data sections to single dictionaries - for key, entries in data.iteritems(): + for key, entries in data.items(): out.write("%s = {\n" % key) for arch in sorted(entries.keys()): out.write(" '%s' : ['%s'],\n" % (arch, "','".join(entries[arch]))) @@ -519,7 +519,7 @@ def updateRpmDicts(rpmrc, pyfile): pass def usage(): - print "rpmutils.py rpmrc.in rpmutils.py" + print("rpmutils.py rpmrc.in rpmutils.py") def main(): import sys diff --git a/src/engine/SCons/Tool/sgicc.py b/src/engine/SCons/Tool/sgicc.py index 662eb7d..94a0497 100644 --- a/src/engine/SCons/Tool/sgicc.py +++ b/src/engine/SCons/Tool/sgicc.py @@ -33,7 +33,7 @@ selection method. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import cc +from . import cc def generate(env): """Add Builders and construction variables for gcc to an Environment.""" diff --git a/src/engine/SCons/Tool/sgilink.py b/src/engine/SCons/Tool/sgilink.py index 6244141..b1e7921 100644 --- a/src/engine/SCons/Tool/sgilink.py +++ b/src/engine/SCons/Tool/sgilink.py @@ -35,7 +35,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Util -import link +from . import link linkers = ['CC', 'cc'] diff --git a/src/engine/SCons/Tool/suncc.py b/src/engine/SCons/Tool/suncc.py index 458538b..4651219 100644 --- a/src/engine/SCons/Tool/suncc.py +++ b/src/engine/SCons/Tool/suncc.py @@ -34,7 +34,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Util -import cc +from . import cc def generate(env): """ diff --git a/src/engine/SCons/Tool/sunf77.py b/src/engine/SCons/Tool/sunf77.py index d05ce54..20d1893 100644 --- a/src/engine/SCons/Tool/sunf77.py +++ b/src/engine/SCons/Tool/sunf77.py @@ -35,7 +35,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Util -from FortranCommon import add_all_to_env +from .FortranCommon import add_all_to_env compilers = ['sunf77', 'f77'] diff --git a/src/engine/SCons/Tool/sunf90.py b/src/engine/SCons/Tool/sunf90.py index 93b89c0..ce1697c 100644 --- a/src/engine/SCons/Tool/sunf90.py +++ b/src/engine/SCons/Tool/sunf90.py @@ -35,7 +35,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Util -from FortranCommon import add_all_to_env +from .FortranCommon import add_all_to_env compilers = ['sunf90', 'f90'] diff --git a/src/engine/SCons/Tool/sunf95.py b/src/engine/SCons/Tool/sunf95.py index c09026c..218569c 100644 --- a/src/engine/SCons/Tool/sunf95.py +++ b/src/engine/SCons/Tool/sunf95.py @@ -35,7 +35,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Util -from FortranCommon import add_all_to_env +from .FortranCommon import add_all_to_env compilers = ['sunf95', 'f95'] diff --git a/src/engine/SCons/Tool/sunlink.py b/src/engine/SCons/Tool/sunlink.py index 5996a30..af13392 100644 --- a/src/engine/SCons/Tool/sunlink.py +++ b/src/engine/SCons/Tool/sunlink.py @@ -37,7 +37,7 @@ import os.path import SCons.Util -import link +from . import link ccLinker = None diff --git a/src/engine/SCons/Tool/tex.py b/src/engine/SCons/Tool/tex.py index 5f24df0..febec35 100644 --- a/src/engine/SCons/Tool/tex.py +++ b/src/engine/SCons/Tool/tex.py @@ -163,15 +163,15 @@ def FindFile(name,suffixes,paths,env,requireExt=False): if ext: name = name + ext if Verbose: - print " searching for '%s' with extensions: " % name,suffixes + print(" searching for '%s' with extensions: " % name,suffixes) for path in paths: testName = os.path.join(path,name) if Verbose: - print " look for '%s'" % testName + print(" look for '%s'" % testName) if os.path.isfile(testName): if Verbose: - print " found '%s'" % testName + print(" found '%s'" % testName) return env.fs.File(testName) else: name_ext = SCons.Util.splitext(testName)[1] @@ -182,14 +182,14 @@ def FindFile(name,suffixes,paths,env,requireExt=False): for suffix in suffixes: testNameExt = testName + suffix if Verbose: - print " look for '%s'" % testNameExt + print(" look for '%s'" % testNameExt) if os.path.isfile(testNameExt): if Verbose: - print " found '%s'" % testNameExt + print(" found '%s'" % testNameExt) return env.fs.File(testNameExt) if Verbose: - print " did not find '%s'" % name + print(" did not find '%s'" % name) return None def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None): @@ -249,7 +249,7 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None saved_hashes[suffix] = theNode.get_csig() if Verbose: - print "hashes: ",saved_hashes + print("hashes: ",saved_hashes) must_rerun_latex = True @@ -268,12 +268,12 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None if saved_hashes[suffix] == new_md5: if Verbose: - print "file %s not changed" % (targetbase+suffix) + print("file %s not changed" % (targetbase+suffix)) return False # unchanged saved_hashes[suffix] = new_md5 must_rerun_latex = True if Verbose: - print "file %s changed, rerunning Latex, new hash = " % (targetbase+suffix), new_md5 + print("file %s changed, rerunning Latex, new hash = " % (targetbase+suffix), new_md5) return True # changed # generate the file name that latex will generate @@ -322,8 +322,8 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None bcffiles = list(dups.keys()) if Verbose: - print "auxfiles ",auxfiles - print "bcffiles ",bcffiles + print("auxfiles ",auxfiles) + print("bcffiles ",bcffiles) # Now decide if bibtex will need to be run. # The information that bibtex reads from the .aux file is @@ -339,7 +339,7 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None content = open(target_aux, "rb").read() if content.find("bibdata") != -1: if Verbose: - print "Need to run bibtex on ",auxfilename + print("Need to run bibtex on ",auxfilename) bibfile = env.fs.File(SCons.Util.splitext(target_aux)[0]) result = BibTeXAction(bibfile, bibfile, env) if result != 0: @@ -362,7 +362,7 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None content = open(target_bcf, "rb").read() if content.find("bibdata") != -1: if Verbose: - print "Need to run biber on ",bcffilename + print("Need to run biber on ",bcffilename) bibfile = env.fs.File(SCons.Util.splitext(target_bcf)[0]) result = BiberAction(bibfile, bibfile, env) if result != 0: @@ -373,7 +373,7 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None if check_MD5(suffix_nodes['.idx'],'.idx') or (count == 1 and run_makeindex): # We must run makeindex if Verbose: - print "Need to run makeindex" + print("Need to run makeindex") idxfile = suffix_nodes['.idx'] result = MakeIndexAction(idxfile, idxfile, env) if result != 0: @@ -391,7 +391,7 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None if check_MD5(suffix_nodes['.nlo'],'.nlo') or (count == 1 and run_nomenclature): # We must run makeindex if Verbose: - print "Need to run makeindex for nomenclature" + print("Need to run makeindex for nomenclature") nclfile = suffix_nodes['.nlo'] result = MakeNclAction(nclfile, nclfile, env) if result != 0: @@ -403,7 +403,7 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None if check_MD5(suffix_nodes['.glo'],'.glo') or (count == 1 and run_glossaries) or (count == 1 and run_glossary): # We must run makeindex if Verbose: - print "Need to run makeindex for glossary" + print("Need to run makeindex for glossary") glofile = suffix_nodes['.glo'] result = MakeGlossaryAction(glofile, glofile, env) if result != 0: @@ -415,7 +415,7 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None if check_MD5(suffix_nodes['.acn'],'.acn') or (count == 1 and run_acronyms): # We must run makeindex if Verbose: - print "Need to run makeindex for acronyms" + print("Need to run makeindex for acronyms") acrfile = suffix_nodes['.acn'] result = MakeAcronymsAction(acrfile, acrfile, env) if result != 0: @@ -428,7 +428,7 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None if check_MD5(suffix_nodes[newglossary_suffix[ig][2]],newglossary_suffix[ig][2]) or (count == 1): # We must run makeindex if Verbose: - print "Need to run makeindex for newglossary" + print("Need to run makeindex for newglossary") newglfile = suffix_nodes[newglossary_suffix[ig][2]] MakeNewGlossaryAction = SCons.Action.Action("$MAKENEWGLOSSARY ${SOURCE.filebase}%s -s ${SOURCE.filebase}.ist -t ${SOURCE.filebase}%s -o ${SOURCE.filebase}%s" % (newglossary_suffix[ig][2],newglossary_suffix[ig][0],newglossary_suffix[ig][1]), "$MAKENEWGLOSSARYCOMSTR") @@ -442,26 +442,26 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None if warning_rerun_re.search(logContent): must_rerun_latex = True if Verbose: - print "rerun Latex due to latex or package rerun warning" + print("rerun Latex due to latex or package rerun warning") if rerun_citations_re.search(logContent): must_rerun_latex = True if Verbose: - print "rerun Latex due to 'Rerun to get citations correct' warning" + print("rerun Latex due to 'Rerun to get citations correct' warning") if undefined_references_re.search(logContent): must_rerun_latex = True if Verbose: - print "rerun Latex due to undefined references or citations" + print("rerun Latex due to undefined references or citations") if (count >= int(env.subst('$LATEXRETRIES')) and must_rerun_latex): - print "reached max number of retries on Latex ,",int(env.subst('$LATEXRETRIES')) + print("reached max number of retries on Latex ,",int(env.subst('$LATEXRETRIES'))) # end of while loop # rename Latex's output to what the target name is if not (str(target[0]) == resultfilename and os.path.isfile(resultfilename)): if os.path.isfile(resultfilename): - print "move %s to %s" % (resultfilename, str(target[0]), ) + print("move %s to %s" % (resultfilename, str(target[0]), )) shutil.move(resultfilename,str(target[0])) # Original comment (when TEXPICTS was not restored): @@ -515,27 +515,27 @@ def is_LaTeX(flist,env,abspath): else: env['ENV']['TEXINPUTS'] = savedpath if Verbose: - print "is_LaTeX search path ",paths - print "files to search :",flist + print("is_LaTeX search path ",paths) + print("files to search :",flist) # Now that we have the search path and file list, check each one for f in flist: if Verbose: - print " checking for Latex source ",str(f) + print(" checking for Latex source ",str(f)) content = f.get_text_contents() if LaTeX_re.search(content): if Verbose: - print "file %s is a LaTeX file" % str(f) + print("file %s is a LaTeX file" % str(f)) return 1 if Verbose: - print "file %s is not a LaTeX file" % str(f) + print("file %s is not a LaTeX file" % str(f)) # now find included files inc_files = [ ] inc_files.extend( include_re.findall(content) ) if Verbose: - print "files included by '%s': "%str(f),inc_files + print("files included by '%s': "%str(f),inc_files) # inc_files is list of file names as given. need to find them # using TEXINPUTS paths. @@ -545,7 +545,7 @@ def is_LaTeX(flist,env,abspath): # make this a list since is_LaTeX takes a list. fileList = [srcNode,] if Verbose: - print "FindFile found ",srcNode + print("FindFile found ",srcNode) if srcNode is not None: file_test = is_LaTeX(fileList, env, abspath) @@ -554,7 +554,7 @@ def is_LaTeX(flist,env,abspath): return file_test if Verbose: - print " done scanning ",str(f) + print(" done scanning ",str(f)) return 0 @@ -619,15 +619,15 @@ def ScanFiles(theFile, target, paths, file_tests, file_tests_search, env, graphi content = theFile.get_text_contents() if Verbose: - print " scanning ",str(theFile) + print(" scanning ",str(theFile)) for i in range(len(file_tests_search)): if file_tests[i][0] is None: if Verbose: - print "scan i ",i," files_tests[i] ",file_tests[i], file_tests[i][1] + print("scan i ",i," files_tests[i] ",file_tests[i], file_tests[i][1]) file_tests[i][0] = file_tests_search[i].search(content) if Verbose and file_tests[i][0]: - print " found match for ",file_tests[i][1][-1] + print(" found match for ",file_tests[i][1][-1]) # for newglossary insert the suffixes in file_tests[i] if file_tests[i][0] and file_tests[i][1][-1] == 'newglossary': findresult = file_tests_search[i].findall(content) @@ -638,19 +638,19 @@ def ScanFiles(theFile, target, paths, file_tests, file_tests_search, env, graphi suffix_list = ['.'+findresult[l][0],'.'+findresult[l][2],'.'+findresult[l][3] ] newglossary_suffix.append(suffix_list) if Verbose: - print " new suffixes for newglossary ",newglossary_suffix + print(" new suffixes for newglossary ",newglossary_suffix) incResult = includeOnly_re.search(content) if incResult: aux_files.append(os.path.join(targetdir, incResult.group(1))) if Verbose: - print "\include file names : ", aux_files + print("\include file names : ", aux_files) # recursively call this on each of the included files inc_files = [ ] inc_files.extend( include_re.findall(content) ) if Verbose: - print "files included by '%s': "%str(theFile),inc_files + print("files included by '%s': "%str(theFile),inc_files) # inc_files is list of file names as given. need to find them # using TEXINPUTS paths. @@ -659,7 +659,7 @@ def ScanFiles(theFile, target, paths, file_tests, file_tests_search, env, graphi if srcNode is not None: file_tests = ScanFiles(srcNode, target, paths, file_tests, file_tests_search, env, graphics_extensions, targetdir, aux_files) if Verbose: - print " done scanning ",str(theFile) + print(" done scanning ",str(theFile)) return file_tests def tex_emitter_core(target, source, env, graphics_extensions): @@ -689,7 +689,7 @@ def tex_emitter_core(target, source, env, graphics_extensions): env.SideEffect(logfilename,target[0]) env.SideEffect(flsfilename,target[0]) if Verbose: - print "side effect :",auxfilename,logfilename,flsfilename + print("side effect :",auxfilename,logfilename,flsfilename) env.Clean(target[0],auxfilename) env.Clean(target[0],logfilename) env.Clean(target[0],flsfilename) @@ -765,7 +765,7 @@ def tex_emitter_core(target, source, env, graphics_extensions): else: env['ENV']['TEXINPUTS'] = savedpath if Verbose: - print "search path ",paths + print("search path ",paths) # scan all sources for side effect files aux_files = [] @@ -774,7 +774,7 @@ def tex_emitter_core(target, source, env, graphics_extensions): for (theSearch,suffix_list) in file_tests: # add side effects if feature is present.If file is to be generated,add all side effects if Verbose and theSearch: - print "check side effects for ",suffix_list[-1] + print("check side effects for ",suffix_list[-1]) if (theSearch != None) or (not source[0].exists() ): file_list = [targetbase,] # for bibunit we need a list of files @@ -788,11 +788,11 @@ def tex_emitter_core(target, source, env, graphics_extensions): if suffix_list[-1] == 'multibib': for multibibmatch in multibib_re.finditer(content): if Verbose: - print "multibib match ",multibibmatch.group(1) + print("multibib match ",multibibmatch.group(1)) if multibibmatch != None: baselist = multibibmatch.group(1).split(',') if Verbose: - print "multibib list ", baselist + print("multibib list ", baselist) for i in range(len(baselist)): file_list.append(os.path.join(targetdir, baselist[i])) # now define the side effects @@ -800,14 +800,14 @@ def tex_emitter_core(target, source, env, graphics_extensions): for suffix in suffix_list[:-1]: env.SideEffect(file_name + suffix,target[0]) if Verbose: - print "side effect tst :",file_name + suffix, " target is ",str(target[0]) + print("side effect tst :",file_name + suffix, " target is ",str(target[0])) env.Clean(target[0],file_name + suffix) for aFile in aux_files: aFile_base = SCons.Util.splitext(aFile)[0] env.SideEffect(aFile_base + '.aux',target[0]) if Verbose: - print "side effect aux :",aFile_base + '.aux' + print("side effect aux :",aFile_base + '.aux') env.Clean(target[0],aFile_base + '.aux') # read fls file to get all other files that latex creates and will read on the next pass # remove files from list that we explicitly dealt with above @@ -820,7 +820,7 @@ def tex_emitter_core(target, source, env, graphics_extensions): out_files.remove(filename) env.SideEffect(out_files,target[0]) if Verbose: - print "side effect fls :",out_files + print("side effect fls :",out_files) env.Clean(target[0],out_files) return (target, source) @@ -840,7 +840,7 @@ def generate(env): generate_common(env) - import dvi + from . import dvi dvi.generate(env) bld = env['BUILDERS']['DVI'] diff --git a/src/engine/SCons/Tool/textfile.py b/src/engine/SCons/Tool/textfile.py index 8dc8f4b..4897113 100644 --- a/src/engine/SCons/Tool/textfile.py +++ b/src/engine/SCons/Tool/textfile.py @@ -54,6 +54,7 @@ import re from SCons.Node import Node from SCons.Node.Python import Value from SCons.Util import is_String, is_Sequence, is_Dict +import collections def _do_subst(node, subs): """ @@ -96,7 +97,7 @@ def _action(target, source, env): raise SCons.Errors.UserError('SUBST_DICT must be dict or sequence') subs = [] for (k,v) in d: - if callable(v): + if isinstance(v, collections.Callable): v = v() if is_String(v): v = env.subst(v) @@ -107,7 +108,7 @@ def _action(target, source, env): # write the file try: fd = open(target[0].get_path(), "wb") - except (OSError,IOError), e: + except (OSError,IOError) as e: raise SCons.Errors.UserError("Can't write target file %s" % target[0]) # separate lines by 'linesep' only if linesep is not empty lsep = None diff --git a/src/engine/SCons/Tool/xgettext.py b/src/engine/SCons/Tool/xgettext.py index 64436b8..489d4d7 100644 --- a/src/engine/SCons/Tool/xgettext.py +++ b/src/engine/SCons/Tool/xgettext.py @@ -55,7 +55,7 @@ class _CmdRunner(object): proc = SCons.Action._subproc(env, command, **kw) self.out, self.err = proc.communicate() self.status = proc.wait() - if self.err: sys.stderr.write(unicode(self.err)) + if self.err: sys.stderr.write(str(self.err)) return self.status def strfunction(self, target, source, env): @@ -153,7 +153,7 @@ from SCons.Builder import BuilderBase class _POTBuilder(BuilderBase): def _execute(self, env, target, source, *args): if not target: - if env.has_key('POTDOMAIN') and env['POTDOMAIN']: + if 'POTDOMAIN' in env and env['POTDOMAIN']: domain = env['POTDOMAIN'] else: domain = 'messages' @@ -175,7 +175,7 @@ def _scan_xgettext_from_files(target, source, env, files = None, path = None): files = [ files ] if path is None: - if env.has_key('XGETTEXTPATH'): + if 'XGETTEXTPATH' in env: path = env['XGETTEXTPATH'] else: path = [] @@ -222,7 +222,7 @@ def _pot_update_emitter(target, source, env): import SCons.Util import SCons.Node.FS - if env.has_key('XGETTEXTFROM'): + if 'XGETTEXTFROM' in env: xfrom = env['XGETTEXTFROM'] else: return target, source diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 822d524..f2e5325 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -33,15 +33,16 @@ import re import types from collections import UserDict, UserList, UserString +import collections # Don't "from types import ..." these because we need to get at the # types module later to look for UnicodeType. InstanceType = types.InstanceType MethodType = types.MethodType FunctionType = types.FunctionType -try: unicode +try: str except NameError: UnicodeType = None -else: UnicodeType = unicode +else: UnicodeType = str def dictify(keys, values, result={}): for k, v in zip(keys, values): @@ -111,7 +112,7 @@ class NodeList(UserList): >>> someList.strip() [ 'foo', 'bar' ] """ - def __nonzero__(self): + def __bool__(self): return len(self.data) != 0 def __str__(self): @@ -153,7 +154,7 @@ class DisplayEngine(object): return if append_newline: text = text + '\n' try: - sys.stdout.write(unicode(text)) + sys.stdout.write(str(text)) except IOError: # Stdout might be connected to a pipe that has been closed # by now. The most likely reason for the pipe being closed @@ -239,7 +240,7 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited={}): ' N = no clean\n' + ' H = no cache\n' + '\n') - sys.stdout.write(unicode(legend)) + sys.stdout.write(str(legend)) tags = ['['] tags.append(' E'[IDX(root.exists())]) @@ -264,10 +265,10 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited={}): children = child_func(root) if prune and rname in visited and children: - sys.stdout.write(''.join(tags + margins + ['+-[', rname, ']']) + u'\n') + sys.stdout.write(''.join(tags + margins + ['+-[', rname, ']']) + '\n') return - sys.stdout.write(''.join(tags + margins + ['+-', rname]) + u'\n') + sys.stdout.write(''.join(tags + margins + ['+-', rname]) + '\n') visited[rname] = 1 @@ -303,11 +304,11 @@ SequenceTypes = (list, tuple, UserList) # Note that profiling data shows a speed-up when comparing # explicitely with str and unicode instead of simply comparing # with basestring. (at least on Python 2.5.1) -StringTypes = (str, unicode, UserString) +StringTypes = (str, str, UserString) # Empirically, it is faster to check explicitely for str and # unicode than for basestring. -BaseStringTypes = (str, unicode) +BaseStringTypes = (str, str) def is_Dict(obj, isinstance=isinstance, DictTypes=DictTypes): return isinstance(obj, DictTypes) @@ -440,7 +441,7 @@ _semi_deepcopy_dispatch = d = {} def semi_deepcopy_dict(x, exclude = [] ): copy = {} - for key, val in x.items(): + for key, val in list(x.items()): # The regular Python copy.deepcopy() also deepcopies the key, # as follows: # @@ -465,7 +466,7 @@ def semi_deepcopy(x): if copier: return copier(x) else: - if hasattr(x, '__semi_deepcopy__') and callable(x.__semi_deepcopy__): + if hasattr(x, '__semi_deepcopy__') and isinstance(x.__semi_deepcopy__, collections.Callable): return x.__semi_deepcopy__() elif isinstance(x, UserDict): return x.__class__(semi_deepcopy_dict(x)) @@ -718,7 +719,7 @@ else: # raised so as to not mask possibly serious disk or # network issues. continue - if stat.S_IMODE(st[stat.ST_MODE]) & 0111: + if stat.S_IMODE(st[stat.ST_MODE]) & 0o111: try: reject.index(f) except ValueError: @@ -979,7 +980,7 @@ class OrderedDict(UserDict): if key not in self._keys: self._keys.append(key) def update(self, dict): - for (key, val) in dict.items(): + for (key, val) in list(dict.items()): self.__setitem__(key, val) def values(self): @@ -1001,7 +1002,7 @@ class Selector(OrderedDict): # Try to perform Environment substitution on the keys of # the dictionary before giving up. s_dict = {} - for (k,v) in self.items(): + for (k,v) in list(self.items()): if k is not None: s_k = env.subst(k) if s_k in s_dict: @@ -1360,7 +1361,7 @@ def AddMethod(obj, function, name=None): print a.listIndex(5) """ if name is None: - name = function.func_name + name = function.__name__ else: function = RenameFunction(function, name) @@ -1376,10 +1377,10 @@ def RenameFunction(function, name): Returns a function identical to the specified function, but with the specified name. """ - return FunctionType(function.func_code, - function.func_globals, + return FunctionType(function.__code__, + function.__globals__, name, - function.func_defaults) + function.__defaults__) md5 = False @@ -1461,7 +1462,7 @@ class Null(object): return self def __repr__(self): return "Null(0x%08X)" % id(self) - def __nonzero__(self): + def __bool__(self): return False def __getattr__(self, name): return self diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py index a1e6756..a30404c 100644 --- a/src/engine/SCons/UtilTests.py +++ b/src/engine/SCons/UtilTests.py @@ -219,7 +219,7 @@ class UtilTestCase(unittest.TestCase): assert not is_Dict(()) assert not is_Dict("") if HasUnicode: - exec "assert not is_Dict(u'')" + exec("assert not is_Dict(u'')") def test_is_List(self): assert is_List([]) @@ -235,12 +235,12 @@ class UtilTestCase(unittest.TestCase): assert not is_List({}) assert not is_List("") if HasUnicode: - exec "assert not is_List(u'')" + exec("assert not is_List(u'')") def test_is_String(self): assert is_String("") if HasUnicode: - exec "assert is_String(u'')" + exec("assert is_String(u'')") assert is_String(UserString('')) try: class mystr(str): @@ -266,7 +266,7 @@ class UtilTestCase(unittest.TestCase): assert not is_Tuple({}) assert not is_Tuple("") if HasUnicode: - exec "assert not is_Tuple(u'')" + exec("assert not is_Tuple(u'')") def test_to_String(self): """Test the to_String() method.""" @@ -285,16 +285,16 @@ class UtilTestCase(unittest.TestCase): assert to_String(s2) == 'foo', s2 if HasUnicode: - s3=UserString(unicode('bar')) + s3=UserString(str('bar')) assert to_String(s3) == s3, s3 - assert to_String(s3) == unicode('bar'), s3 - assert isinstance(to_String(s3), unicode), \ + assert to_String(s3) == str('bar'), s3 + assert isinstance(to_String(s3), str), \ type(to_String(s3)) if HasUnicode: - s4 = unicode('baz') - assert to_String(s4) == unicode('baz'), to_String(s4) - assert isinstance(to_String(s4), unicode), \ + s4 = str('baz') + assert to_String(s4) == str('baz'), to_String(s4) + assert isinstance(to_String(s4), str), \ type(to_String(s4)) def test_WhereIs(self): @@ -313,10 +313,10 @@ class UtilTestCase(unittest.TestCase): os.mkdir(sub2_xxx_exe) test.write(sub3_xxx_exe, "\n") - os.chmod(sub3_xxx_exe, 0777) + os.chmod(sub3_xxx_exe, 0o777) test.write(sub4_xxx_exe, "\n") - os.chmod(sub4_xxx_exe, 0777) + os.chmod(sub4_xxx_exe, 0o777) env_path = os.environ['PATH'] @@ -681,7 +681,7 @@ bling fobj = io.StringIO(content) except TypeError: # Python 2.7 and beyond require unicode strings. - fobj = io.StringIO(unicode(content)) + fobj = io.StringIO(str(content)) lines = LogicalLines(fobj).readlines() assert lines == [ @@ -696,7 +696,7 @@ bling s1 = silent_intern("spam") # Python 3.x does not have a unicode() global function if sys.version[0] == '2': - s2 = silent_intern(unicode("unicode spam")) + s2 = silent_intern(str("unicode spam")) s3 = silent_intern(42) s4 = silent_intern("spam") assert id(s1) == id(s4) diff --git a/src/engine/SCons/Variables/EnumVariableTests.py b/src/engine/SCons/Variables/EnumVariableTests.py index f4b600d..4feb712 100644 --- a/src/engine/SCons/Variables/EnumVariableTests.py +++ b/src/engine/SCons/Variables/EnumVariableTests.py @@ -122,7 +122,7 @@ class EnumVariableTestCase(unittest.TestCase): 'C' : ['C', 'three', 'three'], } - for k, l in table.items(): + for k, l in list(table.items()): x = o0.converter(k) assert x == l[0], "o0 got %s, expected %s" % (x, l[0]) x = o1.converter(k) @@ -186,7 +186,7 @@ class EnumVariableTestCase(unittest.TestCase): 'no_v' : [invalid, invalid, invalid], } - for v, l in table.items(): + for v, l in list(table.items()): l[0](o0, v) l[1](o1, v) l[2](o2, v) diff --git a/src/engine/SCons/Variables/PathVariableTests.py b/src/engine/SCons/Variables/PathVariableTests.py index 084154b..2fa46eb 100644 --- a/src/engine/SCons/Variables/PathVariableTests.py +++ b/src/engine/SCons/Variables/PathVariableTests.py @@ -65,7 +65,7 @@ class PathVariableTestCase(unittest.TestCase): dne = test.workpath('does_not_exist') try: o.validator('X', dne, {}) - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: assert str(e) == 'Path for option X does not exist: %s' % dne, e except: raise Exception("did not catch expected UserError") @@ -89,7 +89,7 @@ class PathVariableTestCase(unittest.TestCase): f = test.workpath('file') try: o.validator('X', f, {}) - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: assert str(e) == 'Directory path for option X is a file: %s' % f, e except: raise Exception("did not catch expected UserError") @@ -97,7 +97,7 @@ class PathVariableTestCase(unittest.TestCase): dne = test.workpath('does_not_exist') try: o.validator('X', dne, {}) - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: assert str(e) == 'Directory path for option X does not exist: %s' % dne, e except: raise Exception("did not catch expected UserError") @@ -122,7 +122,7 @@ class PathVariableTestCase(unittest.TestCase): f = test.workpath('file') try: o.validator('X', f, {}) - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: assert str(e) == 'Path for option X is a file, not a directory: %s' % f, e except: raise Exception("did not catch expected UserError") @@ -146,7 +146,7 @@ class PathVariableTestCase(unittest.TestCase): d = test.workpath('d') try: o.validator('X', d, {}) - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: assert str(e) == 'File path for option X does not exist: %s' % d, e except: raise Exception("did not catch expected UserError") @@ -154,7 +154,7 @@ class PathVariableTestCase(unittest.TestCase): dne = test.workpath('does_not_exist') try: o.validator('X', dne, {}) - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: assert str(e) == 'File path for option X does not exist: %s' % dne, e except: raise Exception("did not catch expected UserError") @@ -198,7 +198,7 @@ class PathVariableTestCase(unittest.TestCase): dne = test.workpath('does_not_exist') try: o.validator('X', dne, {}) - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: expect = 'Path for option X does not exist: %s' % dne assert str(e) == expect, e else: @@ -217,7 +217,7 @@ class PathVariableTestCase(unittest.TestCase): try: o.validator('Y', 'value', {}) - except Exception, e: + except Exception as e: assert str(e) == 'my_validator() got called for Y, value!', e else: raise Exception("did not catch expected exception from my_validator()") diff --git a/src/engine/SCons/Variables/VariablesTests.py b/src/engine/SCons/Variables/VariablesTests.py index ad46bd6..520c8e3 100644 --- a/src/engine/SCons/Variables/VariablesTests.py +++ b/src/engine/SCons/Variables/VariablesTests.py @@ -55,7 +55,7 @@ def check(key, value, env): def checkSave(file, expected): gdict = {} ldict = {} - exec open(file, 'rU').read() in gdict, ldict + exec(open(file, 'rU').read(), gdict, ldict) assert expected == ldict, "%s\n...not equal to...\n%s" % (expected, ldict) class VariablesTestCase(unittest.TestCase): diff --git a/src/engine/SCons/Variables/__init__.py b/src/engine/SCons/Variables/__init__.py index ede7480..8d15b8d 100644 --- a/src/engine/SCons/Variables/__init__.py +++ b/src/engine/SCons/Variables/__init__.py @@ -36,11 +36,11 @@ import SCons.Errors import SCons.Util import SCons.Warnings -from BoolVariable import BoolVariable # okay -from EnumVariable import EnumVariable # okay -from ListVariable import ListVariable # naja -from PackageVariable import PackageVariable # naja -from PathVariable import PathVariable # okay +from .BoolVariable import BoolVariable # okay +from .EnumVariable import EnumVariable # okay +from .ListVariable import ListVariable # naja +from .PackageVariable import PackageVariable # naja +from .PathVariable import PathVariable # okay class Variables(object): @@ -170,7 +170,7 @@ class Variables(object): sys.path.insert(0, dir) try: values['__name__'] = filename - exec open(filename, 'rU').read() in {}, values + exec(open(filename, 'rU').read(), {}, values) finally: if dir: del sys.path[0] @@ -180,7 +180,7 @@ class Variables(object): if args is None: args = self.args - for arg, value in args.items(): + for arg, value in list(args.items()): added = False for option in self.options: if arg in list(option.aliases) + [ option.key ]: @@ -206,7 +206,7 @@ class Variables(object): env[option.key] = option.converter(value) except TypeError: env[option.key] = option.converter(value, env) - except ValueError, x: + except ValueError as x: raise SCons.Errors.UserError('Error converting option: %s\n%s'%(option.key, x)) @@ -268,7 +268,7 @@ class Variables(object): finally: fh.close() - except IOError, x: + except IOError as x: raise SCons.Errors.UserError('Error writing options to file: %s\n%s' % (filename, x)) def GenerateHelpText(self, env, sort=None): diff --git a/src/engine/SCons/compat/__init__.py b/src/engine/SCons/compat/__init__.py index c870fbc..6f1a7ee 100644 --- a/src/engine/SCons/compat/__init__.py +++ b/src/engine/SCons/compat/__init__.py @@ -87,7 +87,7 @@ def rename_module(new, old): rename_module('builtins', '__builtin__') -import _scons_builtins +from . import _scons_builtins try: diff --git a/src/engine/SCons/compat/_scons_subprocess.py b/src/engine/SCons/compat/_scons_subprocess.py index eebe53d..72581f7 100644 --- a/src/engine/SCons/compat/_scons_subprocess.py +++ b/src/engine/SCons/compat/_scons_subprocess.py @@ -439,22 +439,22 @@ except TypeError: def is_int(obj): return isinstance(obj, type(1)) def is_int_or_long(obj): - return type(obj) in (type(1), type(1L)) + return type(obj) in (type(1), type(1)) else: def is_int(obj): return isinstance(obj, int) def is_int_or_long(obj): - return isinstance(obj, (int, long)) + return isinstance(obj, int) try: - types.StringTypes + str except AttributeError: try: - types.StringTypes = (str, unicode) + str = (str, str) except NameError: - types.StringTypes = (str,) + str = (str,) def is_string(obj): - return isinstance(obj, types.StringTypes) + return isinstance(obj, str) _active = [] @@ -785,7 +785,7 @@ class Popen(object): errread, errwrite): """Execute program (MS Windows version)""" - if not isinstance(args, types.StringTypes): + if not isinstance(args, str): args = list2cmdline(args) # Process startup details @@ -802,7 +802,7 @@ class Popen(object): startupinfo.wShowWindow = SW_HIDE comspec = os.environ.get("COMSPEC", "cmd.exe") args = comspec + " /c " + args - if (GetVersion() >= 0x80000000L or + if (GetVersion() >= 0x80000000 or os.path.basename(comspec).lower() == "command.com"): # Win9x, or using command.com on NT. We need to # use the w9xpopen intermediate program. For more @@ -830,7 +830,7 @@ class Popen(object): env, cwd, startupinfo) - except pywintypes.error, e: + except pywintypes.error as e: # Translate pywintypes.error to WindowsError, which is # a subclass of OSError. FIXME: We should really # translate errno using _sys_errlist (or simliar), but @@ -1215,8 +1215,8 @@ def _demo_posix(): # Example 1: Simple redirection: Get process list # plist = Popen(["ps"], stdout=PIPE).communicate()[0] - print "Process list:" - print plist + print("Process list:") + print(plist) # # Example 2: Change uid before executing child @@ -1228,25 +1228,25 @@ def _demo_posix(): # # Example 3: Connecting several subprocesses # - print "Looking for 'hda'..." + print("Looking for 'hda'...") p1 = Popen(["dmesg"], stdout=PIPE) p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) - print repr(p2.communicate()[0]) + print(repr(p2.communicate()[0])) # # Example 4: Catch execution error # - print - print "Trying a weird file..." + print() + print("Trying a weird file...") try: - print Popen(["/this/path/does/not/exist"]).communicate() - except OSError, e: + print(Popen(["/this/path/does/not/exist"]).communicate()) + except OSError as e: if e.errno == errno.ENOENT: - print "The file didn't exist. I thought so..." - print "Child traceback:" - print e.child_traceback + print("The file didn't exist. I thought so...") + print("Child traceback:") + print(e.child_traceback) else: - print "Error", e.errno + print("Error", e.errno) else: sys.stderr.write( "Gosh. No error.\n" ) @@ -1255,15 +1255,15 @@ def _demo_windows(): # # Example 1: Connecting several subprocesses # - print "Looking for 'PROMPT' in set output..." + print("Looking for 'PROMPT' in set output...") p1 = Popen("set", stdout=PIPE, shell=True) p2 = Popen('find "PROMPT"', stdin=p1.stdout, stdout=PIPE) - print repr(p2.communicate()[0]) + print(repr(p2.communicate()[0])) # # Example 2: Simple execution of program # - print "Executing calc..." + print("Executing calc...") p = Popen("calc") p.wait() diff --git a/src/engine/SCons/cpp.py b/src/engine/SCons/cpp.py index 0ba10f5..4cc771b 100644 --- a/src/engine/SCons/cpp.py +++ b/src/engine/SCons/cpp.py @@ -31,6 +31,7 @@ import SCons.compat import os import re +import collections # # First "subsystem" of regular expressions that we set up: @@ -72,7 +73,7 @@ cpp_lines_dict = { # the corresponding compiled regular expression that fetches the arguments # we care about. Table = {} -for op_list, expr in cpp_lines_dict.items(): +for op_list, expr in list(cpp_lines_dict.items()): e = re.compile(expr) for op in op_list: Table[op] = e @@ -87,7 +88,7 @@ del op_list override = { 'if' : 'if(?!def)', } -l = [override.get(x, x) for x in Table.keys()] +l = [override.get(x, x) for x in list(Table.keys())] # Turn the list of expressions into one big honkin' regular expression @@ -130,7 +131,7 @@ CPP_to_Python_Ops_Sub = lambda m: CPP_to_Python_Ops_Dict[m.group(0)] # re module, as late as version 2.2.2, empirically matches the # "!" in "!=" first, instead of finding the longest match. # What's up with that? -l = sorted(CPP_to_Python_Ops_Dict.keys(), key=lambda a: len(a), reverse=True) +l = sorted(list(CPP_to_Python_Ops_Dict.keys()), key=lambda a: len(a), reverse=True) # Turn the list of keys into one regular expression that will allow us # to substitute all of the operators at once. @@ -266,7 +267,7 @@ class PreProcessor(object): d = { 'scons_current_file' : self.scons_current_file } - for op in Table.keys(): + for op in list(Table.keys()): d[op] = getattr(self, 'do_' + op) self.default_table = d @@ -552,7 +553,7 @@ class PreProcessor(object): except KeyError: m = function_name.search(s) s = self.cpp_namespace[m.group(1)] - if callable(s): + if isinstance(s, collections.Callable): args = function_arg_separator.split(m.group(2)) s = s(*args) if not s: diff --git a/src/engine/SCons/cppTests.py b/src/engine/SCons/cppTests.py index 2f2025b..5566e53 100644 --- a/src/engine/SCons/cppTests.py +++ b/src/engine/SCons/cppTests.py @@ -27,7 +27,7 @@ import atexit import sys import unittest -import cpp +from . import cpp diff --git a/src/engine/SCons/dblite.py b/src/engine/SCons/dblite.py index f4ba90a..89b9856 100644 --- a/src/engine/SCons/dblite.py +++ b/src/engine/SCons/dblite.py @@ -14,20 +14,20 @@ keep_all_files = 00000 ignore_corrupt_dbfiles = 0 def corruption_warning(filename): - print "Warning: Discarding corrupt database:", filename + print("Warning: Discarding corrupt database:", filename) -try: unicode +try: str except NameError: def is_string(s): return isinstance(s, str) else: def is_string(s): - return type(s) in (str, unicode) + return type(s) in (str, str) try: - unicode('a') + str('a') except NameError: - def unicode(s): return s + def str(s): return s dblite_suffix = '.dblite' tmp_suffix = '.tmp' @@ -77,7 +77,7 @@ class dblite(object): statinfo = os.stat(self._file_name) self._chown_to = statinfo.st_uid self._chgrp_to = statinfo.st_gid - except OSError, e: + except OSError as e: # db file doesn't exist yet. # Check os.environ for SUDO_UID, use if set self._chown_to = int(os.environ.get('SUDO_UID', -1)) @@ -90,7 +90,7 @@ class dblite(object): else: try: f = self._open(self._file_name, "rb") - except IOError, e: + except IOError as e: if (self._flag != "c"): raise e self._open(self._file_name, "wb", self._mode) @@ -122,7 +122,7 @@ class dblite(object): # (e.g. from a previous run as root). We should still be able to # unlink() the file if the directory's writable, though, so ignore # any OSError exception thrown by the chmod() call. - try: self._os_chmod(self._file_name, 0777) + try: self._os_chmod(self._file_name, 0o777) except OSError: pass self._os_unlink(self._file_name) self._os_rename(self._tmp_name, self._file_name) @@ -151,7 +151,7 @@ class dblite(object): if (not is_string(value)): raise TypeError("value `%s' must be a string but is %s" % (value, type(value))) self._dict[key] = value - self._needs_sync = 0001 + self._needs_sync = 0o001 def keys(self): return list(self._dict.keys()) @@ -171,7 +171,7 @@ class dblite(object): def __len__(self): return len(self._dict) -def open(file, flag=None, mode=0666): +def open(file, flag=None, mode=0o666): return dblite(file, flag, mode) def _exercise(): @@ -179,26 +179,26 @@ def _exercise(): assert len(db) == 0 db["foo"] = "bar" assert db["foo"] == "bar" - db[unicode("ufoo")] = unicode("ubar") - assert db[unicode("ufoo")] == unicode("ubar") + db[str("ufoo")] = str("ubar") + assert db[str("ufoo")] == str("ubar") db.sync() db = open("tmp", "c") assert len(db) == 2, len(db) assert db["foo"] == "bar" db["bar"] = "foo" assert db["bar"] == "foo" - db[unicode("ubar")] = unicode("ufoo") - assert db[unicode("ubar")] == unicode("ufoo") + db[str("ubar")] = str("ufoo") + assert db[str("ubar")] == str("ufoo") db.sync() db = open("tmp", "r") assert len(db) == 4, len(db) assert db["foo"] == "bar" assert db["bar"] == "foo" - assert db[unicode("ufoo")] == unicode("ubar") - assert db[unicode("ubar")] == unicode("ufoo") + assert db[str("ufoo")] == str("ubar") + assert db[str("ubar")] == str("ufoo") try: db.sync() - except IOError, e: + except IOError as e: assert str(e) == "Read-only database: tmp.dblite" else: raise RuntimeError("IOError expected.") @@ -208,13 +208,13 @@ def _exercise(): db.sync() try: db[(1,2)] = "tuple" - except TypeError, e: + except TypeError as e: assert str(e) == "key `(1, 2)' must be a string but is ", str(e) else: raise RuntimeError("TypeError exception expected") try: db["list"] = [1,2] - except TypeError, e: + except TypeError as e: assert str(e) == "value `[1, 2]' must be a string but is ", str(e) else: raise RuntimeError("TypeError exception expected") @@ -238,11 +238,11 @@ def _exercise(): os.unlink("tmp.dblite") try: db = open("tmp", "w") - except IOError, e: + except IOError as e: assert str(e) == "[Errno 2] No such file or directory: 'tmp.dblite'", str(e) else: raise RuntimeError("IOError expected.") - print "OK" + print("OK") if (__name__ == "__main__"): _exercise() diff --git a/src/script/scons-time.py b/src/script/scons-time.py index 3b215f9..4296192 100644 --- a/src/script/scons-time.py +++ b/src/script/scons-time.py @@ -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__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -42,6 +42,7 @@ import shutil import sys import tempfile import time +import collections try: sorted @@ -109,8 +110,8 @@ def HACK_for_exec(cmd, *args): 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 +147,7 @@ class Line(object): 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 +160,15 @@ class Line(object): 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 +254,8 @@ class Gnuplotter(Plotter): 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 +270,7 @@ class Gnuplotter(Plotter): 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() @@ -455,7 +456,7 @@ class SConsTimer(object): Each message is prepended with a standard prefix of our name plus the time. """ - if callable(msg): + if isinstance(msg, collections.Callable): msg = msg(*args) else: msg = msg % args @@ -474,7 +475,7 @@ class SConsTimer(object): The action is called if it's a callable Python function, and otherwise passed to os.system(). """ - if callable(action): + if isinstance(action, collections.Callable): action(*args) else: os.system(action % args) @@ -540,7 +541,7 @@ class SConsTimer(object): 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 +551,7 @@ class SConsTimer(object): 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 +691,13 @@ class SConsTimer(object): """ 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 +752,7 @@ class SConsTimer(object): 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 +857,7 @@ class SConsTimer(object): 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 +890,13 @@ class SConsTimer(object): 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 +1234,7 @@ class SConsTimer(object): 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 +1467,7 @@ class SConsTimer(object): 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) diff --git a/src/script/sconsign.py b/src/script/sconsign.py index e5e9d4f..323d1bf 100644 --- a/src/script/sconsign.py +++ b/src/script/sconsign.py @@ -171,7 +171,7 @@ sys.path = libs + sys.path import SCons.compat # so pickle will import cPickle instead -import whichdb +import dbm import time import pickle import imp @@ -189,8 +189,8 @@ def my_whichdb(filename): 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 @@ def printfield(name, entry, prefix=""): 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 @@ def printentries(entries, location): 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 @@ def printentries(entries, location): 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 @@ class Do_SConsignDB(object): # .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 @@ class Do_SConsignDB(object): # 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 @@ class Do_SConsignDB(object): 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 @@ class Do_SConsignDB(object): 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 @@ def Do_SConsignDir(name): 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 @@ for o, a in opts: 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 @@ if Do_Call: 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) diff --git a/src/test_files.py b/src/test_files.py index 7d8e75e..d71329b 100644 --- a/src/test_files.py +++ b/src/test_files.py @@ -77,7 +77,7 @@ check = { missing = [] no_result = [] -for directory, check_list in check.items(): +for directory, check_list in list(check.items()): if os.path.exists(directory): for c in check_list: f = os.path.join(directory, c) @@ -87,13 +87,13 @@ for directory, check_list in check.items(): no_result.append(directory) if missing: - print "Missing the following files:\n" - print "\t" + "\n\t".join(missing) + print("Missing the following files:\n") + print("\t" + "\n\t".join(missing)) test.fail_test(1) if no_result: - print "Cannot check files, the following have apparently not been built:" - print "\t" + "\n\t".join(no_result) + print("Cannot check files, the following have apparently not been built:") + print("\t" + "\n\t".join(no_result)) test.no_result(1) test.pass_test() diff --git a/src/test_interrupts.py b/src/test_interrupts.py index fb12e2a..1e027a1 100644 --- a/src/test_interrupts.py +++ b/src/test_interrupts.py @@ -102,7 +102,7 @@ for f in files: indent_list.append( (line_num, match.group('try_or_except') ) ) try_except_lines[match.group('indent')] = indent_list uncaught_this_file = [] - for indent in try_except_lines.keys(): + for indent in list(try_except_lines.keys()): exc_keyboardint_seen = 0 exc_all_seen = 0 for (l,statement) in try_except_lines[indent] + [(-1,indent + 'try')]: @@ -129,9 +129,9 @@ for f in files: if expected_num != len(uncaught_this_file): uncaughtKeyboardInterrupt = 1 msg = "%s: expected %d uncaught interrupts, got %d:" - print msg % (f, expected_num, len(uncaught_this_file)) + print(msg % (f, expected_num, len(uncaught_this_file))) for line in uncaught_this_file: - print " File %s:%d: Uncaught KeyboardInterrupt!" % (f,line) + print(" File %s:%d: Uncaught KeyboardInterrupt!" % (f,line)) test.fail_test(uncaughtKeyboardInterrupt) diff --git a/src/test_pychecker.py b/src/test_pychecker.py index f87d303..24aa966 100644 --- a/src/test_pychecker.py +++ b/src/test_pychecker.py @@ -139,7 +139,7 @@ for file in files: mismatches.append(stderr) if mismatches: - print ''.join(mismatches[1:]) + print(''.join(mismatches[1:])) test.fail_test() test.pass_test() diff --git a/src/test_setup.py b/src/test_setup.py index 29d36bf..731fbe7 100644 --- a/src/test_setup.py +++ b/src/test_setup.py @@ -197,9 +197,9 @@ if not os.path.isdir(scons_version) and os.path.isfile(tar_gz): os.system("gunzip -c %s | tar xf -" % tar_gz) if not os.path.isdir(scons_version): - print "Cannot test package installation, found none of the following packages:" - print "\t" + tar_gz - print "\t" + zip + print("Cannot test package installation, found none of the following packages:") + print("\t" + tar_gz) + print("\t" + zip) test.no_result(1) # Verify that a virgin installation installs the version library, diff --git a/src/test_strings.py b/src/test_strings.py index 3288d5f..b57c714 100644 --- a/src/test_strings.py +++ b/src/test_strings.py @@ -248,13 +248,13 @@ for collector in check_list: not_built.append(collector.directory) if missing_strings: - print "Found the following files with missing strings:" - print "\t" + "\n\t".join(missing_strings) + print("Found the following files with missing strings:") + print("\t" + "\n\t".join(missing_strings)) test.fail_test(1) if not_built: - print "Cannot check all strings, the following have apparently not been built:" - print "\t" + "\n\t".join(not_built) + print("Cannot check all strings, the following have apparently not been built:") + print("\t" + "\n\t".join(not_built)) test.no_result(1) test.pass_test() diff --git a/test/AS/nasm.py b/test/AS/nasm.py index be7db3e..551a5ab 100644 --- a/test/AS/nasm.py +++ b/test/AS/nasm.py @@ -69,7 +69,7 @@ else: # anyway...). nasm_format = 'elf' format_map = {} -for k, v in format_map.items(): +for k, v in list(format_map.items()): if sys.platform.find(k) != -1: nasm_format = v break diff --git a/test/Actions/unicode-signature.py b/test/Actions/unicode-signature.py index 0d0c469..0ba50c3 100644 --- a/test/Actions/unicode-signature.py +++ b/test/Actions/unicode-signature.py @@ -36,7 +36,7 @@ import TestSCons test = TestSCons.TestSCons() try: - unicode + str except NameError: import sys msg = "Unicode not supported by Python version %s; skipping test\n" diff --git a/test/AddOption/help.py b/test/AddOption/help.py index d50e595..a3fd7be 100644 --- a/test/AddOption/help.py +++ b/test/AddOption/help.py @@ -57,10 +57,10 @@ lines = test.stdout().split('\n') missing = [e for e in expected_lines if e not in lines] if missing: - print "====== STDOUT:" - print test.stdout() - print "====== Missing the following lines in the above AddOption() help output:" - print "\n".join(missing) + print("====== STDOUT:") + print(test.stdout()) + print("====== Missing the following lines in the above AddOption() help output:") + print("\n".join(missing)) test.fail_test() test.unlink('SConstruct') @@ -70,10 +70,10 @@ lines = test.stdout().split('\n') unexpected = [e for e in expected_lines if e in lines] if unexpected: - print "====== STDOUT:" - print test.stdout() - print "====== Unexpected lines in the above non-AddOption() help output:" - print "\n".join(unexpected) + print("====== STDOUT:") + print(test.stdout()) + print("====== Unexpected lines in the above non-AddOption() help output:") + print("\n".join(unexpected)) test.fail_test() test.pass_test() diff --git a/test/Batch/action-changed.py b/test/Batch/action-changed.py index dc2805a..d031432 100644 --- a/test/Batch/action-changed.py +++ b/test/Batch/action-changed.py @@ -54,7 +54,7 @@ sys.exit(0) """ test.write('build.py', build_py_contents % (python, 'one')) -os.chmod(test.workpath('build.py'), 0755) +os.chmod(test.workpath('build.py'), 0o755) test.write('SConstruct', """ env = Environment() @@ -81,7 +81,7 @@ test.must_match('f3.out', "one\nf3.in\n") test.up_to_date(arguments = '.') test.write('build.py', build_py_contents % (python, 'two')) -os.chmod(test.workpath('build.py'), 0755) +os.chmod(test.workpath('build.py'), 0o755) test.not_up_to_date(arguments = '.') diff --git a/test/Chmod.py b/test/Chmod.py index c00aea0..8b5fbe0 100644 --- a/test/Chmod.py +++ b/test/Chmod.py @@ -87,19 +87,19 @@ test.write('f10', "f10\n") test.subdir('d11') test.subdir('d12') -os.chmod(test.workpath('f1'), 0444) -os.chmod(test.workpath('f1-File'), 0444) -os.chmod(test.workpath('d2'), 0555) -os.chmod(test.workpath('d2-Dir'), 0555) -os.chmod(test.workpath('f3'), 0444) -os.chmod(test.workpath('d4'), 0555) -os.chmod(test.workpath('f5'), 0444) -os.chmod(test.workpath('Chmod-f7.in'), 0444) -os.chmod(test.workpath('f7.out-Chmod'), 0444) -os.chmod(test.workpath('f9'), 0444) -os.chmod(test.workpath('f10'), 0444) -os.chmod(test.workpath('d11'), 0555) -os.chmod(test.workpath('d12'), 0555) +os.chmod(test.workpath('f1'), 0o444) +os.chmod(test.workpath('f1-File'), 0o444) +os.chmod(test.workpath('d2'), 0o555) +os.chmod(test.workpath('d2-Dir'), 0o555) +os.chmod(test.workpath('f3'), 0o444) +os.chmod(test.workpath('d4'), 0o555) +os.chmod(test.workpath('f5'), 0o444) +os.chmod(test.workpath('Chmod-f7.in'), 0o444) +os.chmod(test.workpath('f7.out-Chmod'), 0o444) +os.chmod(test.workpath('f9'), 0o444) +os.chmod(test.workpath('f10'), 0o444) +os.chmod(test.workpath('d11'), 0o555) +os.chmod(test.workpath('d12'), 0o555) expect = test.wrap_stdout(read_str = """\ Chmod("f1", 0666) @@ -123,68 +123,68 @@ cat(["f8.out"], ["f8.in"]) test.run(options = '-n', arguments = '.', stdout = expect) s = stat.S_IMODE(os.stat(test.workpath('f1'))[stat.ST_MODE]) -test.fail_test(s != 0444) +test.fail_test(s != 0o444) s = stat.S_IMODE(os.stat(test.workpath('f1-File'))[stat.ST_MODE]) -test.fail_test(s != 0444) +test.fail_test(s != 0o444) s = stat.S_IMODE(os.stat(test.workpath('d2'))[stat.ST_MODE]) -test.fail_test(s != 0555) +test.fail_test(s != 0o555) s = stat.S_IMODE(os.stat(test.workpath('d2-Dir'))[stat.ST_MODE]) -test.fail_test(s != 0555) +test.fail_test(s != 0o555) test.must_not_exist('bar.out') s = stat.S_IMODE(os.stat(test.workpath('f3'))[stat.ST_MODE]) -test.fail_test(s != 0444) +test.fail_test(s != 0o444) s = stat.S_IMODE(os.stat(test.workpath('d4'))[stat.ST_MODE]) -test.fail_test(s != 0555) +test.fail_test(s != 0o555) s = stat.S_IMODE(os.stat(test.workpath('f5'))[stat.ST_MODE]) -test.fail_test(s != 0444) +test.fail_test(s != 0o444) test.must_not_exist('f6.out') test.must_not_exist('f7.out') s = stat.S_IMODE(os.stat(test.workpath('Chmod-f7.in'))[stat.ST_MODE]) -test.fail_test(s != 0444) +test.fail_test(s != 0o444) s = stat.S_IMODE(os.stat(test.workpath('f7.out-Chmod'))[stat.ST_MODE]) -test.fail_test(s != 0444) +test.fail_test(s != 0o444) test.must_not_exist('f8.out') s = stat.S_IMODE(os.stat(test.workpath('f9'))[stat.ST_MODE]) -test.fail_test(s != 0444) +test.fail_test(s != 0o444) s = stat.S_IMODE(os.stat(test.workpath('f10'))[stat.ST_MODE]) -test.fail_test(s != 0444) +test.fail_test(s != 0o444) s = stat.S_IMODE(os.stat(test.workpath('d11'))[stat.ST_MODE]) -test.fail_test(s != 0555) +test.fail_test(s != 0o555) s = stat.S_IMODE(os.stat(test.workpath('d12'))[stat.ST_MODE]) -test.fail_test(s != 0555) +test.fail_test(s != 0o555) test.run() s = stat.S_IMODE(os.stat(test.workpath('f1'))[stat.ST_MODE]) -test.fail_test(s != 0666) +test.fail_test(s != 0o666) s = stat.S_IMODE(os.stat(test.workpath('f1-File'))[stat.ST_MODE]) -test.fail_test(s != 0666) +test.fail_test(s != 0o666) s = stat.S_IMODE(os.stat(test.workpath('d2'))[stat.ST_MODE]) -test.fail_test(s != 0777) +test.fail_test(s != 0o777) s = stat.S_IMODE(os.stat(test.workpath('d2-Dir'))[stat.ST_MODE]) -test.fail_test(s != 0777) +test.fail_test(s != 0o777) test.must_match('bar.out', "bar.in\n") s = stat.S_IMODE(os.stat(test.workpath('f3'))[stat.ST_MODE]) -test.fail_test(s != 0666) +test.fail_test(s != 0o666) s = stat.S_IMODE(os.stat(test.workpath('d4'))[stat.ST_MODE]) -test.fail_test(s != 0777) +test.fail_test(s != 0o777) s = stat.S_IMODE(os.stat(test.workpath('f5'))[stat.ST_MODE]) -test.fail_test(s != 0666) +test.fail_test(s != 0o666) test.must_match('f6.out', "f6.in\n") test.must_match('f7.out', "f7.in\n") s = stat.S_IMODE(os.stat(test.workpath('Chmod-f7.in'))[stat.ST_MODE]) -test.fail_test(s != 0666) +test.fail_test(s != 0o666) s = stat.S_IMODE(os.stat(test.workpath('f7.out-Chmod'))[stat.ST_MODE]) -test.fail_test(s != 0666) +test.fail_test(s != 0o666) test.must_match('f8.out', "f8.in\n") s = stat.S_IMODE(os.stat(test.workpath('f9'))[stat.ST_MODE]) -test.fail_test(s != 0666) +test.fail_test(s != 0o666) s = stat.S_IMODE(os.stat(test.workpath('f10'))[stat.ST_MODE]) -test.fail_test(s != 0666) +test.fail_test(s != 0o666) s = stat.S_IMODE(os.stat(test.workpath('d11'))[stat.ST_MODE]) -test.fail_test(s != 0777) +test.fail_test(s != 0o777) s = stat.S_IMODE(os.stat(test.workpath('d12'))[stat.ST_MODE]) -test.fail_test(s != 0777) +test.fail_test(s != 0o777) test.pass_test() diff --git a/test/Configure/ConfigureDryRunError.py b/test/Configure/ConfigureDryRunError.py index b4be67e..a8c6309 100644 --- a/test/Configure/ConfigureDryRunError.py +++ b/test/Configure/ConfigureDryRunError.py @@ -97,7 +97,7 @@ test.checkLogAndStdout( ["Checking for C library %s... " % lib, newLog = test.read(test.workpath('config.log')) if newLog != oldLog: - print "Unexpected update of log file within a dry run" + print("Unexpected update of log file within a dry run") test.fail_test() test.pass_test() diff --git a/test/Configure/config-h.py b/test/Configure/config-h.py index cda6c3b..6c70c9c 100644 --- a/test/Configure/config-h.py +++ b/test/Configure/config-h.py @@ -135,19 +135,19 @@ test.run(stdout=expected_stdout) config_h = test.read(test.workpath('config.h')) if expected_config_h != config_h: - print "Unexpected config.h" - print "Expected: " - print "---------------------------------------------------------" - print repr(expected_config_h) - print "---------------------------------------------------------" - print "Found: " - print "---------------------------------------------------------" - print repr(config_h) - print "---------------------------------------------------------" - print "Stdio: " - print "---------------------------------------------------------" - print test.stdout() - print "---------------------------------------------------------" + print("Unexpected config.h") + print("Expected: ") + print("---------------------------------------------------------") + print(repr(expected_config_h)) + print("---------------------------------------------------------") + print("Found: ") + print("---------------------------------------------------------") + print(repr(config_h)) + print("---------------------------------------------------------") + print("Stdio: ") + print("---------------------------------------------------------") + print(test.stdout()) + print("---------------------------------------------------------") test.fail_test() expected_read_str = re.sub(r'\b((yes)|(no))\b', @@ -162,19 +162,19 @@ test.run(stdout=expected_stdout) config_h = test.read(test.workpath('config.h')) if expected_config_h != config_h: - print "Unexpected config.h" - print "Expected: " - print "---------------------------------------------------------" - print repr(expected_config_h) - print "---------------------------------------------------------" - print "Found: " - print "---------------------------------------------------------" - print repr(config_h) - print "---------------------------------------------------------" - print "Stdio: " - print "---------------------------------------------------------" - print test.stdout() - print "---------------------------------------------------------" + print("Unexpected config.h") + print("Expected: ") + print("---------------------------------------------------------") + print(repr(expected_config_h)) + print("---------------------------------------------------------") + print("Found: ") + print("---------------------------------------------------------") + print(repr(config_h)) + print("---------------------------------------------------------") + print("Stdio: ") + print("---------------------------------------------------------") + print(test.stdout()) + print("---------------------------------------------------------") test.fail_test() test.pass_test() diff --git a/test/Configure/implicit-cache.py b/test/Configure/implicit-cache.py index 0f04b1e..059fd4c 100644 --- a/test/Configure/implicit-cache.py +++ b/test/Configure/implicit-cache.py @@ -93,11 +93,11 @@ test.run_sconsign('-d .sconf_temp -e conftest_0.c --raw .sconsign.dblite') new_sconsign_dblite = test.stdout() if old_sconsign_dblite != new_sconsign_dblite: - print ".sconsign.dblite did not match:" - print "FIRST RUN ==========" - print old_sconsign_dblite - print "SECOND RUN ==========" - print new_sconsign_dblite + print(".sconsign.dblite did not match:") + print("FIRST RUN ==========") + print(old_sconsign_dblite) + print("SECOND RUN ==========") + print(new_sconsign_dblite) test.fail_test() test.pass_test() diff --git a/test/Copy-Action.py b/test/Copy-Action.py index 51635c5..ded158a 100644 --- a/test/Copy-Action.py +++ b/test/Copy-Action.py @@ -84,8 +84,8 @@ test.subdir('d5') test.write(['d5', 'f12.in'], "f12.in\n") test.write('f 13.in', "f 13.in\n") -os.chmod('f1.in', 0646) -os.chmod('f4.in', 0644) +os.chmod('f1.in', 0o646) +os.chmod('f4.in', 0o644) test.sleep() diff --git a/test/Deprecated/Options/Options.py b/test/Deprecated/Options/Options.py index 8116a63..61a12f3 100644 --- a/test/Deprecated/Options/Options.py +++ b/test/Deprecated/Options/Options.py @@ -237,7 +237,7 @@ opts.Save('options.saved', env) def checkSave(file, expected): gdict = {} ldict = {} - exec open(file, 'rU').read() in gdict, ldict + exec(open(file, 'rU').read(), gdict, ldict) assert expected == ldict, "%s\n...not equal to...\n%s" % (expected, ldict) # First test with no command line options diff --git a/test/Deprecated/SourceCode/BitKeeper/BitKeeper.py b/test/Deprecated/SourceCode/BitKeeper/BitKeeper.py index 28b8761..9a36eac 100644 --- a/test/Deprecated/SourceCode/BitKeeper/BitKeeper.py +++ b/test/Deprecated/SourceCode/BitKeeper/BitKeeper.py @@ -67,7 +67,7 @@ test.subdir('BK', 'import', ['import', 'sub']) # Test using BitKeeper to fetch from SCCS/s.file files. sccs = test.where_is('sccs') if not sccs: - print "Could not find SCCS, skipping sub-test of BitKeeper using SCCS files." + print("Could not find SCCS, skipping sub-test of BitKeeper using SCCS files.") else: test.subdir('work1', ['work1', 'SCCS'], @@ -167,9 +167,9 @@ sub/fff.in 1.1 -> 1.2: 1 lines rcs = test.where_is('rcs') ci = test.where_is('ci') if not rcs: - print "Could not find RCS,\nskipping sub-test of BitKeeper using RCS files." + print("Could not find RCS,\nskipping sub-test of BitKeeper using RCS files.") elif not ci: - print "Could not find the RCS ci command,\nskipping sub-test of BitKeeper using RCS files." + print("Could not find the RCS ci command,\nskipping sub-test of BitKeeper using RCS files.") else: test.subdir('work2', ['work2', 'RCS'], diff --git a/test/Deprecated/SourceCode/Subversion.py b/test/Deprecated/SourceCode/Subversion.py index a97c86f..ac3eb57 100644 --- a/test/Deprecated/SourceCode/Subversion.py +++ b/test/Deprecated/SourceCode/Subversion.py @@ -50,7 +50,7 @@ svnadmin = test.where_is('svnadmin') if not svn: test.skip_test("Could not find 'svnadmin'; skipping test(s).\n") -print "Short-circuiting this test until we support Subversion" +print("Short-circuiting this test until we support Subversion") test.pass_test() test.subdir('Subversion', 'import', ['import', 'sub'], 'work1', 'work2') diff --git a/test/GetBuildFailures/parallel.py b/test/GetBuildFailures/parallel.py index b7576af..101c2e2 100644 --- a/test/GetBuildFailures/parallel.py +++ b/test/GetBuildFailures/parallel.py @@ -102,8 +102,8 @@ error_45 = f4_error + f5_error error_54 = f5_error + f4_error if test.stderr() not in [error_45, error_54]: - print "Did not find the following output in list of expected strings:" - print test.stderr(), + print("Did not find the following output in list of expected strings:") + print(test.stderr(), end=' ') test.fail_test() # We jump through hoops above to try to make sure that the individual @@ -121,8 +121,8 @@ failed_45 = f4_failed + f5_failed failed_54 = f5_failed + f4_failed if test.stdout() not in [failed_45, failed_54]: - print "Did not find the following output in list of expected strings:" - print test.stdout(), + print("Did not find the following output in list of expected strings:") + print(test.stdout(), end=' ') test.fail_test() test.must_match(test.workpath('f3'), 'f3.in\n') diff --git a/test/Glob/glob-libpath.py b/test/Glob/glob-libpath.py index b09aab9..6ee06e6 100644 --- a/test/Glob/glob-libpath.py +++ b/test/Glob/glob-libpath.py @@ -77,10 +77,10 @@ test.write(['src', 'util', 'util.cpp'], """int i=0; test.run(arguments = '-Q .') if not test.match_re_dotall(test.stdout(), r".*(-L|/LIBPATH:)build[/\\]util.*"): - print repr(test.stdout())+" should contain -Lbuild/util or /LIBPATH:build\\util" + print(repr(test.stdout())+" should contain -Lbuild/util or /LIBPATH:build\\util") test.fail_test() if test.match_re_dotall(test.stdout(), r".*(-L|/LIBPATH:)src[/\\]util.*"): - print repr(test.stdout())+" should not contain -Lsrc/util or /LIBPATH:src\\util" + print(repr(test.stdout())+" should not contain -Lsrc/util or /LIBPATH:src\\util") test.fail_test() test.pass_test() diff --git a/test/Install/Install.py b/test/Install/Install.py index adadfd9..d66660b 100644 --- a/test/Install/Install.py +++ b/test/Install/Install.py @@ -129,7 +129,7 @@ test.must_match(['work', 'f2.out'], "f2.in\n") # if a target can not be unlinked before building it: test.write(['work', 'f1.in'], "f1.in again again\n") -os.chmod(test.workpath('work', 'export'), 0555) +os.chmod(test.workpath('work', 'export'), 0o555) f = open(f1_out, 'rb') diff --git a/test/Interactive/version.py b/test/Interactive/version.py index bbca9ef..295b9d3 100644 --- a/test/Interactive/version.py +++ b/test/Interactive/version.py @@ -76,7 +76,7 @@ expect2 = r"""scons>>> SCons by Steven Knight et al\.: stdout = test.stdout() + '\n' if not test.match_re(stdout, expect1) and not test.match_re(stdout, expect2): - print repr(stdout) + print(repr(stdout)) test.fail_test() diff --git a/test/Java/multi-step.py b/test/Java/multi-step.py index a8efcd4..add4208 100644 --- a/test/Java/multi-step.py +++ b/test/Java/multi-step.py @@ -557,7 +557,7 @@ test.must_exist(['buildout', 'jni', 'SampleTest.java']) # it doesn't exist. p = test.workpath('buildout', 'jni', 'SampleTest.class') if not os.path.exists(p): - print 'Warning: %s does not exist' % p + print('Warning: %s does not exist' % p) test.up_to_date(arguments = '.') diff --git a/test/MSVC/batch-longlines.py b/test/MSVC/batch-longlines.py index ef7233b..c584aba 100644 --- a/test/MSVC/batch-longlines.py +++ b/test/MSVC/batch-longlines.py @@ -1,61 +1,61 @@ -#!/usr/bin/env python -# -# __COPYRIGHT__ -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# 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. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -""" -Verify operation of Visual C/C++ batch builds with long lines. - -Only runs on Windows. -""" - -import TestSCons - -test = TestSCons.TestSCons() - -test.skip_if_not_msvc() - -_python_ = TestSCons._python_ - -for i in xrange(1,200): - test.write('source-file-with-quite-a-long-name-maybe-unrealistic-but-who-cares-%05d.cxx'%i, - '/* source file %d */\nint var%d;\n'%(i,i)) - -test.write('SConstruct', """ -env = Environment(tools=['msvc', 'mslink'], - MSVC_BATCH=ARGUMENTS.get('MSVC_BATCH')) -env.SharedLibrary('mylib', Glob('source*.cxx')) -""" % locals()) - -test.run(arguments = 'MSVC_BATCH=1 .') - -test.must_exist('mylib.dll') - -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# 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. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify operation of Visual C/C++ batch builds with long lines. + +Only runs on Windows. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.skip_if_not_msvc() + +_python_ = TestSCons._python_ + +for i in range(1,200): + test.write('source-file-with-quite-a-long-name-maybe-unrealistic-but-who-cares-%05d.cxx'%i, + '/* source file %d */\nint var%d;\n'%(i,i)) + +test.write('SConstruct', """ +env = Environment(tools=['msvc', 'mslink'], + MSVC_BATCH=ARGUMENTS.get('MSVC_BATCH')) +env.SharedLibrary('mylib', Glob('source*.cxx')) +""" % locals()) + +test.run(arguments = 'MSVC_BATCH=1 .') + +test.must_exist('mylib.dll') + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/MSVC/msvc.py b/test/MSVC/msvc.py index c68fb45..6f5c8d6 100644 --- a/test/MSVC/msvc.py +++ b/test/MSVC/msvc.py @@ -181,9 +181,9 @@ slow = time.time() - start # using precompiled headers should be faster limit = slow*0.90 if fast >= limit: - print "Using precompiled headers was not fast enough:" - print "slow.obj: %.3fs" % slow - print "fast.obj: %.3fs (expected less than %.3fs)" % (fast, limit) + print("Using precompiled headers was not fast enough:") + print("slow.obj: %.3fs" % slow) + print("fast.obj: %.3fs (expected less than %.3fs)" % (fast, limit)) test.fail_test() # Modifying resource.h should cause both the resource and precompiled header to be rebuilt: diff --git a/test/QT/QTFLAGS.py b/test/QT/QTFLAGS.py index 008397a..b7172fc 100644 --- a/test/QT/QTFLAGS.py +++ b/test/QT/QTFLAGS.py @@ -147,7 +147,7 @@ test.must_exist(['work1', 'mmmmocFromH.cxx'], ['work1', 'mmmanother_ui_file.cxx']) def _flagTest(test,fileToContentsStart): - for f,c in fileToContentsStart.items(): + for f,c in list(fileToContentsStart.items()): if test.read(test.workpath('work1', f)).find(c) != 0: return 1 return 0 diff --git a/test/QT/copied-env.py b/test/QT/copied-env.py index efa91be..59a344d 100644 --- a/test/QT/copied-env.py +++ b/test/QT/copied-env.py @@ -70,8 +70,8 @@ moc_MyForm = [x for x in test.stdout().split('\n') if x.find('moc_MyForm') != -1 MYLIB_IMPL = [x for x in moc_MyForm if x.find('MYLIB_IMPL') != -1] if not MYLIB_IMPL: - print "Did not find MYLIB_IMPL on moc_MyForm compilation line:" - print test.stdout() + print("Did not find MYLIB_IMPL on moc_MyForm compilation line:") + print(test.stdout()) test.fail_test() test.pass_test() diff --git a/test/QT/warnings.py b/test/QT/warnings.py index a861b24..5e680f6 100644 --- a/test/QT/warnings.py +++ b/test/QT/warnings.py @@ -59,8 +59,8 @@ scons: warning: Generated moc file 'aaa.moc' is not included by 'aaa.cpp' """ + TestSCons.file_expr if not re.search(match12, test.stderr()): - print "Did not find expected regular expression in stderr:" - print test.stderr() + print("Did not find expected regular expression in stderr:") + print(test.stderr()) test.fail_test() os.environ['QTDIR'] = test.QT diff --git a/test/SConsignFile/use-dbhash.py b/test/SConsignFile/use-dbhash.py index 45e3e36..bd9b799 100644 --- a/test/SConsignFile/use-dbhash.py +++ b/test/SConsignFile/use-dbhash.py @@ -35,7 +35,7 @@ _python_ = TestSCons._python_ test = TestSCons.TestSCons() try: - import dbhash + import dbm.bsd except ImportError: test.skip_test('No dbhash in this version of Python; skipping test.\n') diff --git a/test/SConsignFile/use-dbm.py b/test/SConsignFile/use-dbm.py index 75f088d..90983b3 100644 --- a/test/SConsignFile/use-dbm.py +++ b/test/SConsignFile/use-dbm.py @@ -35,7 +35,7 @@ _python_ = TestSCons._python_ test = TestSCons.TestSCons() try: - import dbm + import dbm.ndbm except ImportError: test.skip_test('No dbm in this version of Python; skipping test.\n') diff --git a/test/SConsignFile/use-dumbdbm.py b/test/SConsignFile/use-dumbdbm.py index 9d48fe5..84f1dd4 100644 --- a/test/SConsignFile/use-dumbdbm.py +++ b/test/SConsignFile/use-dumbdbm.py @@ -35,7 +35,7 @@ _python_ = TestSCons._python_ test = TestSCons.TestSCons() try: - import dumbdbm + import dbm.dumb except ImportError: test.skip_test('No dumbdbm in this version of Python; skipping test.\n') diff --git a/test/SConsignFile/use-gdbm.py b/test/SConsignFile/use-gdbm.py index 1eb3645..a7e4f59 100644 --- a/test/SConsignFile/use-gdbm.py +++ b/test/SConsignFile/use-gdbm.py @@ -35,7 +35,7 @@ _python_ = TestSCons._python_ test = TestSCons.TestSCons() try: - import gdbm + import dbm.gnu except ImportError: test.skip_test('No gdbm in this version of Python; skipping test.\n') diff --git a/test/SHELL.py b/test/SHELL.py index 93ed0b1..faee27f 100644 --- a/test/SHELL.py +++ b/test/SHELL.py @@ -64,7 +64,7 @@ ofp.close() sys.exit(0) """ % locals()) -os.chmod(my_shell, 0755) +os.chmod(my_shell, 0o755) test.write('SConstruct', """\ env = Environment(SHELL = r'%(my_shell)s') diff --git a/test/Scanner/unicode.py b/test/Scanner/unicode.py index 55e22bd..7a72804 100644 --- a/test/Scanner/unicode.py +++ b/test/Scanner/unicode.py @@ -36,7 +36,7 @@ _python_ = TestSCons._python_ test = TestSCons.TestSCons() try: - unicode + str except NameError: import sys msg = "Unicode not supported by Python version %s; skipping test\n" @@ -102,28 +102,28 @@ include utf16be.k foo.k 1 line 4 """) -contents = unicode("""\ +contents = str("""\ ascii.k 1 line 1 include ascii.inc ascii.k 1 line 3 """) test.write('ascii.k', contents.encode('ascii')) -contents = unicode("""\ +contents = str("""\ utf8.k 1 line 1 include utf8.inc utf8.k 1 line 3 """) test.write('utf8.k', codecs.BOM_UTF8 + contents.encode('utf-8')) -contents = unicode("""\ +contents = str("""\ utf16le.k 1 line 1 include utf16le.inc utf16le.k 1 line 3 """) test.write('utf16le.k', codecs.BOM_UTF16_LE + contents.encode('utf-16-le')) -contents = unicode("""\ +contents = str("""\ utf16be.k 1 line 1 include utf16be.inc utf16be.k 1 line 3 diff --git a/test/TEMPFILEPREFIX.py b/test/TEMPFILEPREFIX.py index f9b3240..8e756af 100644 --- a/test/TEMPFILEPREFIX.py +++ b/test/TEMPFILEPREFIX.py @@ -45,7 +45,7 @@ print sys.argv echo_py = test.workpath('echo.py') st = os.stat(echo_py) -os.chmod(echo_py, st[stat.ST_MODE]|0111) +os.chmod(echo_py, st[stat.ST_MODE]|0o111) test.write('SConstruct', """ import os diff --git a/test/TEX/TEX.py b/test/TEX/TEX.py index 24d4bdd..863144d 100644 --- a/test/TEX/TEX.py +++ b/test/TEX/TEX.py @@ -173,14 +173,14 @@ Run \texttt{latex}, then \texttt{bibtex}, then \texttt{latex} twice again \cite{ reruns = [x for x in output_lines if x.find('latex -interaction=nonstopmode -recorder rerun.tex') != -1] if len(reruns) != 2: - print "Expected 2 latex calls, got %s:" % len(reruns) - print '\n'.join(reruns) + print("Expected 2 latex calls, got %s:" % len(reruns)) + print('\n'.join(reruns)) test.fail_test() bibtex = [x for x in output_lines if x.find('bibtex bibtex-test') != -1] if len(bibtex) != 1: - print "Expected 1 bibtex call, got %s:" % len(bibtex) - print '\n'.join(bibtex) + print("Expected 1 bibtex call, got %s:" % len(bibtex)) + print('\n'.join(bibtex)) test.fail_test() test.pass_test() diff --git a/test/Value.py b/test/Value.py index f3ad458..025c6de 100644 --- a/test/Value.py +++ b/test/Value.py @@ -81,7 +81,7 @@ open(sys.argv[-1],'wb').write(" ".join(sys.argv[1:-2])) # to make sure there's no difference in behavior. for source_signature in ['MD5', 'timestamp-newer']: - print "Testing Value node with source signatures:", source_signature + print("Testing Value node with source signatures:", source_signature) test.write('SConstruct', SConstruct_content % locals()) diff --git a/test/Variables/Variables.py b/test/Variables/Variables.py index 454e32e..d0bf432 100644 --- a/test/Variables/Variables.py +++ b/test/Variables/Variables.py @@ -231,7 +231,7 @@ opts.Save('variables.saved', env) def checkSave(file, expected): gdict = {} ldict = {} - exec open(file, 'rU').read() in gdict, ldict + exec(open(file, 'rU').read(), gdict, ldict) assert expected == ldict, "%s\n...not equal to...\n%s" % (expected, ldict) # First test with no command line variables diff --git a/test/WhereIs.py b/test/WhereIs.py index dc127b6..07c3f6c 100644 --- a/test/WhereIs.py +++ b/test/WhereIs.py @@ -45,10 +45,10 @@ if sys.platform != 'win32': os.mkdir(sub2_xxx_exe) test.write(sub3_xxx_exe, "\n") -os.chmod(sub3_xxx_exe, 0777) +os.chmod(sub3_xxx_exe, 0o777) test.write(sub4_xxx_exe, "\n") -os.chmod(sub4_xxx_exe, 0777) +os.chmod(sub4_xxx_exe, 0o777) env_path = os.environ['PATH'] diff --git a/test/Win32/bad-drive.py b/test/Win32/bad-drive.py index f2a55b8..ff98b4e 100644 --- a/test/Win32/bad-drive.py +++ b/test/Win32/bad-drive.py @@ -50,8 +50,8 @@ for i in range(len(uppercase)-1, -1, -1): break if bad_drive is None: - print "All drive letters appear to be in use." - print "Cannot test SCons handling of invalid Windows drive letters." + print("All drive letters appear to be in use.") + print("Cannot test SCons handling of invalid Windows drive letters.") test.no_result(1); test.write('SConstruct', """ diff --git a/test/Win32/default-drive.py b/test/Win32/default-drive.py index f427a20..2bc14b1 100644 --- a/test/Win32/default-drive.py +++ b/test/Win32/default-drive.py @@ -59,7 +59,7 @@ test.write(['src', 'file.in'], "src/file.in\n") build_file_out = test.workpath('build', 'file.out') -print os.path.splitdrive(build_file_out)[1] +print(os.path.splitdrive(build_file_out)[1]) test.run(chdir = 'src', arguments = os.path.splitdrive(build_file_out)[1]) diff --git a/test/ZIP/ZIP.py b/test/ZIP/ZIP.py index af2450b..f2acad8 100644 --- a/test/ZIP/ZIP.py +++ b/test/ZIP/ZIP.py @@ -47,7 +47,7 @@ def zipfile_contains(zipfilename, names): for name in names: try: info=zf.getinfo(name) - except KeyError, e: # name not found + except KeyError as e: # name not found zf.close() return False return True diff --git a/test/ZIP/ZIPROOT.py b/test/ZIP/ZIPROOT.py index 96747a7..f3e4496 100644 --- a/test/ZIP/ZIPROOT.py +++ b/test/ZIP/ZIPROOT.py @@ -1,98 +1,98 @@ -#!/usr/bin/env python -# -# __COPYRIGHT__ -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# 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. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -import os -import stat - -import TestSCons - -_python_ = TestSCons._python_ - -test = TestSCons.TestSCons() - -import zipfile - -def zipfile_contains(zipfilename, names): - """Returns True if zipfilename contains all the names, False otherwise.""" - zf=zipfile.ZipFile(zipfilename, 'r') - if type(names)==type(''): - names=[names] - for name in names: - try: - info=zf.getinfo(name) - except KeyError, e: # name not found - zf.close() - return False - return True - -def zipfile_files(fname): - """Returns all the filenames in zip file fname.""" - zf = zipfile.ZipFile(fname, 'r') - return [x.filename for x in zf.infolist()] - -test.subdir('sub1') -test.subdir(['sub1', 'sub2']) - -test.write('SConstruct', """ -env = Environment(tools = ['zip']) -env.Zip(target = 'aaa.zip', source = ['sub1/file1'], ZIPROOT='sub1') -env.Zip(target = 'bbb.zip', source = ['sub1/file2', 'sub1/sub2/file2'], ZIPROOT='sub1') -""" % locals()) - -test.write(['sub1', 'file1'], "file1\n") -test.write(['sub1', 'file2'], "file2a\n") -test.write(['sub1', 'sub2', 'file2'], "file2b\n") - -test.run(arguments = 'aaa.zip', stderr = None) - -test.must_exist('aaa.zip') - -# TEST: Zip file should contain 'file1', not 'sub1/file1', because of ZIPROOT. -zf=zipfile.ZipFile('aaa.zip', 'r') -test.fail_test(zf.testzip() is not None) -zf.close() - -files=zipfile_files('aaa.zip') -test.fail_test(zipfile_files('aaa.zip') != ['file1'], - message='Zip file aaa.zip has wrong files: %s'%repr(files)) - -### - -test.run(arguments = 'bbb.zip', stderr = None) - -test.must_exist('bbb.zip') - -# TEST: Zip file should contain 'sub2/file2', not 'sub1/sub2/file2', because of ZIPROOT. -zf=zipfile.ZipFile('bbb.zip', 'r') -test.fail_test(zf.testzip() is not None) -zf.close() - -files=zipfile_files('bbb.zip') -test.fail_test(zipfile_files('bbb.zip') != ['file2', 'sub2/file2'], - message='Zip file bbb.zip has wrong files: %s'%repr(files)) - - -test.pass_test() +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# 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. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import os +import stat + +import TestSCons + +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons() + +import zipfile + +def zipfile_contains(zipfilename, names): + """Returns True if zipfilename contains all the names, False otherwise.""" + zf=zipfile.ZipFile(zipfilename, 'r') + if type(names)==type(''): + names=[names] + for name in names: + try: + info=zf.getinfo(name) + except KeyError as e: # name not found + zf.close() + return False + return True + +def zipfile_files(fname): + """Returns all the filenames in zip file fname.""" + zf = zipfile.ZipFile(fname, 'r') + return [x.filename for x in zf.infolist()] + +test.subdir('sub1') +test.subdir(['sub1', 'sub2']) + +test.write('SConstruct', """ +env = Environment(tools = ['zip']) +env.Zip(target = 'aaa.zip', source = ['sub1/file1'], ZIPROOT='sub1') +env.Zip(target = 'bbb.zip', source = ['sub1/file2', 'sub1/sub2/file2'], ZIPROOT='sub1') +""" % locals()) + +test.write(['sub1', 'file1'], "file1\n") +test.write(['sub1', 'file2'], "file2a\n") +test.write(['sub1', 'sub2', 'file2'], "file2b\n") + +test.run(arguments = 'aaa.zip', stderr = None) + +test.must_exist('aaa.zip') + +# TEST: Zip file should contain 'file1', not 'sub1/file1', because of ZIPROOT. +zf=zipfile.ZipFile('aaa.zip', 'r') +test.fail_test(zf.testzip() is not None) +zf.close() + +files=zipfile_files('aaa.zip') +test.fail_test(zipfile_files('aaa.zip') != ['file1'], + message='Zip file aaa.zip has wrong files: %s'%repr(files)) + +### + +test.run(arguments = 'bbb.zip', stderr = None) + +test.must_exist('bbb.zip') + +# TEST: Zip file should contain 'sub2/file2', not 'sub1/sub2/file2', because of ZIPROOT. +zf=zipfile.ZipFile('bbb.zip', 'r') +test.fail_test(zf.testzip() is not None) +zf.close() + +files=zipfile_files('bbb.zip') +test.fail_test(zipfile_files('bbb.zip') != ['file2', 'sub2/file2'], + message='Zip file bbb.zip has wrong files: %s'%repr(files)) + + +test.pass_test() diff --git a/test/gnutools.py b/test/gnutools.py index e1b7e42..f79efe4 100644 --- a/test/gnutools.py +++ b/test/gnutools.py @@ -118,7 +118,7 @@ def testObject(test, obj, expect): line1 = contents.split('\n')[0] actual = ' '.join(line1.split()) if not expect == actual: - print "%s: %s != %s\n" % (obj, repr(expect), repr(actual)) + print("%s: %s != %s\n" % (obj, repr(expect), repr(actual))) test.fail_test() if sys.platform in ('win32', 'cygwin'): diff --git a/test/import.py b/test/import.py index ef5ee61..fb8a28c 100644 --- a/test/import.py +++ b/test/import.py @@ -185,8 +185,8 @@ for tool in tools: matched = 1 break if not matched: - print "Failed importing '%s', stderr:" % tool - print stderr + print("Failed importing '%s', stderr:" % tool) + print(stderr) failures.append(tool) test.fail_test(len(failures)) diff --git a/test/long-lines/signature.py b/test/long-lines/signature.py index bc5d11a..ce38bec 100644 --- a/test/long-lines/signature.py +++ b/test/long-lines/signature.py @@ -51,7 +51,7 @@ fp.write('FILEFLAG=%s\\n' % args[2]) fp.write('TIMESTAMP=%s\\n' % args[3]) """) -os.chmod(build_py, 0755) +os.chmod(build_py, 0o755) test.write('SConstruct', """\ arg = 'a_long_ignored_argument' diff --git a/test/option--random.py b/test/option--random.py index a9b9b9d..59592cb 100644 --- a/test/option--random.py +++ b/test/option--random.py @@ -66,7 +66,7 @@ tries = 0 max_tries = 10 while test.stdout() == non_random_output: if tries >= max_tries: - print "--random generated the non-random output %s times!" % max_tries + print("--random generated the non-random output %s times!" % max_tries) test.fail_test() tries = tries + 1 test.run(arguments = '-n -Q --random') @@ -84,7 +84,7 @@ tries = 0 max_tries = 10 while test.stdout() == non_random_output: if tries >= max_tries: - print "--random generated the non-random output %s times!" % max_tries + print("--random generated the non-random output %s times!" % max_tries) test.fail_test() tries = tries + 1 test.run(arguments = '-n -Q --random') diff --git a/test/option-v.py b/test/option-v.py index 680f541..8985db0 100644 --- a/test/option-v.py +++ b/test/option-v.py @@ -55,13 +55,13 @@ expect2 = r"""SCons by Steven Knight et al.: test.run(arguments = '-v') stdout = test.stdout() if not test.match_re(stdout, expect1) and not test.match_re(stdout, expect2): - print stdout + print(stdout) test.fail_test() test.run(arguments = '--version') stdout = test.stdout() if not test.match_re(stdout, expect1) and not test.match_re(stdout, expect2): - print stdout + print(stdout) test.fail_test() test.pass_test() diff --git a/test/option/debug-count.py b/test/option/debug-count.py index 3f8a23c..076d7fa 100644 --- a/test/option/debug-count.py +++ b/test/option/debug-count.py @@ -74,10 +74,10 @@ for args in ['-h --debug=count', '--debug=count']: missing = [o for o in objects if find_object_count(o, stdout) is None] if missing: - print "Missing the following object lines from '%s' output:" % args - print "\t", ' '.join(missing) - print "STDOUT ==========" - print stdout + print("Missing the following object lines from '%s' output:" % args) + print("\t", ' '.join(missing)) + print("STDOUT ==========") + print(stdout) test.fail_test(1) expect_warning = """ diff --git a/test/option/debug-time.py b/test/option/debug-time.py index 198d71d..7448e1c 100644 --- a/test/option/debug-time.py +++ b/test/option/debug-time.py @@ -20,7 +20,7 @@ # 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 + __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -164,7 +164,7 @@ outside of the 15%% tolerance. """ % locals()) if failures or warnings: - print '\n'.join([test.stdout()] + failures + warnings) + print('\n'.join([test.stdout()] + failures + warnings)) if failures: test.fail_test(1) @@ -172,7 +172,7 @@ test.run(arguments = "--debug=time . SLEEP=0") command_time = get_command_time(test.stdout()) if command_time != 0.0: - print "Up-to-date run received non-zero command time of %s" % command_time + print("Up-to-date run received non-zero command time of %s" % command_time) test.fail_test() @@ -201,14 +201,14 @@ outside of the 1%% tolerance. """ % locals()) if failures: - print '\n'.join([test.stdout()] + failures) + print('\n'.join([test.stdout()] + failures)) test.fail_test(1) test.run(arguments = "-j4 --debug=time . SLEEP=1") command_time = get_command_time(test.stdout()) if command_time != 0.0: - print "Up-to-date run received non-zero command time of %s" % command_time + print("Up-to-date run received non-zero command time of %s" % command_time) test.fail_test() diff --git a/test/option/help-options.py b/test/option/help-options.py index 45bbfa0..1b23cb3 100644 --- a/test/option/help-options.py +++ b/test/option/help-options.py @@ -60,8 +60,8 @@ options = [x[-1] == ',' and x[:-1] or x for x in options] lowered = [x.lower() for x in options] ordered = sorted(lowered) if lowered != ordered: - print "lowered =", lowered - print "sorted =", ordered + print("lowered =", lowered) + print("sorted =", ordered) test.fail_test() test.pass_test() diff --git a/test/option/profile.py b/test/option/profile.py index d53c690..513da47 100644 --- a/test/option/profile.py +++ b/test/option/profile.py @@ -36,7 +36,7 @@ else: # when we drop support for Python 2.6. class StringIO(_StringIO): def write(self, s): - _StringIO.write(self, unicode(s)) + _StringIO.write(self, str(s)) import TestSCons diff --git a/test/scons-time/run/config/python.py b/test/scons-time/run/config/python.py index 6cf965b..57b732d 100644 --- a/test/scons-time/run/config/python.py +++ b/test/scons-time/run/config/python.py @@ -53,7 +53,7 @@ for arg in sys.argv[1:]: print 'my_python.py: %s' % profile """) -os.chmod(my_python_py, 0755) +os.chmod(my_python_py, 0o755) test.run(arguments = 'run -f config foo.tar.gz') diff --git a/test/scons-time/run/option/python.py b/test/scons-time/run/option/python.py index a28e23f..70feb70 100644 --- a/test/scons-time/run/option/python.py +++ b/test/scons-time/run/option/python.py @@ -49,7 +49,7 @@ for arg in sys.argv[1:]: sys.stdout.write('my_python.py: %s\\n' % profile) """) -os.chmod(my_python_py, 0755) +os.chmod(my_python_py, 0o755) test.run(arguments = 'run --python %s foo.tar.gz' % my_python_py) diff --git a/test/sconsign/nonwritable.py b/test/sconsign/nonwritable.py index 913dcf1..5ae55bb 100644 --- a/test/sconsign/nonwritable.py +++ b/test/sconsign/nonwritable.py @@ -78,7 +78,7 @@ test.write(['work1', 'foo.in'], "work1/foo.in\n") test.write(work1__sconsign_dblite, "") -os.chmod(work1__sconsign_dblite, 0444) +os.chmod(work1__sconsign_dblite, 0o444) test.run(chdir='work1', arguments='.') @@ -95,7 +95,7 @@ test.write(['work2', 'foo.in'], "work2/foo.in\n") pickle.dump({}, open(work2_sub1__sconsign, 'wb'), 1) pickle.dump({}, open(work2_sub2__sconsign, 'wb'), 1) -os.chmod(work2_sub1__sconsign, 0444) +os.chmod(work2_sub1__sconsign, 0o444) test.run(chdir='work2', arguments='.') diff --git a/test/sconsign/script/SConsignFile.py b/test/sconsign/script/SConsignFile.py index a9f79f4..71a7e6d 100644 --- a/test/sconsign/script/SConsignFile.py +++ b/test/sconsign/script/SConsignFile.py @@ -86,8 +86,8 @@ output.write(input.read()) sys.exit(0) """) -test.chmod(fake_cc_py, 0755) -test.chmod(fake_link_py, 0755) +test.chmod(fake_cc_py, 0o755) +test.chmod(fake_link_py, 0o755) # Note: We don't use os.path.join() representations of the file names # in the expected output because paths in the .sconsign files are diff --git a/test/sconsign/script/Signatures.py b/test/sconsign/script/Signatures.py index cfd2a7f..5babe67 100644 --- a/test/sconsign/script/Signatures.py +++ b/test/sconsign/script/Signatures.py @@ -105,8 +105,8 @@ output.write(input.read()) sys.exit(0) """) -test.chmod(fake_cc_py, 0755) -test.chmod(fake_link_py, 0755) +test.chmod(fake_cc_py, 0o755) +test.chmod(fake_link_py, 0o755) test.write('SConstruct', """ SConsignFile(None) diff --git a/test/sconsign/script/no-SConsignFile.py b/test/sconsign/script/no-SConsignFile.py index 829d650..70b18c8 100644 --- a/test/sconsign/script/no-SConsignFile.py +++ b/test/sconsign/script/no-SConsignFile.py @@ -94,8 +94,8 @@ output.write(input.read()) sys.exit(0) """) -test.chmod(fake_cc_py, 0755) -test.chmod(fake_link_py, 0755) +test.chmod(fake_cc_py, 0o755) +test.chmod(fake_link_py, 0o755) # Note: We don't use os.path.join() representations of the file names # in the expected output because paths in the .sconsign files are diff --git a/test/site_scons/sysdirs.py b/test/site_scons/sysdirs.py index c05ef67..d05f6a4 100644 --- a/test/site_scons/sysdirs.py +++ b/test/site_scons/sysdirs.py @@ -1,71 +1,71 @@ -#!/usr/bin/env python -# -# __COPYRIGHT__ -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# 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. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -import TestSCons - -""" -Verify site_scons system dirs are getting loaded. -Uses an internal test fixture to get at the site_scons dirs. - -TODO: it would be great to test if it can actually load site_scons -files from the system dirs, but the test harness can't put files in -those dirs (which may not even exist on a build system). -""" - -test = TestSCons.TestSCons() - -test.write('SConstruct', """ -import SCons.Script -SCons.Script.Main.test_load_all_site_scons_dirs(Dir('.').path) -""") - -test.run(arguments = '-Q .') - -import SCons.Platform -platform = SCons.Platform.platform_default() -if platform in ('win32', 'cygwin'): - dir_to_check_for='Application Data' -elif platform in ('darwin'): - dir_to_check_for='Library' -else: - dir_to_check_for='.scons' - -if 'Loading site dir' not in test.stdout(): - print test.stdout() - test.fail_test() -if dir_to_check_for not in test.stdout(): - print test.stdout() - test.fail_test() - -test.pass_test() - -# end of file - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# 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. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import TestSCons + +""" +Verify site_scons system dirs are getting loaded. +Uses an internal test fixture to get at the site_scons dirs. + +TODO: it would be great to test if it can actually load site_scons +files from the system dirs, but the test harness can't put files in +those dirs (which may not even exist on a build system). +""" + +test = TestSCons.TestSCons() + +test.write('SConstruct', """ +import SCons.Script +SCons.Script.Main.test_load_all_site_scons_dirs(Dir('.').path) +""") + +test.run(arguments = '-Q .') + +import SCons.Platform +platform = SCons.Platform.platform_default() +if platform in ('win32', 'cygwin'): + dir_to_check_for='Application Data' +elif platform in ('darwin'): + dir_to_check_for='Library' +else: + dir_to_check_for='.scons' + +if 'Loading site dir' not in test.stdout(): + print(test.stdout()) + test.fail_test() +if dir_to_check_for not in test.stdout(): + print(test.stdout()) + test.fail_test() + +test.pass_test() + +# end of file + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/spaces.py b/test/spaces.py index db1ae97..1309047 100644 --- a/test/spaces.py +++ b/test/spaces.py @@ -36,7 +36,7 @@ if sys.platform == 'win32': else: test.write('duplicate a file.sh', 'cp foo.in foo.out\n') copy = test.workpath('duplicate a file.sh') - os.chmod(test.workpath('duplicate a file.sh'), 0777) + os.chmod(test.workpath('duplicate a file.sh'), 0o777) test.write('SConstruct', r''' diff --git a/test/subdivide.py b/test/subdivide.py index 2978e08..44402c9 100644 --- a/test/subdivide.py +++ b/test/subdivide.py @@ -76,8 +76,8 @@ for s in sys.argv[2:]: ofp.write(open(s, 'rb').read()) """) -test.chmod(fake_cc_py, 0755) -test.chmod(fake_link_py, 0755) +test.chmod(fake_cc_py, 0o755) +test.chmod(fake_link_py, 0o755) test.write('SConstruct', """\ SConsignFile(None) diff --git a/test/update-release-info/update-release-info.py b/test/update-release-info/update-release-info.py index d3125c7..0db65ba 100644 --- a/test/update-release-info/update-release-info.py +++ b/test/update-release-info/update-release-info.py @@ -201,7 +201,7 @@ RELEASE 2.0.0.alpha.yyyymmdd - NEW DATE WILL BE INSERTED HERE """, mode = 'r') -years = ', '.join(map(str, range(2001, this_year + 1))) +years = ', '.join(map(str, list(range(2001, this_year + 1)))) test.must_match(SConstruct, """ month_year = 'MONTH YEAR' copyright_years = %s diff --git a/timings/ElectricCloud/TimeSCons-run.py b/timings/ElectricCloud/TimeSCons-run.py index be75d12..fbe0028 100644 --- a/timings/ElectricCloud/TimeSCons-run.py +++ b/timings/ElectricCloud/TimeSCons-run.py @@ -87,7 +87,7 @@ test.run(program=test.workpath('genscons.pl'), arguments=' '.join(arguments)) # This print is nott for debugging, leave it alone! # We want to display the output from genscons.pl's generation the build # configuration, so the buildbot logs contain more info. -print test.stdout() +print(test.stdout()) test.main(chdir='sconsbld') diff --git a/www/gen_sched_table.py b/www/gen_sched_table.py index e67f0d7..9ac8acd 100755 --- a/www/gen_sched_table.py +++ b/www/gen_sched_table.py @@ -6,13 +6,13 @@ import datetime months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] -print '' +print('
') def row(*cells, **kw): td = kw.get('tr','td') - print ' ' + print(' ') for cell in cells: - print ' <%s>%s' % (td,cell,td) - print ' ' + print(' <%s>%s' % (td,cell,td)) + print(' ') row('Estimated date', 'Type', 'Comments', tr = 'th') if len(sys.argv) > 1: @@ -30,7 +30,7 @@ for line in f: incr,type,desc = line[1:].strip().split(None,2) now = now + datetime.timedelta(int(incr)) else: - print 'dunna understand code', line[0] + print('dunna understand code', line[0]) sys.exit(1) #name = current + '.d' + str(now).replace('-','') date = '%s-%s-%s' % (now.day,months[now.month-1],now.year) @@ -41,7 +41,7 @@ for line in f: else: category = current = type row(date, category, desc) -print '
' +print('') # Local Variables: # tab-width:4 -- cgit v0.12 From b554eb817c60f4e419bbc84efc02c7fbc62b7ced Mon Sep 17 00:00:00 2001 From: Gary Oberbrunner Date: Sun, 22 Sep 2013 13:10:51 -0400 Subject: Manual python3 post-2to3 fixes from Neal Becker --- review.py | 2 +- src/engine/SCons/Action.py | 32 +++++++++++++++++++------------- src/engine/SCons/Conftest.py | 1 - src/engine/SCons/Errors.py | 4 +--- src/engine/SCons/Executor.py | 2 +- src/engine/SCons/SConf.py | 16 +++++++++++----- src/engine/SCons/Scanner/__init__.py | 2 +- src/engine/SCons/Script/SConscript.py | 2 +- src/engine/SCons/Script/__init__.py | 2 +- src/engine/SCons/Taskmaster.py | 10 +++------- src/engine/SCons/Tool/__init__.py | 4 ++-- src/engine/SCons/Tool/g++.py | 5 ++--- src/engine/SCons/Tool/gas.py | 5 ++++- src/engine/SCons/Tool/gcc.py | 2 +- src/engine/SCons/Tool/link.py | 2 +- src/engine/SCons/Tool/swig.py | 2 +- src/engine/SCons/Util.py | 19 +++++++++++++++---- src/engine/SCons/dblite.py | 16 ++++++---------- src/script/scons.py | 10 +++++----- 19 files changed, 76 insertions(+), 62 deletions(-) diff --git a/review.py b/review.py index 72e187e..8d033ed 100644 --- a/review.py +++ b/review.py @@ -1627,7 +1627,7 @@ def FormatSubversionPropertyChanges(filename, props): See the following doctest for example. - >>> print FormatSubversionPropertyChanges('foo.cc', [('svn:eol-style', 'LF')]) + >>> print(FormatSubversionPropertyChanges('foo.cc', [('svn:eol-style', 'LF')])) Property changes on: foo.cc ___________________________________________________________________ Added: svn:eol-style diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index e8574cb..68c93b4 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -237,9 +237,9 @@ def _code_contents(code): # The code contents depends on the number of local variables # but not their actual names. - contents.append("%s,%s" % (code.co_argcount, len(code.co_varnames))) + contents.append(str.encode("%s,%s" % (code.co_argcount, len(code.co_varnames)))) try: - contents.append(",%s,%s" % (len(code.co_cellvars), len(code.co_freevars))) + contents.append(str.encode(",%s,%s" % (len(code.co_cellvars), len(code.co_freevars)))) except AttributeError: # Older versions of Python do not support closures. contents.append(",0,0") @@ -252,19 +252,19 @@ def _code_contents(code): # Note that we also always ignore the first entry of co_consts # which contains the function doc string. We assume that the # function does not access its doc string. - contents.append(',(' + ','.join(map(_object_contents,code.co_consts[1:])) + ')') + contents.append(b',(' + b','.join(map(_object_contents,code.co_consts[1:])) + b')') # The code contents depends on the variable names used to # accessed global variable, as changing the variable name changes # the variable actually accessed and therefore changes the # function result. - contents.append(',(' + ','.join(map(_object_contents,code.co_names)) + ')') + contents.append(b',(' + b','.join(map(_object_contents,code.co_names)) + b')') # The code contents depends on its actual code!!! - contents.append(',(' + str(remove_set_lineno_codes(code.co_code)) + ')') + contents.append(b',(' + remove_set_lineno_codes(code.co_code) + b')') - return ''.join(contents) + return b''.join(contents) def _function_contents(func): @@ -274,9 +274,9 @@ def _function_contents(func): # The function contents depends on the value of defaults arguments if func.__defaults__: - contents.append(',(' + ','.join(map(_object_contents,func.__defaults__)) + ')') + contents.append(b',(' + b','.join(map(_object_contents,func.__defaults__)) + b')') else: - contents.append(',()') + contents.append(b',()') # The function contents depends on the closure captured cell values. try: @@ -290,9 +290,9 @@ def _function_contents(func): xxx = [_object_contents(x.cell_contents) for x in closure] except AttributeError: xxx = [] - contents.append(',(' + ','.join(xxx) + ')') + contents.append(b',(' + b','.join(xxx) + b')') - return ''.join(contents) + return b''.join(contents) def _actionAppend(act1, act2): @@ -434,14 +434,20 @@ class ActionBase(object): def get_contents(self, target, source, env): result = [ self.get_presig(target, source, env) ] + def clean (u): + if isinstance (u, bytes): + return u + elif isinstance (u, str): + return bytes (u, 'utf-8') + result = [ clean(r) for r in result ] # This should never happen, as the Action() factory should wrap # the varlist, but just in case an action is created directly, # we duplicate this check here. vl = self.get_varlist(target, source, env) if is_String(vl): vl = (vl,) for v in vl: - result.append(env.subst('${'+v+'}')) - return ''.join(result) + result.append(bytes(env.subst('${'+v+'}'), 'utf-8')) + return b''.join(result) def __add__(self, other): return _actionAppend(self, other) @@ -1135,7 +1141,7 @@ class ListAction(ActionBase): Simple concatenation of the signatures of the elements. """ - return "".join([x.get_contents(target, source, env) for x in self.list]) + return b"".join([x.get_contents(target, source, env) for x in self.list]) def __call__(self, target, source, env, exitstatfunc=_null, presub=_null, show=_null, execute=_null, chdir=_null, executor=None): diff --git a/src/engine/SCons/Conftest.py b/src/engine/SCons/Conftest.py index d466278..4e2a3e8 100644 --- a/src/engine/SCons/Conftest.py +++ b/src/engine/SCons/Conftest.py @@ -101,7 +101,6 @@ Autoconf-like configuration support; low level implementation of tests. # import re -from types import IntType # # PUBLIC VARIABLES diff --git a/src/engine/SCons/Errors.py b/src/engine/SCons/Errors.py index 3b8c3f9..54e888c 100644 --- a/src/engine/SCons/Errors.py +++ b/src/engine/SCons/Errors.py @@ -32,8 +32,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Util -import exceptions - class BuildError(Exception): """ Errors occuring while building. @@ -163,7 +161,7 @@ def convert_to_BuildError(status, exc_info=None): status=2, exitstatus=2, exc_info=exc_info) - elif isinstance(status, exceptions.EnvironmentError): + elif isinstance(status, EnvironmentError): # If an IOError/OSError happens, raise a BuildError. # Report the name of the file or directory that caused the # error, which might be different from the target being built diff --git a/src/engine/SCons/Executor.py b/src/engine/SCons/Executor.py index 6f2489b..68419b8 100644 --- a/src/engine/SCons/Executor.py +++ b/src/engine/SCons/Executor.py @@ -427,7 +427,7 @@ class Executor(object): except KeyError: pass env = self.get_build_env() - result = "".join([action.get_contents(self.get_all_targets(), + result = b"".join([action.get_contents(self.get_all_targets(), self.get_all_sources(), env) for action in self.get_action_list()]) diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index 987f88d..e14c5e0 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -175,13 +175,19 @@ class Streamer(object): """ def __init__(self, orig): self.orig = orig - self.s = io.StringIO() + try: + import StringIO + self.s = StringIO.StringIO() + except: + self.s = io.StringIO() def write(self, str): - if self.orig: - self.orig.write(str) - self.s.write(str) - + try: + if self.orig: + self.orig.write(str) + self.s.write(str) + except: + print ('oops') def writelines(self, lines): for l in lines: self.write(l + '\n') diff --git a/src/engine/SCons/Scanner/__init__.py b/src/engine/SCons/Scanner/__init__.py index 6ec8df9..8801094 100644 --- a/src/engine/SCons/Scanner/__init__.py +++ b/src/engine/SCons/Scanner/__init__.py @@ -325,7 +325,7 @@ class Classic(Current): def __init__(self, name, suffixes, path_variable, regex, *args, **kw): - self.cre = re.compile(regex, re.M) + self.cre = re.compile(SCons.Util.to_bytes(regex), re.M) def _scan(node, env, path=(), self=self): node = node.rfile() diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py index fefffef..05cb6a6 100644 --- a/src/engine/SCons/Script/SConscript.py +++ b/src/engine/SCons/Script/SConscript.py @@ -257,7 +257,7 @@ def _SConscript(fs, *files, **kw): pass try: try: - exec(_file_, call_stack[-1].globals) + exec(_file_.read(), call_stack[-1].globals) except SConscriptReturn: pass finally: diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py index 9f2837c..e9e8b71 100644 --- a/src/engine/SCons/Script/__init__.py +++ b/src/engine/SCons/Script/__init__.py @@ -364,7 +364,7 @@ GlobalDefaultBuilders = [ ] for name in GlobalDefaultEnvironmentFunctions + GlobalDefaultBuilders: - exec("%s = _SConscript.DefaultEnvironmentCall(%s)" % (name, repr(name))) + exec ("%s = _SConscript.DefaultEnvironmentCall(%s)" % (name, repr(name))) del name # There are a handful of variables that used to live in the diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py index 54d04a8..14ffe8c 100644 --- a/src/engine/SCons/Taskmaster.py +++ b/src/engine/SCons/Taskmaster.py @@ -518,13 +518,9 @@ class Task(object): Raises a pending exception that was recorded while getting a Task ready for execution. """ - exc = self.exc_info()[:] - try: - exc_type, exc_value, exc_traceback = exc - except ValueError: - exc_type, exc_value = exc - exc_traceback = None - raise exc_type(exc_value).with_traceback(exc_traceback) + + import six + six.reraise(*self.exc_info()) class AlwaysTask(Task): def needs_execute(self): diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index ac180a9..1d5b504 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -114,7 +114,7 @@ class Tool(object): if file: file.close() except ImportError as e: - if str(e)!="No module named %s"%self.name: + if not str(e).startswith ("No module"): raise SCons.Errors.EnvironmentError(e) try: import zipimport @@ -144,7 +144,7 @@ class Tool(object): file.close() return module except ImportError as e: - if str(e)!="No module named %s"%self.name: + if not str(e).startswith("No module"): raise SCons.Errors.EnvironmentError(e) try: import zipimport diff --git a/src/engine/SCons/Tool/g++.py b/src/engine/SCons/Tool/g++.py index e4da5fe..0e1c181 100644 --- a/src/engine/SCons/Tool/g++.py +++ b/src/engine/SCons/Tool/g++.py @@ -40,8 +40,7 @@ import subprocess import SCons.Tool import SCons.Util -cplusplus = __import__('c++', globals(), locals(), []) - +cplusplus = __import__(__package__+'.c++', globals(), locals(), ['*']) compilers = ['g++'] def generate(env): @@ -75,7 +74,7 @@ def generate(env): #line = pipe.stdout.read().strip() #if line: # env['CXXVERSION'] = line - line = pipe.stdout.readline() + line = SCons.Util.to_str (pipe.stdout.readline()) match = re.search(r'[0-9]+(\.[0-9]+)+', line) if match: env['CXXVERSION'] = match.group(0) diff --git a/src/engine/SCons/Tool/gas.py b/src/engine/SCons/Tool/gas.py index 28f84db..d01bd60 100644 --- a/src/engine/SCons/Tool/gas.py +++ b/src/engine/SCons/Tool/gas.py @@ -33,7 +33,10 @@ selection method. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -as_module = __import__('as', globals(), locals(), []) +try: + as_module = __import__('as', globals(), locals(), []) +except: + as_module = __import__(__package__+'.as', globals(), locals(), ['*']) assemblers = ['as', 'gas'] diff --git a/src/engine/SCons/Tool/gcc.py b/src/engine/SCons/Tool/gcc.py index 4f87b24..72f9bfd 100644 --- a/src/engine/SCons/Tool/gcc.py +++ b/src/engine/SCons/Tool/gcc.py @@ -65,7 +65,7 @@ def generate(env): #line = pipe.stdout.read().strip() #if line: # env['CCVERSION'] = line - line = pipe.stdout.readline() + line = SCons.Util.to_str (pipe.stdout.readline()) match = re.search(r'[0-9]+(\.[0-9]+)+', line) if match: env['CCVERSION'] = match.group(0) diff --git a/src/engine/SCons/Tool/link.py b/src/engine/SCons/Tool/link.py index 5539f62..864a018 100644 --- a/src/engine/SCons/Tool/link.py +++ b/src/engine/SCons/Tool/link.py @@ -42,7 +42,7 @@ import SCons.Warnings from SCons.Tool.FortranCommon import isfortran -cplusplus = __import__('c++', globals(), locals(), []) +cplusplus = __import__(__package__+'.c++', globals(), locals(), ['*']) issued_mixed_link_warning = False diff --git a/src/engine/SCons/Tool/swig.py b/src/engine/SCons/Tool/swig.py index d51a386..5d2264c 100644 --- a/src/engine/SCons/Tool/swig.py +++ b/src/engine/SCons/Tool/swig.py @@ -131,7 +131,7 @@ def _get_swig_version(env): stdout = subprocess.PIPE) if pipe.wait() != 0: return - out = pipe.stdout.read() + out = SCons.Util.to_str (pipe.stdout.read()) match = re.search(r'SWIG Version\s+(\S+)$', out, re.MULTILINE) if match: return match.group(1) diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index f2e5325..00fde6c 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -37,7 +37,6 @@ import collections # Don't "from types import ..." these because we need to get at the # types module later to look for UnicodeType. -InstanceType = types.InstanceType MethodType = types.MethodType FunctionType = types.FunctionType try: str @@ -1370,7 +1369,7 @@ def AddMethod(obj, function, name=None): setattr(obj, name, MethodType(function, obj, obj.__class__)) else: # "obj" is a class, so it gets an unbound method. - setattr(obj, name, MethodType(function, None, obj)) + setattr(obj, name, function) def RenameFunction(function, name): """ @@ -1402,7 +1401,7 @@ else: md5 = True def MD5signature(s): m = hashlib.md5() - m.update(str(s)) + m.update(to_bytes(str(s))) return m.hexdigest() def MD5filesignature(fname, chunksize=65536): @@ -1412,7 +1411,7 @@ else: blck = f.read(chunksize) if not blck: break - m.update(str(blck)) + m.update(to_bytes (str(blck))) f.close() return m.hexdigest() @@ -1486,6 +1485,18 @@ class NullSeq(Null): del __revision__ +def to_bytes (s): + if bytes is str: + return s + else: + return bytes (s, 'utf-8') + +def to_str (s): + if bytes is str: + return s + else: + return str (s, 'utf-8') + # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/src/engine/SCons/dblite.py b/src/engine/SCons/dblite.py index 89b9856..99af54a 100644 --- a/src/engine/SCons/dblite.py +++ b/src/engine/SCons/dblite.py @@ -16,14 +16,10 @@ ignore_corrupt_dbfiles = 0 def corruption_warning(filename): print("Warning: Discarding corrupt database:", filename) -try: str -except NameError: - def is_string(s): - return isinstance(s, str) -else: - def is_string(s): - return type(s) in (str, str) - +def is_string(s): + return isinstance(s, str) +def is_bytes(s): + return isinstance (s, bytes) try: str('a') except NameError: @@ -148,8 +144,8 @@ class dblite(object): self._check_writable() if (not is_string(key)): raise TypeError("key `%s' must be a string but is %s" % (key, type(key))) - if (not is_string(value)): - raise TypeError("value `%s' must be a string but is %s" % (value, type(value))) + if (not is_bytes(value)): + raise TypeError("value `%s' must be a bytes but is %s" % (value, type(value))) self._dict[key] = value self._needs_sync = 0o001 diff --git a/src/script/scons.py b/src/script/scons.py index 46e6d2b..89eef34 100644 --- a/src/script/scons.py +++ b/src/script/scons.py @@ -55,11 +55,11 @@ import sys # engine modules if they're in either directory. -if sys.version_info >= (3,0,0): - msg = "scons: *** SCons version %s does not run under Python version %s.\n\ -Python 3 is not yet supported.\n" - sys.stderr.write(msg % (__version__, sys.version.split()[0])) - sys.exit(1) +## if sys.version_info >= (3,0,0): +## msg = "scons: *** SCons version %s does not run under Python version %s.\n\ +## Python 3 is not yet supported.\n" +## sys.stderr.write(msg % (__version__, sys.version.split()[0])) +## sys.exit(1) script_dir = sys.path[0] -- cgit v0.12 From 0727ee61d6ec6eeb099b0d179fa77a1a86046ee8 Mon Sep 17 00:00:00 2001 From: ndbecker2 Date: Mon, 9 Sep 2013 10:14:53 -0400 Subject: 2 minor issues (transplanted from 6711a6b819f61764bb82c0f32a251b91ec66a0b2) --- QMTest/TestCmd.py | 3 ++- src/engine/SCons/Action.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/QMTest/TestCmd.py b/QMTest/TestCmd.py index 4f08d1f..26401ad 100644 --- a/QMTest/TestCmd.py +++ b/QMTest/TestCmd.py @@ -1,3 +1,4 @@ +from __future__ import print_function """ TestCmd.py: a testing framework for commands and scripts. @@ -950,7 +951,7 @@ class TestCmd(object): condition = self.condition if self._preserve[condition]: for dir in self._dirlist: - print(str("Preserved directory " + dir + "\n"), end=' ') + print("Preserved directory " + dir + "\n", end=' ') else: list = self._dirlist[:] list.reverse() diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index 68c93b4..7a97dae 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -446,7 +446,7 @@ class ActionBase(object): vl = self.get_varlist(target, source, env) if is_String(vl): vl = (vl,) for v in vl: - result.append(bytes(env.subst('${'+v+'}'), 'utf-8')) + result.append(SCons.Util.to_bytes(env.subst('${'+v+'}'))) return b''.join(result) def __add__(self, other): -- cgit v0.12 From 8473d8293b056663f8a3caf04550039b18690a70 Mon Sep 17 00:00:00 2001 From: ndbecker2 Date: Mon, 9 Sep 2013 10:39:46 -0400 Subject: minor cleanup (transplanted from 4feb1b15eb7a0c76cb020e09817c509a782d45b7) --- src/engine/SCons/Action.py | 7 +------ src/engine/SCons/Util.py | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index 7a97dae..66757a4 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -434,12 +434,7 @@ class ActionBase(object): def get_contents(self, target, source, env): result = [ self.get_presig(target, source, env) ] - def clean (u): - if isinstance (u, bytes): - return u - elif isinstance (u, str): - return bytes (u, 'utf-8') - result = [ clean(r) for r in result ] + result = [ SCons.Util.to_bytes(r) for r in result ] # This should never happen, as the Action() factory should wrap # the varlist, but just in case an action is created directly, # we duplicate this check here. diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 00fde6c..0c4daff 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -1486,7 +1486,7 @@ class NullSeq(Null): del __revision__ def to_bytes (s): - if bytes is str: + if isinstance (s, bytes) or bytes is str: return s else: return bytes (s, 'utf-8') -- cgit v0.12 From 7dd07e75f428379c90eb9bb486b79ad103283bf6 Mon Sep 17 00:00:00 2001 From: ndbecker2 Date: Mon, 9 Sep 2013 12:03:44 -0400 Subject: fix for cpp scanner (maybe) (transplanted from c68b1a5da5ad47befc3a7e802d8ae23372f0e1a8) --- src/engine/SCons/Scanner/__init__.py | 3 ++- src/engine/SCons/dblite.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/engine/SCons/Scanner/__init__.py b/src/engine/SCons/Scanner/__init__.py index 8801094..b947961 100644 --- a/src/engine/SCons/Scanner/__init__.py +++ b/src/engine/SCons/Scanner/__init__.py @@ -394,6 +394,7 @@ class ClassicCPP(Classic): the contained filename in group 1. """ def find_include(self, include, source_dir, path): + include = list (map (SCons.Util.to_str, include)) if include[0] == '"': paths = (source_dir,) + tuple(path) else: @@ -405,7 +406,7 @@ class ClassicCPP(Classic): return n, i def sort_key(self, include): - return SCons.Node.FS._my_normcase(' '.join(include)) + return SCons.Node.FS._my_normcase(b' '.join(include)) # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/dblite.py b/src/engine/SCons/dblite.py index 99af54a..4b02239 100644 --- a/src/engine/SCons/dblite.py +++ b/src/engine/SCons/dblite.py @@ -26,6 +26,8 @@ except NameError: def str(s): return s dblite_suffix = '.dblite' +if bytes is not str: + dblite_suffix += '.p3' tmp_suffix = '.tmp' class dblite(object): @@ -238,7 +240,6 @@ def _exercise(): assert str(e) == "[Errno 2] No such file or directory: 'tmp.dblite'", str(e) else: raise RuntimeError("IOError expected.") - print("OK") if (__name__ == "__main__"): _exercise() -- cgit v0.12 From 9f36c5b899b8d2d54cae8d3da76b01308c144ed6 Mon Sep 17 00:00:00 2001 From: ndbecker2 Date: Tue, 10 Sep 2013 10:02:23 -0400 Subject: setup.py: don't error on py3 (transplanted from 16fc64cadd68f2f9032c14d04bc0bf94f99b71a4) --- src/setup.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/setup.py b/src/setup.py index a8b59a3..2c75c60 100644 --- a/src/setup.py +++ b/src/setup.py @@ -46,14 +46,6 @@ man_pages = [ 'scons-time.1', ] -# Exit with error if trying to install with Python >= 3.0 -if sys.version_info >= (3,0,0): - msg = "scons: *** SCons does not run under Python version %s.\n\ -Python 3 and above are not yet supported.\n" - sys.stderr.write(msg % (sys.version.split()[0])) - sys.exit(1) - - # change to setup.py directory if it was executed from other dir (head, tail) = os.path.split(sys.argv[0]) if head: -- cgit v0.12 From 1a1a11122ad28df19d305af879ba79a2b08ce7d4 Mon Sep 17 00:00:00 2001 From: Stefan Zimmermann Date: Mon, 31 Mar 2014 15:13:02 +0000 Subject: Made former 2to3 changes Python 2.7 compatible (or removed unneeded changes). --- QMTest/TestCmd.py | 7 +- QMTest/TestCmdTests.py | 109 ++++++++-------- QMTest/TestCommon.py | 1 + QMTest/TestSCons.py | 12 +- QMTest/TestSConsign.py | 1 + QMTest/scons_tdb.py | 4 +- SConstruct | 15 +-- bench/bench.py | 4 +- bench/env.__setitem__.py | 4 +- bench/is_types.py | 12 +- bench/timeit.py | 4 +- bin/Command.py | 1 + bin/SConsDoc.py | 9 +- bin/calibrate.py | 2 +- bin/caller-tree.py | 3 +- bin/docs-create-example-outputs.py | 1 + bin/docs-update-generated.py | 1 + bin/docs-validate.py | 1 + bin/install_python.py | 1 + bin/install_scons.py | 8 +- bin/linecount.py | 2 +- bin/memlogs.py | 1 + bin/memoicmp.py | 9 +- bin/objcounts.py | 5 +- bin/scons-diff.py | 5 +- bin/scons-proc.py | 4 +- bin/scons-test.py | 5 +- bin/scons-unzip.py | 1 + bin/scons_dev_master.py | 1 + bin/sfsum | 11 +- bin/svn-bisect.py | 2 +- bin/update-release-info.py | 3 +- bin/xmlagenda.py | 1 + doc/SConscript | 25 ++-- review.py | 139 ++++++++++++--------- runtest.py | 8 +- src/engine/SCons/Action.py | 19 ++- src/engine/SCons/ActionTests.py | 8 +- src/engine/SCons/Builder.py | 21 ++-- src/engine/SCons/BuilderTests.py | 9 +- src/engine/SCons/Conftest.py | 2 +- src/engine/SCons/Debug.py | 4 +- src/engine/SCons/Defaults.py | 7 +- src/engine/SCons/Environment.py | 33 +++-- src/engine/SCons/EnvironmentTests.py | 17 +-- src/engine/SCons/Executor.py | 4 +- src/engine/SCons/Memoize.py | 1 + src/engine/SCons/MemoizeTests.py | 5 +- src/engine/SCons/Node/FS.py | 10 +- src/engine/SCons/Node/FSTests.py | 4 +- src/engine/SCons/Node/__init__.py | 4 +- src/engine/SCons/Platform/__init__.py | 1 + src/engine/SCons/Platform/posix.py | 2 +- src/engine/SCons/SConf.py | 21 ++-- src/engine/SCons/SConfTests.py | 2 +- src/engine/SCons/SConsign.py | 9 +- src/engine/SCons/Scanner/Fortran.py | 3 +- src/engine/SCons/Scanner/LaTeX.py | 4 +- src/engine/SCons/Scanner/Prog.py | 3 +- src/engine/SCons/Scanner/ProgTests.py | 2 +- src/engine/SCons/Scanner/ScannerTests.py | 2 +- src/engine/SCons/Scanner/__init__.py | 5 +- src/engine/SCons/Script/Interactive.py | 5 +- src/engine/SCons/Script/Main.py | 7 +- src/engine/SCons/Script/SConsOptions.py | 2 +- src/engine/SCons/Script/SConscript.py | 4 +- src/engine/SCons/Subst.py | 4 +- src/engine/SCons/SubstTests.py | 1 + src/engine/SCons/Taskmaster.py | 29 ++--- src/engine/SCons/TaskmasterTests.py | 2 +- src/engine/SCons/Tool/FortranCommon.py | 5 +- src/engine/SCons/Tool/MSCommon/common.py | 5 +- src/engine/SCons/Tool/MSCommon/vc.py | 2 +- src/engine/SCons/Tool/MSCommon/vs.py | 2 +- src/engine/SCons/Tool/__init__.py | 3 +- .../docbook-xsl-1.76.1/extensions/docbook.py | 1 + .../docbook/docbook-xsl-1.76.1/extensions/xslt.py | 1 + src/engine/SCons/Tool/install.py | 1 + src/engine/SCons/Tool/intelc.py | 6 +- src/engine/SCons/Tool/link.py | 1 + src/engine/SCons/Tool/mslink.py | 3 +- src/engine/SCons/Tool/msvs.py | 17 +-- src/engine/SCons/Tool/msvsTests.py | 1 + src/engine/SCons/Tool/packaging/__init__.py | 2 +- src/engine/SCons/Tool/packaging/ipk.py | 2 +- src/engine/SCons/Tool/packaging/msi.py | 6 +- src/engine/SCons/Tool/packaging/rpm.py | 4 +- src/engine/SCons/Tool/qt.py | 1 + src/engine/SCons/Tool/rpmutils.py | 1 + src/engine/SCons/Tool/tex.py | 1 + src/engine/SCons/Tool/textfile.py | 3 +- src/engine/SCons/Tool/xgettext.py | 3 +- src/engine/SCons/Util.py | 61 ++++++--- src/engine/SCons/UtilTests.py | 17 +-- src/engine/SCons/Variables/EnumVariableTests.py | 4 +- src/engine/SCons/Variables/__init__.py | 2 +- src/engine/SCons/compat/_scons_subprocess.py | 12 +- src/engine/SCons/cpp.py | 11 +- src/engine/SCons/cppTests.py | 2 +- src/engine/SCons/dblite.py | 26 ++-- src/script/scons-time.py | 12 +- src/script/sconsign.py | 10 +- src/test_files.py | 3 +- src/test_interrupts.py | 2 +- src/test_pychecker.py | 1 + src/test_setup.py | 1 + src/test_strings.py | 1 + test/AS/nasm.py | 2 +- test/Actions/unicode-signature.py | 12 +- test/AddOption/help.py | 1 + test/Configure/ConfigureDryRunError.py | 1 + test/Configure/config-h.py | 1 + test/Configure/implicit-cache.py | 1 + test/Deprecated/SourceCode/BitKeeper/BitKeeper.py | 1 + test/Deprecated/SourceCode/Subversion.py | 1 + test/GetBuildFailures/parallel.py | 1 + test/Glob/glob-libpath.py | 1 + test/Interactive/version.py | 1 + test/Java/multi-step.py | 1 + test/MSVC/msvc.py | 1 + test/QT/QTFLAGS.py | 2 +- test/QT/copied-env.py | 1 + test/QT/warnings.py | 1 + test/Scanner/unicode.py | 20 +-- test/TEX/TEX.py | 1 + test/Value.py | 1 + test/Win32/bad-drive.py | 1 + test/Win32/default-drive.py | 1 + test/gnutools.py | 1 + test/import.py | 1 + test/option--random.py | 1 + test/option-v.py | 1 + test/option/debug-count.py | 1 + test/option/debug-time.py | 2 +- test/option/help-options.py | 1 + test/option/profile.py | 4 +- test/site_scons/sysdirs.py | 1 + test/update-release-info/update-release-info.py | 2 +- timings/ElectricCloud/TimeSCons-run.py | 1 + www/gen_sched_table.py | 1 + 140 files changed, 566 insertions(+), 418 deletions(-) diff --git a/QMTest/TestCmd.py b/QMTest/TestCmd.py index 26401ad..488d940 100644 --- a/QMTest/TestCmd.py +++ b/QMTest/TestCmd.py @@ -1,4 +1,3 @@ -from __future__ import print_function """ TestCmd.py: a testing framework for commands and scripts. @@ -286,7 +285,7 @@ version. # PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, # AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - +from __future__ import division, print_function __author__ = "Steven Knight " __revision__ = "TestCmd.py 1.3.D001 2010/06/03 12:58:27 knight" @@ -356,7 +355,7 @@ except NameError: return isinstance(e, (str, UserString)) else: def is_String(e): - return isinstance(e, (str, UserString)) + return isinstance(e, (str, unicode, UserString)) tempfile.template = 'testcmd.' if os.name in ('posix', 'nt'): @@ -951,7 +950,7 @@ class TestCmd(object): condition = self.condition if self._preserve[condition]: for dir in self._dirlist: - print("Preserved directory " + dir + "\n", end=' ') + print("Preserved directory " + dir + "\n") else: list = self._dirlist[:] list.reverse() diff --git a/QMTest/TestCmdTests.py b/QMTest/TestCmdTests.py index 96e0cbf..6611590 100644 --- a/QMTest/TestCmdTests.py +++ b/QMTest/TestCmdTests.py @@ -19,6 +19,8 @@ AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. """ +from six import PY3 + __author__ = "Steven Knight " __revision__ = "TestCmdTests.py 1.3.D001 2010/06/03 12:58:27 knight" @@ -26,13 +28,20 @@ import os import shutil import signal import stat -import io +if PY3: + from io import StringIO +else: + from StringIO import StringIO import sys import tempfile import time import types import unittest -import collections +if PY3: + from collections import UserList +else: + from UserList import UserList + # Strip the current directory so we get the right TestCmd.py module. sys.path = sys.path[1:] @@ -1032,14 +1041,14 @@ class match_exact_TestCase(TestCmdTestCase): assert test.match_exact("abcde\n", "abcde\n") assert not test.match_exact(["12345\n", "abcde\n"], ["1[0-9]*5\n", "a.*e\n"]) assert test.match_exact(["12345\n", "abcde\n"], ["12345\n", "abcde\n"]) - assert not test.match_exact(collections.UserList(["12345\n", "abcde\n"]), + assert not test.match_exact(UserList(["12345\n", "abcde\n"]), ["1[0-9]*5\n", "a.*e\n"]) - assert test.match_exact(collections.UserList(["12345\n", "abcde\n"]), + assert test.match_exact(UserList(["12345\n", "abcde\n"]), ["12345\n", "abcde\n"]) assert not test.match_exact(["12345\n", "abcde\n"], - collections.UserList(["1[0-9]*5\n", "a.*e\n"])) + UserList(["1[0-9]*5\n", "a.*e\n"])) assert test.match_exact(["12345\n", "abcde\n"], - collections.UserList(["12345\n", "abcde\n"])) + UserList(["12345\n", "abcde\n"])) assert not test.match_exact("12345\nabcde\n", "1[0-9]*5\na.*e\n") assert test.match_exact("12345\nabcde\n", "12345\nabcde\n") lines = ["vwxyz\n", "67890\n"] @@ -1098,28 +1107,28 @@ sys.exit(0) ["1.*j\n"]) assert test.match_re_dotall(["12345\n", "abcde\n", "fghij\n"], ["12345\n", "abcde\n", "fghij\n"]) - assert test.match_re_dotall(collections.UserList(["12345\n", - "abcde\n", - "fghij\n"]), + assert test.match_re_dotall(UserList(["12345\n", + "abcde\n", + "fghij\n"]), ["1[0-9]*5\n", "a.*e\n", "f.*j\n"]) - assert test.match_re_dotall(collections.UserList(["12345\n", - "abcde\n", - "fghij\n"]), + assert test.match_re_dotall(UserList(["12345\n", + "abcde\n", + "fghij\n"]), ["1.*j\n"]) - assert test.match_re_dotall(collections.UserList(["12345\n", - "abcde\n", - "fghij\n"]), + assert test.match_re_dotall(UserList(["12345\n", + "abcde\n", + "fghij\n"]), ["12345\n", "abcde\n", "fghij\n"]) assert test.match_re_dotall(["12345\n", "abcde\n", "fghij\n"], - collections.UserList(["1[0-9]*5\n", - "a.*e\n", - "f.*j\n"])) + UserList(["1[0-9]*5\n", + "a.*e\n", + "f.*j\n"])) assert test.match_re_dotall(["12345\n", "abcde\n", "fghij\n"], - collections.UserList(["1.*j\n"])) + UserList(["1.*j\n"])) assert test.match_re_dotall(["12345\n", "abcde\n", "fghij\n"], - collections.UserList(["12345\n", - "abcde\n", - "fghij\n"])) + UserList(["12345\n", + "abcde\n", + "fghij\n"])) assert test.match_re_dotall("12345\nabcde\nfghij\n", "1[0-9]*5\na.*e\nf.*j\n") assert test.match_re_dotall("12345\nabcde\nfghij\n", "1.*j\n") @@ -1176,14 +1185,14 @@ sys.exit(0) assert test.match_re("abcde\n", "abcde\n") assert test.match_re(["12345\n", "abcde\n"], ["1[0-9]*5\n", "a.*e\n"]) assert test.match_re(["12345\n", "abcde\n"], ["12345\n", "abcde\n"]) - assert test.match_re(collections.UserList(["12345\n", "abcde\n"]), + assert test.match_re(UserList(["12345\n", "abcde\n"]), ["1[0-9]*5\n", "a.*e\n"]) - assert test.match_re(collections.UserList(["12345\n", "abcde\n"]), + assert test.match_re(UserList(["12345\n", "abcde\n"]), ["12345\n", "abcde\n"]) assert test.match_re(["12345\n", "abcde\n"], - collections.UserList(["1[0-9]*5\n", "a.*e\n"])) + UserList(["1[0-9]*5\n", "a.*e\n"])) assert test.match_re(["12345\n", "abcde\n"], - collections.UserList(["12345\n", "abcde\n"])) + UserList(["12345\n", "abcde\n"])) assert test.match_re("12345\nabcde\n", "1[0-9]*5\na.*e\n") assert test.match_re("12345\nabcde\n", "12345\nabcde\n") lines = ["vwxyz\n", "67890\n"] @@ -1463,7 +1472,7 @@ class preserve_TestCase(TestCmdTestCase): def test_preserve(self): """Test preserve()""" def cleanup_test(test, cond=None, stdout=""): - io = io.StringIO() + io = StringIO() save = sys.stdout sys.stdout = io try: @@ -1603,7 +1612,7 @@ class read_TestCase(TestCmdTestCase): _file_matches(wdir_foo_file3, test.read(['foo', 'file3']), "Test\nfile\n#3.\n") _file_matches(wdir_foo_file3, - test.read(collections.UserList(['foo', 'file3'])), + test.read(UserList(['foo', 'file3'])), "Test\nfile\n#3.\n") _file_matches(wdir_file4, test.read('file4', mode = 'r'), "Test\nfile\n#4.\n") @@ -1862,8 +1871,8 @@ class run_verbose_TestCase(TestCmdTestCase): workdir = '', verbose = 1) - sys.stdout = io.StringIO() - sys.stderr = io.StringIO() + sys.stdout = StringIO() + sys.stderr = StringIO() test.run(arguments = ['arg1 arg2']) o = sys.stdout.getvalue() @@ -1876,8 +1885,8 @@ class run_verbose_TestCase(TestCmdTestCase): workdir = '', verbose = 1) - sys.stdout = io.StringIO() - sys.stderr = io.StringIO() + sys.stdout = StringIO() + sys.stderr = StringIO() testx.run(arguments = ['arg1 arg2']) expect = '"%s" "arg1 arg2"\n' % t.scriptx_path @@ -1913,8 +1922,8 @@ class run_verbose_TestCase(TestCmdTestCase): workdir = '', verbose = 2) - sys.stdout = io.StringIO() - sys.stderr = io.StringIO() + sys.stdout = StringIO() + sys.stderr = StringIO() test.run(arguments = ['arg1 arg2']) @@ -1934,8 +1943,8 @@ class run_verbose_TestCase(TestCmdTestCase): workdir = '', verbose = 2) - sys.stdout = io.StringIO() - sys.stderr = io.StringIO() + sys.stdout = StringIO() + sys.stderr = StringIO() testx.run(arguments = ['arg1 arg2']) @@ -1958,8 +1967,8 @@ class run_verbose_TestCase(TestCmdTestCase): workdir = '', verbose = 2) - sys.stdout = io.StringIO() - sys.stderr = io.StringIO() + sys.stdout = StringIO() + sys.stderr = StringIO() test.run(arguments = ['arg1 arg2']) @@ -1978,8 +1987,8 @@ class run_verbose_TestCase(TestCmdTestCase): workdir = '', verbose = 3) - sys.stdout = io.StringIO() - sys.stderr = io.StringIO() + sys.stdout = StringIO() + sys.stderr = StringIO() test.run(arguments = ['arg1 arg2']) @@ -2002,8 +2011,8 @@ class run_verbose_TestCase(TestCmdTestCase): interpreter = 'python', workdir = '') - sys.stdout = io.StringIO() - sys.stderr = io.StringIO() + sys.stdout = StringIO() + sys.stderr = StringIO() test.run(arguments = ['arg1 arg2']) @@ -2022,8 +2031,8 @@ class run_verbose_TestCase(TestCmdTestCase): testx = TestCmd.TestCmd(program = t.scriptx, workdir = '') - sys.stdout = io.StringIO() - sys.stderr = io.StringIO() + sys.stdout = StringIO() + sys.stderr = StringIO() testx.run(arguments = ['arg1 arg2']) @@ -2048,8 +2057,8 @@ class run_verbose_TestCase(TestCmdTestCase): workdir = '', verbose = 1) - sys.stdout = io.StringIO() - sys.stderr = io.StringIO() + sys.stdout = StringIO() + sys.stderr = StringIO() test.run(arguments = ['arg1 arg2']) o = sys.stdout.getvalue() @@ -2062,8 +2071,8 @@ class run_verbose_TestCase(TestCmdTestCase): workdir = '', verbose = 1) - sys.stdout = io.StringIO() - sys.stderr = io.StringIO() + sys.stdout = StringIO() + sys.stderr = StringIO() testx.run(arguments = ['arg1 arg2']) expect = '"%s" "arg1 arg2"\n' % t.scriptx_path @@ -2769,7 +2778,7 @@ class subdir_TestCase(TestCmdTestCase): assert test.subdir(['foo', 'fail']) == 0 assert test.subdir(['sub', 'dir', 'ectory'], 'sub') == 1 assert test.subdir('one', - collections.UserList(['one', 'two']), + UserList(['one', 'two']), ['one', 'two', 'three']) == 3 assert os.path.isdir(test.workpath('foo')) assert os.path.isdir(test.workpath('bar')) @@ -2962,7 +2971,7 @@ class unlink_TestCase(TestCmdTestCase): test.unlink(['foo', 'file3a']) assert not os.path.exists(wdir_foo_file3a) - test.unlink(collections.UserList(['foo', 'file3b'])) + test.unlink(UserList(['foo', 'file3b'])) assert not os.path.exists(wdir_foo_file3b) test.unlink([test.workdir, 'foo', 'file4']) diff --git a/QMTest/TestCommon.py b/QMTest/TestCommon.py index 5a397ff..f1a7407 100644 --- a/QMTest/TestCommon.py +++ b/QMTest/TestCommon.py @@ -90,6 +90,7 @@ The TestCommon module also provides the following variables # PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, # AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +from __future__ import print_function __author__ = "Steven Knight " __revision__ = "TestCommon.py 1.3.D001 2010/06/03 12:58:27 knight" diff --git a/QMTest/TestSCons.py b/QMTest/TestSCons.py index 72624e6..5d0b4c6 100644 --- a/QMTest/TestSCons.py +++ b/QMTest/TestSCons.py @@ -13,7 +13,7 @@ attributes defined in this subclass. """ # __COPYRIGHT__ - +from __future__ import division, print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -721,7 +721,7 @@ class TestSCons(TestCommon): home = os.path.normpath('%s/..'%jar) if os.path.isdir(home): return home - print(("Could not determine JAVA_HOME: %s is not a directory" % home)) + print("Could not determine JAVA_HOME: %s is not a directory" % home) self.fail_test() def java_where_jar(self, version=None): @@ -1013,7 +1013,7 @@ SConscript( sconscript ) raise NoMatch(lastEnd) return m.end() + lastEnd try: - #print len(os.linesep) + #print(len(os.linesep)) ls = os.linesep nols = "(" for i in range(len(ls)): @@ -1241,7 +1241,7 @@ class TimeSCons(TestSCons): self.variables = kw.get('variables') default_calibrate_variables = [] if self.variables is not None: - for variable, value in list(self.variables.items()): + for variable, value in self.variables.items(): value = os.environ.get(variable, value) try: value = int(value) @@ -1297,7 +1297,7 @@ class TimeSCons(TestSCons): """ if 'options' not in kw and self.variables: options = [] - for variable, value in list(self.variables.items()): + for variable, value in self.variables.items(): options.append('%s=%s' % (variable, value)) kw['options'] = ' '.join(options) if self.calibrate: @@ -1323,7 +1323,7 @@ class TimeSCons(TestSCons): self.elapsed_time(), "seconds", sort=0) - for name, args in list(stats.items()): + for name, args in stats.items(): self.trace(name, trace, **args) def uptime(self): diff --git a/QMTest/TestSConsign.py b/QMTest/TestSConsign.py index 665059c..a48b648 100644 --- a/QMTest/TestSConsign.py +++ b/QMTest/TestSConsign.py @@ -1,4 +1,5 @@ # __COPYRIGHT__ +from __future__ import print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/QMTest/scons_tdb.py b/QMTest/scons_tdb.py index 845e99c..76c7fe1 100644 --- a/QMTest/scons_tdb.py +++ b/QMTest/scons_tdb.py @@ -20,7 +20,7 @@ # 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, print_function """ QMTest classes to support SCons' testing and Aegis-inspired workflow. @@ -92,7 +92,7 @@ def get_explicit_arguments(e): # Determine which subset of the 'arguments' have been set # explicitly. explicit_arguments = {} - for name, field in list(arguments.items()): + for name, field in arguments.items(): # Do not record computed fields. if field.IsComputed(): continue diff --git a/SConstruct b/SConstruct index f289947..1a0aef0 100644 --- a/SConstruct +++ b/SConstruct @@ -2,6 +2,7 @@ # SConstruct file to build scons packages during development. # # See the README.rst file for an overview of how SCons is built and tested. +from __future__ import print_function # When this gets changed, you must also change the copyright_years string # in QMTest/TestSCons.py so the test scripts look for the right string. @@ -327,7 +328,7 @@ try: import zipfile def zipit(env, target, source): - print "Zipping %s:" % str(target[0]) + print("Zipping %s:" % str(target[0])) def visit(arg, dirname, names): for name in names: path = os.path.join(dirname, name) @@ -341,7 +342,7 @@ try: zf.close() def unzipit(env, target, source): - print "Unzipping %s:" % str(source[0]) + print("Unzipping %s:" % str(source[0])) zf = zipfile.ZipFile(str(source[0]), 'r') for name in zf.namelist(): dest = os.path.join(env['UNPACK_ZIP_DIR'], name) @@ -350,7 +351,7 @@ try: os.makedirs(dir) except: pass - print dest,name + print(dest,name) # if the file exists, then delete it before writing # to it so that we don't end up trying to write to a symlink: if os.path.isfile(dest) or os.path.islink(dest): @@ -558,7 +559,7 @@ else: i = install_egg_info(dist) i.finalize_options() import os.path - print os.path.split(i.outputs[0])[1] + print(os.path.split(i.outputs[0])[1]) """ % version try: @@ -853,7 +854,7 @@ for p in [ scons ]: AddPostAction(dist_distutils_targets, Chmod(dist_distutils_targets, 0644)) if not gzip: - print "gzip not found in %s; skipping .tar.gz package for %s." % (os.environ['PATH'], pkg) + print("gzip not found in %s; skipping .tar.gz package for %s." % (os.environ['PATH'], pkg)) else: distutils_formats.append('gztar') @@ -928,7 +929,7 @@ for p in [ scons ]: env.Command(digest, tar_gz, Digestify) if not zipit: - print "zip not found; skipping .zip package for %s." % pkg + print("zip not found; skipping .zip package for %s." % pkg) else: distutils_formats.append('zip') @@ -1211,7 +1212,7 @@ elif svn_status_lines: sentries = [l.split()[-1] for l in slines] sfiles = list(filter(os.path.isfile, sentries)) else: - print "Not building in a Mercurial or Subversion tree; skipping building src package." + print("Not building in a Mercurial or Subversion tree; skipping building src package.") if sfiles: remove_patterns = [ diff --git a/bench/bench.py b/bench/bench.py index 1a98d8c..f1d18c6 100644 --- a/bench/bench.py +++ b/bench/bench.py @@ -23,7 +23,7 @@ # # This will allow (as much as possible) us to time just the code itself, # not Python function call overhead. - +from __future__ import division, print_function import getopt import sys @@ -94,7 +94,7 @@ exec(open(args[0], 'rU').read()) try: FunctionList except NameError: - function_names = sorted([x for x in list(locals().keys()) if x[:4] == FunctionPrefix]) + function_names = sorted([x for x in locals().keys() if x[:4] == FunctionPrefix]) l = [locals()[f] for f in function_names] FunctionList = [f for f in l if isinstance(f, types.FunctionType)] diff --git a/bench/env.__setitem__.py b/bench/env.__setitem__.py index 284653e..9c27b6d 100644 --- a/bench/env.__setitem__.py +++ b/bench/env.__setitem__.py @@ -33,7 +33,7 @@ class Timing(object): def times(num=1000000, init='', title='Results:', **statements): # time each statement timings = [] - for n, s in list(statements.items()): + for n, s in statements.items(): t = Timing(n, num, init, s) t.timeit() timings.append(t) @@ -287,7 +287,7 @@ else: # that the timer will use to get at these classes. class_names = [] -for n in list(locals().keys()): +for n in locals().keys(): #if n.startswith('env_'): if n[:4] == 'env_': class_names.append(n) diff --git a/bench/is_types.py b/bench/is_types.py index b6da0d2..69c029f 100644 --- a/bench/is_types.py +++ b/bench/is_types.py @@ -17,11 +17,11 @@ InstanceType = types.InstanceType DictType = dict ListType = list StringType = str -try: str +try: unicode except NameError: UnicodeType = None else: - UnicodeType = str + UnicodeType = unicode # The original implementations, pretty straightforward checks for the @@ -36,7 +36,7 @@ def original_is_List(e): if UnicodeType is not None: def original_is_String(e): - return isinstance(e, (str,UserString)) + return isinstance(e, (str,unicode,UserString)) else: def original_is_String(e): return isinstance(e, (str,UserString)) @@ -58,7 +58,7 @@ def checkInstanceType_is_List(e): if UnicodeType is not None: def checkInstanceType_is_String(e): return isinstance(e, str) \ - or isinstance(e, str) \ + or isinstance(e, unicode) \ or (isinstance(e, types.InstanceType) and isinstance(e, UserString)) else: def checkInstanceType_is_String(e): @@ -84,7 +84,7 @@ if UnicodeType is not None: def cache_type_e_is_String(e): t = type(e) return t is str \ - or t is str \ + or t is unicode \ or (t is types.InstanceType and isinstance(e, UserString)) else: def cache_type_e_is_String(e): @@ -136,7 +136,7 @@ if UnicodeType is not None: t = type(obj) if t is types.InstanceType: t = instanceTypeMap.get(obj.__class__, t) - elif t is str: + elif t is unicode: t = str return t else: diff --git a/bench/timeit.py b/bench/timeit.py index 2840010..7db0dd4 100644 --- a/bench/timeit.py +++ b/bench/timeit.py @@ -46,7 +46,7 @@ be aware of it. The baseline overhead can be measured by invoking the program without arguments. The baseline overhead differs between Python versions! """ - +from __future__ import division, print_function try: import gc @@ -245,7 +245,7 @@ def main(args=None): precision = precision + 1 verbose = precision + 1 if o in ("-h", "--help"): - print(__doc__, end=' ') + print(__doc__) return 0 setup = "\n".join(setup) or "pass" # Include the current directory, so that local imports work (sys.path diff --git a/bin/Command.py b/bin/Command.py index 768caed..dadd7a9 100644 --- a/bin/Command.py +++ b/bin/Command.py @@ -4,6 +4,7 @@ # # XXX Describe what the script does here. # +from __future__ import print_function import getopt import os diff --git a/bin/SConsDoc.py b/bin/SConsDoc.py index 453e241..80f41a5 100644 --- a/bin/SConsDoc.py +++ b/bin/SConsDoc.py @@ -24,6 +24,7 @@ # # Module for handling SCons documentation processing. # +from __future__ import print_function __doc__ = """ This module parses home-brew XML files that document various things @@ -51,7 +52,7 @@ Builder example: to indicate a new paragraph. - print "this is example code, it will be offset and indented" + print("this is example code, it will be offset and indented") @@ -71,7 +72,7 @@ Function example: &f-FUNCTION; element. It need not be on a line by itself. - print "this is example code, it will be offset and indented" + print("this is example code, it will be offset and indented") @@ -88,7 +89,7 @@ Construction variable example: &t-VARIABLE; element. It need not be on a line by itself. - print "this is example code, it will be offset and indented" + print("this is example code, it will be offset and indented") @@ -105,7 +106,7 @@ Tool example: &t-TOOL; element. It need not be on a line by itself. - print "this is example code, it will be offset and indented" + print("this is example code, it will be offset and indented") diff --git a/bin/calibrate.py b/bin/calibrate.py index 31c04e8..3f9104e 100644 --- a/bin/calibrate.py +++ b/bin/calibrate.py @@ -20,7 +20,7 @@ # 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, print_function import optparse import os diff --git a/bin/caller-tree.py b/bin/caller-tree.py index 327e6a1..21cda4b 100644 --- a/bin/caller-tree.py +++ b/bin/caller-tree.py @@ -39,6 +39,7 @@ # function at the same time, for example, their counts will intermix. # So use this to get a *general* idea of who's calling what, not for # fine-grained performance tuning. +from __future__ import print_function import sys @@ -86,7 +87,7 @@ def print_entry(e, level, calls): else: print() -for e in [ e for e in list(AllCalls.values()) if not e.calls ]: +for e in [ e for e in AllCalls.values() if not e.calls ]: print_entry(e, 0, '') # Local Variables: diff --git a/bin/docs-create-example-outputs.py b/bin/docs-create-example-outputs.py index b2dfbea..64dcf2e 100644 --- a/bin/docs-create-example-outputs.py +++ b/bin/docs-create-example-outputs.py @@ -3,6 +3,7 @@ # Searches through the whole doc/user tree and creates # all output files for the single examples. # +from __future__ import print_function import os import sys diff --git a/bin/docs-update-generated.py b/bin/docs-update-generated.py index 2b419a4..d22cc32 100644 --- a/bin/docs-update-generated.py +++ b/bin/docs-update-generated.py @@ -6,6 +6,7 @@ # as well as the entity declarations for them. # Uses scons-proc.py under the hood... # +from __future__ import print_function import os import SConsDoc diff --git a/bin/docs-validate.py b/bin/docs-validate.py index e5d0659..e53a89d 100644 --- a/bin/docs-validate.py +++ b/bin/docs-validate.py @@ -3,6 +3,7 @@ # Searches through the whole source tree and validates all # documentation files against our own XSD in docs/xsd. # +from __future__ import print_function import sys,os import SConsDoc diff --git a/bin/install_python.py b/bin/install_python.py index dca37d0..5c947ac 100644 --- a/bin/install_python.py +++ b/bin/install_python.py @@ -6,6 +6,7 @@ # This was written for a Linux system (specifically Ubuntu) but should # be reasonably generic to any POSIX-style system with a /usr/local # hierarchy. +from __future__ import print_function import getopt import os diff --git a/bin/install_scons.py b/bin/install_scons.py index b732193..7a39e96 100644 --- a/bin/install_scons.py +++ b/bin/install_scons.py @@ -17,13 +17,17 @@ # This was written for a Linux system (specifically Ubuntu) but should # be reasonably generic to any POSIX-style system with a /usr/local # hierarchy. +from __future__ import print_function import getopt import os import shutil import sys import tarfile -import urllib.request, urllib.parse, urllib.error +try: + from urllib.request import urlretrieve +except ImportError: # Python < 3 + from urllib import urlretrieve from Command import CommandRunner, Usage @@ -171,7 +175,7 @@ Usage: install_scons.py [-ahnq] [-d DIR] [-p PREFIX] [VERSION ...] if not os.path.exists(tar_gz): if not os.path.exists(downloads_dir): cmd.run('mkdir %(downloads_dir)s') - cmd.run((urllib.request.urlretrieve, tar_gz_url, tar_gz), + cmd.run((urlretrieve, tar_gz_url, tar_gz), 'wget -O %(tar_gz)s %(tar_gz_url)s') def extract(tar_gz): diff --git a/bin/linecount.py b/bin/linecount.py index 2d478f0..897f1e8 100644 --- a/bin/linecount.py +++ b/bin/linecount.py @@ -21,7 +21,7 @@ # in each category, the number of non-blank lines, and the number of # non-comment lines. The last figure (non-comment) lines is the most # interesting one for most purposes. - +from __future__ import division, print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/bin/memlogs.py b/bin/memlogs.py index 0409dfe..6e68ce0 100644 --- a/bin/memlogs.py +++ b/bin/memlogs.py @@ -20,6 +20,7 @@ # 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 print_function import getopt import sys diff --git a/bin/memoicmp.py b/bin/memoicmp.py index 5021c41..1106ac3 100644 --- a/bin/memoicmp.py +++ b/bin/memoicmp.py @@ -2,6 +2,7 @@ # # A script to compare the --debug=memoizer output found in # two different files. +from future import print_function import sys @@ -29,14 +30,14 @@ def memoize_cmp(filea, fileb): ma_o = [] mb_o = [] mab = [] - for k in list(ma.keys()): - if k in list(mb.keys()): + for k in ma.keys(): + if k in mb.keys(): if k not in mab: mab.append(k) else: ma_o.append(k) - for k in list(mb.keys()): - if k in list(ma.keys()): + for k in mb.keys(): + if k in ma.keys(): if k not in mab: mab.append(k) else: diff --git a/bin/objcounts.py b/bin/objcounts.py index 25b985b..2bd8923 100644 --- a/bin/objcounts.py +++ b/bin/objcounts.py @@ -20,6 +20,7 @@ # 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 print_function import re import sys @@ -47,7 +48,7 @@ c1 = fetch_counts(sys.argv[1]) c2 = fetch_counts(sys.argv[2]) common = {} -for k in list(c1.keys()): +for k in c1.keys(): try: common[k] = (c1[k], c2[k]) except KeyError: @@ -58,7 +59,7 @@ for k in list(c1.keys()): if not '.' in k: s = '.'+k l = len(s) - for k2 in list(c2.keys()): + for k2 in c2.keys(): if k2[-l:] == s: common[k2] = (c1[k], c2[k2]) del c1[k] diff --git a/bin/scons-diff.py b/bin/scons-diff.py index 5181fa1..8597501 100644 --- a/bin/scons-diff.py +++ b/bin/scons-diff.py @@ -8,6 +8,7 @@ # etc. so that you can diff trees without having to ignore changes in # version lines. # +from __future__ import print_function import difflib import getopt @@ -161,7 +162,7 @@ def diff_file(left, right): else: if text: diff_line(left, right) - print(text, end=' ') + print(text) elif report_same: print('Files %s and %s are identical' % (left, right)) @@ -173,7 +174,7 @@ def diff_dir(left, right): u[l] = 1 for r in rlist: u[r] = 1 - for x in sorted([ x for x in list(u.keys()) if x[-4:] != '.pyc' ]): + for x in sorted([ x for x in u.keys() if x[-4:] != '.pyc' ]): if x in llist: if x in rlist: do_diff(os.path.join(left, x), diff --git a/bin/scons-proc.py b/bin/scons-proc.py index 19be4c3..b93b25a 100644 --- a/bin/scons-proc.py +++ b/bin/scons-proc.py @@ -9,6 +9,8 @@ # DocBook-formatted generated XML files containing the summary text # and/or .mod files containing the ENTITY definitions for each item. # +from __future__ import print_function + import getopt import os import re @@ -106,7 +108,7 @@ Link_Entities_Header = """\ class SCons_XML(object): def __init__(self, entries, **kw): self.values = entries - for k, v in list(kw.items()): + for k, v in kw.items(): setattr(self, k, v) def fopen(self, name): diff --git a/bin/scons-test.py b/bin/scons-test.py index 788fc6d..dd54dd1 100644 --- a/bin/scons-test.py +++ b/bin/scons-test.py @@ -14,6 +14,7 @@ # relevant information about the system, the Python version, etc., # so that problems on different platforms can be identified sooner. # +from __future__ import print_function import atexit import getopt @@ -224,7 +225,7 @@ if format == '--xml': print(" ") command = '"%s" runtest.py -q -o - --xml %s' % (sys.executable, runtest_args) - #print command + #print(command) os.system(command) print("") @@ -243,7 +244,7 @@ else: print_version_info("engine", SCons) command = '"%s" runtest.py %s' % (sys.executable, runtest_args) - #print command + #print(command) os.system(command) # Local Variables: diff --git a/bin/scons-unzip.py b/bin/scons-unzip.py index 75d3281..a64179f 100644 --- a/bin/scons-unzip.py +++ b/bin/scons-unzip.py @@ -7,6 +7,7 @@ # I'm using this to make it more convenient to manage working on multiple # changes on Windows, where I don't have access to my Aegis tools. # +from __future__ import print_function import getopt import os.path diff --git a/bin/scons_dev_master.py b/bin/scons_dev_master.py index 71034ad..a8862ea 100644 --- a/bin/scons_dev_master.py +++ b/bin/scons_dev_master.py @@ -3,6 +3,7 @@ # A script for turning a generic Ubuntu system into a master for # SCons development. +from __future__ import print_function import getopt import sys diff --git a/bin/sfsum b/bin/sfsum index 2dfa422..142793a 100644 --- a/bin/sfsum +++ b/bin/sfsum @@ -22,6 +22,7 @@ # # https://sourceforge.net/projects/sitedocs/ # +from __future__ import print_function import xml.sax import xml.sax.saxutils @@ -121,9 +122,9 @@ if __name__ == '__main__': # generalized once we figure out other things for this script to do. bugs = [x for x in Artifacts['Bugs'] if x.status == 'Open'] - print list(Artifacts.keys()) + print(list(Artifacts.keys())) - print "%d open bugs" % len(bugs) + print("%d open bugs" % len(bugs)) # Sort them into a separate list for each assignee. Assigned = {} @@ -141,7 +142,7 @@ if __name__ == '__main__': except KeyError: pass else: - print " %s" % a - b.sort(lambda x, y: cmp(x.artifact_id, y.artifact_id)) + print(" %s" % a) + b.sort(key=lambda x, y: (x.artifact_id, y.artifact_id)) for bug in b: - print " %-6s %s" % (bug.artifact_id, bug.summary) + print(" %-6s %s" % (bug.artifact_id, bug.summary)) diff --git a/bin/svn-bisect.py b/bin/svn-bisect.py index f262366..dbf8dd9 100755 --- a/bin/svn-bisect.py +++ b/bin/svn-bisect.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- Python -*- - +from __future__ import division, print_function import sys from math import log, ceil diff --git a/bin/update-release-info.py b/bin/update-release-info.py index f60c187..b6cf942 100644 --- a/bin/update-release-info.py +++ b/bin/update-release-info.py @@ -56,6 +56,7 @@ In 'post' mode, files are prepared for the next release cycle: # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -332,7 +333,7 @@ t.replace_assign('deprecated_python_version', str(deprecated_version)) # Update doc/user/main.{in,xml} -docyears = ', '.join(map(str, iter(list(range(2004, release_date[0] + 1))))) +docyears = ', '.join(map(str, range(2004, release_date[0] + 1))) t = UpdateFile(os.path.join('doc', 'user', 'main.in')) if DEBUG: t.file = '/tmp/main.in' ## TODO debug these diff --git a/bin/xmlagenda.py b/bin/xmlagenda.py index 40f5ca1..fcfe53e 100755 --- a/bin/xmlagenda.py +++ b/bin/xmlagenda.py @@ -18,6 +18,7 @@ # Grab the sort bar on the far left (just above the "1" for row one) # and move it down one row. (Row one becomes a floating header) # Voila! +from __future__ import print_function # The team members # FIXME: These names really should be external to this script diff --git a/doc/SConscript b/doc/SConscript index 8dcf697..c6b8f74 100644 --- a/doc/SConscript +++ b/doc/SConscript @@ -23,6 +23,7 @@ # 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 print_function import os.path import re @@ -84,16 +85,16 @@ except: try: import lxml except: - print "doc: Neither libxml2 nor lxml Python bindings found!" - print " Please install one of the packages python-libxml2 or python-lxml." + print("doc: Neither libxml2 nor lxml Python bindings found!") + print(" Please install one of the packages python-libxml2 or python-lxml.") skip_doc = True if not fop and not xep: - print "doc: No PDF renderer found (fop|xep)!" + print("doc: No PDF renderer found (fop|xep)!") skip_doc = True if skip_doc: - print "doc: ...skipping building User Guide." + print("doc: ...skipping building User Guide.") else: # # Always create a version.xml file containing the version information @@ -109,18 +110,18 @@ else: # Ensure that all XML files are valid against our XSD, and # that all example names and example output suffixes are unique # - print "Validating files against SCons XSD..." + print("Validating files against SCons XSD...") if SConsDoc.validate_all_xml(['src'], xsdfile='xsd/scons.xsd'): - print "OK" + print("OK") else: - print "Validation failed! Please correct the errors above and try again." + print("Validation failed! Please correct the errors above and try again.") sys.exit(0) - print "Checking whether all example names are unique..." + print("Checking whether all example names are unique...") if SConsExamples.exampleNamesAreUnique(os.path.join('doc','user')): - print "OK" + print("OK") else: - print "Not all example names and suffixes are unique! Please correct the errors listed above and try again." + print("Not all example names and suffixes are unique! Please correct the errors listed above and try again.") sys.exit(0) # @@ -358,7 +359,7 @@ else: # epydoc_cli is found if not epydoc_cli and not epydoc: - print "doc: epydoc not found, skipping building API documentation." + print("doc: epydoc not found, skipping building API documentation.") else: # XXX Should be in common with reading the same thing in # the SConstruct file. @@ -380,7 +381,7 @@ else: tar_list.append(htmldir) if not epydoc_cli: - print "doc: command line epydoc is not found, skipping PDF/PS/Tex output" + print("doc: command line epydoc is not found, skipping PDF/PS/Tex output") else: # PDF and PostScript and TeX are built from the # same invocation. diff --git a/review.py b/review.py index 8d033ed..c01472e 100644 --- a/review.py +++ b/review.py @@ -13,6 +13,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import print_function """Tool for uploading diffs from a version control system to the codereview app. @@ -31,8 +32,16 @@ against by using the '--rev' option. # This code is derived from appcfg.py in the App Engine SDK (open source), # and from ASPN recipe #146306. -import configparser -import http.cookiejar +try: + from configparser import ConfigParser +except ImportError: # Python < 3 + from ConfigParser import ConfigParser +try: + from http.cookiejar import ( + CookieJar, MozillaCookieJar, LoadError as CookieLoadError) +except ImportError: # Python < 3 + from cookielib import ( + CookieJar, MozillaCookieJar, LoadError as CookieLoadError) import fnmatch import getpass import logging @@ -43,6 +52,24 @@ import re import socket import subprocess import sys +try: + from urllib.request import ( + Request, OpenerDirector, + ProxyHandler, UnknownHandler, HTTPHandler, HTTPSHandler, + HTTPDefaultErrorHandler, HTTPErrorProcessor, + HTTPCookieProcessor) + from urllib.error import HTTPError + from urllib.parse import ( + urlencode, urlparse, urlunparse, splituser as urlsplituser) +except ImportError: # Python < 3 + from urllib2 import ( + Request, OpenerDirector, + ProxyHandler, UnknownHandler, HTTPHandler, HTTPSHandler, + HTTPDefaultErrorHandler, HTTPErrorProcessor, HTTPError, + HTTPCookieProcessor, + urlparse) + from urllib import urlencode, splituser as urlsplituser + from urlparse import urlparse, urlunparse import urllib.request, urllib.parse, urllib.error import urllib.request, urllib.error, urllib.parse import urllib.parse @@ -155,11 +182,11 @@ def ErrorExit(msg): sys.exit(1) -class ClientLoginError(urllib.error.HTTPError): +class ClientLoginError(HTTPError): """Raised to indicate there was an error authenticating with ClientLogin.""" def __init__(self, url, code, msg, headers, args): - urllib.error.HTTPError.__init__(self, url, code, msg, headers, None) + HTTPError.__init__(self, url, code, msg, headers, None) self.args = args self.reason = args["Error"] self.info = args.get("Info", None) @@ -212,7 +239,7 @@ class AbstractRpcServer(object): def _CreateRequest(self, url, data=None): """Creates a new urllib request.""" logging.debug("Creating request for: '%s' with payload:\n%s", url, data) - req = urllib.request.Request(url, data=data) + req = Request(url, data=data) if self.host_override: req.add_header("Host", self.host_override) for key, value in self.extra_headers.items(): @@ -239,7 +266,7 @@ class AbstractRpcServer(object): account_type = "HOSTED" req = self._CreateRequest( url="https://www.google.com/accounts/ClientLogin", - data=urllib.parse.urlencode({ + data=urlencode({ "Email": email, "Passwd": password, "service": "ah", @@ -253,7 +280,7 @@ class AbstractRpcServer(object): response_dict = dict(x.split("=") for x in response_body.split("\n") if x) return response_dict["Auth"] - except urllib.error.HTTPError as e: + except HTTPError as e: if e.code == 403: body = e.read() response_dict = dict(x.split("=", 1) for x in body.split("\n") if x) @@ -275,15 +302,15 @@ class AbstractRpcServer(object): continue_location = "http://localhost/" args = {"continue": continue_location, "auth": auth_token} req = self._CreateRequest("%s/_ah/login?%s" % - (self.host, urllib.parse.urlencode(args))) + (self.host, urlencode(args))) try: response = self.opener.open(req) - except urllib.error.HTTPError as e: + except HTTPError as e: response = e if (response.code != 302 or response.info()["location"] != continue_location): - raise urllib.error.HTTPError(req.get_full_url(), response.code, response.msg, - response.headers, response.fp) + raise HTTPError(req.get_full_url(), response.code, response.msg, + response.headers, response.fp) self.authenticated = True def _Authenticate(self): @@ -306,23 +333,23 @@ class AbstractRpcServer(object): try: auth_token = self._GetAuthToken(credentials[0], credentials[1]) except ClientLoginError as e: - print('', file=sys.stderr) + print(file=sys.stderr) if e.reason == "BadAuthentication": if e.info == "InvalidSecondFactor": - print(( - "Use an application-specific password instead " - "of your regular account password.\n" - "See http://www.google.com/" - "support/accounts/bin/answer.py?answer=185833"), file=sys.stderr) + print("Use an application-specific password instead " + "of your regular account password.\n" + "See http://www.google.com/" + "support/accounts/bin/answer.py?answer=185833", + file=sys.stderr) else: print("Invalid username or password.", file=sys.stderr) elif e.reason == "CaptchaRequired": - print(( - "Please go to\n" - "https://www.google.com/accounts/DisplayUnlockCaptcha\n" - "and verify you are a human. Then try again.\n" - "If you are using a Google Apps account the URL is:\n" - "https://www.google.com/a/yourdomain.com/UnlockCaptcha"), file=sys.stderr) + print("Please go to\n" + "https://www.google.com/accounts/DisplayUnlockCaptcha\n" + "and verify you are a human. Then try again.\n" + "If you are using a Google Apps account the URL is:\n" + "https://www.google.com/a/yourdomain.com/UnlockCaptcha", + file=sys.stderr) elif e.reason == "NotVerified": print("Account not verified.", file=sys.stderr) elif e.reason == "TermsNotAgreed": @@ -333,14 +360,15 @@ class AbstractRpcServer(object): print("The user account has been disabled.", file=sys.stderr) break elif e.reason == "ServiceDisabled": - print(("The user's access to the service has been " - "disabled."), file=sys.stderr) + print("The user's access to the service has been disabled.", + file=sys.stderr) elif e.reason == "ServiceUnavailable": - print("The service is not available; try again later.", file=sys.stderr) + print("The service is not available; try again later.", + file=sys.stderr) else: # Unknown error. raise - print('', file=sys.stderr) + print(file=sys.stderr) continue self._GetAuthCookie(auth_token) return @@ -380,18 +408,18 @@ class AbstractRpcServer(object): args = dict(kwargs) url = "%s%s" % (self.host, request_path) if args: - url += "?" + urllib.parse.urlencode(args) + url += "?" + urlencode(args) req = self._CreateRequest(url=url, data=payload) req.add_header("Content-Type", content_type) if extra_headers: - for header, value in list(extra_headers.items()): + for header, value in extra_headers.items(): req.add_header(header, value) try: f = self.opener.open(req) response = f.read() f.close() return response - except urllib.error.HTTPError as e: + except HTTPError as e: if tries > 3: raise elif e.code == 401 or e.code == 302: @@ -402,7 +430,7 @@ class AbstractRpcServer(object): elif e.code == 301: # Handle permanent redirect manually. url = e.info()["location"] - url_loc = urllib.parse.urlparse(url) + url_loc = urlparse(url) self.host = '%s://%s' % (url_loc[0], url_loc[1]) else: raise @@ -426,23 +454,23 @@ class HttpRpcServer(AbstractRpcServer): Returns: A urllib2.OpenerDirector object. """ - opener = urllib.request.OpenerDirector() - opener.add_handler(urllib.request.ProxyHandler()) - opener.add_handler(urllib.request.UnknownHandler()) - opener.add_handler(urllib.request.HTTPHandler()) - opener.add_handler(urllib.request.HTTPDefaultErrorHandler()) - opener.add_handler(urllib.request.HTTPSHandler()) - opener.add_handler(urllib2.HTTPErrorProcessor()) + opener = OpenerDirector() + opener.add_handler(ProxyHandler()) + opener.add_handler(UnknownHandler()) + opener.add_handler(HTTPHandler()) + opener.add_handler(HTTPDefaultErrorHandler()) + opener.add_handler(HTTPSHandler()) + opener.add_handler(HTTPErrorProcessor()) if self.save_cookies: self.cookie_file = os.path.expanduser("~/.codereview_upload_cookies") - self.cookie_jar = http.cookiejar.MozillaCookieJar(self.cookie_file) + self.cookie_jar = MozillaCookieJar(self.cookie_file) if os.path.exists(self.cookie_file): try: self.cookie_jar.load() self.authenticated = True StatusUpdate("Loaded authentication cookies from %s" % self.cookie_file) - except (http.cookiejar.LoadError, IOError): + except (CookieLoadError, IOError): # Failed to load cookies - just ignore them. pass else: @@ -453,8 +481,8 @@ class HttpRpcServer(AbstractRpcServer): os.chmod(self.cookie_file, 0o600) else: # Don't save cookies across runs of update.py. - self.cookie_jar = http.cookiejar.CookieJar() - opener.add_handler(urllib.request.HTTPCookieProcessor(self.cookie_jar)) + self.cookie_jar = CookieJar() + opener.add_handler(HTTPCookieProcessor(self.cookie_jar)) return opener @@ -804,8 +832,8 @@ class VersionControlSystem(object): else: type = "current" if len(content) > MAX_UPLOAD_SIZE: - print(("Not uploading the %s file for %s because it's too large." % - (type, filename))) + print("Not uploading the %s file for %s because it's too large." % + (type, filename)) file_too_large = True content = "" checksum = md5(content).hexdigest() @@ -832,7 +860,7 @@ class VersionControlSystem(object): patches = dict() [patches.setdefault(v, k) for k, v in patch_list] - for filename in list(patches.keys()): + for filename in patches.keys(): base_content, new_content, is_binary, status = files[filename] file_id_str = patches.get(filename) if file_id_str.find("nobase") != -1: @@ -898,7 +926,7 @@ class SubversionVCS(VersionControlSystem): for line in info.splitlines(): if line.startswith("URL: "): url = line.split()[1] - scheme, netloc, path, params, query, fragment = urllib.parse.urlparse(url) + scheme, netloc, path, params, query, fragment = urlparse(url) guess = "" if netloc == "svn.python.org" and scheme == "svn+ssh": path = "projects" + path @@ -908,8 +936,7 @@ class SubversionVCS(VersionControlSystem): scheme = "http" guess = "Google Code " path = path + "/" - base = urllib.parse.urlunparse((scheme, netloc, path, params, - query, fragment)) + base = urlunparse((scheme, netloc, path, params, query, fragment)) logging.info("Guessed %sbase = %s", guess, base) return base if required: @@ -1412,8 +1439,8 @@ def UploadSeparatePatches(issue, rpc_server, patchset, data, options): rv = [] for patch in patches: if len(patch[1]) > MAX_UPLOAD_SIZE: - print(("Not uploading the patch for " + patch[0] + - " because the file is too large.")) + print("Not uploading the patch for " + patch[0] + + " because the file is too large.") continue form_fields = [("filename", patch[0])] if not options.download_base: @@ -1551,7 +1578,7 @@ def LoadSubversionAutoProperties(): subversion_config = os.path.expanduser("~/.subversion/config") if not os.path.exists(subversion_config): return {} - config = configparser.ConfigParser() + config = ConfigParser() config.read(subversion_config) if (config.has_section("miscellany") and config.has_option("miscellany", "enable-auto-props") and @@ -1606,7 +1633,7 @@ def GetSubversionPropertyChanges(filename): svn_auto_props_map = LoadSubversionAutoProperties() all_props = [] - for file_pattern, props in list(svn_auto_props_map.items()): + for file_pattern, props in svn_auto_props_map.items(): if fnmatch.fnmatch(filename, file_pattern): all_props.extend(props) if all_props: @@ -1703,12 +1730,12 @@ def RealMain(argv, data=None): options.account_type) form_fields = [("subject", message)] if base: - b = urllib.parse.urlparse(base) - username, netloc = urllib.parse.splituser(b.netloc) + b = urlparse(base) + username, netloc = urlsplituser(b.netloc) if username: logging.info("Removed username from base URL") - base = urllib.parse.urlunparse((b.scheme, netloc, b.path, b.params, - b.query, b.fragment)) + base = urlunparse((b.scheme, netloc, b.path, b.params, + b.query, b.fragment)) form_fields.append(("base", base)) if options.issue: form_fields.append(("issue", str(options.issue))) diff --git a/runtest.py b/runtest.py index 65d7851..0fad655 100755 --- a/runtest.py +++ b/runtest.py @@ -81,6 +81,7 @@ # library directory. If we ever resurrect that as the default, then # you can find the appropriate code in the 0.04 version of this script, # rather than reinventing that wheel.) +from __future__ import print_function import getopt import glob @@ -92,7 +93,10 @@ import time try: import threading - import queue # 2to3: rename to queue + try: + from queue import Queue + except ImportError: # Python < 3 + from Queue import Queue threading_ok = True except ImportError: print("Can't import threading or queue") @@ -865,7 +869,7 @@ class RunTest(threading.Thread): if jobs > 1 and threading_ok: print("Running tests using %d jobs"%jobs) # Start worker threads - queue = queue.Queue() + queue = Queue() io_lock = threading.Lock() for i in range(1, jobs): t = RunTest(queue, io_lock) diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index 66757a4..006e8f5 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -114,7 +114,6 @@ import SCons.Errors import SCons.Executor import SCons.Util import SCons.Subst -import collections # we use these a lot, so try to optimize them is_String = SCons.Util.is_String @@ -329,7 +328,7 @@ def _do_create_keywords(args, kw): cmdstrfunc = args[0] if cmdstrfunc is None or is_String(cmdstrfunc): kw['cmdstr'] = cmdstrfunc - elif isinstance(cmdstrfunc, collections.Callable): + elif callable(cmdstrfunc): kw['strfunction'] = cmdstrfunc else: raise SCons.Errors.UserError( @@ -360,7 +359,7 @@ def _do_create_action(act, kw): if is_List(act): return CommandAction(act, **kw) - if isinstance(act, collections.Callable): + if callable(act): try: gen = kw['generator'] del kw['generator'] @@ -494,7 +493,7 @@ class _ActionAction(ActionBase): self.targets = targets if batch_key: - if not isinstance(batch_key, collections.Callable): + if not callable(batch_key): # They have set batch_key, but not to their own # callable. The default behavior here will batch # *all* targets+sources using this action, separated @@ -514,7 +513,7 @@ class _ActionAction(ActionBase): # This code assumes s is a regular string, but should # work if it's unicode too. try: - sys.stdout.write(str(s + "\n")) + sys.stdout.write(s + u"\n") except UnicodeDecodeError: sys.stdout.write(s + "\n") @@ -555,7 +554,7 @@ class _ActionAction(ActionBase): source = executor.get_all_sources() t = ' and '.join(map(str, target)) l = '\n '.join(self.presub_lines(env)) - out = "Building %s with action:\n %s\n" % (t, l) + out = u"Building %s with action:\n %s\n" % (t, l) sys.stdout.write(out) cmd = None if show and self.strfunction: @@ -655,7 +654,7 @@ def _subproc(scons_env, cmd, error = 'ignore', **kw): # Ensure that the ENV values are all strings: new_env = {} - for key, value in list(ENV.items()): + for key, value in ENV.items(): if is_List(value): # If the value is a list, then we assume it is a path list, # because that's a pretty common list-like value to stick @@ -781,7 +780,7 @@ class CommandAction(_ActionAction): ENV = get_default_ENV(env) # Ensure that the ENV values are all strings: - for key, value in list(ENV.items()): + for key, value in ENV.items(): if not is_String(value): if is_List(value): # If the value is a list, then we assume it is a @@ -1040,7 +1039,7 @@ class FunctionAction(_ActionAction): else: if strfunc is None: return None - if isinstance(strfunc, collections.Callable): + if callable(strfunc): return strfunc(target, source, env) name = self.function_name() tstr = array(target) @@ -1216,7 +1215,7 @@ class ActionCaller(object): def subst_kw(self, target, source, env): kw = {} - for key in list(self.kw.keys()): + for key in self.kw.keys(): kw[key] = self.subst(self.kw[key], target, source, env) return kw diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py index 6edf373..754c6e7 100644 --- a/src/engine/SCons/ActionTests.py +++ b/src/engine/SCons/ActionTests.py @@ -133,7 +133,7 @@ class Environment(object): self.d['SPAWN'] = scons_env['SPAWN'] self.d['PSPAWN'] = scons_env['PSPAWN'] self.d['ESCAPE'] = scons_env['ESCAPE'] - for k, v in list(kw.items()): + for k, v in kw.items(): self.d[k] = v # Just use the underlying scons_subst*() utility methods. def subst(self, strSubst, raw=0, target=[], source=[], conv=None): @@ -158,12 +158,12 @@ class Environment(object): def Clone(self, **kw): res = Environment() res.d = SCons.Util.semi_deepcopy(self.d) - for k, v in list(kw.items()): + for k, v in kw.items(): res.d[k] = v return res def sig_dict(self): d = {} - for k,v in list(self.items()): d[k] = v + for k,v in self.items(): d[k] = v d['TARGETS'] = ['__t1__', '__t2__', '__t3__', '__t4__', '__t5__', '__t6__'] d['TARGET'] = d['TARGETS'][0] d['SOURCES'] = ['__s1__', '__s2__', '__s3__', '__s4__', '__s5__', '__s6__'] @@ -305,7 +305,7 @@ class ActionTestCase(unittest.TestCase): # a singleton list returns the contained action test_positional_args(cmd_action, ["string"]) - try: str + try: unicode except NameError: pass else: a2 = eval("SCons.Action.Action(u'string')") diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py index 6abcbcf..0f7aff4 100644 --- a/src/engine/SCons/Builder.py +++ b/src/engine/SCons/Builder.py @@ -179,7 +179,7 @@ class CallableSelector(SCons.Util.Selector): finds if it can.""" def __call__(self, env, source): value = SCons.Util.Selector.__call__(self, env, source) - if isinstance(value, collections.Callable): + if callable(value): value = value(env, source) return value @@ -230,7 +230,7 @@ class OverrideWarner(collections.UserDict): def warn(self): if self.already_warned: return - for k in list(self.keys()): + for k in self.keys(): if k in misleading_keywords: alt = misleading_keywords[k] msg = "Did you mean to use `%s' instead of `%s'?" % (alt, k) @@ -336,7 +336,7 @@ class EmitterProxy(object): # in strings. Maybe we should change that? while SCons.Util.is_String(emitter) and emitter in env: emitter = env[emitter] - if isinstance(emitter, collections.Callable): + if callable(emitter): target, source = emitter(target, source, env) elif SCons.Util.is_List(emitter): for e in emitter: @@ -426,9 +426,12 @@ class BuilderBase(object): src_builder = [ src_builder ] self.src_builder = src_builder - def __bool__(self): + def __nonzero__(self): raise InternalError("Do not test for the Node.builder attribute directly; use Node.has_builder() instead") + def __bool__(self): + return self.__nonzero__() + def get_name(self, env): """Attempts to get the name of the Builder. @@ -638,18 +641,18 @@ class BuilderBase(object): def get_prefix(self, env, sources=[]): prefix = self.prefix - if isinstance(prefix, collections.Callable): + if callable(prefix): prefix = prefix(env, sources) return env.subst(prefix) def set_suffix(self, suffix): - if not isinstance(suffix, collections.Callable): + if not callable(suffix): suffix = self.adjust_suffix(suffix) self.suffix = suffix def get_suffix(self, env, sources=[]): suffix = self.suffix - if isinstance(suffix, collections.Callable): + if callable(suffix): suffix = suffix(env, sources) return env.subst(suffix) @@ -658,7 +661,7 @@ class BuilderBase(object): src_suffix = [] elif not SCons.Util.is_List(src_suffix): src_suffix = [ src_suffix ] - self.src_suffix = [isinstance(suf, collections.Callable) and suf or self.adjust_suffix(suf) for suf in src_suffix] + self.src_suffix = [callable(suf) and suf or self.adjust_suffix(suf) for suf in src_suffix] def get_src_suffix(self, env): """Get the first src_suffix in the list of src_suffixes.""" @@ -868,7 +871,7 @@ def is_a_Builder(obj): """ return (isinstance(obj, BuilderBase) or isinstance(obj, CompositeBuilder) - or isinstance(obj, collections.Callable)) + or callable(obj)) # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py index da03a3c..41b640b 100644 --- a/src/engine/SCons/BuilderTests.py +++ b/src/engine/SCons/BuilderTests.py @@ -20,6 +20,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -77,7 +78,7 @@ class Environment(object): self.d['SHELL'] = scons_env['SHELL'] self.d['SPAWN'] = scons_env['SPAWN'] self.d['ESCAPE'] = scons_env['ESCAPE'] - for k, v in list(kw.items()): + for k, v in kw.items(): self.d[k] = v global env_arg2nodes_called env_arg2nodes_called = None @@ -138,7 +139,7 @@ class Environment(object): return list(self.d.items()) def sig_dict(self): d = {} - for k,v in list(self.items()): d[k] = v + for k,v in self.items(): d[k] = v d['TARGETS'] = ['__t1__', '__t2__', '__t3__', '__t4__', '__t5__', '__t6__'] d['TARGET'] = d['TARGETS'][0] d['SOURCES'] = ['__s1__', '__s2__', '__s3__', '__s4__', '__s5__', '__s6__'] @@ -305,11 +306,11 @@ class BuilderTestCase(unittest.TestCase): #be = target.get_build_env() #assert be['VAR'] == 'foo', be['VAR'] - try: str + try: unicode except NameError: uni = str else: - uni = str + uni = unicode target = builder(env, target = uni('n12 n13'), source = [uni('n14 n15')])[0] diff --git a/src/engine/SCons/Conftest.py b/src/engine/SCons/Conftest.py index 4e2a3e8..6212a47 100644 --- a/src/engine/SCons/Conftest.py +++ b/src/engine/SCons/Conftest.py @@ -728,7 +728,7 @@ def _Have(context, key, have, comment = None): line = "#define %s 1\n" % key_up elif have == 0: line = "/* #undef %s */\n" % key_up - elif isinstance(have, IntType): + elif isinstance(have, int): line = "#define %s %d\n" % (key_up, have) else: line = "#define %s %s\n" % (key_up, str(have)) diff --git a/src/engine/SCons/Debug.py b/src/engine/SCons/Debug.py index 363c8b7..1c0c638 100644 --- a/src/engine/SCons/Debug.py +++ b/src/engine/SCons/Debug.py @@ -73,7 +73,7 @@ def dumpLoggedInstances(classes, file=sys.stdout): obj = ref() if obj is not None: file.write(' %s:\n' % obj) - for key, value in list(obj.__dict__.items()): + for key, value in obj.__dict__.items(): file.write(' %20s : %s\n' % (key, value)) @@ -143,7 +143,7 @@ def caller_trace(back=0): # print a single caller and its callers, if any def _dump_one_caller(key, file, level=0): leader = ' '*level - for v,c in sorted([(-v,c) for c,v in list(caller_dicts[key].items())]): + for v,c in sorted([(-v,c) for c,v in caller_dicts[key].items()]): file.write("%s %6d %s:%d(%s)\n" % ((leader,-v) + func_shorten(c[-3:]))) if c in caller_dicts: _dump_one_caller(c, file, level+1) diff --git a/src/engine/SCons/Defaults.py b/src/engine/SCons/Defaults.py index fe1f87b..491b9f2 100644 --- a/src/engine/SCons/Defaults.py +++ b/src/engine/SCons/Defaults.py @@ -31,7 +31,7 @@ from distutils.msvccompiler. # 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 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -50,7 +50,6 @@ import SCons.Environment import SCons.PathList import SCons.Subst import SCons.Tool -import collections # A placeholder for a default Environment (for fetching source files # from source code management systems and the like). This must be @@ -326,9 +325,9 @@ def _stripixes(prefix, itms, suffix, stripprefixes, stripsuffixes, env, c=None): if not itms: return itms - if not isinstance(c, collections.Callable): + if not callable(c): env_c = env['_concat'] - if env_c != _concat and isinstance(env_c, collections.Callable): + if env_c != _concat and callable(env_c): # There's a custom _concat() method in the construction # environment, and we've allowed people to set that in # the past (see test/custom-concat.py), so preserve the diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 88b0553..b5bd620 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -58,7 +58,6 @@ import SCons.Subst import SCons.Tool import SCons.Util import SCons.Warnings -import collections class _Null(object): pass @@ -128,7 +127,7 @@ future_reserved_construction_var_names = [ def copy_non_reserved_keywords(dict): result = semi_deepcopy(dict) - for k in list(result.keys()): + for k in result.keys(): if k in reserved_construction_var_names: msg = "Ignoring attempt to set reserved variable `$%s'" SCons.Warnings.warn(SCons.Warnings.ReservedVariableWarning, msg % k) @@ -152,7 +151,7 @@ def _set_BUILDERS(env, key, value): except KeyError: bd = BuilderDict(kwbd, env) env._dict[key] = bd - for k, v in list(value.items()): + for k, v in value.items(): if not SCons.Builder.is_a_Builder(v): raise SCons.Errors.UserError('%s is not a Builder.' % repr(v)) bd.update(value) @@ -324,7 +323,7 @@ class BuilderDict(UserDict): delattr(self.env, item) def update(self, dict): - for i, v in list(dict.items()): + for i, v in dict.items(): self.__setitem__(i, v) @@ -518,7 +517,7 @@ class SubstitutionEnvironment(object): def subst_kw(self, kw, raw=0, target=None, source=None): nkw = {} - for k, v in list(kw.items()): + for k, v in kw.items(): k = self.subst(k, raw, target, source) if SCons.Util.is_String(v): v = self.subst(v, raw, target, source) @@ -592,7 +591,7 @@ class SubstitutionEnvironment(object): out,err = p.communicate() status = p.wait() if err: - sys.stderr.write(str(err)) + sys.stderr.write(u"" + err) if status: raise OSError("'%s' exited %d" % (command, status)) return out @@ -630,7 +629,7 @@ class SubstitutionEnvironment(object): if not o: return self overrides = {} merges = None - for key, value in list(o.items()): + for key, value in o.items(): if key == 'parse_flags': merges = value else: @@ -815,7 +814,7 @@ class SubstitutionEnvironment(object): if not unique: self.Append(**args) return self - for key, value in list(args.items()): + for key, value in args.items(): if not value: continue try: @@ -1005,7 +1004,7 @@ class Base(SubstitutionEnvironment): # Now restore the passed-in and customized variables # to the environment, since the values the user set explicitly # should override any values set by the tools. - for key, val in list(save.items()): + for key, val in save.items(): self._dict[key] = val # Finally, apply any flags to be merged in @@ -1263,7 +1262,7 @@ class Base(SubstitutionEnvironment): values move to end. """ kw = copy_non_reserved_keywords(kw) - for key, val in list(kw.items()): + for key, val in kw.items(): if SCons.Util.is_List(val): val = _delete_duplicates(val, delete_existing) if key not in self._dict or self._dict[key] in ('', None): @@ -1403,7 +1402,7 @@ class Base(SubstitutionEnvironment): # so the tools can use the new variables kw = copy_non_reserved_keywords(kw) new = {} - for key, value in list(kw.items()): + for key, value in kw.items(): new[key] = SCons.Subst.scons_subst_once(value, self, key) clone.Replace(**new) @@ -1470,7 +1469,7 @@ class Base(SubstitutionEnvironment): copy_function = self._copy_from_cache elif function == 'timestamp-match': function = self._changed_timestamp_match - elif not isinstance(function, collections.Callable): + elif not callable(function): raise UserError("Unknown Decider value %s" % repr(function)) # We don't use AddMethod because we don't want to turn the @@ -1603,7 +1602,7 @@ class Base(SubstitutionEnvironment): in an Environment. """ kw = copy_non_reserved_keywords(kw) - for key, val in list(kw.items()): + for key, val in kw.items(): # It would be easier on the eyes to write this using # "continue" statements whenever we finish processing an item, # but Python 1.5.2 apparently doesn't let you use "continue" @@ -1694,7 +1693,7 @@ class Base(SubstitutionEnvironment): values move to front. """ kw = copy_non_reserved_keywords(kw) - for key, val in list(kw.items()): + for key, val in kw.items(): if SCons.Util.is_List(val): val = _delete_duplicates(val, not delete_existing) if key not in self._dict or self._dict[key] in ('', None): @@ -1769,7 +1768,7 @@ class Base(SubstitutionEnvironment): return os.path.join(dir, new_prefix+name+new_suffix) def SetDefault(self, **kw): - for k in list(kw.keys()): + for k in kw.keys(): if k in self._dict: del kw[k] self.Replace(**kw) @@ -1831,7 +1830,7 @@ class Base(SubstitutionEnvironment): uniq = {} for executor in [n.get_executor() for n in nodes]: uniq[executor] = 1 - for executor in list(uniq.keys()): + for executor in uniq.keys(): executor.add_pre_action(action) return nodes @@ -1841,7 +1840,7 @@ class Base(SubstitutionEnvironment): uniq = {} for executor in [n.get_executor() for n in nodes]: uniq[executor] = 1 - for executor in list(uniq.keys()): + for executor in uniq.keys(): executor.add_post_action(action) return nodes diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index 3af879a..22552b3 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -20,6 +20,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -160,7 +161,7 @@ class TestEnvironmentFixture(object): default_keys = { 'CC' : 'cc', 'CCFLAGS' : '-DNDEBUG', 'ENV' : { 'TMP' : '/tmp' } } - for key, value in list(default_keys.items()): + for key, value in default_keys.items(): if key not in kw: kw[key] = value if 'BUILDERS' not in kw: @@ -263,16 +264,10 @@ class SubstitutionTestCase(unittest.TestCase): assert isinstance(nodes[0], X) assert nodes[0].name == "Util.py UtilTests.py" - try: str - except NameError: pass - else: - code = """if 1: - nodes = env.arg2nodes(u"Util.py UtilTests.py", Factory) - assert len(nodes) == 1, nodes - assert isinstance(nodes[0], X) - assert nodes[0].name == u"Util.py UtilTests.py" - \n""" - exec(code, globals(), locals()) + nodes = env.arg2nodes(u"Util.py UtilTests.py", Factory) + assert len(nodes) == 1, nodes + assert isinstance(nodes[0], X) + assert nodes[0].name == u"Util.py UtilTests.py" nodes = env.arg2nodes(["Util.py", "UtilTests.py"], Factory) assert len(nodes) == 2, nodes diff --git a/src/engine/SCons/Executor.py b/src/engine/SCons/Executor.py index 68419b8..6248cf1 100644 --- a/src/engine/SCons/Executor.py +++ b/src/engine/SCons/Executor.py @@ -428,8 +428,8 @@ class Executor(object): pass env = self.get_build_env() result = b"".join([action.get_contents(self.get_all_targets(), - self.get_all_sources(), - env) + self.get_all_sources(), + env) for action in self.get_action_list()]) self._memo['get_contents'] = result return result diff --git a/src/engine/SCons/Memoize.py b/src/engine/SCons/Memoize.py index 9fe6851..ac728c9 100644 --- a/src/engine/SCons/Memoize.py +++ b/src/engine/SCons/Memoize.py @@ -20,6 +20,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/src/engine/SCons/MemoizeTests.py b/src/engine/SCons/MemoizeTests.py index b6750e0..06b4235 100644 --- a/src/engine/SCons/MemoizeTests.py +++ b/src/engine/SCons/MemoizeTests.py @@ -20,6 +20,7 @@ # 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 six import add_metaclass __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -29,8 +30,8 @@ import unittest import SCons.Memoize - -class FakeObject(object, metaclass=SCons.Memoize.Memoized_Metaclass): +@add_metaclass(SCons.Memoize.Memoized_Metaclass) +class FakeObject(object): memoizer_counters = [] diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 22dca1f..91c6893 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -31,6 +31,7 @@ that can be used by scripts or modules looking for the canonical default. # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -54,7 +55,6 @@ import SCons.Util import SCons.Warnings from SCons.Debug import Trace -import collections do_store_info = True print_duplicate = 0 @@ -1509,7 +1509,7 @@ class Dir(Base): This clears any cached information that is invalidated by changing the repository.""" - for node in list(self.entries.values()): + for node in self.entries.values(): if node != self.dir: if node != self and isinstance(node, Dir): node.__clearRepositoryCache(duplicate) @@ -2056,7 +2056,7 @@ class Dir(Base): # We use the .name attribute from the Node because the keys of # the dir.entries dictionary are normalized (that is, all upper # case) on case-insensitive systems like Windows. - node_names = [ v.name for k, v in list(dir.entries.items()) + node_names = [ v.name for k, v in dir.entries.items() if k not in ('.', '..') ] names.extend(node_names) if not strings: @@ -3197,10 +3197,10 @@ class FileFinder(object): except KeyError: pass - if verbose and not isinstance(verbose, collections.Callable): + if verbose and not callable(verbose): if not SCons.Util.is_String(verbose): verbose = "find_file" - _verbose = ' %s: ' % verbose + _verbose = u' %s: ' % verbose verbose = lambda s: sys.stdout.write(_verbose + s) filedir, filename = os.path.split(filename) diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index e8442e9..66803f9 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -20,7 +20,7 @@ # 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, print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -1305,7 +1305,7 @@ class FSTestCase(_tempdirTestCase): assert f1.get_contents() == "Foo\x1aBar", f1.get_contents() # This tests to make sure we can decode UTF-8 text files. - test_string = "Foo\x1aBar" + test_string = u"Foo\x1aBar" test.write("utf8_file", test_string.encode('utf-8')) f1 = fs.File(test.workpath("utf8_file")) assert eval('f1.get_text_contents() == u"Foo\x1aBar"'), \ diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 8f48d86..7f5d7ff 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -1197,8 +1197,8 @@ class Node(object): new_bkids = new.bsources + new.bdepends + new.bimplicit new_bkidsigs = new.bsourcesigs + new.bdependsigs + new.bimplicitsigs - osig = dict(list(zip(old_bkids, old_bkidsigs))) - nsig = dict(list(zip(new_bkids, new_bkidsigs))) + osig = dict(zip(old_bkids, old_bkidsigs)) + nsig = dict(zip(new_bkids, new_bkidsigs)) # The sources and dependencies we'll want to report are all stored # as relative paths to this target's directory, but we want to diff --git a/src/engine/SCons/Platform/__init__.py b/src/engine/SCons/Platform/__init__.py index 6ef8b05..dba3606 100644 --- a/src/engine/SCons/Platform/__init__.py +++ b/src/engine/SCons/Platform/__init__.py @@ -41,6 +41,7 @@ their own platform definition. # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/src/engine/SCons/Platform/posix.py b/src/engine/SCons/Platform/posix.py index d1f6c78..908be4d 100644 --- a/src/engine/SCons/Platform/posix.py +++ b/src/engine/SCons/Platform/posix.py @@ -92,7 +92,7 @@ def _get_env_command(sh, escape, cmd, args, env): s = ' '.join(args) if env: l = ['env', '-'] + \ - [escape(t[0])+'='+escape(t[1]) for t in list(env.items())] + \ + [escape(t[0])+'='+escape(t[1]) for t in env.items()] + \ [sh, '-c', escape(s)] s = ' '.join(l) return s diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index e14c5e0..62f2671 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -25,6 +25,7 @@ Autoconf-like configuration support. # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -118,7 +119,7 @@ def CreateConfigHBuilder(env): _stringConfigH) sconfigHBld = SCons.Builder.Builder(action=action) env.Append( BUILDERS={'SConfigHBuilder':sconfigHBld} ) - for k in list(_ac_config_hs.keys()): + for k in _ac_config_hs.keys(): env.SConfigHBuilder(k, env.Value(_ac_config_hs[k])) class SConfWarning(SCons.Warnings.Warning): @@ -175,19 +176,13 @@ class Streamer(object): """ def __init__(self, orig): self.orig = orig - try: - import StringIO - self.s = StringIO.StringIO() - except: - self.s = io.StringIO() + self.s = io.StringIO() def write(self, str): - try: - if self.orig: - self.orig.write(str) - self.s.write(str) - except: - print ('oops') + if self.orig: + self.orig.write(str) + self.s.write(str) + def writelines(self, lines): for l in lines: self.write(l + '\n') @@ -658,7 +653,7 @@ class SConfBase(object): """Adds all the tests given in the tests dictionary to this SConf instance """ - for name in list(tests.keys()): + for name in tests.keys(): self.AddTest(name, tests[name]) def _createDir( self, node ): diff --git a/src/engine/SCons/SConfTests.py b/src/engine/SCons/SConfTests.py index ba524fd..e604886 100644 --- a/src/engine/SCons/SConfTests.py +++ b/src/engine/SCons/SConfTests.py @@ -60,7 +60,7 @@ class SConfTestCase(unittest.TestCase): # We try to reset scons' state (including all global variables) import SCons.SConsign SCons.SConsign.write() # simulate normal scons-finish - for n in list(sys.modules.keys()): + for n in sys.modules.keys(): if n.split('.')[0] == 'SCons' and n[:12] != 'SCons.compat': m = sys.modules[n] if isinstance(m, ModuleType): diff --git a/src/engine/SCons/SConsign.py b/src/engine/SCons/SConsign.py index 5ce61be..ab8e297 100644 --- a/src/engine/SCons/SConsign.py +++ b/src/engine/SCons/SConsign.py @@ -26,6 +26,7 @@ Writing and reading information to the .sconsign file or files. # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -172,7 +173,7 @@ class Base(object): pass def merge(self): - for key, node in list(self.to_be_merged.items()): + for key, node in self.to_be_merged.items(): entry = node.get_stored_info() try: ninfo = entry.ninfo @@ -218,7 +219,7 @@ class DB(Base): except Exception as e: SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning, "Ignoring corrupt sconsign entry : %s (%s)\n"%(self.dir.tpath, e)) - for key, entry in list(self.entries.items()): + for key, entry in self.entries.items(): entry.convert_from_sconsign(dir, key) if mode == "r": @@ -245,7 +246,7 @@ class DB(Base): # the Repository; we only write to our own .sconsign file, # not to .sconsign files in Repositories. path = normcase(self.dir.path) - for key, entry in list(self.entries.items()): + for key, entry in self.entries.items(): entry.convert_to_sconsign() db[path] = pickle.dumps(self.entries, 1) @@ -333,7 +334,7 @@ class DirFile(Dir): fname = self.sconsign except IOError: return - for key, entry in list(self.entries.items()): + for key, entry in self.entries.items(): entry.convert_to_sconsign() pickle.dump(self.entries, file, 1) file.close() diff --git a/src/engine/SCons/Scanner/Fortran.py b/src/engine/SCons/Scanner/Fortran.py index 5339ab2..1b55130 100644 --- a/src/engine/SCons/Scanner/Fortran.py +++ b/src/engine/SCons/Scanner/Fortran.py @@ -35,7 +35,6 @@ import SCons.Node.FS import SCons.Scanner import SCons.Util import SCons.Warnings -import collections class F90Scanner(SCons.Scanner.Classic): """ @@ -110,7 +109,7 @@ class F90Scanner(SCons.Scanner.Classic): # is actually found in a Repository or locally. nodes = [] source_dir = node.get_dir() - if isinstance(path, collections.Callable): + if callable(path): path = path() for dep in mods_and_includes: n, i = self.find_include(dep, source_dir, path) diff --git a/src/engine/SCons/Scanner/LaTeX.py b/src/engine/SCons/Scanner/LaTeX.py index 1e0fea1..2cb1ed5 100644 --- a/src/engine/SCons/Scanner/LaTeX.py +++ b/src/engine/SCons/Scanner/LaTeX.py @@ -200,14 +200,14 @@ class LaTeX(SCons.Scanner.Base): """ def __init__(self, dictionary): self.dictionary = {} - for k,n in list(dictionary.items()): + for k,n in dictionary.items(): self.dictionary[k] = ( SCons.Scanner.FindPathDirs(n), FindENVPathDirs(n) ) def __call__(self, env, dir=None, target=None, source=None, argument=None): di = {} - for k,(c,cENV) in list(self.dictionary.items()): + for k,(c,cENV) in self.dictionary.items(): di[k] = ( c(env, dir=None, target=None, source=None, argument=None) , cENV(env, dir=None, target=None, source=None, diff --git a/src/engine/SCons/Scanner/Prog.py b/src/engine/SCons/Scanner/Prog.py index 6e2da21..49e93a5 100644 --- a/src/engine/SCons/Scanner/Prog.py +++ b/src/engine/SCons/Scanner/Prog.py @@ -27,7 +27,6 @@ import SCons.Node import SCons.Node.FS import SCons.Scanner import SCons.Util -import collections # global, set by --debug=findlibs print_find_libs = None @@ -77,7 +76,7 @@ def scan(node, env, libpath = ()): result = [] - if isinstance(libpath, collections.Callable): + if callable(libpath): libpath = libpath() find_file = SCons.Node.FS.find_file diff --git a/src/engine/SCons/Scanner/ProgTests.py b/src/engine/SCons/Scanner/ProgTests.py index f564c91..250838d 100644 --- a/src/engine/SCons/Scanner/ProgTests.py +++ b/src/engine/SCons/Scanner/ProgTests.py @@ -230,7 +230,7 @@ def suite(): suite.addTest(ProgramScannerTestCase6()) suite.addTest(ProgramScannerTestCase7()) suite.addTest(ProgramScannerTestCase8()) - try: str + try: unicode except NameError: pass else: code = """if 1: diff --git a/src/engine/SCons/Scanner/ScannerTests.py b/src/engine/SCons/Scanner/ScannerTests.py index 5a4639d..ee26922 100644 --- a/src/engine/SCons/Scanner/ScannerTests.py +++ b/src/engine/SCons/Scanner/ScannerTests.py @@ -569,7 +569,7 @@ class ClassicCPPTestCase(unittest.TestCase): assert n == 'path/bbb', n assert i == 'bbb', i - n, i = s.find_include(('<', 'ccc'), 'foo', ('path',)) + n, i = s.find_include(('<', u'ccc'), 'foo', ('path',)) assert n == 'path/ccc', n assert i == 'ccc', i diff --git a/src/engine/SCons/Scanner/__init__.py b/src/engine/SCons/Scanner/__init__.py index b947961..2375bc4 100644 --- a/src/engine/SCons/Scanner/__init__.py +++ b/src/engine/SCons/Scanner/__init__.py @@ -33,7 +33,6 @@ import re import SCons.Node.FS import SCons.Util -import collections class _Null(object): @@ -179,7 +178,7 @@ class Base(object): self.node_class = node_class self.node_factory = node_factory self.scan_check = scan_check - if isinstance(recursive, collections.Callable): + if callable(recursive): self.recurse_nodes = recursive elif recursive: self.recurse_nodes = self._recurse_all_nodes @@ -370,7 +369,7 @@ class Classic(Current): # is actually found in a Repository or locally. nodes = [] source_dir = node.get_dir() - if isinstance(path, collections.Callable): + if callable(path): path = path() for include in includes: n, i = self.find_include(include, source_dir, path) diff --git a/src/engine/SCons/Script/Interactive.py b/src/engine/SCons/Script/Interactive.py index 87fe1cf..0b28f1a 100644 --- a/src/engine/SCons/Script/Interactive.py +++ b/src/engine/SCons/Script/Interactive.py @@ -19,6 +19,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -120,7 +121,7 @@ class SConsInteractiveCmd(cmd.Cmd): def __init__(self, **kw): cmd.Cmd.__init__(self) - for key, val in list(kw.items()): + for key, val in kw.items(): setattr(self, key, val) if sys.platform == 'win32': @@ -249,7 +250,7 @@ class SConsInteractiveCmd(cmd.Cmd): while n: n = walker.get_next() - for node in list(seen_nodes.keys()): + for node in seen_nodes.keys(): # Call node.clear() to clear most of the state node.clear() # node.clear() doesn't reset node.state, so call diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index 9a52937..584960b 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -10,6 +10,8 @@ some other module. If it's specific to the "scons" script invocation, it goes here. """ +from __future__ import print_function + unsupported_python_version = (2, 3, 0) deprecated_python_version = (2, 7, 0) @@ -68,7 +70,6 @@ import SCons.Util import SCons.Warnings import SCons.Script.Interactive -import collections def fetch_win32_parallel_msg(): # A subsidiary function that exists solely to isolate this import @@ -105,7 +106,7 @@ class Progressor(object): self.interval = interval self.overwrite = overwrite - if isinstance(obj, collections.Callable): + if callable(obj): self.func = obj elif SCons.Util.is_List(obj): self.func = self.spinner @@ -716,7 +717,7 @@ def _load_site_scons_dir(topdir, site_dir_name=None): modname = os.path.basename(pathname)[:-len(sfx)] site_m = {"__file__": pathname, "__name__": modname, "__doc__": None} re_special = re.compile("__[^_]+__") - for k in list(m.__dict__.keys()): + for k in m.__dict__.keys(): if not re_special.match(k): site_m[k] = m.__dict__[k] diff --git a/src/engine/SCons/Script/SConsOptions.py b/src/engine/SCons/Script/SConsOptions.py index 559db97..a97fc94 100644 --- a/src/engine/SCons/Script/SConsOptions.py +++ b/src/engine/SCons/Script/SConsOptions.py @@ -611,7 +611,7 @@ def Parser(version): deprecated_debug_options=deprecated_debug_options): if value in debug_options: parser.values.debug.append(value) - elif value in list(deprecated_debug_options.keys()): + elif value in deprecated_debug_options.keys(): parser.values.debug.append(value) try: parser.values.delayed_warnings diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py index 05cb6a6..b2dc4c1 100644 --- a/src/engine/SCons/Script/SConscript.py +++ b/src/engine/SCons/Script/SConscript.py @@ -26,7 +26,7 @@ files. # 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, print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -529,7 +529,7 @@ class SConsEnvironment(SCons.Environment.Base): return x ls = list(map(subst_element, ls)) subst_kw = {} - for key, val in list(kw.items()): + for key, val in kw.items(): if SCons.Util.is_String(val): val = self.subst(val) elif SCons.Util.is_List(val): diff --git a/src/engine/SCons/Subst.py b/src/engine/SCons/Subst.py index cca9bbc..f1e80ac 100644 --- a/src/engine/SCons/Subst.py +++ b/src/engine/SCons/Subst.py @@ -472,7 +472,7 @@ def scons_subst(strSubst, env, mode=SUBST_RAW, target=None, source=None, gvars={ def func(l, conv=self.conv, substitute=self.substitute, lvars=lvars): return conv(substitute(l, lvars)) return list(map(func, s)) - elif isinstance(s, collections.Callable): + elif callable(s): try: s = s(target=lvars['TARGETS'], source=lvars['SOURCES'], @@ -681,7 +681,7 @@ def scons_subst_list(strSubst, env, mode=SUBST_RAW, target=None, source=None, gv for a in s: self.substitute(a, lvars, 1) self.next_word() - elif isinstance(s, collections.Callable): + elif callable(s): try: s = s(target=lvars['TARGETS'], source=lvars['SOURCES'], diff --git a/src/engine/SCons/SubstTests.py b/src/engine/SCons/SubstTests.py index da21020..7001899 100644 --- a/src/engine/SCons/SubstTests.py +++ b/src/engine/SCons/SubstTests.py @@ -20,6 +20,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py index 14ffe8c..86bff53 100644 --- a/src/engine/SCons/Taskmaster.py +++ b/src/engine/SCons/Taskmaster.py @@ -19,6 +19,7 @@ # 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 print_function __doc__ = """ Generic Taskmaster module for the SCons build engine. @@ -164,7 +165,7 @@ class Task(object): """ global print_prepare T = self.tm.trace - if T: T.write(self.trace_message('Task.prepare()', self.node)) + if T: T.write(self.trace_message(u'Task.prepare()', self.node)) # Now that it's the appropriate time, give the TaskMaster a # chance to raise any exceptions it encountered while preparing @@ -224,7 +225,7 @@ class Task(object): prepare(), executed() or failed(). """ T = self.tm.trace - if T: T.write(self.trace_message('Task.execute()', self.node)) + if T: T.write(self.trace_message(u'Task.execute()', self.node)) try: cached_targets = [] @@ -383,7 +384,7 @@ class Task(object): This is the default behavior for building only what's necessary. """ T = self.tm.trace - if T: T.write(self.trace_message('Task.make_ready_current()', + if T: T.write(self.trace_message(u'Task.make_ready_current()', self.node)) self.out_of_date = [] @@ -428,7 +429,7 @@ class Task(object): that can be put back on the candidates list. """ T = self.tm.trace - if T: T.write(self.trace_message('Task.postprocess()', self.node)) + if T: T.write(self.trace_message(u'Task.postprocess()', self.node)) # We may have built multiple targets, some of which may have # common parents waiting for this build. Count up how many @@ -445,7 +446,7 @@ class Task(object): # A node can only be in the pending_children set if it has # some waiting_parents. if t.waiting_parents: - if T: T.write(self.trace_message('Task.postprocess()', + if T: T.write(self.trace_message(u'Task.postprocess()', t, 'removing')) pending_children.discard(t) @@ -462,9 +463,9 @@ class Task(object): if p.ref_count == 0: self.tm.candidates.append(p) - for p, subtract in list(parents.items()): + for p, subtract in parents.items(): p.ref_count = p.ref_count - subtract - if T: T.write(self.trace_message('Task.postprocess()', + if T: T.write(self.trace_message(u'Task.postprocess()', p, 'adjusted parent ref count')) if p.ref_count == 0: @@ -744,12 +745,12 @@ class Taskmaster(object): self.ready_exc = None T = self.trace - if T: T.write('\n' + self.trace_message('Looking for a node to evaluate')) + if T: T.write(u'\n' + self.trace_message('Looking for a node to evaluate')) while True: node = self.next_candidate() if node is None: - if T: T.write(self.trace_message('No candidate anymore.') + '\n') + if T: T.write(self.trace_message('No candidate anymore.') + u'\n') return None node = node.disambiguate() @@ -772,7 +773,7 @@ class Taskmaster(object): else: S = None - if T: T.write(self.trace_message(' Considering node %s and its children:' % self.trace_node(node))) + if T: T.write(self.trace_message(u' Considering node %s and its children:' % self.trace_node(node))) if state == NODE_NO_STATE: # Mark this node as being on the execution stack: @@ -780,7 +781,7 @@ class Taskmaster(object): elif state > NODE_PENDING: # Skip this node if it has already been evaluated: if S: S.already_handled = S.already_handled + 1 - if T: T.write(self.trace_message(' already handled (executed)')) + if T: T.write(self.trace_message(u' already handled (executed)')) continue executor = node.get_executor() @@ -811,7 +812,7 @@ class Taskmaster(object): for child in chain(executor.get_all_prerequisites(), children): childstate = child.get_state() - if T: T.write(self.trace_message(' ' + self.trace_node(child))) + if T: T.write(self.trace_message(u' ' + self.trace_node(child))) if childstate == NODE_NO_STATE: children_not_visited.append(child) @@ -870,7 +871,7 @@ class Taskmaster(object): # count so we can be put back on the list for # re-evaluation when they've all finished. node.ref_count = node.ref_count + child.add_to_waiting_parents(node) - if T: T.write(self.trace_message(' adjusted ref count: %s, child %s' % + if T: T.write(self.trace_message(u' adjusted ref count: %s, child %s' % (self.trace_node(node), repr(str(child))))) if T: @@ -896,7 +897,7 @@ class Taskmaster(object): # The default when we've gotten through all of the checks above: # this node is ready to be built. if S: S.build = S.build + 1 - if T: T.write(self.trace_message('Evaluating %s\n' % + if T: T.write(self.trace_message(u'Evaluating %s\n' % self.trace_node(node))) # For debugging only: diff --git a/src/engine/SCons/TaskmasterTests.py b/src/engine/SCons/TaskmasterTests.py index 0140278..278b690 100644 --- a/src/engine/SCons/TaskmasterTests.py +++ b/src/engine/SCons/TaskmasterTests.py @@ -20,7 +20,7 @@ # 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 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/src/engine/SCons/Tool/FortranCommon.py b/src/engine/SCons/Tool/FortranCommon.py index c21128e..088c717 100644 --- a/src/engine/SCons/Tool/FortranCommon.py +++ b/src/engine/SCons/Tool/FortranCommon.py @@ -26,6 +26,7 @@ Stuff for processing Fortran, common to all fortran dialects. # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -167,7 +168,7 @@ def add_fortran_to_env(env): except KeyError: FortranSuffixes = ['.f', '.for', '.ftn'] - #print "Adding %s to fortran suffixes" % FortranSuffixes + #print("Adding %s to fortran suffixes" % FortranSuffixes) try: FortranPPSuffixes = env['FORTRANPPFILESUFFIXES'] except KeyError: @@ -191,7 +192,7 @@ def add_f77_to_env(env): except KeyError: F77Suffixes = ['.f77'] - #print "Adding %s to f77 suffixes" % F77Suffixes + #print("Adding %s to f77 suffixes" % F77Suffixes) try: F77PPSuffixes = env['F77PPFILESUFFIXES'] except KeyError: diff --git a/src/engine/SCons/Tool/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py index dcf69c8..e1b4820 100644 --- a/src/engine/SCons/Tool/MSCommon/common.py +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -20,6 +20,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -113,7 +114,7 @@ def normalize_env(env, keys, force=False): Note: the environment is copied.""" normenv = {} if env: - for k in list(env.keys()): + for k in env.keys(): normenv[k] = copy.deepcopy(env[k]).encode('mbcs') for k in keys: @@ -217,7 +218,7 @@ def parse_output(output, keep = ("INCLUDE", "LIB", "LIBPATH", "PATH")): dkeep[key].append(p) for line in output.splitlines(): - for k,v in list(rdk.items()): + for k,v in rdk.items(): m = v.match(line) if m: add_env(m, k) diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index 35b95d5..1a221ac 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -468,7 +468,7 @@ def msvc_setup_env(env): SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg) return None - for k, v in list(d.items()): + for k, v in d.items(): debug('vc.py:msvc_setup_env() env:%s -> %s'%(k,v)) env.PrependENVPath(k, v, delete_existing=True) diff --git a/src/engine/SCons/Tool/MSCommon/vs.py b/src/engine/SCons/Tool/MSCommon/vs.py index 3219719..0a170fb 100644 --- a/src/engine/SCons/Tool/MSCommon/vs.py +++ b/src/engine/SCons/Tool/MSCommon/vs.py @@ -536,7 +536,7 @@ def msvs_setup_env(env): env['ENV'] = save_ENV vars = parse_output(output, vars) - for k, v in list(vars.items()): + for k, v in vars.items(): env.PrependENVPath(k, v, delete_existing=1) def query_versions(): diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index 1d5b504..517b987 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -34,6 +34,7 @@ tool definition. # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -631,7 +632,7 @@ class ToolInitializer(object): so we no longer copy and re-bind them when the construction environment gets cloned. """ - for method in list(self.methods.values()): + for method in self.methods.values(): env.RemoveMethod(method) def apply_tools(self, env): diff --git a/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py b/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py index ef03206..e7b8cfa 100644 --- a/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py +++ b/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py @@ -1,5 +1,6 @@ # docbook.py: extension module # $Id: docbook.py 8353 2009-03-17 16:57:50Z mzjn $ +from __future__ import print_function import sys import string diff --git a/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/xslt.py b/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/xslt.py index 8554dd1..77ca0de 100644 --- a/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/xslt.py +++ b/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/xslt.py @@ -1,5 +1,6 @@ #!/usr/bin/python -u # $Id: xslt.py 8353 2009-03-17 16:57:50Z mzjn $ +from __future__ import print_function import sys import libxml2 diff --git a/src/engine/SCons/Tool/install.py b/src/engine/SCons/Tool/install.py index 4236e81..0d75765 100644 --- a/src/engine/SCons/Tool/install.py +++ b/src/engine/SCons/Tool/install.py @@ -29,6 +29,7 @@ selection method. # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/src/engine/SCons/Tool/intelc.py b/src/engine/SCons/Tool/intelc.py index 8b178a7..86c6e12 100644 --- a/src/engine/SCons/Tool/intelc.py +++ b/src/engine/SCons/Tool/intelc.py @@ -30,7 +30,7 @@ selection method. # 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, print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -438,14 +438,14 @@ def generate(env, version=None, abi=None, topdir=None, verbose=0): 'LIB' : libdir, 'PATH' : bindir, 'LD_LIBRARY_PATH' : libdir} - for p in list(paths.keys()): + for p in paths.keys(): env.PrependENVPath(p, os.path.join(topdir, paths[p])) if is_mac: paths={'INCLUDE' : 'include', 'LIB' : libdir, 'PATH' : bindir, 'LD_LIBRARY_PATH' : libdir} - for p in list(paths.keys()): + for p in paths.keys(): env.PrependENVPath(p, os.path.join(topdir, paths[p])) if is_windows: # env key reg valname default subdir of top diff --git a/src/engine/SCons/Tool/link.py b/src/engine/SCons/Tool/link.py index 864a018..c7c6790 100644 --- a/src/engine/SCons/Tool/link.py +++ b/src/engine/SCons/Tool/link.py @@ -30,6 +30,7 @@ selection method. # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/src/engine/SCons/Tool/mslink.py b/src/engine/SCons/Tool/mslink.py index b56d34a..f30c1d3 100644 --- a/src/engine/SCons/Tool/mslink.py +++ b/src/engine/SCons/Tool/mslink.py @@ -30,6 +30,7 @@ selection method. # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -183,7 +184,7 @@ def prog_emitter(target, source, env): # MSVC 11 and above need the PCH object file to be added to the link line, # otherwise you get link error LNK2011. pchobj = SCons.Util.splitext(str(env['PCH']))[0] + '.obj' - # print "prog_emitter, version %s, appending pchobj %s"%(version_num, pchobj) + # print("prog_emitter, version %s, appending pchobj %s"%(version_num, pchobj)) if pchobj not in extrasources: extrasources.append(pchobj) diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py index 0879a28..370af9a 100644 --- a/src/engine/SCons/Tool/msvs.py +++ b/src/engine/SCons/Tool/msvs.py @@ -29,6 +29,7 @@ selection method. # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -357,7 +358,7 @@ class _DSPGenerator(object): AddConfig(self, variants[i], buildtarget[i], outdir[i], runfile[i], cmdargs) self.platforms = [] - for key in list(self.configs.keys()): + for key in self.configs.keys(): platform = self.configs[key].platform if not platform in self.platforms: self.platforms.append(platform) @@ -480,7 +481,7 @@ class _GenerateV6DSP(_DSPGenerator): 'Resource Files': 'r|rc|ico|cur|bmp|dlg|rc2|rct|bin|cnt|rtf|gif|jpg|jpeg|jpe', 'Other Files': ''} - for kind in sorted(list(categories.keys()), key=lambda a: a.lower()): + for kind in sorted(categories.keys(), key=lambda a: a.lower()): if not self.sources[kind]: continue # skip empty groups @@ -744,7 +745,7 @@ class _GenerateV7DSP(_DSPGenerator): self.file.write(pdata + '-->\n') def printSources(self, hierarchy, commonprefix): - sorteditems = sorted(list(hierarchy.items()), key=lambda a: a[0].lower()) + sorteditems = sorted(hierarchy.items(), key=lambda a: a[0].lower()) # First folders, then files for key, value in sorteditems: @@ -774,7 +775,7 @@ class _GenerateV7DSP(_DSPGenerator): self.file.write('\t\n') - cats = sorted([k for k in list(categories.keys()) if self.sources[k]], + cats = sorted([k for k in categories.keys() if self.sources[k]], key=lambda a: a.lower()) for kind in cats: if len(cats) > 1: @@ -1055,7 +1056,7 @@ class _GenerateV10DSP(_DSPGenerator): self.file.write(pdata + '-->\n') def printFilters(self, hierarchy, name): - sorteditems = sorted(list(hierarchy.items()), key = lambda a: a[0].lower()) + sorteditems = sorted(hierarchy.items(), key = lambda a: a[0].lower()) for key, value in sorteditems: if SCons.Util.is_Dict(value): @@ -1072,7 +1073,7 @@ class _GenerateV10DSP(_DSPGenerator): 'Resource Files': 'None', 'Other Files': 'None'} - sorteditems = sorted(list(hierarchy.items()), key = lambda a: a[0].lower()) + sorteditems = sorted(hierarchy.items(), key = lambda a: a[0].lower()) # First folders, then files for key, value in sorteditems: @@ -1098,7 +1099,7 @@ class _GenerateV10DSP(_DSPGenerator): 'Resource Files': 'r;rc;ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe', 'Other Files': ''} - cats = sorted([k for k in list(categories.keys()) if self.sources[k]], + cats = sorted([k for k in categories.keys() if self.sources[k]], key = lambda a: a.lower()) # print vcxproj.filters file first @@ -1254,7 +1255,7 @@ class _GenerateV7DSW(_DSWGenerator): AddConfig(self, variant) self.platforms = [] - for key in list(self.configs.keys()): + for key in self.configs.keys(): platform = self.configs[key].platform if not platform in self.platforms: self.platforms.append(platform) diff --git a/src/engine/SCons/Tool/msvsTests.py b/src/engine/SCons/Tool/msvsTests.py index 1466db6..1f5fb2b 100644 --- a/src/engine/SCons/Tool/msvsTests.py +++ b/src/engine/SCons/Tool/msvsTests.py @@ -20,6 +20,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/src/engine/SCons/Tool/packaging/__init__.py b/src/engine/SCons/Tool/packaging/__init__.py index c3de2aa..345ec87 100644 --- a/src/engine/SCons/Tool/packaging/__init__.py +++ b/src/engine/SCons/Tool/packaging/__init__.py @@ -72,7 +72,7 @@ def Tag(env, target, source, *more_tags, **kw_tags): target=env.Flatten(target) for t in target: - for (k,v) in list(kw_tags.items()): + for (k,v) in kw_tags.items(): # all file tags have to start with PACKAGING_, so we can later # differentiate between "normal" object attributes and the # packaging attributes. As the user should not be bothered with diff --git a/src/engine/SCons/Tool/packaging/ipk.py b/src/engine/SCons/Tool/packaging/ipk.py index ad27a62..6549445 100644 --- a/src/engine/SCons/Tool/packaging/ipk.py +++ b/src/engine/SCons/Tool/packaging/ipk.py @@ -169,7 +169,7 @@ Description: $X_IPK_DESCRIPTION # # close all opened files - for f in list(opened_files.values()): + for f in opened_files.values(): f.close() # call a user specified function diff --git a/src/engine/SCons/Tool/packaging/msi.py b/src/engine/SCons/Tool/packaging/msi.py index 70fdc48..49c28ca 100644 --- a/src/engine/SCons/Tool/packaging/msi.py +++ b/src/engine/SCons/Tool/packaging/msi.py @@ -172,7 +172,7 @@ def generate_guids(root): # find all XMl nodes matching the key, retrieve their attribute, hash their # subtree, convert hash to string and add as a attribute to the xml node. - for (key,value) in list(needs_id.items()): + for (key,value) in needs_id.items(): node_list = root.getElementsByTagName(key) attribute = value for node in node_list: @@ -335,7 +335,7 @@ def build_wxsfile_file_section(root, files, NAME, VERSION, VENDOR, filename_set, } # fill in the default tags given above. - for k,v in [ (k, v) for (k,v) in list(h.items()) if not hasattr(file, k) ]: + for k,v in [ (k, v) for (k,v) in h.items() if not hasattr(file, k) ]: setattr( file, k, v ) File = factory.createElement( 'File' ) @@ -382,7 +382,7 @@ def build_wxsfile_features_section(root, files, NAME, VERSION, SUMMARY, id_set): Feature.attributes['Description'] = escape( SUMMARY ) Feature.attributes['Display'] = 'expand' - for (feature, files) in list(create_feature_dict(files).items()): + for (feature, files) in create_feature_dict(files).items(): SubFeature = factory.createElement('Feature') SubFeature.attributes['Level'] = '1' diff --git a/src/engine/SCons/Tool/packaging/rpm.py b/src/engine/SCons/Tool/packaging/rpm.py index 4958065..a9e0fa2 100644 --- a/src/engine/SCons/Tool/packaging/rpm.py +++ b/src/engine/SCons/Tool/packaging/rpm.py @@ -277,7 +277,7 @@ def build_specfile_filesection(spec, files): for file in files: # build the tagset tags = {} - for k in list(supported_tags.keys()): + for k in supported_tags.keys(): try: tags[k]=getattr(file, k) except AttributeError: @@ -340,7 +340,7 @@ class SimpleTagCompiler(object): for key, replacement in international: try: #int_values_for_key = [ (get_country_code(k),v) for k,v in values.items() if strip_country_code(k) == key ] - x = [t for t in list(values.items()) if strip_country_code(t[0]) == key] + x = [t for t in values.items() if strip_country_code(t[0]) == key] int_values_for_key = [(get_country_code(t[0]),t[1]) for t in x] for v in int_values_for_key: str = str + replacement % v diff --git a/src/engine/SCons/Tool/qt.py b/src/engine/SCons/Tool/qt.py index fdfdd26..723c39c 100644 --- a/src/engine/SCons/Tool/qt.py +++ b/src/engine/SCons/Tool/qt.py @@ -31,6 +31,7 @@ selection method. # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/src/engine/SCons/Tool/rpmutils.py b/src/engine/SCons/Tool/rpmutils.py index e96c54c..a444508 100644 --- a/src/engine/SCons/Tool/rpmutils.py +++ b/src/engine/SCons/Tool/rpmutils.py @@ -34,6 +34,7 @@ exact syntax. # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/src/engine/SCons/Tool/tex.py b/src/engine/SCons/Tool/tex.py index febec35..dac98b7 100644 --- a/src/engine/SCons/Tool/tex.py +++ b/src/engine/SCons/Tool/tex.py @@ -31,6 +31,7 @@ selection method. # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/src/engine/SCons/Tool/textfile.py b/src/engine/SCons/Tool/textfile.py index 4897113..693b62b 100644 --- a/src/engine/SCons/Tool/textfile.py +++ b/src/engine/SCons/Tool/textfile.py @@ -54,7 +54,6 @@ import re from SCons.Node import Node from SCons.Node.Python import Value from SCons.Util import is_String, is_Sequence, is_Dict -import collections def _do_subst(node, subs): """ @@ -97,7 +96,7 @@ def _action(target, source, env): raise SCons.Errors.UserError('SUBST_DICT must be dict or sequence') subs = [] for (k,v) in d: - if isinstance(v, collections.Callable): + if callable(v): v = v() if is_String(v): v = env.subst(v) diff --git a/src/engine/SCons/Tool/xgettext.py b/src/engine/SCons/Tool/xgettext.py index 489d4d7..f9375a2 100644 --- a/src/engine/SCons/Tool/xgettext.py +++ b/src/engine/SCons/Tool/xgettext.py @@ -23,6 +23,7 @@ Tool specific initialization of `xgettext` tool. # 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 six import u __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -55,7 +56,7 @@ class _CmdRunner(object): proc = SCons.Action._subproc(env, command, **kw) self.out, self.err = proc.communicate() self.status = proc.wait() - if self.err: sys.stderr.write(str(self.err)) + if self.err: sys.stderr.write(u(self.err)) return self.status def strfunction(self, target, source, env): diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 0c4daff..60e5c10 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -23,6 +23,7 @@ Various utility functions go here. # 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 six import PY2, PY3, u __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -32,14 +33,22 @@ import copy import re import types -from collections import UserDict, UserList, UserString -import collections +try: + from collections import UserDict, UserList, UserString +except ImportError: # Python < 3 + from UserDict import UserDict + from UserList import UserList + from UserString import UserString # Don't "from types import ..." these because we need to get at the # types module later to look for UnicodeType. +try: + InstanceType = types.InstanceType +except AttributeError: # Python 3 + InstanceType = None MethodType = types.MethodType FunctionType = types.FunctionType -try: str +try: unicode except NameError: UnicodeType = None else: UnicodeType = str @@ -111,9 +120,12 @@ class NodeList(UserList): >>> someList.strip() [ 'foo', 'bar' ] """ - def __bool__(self): + def __nonzero__(self): return len(self.data) != 0 + def __bool__(self): + return self.__nonzero__() + def __str__(self): return ' '.join(map(str, self.data)) @@ -153,7 +165,7 @@ class DisplayEngine(object): return if append_newline: text = text + '\n' try: - sys.stdout.write(str(text)) + sys.stdout.write(u(text)) except IOError: # Stdout might be connected to a pipe that has been closed # by now. The most likely reason for the pipe being closed @@ -239,7 +251,7 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited={}): ' N = no clean\n' + ' H = no cache\n' + '\n') - sys.stdout.write(str(legend)) + sys.stdout.write(u(legend)) tags = ['['] tags.append(' E'[IDX(root.exists())]) @@ -264,10 +276,10 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited={}): children = child_func(root) if prune and rname in visited and children: - sys.stdout.write(''.join(tags + margins + ['+-[', rname, ']']) + '\n') + sys.stdout.write(''.join(tags + margins + ['+-[', rname, ']']) + u'\n') return - sys.stdout.write(''.join(tags + margins + ['+-', rname]) + '\n') + sys.stdout.write(''.join(tags + margins + ['+-', rname]) + u'\n') visited[rname] = 1 @@ -303,11 +315,17 @@ SequenceTypes = (list, tuple, UserList) # Note that profiling data shows a speed-up when comparing # explicitely with str and unicode instead of simply comparing # with basestring. (at least on Python 2.5.1) -StringTypes = (str, str, UserString) +try: + StringTypes = (str, unicode, UserString) +except NameError: + StringTypes = (str, UserString) # Empirically, it is faster to check explicitely for str and # unicode than for basestring. -BaseStringTypes = (str, str) +try: + BaseStringTypes = (str, unicode) +except NameError: + BaseStringTypes = (str) def is_Dict(obj, isinstance=isinstance, DictTypes=DictTypes): return isinstance(obj, DictTypes) @@ -440,7 +458,7 @@ _semi_deepcopy_dispatch = d = {} def semi_deepcopy_dict(x, exclude = [] ): copy = {} - for key, val in list(x.items()): + for key, val in x.items(): # The regular Python copy.deepcopy() also deepcopies the key, # as follows: # @@ -465,7 +483,7 @@ def semi_deepcopy(x): if copier: return copier(x) else: - if hasattr(x, '__semi_deepcopy__') and isinstance(x.__semi_deepcopy__, collections.Callable): + if hasattr(x, '__semi_deepcopy__') and callable(x.__semi_deepcopy__): return x.__semi_deepcopy__() elif isinstance(x, UserDict): return x.__class__(semi_deepcopy_dict(x)) @@ -979,7 +997,7 @@ class OrderedDict(UserDict): if key not in self._keys: self._keys.append(key) def update(self, dict): - for (key, val) in list(dict.items()): + for (key, val) in dict.items(): self.__setitem__(key, val) def values(self): @@ -1001,7 +1019,7 @@ class Selector(OrderedDict): # Try to perform Environment substitution on the keys of # the dictionary before giving up. s_dict = {} - for (k,v) in list(self.items()): + for (k,v) in self.items(): if k is not None: s_k = env.subst(k) if s_k in s_dict: @@ -1346,8 +1364,9 @@ def make_path_relative(path): def AddMethod(obj, function, name=None): """ - Adds either a bound method to an instance or an unbound method to - a class. If name is ommited the name of the specified function + Adds either a bound method to an instance or the function itself + (or an unbound method in Python 2) to a class. + If name is ommited the name of the specified function is used by default. Example: a = A() @@ -1366,9 +1385,15 @@ def AddMethod(obj, function, name=None): if hasattr(obj, '__class__') and obj.__class__ is not type: # "obj" is an instance, so it gets a bound method. - setattr(obj, name, MethodType(function, obj, obj.__class__)) + if PY3: + method = MethodType(function, obj) + else: + method = MethodType(function, obj, obj.__class__) + setattr(obj, name, method) else: # "obj" is a class, so it gets an unbound method. + if PY2: + function = MethodType(function, None, obj) setattr(obj, name, function) def RenameFunction(function, name): @@ -1461,6 +1486,8 @@ class Null(object): return self def __repr__(self): return "Null(0x%08X)" % id(self) + def __nonzero__(self): + return False def __bool__(self): return False def __getattr__(self, name): diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py index a30404c..5666f36 100644 --- a/src/engine/SCons/UtilTests.py +++ b/src/engine/SCons/UtilTests.py @@ -20,6 +20,7 @@ # 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 six import u __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -285,16 +286,16 @@ class UtilTestCase(unittest.TestCase): assert to_String(s2) == 'foo', s2 if HasUnicode: - s3=UserString(str('bar')) + s3=UserString(unicode('bar')) assert to_String(s3) == s3, s3 - assert to_String(s3) == str('bar'), s3 - assert isinstance(to_String(s3), str), \ + assert to_String(s3) == unicode('bar'), s3 + assert isinstance(to_String(s3), unicode), \ type(to_String(s3)) if HasUnicode: - s4 = str('baz') - assert to_String(s4) == str('baz'), to_String(s4) - assert isinstance(to_String(s4), str), \ + s4 = unicode('baz') + assert to_String(s4) == unicode('baz'), to_String(s4) + assert isinstance(to_String(s4), unicode), \ type(to_String(s4)) def test_WhereIs(self): @@ -681,7 +682,7 @@ bling fobj = io.StringIO(content) except TypeError: # Python 2.7 and beyond require unicode strings. - fobj = io.StringIO(str(content)) + fobj = io.StringIO(u(content)) lines = LogicalLines(fobj).readlines() assert lines == [ @@ -696,7 +697,7 @@ bling s1 = silent_intern("spam") # Python 3.x does not have a unicode() global function if sys.version[0] == '2': - s2 = silent_intern(str("unicode spam")) + s2 = silent_intern(unicode("unicode spam")) s3 = silent_intern(42) s4 = silent_intern("spam") assert id(s1) == id(s4) diff --git a/src/engine/SCons/Variables/EnumVariableTests.py b/src/engine/SCons/Variables/EnumVariableTests.py index 4feb712..f4b600d 100644 --- a/src/engine/SCons/Variables/EnumVariableTests.py +++ b/src/engine/SCons/Variables/EnumVariableTests.py @@ -122,7 +122,7 @@ class EnumVariableTestCase(unittest.TestCase): 'C' : ['C', 'three', 'three'], } - for k, l in list(table.items()): + for k, l in table.items(): x = o0.converter(k) assert x == l[0], "o0 got %s, expected %s" % (x, l[0]) x = o1.converter(k) @@ -186,7 +186,7 @@ class EnumVariableTestCase(unittest.TestCase): 'no_v' : [invalid, invalid, invalid], } - for v, l in list(table.items()): + for v, l in table.items(): l[0](o0, v) l[1](o1, v) l[2](o2, v) diff --git a/src/engine/SCons/Variables/__init__.py b/src/engine/SCons/Variables/__init__.py index 8d15b8d..1c8d834 100644 --- a/src/engine/SCons/Variables/__init__.py +++ b/src/engine/SCons/Variables/__init__.py @@ -180,7 +180,7 @@ class Variables(object): if args is None: args = self.args - for arg, value in list(args.items()): + for arg, value in args.items(): added = False for option in self.options: if arg in list(option.aliases) + [ option.key ]: diff --git a/src/engine/SCons/compat/_scons_subprocess.py b/src/engine/SCons/compat/_scons_subprocess.py index 72581f7..e4ac777 100644 --- a/src/engine/SCons/compat/_scons_subprocess.py +++ b/src/engine/SCons/compat/_scons_subprocess.py @@ -351,6 +351,8 @@ except that: """ +from __future__ import print_function +from six import integer_types import sys mswindows = (sys.platform == "win32") @@ -444,15 +446,15 @@ else: def is_int(obj): return isinstance(obj, int) def is_int_or_long(obj): - return isinstance(obj, int) + return isinstance(obj, integer_types) try: - str + types.StringTypes except AttributeError: try: - str = (str, str) + types.StringTypes = (str, unicode) except NameError: - str = (str,) + types.StringTypes = (str,) def is_string(obj): return isinstance(obj, str) @@ -785,7 +787,7 @@ class Popen(object): errread, errwrite): """Execute program (MS Windows version)""" - if not isinstance(args, str): + if not isinstance(args, types.StringTypes): args = list2cmdline(args) # Process startup details diff --git a/src/engine/SCons/cpp.py b/src/engine/SCons/cpp.py index 4cc771b..0ba10f5 100644 --- a/src/engine/SCons/cpp.py +++ b/src/engine/SCons/cpp.py @@ -31,7 +31,6 @@ import SCons.compat import os import re -import collections # # First "subsystem" of regular expressions that we set up: @@ -73,7 +72,7 @@ cpp_lines_dict = { # the corresponding compiled regular expression that fetches the arguments # we care about. Table = {} -for op_list, expr in list(cpp_lines_dict.items()): +for op_list, expr in cpp_lines_dict.items(): e = re.compile(expr) for op in op_list: Table[op] = e @@ -88,7 +87,7 @@ del op_list override = { 'if' : 'if(?!def)', } -l = [override.get(x, x) for x in list(Table.keys())] +l = [override.get(x, x) for x in Table.keys()] # Turn the list of expressions into one big honkin' regular expression @@ -131,7 +130,7 @@ CPP_to_Python_Ops_Sub = lambda m: CPP_to_Python_Ops_Dict[m.group(0)] # re module, as late as version 2.2.2, empirically matches the # "!" in "!=" first, instead of finding the longest match. # What's up with that? -l = sorted(list(CPP_to_Python_Ops_Dict.keys()), key=lambda a: len(a), reverse=True) +l = sorted(CPP_to_Python_Ops_Dict.keys(), key=lambda a: len(a), reverse=True) # Turn the list of keys into one regular expression that will allow us # to substitute all of the operators at once. @@ -267,7 +266,7 @@ class PreProcessor(object): d = { 'scons_current_file' : self.scons_current_file } - for op in list(Table.keys()): + for op in Table.keys(): d[op] = getattr(self, 'do_' + op) self.default_table = d @@ -553,7 +552,7 @@ class PreProcessor(object): except KeyError: m = function_name.search(s) s = self.cpp_namespace[m.group(1)] - if isinstance(s, collections.Callable): + if callable(s): args = function_arg_separator.split(m.group(2)) s = s(*args) if not s: diff --git a/src/engine/SCons/cppTests.py b/src/engine/SCons/cppTests.py index 5566e53..2f2025b 100644 --- a/src/engine/SCons/cppTests.py +++ b/src/engine/SCons/cppTests.py @@ -27,7 +27,7 @@ import atexit import sys import unittest -from . import cpp +import cpp diff --git a/src/engine/SCons/dblite.py b/src/engine/SCons/dblite.py index 4b02239..dbbd65d 100644 --- a/src/engine/SCons/dblite.py +++ b/src/engine/SCons/dblite.py @@ -1,5 +1,6 @@ # dblite.py module contributed by Ralf W. Grosse-Kunstleve. # Extended for Unicode by Steven Knight. +from __future__ import print_function import SCons.compat @@ -16,14 +17,19 @@ ignore_corrupt_dbfiles = 0 def corruption_warning(filename): print("Warning: Discarding corrupt database:", filename) -def is_string(s): - return isinstance(s, str) +try: unicode +except NameError: + def is_string(s): + return isinstance(s, str) +else: + def is_string(s): + return type(s) in (str, unicode) def is_bytes(s): return isinstance (s, bytes) try: - str('a') + unicode('a') except NameError: - def str(s): return s + def unicode(s): return s dblite_suffix = '.dblite' if bytes is not str: @@ -177,23 +183,23 @@ def _exercise(): assert len(db) == 0 db["foo"] = "bar" assert db["foo"] == "bar" - db[str("ufoo")] = str("ubar") - assert db[str("ufoo")] == str("ubar") + db[unicode("ufoo")] = unicode("ubar") + assert db[unicode("ufoo")] == unicode("ubar") db.sync() db = open("tmp", "c") assert len(db) == 2, len(db) assert db["foo"] == "bar" db["bar"] = "foo" assert db["bar"] == "foo" - db[str("ubar")] = str("ufoo") - assert db[str("ubar")] == str("ufoo") + db[unicode("ubar")] = unicode("ufoo") + assert db[unicode("ubar")] == unicode("ufoo") db.sync() db = open("tmp", "r") assert len(db) == 4, len(db) assert db["foo"] == "bar" assert db["bar"] == "foo" - assert db[str("ufoo")] == str("ubar") - assert db[str("ubar")] == str("ufoo") + assert db[unicode("ufoo")] == unicode("ubar") + assert db[unicode("ubar")] == unicode("ufoo") try: db.sync() except IOError as e: diff --git a/src/script/scons-time.py b/src/script/scons-time.py index 4296192..9737dfe 100644 --- a/src/script/scons-time.py +++ b/src/script/scons-time.py @@ -29,8 +29,7 @@ # 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, print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -42,7 +41,6 @@ import shutil import sys import tempfile import time -import collections try: sorted @@ -456,7 +454,7 @@ class SConsTimer(object): Each message is prepended with a standard prefix of our name plus the time. """ - if isinstance(msg, collections.Callable): + if callable(msg): msg = msg(*args) else: msg = msg % args @@ -475,7 +473,7 @@ class SConsTimer(object): The action is called if it's a callable Python function, and otherwise passed to os.system(). """ - if isinstance(action, collections.Callable): + if callable(action): action(*args) else: os.system(action % args) @@ -697,7 +695,7 @@ class SConsTimer(object): 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 list(statistics.items()) if e[0][2] == function ] + matches = [ e for e in statistics.items() if e[0][2] == function ] r = matches[0] return r[0][0], r[0][1], r[0][2], r[1][3] @@ -1467,7 +1465,7 @@ class SConsTimer(object): elif o in ('--title',): self.title = a elif o in ('--which',): - if not a in list(self.time_strings.keys()): + if not a in 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) diff --git a/src/script/sconsign.py b/src/script/sconsign.py index 323d1bf..e99a741 100644 --- a/src/script/sconsign.py +++ b/src/script/sconsign.py @@ -22,6 +22,9 @@ # 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 print_function + +from six import PY2, PY3 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -171,6 +174,8 @@ sys.path = libs + sys.path import SCons.compat # so pickle will import cPickle instead +if PY2: + import whichdb import dbm import time import pickle @@ -189,7 +194,10 @@ def my_whichdb(filename): pass return _orig_whichdb(filename) -_orig_whichdb = dbm.whichdb +if PY3: + _orig_whichdb = dbm.whichdb +else: + _orig_whichdb = whichdb.whichdb dbm.whichdb = my_whichdb def my_import(mname): diff --git a/src/test_files.py b/src/test_files.py index d71329b..1eee11d 100644 --- a/src/test_files.py +++ b/src/test_files.py @@ -21,6 +21,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -77,7 +78,7 @@ check = { missing = [] no_result = [] -for directory, check_list in list(check.items()): +for directory, check_list in check.items(): if os.path.exists(directory): for c in check_list: f = os.path.join(directory, c) diff --git a/src/test_interrupts.py b/src/test_interrupts.py index 1e027a1..de3a0db 100644 --- a/src/test_interrupts.py +++ b/src/test_interrupts.py @@ -102,7 +102,7 @@ for f in files: indent_list.append( (line_num, match.group('try_or_except') ) ) try_except_lines[match.group('indent')] = indent_list uncaught_this_file = [] - for indent in list(try_except_lines.keys()): + for indent in try_except_lines.keys(): exc_keyboardint_seen = 0 exc_all_seen = 0 for (l,statement) in try_except_lines[indent] + [(-1,indent + 'try')]: diff --git a/src/test_pychecker.py b/src/test_pychecker.py index 24aa966..54d78fb 100644 --- a/src/test_pychecker.py +++ b/src/test_pychecker.py @@ -20,6 +20,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/src/test_setup.py b/src/test_setup.py index 731fbe7..edf0de5 100644 --- a/src/test_setup.py +++ b/src/test_setup.py @@ -21,6 +21,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/src/test_strings.py b/src/test_strings.py index b57c714..297d59d 100644 --- a/src/test_strings.py +++ b/src/test_strings.py @@ -21,6 +21,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/AS/nasm.py b/test/AS/nasm.py index 551a5ab..be7db3e 100644 --- a/test/AS/nasm.py +++ b/test/AS/nasm.py @@ -69,7 +69,7 @@ else: # anyway...). nasm_format = 'elf' format_map = {} -for k, v in list(format_map.items()): +for k, v in format_map.items(): if sys.platform.find(k) != -1: nasm_format = v break diff --git a/test/Actions/unicode-signature.py b/test/Actions/unicode-signature.py index 0ba50c3..d91bfa8 100644 --- a/test/Actions/unicode-signature.py +++ b/test/Actions/unicode-signature.py @@ -35,12 +35,12 @@ import TestSCons test = TestSCons.TestSCons() -try: - str -except NameError: - import sys - msg = "Unicode not supported by Python version %s; skipping test\n" - test.skip_test(msg % sys.version[:3]) +## try: +## unicode +## except NameError: +## import sys +## msg = "Unicode not supported by Python version %s; skipping test\n" +## test.skip_test(msg % sys.version[:3]) test.write('SConstruct', """ fnode = File(u'foo.txt') diff --git a/test/AddOption/help.py b/test/AddOption/help.py index a3fd7be..7b886cb 100644 --- a/test/AddOption/help.py +++ b/test/AddOption/help.py @@ -20,6 +20,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/Configure/ConfigureDryRunError.py b/test/Configure/ConfigureDryRunError.py index a8c6309..fa85042 100644 --- a/test/Configure/ConfigureDryRunError.py +++ b/test/Configure/ConfigureDryRunError.py @@ -21,6 +21,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/Configure/config-h.py b/test/Configure/config-h.py index 6c70c9c..ed95055 100644 --- a/test/Configure/config-h.py +++ b/test/Configure/config-h.py @@ -21,6 +21,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/Configure/implicit-cache.py b/test/Configure/implicit-cache.py index 059fd4c..1a9ff34 100644 --- a/test/Configure/implicit-cache.py +++ b/test/Configure/implicit-cache.py @@ -21,6 +21,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/Deprecated/SourceCode/BitKeeper/BitKeeper.py b/test/Deprecated/SourceCode/BitKeeper/BitKeeper.py index 9a36eac..2959736 100644 --- a/test/Deprecated/SourceCode/BitKeeper/BitKeeper.py +++ b/test/Deprecated/SourceCode/BitKeeper/BitKeeper.py @@ -20,6 +20,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/Deprecated/SourceCode/Subversion.py b/test/Deprecated/SourceCode/Subversion.py index ac3eb57..7d45a8c 100644 --- a/test/Deprecated/SourceCode/Subversion.py +++ b/test/Deprecated/SourceCode/Subversion.py @@ -21,6 +21,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/GetBuildFailures/parallel.py b/test/GetBuildFailures/parallel.py index 101c2e2..e746d53 100644 --- a/test/GetBuildFailures/parallel.py +++ b/test/GetBuildFailures/parallel.py @@ -21,6 +21,7 @@ # 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 print_function """ Verify that a failed build action with -j works as expected. diff --git a/test/Glob/glob-libpath.py b/test/Glob/glob-libpath.py index 6ee06e6..0878090 100644 --- a/test/Glob/glob-libpath.py +++ b/test/Glob/glob-libpath.py @@ -21,6 +21,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/Interactive/version.py b/test/Interactive/version.py index 295b9d3..34f8825 100644 --- a/test/Interactive/version.py +++ b/test/Interactive/version.py @@ -21,6 +21,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ diff --git a/test/Java/multi-step.py b/test/Java/multi-step.py index add4208..44ebd31 100644 --- a/test/Java/multi-step.py +++ b/test/Java/multi-step.py @@ -21,6 +21,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/MSVC/msvc.py b/test/MSVC/msvc.py index 6f5c8d6..a70ed67 100644 --- a/test/MSVC/msvc.py +++ b/test/MSVC/msvc.py @@ -21,6 +21,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/QT/QTFLAGS.py b/test/QT/QTFLAGS.py index b7172fc..008397a 100644 --- a/test/QT/QTFLAGS.py +++ b/test/QT/QTFLAGS.py @@ -147,7 +147,7 @@ test.must_exist(['work1', 'mmmmocFromH.cxx'], ['work1', 'mmmanother_ui_file.cxx']) def _flagTest(test,fileToContentsStart): - for f,c in list(fileToContentsStart.items()): + for f,c in fileToContentsStart.items(): if test.read(test.workpath('work1', f)).find(c) != 0: return 1 return 0 diff --git a/test/QT/copied-env.py b/test/QT/copied-env.py index 59a344d..3989143 100644 --- a/test/QT/copied-env.py +++ b/test/QT/copied-env.py @@ -20,6 +20,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/QT/warnings.py b/test/QT/warnings.py index 5e680f6..a1cf221 100644 --- a/test/QT/warnings.py +++ b/test/QT/warnings.py @@ -21,6 +21,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/Scanner/unicode.py b/test/Scanner/unicode.py index 7a72804..2737f7d 100644 --- a/test/Scanner/unicode.py +++ b/test/Scanner/unicode.py @@ -35,12 +35,12 @@ _python_ = TestSCons._python_ test = TestSCons.TestSCons() -try: - str -except NameError: - import sys - msg = "Unicode not supported by Python version %s; skipping test\n" - test.skip_test(msg % sys.version[:3]) +## try: +## unicode +## except NameError: +## import sys +## msg = "Unicode not supported by Python version %s; skipping test\n" +## test.skip_test(msg % sys.version[:3]) import codecs @@ -102,28 +102,28 @@ include utf16be.k foo.k 1 line 4 """) -contents = str("""\ +contents = (u"""\ ascii.k 1 line 1 include ascii.inc ascii.k 1 line 3 """) test.write('ascii.k', contents.encode('ascii')) -contents = str("""\ +contents = (u"""\ utf8.k 1 line 1 include utf8.inc utf8.k 1 line 3 """) test.write('utf8.k', codecs.BOM_UTF8 + contents.encode('utf-8')) -contents = str("""\ +contents = (u"""\ utf16le.k 1 line 1 include utf16le.inc utf16le.k 1 line 3 """) test.write('utf16le.k', codecs.BOM_UTF16_LE + contents.encode('utf-16-le')) -contents = str("""\ +contents = (u"""\ utf16be.k 1 line 1 include utf16be.inc utf16be.k 1 line 3 diff --git a/test/TEX/TEX.py b/test/TEX/TEX.py index 863144d..b749690 100644 --- a/test/TEX/TEX.py +++ b/test/TEX/TEX.py @@ -20,6 +20,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/Value.py b/test/Value.py index 025c6de..7abe758 100644 --- a/test/Value.py +++ b/test/Value.py @@ -21,6 +21,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/Win32/bad-drive.py b/test/Win32/bad-drive.py index ff98b4e..4d0d6e9 100644 --- a/test/Win32/bad-drive.py +++ b/test/Win32/bad-drive.py @@ -21,6 +21,7 @@ # 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 print_function """ This test verifies (on Windows systems) that we fail gracefully and diff --git a/test/Win32/default-drive.py b/test/Win32/default-drive.py index 2bc14b1..31253e4 100644 --- a/test/Win32/default-drive.py +++ b/test/Win32/default-drive.py @@ -21,6 +21,7 @@ # 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 print_function """ This test verifies (on Windows systems) that specifying an diff --git a/test/gnutools.py b/test/gnutools.py index f79efe4..b0ebc1c 100644 --- a/test/gnutools.py +++ b/test/gnutools.py @@ -21,6 +21,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/import.py b/test/import.py index fb8a28c..d1e1ecf 100644 --- a/test/import.py +++ b/test/import.py @@ -21,6 +21,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/option--random.py b/test/option--random.py index 59592cb..357cf2e 100644 --- a/test/option--random.py +++ b/test/option--random.py @@ -21,6 +21,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/option-v.py b/test/option-v.py index 8985db0..43245da 100644 --- a/test/option-v.py +++ b/test/option-v.py @@ -21,6 +21,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/option/debug-count.py b/test/option/debug-count.py index 076d7fa..ce79086 100644 --- a/test/option/debug-count.py +++ b/test/option/debug-count.py @@ -20,6 +20,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/option/debug-time.py b/test/option/debug-time.py index 7448e1c..7dd17fe 100644 --- a/test/option/debug-time.py +++ b/test/option/debug-time.py @@ -20,7 +20,7 @@ # 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, print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/option/help-options.py b/test/option/help-options.py index 1b23cb3..e14eff2 100644 --- a/test/option/help-options.py +++ b/test/option/help-options.py @@ -20,6 +20,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/option/profile.py b/test/option/profile.py index 513da47..97f84db 100644 --- a/test/option/profile.py +++ b/test/option/profile.py @@ -21,6 +21,8 @@ # 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 six import u + __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import sys @@ -36,7 +38,7 @@ else: # when we drop support for Python 2.6. class StringIO(_StringIO): def write(self, s): - _StringIO.write(self, str(s)) + _StringIO.write(self, u(s)) import TestSCons diff --git a/test/site_scons/sysdirs.py b/test/site_scons/sysdirs.py index d05f6a4..87f448d 100644 --- a/test/site_scons/sysdirs.py +++ b/test/site_scons/sysdirs.py @@ -21,6 +21,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/update-release-info/update-release-info.py b/test/update-release-info/update-release-info.py index 0db65ba..d3125c7 100644 --- a/test/update-release-info/update-release-info.py +++ b/test/update-release-info/update-release-info.py @@ -201,7 +201,7 @@ RELEASE 2.0.0.alpha.yyyymmdd - NEW DATE WILL BE INSERTED HERE """, mode = 'r') -years = ', '.join(map(str, list(range(2001, this_year + 1)))) +years = ', '.join(map(str, range(2001, this_year + 1))) test.must_match(SConstruct, """ month_year = 'MONTH YEAR' copyright_years = %s diff --git a/timings/ElectricCloud/TimeSCons-run.py b/timings/ElectricCloud/TimeSCons-run.py index fbe0028..130d916 100644 --- a/timings/ElectricCloud/TimeSCons-run.py +++ b/timings/ElectricCloud/TimeSCons-run.py @@ -20,6 +20,7 @@ # 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 print_function """ This configuration comes from the following blog article: diff --git a/www/gen_sched_table.py b/www/gen_sched_table.py index 9ac8acd..85b1b81 100755 --- a/www/gen_sched_table.py +++ b/www/gen_sched_table.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +from __future__ import print_function import sys import datetime -- cgit v0.12 From cbd2254037664fdfe6ba1bf6678896fbd51698a9 Mon Sep 17 00:00:00 2001 From: Stefan Zimmermann Date: Fri, 27 Dec 2013 09:39:26 +0000 Subject: QMTest: open() in text mode. Add ()s to prints on writing test scripts from str. --- QMTest/SConscript | 4 ++-- QMTest/TestCmd.py | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/QMTest/SConscript b/QMTest/SConscript index 33fe903..5469d29 100644 --- a/QMTest/SConscript +++ b/QMTest/SConscript @@ -44,12 +44,12 @@ files = [ def copy(target, source, env): t = str(target[0]) s = str(source[0]) - c = open(s, 'rb').read() + c = open(s, 'r').read() # Note: We construct the __ VERSION __ substitution string at # run-time so it doesn't get replaced when this file gets copied # into the tree for packaging. c = c.replace('__' + 'VERSION' + '__', env['VERSION']) - open(t, 'wb').write(c) + open(t, 'w').write(c) for file in files: # Guarantee that real copies of these files always exist in diff --git a/QMTest/TestCmd.py b/QMTest/TestCmd.py index 488d940..c075cd3 100644 --- a/QMTest/TestCmd.py +++ b/QMTest/TestCmd.py @@ -287,6 +287,8 @@ version. # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. from __future__ import division, print_function +from six import PY3 + __author__ = "Steven Knight " __revision__ = "TestCmd.py 1.3.D001 2010/06/03 12:58:27 knight" __version__ = "1.3" @@ -1705,7 +1707,7 @@ class TestCmd(object): do_chmod(os.path.join(dirpath, name)) do_chmod(top) - def write(self, file, content, mode = 'wb'): + def write(self, file, content, mode = 'w'): """Writes the specified content text (second argument) to the specified file name (first argument). The file name may be a list, in which case the elements are concatenated with the @@ -1714,6 +1716,8 @@ class TestCmd(object): exist. The I/O mode for the file may be specified; it must begin with a 'w'. The default is 'wb' (binary write). """ + if PY3: + content = re.sub('print (.+)', 'print(\1)', content) file = self.canonicalize(file) if mode[0] != 'w': raise ValueError("mode must begin with 'w'") -- cgit v0.12 From 724d115835ddfe49096b9ad695a3b75cb612745a Mon Sep 17 00:00:00 2001 From: Stefan Zimmermann Date: Fri, 27 Dec 2013 09:40:41 +0000 Subject: SConstruct: open() in text mode. Fixed octal literals. --- SConstruct | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/SConstruct b/SConstruct index 1a0aef0..09eb739 100644 --- a/SConstruct +++ b/SConstruct @@ -70,7 +70,7 @@ def whereis(file): st = os.stat(f_ext) except: continue - if stat.S_IMODE(st[stat.ST_MODE]) & 0111: + if stat.S_IMODE(st[stat.ST_MODE]) & 0o111: return f_ext return None @@ -372,7 +372,7 @@ def SCons_revision(target, source, env): """ t = str(target[0]) s = source[0].rstr() - contents = open(s, 'rb').read() + contents = open(s, 'r').read() # Note: We construct the __*__ substitution strings here # so that they don't get replaced when this file gets # copied into the tree for packaging. @@ -386,7 +386,7 @@ def SCons_revision(target, source, env): contents = contents.replace('__REVISION' + '__', env['REVISION']) contents = contents.replace('__VERSION' + '__', env['VERSION']) contents = contents.replace('__NULL' + '__', '') - open(t, 'wb').write(contents) + open(t, 'w').write(contents) os.chmod(t, os.stat(s)[0]) revaction = SCons_revision @@ -851,7 +851,7 @@ for p in [ scons ]: dist_distutils_targets = env.Install('$DISTDIR', distutils_targets) Local(dist_distutils_targets) - AddPostAction(dist_distutils_targets, Chmod(dist_distutils_targets, 0644)) + AddPostAction(dist_distutils_targets, Chmod(dist_distutils_targets, 0o644)) if not gzip: print("gzip not found in %s; skipping .tar.gz package for %s." % (os.environ['PATH'], pkg)) @@ -866,8 +866,8 @@ for p in [ scons ]: dist_tar_gz = env.Install('$DISTDIR', tar_gz) dist_platform_tar_gz = env.Install('$DISTDIR', platform_tar_gz) Local(dist_tar_gz, dist_platform_tar_gz) - AddPostAction(dist_tar_gz, Chmod(dist_tar_gz, 0644)) - AddPostAction(dist_platform_tar_gz, Chmod(dist_platform_tar_gz, 0644)) + AddPostAction(dist_tar_gz, Chmod(dist_tar_gz, 0o644)) + AddPostAction(dist_platform_tar_gz, Chmod(dist_platform_tar_gz, 0o644)) # # Unpack the tar.gz archive created by the distutils into @@ -941,8 +941,8 @@ for p in [ scons ]: dist_zip = env.Install('$DISTDIR', zip) dist_platform_zip = env.Install('$DISTDIR', platform_zip) Local(dist_zip, dist_platform_zip) - AddPostAction(dist_zip, Chmod(dist_zip, 0644)) - AddPostAction(dist_platform_zip, Chmod(dist_platform_zip, 0644)) + AddPostAction(dist_zip, Chmod(dist_zip, 0o644)) + AddPostAction(dist_platform_zip, Chmod(dist_platform_zip, 0o644)) # # Unpack the zip archive created by the distutils into @@ -1029,8 +1029,8 @@ for p in [ scons ]: dist_noarch_rpm = env.Install('$DISTDIR', noarch_rpm) dist_src_rpm = env.Install('$DISTDIR', src_rpm) Local(dist_noarch_rpm, dist_src_rpm) - AddPostAction(dist_noarch_rpm, Chmod(dist_noarch_rpm, 0644)) - AddPostAction(dist_src_rpm, Chmod(dist_src_rpm, 0644)) + AddPostAction(dist_noarch_rpm, Chmod(dist_noarch_rpm, 0o644)) + AddPostAction(dist_src_rpm, Chmod(dist_src_rpm, 0o644)) dfiles = [os.path.join(test_rpm_dir, 'usr', x) for x in dst_files] env.Command(dfiles, @@ -1097,8 +1097,8 @@ for p in [ scons ]: dist_local_tar_gz = os.path.join("$DISTDIR/%s.tar.gz" % s_l_v) dist_local_zip = os.path.join("$DISTDIR/%s.zip" % s_l_v) - AddPostAction(dist_local_tar_gz, Chmod(dist_local_tar_gz, 0644)) - AddPostAction(dist_local_zip, Chmod(dist_local_zip, 0644)) + AddPostAction(dist_local_tar_gz, Chmod(dist_local_tar_gz, 0o644)) + AddPostAction(dist_local_zip, Chmod(dist_local_zip, 0o644)) commands = [ Delete(build_dir_local), -- cgit v0.12 From b5d204ffae80f78083c34b0ba4c105791d57c084 Mon Sep 17 00:00:00 2001 From: Stefan Zimmermann Date: Fri, 27 Dec 2013 09:43:46 +0000 Subject: copy_func: return 0 instead of return shutil.* --- src/engine/SCons/Defaults.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/engine/SCons/Defaults.py b/src/engine/SCons/Defaults.py index 491b9f2..92f2344 100644 --- a/src/engine/SCons/Defaults.py +++ b/src/engine/SCons/Defaults.py @@ -183,11 +183,11 @@ def copy_func(dest, src): if SCons.Util.is_List(src) and os.path.isdir(dest): for file in src: shutil.copy2(file, dest) - return 0 elif os.path.isfile(src): - return shutil.copy2(src, dest) + shutil.copy2(src, dest) else: - return shutil.copytree(src, dest, 1) + shutil.copytree(src, dest, 1) + return 0 Copy = ActionFactory(copy_func, lambda dest, src: 'Copy("%s", "%s")' % (dest, src), -- cgit v0.12 From 808610957042c630d19c7f7b0fd9b87b81f9de2e Mon Sep 17 00:00:00 2001 From: Stefan Zimmermann Date: Fri, 27 Dec 2013 09:51:19 +0000 Subject: Environment.py: __cmp__ to __eq__. list(*.keys()) for item deletion loops. --- src/engine/SCons/Environment.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index b5bd620..7a369a9 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -127,7 +127,7 @@ future_reserved_construction_var_names = [ def copy_non_reserved_keywords(dict): result = semi_deepcopy(dict) - for k in result.keys(): + for k in list(result.keys()): if k in reserved_construction_var_names: msg = "Ignoring attempt to set reserved variable `$%s'" SCons.Warnings.warn(SCons.Warnings.ReservedVariableWarning, msg % k) @@ -398,8 +398,8 @@ class SubstitutionEnvironment(object): # gotten better than dict.has_key() in Python 2.5.) self._special_set_keys = list(self._special_set.keys()) - def __cmp__(self, other): - return cmp(self._dict, other._dict) + def __eq__(self, other): + return self._dict == other._dict def __delitem__(self, key): special = self._special_del.get(key) @@ -1768,7 +1768,7 @@ class Base(SubstitutionEnvironment): return os.path.join(dir, new_prefix+name+new_suffix) def SetDefault(self, **kw): - for k in kw.keys(): + for k in list(kw.keys()): if k in self._dict: del kw[k] self.Replace(**kw) -- cgit v0.12 From d1c2f4dbdbf5ca3f5c1f8bf6da45c09d82046683 Mon Sep 17 00:00:00 2001 From: Stefan Zimmermann Date: Fri, 27 Dec 2013 13:05:24 +0000 Subject: doc/SConscript: Fixed octal literal. --- doc/SConscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/SConscript b/doc/SConscript index c6b8f74..a1feba9 100644 --- a/doc/SConscript +++ b/doc/SConscript @@ -414,7 +414,7 @@ if tar_deps: tar_list = ' '.join([x.replace(build+'/', '') for x in tar_list]) t = env.Command(dist_doc_tar_gz, tar_deps, "tar cf${TAR_HFLAG} - -C %s %s | gzip > $TARGET" % (build, tar_list)) - AddPostAction(dist_doc_tar_gz, Chmod(dist_doc_tar_gz, 0644)) + AddPostAction(dist_doc_tar_gz, Chmod(dist_doc_tar_gz, 0o644)) Local(t) Alias('doc', t) else: -- cgit v0.12 From fd24c4ea622e271936c2df2a5efa484cd351bd9c Mon Sep 17 00:00:00 2001 From: Stefan Zimmermann Date: Fri, 27 Dec 2013 13:07:07 +0000 Subject: Use exec() with compile() to preserve script name. --- src/engine/SCons/Script/SConscript.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py index b2dc4c1..3ee9464 100644 --- a/src/engine/SCons/Script/SConscript.py +++ b/src/engine/SCons/Script/SConscript.py @@ -26,7 +26,6 @@ files. # 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, print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -257,7 +256,8 @@ def _SConscript(fs, *files, **kw): pass try: try: - exec(_file_.read(), call_stack[-1].globals) + exec(compile(_file_.read(), _file_.name, 'exec'), + call_stack[-1].globals) except SConscriptReturn: pass finally: -- cgit v0.12 From 87b458d186fe0553b054b8eeb7d57c80e0a54f21 Mon Sep 17 00:00:00 2001 From: Stefan Zimmermann Date: Mon, 31 Mar 2014 15:21:40 +0000 Subject: More __cmp__ to __eq__ (and __lt__). Resolved some UnboundLocalErrors after except. --- bin/SConsDoc.py | 6 ++++-- bin/scons-proc.py | 11 ++++++++--- src/engine/SCons/Action.py | 4 ++-- src/engine/SCons/Builder.py | 11 +++++++---- src/engine/SCons/BuilderTests.py | 22 ++++++++++++++-------- src/engine/SCons/EnvironmentTests.py | 8 ++++---- src/engine/SCons/Memoize.py | 6 +++--- src/engine/SCons/Scanner/ScannerTests.py | 2 +- src/engine/SCons/Scanner/__init__.py | 6 +++--- src/engine/SCons/Util.py | 6 +++--- test/Scanner/generated.py | 4 ++-- 11 files changed, 51 insertions(+), 35 deletions(-) diff --git a/bin/SConsDoc.py b/bin/SConsDoc.py index 80f41a5..72c0306 100644 --- a/bin/SConsDoc.py +++ b/bin/SConsDoc.py @@ -668,8 +668,10 @@ class Item(object): if name[0] == '_': name = name[1:] return name.lower() - def __cmp__(self, other): - return cmp(self.sort_name, other.sort_name) + def __eq__(self, other): + return self.sort_name == other.sort_name + def __lt__(self, other): + return self.sort_name < other.sort_name class Builder(Item): pass diff --git a/bin/scons-proc.py b/bin/scons-proc.py index b93b25a..138cff7 100644 --- a/bin/scons-proc.py +++ b/bin/scons-proc.py @@ -231,10 +231,15 @@ class Proxy(object): """Retrieve the entire wrapped object""" return self.__subject - def __cmp__(self, other): + def __eq__(self, other): if issubclass(other.__class__, self.__subject.__class__): - return cmp(self.__subject, other) - return cmp(self.__dict__, other.__dict__) + return self.__subject == other + return self.__dict__ == other.__dict__ + + ## def __lt__(self, other): + ## if issubclass(other.__class__, self.__subject.__class__): + ## return self.__subject < other + ## return self.__dict__ < other.__dict__ class SConsThing(Proxy): def idfunc(self): diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index 006e8f5..49b9f35 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -420,8 +420,8 @@ class ActionBase(object): other objects (Builders, Executors, etc.) This provides the common methods for manipulating and combining those actions.""" - def __cmp__(self, other): - return cmp(self.__dict__, other) + def __eq__(self, other): + return self.__dict__ == other def no_batch_key(self, env, target, source): return None diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py index 0f7aff4..4b41827 100644 --- a/src/engine/SCons/Builder.py +++ b/src/engine/SCons/Builder.py @@ -345,8 +345,11 @@ class EmitterProxy(object): return (target, source) - def __cmp__(self, other): - return cmp(self.var, other.var) + def __eq__(self, other): + return self.var == other.var + + def __lt__(self, other): + return self.var < other.var class BuilderBase(object): """Base class for Builders, objects that create output @@ -449,8 +452,8 @@ class BuilderBase(object): except AttributeError: return str(self.__class__) - def __cmp__(self, other): - return cmp(self.__dict__, other.__dict__) + def __eq__(self, other): + return self.__dict__ == other.__dict__ def splitext(self, path, env=None): if not env: diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py index 41b640b..eb56299 100644 --- a/src/engine/SCons/BuilderTests.py +++ b/src/engine/SCons/BuilderTests.py @@ -145,8 +145,8 @@ class Environment(object): d['SOURCES'] = ['__s1__', '__s2__', '__s3__', '__s4__', '__s5__', '__s6__'] d['SOURCE'] = d['SOURCES'][0] return d - def __cmp__(self, other): - return cmp(self.scanner, other.scanner) or cmp(self.d, other.d) + def __eq__(self, other): + return self.scanner == other.scanner or self.d == other.d class MyAction(object): def __init__(self, action): @@ -1500,9 +1500,10 @@ class CompositeBuilderTestCase(unittest.TestCase): builder(env, target='test3', source=['test2.bar', 'test1.foo'])[0] except SCons.Errors.UserError as e: flag = 1 + err = e assert flag, "UserError should be thrown when we call a builder with files of different suffixes." expect = "While building `['test3']' from `test1.foo': Cannot build multiple sources with different extensions: .bar, .foo" - assert str(e) == expect, e + assert str(err) == expect, err def test_source_ext_match(self): """Test the CompositeBuilder source_ext_match argument""" @@ -1584,45 +1585,50 @@ class CompositeBuilderTestCase(unittest.TestCase): builder(env, target='t5', source=['test5a.foo', 'test5b.inb'])[0] except SCons.Errors.UserError as e: flag = 1 + err = e assert flag, "UserError should be thrown when we call a builder with files of different suffixes." expect = "While building `['t5']' from `test5b.bar': Cannot build multiple sources with different extensions: .foo, .bar" - assert str(e) == expect, e + assert str(err) == expect, err flag = 0 try: builder(env, target='t6', source=['test6a.bar', 'test6b.ina'])[0] except SCons.Errors.UserError as e: flag = 1 + err = e assert flag, "UserError should be thrown when we call a builder with files of different suffixes." expect = "While building `['t6']' from `test6b.foo': Cannot build multiple sources with different extensions: .bar, .foo" - assert str(e) == expect, e + assert str(err) == expect, err flag = 0 try: builder(env, target='t4', source=['test4a.ina', 'test4b.inb'])[0] except SCons.Errors.UserError as e: flag = 1 + err = e assert flag, "UserError should be thrown when we call a builder with files of different suffixes." expect = "While building `['t4']' from `test4b.bar': Cannot build multiple sources with different extensions: .foo, .bar" - assert str(e) == expect, e + assert str(err) == expect, err flag = 0 try: builder(env, target='t7', source=[env.fs.File('test7')])[0] except SCons.Errors.UserError as e: flag = 1 + err = e assert flag, "UserError should be thrown when we call a builder with files of different suffixes." expect = "While building `['t7']': Cannot deduce file extension from source files: ['test7']" - assert str(e) == expect, e + assert str(err) == expect, err flag = 0 try: builder(env, target='t8', source=['test8.unknown'])[0] except SCons.Errors.UserError as e: flag = 1 + err = e assert flag, "UserError should be thrown when we call a builder target with an unknown suffix." expect = "While building `['t8']' from `['test8.unknown']': Don't know how to build from a source file with suffix `.unknown'. Expected a suffix in this list: ['.foo', '.bar']." - assert str(e) == expect, e + assert str(err) == expect, err if __name__ == "__main__": suite = unittest.TestSuite() diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index 22552b3..6933b6b 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -113,11 +113,11 @@ class Scanner(object): global scanned_it scanned_it[filename] = 1 - def __cmp__(self, other): + def __eq__(self, other): try: - return cmp(self.__dict__, other.__dict__) + return self.__dict__ == other.__dict__ except AttributeError: - return 1 + return False def get_skeys(self, env): return self.skeys @@ -1613,7 +1613,7 @@ def exists(env): self.name = name def __str__(self): return self.name - def __cmp__(self, other): + def __eq__(self, other): raise Exception("should not compare") ccc = C('ccc') diff --git a/src/engine/SCons/Memoize.py b/src/engine/SCons/Memoize.py index ac728c9..d2938c7 100644 --- a/src/engine/SCons/Memoize.py +++ b/src/engine/SCons/Memoize.py @@ -145,11 +145,11 @@ class Counter(object): def display(self): fmt = " %7d hits %7d misses %s()" print(fmt % (self.hit, self.miss, self.name)) - def __cmp__(self, other): + def __eq__(self, other): try: - return cmp(self.name, other.name) + return self.name == other.name except AttributeError: - return 0 + return True class CountValue(Counter): """ diff --git a/src/engine/SCons/Scanner/ScannerTests.py b/src/engine/SCons/Scanner/ScannerTests.py index ee26922..f29d545 100644 --- a/src/engine/SCons/Scanner/ScannerTests.py +++ b/src/engine/SCons/Scanner/ScannerTests.py @@ -234,7 +234,7 @@ class BaseTestCase(unittest.TestCase): def test___cmp__(self): """Test the Scanner.Base class __cmp__() method""" s = SCons.Scanner.Base(self.func, "Cmp") - assert cmp(s, None) + assert s != None def test_hash(self): """Test the Scanner.Base class __hash__() method""" diff --git a/src/engine/SCons/Scanner/__init__.py b/src/engine/SCons/Scanner/__init__.py index 2375bc4..5700fe9 100644 --- a/src/engine/SCons/Scanner/__init__.py +++ b/src/engine/SCons/Scanner/__init__.py @@ -221,12 +221,12 @@ class Base(object): nodes.append(l) return nodes - def __cmp__(self, other): + def __eq__(self, other): try: - return cmp(self.__dict__, other.__dict__) + return self.__dict__ == other.__dict__ except AttributeError: # other probably doesn't have a __dict__ - return cmp(self.__dict__, other) + return self.__dict__ == other def __hash__(self): return id(self) diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 60e5c10..7ea2789 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -537,10 +537,10 @@ class Proxy(object): """Retrieve the entire wrapped object""" return self._subject - def __cmp__(self, other): + def __eq__(self, other): if issubclass(other.__class__, self._subject.__class__): - return cmp(self._subject, other) - return cmp(self.__dict__, other.__dict__) + return self._subject == other + return self.__dict__ == other.__dict__ class Delegate(object): """A Python Descriptor class that delegates attribute fetches diff --git a/test/Scanner/generated.py b/test/Scanner/generated.py index 845111c..82206c2 100644 --- a/test/Scanner/generated.py +++ b/test/Scanner/generated.py @@ -317,8 +317,8 @@ def write_out(file, dict): class CScannerCounter(object): def __init__(self, original_CScanner, *args, **kw): self.original_CScanner = original_CScanner - def __cmp__(self, *args, **kw): - return self.original_CScanner.__cmp__(*args, **kw) + def __eq__(self, *args, **kw): + return self.original_CScanner.__eq__(*args, **kw) def __hash__(self, *args, **kw): return self.original_CScanner.__hash__(*args, **kw) def __str__(self, *args, **kw): -- cgit v0.12 From 6c1162f68d4682a045d35806a49dee50fba62808 Mon Sep 17 00:00:00 2001 From: Stefan Zimmermann Date: Fri, 27 Dec 2013 13:28:41 +0000 Subject: ActionTests: No string.join(). b prefix for assert Action.get_contents(). --- src/engine/SCons/ActionTests.py | 74 ++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py index 754c6e7..01b38f3 100644 --- a/src/engine/SCons/ActionTests.py +++ b/src/engine/SCons/ActionTests.py @@ -62,7 +62,7 @@ test = TestCmd.TestCmd(workdir = '') test.write('act.py', """\ import os, string, sys f = open(sys.argv[1], 'w') -f.write("act.py: '" + string.join(sys.argv[2:], "' '") + "'\\n") +f.write("act.py: '" + "' '".join(sys.argv[2:]) + "'\\n") try: if sys.argv[3]: f.write("act.py: '" + os.environ[sys.argv[3]] + "'\\n") @@ -1326,7 +1326,7 @@ class CommandActionTestCase(unittest.TestCase): c = a.get_contents(target=[], source=[], env=Environment(foo = 'FFF', bar = 'BBB', baz = CmdGen)) - assert c == "| | FFF BBB 1", c + assert c == b"| | FFF BBB 1", c # Make sure that CommandActions use an Environment's # subst_target_source() method for substitution. @@ -1337,7 +1337,7 @@ class CommandActionTestCase(unittest.TestCase): c = a.get_contents(target=DummyNode('ttt'), source = DummyNode('sss'), env=SpecialEnvironment(foo = 'GGG', bar = 'CCC', baz = 'ZZZ')) - assert c == 'subst_target_source: | $( $foo | $bar $) | $baz 1', c + assert c == b'subst_target_source: | $( $foo | $bar $) | $baz 1', c # We've discussed using the real target and source names in a # CommandAction's signature contents. This would have have the @@ -1354,35 +1354,35 @@ class CommandActionTestCase(unittest.TestCase): a = SCons.Action.CommandAction(["$TARGET"]) c = a.get_contents(target=t, source=s, env=env) - assert c == "t1", c + assert c == b"t1", c a = SCons.Action.CommandAction(["$TARGETS"]) c = a.get_contents(target=t, source=s, env=env) - assert c == "t1 t2 t3 t4 t5 t6", c + assert c == b"t1 t2 t3 t4 t5 t6", c a = SCons.Action.CommandAction(["${TARGETS[2]}"]) c = a.get_contents(target=t, source=s, env=env) - assert c == "t3", c + assert c == b"t3", c a = SCons.Action.CommandAction(["${TARGETS[3:5]}"]) c = a.get_contents(target=t, source=s, env=env) - assert c == "t4 t5", c + assert c == b"t4 t5", c a = SCons.Action.CommandAction(["$SOURCE"]) c = a.get_contents(target=t, source=s, env=env) - assert c == "s1", c + assert c == b"s1", c a = SCons.Action.CommandAction(["$SOURCES"]) c = a.get_contents(target=t, source=s, env=env) - assert c == "s1 s2 s3 s4 s5 s6", c + assert c == b"s1 s2 s3 s4 s5 s6", c a = SCons.Action.CommandAction(["${SOURCES[2]}"]) c = a.get_contents(target=t, source=s, env=env) - assert c == "s3", c + assert c == b"s3", c a = SCons.Action.CommandAction(["${SOURCES[3:5]}"]) c = a.get_contents(target=t, source=s, env=env) - assert c == "s4 s5", c + assert c == b"s4 s5", c class CommandGeneratorActionTestCase(unittest.TestCase): @@ -1499,7 +1499,7 @@ class CommandGeneratorActionTestCase(unittest.TestCase): ignore = 'foo', test=test) a = self.factory(f) c = a.get_contents(target=[], source=[], env=env) - assert c == "guux FFF BBB test", c + assert c == b"guux FFF BBB test", c def test_get_contents_of_function_action(self): """Test contents of a CommandGeneratorAction-generated FunctionAction @@ -1509,13 +1509,13 @@ class CommandGeneratorActionTestCase(unittest.TestCase): pass func_matches = [ - "0,0,0,0,(),(),(d\000\000S),(),()", - "0,0,0,0,(),(),(d\x00\x00S),(),()", + b"0,0,0,0,(),(),(d\000\000S),(),()", + b"0,0,0,0,(),(),(d\x00\x00S),(),()", ] meth_matches = [ - "1,1,0,0,(),(),(d\000\000S),(),()", - "1,1,0,0,(),(),(d\x00\x00S),(),()", + b"1,1,0,0,(),(),(d\000\000S),(),()", + b"1,1,0,0,(),(),(d\x00\x00S),(),()", ] def f_global(target, source, env, for_signature): @@ -1540,7 +1540,7 @@ class CommandGeneratorActionTestCase(unittest.TestCase): def f_local(target, source, env, for_signature): return SCons.Action.Action(LocalFunc, varlist=['XYZ']) - matches_foo = [x + "foo" for x in func_matches] + matches_foo = [x + b"foo" for x in func_matches] a = self.factory(f_global) c = a.get_contents(target=[], source=[], env=env) @@ -1668,13 +1668,13 @@ class FunctionActionTestCase(unittest.TestCase): pass func_matches = [ - "0,0,0,0,(),(),(d\000\000S),(),()", - "0,0,0,0,(),(),(d\x00\x00S),(),()", + b"0,0,0,0,(),(),(d\000\000S),(),()", + b"0,0,0,0,(),(),(d\x00\x00S),(),()", ] meth_matches = [ - "1,1,0,0,(),(),(d\000\000S),(),()", - "1,1,0,0,(),(),(d\x00\x00S),(),()", + b"1,1,0,0,(),(),(d\000\000S),(),()", + b"1,1,0,0,(),(),(d\x00\x00S),(),()", ] def factory(act, **kw): @@ -1688,7 +1688,7 @@ class FunctionActionTestCase(unittest.TestCase): c = a.get_contents(target=[], source=[], env=Environment()) assert c in func_matches, repr(c) - matches_foo = [x + "foo" for x in func_matches] + matches_foo = [x + b"foo" for x in func_matches] a = factory(GlobalFunc, varlist=['XYZ']) c = a.get_contents(target=[], source=[], env=Environment()) @@ -1706,10 +1706,10 @@ class FunctionActionTestCase(unittest.TestCase): class Foo(object): def get_contents(self, target, source, env): - return 'xyzzy' + return b'xyzzy' a = factory(Foo()) c = a.get_contents(target=[], source=[], env=Environment()) - assert c == 'xyzzy', repr(c) + assert c == b'xyzzy', repr(c) class LocalClass(object): def LocalMethod(self): @@ -1820,7 +1820,7 @@ class ListActionTestCase(unittest.TestCase): "z"]) c = a.get_contents(target=[], source=[], env=Environment(s = self)) assert self.foo==1, self.foo - assert c == "xyz", c + assert c == b"xyz", c class LazyActionTestCase(unittest.TestCase): def test___init__(self): @@ -1871,7 +1871,7 @@ class LazyActionTestCase(unittest.TestCase): a = SCons.Action.Action("${FOO}") env = Environment(FOO = [["This", "is", "a", "test"]]) c = a.get_contents(target=[], source=[], env=env) - assert c == "This is a test", c + assert c == b"This is a test", c def test_get_contents_of_function_action(self): """Test fetching the contents of a lazy-evaluation FunctionAction @@ -1881,13 +1881,13 @@ class LazyActionTestCase(unittest.TestCase): pass func_matches = [ - "0,0,0,0,(),(),(d\000\000S),(),()", - "0,0,0,0,(),(),(d\x00\x00S),(),()", + b"0,0,0,0,(),(),(d\000\000S),(),()", + b"0,0,0,0,(),(),(d\x00\x00S),(),()", ] meth_matches = [ - "1,1,0,0,(),(),(d\000\000S),(),()", - "1,1,0,0,(),(),(d\x00\x00S),(),()", + b"1,1,0,0,(),(),(d\000\000S),(),()", + b"1,1,0,0,(),(),(d\x00\x00S),(),()", ] def factory(act, **kw): @@ -1904,7 +1904,7 @@ class LazyActionTestCase(unittest.TestCase): c = a.get_contents(target=[], source=[], env=env) assert c in func_matches, repr(c) - matches_foo = [x + "foo" for x in func_matches] + matches_foo = [x + b"foo" for x in func_matches] env = Environment(FOO = factory(GlobalFunc, varlist=['XYZ'])) c = a.get_contents(target=[], source=[], env=env) @@ -1931,8 +1931,8 @@ class ActionCallerTestCase(unittest.TestCase): pass matches = [ - "d\000\000S", - "d\x00\x00S" + b"d\000\000S", + b"d\x00\x00S" ] af = SCons.Action.ActionFactory(GlobalFunc, strfunc) @@ -1946,8 +1946,8 @@ class ActionCallerTestCase(unittest.TestCase): assert c in matches, repr(c) matches = [ - 'd\000\000S', - "d\x00\x00S" + b'd\000\000S', + b"d\x00\x00S" ] class LocalActFunc(object): @@ -1965,8 +1965,8 @@ class ActionCallerTestCase(unittest.TestCase): assert c in matches, repr(c) matches = [ - "", - "", + b"", + b"", ] af = SCons.Action.ActionFactory(str, strfunc) -- cgit v0.12 From 2d2df48b33045bb15b543264114c6ef35773ef29 Mon Sep 17 00:00:00 2001 From: Stefan Zimmermann Date: Fri, 27 Dec 2013 13:30:45 +0000 Subject: Another list(*.keys()) for item deletion loop. --- src/engine/SCons/SConfTests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/SCons/SConfTests.py b/src/engine/SCons/SConfTests.py index e604886..ba524fd 100644 --- a/src/engine/SCons/SConfTests.py +++ b/src/engine/SCons/SConfTests.py @@ -60,7 +60,7 @@ class SConfTestCase(unittest.TestCase): # We try to reset scons' state (including all global variables) import SCons.SConsign SCons.SConsign.write() # simulate normal scons-finish - for n in sys.modules.keys(): + for n in list(sys.modules.keys()): if n.split('.')[0] == 'SCons' and n[:12] != 'SCons.compat': m = sys.modules[n] if isinstance(m, ModuleType): -- cgit v0.12 From 26003a0bd3168f8c2ee3d92a26d35ca977f8e25b Mon Sep 17 00:00:00 2001 From: Stefan Zimmermann Date: Wed, 8 Jan 2014 13:25:16 +0000 Subject: Some more six.PY2/PY3 usage. --- bin/install_scons.py | 6 ++++-- review.py | 14 ++++++++------ runtest.py | 6 ++++-- src/engine/SCons/Util.py | 11 ++++------- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/bin/install_scons.py b/bin/install_scons.py index 7a39e96..afd0789 100644 --- a/bin/install_scons.py +++ b/bin/install_scons.py @@ -19,14 +19,16 @@ # hierarchy. from __future__ import print_function +from six import PY3 + import getopt import os import shutil import sys import tarfile -try: +if PY3: from urllib.request import urlretrieve -except ImportError: # Python < 3 +else: from urllib import urlretrieve from Command import CommandRunner, Usage diff --git a/review.py b/review.py index c01472e..9f1ba82 100644 --- a/review.py +++ b/review.py @@ -15,6 +15,8 @@ # limitations under the License. from __future__ import print_function +from six import PY3 + """Tool for uploading diffs from a version control system to the codereview app. Usage summary: upload.py [options] [-- diff_options] [path...] @@ -32,14 +34,14 @@ against by using the '--rev' option. # This code is derived from appcfg.py in the App Engine SDK (open source), # and from ASPN recipe #146306. -try: +if PY3: from configparser import ConfigParser -except ImportError: # Python < 3 +else: from ConfigParser import ConfigParser -try: +if PY3: from http.cookiejar import ( CookieJar, MozillaCookieJar, LoadError as CookieLoadError) -except ImportError: # Python < 3 +else: from cookielib import ( CookieJar, MozillaCookieJar, LoadError as CookieLoadError) import fnmatch @@ -52,7 +54,7 @@ import re import socket import subprocess import sys -try: +if PY3: from urllib.request import ( Request, OpenerDirector, ProxyHandler, UnknownHandler, HTTPHandler, HTTPSHandler, @@ -61,7 +63,7 @@ try: from urllib.error import HTTPError from urllib.parse import ( urlencode, urlparse, urlunparse, splituser as urlsplituser) -except ImportError: # Python < 3 +else: from urllib2 import ( Request, OpenerDirector, ProxyHandler, UnknownHandler, HTTPHandler, HTTPSHandler, diff --git a/runtest.py b/runtest.py index 2470a61..6380292 100755 --- a/runtest.py +++ b/runtest.py @@ -85,6 +85,8 @@ # rather than reinventing that wheel.) from __future__ import print_function +from six import PY3 + import getopt import glob import os @@ -95,9 +97,9 @@ import time try: import threading - try: + if PY3: from queue import Queue - except ImportError: # Python < 3 + else: from Queue import Queue threading_ok = True except ImportError: diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 7ea2789..052b3fc 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -33,24 +33,21 @@ import copy import re import types -try: +if PY3: from collections import UserDict, UserList, UserString -except ImportError: # Python < 3 +else: from UserDict import UserDict from UserList import UserList from UserString import UserString # Don't "from types import ..." these because we need to get at the # types module later to look for UnicodeType. -try: - InstanceType = types.InstanceType -except AttributeError: # Python 3 - InstanceType = None +InstanceType = types.InstanceType if PY2 else None MethodType = types.MethodType FunctionType = types.FunctionType try: unicode except NameError: UnicodeType = None -else: UnicodeType = str +else: UnicodeType = unicode def dictify(keys, values, result={}): for k, v in zip(keys, values): -- cgit v0.12 From 8986df6b325e924f4143b03705129899fccc72ba Mon Sep 17 00:00:00 2001 From: Stefan Zimmermann Date: Wed, 8 Jan 2014 13:27:10 +0000 Subject: Fixed re.sub for PY3 print() in TestCmd.write(). --- QMTest/TestCmd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QMTest/TestCmd.py b/QMTest/TestCmd.py index c075cd3..2ac3da1 100644 --- a/QMTest/TestCmd.py +++ b/QMTest/TestCmd.py @@ -1717,7 +1717,7 @@ class TestCmd(object): begin with a 'w'. The default is 'wb' (binary write). """ if PY3: - content = re.sub('print (.+)', 'print(\1)', content) + content = re.sub(r'print (.+)', r'print(\1)', content) file = self.canonicalize(file) if mode[0] != 'w': raise ValueError("mode must begin with 'w'") -- cgit v0.12 From ea1890249923aab9cda388b2d22b566dbb7b8949 Mon Sep 17 00:00:00 2001 From: Rocco Matano Date: Fri, 7 Mar 2014 15:39:43 +0100 Subject: fix some minor 2to3 issues on windows --- src/engine/SCons/Platform/win32.py | 22 +++++++++++++--------- src/engine/SCons/Tool/386asm.py | 2 +- src/engine/SCons/Tool/MSCommon/common.py | 5 ++--- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/engine/SCons/Platform/win32.py b/src/engine/SCons/Platform/win32.py index 879817d..1e4fb2a 100644 --- a/src/engine/SCons/Platform/win32.py +++ b/src/engine/SCons/Platform/win32.py @@ -61,16 +61,21 @@ else: parallel_msg = None import builtins - - _builtin_file = builtins.file + builtin_file = getattr(builtins, 'file', None) is not None + + if builtin_file: + _builtin_file = builtins.file + + class _scons_file(_builtin_file): + def __init__(self, *args, **kw): + _builtin_file.__init__(self, *args, **kw) + win32api.SetHandleInformation(msvcrt.get_osfhandle(self.fileno()), + win32con.HANDLE_FLAG_INHERIT, 0) + + builtins.file = _scons_file + _builtin_open = builtins.open - class _scons_file(_builtin_file): - def __init__(self, *args, **kw): - _builtin_file.__init__(self, *args, **kw) - win32api.SetHandleInformation(msvcrt.get_osfhandle(self.fileno()), - win32con.HANDLE_FLAG_INHERIT, 0) - def _scons_open(*args, **kw): fp = _builtin_open(*args, **kw) win32api.SetHandleInformation(msvcrt.get_osfhandle(fp.fileno()), @@ -78,7 +83,6 @@ else: 0) return fp - builtins.file = _scons_file builtins.open = _scons_open try: diff --git a/src/engine/SCons/Tool/386asm.py b/src/engine/SCons/Tool/386asm.py index 8acc55f..51738eb 100644 --- a/src/engine/SCons/Tool/386asm.py +++ b/src/engine/SCons/Tool/386asm.py @@ -37,7 +37,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" from SCons.Tool.PharLapCommon import addPharLapPaths import SCons.Util -as_module = __import__('as', globals(), locals(), []) +as_module = __import__('as', globals(), locals(), [], 1) def generate(env): """Add Builders and construction variables for ar to an Environment.""" diff --git a/src/engine/SCons/Tool/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py index e5c78e9..4a91310 100644 --- a/src/engine/SCons/Tool/MSCommon/common.py +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -115,11 +115,11 @@ def normalize_env(env, keys, force=False): normenv = {} if env: for k in env.keys(): - normenv[k] = copy.deepcopy(env[k]).encode('mbcs') + normenv[k] = copy.deepcopy(env[k]) for k in keys: if k in os.environ and (force or not k in normenv): - normenv[k] = os.environ[k].encode('mbcs') + normenv[k] = os.environ[k] # This shouldn't be necessary, since the default environment should include system32, # but keep this here to be safe, since it's needed to find reg.exe which the MSVC @@ -212,7 +212,6 @@ def parse_output(output, keep = ("INCLUDE", "LIB", "LIBPATH", "PATH")): for p in plist: # Do not add empty paths (when a var ends with ;) if p: - p = p.encode('mbcs') # XXX: For some reason, VC98 .bat file adds "" around the PATH # values, and it screws up the environment later, so we strip # it. -- cgit v0.12 From 18ecb44af82ac0b95c852ff05eaf4fe3af3fb724 Mon Sep 17 00:00:00 2001 From: Stefan Zimmermann Date: Mon, 31 Mar 2014 22:32:02 +0000 Subject: Additional ()s for print. --- src/script/scons.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/script/scons.py b/src/script/scons.py index d0bb812..25ae644 100644 --- a/src/script/scons.py +++ b/src/script/scons.py @@ -191,7 +191,7 @@ if __name__ == "__main__": 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 -- cgit v0.12 From e7fbae42ed9a4db4be2152c2bccd05ce46226689 Mon Sep 17 00:00:00 2001 From: Stefan Zimmermann Date: Mon, 31 Mar 2014 22:37:42 +0000 Subject: SConstruct: More bytes/str fixes. --- SConstruct | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/SConstruct b/SConstruct index f1f1fa3..a18de57 100644 --- a/SConstruct +++ b/SConstruct @@ -418,7 +418,8 @@ def soelim(target, source, env): def soscan(node, env, path): c = node.get_text_contents() - return re.compile(r"^[\.']so\s+(\S+)", re.M).findall(c) + # Node contents are bytes ==> br"..." + return re.compile(br"^[\.']so\s+(\S+)", re.M).findall(c) soelimbuilder = Builder(action = Action(soelim), source_scanner = Scanner(soscan)) @@ -828,7 +829,7 @@ for p in [ scons ]: def write_src_files(target, source, **kw): global src_files src_files.sort() - f = open(str(target[0]), 'wb') + f = open(str(target[0]), 'w') for file in src_files: f.write(file + "\n") f.close() -- cgit v0.12 From 83cdce661b4a953f2b307f60577db53fb23a8b2d Mon Sep 17 00:00:00 2001 From: Stefan Zimmermann Date: Mon, 31 Mar 2014 22:38:22 +0000 Subject: engine.SCons: More bytes/str fixes. --- src/engine/SCons/Action.py | 2 +- src/engine/SCons/Node/FS.py | 2 +- src/engine/SCons/Tool/docbook/__init__.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index d7d9afd..cec241d 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -290,7 +290,7 @@ def _function_contents(func): xxx = [_object_contents(x.cell_contents) for x in closure] except AttributeError: xxx = [] - contents.append(b',(' + b','.join(xxx) + b')') + contents.append(b',(' + ','.join(xxx).encode('ascii') + b')') return b''.join(contents) diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index a537ca8..efca0c7 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -2420,7 +2420,7 @@ class File(Base): def get_contents(self): if not self.rexists(): - return '' + return b'' # Should always be bytes fname = self.rfile().abspath try: contents = open(fname, "rb").read() diff --git a/src/engine/SCons/Tool/docbook/__init__.py b/src/engine/SCons/Tool/docbook/__init__.py index aacc26d..627ff51 100644 --- a/src/engine/SCons/Tool/docbook/__init__.py +++ b/src/engine/SCons/Tool/docbook/__init__.py @@ -335,7 +335,7 @@ def __build_lxml(target, source, env): result = transform(doc) try: - of = open(str(target[0]), "w") + of = open(str(target[0]), "wb") of.write(of.write(etree.tostring(result, pretty_print=True))) of.close() except: -- cgit v0.12 From 7ae89fc5202506a060260f6052ec2f464c451107 Mon Sep 17 00:00:00 2001 From: Stefan Zimmermann Date: Mon, 31 Mar 2014 22:39:12 +0000 Subject: Tool.gs: Changed relative pdf import to absolute. --- src/engine/SCons/Tool/gs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/SCons/Tool/gs.py b/src/engine/SCons/Tool/gs.py index 443ace2..25359a8 100644 --- a/src/engine/SCons/Tool/gs.py +++ b/src/engine/SCons/Tool/gs.py @@ -62,7 +62,7 @@ def generate(env): if GhostscriptAction is None: GhostscriptAction = SCons.Action.Action('$GSCOM', '$GSCOMSTR') - from . import pdf + from SCons.Tool import pdf pdf.generate(env) bld = env['BUILDERS']['PDF'] -- cgit v0.12 From fad7c3eaf7f9cae12dbf03e03df7919d6fedea0e Mon Sep 17 00:00:00 2001 From: Stefan Zimmermann Date: Tue, 1 Apr 2014 07:19:29 +0000 Subject: Main: Use exec() with compile(). --- src/engine/SCons/Script/Main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index 7906488..8725530 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -733,7 +733,7 @@ def _load_site_scons_dir(topdir, site_dir_name=None): site_m[k] = m.__dict__[k] # This is the magic. - exec(fp, site_m) + exec(compile(fp.read(), fp.name, 'exec'), site_m) except KeyboardInterrupt: raise except Exception as e: -- cgit v0.12 From a13f1049893f07d3a77474d77214a24eee3cb75b Mon Sep 17 00:00:00 2001 From: Stefan Zimmermann Date: Tue, 1 Apr 2014 07:28:31 +0000 Subject: test: site_scons/site_init: list() globals keys for looping to allow changes. --- test/site_scons/site_init.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/site_scons/site_init.py b/test/site_scons/site_init.py index 9f2e411..45201ac 100644 --- a/test/site_scons/site_init.py +++ b/test/site_scons/site_init.py @@ -51,7 +51,7 @@ import os.path import re special = [] -for x in globals().keys(): +for x in list(globals().keys()): if re.match("__[^_]+__", x): if x in ("__builtins__", "__package__",): # Ignore certain keywords, as they are known to be added by Python -- cgit v0.12 From 4631c0c43550e65bb4cb57a21b17c329966b2e03 Mon Sep 17 00:00:00 2001 From: Stefan Zimmermann Date: Tue, 1 Apr 2014 07:40:28 +0000 Subject: Main: No __future__.print_function (would affect exec()'d code). --- src/engine/SCons/Script/Main.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index 8725530..0663c7a 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -10,7 +10,9 @@ some other module. If it's specific to the "scons" script invocation, it goes here. """ -from __future__ import print_function +# Would affect exec()'d site_init.py: +## from __future__ import print_function +from six import print_ unsupported_python_version = (2, 3, 0) deprecated_python_version = (2, 7, 0) @@ -339,7 +341,7 @@ class CleanTask(SCons.Taskmaster.AlwaysTask): except SCons.Errors.UserError as e: print(e) except (IOError, OSError) as e: - print("scons: Could not remove '%s':" % pathstr, e.strerror) + print_("scons: Could not remove '%s':" % pathstr, e.strerror) def show(self): target = self.targets[0] @@ -364,7 +366,7 @@ class CleanTask(SCons.Taskmaster.AlwaysTask): # the file not existing. In either case, print a # message and keep going to try to remove as many # targets aa possible. - print("scons: Could not remove '%s':" % str(t), e.strerror) + print_("scons: Could not remove '%s':" % str(t), e.strerror) else: if removed: display("Removed " + str(t)) @@ -798,7 +800,7 @@ def _load_all_site_scons_dirs(topdir, verbose=None): dirs=sysdirs + [topdir] for d in dirs: if verbose: # this is used by unit tests. - print("Loading site dir ", d) + print_("Loading site dir ", d) _load_site_scons_dir(d) def test_load_all_site_scons_dirs(d): -- cgit v0.12 From 8490ea812140862af7058f9617959061510c3701 Mon Sep 17 00:00:00 2001 From: Gary Oberbrunner Date: Sun, 6 Apr 2014 10:50:33 -0400 Subject: Added change log for python3 port --- src/CHANGES.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 5cea35f..f65dfd5 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -6,6 +6,9 @@ RELEASE 2.3.2.alpha.yyyymmdd - NEW DATE WILL BE INSERTED HERE + From Neal Becker and Stefan Zimmermann: + - Python 3 port and compatibility + From Gary Oberbrunner: - get default RPM architecture more robustly when building RPMs -- cgit v0.12 From a6ea2d760464092ea91a0dd01ba6260288aa3587 Mon Sep 17 00:00:00 2001 From: Gary Oberbrunner Date: Sun, 20 Apr 2014 06:56:10 -0400 Subject: Added six module as SCons.compat.six, for python3 port. --- QMTest/TestCmd.py | 4 +- QMTest/TestCmdTests.py | 50 +-- bin/install_scons.py | 2 +- review.py | 8 +- runtest.py | 5 +- src/engine/SCons/MemoizeTests.py | 2 +- src/engine/SCons/Script/Main.py | 2 +- src/engine/SCons/Taskmaster.py | 10 +- src/engine/SCons/Tool/xgettext.py | 30 +- src/engine/SCons/Util.py | 32 +- src/engine/SCons/UtilTests.py | 6 +- src/engine/SCons/compat/_scons_subprocess.py | 2 +- src/engine/SCons/compat/six.py | 646 +++++++++++++++++++++++++++ src/engine/SCons/compat/sixTests.py | 34 ++ src/script/sconsign.py | 4 +- test/option/profile.py | 4 +- 16 files changed, 760 insertions(+), 81 deletions(-) create mode 100755 src/engine/SCons/compat/six.py create mode 100644 src/engine/SCons/compat/sixTests.py diff --git a/QMTest/TestCmd.py b/QMTest/TestCmd.py index 55c198f..e6b128b 100644 --- a/QMTest/TestCmd.py +++ b/QMTest/TestCmd.py @@ -287,7 +287,7 @@ version. # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. from __future__ import division, print_function -from six import PY3 +from SCons.compat.six import PY3 __author__ = "Steven Knight " __revision__ = "TestCmd.py 1.3.D001 2010/06/03 12:58:27 knight" @@ -685,7 +685,7 @@ if subprocess.mswindows: assert ol is None lpBuffer = ctypes.create_string_buffer(bufSize) bytesRead = DWORD() - bErr = ctypes.windll.kernel32.ReadFile( + bErr = ctypes.windll.kernel32.ReadFile( hFile, lpBuffer, bufSize, ctypes.byref(bytesRead), ol) if not bErr: raise ctypes.WinError() return (0, ctypes.string_at(lpBuffer, bytesRead.value)) diff --git a/QMTest/TestCmdTests.py b/QMTest/TestCmdTests.py index 6611590..a2e7022 100644 --- a/QMTest/TestCmdTests.py +++ b/QMTest/TestCmdTests.py @@ -19,7 +19,7 @@ AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. """ -from six import PY3 +from SCons.compat.six import PY3 __author__ = "Steven Knight " __revision__ = "TestCmdTests.py 1.3.D001 2010/06/03 12:58:27 knight" @@ -1870,24 +1870,24 @@ class run_verbose_TestCase(TestCmdTestCase): interpreter = 'python', workdir = '', verbose = 1) - + sys.stdout = StringIO() sys.stderr = StringIO() - + test.run(arguments = ['arg1 arg2']) o = sys.stdout.getvalue() assert o == '', o e = sys.stderr.getvalue() expect = 'python "%s" "arg1 arg2"\n' % t.script_path assert expect == e, (expect, e) - + testx = TestCmd.TestCmd(program = t.scriptx, workdir = '', verbose = 1) - + sys.stdout = StringIO() sys.stderr = StringIO() - + testx.run(arguments = ['arg1 arg2']) expect = '"%s" "arg1 arg2"\n' % t.scriptx_path o = sys.stdout.getvalue() @@ -1921,10 +1921,10 @@ class run_verbose_TestCase(TestCmdTestCase): interpreter = 'python', workdir = '', verbose = 2) - + sys.stdout = StringIO() sys.stderr = StringIO() - + test.run(arguments = ['arg1 arg2']) line_fmt = "script: %s: %s: ['arg1 arg2']\n" @@ -1938,14 +1938,14 @@ class run_verbose_TestCase(TestCmdTestCase): expect = 'python "%s" "arg1 arg2"\n' % t.script_path e = sys.stderr.getvalue() assert e == expect, (e, expect) - + testx = TestCmd.TestCmd(program = t.scriptx, workdir = '', verbose = 2) - + sys.stdout = StringIO() sys.stderr = StringIO() - + testx.run(arguments = ['arg1 arg2']) line_fmt = "scriptx.bat: %s: %s: ['arg1 arg2']\n" @@ -1966,10 +1966,10 @@ class run_verbose_TestCase(TestCmdTestCase): interpreter = 'python', workdir = '', verbose = 2) - + sys.stdout = StringIO() sys.stderr = StringIO() - + test.run(arguments = ['arg1 arg2']) line_fmt = "scriptout: %s: %s: ['arg1 arg2']\n" @@ -1986,10 +1986,10 @@ class run_verbose_TestCase(TestCmdTestCase): interpreter = 'python', workdir = '', verbose = 3) - + sys.stdout = StringIO() sys.stderr = StringIO() - + test.run(arguments = ['arg1 arg2']) line_fmt = "scriptout: %s: %s: ['arg1 arg2']\n" @@ -2010,10 +2010,10 @@ class run_verbose_TestCase(TestCmdTestCase): test = TestCmd.TestCmd(program = t.script, interpreter = 'python', workdir = '') - + sys.stdout = StringIO() sys.stderr = StringIO() - + test.run(arguments = ['arg1 arg2']) line_fmt = "script: %s: %s: ['arg1 arg2']\n" @@ -2027,13 +2027,13 @@ class run_verbose_TestCase(TestCmdTestCase): expect = 'python "%s" "arg1 arg2"\n' % t.script_path e = sys.stderr.getvalue() assert e == expect, (e, expect) - + testx = TestCmd.TestCmd(program = t.scriptx, workdir = '') - + sys.stdout = StringIO() sys.stderr = StringIO() - + testx.run(arguments = ['arg1 arg2']) line_fmt = "scriptx.bat: %s: %s: ['arg1 arg2']\n" @@ -2056,24 +2056,24 @@ class run_verbose_TestCase(TestCmdTestCase): interpreter = 'python', workdir = '', verbose = 1) - + sys.stdout = StringIO() sys.stderr = StringIO() - + test.run(arguments = ['arg1 arg2']) o = sys.stdout.getvalue() assert o == '', o e = sys.stderr.getvalue() expect = 'python "%s" "arg1 arg2"\n' % t.script_path assert expect == e, (expect, e) - + testx = TestCmd.TestCmd(program = t.scriptx, workdir = '', verbose = 1) - + sys.stdout = StringIO() sys.stderr = StringIO() - + testx.run(arguments = ['arg1 arg2']) expect = '"%s" "arg1 arg2"\n' % t.scriptx_path o = sys.stdout.getvalue() diff --git a/bin/install_scons.py b/bin/install_scons.py index afd0789..55e327d 100644 --- a/bin/install_scons.py +++ b/bin/install_scons.py @@ -19,7 +19,7 @@ # hierarchy. from __future__ import print_function -from six import PY3 +from SCons.compat.six import PY3 import getopt import os diff --git a/review.py b/review.py index 9f1ba82..a796b2f 100644 --- a/review.py +++ b/review.py @@ -15,7 +15,7 @@ # limitations under the License. from __future__ import print_function -from six import PY3 +from SCons.compat.six import PY3 """Tool for uploading diffs from a version control system to the codereview app. @@ -120,7 +120,7 @@ VCS_UNKNOWN = "Unknown" # whitelist for non-binary filetypes which do not start with "text/" # .mm (Objective-C) shows up as application/x-freemind on my Linux box. TEXT_MIMETYPES = ['application/javascript', 'application/x-javascript', - 'application/xml', 'application/x-freemind', + 'application/xml', 'application/x-freemind', 'application/x-sh'] VCS_ABBREVIATIONS = { @@ -1474,7 +1474,7 @@ def GuessVCSName(): """ def RunDetectCommand(vcs_type, command): """Helper to detect VCS by executing command. - + Returns: A pair (vcs, output) or None. Throws exception on error. """ @@ -1486,7 +1486,7 @@ def GuessVCSName(): (errcode, message) = xxx_todo_changeme.args if errcode != errno.ENOENT: # command not found code raise - + # Mercurial has a command to get the base directory of a repository # Try running it, but don't die if we don't have hg installed. # NOTE: we try Mercurial first as it can sit on top of an SVN working copy. diff --git a/runtest.py b/runtest.py index 7155556..485374a 100755 --- a/runtest.py +++ b/runtest.py @@ -81,7 +81,6 @@ # rather than reinventing that wheel.) from __future__ import print_function -from six import PY3 import getopt import glob @@ -93,9 +92,9 @@ import time try: import threading - if PY3: + try: # python3 from queue import Queue - else: + except ImportError as e: # python2 from Queue import Queue threading_ok = True except ImportError: diff --git a/src/engine/SCons/MemoizeTests.py b/src/engine/SCons/MemoizeTests.py index c1c69ae..8476349 100644 --- a/src/engine/SCons/MemoizeTests.py +++ b/src/engine/SCons/MemoizeTests.py @@ -20,7 +20,7 @@ # 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 six import add_metaclass +from SCons.compat.six import add_metaclass __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index 0663c7a..1357e7f 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -12,7 +12,7 @@ it goes here. # Would affect exec()'d site_init.py: ## from __future__ import print_function -from six import print_ +from SCons.compat.six import print_ unsupported_python_version = (2, 3, 0) deprecated_python_version = (2, 7, 0) diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py index 00147b2..4a06654 100644 --- a/src/engine/SCons/Taskmaster.py +++ b/src/engine/SCons/Taskmaster.py @@ -306,7 +306,7 @@ class Task(object): t.push_to_cache() t.built() t.visited() - if (not print_prepare and + if (not print_prepare and (not hasattr(self, 'options') or not self.options.debug_includes)): t.release_target_info() else: @@ -424,7 +424,7 @@ class Task(object): # parallel build...) t.visited() t.set_state(NODE_UP_TO_DATE) - if (not print_prepare and + if (not print_prepare and (not hasattr(self, 'options') or not self.options.debug_includes)): t.release_target_info() @@ -533,8 +533,8 @@ class Task(object): Task ready for execution. """ - import six - six.reraise(*self.exc_info()) + import SCons.compat.six + SCons.compat.six.reraise(*self.exc_info()) class AlwaysTask(Task): def needs_execute(self): @@ -940,7 +940,7 @@ class Taskmaster(object): executor = node.get_executor() if executor is None: return None - + tlist = executor.get_all_targets() task = self.tasker(self, tlist, node in self.original_top, node) diff --git a/src/engine/SCons/Tool/xgettext.py b/src/engine/SCons/Tool/xgettext.py index f9375a2..923fd17 100644 --- a/src/engine/SCons/Tool/xgettext.py +++ b/src/engine/SCons/Tool/xgettext.py @@ -1,10 +1,10 @@ -""" xgettext tool +""" xgettext tool Tool specific initialization of `xgettext` tool. """ # __COPYRIGHT__ -# +# # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including @@ -12,10 +12,10 @@ Tool specific initialization of `xgettext` tool. # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: -# +# # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. -# +# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -23,7 +23,7 @@ Tool specific initialization of `xgettext` tool. # 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 six import u +from SCons.compat.six import u __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -40,12 +40,12 @@ class _CmdRunner(object): self.command = command self.commandstr = commandstr - def __call__(self, target, source, env): + def __call__(self, target, source, env): import SCons.Action import subprocess import os import sys - kw = { + kw = { 'stdin' : 'devnull', 'stdout' : subprocess.PIPE, 'stderr' : subprocess.PIPE, @@ -105,9 +105,9 @@ def _update_pot_file(target, source, env): os.chdir(save_os_cwd) # If the command was not successfull, return error code. if status: return status - + new_content = cmd.out - + if not new_content: # When xgettext finds no internationalized messages, no *.pot is created # (because we don't want to bother translators with empty POT files). @@ -145,7 +145,7 @@ def _update_pot_file(target, source, env): # Print message employing SCons.Action.Action for that. msg = "Not writting " + repr(str(target[0])) + " (" + explain + ")" env.Execute(SCons.Action.Action(nop, msg)) - return 0 + return 0 ############################################################################# ############################################################################# @@ -208,7 +208,7 @@ def _scan_xgettext_from_files(target, source, env, files = None, path = None): contents = re_emptyln.sub("", contents) contents = re_trailws.sub("", contents) depnames = contents.splitlines() - for depname in depnames: + for depname in depnames: depfile = SCons.Node.FS.find_file(depname, dirs) if not depfile: depfile = env.arg2nodes(depname, dirs[0].File) @@ -223,7 +223,7 @@ def _pot_update_emitter(target, source, env): import SCons.Util import SCons.Node.FS - if 'XGETTEXTFROM' in env: + if 'XGETTEXTFROM' in env: xfrom = env['XGETTEXTFROM'] else: return target, source @@ -231,13 +231,13 @@ def _pot_update_emitter(target, source, env): xfrom = [ xfrom ] xfrom = SCons.Util.flatten(xfrom) - + # Prepare list of 'POTFILE.in' files. files = [] for xf in xfrom: if not isinstance(xf, SCons.Node.FS.Base): if SCons.Util.is_String(xf): - # Interpolate variables in strings + # Interpolate variables in strings xf = env.subst(xf, source = source, target = target) xf = env.arg2nodes(xf) files.extend(xf) @@ -275,7 +275,7 @@ def generate(env,**kw): try: env['XGETTEXT'] = _detect_xgettext(env) except: - env['XGETTEXT'] = 'xgettext' + env['XGETTEXT'] = 'xgettext' # NOTE: sources="$SOURCES" would work as well. However, we use following # construction to convert absolute paths provided by scons onto paths # relative to current working dir. Note, that scons expands $SOURCE(S) to diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 052b3fc..3a368cb 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -23,7 +23,7 @@ Various utility functions go here. # 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 six import PY2, PY3, u +from SCons.compat.six import PY2, PY3, u __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -348,7 +348,7 @@ def is_Scalar(obj, isinstance=isinstance, StringTypes=StringTypes, SequenceTypes # assumes that the obj argument is a string must of the time. return isinstance(obj, StringTypes) or not isinstance(obj, SequenceTypes) -def do_flatten(sequence, result, isinstance=isinstance, +def do_flatten(sequence, result, isinstance=isinstance, StringTypes=StringTypes, SequenceTypes=SequenceTypes): for item in sequence: if isinstance(item, StringTypes) or not isinstance(item, SequenceTypes): @@ -356,7 +356,7 @@ def do_flatten(sequence, result, isinstance=isinstance, else: do_flatten(item, result) -def flatten(obj, isinstance=isinstance, StringTypes=StringTypes, +def flatten(obj, isinstance=isinstance, StringTypes=StringTypes, SequenceTypes=SequenceTypes, do_flatten=do_flatten): """Flatten a sequence to a non-nested list. @@ -374,7 +374,7 @@ def flatten(obj, isinstance=isinstance, StringTypes=StringTypes, do_flatten(item, result) return result -def flatten_sequence(sequence, isinstance=isinstance, StringTypes=StringTypes, +def flatten_sequence(sequence, isinstance=isinstance, StringTypes=StringTypes, SequenceTypes=SequenceTypes, do_flatten=do_flatten): """Flatten a sequence to a non-nested list. @@ -395,7 +395,7 @@ def flatten_sequence(sequence, isinstance=isinstance, StringTypes=StringTypes, # to_String_for_signature() will use a for_signature() method if the # specified object has one. # -def to_String(s, +def to_String(s, isinstance=isinstance, str=str, UserString=UserString, BaseStringTypes=BaseStringTypes): if isinstance(s,BaseStringTypes): @@ -408,11 +408,11 @@ def to_String(s, else: return str(s) -def to_String_for_subst(s, +def to_String_for_subst(s, isinstance=isinstance, str=str, to_String=to_String, BaseStringTypes=BaseStringTypes, SequenceTypes=SequenceTypes, UserString=UserString): - + # Note that the test cases are sorted by order of probability. if isinstance(s, BaseStringTypes): return s @@ -428,7 +428,7 @@ def to_String_for_subst(s, else: return str(s) -def to_String_for_signature(obj, to_String_for_subst=to_String_for_subst, +def to_String_for_signature(obj, to_String_for_subst=to_String_for_subst, AttributeError=AttributeError): try: f = obj.for_signature @@ -486,7 +486,7 @@ def semi_deepcopy(x): return x.__class__(semi_deepcopy_dict(x)) elif isinstance(x, UserList): return x.__class__(_semi_deepcopy_list(x)) - + return x @@ -632,7 +632,7 @@ else: builtins.WindowsError = WindowsError else: del e - + HKEY_CLASSES_ROOT = None HKEY_LOCAL_MACHINE = None HKEY_CURRENT_USER = None @@ -741,7 +741,7 @@ else: continue return None -def PrependPath(oldpath, newpath, sep = os.pathsep, +def PrependPath(oldpath, newpath, sep = os.pathsep, delete_existing=1, canonicalize=None): """This prepends newpath elements to the given oldpath. Will only add any particular path once (leaving the first one it encounters @@ -760,7 +760,7 @@ def PrependPath(oldpath, newpath, sep = os.pathsep, not move it to the beginning; it will stay where it is in the list. - If canonicalize is not None, it is applied to each element of + If canonicalize is not None, it is applied to each element of newpath before use. """ @@ -782,7 +782,7 @@ def PrependPath(oldpath, newpath, sep = os.pathsep, newpaths=list(map(canonicalize, newpaths)) if not delete_existing: - # First uniquify the old paths, making sure to + # First uniquify the old paths, making sure to # preserve the first instance (in Unix/Linux, # the first one wins), and remembering them in normpaths. # Then insert the new paths at the head of the list @@ -823,7 +823,7 @@ def PrependPath(oldpath, newpath, sep = os.pathsep, else: return sep.join(paths) -def AppendPath(oldpath, newpath, sep = os.pathsep, +def AppendPath(oldpath, newpath, sep = os.pathsep, delete_existing=1, canonicalize=None): """This appends new path elements to the given old path. Will only add any particular path once (leaving the last one it @@ -841,7 +841,7 @@ def AppendPath(oldpath, newpath, sep = os.pathsep, If delete_existing is 0, then adding a path that exists will not move it to the end; it will stay where it is in the list. - If canonicalize is not None, it is applied to each element of + If canonicalize is not None, it is applied to each element of newpath before use. """ @@ -1436,7 +1436,7 @@ else: m.update(to_bytes (str(blck))) f.close() return m.hexdigest() - + def MD5collect(signatures): """ Collects a list of signatures into an aggregate signature. diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py index 3167b9d..c52c910 100644 --- a/src/engine/SCons/UtilTests.py +++ b/src/engine/SCons/UtilTests.py @@ -20,7 +20,7 @@ # 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 six import u +from SCons.compat.six import u __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -697,7 +697,7 @@ bling def test_intern(self): s1 = silent_intern("spam") # Python 3.x does not have a unicode() global function - if sys.version[0] == '2': + if sys.version[0] == '2': s2 = silent_intern(unicode("unicode spam")) s3 = silent_intern(42) s4 = silent_intern("spam") @@ -710,7 +710,7 @@ class MD5TestCase(unittest.TestCase): """Test collecting a list of signatures into a new signature value """ s = list(map(MD5signature, ('111', '222', '333'))) - + assert '698d51a19d8a121ce581499d7b701668' == MD5collect(s[0:1]) assert '8980c988edc2c78cc43ccb718c06efd5' == MD5collect(s[0:2]) assert '53fd88c84ff8a285eb6e0a687e55b8c7' == MD5collect(s) diff --git a/src/engine/SCons/compat/_scons_subprocess.py b/src/engine/SCons/compat/_scons_subprocess.py index e4ac777..a58539d 100644 --- a/src/engine/SCons/compat/_scons_subprocess.py +++ b/src/engine/SCons/compat/_scons_subprocess.py @@ -352,7 +352,7 @@ except that: """ from __future__ import print_function -from six import integer_types +from SCons.compat.six import integer_types import sys mswindows = (sys.platform == "win32") diff --git a/src/engine/SCons/compat/six.py b/src/engine/SCons/compat/six.py new file mode 100755 index 0000000..019130f --- /dev/null +++ b/src/engine/SCons/compat/six.py @@ -0,0 +1,646 @@ +"""Utilities for writing code that runs on Python 2 and 3""" + +# Copyright (c) 2010-2014 Benjamin Peterson +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE 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. + +import operator +import sys +import types + +__author__ = "Benjamin Peterson " +__version__ = "1.6.1" + + +# Useful for very coarse version differentiation. +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 + +if PY3: + string_types = str, + integer_types = int, + class_types = type, + text_type = str + binary_type = bytes + + MAXSIZE = sys.maxsize +else: + string_types = basestring, + integer_types = (int, long) + class_types = (type, types.ClassType) + text_type = unicode + binary_type = str + + if sys.platform.startswith("java"): + # Jython always uses 32 bits. + MAXSIZE = int((1 << 31) - 1) + else: + # It's possible to have sizeof(long) != sizeof(Py_ssize_t). + class X(object): + def __len__(self): + return 1 << 31 + try: + len(X()) + except OverflowError: + # 32-bit + MAXSIZE = int((1 << 31) - 1) + else: + # 64-bit + MAXSIZE = int((1 << 63) - 1) + del X + + +def _add_doc(func, doc): + """Add documentation to a function.""" + func.__doc__ = doc + + +def _import_module(name): + """Import module, returning the module after the last dot.""" + __import__(name) + return sys.modules[name] + + +class _LazyDescr(object): + + def __init__(self, name): + self.name = name + + def __get__(self, obj, tp): + try: + result = self._resolve() + except ImportError: + # See the nice big comment in MovedModule.__getattr__. + raise AttributeError("%s could not be imported " % self.name) + setattr(obj, self.name, result) # Invokes __set__. + # This is a bit ugly, but it avoids running this again. + delattr(obj.__class__, self.name) + return result + + +class MovedModule(_LazyDescr): + + def __init__(self, name, old, new=None): + super(MovedModule, self).__init__(name) + if PY3: + if new is None: + new = name + self.mod = new + else: + self.mod = old + + def _resolve(self): + return _import_module(self.mod) + + def __getattr__(self, attr): + # It turns out many Python frameworks like to traverse sys.modules and + # try to load various attributes. This causes problems if this is a + # platform-specific module on the wrong platform, like _winreg on + # Unixes. Therefore, we silently pretend unimportable modules do not + # have any attributes. See issues #51, #53, #56, and #63 for the full + # tales of woe. + # + # First, if possible, avoid loading the module just to look at __file__, + # __name__, or __path__. + if (attr in ("__file__", "__name__", "__path__") and + self.mod not in sys.modules): + raise AttributeError(attr) + try: + _module = self._resolve() + except ImportError: + raise AttributeError(attr) + value = getattr(_module, attr) + setattr(self, attr, value) + return value + + +class _LazyModule(types.ModuleType): + + def __init__(self, name): + super(_LazyModule, self).__init__(name) + self.__doc__ = self.__class__.__doc__ + + def __dir__(self): + attrs = ["__doc__", "__name__"] + attrs += [attr.name for attr in self._moved_attributes] + return attrs + + # Subclasses should override this + _moved_attributes = [] + + +class MovedAttribute(_LazyDescr): + + def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): + super(MovedAttribute, self).__init__(name) + if PY3: + if new_mod is None: + new_mod = name + self.mod = new_mod + if new_attr is None: + if old_attr is None: + new_attr = name + else: + new_attr = old_attr + self.attr = new_attr + else: + self.mod = old_mod + if old_attr is None: + old_attr = name + self.attr = old_attr + + def _resolve(self): + module = _import_module(self.mod) + return getattr(module, self.attr) + + + +class _MovedItems(_LazyModule): + """Lazy loading of moved objects""" + + +_moved_attributes = [ + MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), + MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), + MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), + MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), + MovedAttribute("map", "itertools", "builtins", "imap", "map"), + MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("reload_module", "__builtin__", "imp", "reload"), + MovedAttribute("reduce", "__builtin__", "functools"), + MovedAttribute("StringIO", "StringIO", "io"), + MovedAttribute("UserString", "UserString", "collections"), + MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), + MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), + + MovedModule("builtins", "__builtin__"), + MovedModule("configparser", "ConfigParser"), + MovedModule("copyreg", "copy_reg"), + MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), + MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), + MovedModule("http_cookies", "Cookie", "http.cookies"), + MovedModule("html_entities", "htmlentitydefs", "html.entities"), + MovedModule("html_parser", "HTMLParser", "html.parser"), + MovedModule("http_client", "httplib", "http.client"), + MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), + MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), + MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), + MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), + MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), + MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), + MovedModule("cPickle", "cPickle", "pickle"), + MovedModule("queue", "Queue"), + MovedModule("reprlib", "repr"), + MovedModule("socketserver", "SocketServer"), + MovedModule("_thread", "thread", "_thread"), + MovedModule("tkinter", "Tkinter"), + MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), + MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), + MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), + MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), + MovedModule("tkinter_tix", "Tix", "tkinter.tix"), + MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), + MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), + MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), + MovedModule("tkinter_colorchooser", "tkColorChooser", + "tkinter.colorchooser"), + MovedModule("tkinter_commondialog", "tkCommonDialog", + "tkinter.commondialog"), + MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), + MovedModule("tkinter_font", "tkFont", "tkinter.font"), + MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), + MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", + "tkinter.simpledialog"), + MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), + MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), + MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), + MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), + MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), + MovedModule("xmlrpc_server", "xmlrpclib", "xmlrpc.server"), + MovedModule("winreg", "_winreg"), +] +for attr in _moved_attributes: + setattr(_MovedItems, attr.name, attr) + if isinstance(attr, MovedModule): + sys.modules[__name__ + ".moves." + attr.name] = attr +del attr + +_MovedItems._moved_attributes = _moved_attributes + +moves = sys.modules[__name__ + ".moves"] = _MovedItems(__name__ + ".moves") + + +class Module_six_moves_urllib_parse(_LazyModule): + """Lazy loading of moved objects in six.moves.urllib_parse""" + + +_urllib_parse_moved_attributes = [ + MovedAttribute("ParseResult", "urlparse", "urllib.parse"), + MovedAttribute("SplitResult", "urlparse", "urllib.parse"), + MovedAttribute("parse_qs", "urlparse", "urllib.parse"), + MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), + MovedAttribute("urldefrag", "urlparse", "urllib.parse"), + MovedAttribute("urljoin", "urlparse", "urllib.parse"), + MovedAttribute("urlparse", "urlparse", "urllib.parse"), + MovedAttribute("urlsplit", "urlparse", "urllib.parse"), + MovedAttribute("urlunparse", "urlparse", "urllib.parse"), + MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), + MovedAttribute("quote", "urllib", "urllib.parse"), + MovedAttribute("quote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote", "urllib", "urllib.parse"), + MovedAttribute("unquote_plus", "urllib", "urllib.parse"), + MovedAttribute("urlencode", "urllib", "urllib.parse"), + MovedAttribute("splitquery", "urllib", "urllib.parse"), +] +for attr in _urllib_parse_moved_attributes: + setattr(Module_six_moves_urllib_parse, attr.name, attr) +del attr + +Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes + +sys.modules[__name__ + ".moves.urllib_parse"] = sys.modules[__name__ + ".moves.urllib.parse"] = Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse") + + +class Module_six_moves_urllib_error(_LazyModule): + """Lazy loading of moved objects in six.moves.urllib_error""" + + +_urllib_error_moved_attributes = [ + MovedAttribute("URLError", "urllib2", "urllib.error"), + MovedAttribute("HTTPError", "urllib2", "urllib.error"), + MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), +] +for attr in _urllib_error_moved_attributes: + setattr(Module_six_moves_urllib_error, attr.name, attr) +del attr + +Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes + +sys.modules[__name__ + ".moves.urllib_error"] = sys.modules[__name__ + ".moves.urllib.error"] = Module_six_moves_urllib_error(__name__ + ".moves.urllib.error") + + +class Module_six_moves_urllib_request(_LazyModule): + """Lazy loading of moved objects in six.moves.urllib_request""" + + +_urllib_request_moved_attributes = [ + MovedAttribute("urlopen", "urllib2", "urllib.request"), + MovedAttribute("install_opener", "urllib2", "urllib.request"), + MovedAttribute("build_opener", "urllib2", "urllib.request"), + MovedAttribute("pathname2url", "urllib", "urllib.request"), + MovedAttribute("url2pathname", "urllib", "urllib.request"), + MovedAttribute("getproxies", "urllib", "urllib.request"), + MovedAttribute("Request", "urllib2", "urllib.request"), + MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), + MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), + MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), + MovedAttribute("BaseHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), + MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), + MovedAttribute("FileHandler", "urllib2", "urllib.request"), + MovedAttribute("FTPHandler", "urllib2", "urllib.request"), + MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), + MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), + MovedAttribute("urlretrieve", "urllib", "urllib.request"), + MovedAttribute("urlcleanup", "urllib", "urllib.request"), + MovedAttribute("URLopener", "urllib", "urllib.request"), + MovedAttribute("FancyURLopener", "urllib", "urllib.request"), + MovedAttribute("proxy_bypass", "urllib", "urllib.request"), +] +for attr in _urllib_request_moved_attributes: + setattr(Module_six_moves_urllib_request, attr.name, attr) +del attr + +Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes + +sys.modules[__name__ + ".moves.urllib_request"] = sys.modules[__name__ + ".moves.urllib.request"] = Module_six_moves_urllib_request(__name__ + ".moves.urllib.request") + + +class Module_six_moves_urllib_response(_LazyModule): + """Lazy loading of moved objects in six.moves.urllib_response""" + + +_urllib_response_moved_attributes = [ + MovedAttribute("addbase", "urllib", "urllib.response"), + MovedAttribute("addclosehook", "urllib", "urllib.response"), + MovedAttribute("addinfo", "urllib", "urllib.response"), + MovedAttribute("addinfourl", "urllib", "urllib.response"), +] +for attr in _urllib_response_moved_attributes: + setattr(Module_six_moves_urllib_response, attr.name, attr) +del attr + +Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes + +sys.modules[__name__ + ".moves.urllib_response"] = sys.modules[__name__ + ".moves.urllib.response"] = Module_six_moves_urllib_response(__name__ + ".moves.urllib.response") + + +class Module_six_moves_urllib_robotparser(_LazyModule): + """Lazy loading of moved objects in six.moves.urllib_robotparser""" + + +_urllib_robotparser_moved_attributes = [ + MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), +] +for attr in _urllib_robotparser_moved_attributes: + setattr(Module_six_moves_urllib_robotparser, attr.name, attr) +del attr + +Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes + +sys.modules[__name__ + ".moves.urllib_robotparser"] = sys.modules[__name__ + ".moves.urllib.robotparser"] = Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser") + + +class Module_six_moves_urllib(types.ModuleType): + """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" + parse = sys.modules[__name__ + ".moves.urllib_parse"] + error = sys.modules[__name__ + ".moves.urllib_error"] + request = sys.modules[__name__ + ".moves.urllib_request"] + response = sys.modules[__name__ + ".moves.urllib_response"] + robotparser = sys.modules[__name__ + ".moves.urllib_robotparser"] + + def __dir__(self): + return ['parse', 'error', 'request', 'response', 'robotparser'] + + +sys.modules[__name__ + ".moves.urllib"] = Module_six_moves_urllib(__name__ + ".moves.urllib") + + +def add_move(move): + """Add an item to six.moves.""" + setattr(_MovedItems, move.name, move) + + +def remove_move(name): + """Remove item from six.moves.""" + try: + delattr(_MovedItems, name) + except AttributeError: + try: + del moves.__dict__[name] + except KeyError: + raise AttributeError("no such move, %r" % (name,)) + + +if PY3: + _meth_func = "__func__" + _meth_self = "__self__" + + _func_closure = "__closure__" + _func_code = "__code__" + _func_defaults = "__defaults__" + _func_globals = "__globals__" + + _iterkeys = "keys" + _itervalues = "values" + _iteritems = "items" + _iterlists = "lists" +else: + _meth_func = "im_func" + _meth_self = "im_self" + + _func_closure = "func_closure" + _func_code = "func_code" + _func_defaults = "func_defaults" + _func_globals = "func_globals" + + _iterkeys = "iterkeys" + _itervalues = "itervalues" + _iteritems = "iteritems" + _iterlists = "iterlists" + + +try: + advance_iterator = next +except NameError: + def advance_iterator(it): + return it.next() +next = advance_iterator + + +try: + callable = callable +except NameError: + def callable(obj): + return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) + + +if PY3: + def get_unbound_function(unbound): + return unbound + + create_bound_method = types.MethodType + + Iterator = object +else: + def get_unbound_function(unbound): + return unbound.im_func + + def create_bound_method(func, obj): + return types.MethodType(func, obj, obj.__class__) + + class Iterator(object): + + def next(self): + return type(self).__next__(self) + + callable = callable +_add_doc(get_unbound_function, + """Get the function out of a possibly unbound function""") + + +get_method_function = operator.attrgetter(_meth_func) +get_method_self = operator.attrgetter(_meth_self) +get_function_closure = operator.attrgetter(_func_closure) +get_function_code = operator.attrgetter(_func_code) +get_function_defaults = operator.attrgetter(_func_defaults) +get_function_globals = operator.attrgetter(_func_globals) + + +def iterkeys(d, **kw): + """Return an iterator over the keys of a dictionary.""" + return iter(getattr(d, _iterkeys)(**kw)) + +def itervalues(d, **kw): + """Return an iterator over the values of a dictionary.""" + return iter(getattr(d, _itervalues)(**kw)) + +def iteritems(d, **kw): + """Return an iterator over the (key, value) pairs of a dictionary.""" + return iter(getattr(d, _iteritems)(**kw)) + +def iterlists(d, **kw): + """Return an iterator over the (key, [values]) pairs of a dictionary.""" + return iter(getattr(d, _iterlists)(**kw)) + + +if PY3: + def b(s): + return s.encode("latin-1") + def u(s): + return s + unichr = chr + if sys.version_info[1] <= 1: + def int2byte(i): + return bytes((i,)) + else: + # This is about 2x faster than the implementation above on 3.2+ + int2byte = operator.methodcaller("to_bytes", 1, "big") + byte2int = operator.itemgetter(0) + indexbytes = operator.getitem + iterbytes = iter + import io + StringIO = io.StringIO + BytesIO = io.BytesIO +else: + def b(s): + return s + # Workaround for standalone backslash + def u(s): + return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") + unichr = unichr + int2byte = chr + def byte2int(bs): + return ord(bs[0]) + def indexbytes(buf, i): + return ord(buf[i]) + def iterbytes(buf): + return (ord(byte) for byte in buf) + import StringIO + StringIO = BytesIO = StringIO.StringIO +_add_doc(b, """Byte literal""") +_add_doc(u, """Text literal""") + + +if PY3: + exec_ = getattr(moves.builtins, "exec") + + + def reraise(tp, value, tb=None): + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + +else: + def exec_(_code_, _globs_=None, _locs_=None): + """Execute code in a namespace.""" + if _globs_ is None: + frame = sys._getframe(1) + _globs_ = frame.f_globals + if _locs_ is None: + _locs_ = frame.f_locals + del frame + elif _locs_ is None: + _locs_ = _globs_ + exec("""exec _code_ in _globs_, _locs_""") + + + exec_("""def reraise(tp, value, tb=None): + raise tp, value, tb +""") + + +print_ = getattr(moves.builtins, "print", None) +if print_ is None: + def print_(*args, **kwargs): + """The new-style print function for Python 2.4 and 2.5.""" + fp = kwargs.pop("file", sys.stdout) + if fp is None: + return + def write(data): + if not isinstance(data, basestring): + data = str(data) + # If the file has an encoding, encode unicode with it. + if (isinstance(fp, file) and + isinstance(data, unicode) and + fp.encoding is not None): + errors = getattr(fp, "errors", None) + if errors is None: + errors = "strict" + data = data.encode(fp.encoding, errors) + fp.write(data) + want_unicode = False + sep = kwargs.pop("sep", None) + if sep is not None: + if isinstance(sep, unicode): + want_unicode = True + elif not isinstance(sep, str): + raise TypeError("sep must be None or a string") + end = kwargs.pop("end", None) + if end is not None: + if isinstance(end, unicode): + want_unicode = True + elif not isinstance(end, str): + raise TypeError("end must be None or a string") + if kwargs: + raise TypeError("invalid keyword arguments to print()") + if not want_unicode: + for arg in args: + if isinstance(arg, unicode): + want_unicode = True + break + if want_unicode: + newline = unicode("\n") + space = unicode(" ") + else: + newline = "\n" + space = " " + if sep is None: + sep = space + if end is None: + end = newline + for i, arg in enumerate(args): + if i: + write(sep) + write(arg) + write(end) + +_add_doc(reraise, """Reraise an exception.""") + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + return meta("NewBase", bases, {}) + +def add_metaclass(metaclass): + """Class decorator for creating a class with a metaclass.""" + def wrapper(cls): + orig_vars = cls.__dict__.copy() + orig_vars.pop('__dict__', None) + orig_vars.pop('__weakref__', None) + slots = orig_vars.get('__slots__') + if slots is not None: + if isinstance(slots, str): + slots = [slots] + for slots_var in slots: + orig_vars.pop(slots_var) + return metaclass(cls.__name__, cls.__bases__, orig_vars) + return wrapper diff --git a/src/engine/SCons/compat/sixTests.py b/src/engine/SCons/compat/sixTests.py new file mode 100644 index 0000000..f8c1979 --- /dev/null +++ b/src/engine/SCons/compat/sixTests.py @@ -0,0 +1,34 @@ +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# 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. +# + +import unittest + +class sixTestCase(unittest.TestCase): + + def test_import(self): + """Test that six imports correctly.""" + import sys + print sys.path + from SCons.compat.six import PY2, PY3 + self.assertTrue(PY2 or PY3) + diff --git a/src/script/sconsign.py b/src/script/sconsign.py index e99a741..9f75e3a 100644 --- a/src/script/sconsign.py +++ b/src/script/sconsign.py @@ -24,7 +24,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from __future__ import print_function -from six import PY2, PY3 +from SCons.compat.six import PY2, PY3 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -85,7 +85,7 @@ try: except ImportError: pass else: - # when running from an egg add the egg's directory + # when running from an egg add the egg's directory try: d = pkg_resources.get_distribution('scons') except pkg_resources.DistributionNotFound: diff --git a/test/option/profile.py b/test/option/profile.py index 97f84db..f408136 100644 --- a/test/option/profile.py +++ b/test/option/profile.py @@ -21,7 +21,7 @@ # 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 six import u +from SCons.compat.six import u __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -113,7 +113,7 @@ memory_lines = [l for l in lines if l.find(expect) != -1] test.fail_test(len(memory_lines) != 1) - + test.pass_test() -- cgit v0.12 From 98bb69c7c9e13ea57ae7e6e8db4740a4dd43ed16 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 25 Feb 2015 21:02:49 -0800 Subject: remove extra parens causing syntax error --- src/engine/SCons/Script/Main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index 3ef88c7..556ddd3 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -373,7 +373,7 @@ class CleanTask(SCons.Taskmaster.AlwaysTask): # the file not existing. In either case, print a # message and keep going to try to remove as many # targets aa possible. - print(("scons: Could not remove '%s':" % str(t), e.strerror) + print("scons: Could not remove '%s':" % str(t), e.strerror) else: if removed: display("Removed " + str(t)) -- cgit v0.12 From 70545358cf838a2142ec39c925bcde00ebff72f6 Mon Sep 17 00:00:00 2001 From: hhsprings Date: Fri, 13 Mar 2015 23:02:05 +0900 Subject: =?UTF-8?q?This=20patch=20is=20not=20for=20Python=202.7,=20but=20f?= =?UTF-8?q?or=20`Microsoft=20Visual=20C++=20Compiler=20for=20Python=202.7'?= =?UTF-8?q?.=20Althouh=20maintainers=20claims=20`This=20will=20be=20the=20?= =?UTF-8?q?last=20release=20to=20support=20Python=20versions=20earlier=20t?= =?UTF-8?q?han=202.7,=20as=20we=20begin=20to=20move=20toward=20supporting?= =?UTF-8?q?=20Python=203.`,=20that=E2=80=99s=20not=20the=20same=20as=20sup?= =?UTF-8?q?porting=20compiler.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/engine/SCons/Tool/MSCommon/common.py | 4 +- src/engine/SCons/Tool/MSCommon/vc.py | 84 ++++++++++++++++++++------------ 2 files changed, 55 insertions(+), 33 deletions(-) diff --git a/src/engine/SCons/Tool/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py index ccfe739..9549a66 100644 --- a/src/engine/SCons/Tool/MSCommon/common.py +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -84,8 +84,8 @@ def is_win64(): return _is_win64 -def read_reg(value): - return SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, value)[0] +def read_reg(value, hkroot=SCons.Util.HKEY_LOCAL_MACHINE): + return SCons.Util.RegGetValue(hkroot, value)[0] def has_reg(value): """Return True if the given key exists in HKEY_LOCAL_MACHINE, False diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index 97cb349..71117cd 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -35,6 +35,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" __doc__ = """Module for Visual C/C++ detection and configuration. """ import SCons.compat +import SCons.Util import os import platform @@ -137,32 +138,46 @@ def get_host_target(env): _VCVER = ["12.0", "12.0Exp", "11.0", "11.0Exp", "10.0", "10.0Exp", "9.0", "9.0Exp","8.0", "8.0Exp","7.1", "7.0", "6.0"] _VCVER_TO_PRODUCT_DIR = { - '12.0' : [ - r'Microsoft\VisualStudio\12.0\Setup\VC\ProductDir'], - '12.0Exp' : [ - r'Microsoft\VCExpress\12.0\Setup\VC\ProductDir'], - '11.0': [ - r'Microsoft\VisualStudio\11.0\Setup\VC\ProductDir'], - '11.0Exp' : [ - r'Microsoft\VCExpress\11.0\Setup\VC\ProductDir'], - '10.0': [ - r'Microsoft\VisualStudio\10.0\Setup\VC\ProductDir'], - '10.0Exp' : [ - r'Microsoft\VCExpress\10.0\Setup\VC\ProductDir'], - '9.0': [ - r'Microsoft\VisualStudio\9.0\Setup\VC\ProductDir'], - '9.0Exp' : [ - r'Microsoft\VCExpress\9.0\Setup\VC\ProductDir'], - '8.0': [ - r'Microsoft\VisualStudio\8.0\Setup\VC\ProductDir'], - '8.0Exp': [ - r'Microsoft\VCExpress\8.0\Setup\VC\ProductDir'], - '7.1': [ - r'Microsoft\VisualStudio\7.1\Setup\VC\ProductDir'], - '7.0': [ - r'Microsoft\VisualStudio\7.0\Setup\VC\ProductDir'], - '6.0': [ - r'Microsoft\VisualStudio\6.0\Setup\Microsoft Visual C++\ProductDir'] + '12.0' : [ + (SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\12.0\Setup\VC\ProductDir'), + ], + '12.0Exp' : [ + (SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VCExpress\12.0\Setup\VC\ProductDir'), + ], + '11.0': [ + (SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\11.0\Setup\VC\ProductDir'), + ], + '11.0Exp' : [ + (SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VCExpress\11.0\Setup\VC\ProductDir'), + ], + '10.0': [ + (SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\10.0\Setup\VC\ProductDir'), + ], + '10.0Exp' : [ + (SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VCExpress\10.0\Setup\VC\ProductDir'), + ], + '9.0': [ + (SCons.Util.HKEY_CURRENT_USER, r'Microsoft\DevDiv\VCForPython\9.0\installdir',), + (SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\9.0\Setup\VC\ProductDir',), + ], + '9.0Exp' : [ + (SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VCExpress\9.0\Setup\VC\ProductDir'), + ], + '8.0': [ + (SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\8.0\Setup\VC\ProductDir'), + ], + '8.0Exp': [ + (SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VCExpress\8.0\Setup\VC\ProductDir'), + ], + '7.1': [ + (SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\7.1\Setup\VC\ProductDir'), + ], + '7.0': [ + (SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\7.0\Setup\VC\ProductDir'), + ], + '6.0': [ + (SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\6.0\Setup\Microsoft Visual C++\ProductDir'), + ] } def msvc_version_to_maj_min(msvc_version): @@ -212,18 +227,25 @@ def find_vc_pdir(msvc_version): If for some reason the requested version could not be found, an exception which inherits from VisualCException will be raised.""" root = 'Software\\' - if common.is_win64(): - root = root + 'Wow6432Node\\' try: hkeys = _VCVER_TO_PRODUCT_DIR[msvc_version] except KeyError: debug("Unknown version of MSVC: %s" % msvc_version) raise UnsupportedVersion("Unknown version %s" % msvc_version) - for key in hkeys: - key = root + key + for hkroot, key in hkeys: try: - comps = common.read_reg(key) + comps = None + if common.is_win64(): + try: + # ordinally at win64, try Wow6432Node first. + comps = common.read_reg(root + 'Wow6432Node\\' + key, hkroot) + except WindowsError, e: + # at Microsoft Visual Studio for Python 2.7, value is not in Wow6432Node + pass + if not comps: + # not Win64, or Microsoft Visual Studio for Python 2.7 + comps = common.read_reg(root + key, hkroot) except WindowsError, e: debug('find_vc_dir(): no VC registry key %s' % repr(key)) else: -- cgit v0.12 From 7e15cea215477c4eb495be1e8459e7eacd02b235 Mon Sep 17 00:00:00 2001 From: William Roberts Date: Tue, 17 Mar 2015 14:26:53 -0700 Subject: bug 2831: Allow appending Help text to Options Output http://scons.tigris.org/issues/show_bug.cgi?id=2831 In order to append, rather than clobber Help() generated text, use Help("my message", append=True) The append argument is only respected on the first call to this method as it operates on global data. --- src/CHANGES.txt | 3 +++ src/engine/SCons/Script/Main.py | 3 +++ src/engine/SCons/Script/SConscript.py | 4 ++-- src/engine/SCons/Script/__init__.py | 15 ++++++++++++--- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 55b48a5..cd98f12 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -6,6 +6,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER + From William Roberts: + - Fix bug 2831 and allow Help() text to be appended to AddOption() help. + From Russel Winder: - Add support for f08 file extensions for Fortran 2008 code. diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index c7a9d27..4ccd2b3 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -484,6 +484,9 @@ def GetOption(name): def SetOption(name, value): return OptionsParser.values.set_option(name, value) +def PrintHelp(file=None): + OptionsParser.print_help(file=file) + # class Stats(object): def __init__(self): diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py index f4a7f07..3502534 100644 --- a/src/engine/SCons/Script/SConscript.py +++ b/src/engine/SCons/Script/SConscript.py @@ -499,9 +499,9 @@ class SConsEnvironment(SCons.Environment.Base): name = self.subst(name) return SCons.Script.Main.GetOption(name) - def Help(self, text): + def Help(self, text, append=False): text = self.subst(text, raw=1) - SCons.Script.HelpFunction(text) + SCons.Script.HelpFunction(text, append=append) def Import(self, *vars): try: diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py index bb7b632..a9d7708 100644 --- a/src/engine/SCons/Script/__init__.py +++ b/src/engine/SCons/Script/__init__.py @@ -41,6 +41,7 @@ start_time = time.time() import collections import os +import StringIO import sys # Special chicken-and-egg handling of the "--debug=memoizer" flag: @@ -107,6 +108,7 @@ QuestionTask = Main.QuestionTask #SConscriptSettableOptions = Main.SConscriptSettableOptions AddOption = Main.AddOption +PrintHelp = Main.PrintHelp GetOption = Main.GetOption SetOption = Main.SetOption Progress = Main.Progress @@ -258,10 +260,17 @@ def _Set_Default_Targets(env, tlist): # help_text = None -def HelpFunction(text): +def HelpFunction(text, append=False): global help_text - if SCons.Script.help_text is None: - SCons.Script.help_text = text + if help_text is None: + if append: + s = StringIO.StringIO() + PrintHelp(s) + help_text = s.getvalue() + s.close() + else: + help_text = "" + help_text = help_text + "\nLocal Build Variables:\n" + text else: help_text = help_text + text -- cgit v0.12 From 654e4414d80324b2a4c2edf3c685a38feec514f6 Mon Sep 17 00:00:00 2001 From: William Blevins Date: Wed, 13 May 2015 00:06:05 -0400 Subject: Issue 2264: Added SWIG recursive dependency tests. --- QMTest/TestCommon.py | 32 ++++++++++ test/SWIG/recursive-includes-cpp.py | 123 ++++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 test/SWIG/recursive-includes-cpp.py diff --git a/QMTest/TestCommon.py b/QMTest/TestCommon.py index 4e90e16..275d4f2 100644 --- a/QMTest/TestCommon.py +++ b/QMTest/TestCommon.py @@ -36,6 +36,8 @@ provided by the TestCommon class: test.must_contain('file', 'required text\n') + test.must_contain_all(output, lines, ['title', find]) + test.must_contain_all_lines(output, lines, ['title', find]) test.must_contain_any_line(output, lines, ['title', find]) @@ -305,6 +307,36 @@ class TestCommon(TestCmd): print file_contents self.fail_test(not contains) + def must_contain_all(self, output, input, title=None, find=None): + """Ensures that the specified output string (first argument) + contains all of the specified input as a block (second argument). + + An optional third argument can be used to describe the type + of output being searched, and only shows up in failure output. + + An optional fourth argument can be used to supply a different + function, of the form "find(line, output), to use when searching + for lines in the output. + """ + if find is None: + def find(o, i): + try: + return o.index(i) + except ValueError: + return None + + if is_List(output): + output = os.newline.join(output) + + if find(output, input) is None: + if title is None: + title = 'output' + print 'Missing expected input from %s:' % title + print input + print self.banner(title + ' ') + print output + self.fail_test() + def must_contain_all_lines(self, output, lines, title=None, find=None): """Ensures that the specified output string (first argument) contains all of the specified lines (second argument). diff --git a/test/SWIG/recursive-includes-cpp.py b/test/SWIG/recursive-includes-cpp.py new file mode 100644 index 0000000..364bd73 --- /dev/null +++ b/test/SWIG/recursive-includes-cpp.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# 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. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that SWIG include directives produce the correct dependencies +in cases of recursive inclusion. +""" + +import os +import TestSCons +from SCons.Defaults import DefaultEnvironment + +DefaultEnvironment( tools = [ 'swig' ] ) + +test = TestSCons.TestSCons() + +# Check for prerequisites of this test. +for pre_req in ['swig', 'python']: + if not test.where_is(pre_req): + test.skip_test('Can not find installed "' + pre_req + '", skipping test.%s' % os.linesep) + +test.write("recursive.h", """\ +/* An empty header file. */ +""") + +test.write("main.h", """\ +#include "recursive.h" +""") + +test.write("main.c", """\ +#include "main.h" +""") + +test.write("mod.i", """\ +%module mod + +%include "main.h" + +#include "main.h" +""") + +test.write('SConstruct', """\ +import distutils.sysconfig + +DefaultEnvironment( tools = [ 'swig' ] ) + +env = Environment( + SWIGFLAGS = [ + '-python' + ], + CPPPATH = [ + distutils.sysconfig.get_python_inc() + ], + SHLIBPREFIX = "" +) + +env.SharedLibrary( + 'mod.so', + [ + "mod.i", + "main.c", + ] +) +""") + +expectMain = """\ ++-main.os + +-main.c + +-main.h + +-recursive.h""" + +expectMod = """\ ++-mod_wrap.os + +-mod_wrap.c + | +-mod.i + | +-main.h + | +-recursive.h""" + +# Validate that the recursive dependencies are found with SWIG scanning first. +test.run( arguments = '--tree=all mod_wrap.os main.os' ) + +test.must_contain_all( test.stdout(), expectMain ) +test.must_contain_all( test.stdout(), expectMod ) + +# Validate that the recursive dependencies are found consistently. +test.run( arguments = '--tree=all main.os mod_wrap.os' ) + +test.must_contain_all( test.stdout(), expectMain ) +test.must_contain_all( test.stdout(), expectMod ) + +test.run() +test.up_to_date() + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From 6af468c642134c73c70820b17cad562c35785fdd Mon Sep 17 00:00:00 2001 From: Andrew Featherstone Date: Fri, 15 May 2015 21:02:10 +0100 Subject: Corrects comparison of actions from different environments. --- src/engine/SCons/Builder.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py index c82f6ac..4e8aee9 100644 --- a/src/engine/SCons/Builder.py +++ b/src/engine/SCons/Builder.py @@ -292,8 +292,8 @@ def _node_errors(builder, env, tlist, slist): if t.has_explicit_builder(): if not t.env is None and not t.env is env: action = t.builder.action - t_contents = action.get_contents(tlist, slist, t.env) - contents = action.get_contents(tlist, slist, env) + t_contents = t.builder.action.get_contents(tlist, slist, t.env) + contents = builder.action.get_contents(tlist, slist, env) if t_contents == contents: msg = "Two different environments were specified for target %s,\n\tbut they appear to have the same action: %s" % (t, action.genstring(tlist, slist, t.env)) -- cgit v0.12 From b27b2316842dfa291feef332c80f676fd097d809 Mon Sep 17 00:00:00 2001 From: William Blevins Date: Sun, 17 May 2015 19:57:44 -0400 Subject: Issue 2264: Added cross-language scanner support. --- src/engine/SCons/Defaults.py | 2 +- src/engine/SCons/Executor.py | 26 ++++++---------------- src/engine/SCons/Node/__init__.py | 26 +++++++++++++--------- src/engine/SCons/Scanner/SWIG.py | 45 +++++++++++++++++++++++++++++++++++++++ src/engine/SCons/Tool/__init__.py | 7 ++++++ src/engine/SCons/Tool/swig.py | 6 ------ 6 files changed, 75 insertions(+), 37 deletions(-) create mode 100644 src/engine/SCons/Scanner/SWIG.py diff --git a/src/engine/SCons/Defaults.py b/src/engine/SCons/Defaults.py index 6500443..3e37fa5 100644 --- a/src/engine/SCons/Defaults.py +++ b/src/engine/SCons/Defaults.py @@ -484,7 +484,7 @@ class Variable_Method_Caller(object): ConstructionEnvironment = { 'BUILDERS' : {}, - 'SCANNERS' : [], + 'SCANNERS' : [ SCons.Tool.SourceFileScanner ], 'CONFIGUREDIR' : '#/.sconf_temp', 'CONFIGURELOG' : '#/config.log', 'CPPSUFFIXES' : SCons.Tool.CSuffixes, diff --git a/src/engine/SCons/Executor.py b/src/engine/SCons/Executor.py index 98ed758..59e57e3 100644 --- a/src/engine/SCons/Executor.py +++ b/src/engine/SCons/Executor.py @@ -486,29 +486,15 @@ class Executor(object): each individual target, which is a hell of a lot more efficient. """ env = self.get_build_env() + path = self.get_build_scanner_path + kw = self.get_kw() # TODO(batch): scan by batches) deps = [] - if scanner: - for node in node_list: - node.disambiguate() - s = scanner.select(node) - if not s: - continue - path = self.get_build_scanner_path(s) - deps.extend(node.get_implicit_deps(env, s, path)) - else: - kw = self.get_kw() - for node in node_list: - node.disambiguate() - scanner = node.get_env_scanner(env, kw) - if not scanner: - continue - scanner = scanner.select(node) - if not scanner: - continue - path = self.get_build_scanner_path(scanner) - deps.extend(node.get_implicit_deps(env, scanner, path)) + + for node in node_list: + node.disambiguate() + deps.extend(node.get_implicit_deps(env, scanner, path, kw)) deps.extend(self.get_implicit_deps()) diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index f2d37c2..5721442 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -916,32 +916,38 @@ class Node(object): """ return [] - def get_implicit_deps(self, env, scanner, path): + def get_implicit_deps(self, env, scanner, path, kw = {}): """Return a list of implicit dependencies for this node. This method exists to handle recursive invocation of the scanner on the implicit dependencies returned by the scanner, if the scanner's recursive flag says that we should. """ - if not scanner: - return [] - - # Give the scanner a chance to select a more specific scanner - # for this Node. - #scanner = scanner.select(self) - nodes = [self] seen = {} seen[self] = 1 deps = [] while nodes: n = nodes.pop(0) - d = [x for x in n.get_found_includes(env, scanner, path) if x not in seen] + + if not scanner: + s = n.get_env_scanner(env, kw) + if s: + s = s.select(n) + else: + s = scanner.select(n) + + if not s: + continue + + p = path(s) + + d = [x for x in n.get_found_includes(env, s, p) if x not in seen] if d: deps.extend(d) for n in d: seen[n] = 1 - nodes.extend(scanner.recurse_nodes(d)) + nodes.extend(s.recurse_nodes(d)) return deps diff --git a/src/engine/SCons/Scanner/SWIG.py b/src/engine/SCons/Scanner/SWIG.py new file mode 100644 index 0000000..2650e4b --- /dev/null +++ b/src/engine/SCons/Scanner/SWIG.py @@ -0,0 +1,45 @@ +"""SCons.Scanner.SWIG + +This module implements the dependency scanner for SWIG code. + +""" + +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# 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. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import SCons.Scanner + +SWIGSuffixes = [ '.i' ] + +def SWIGScanner(): + expr = '^[ \t]*%[ \t]*(?:include|import|extern)[ \t]*(<|"?)([^>\s"]+)(?:>|"?)' + scanner = SCons.Scanner.ClassicCPP("SWIGScanner", ".i", "SWIGPATH", expr) + return scanner + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index efd2e33..6002d72 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -51,6 +51,7 @@ import SCons.Scanner.C import SCons.Scanner.D import SCons.Scanner.LaTeX import SCons.Scanner.Prog +import SCons.Scanner.SWIG DefaultToolpath=[] @@ -60,6 +61,7 @@ LaTeXScanner = SCons.Scanner.LaTeX.LaTeXScanner() PDFLaTeXScanner = SCons.Scanner.LaTeX.PDFLaTeXScanner() ProgramScanner = SCons.Scanner.Prog.ProgramScanner() SourceFileScanner = SCons.Scanner.Base({}, name='SourceFileScanner') +SWIGScanner = SCons.Scanner.SWIG.SWIGScanner() CSuffixes = [".c", ".C", ".cxx", ".cpp", ".c++", ".cc", ".h", ".H", ".hxx", ".hpp", ".hh", @@ -73,12 +75,17 @@ IDLSuffixes = [".idl", ".IDL"] LaTeXSuffixes = [".tex", ".ltx", ".latex"] +SWIGSuffixes = ['.i'] + for suffix in CSuffixes: SourceFileScanner.add_scanner(suffix, CScanner) for suffix in DSuffixes: SourceFileScanner.add_scanner(suffix, DScanner) +for suffix in SWIGSuffixes: + SourceFileScanner.add_scanner(suffix, SWIGScanner) + # FIXME: what should be done here? Two scanners scan the same extensions, # but look for different files, e.g., "picture.eps" vs. "picture.pdf". # The builders for DVI and PDF explicitly reference their scanners diff --git a/src/engine/SCons/Tool/swig.py b/src/engine/SCons/Tool/swig.py index a315182..959d5fe 100644 --- a/src/engine/SCons/Tool/swig.py +++ b/src/engine/SCons/Tool/swig.py @@ -39,7 +39,6 @@ import subprocess import SCons.Action import SCons.Defaults -import SCons.Scanner import SCons.Tool import SCons.Util import SCons.Node @@ -173,11 +172,6 @@ def generate(env): env['_SWIGINCFLAGS'] = '$( ${_concat(SWIGINCPREFIX, SWIGPATH, SWIGINCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' env['SWIGCOM'] = '$SWIG -o $TARGET ${_SWIGOUTDIR} ${_SWIGINCFLAGS} $SWIGFLAGS $SOURCES' - expr = '^[ \t]*%[ \t]*(?:include|import|extern)[ \t]*(<|"?)([^>\s"]+)(?:>|"?)' - scanner = SCons.Scanner.ClassicCPP("SWIGScan", ".i", "SWIGPATH", expr) - - env.Append(SCANNERS = scanner) - def exists(env): swig = env.get('SWIG') or env.Detect(['swig']) return swig -- cgit v0.12 From 279caec8f29b92cc569be83eb7b0c7a271136ad4 Mon Sep 17 00:00:00 2001 From: William Blevins Date: Sun, 17 May 2015 23:38:23 -0400 Subject: Issue 2264: Updated tests to reflect Node changes. --- src/engine/SCons/ExecutorTests.py | 4 ++- src/engine/SCons/Node/NodeTests.py | 19 ++++++++----- test/Fortran/FORTRANSUFFIXES.py | 56 +++++++++++++++++++------------------- test/QT/manual.py | 6 ++-- test/Scanner/exception.py | 14 +++++----- test/Scanner/generated.py | 1 + 6 files changed, 55 insertions(+), 45 deletions(-) diff --git a/src/engine/SCons/ExecutorTests.py b/src/engine/SCons/ExecutorTests.py index 9df0b2d..f390319 100644 --- a/src/engine/SCons/ExecutorTests.py +++ b/src/engine/SCons/ExecutorTests.py @@ -83,7 +83,9 @@ class MyNode(object): executor(self) def get_env_scanner(self, env, kw): return MyScanner('dep-') - def get_implicit_deps(self, env, scanner, path): + def get_implicit_deps(self, env, scanner, path, kw={}): + if not scanner: + scanner = self.get_env_scanner(env, kw) return [scanner.prefix + str(self)] def add_to_implicit(self, deps): self.implicit.extend(deps) diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index a6471b4..4639cf9 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -132,7 +132,12 @@ class Environment(object): def get_factory(self, factory): return factory or MyNode def get_scanner(self, scanner_key): - return self._dict['SCANNERS'][0] + try: + return self._dict['SCANNERS'][0] + except: + pass + + return [] class Builder(object): def __init__(self, env=None, is_explicit=1): @@ -185,7 +190,7 @@ class Scanner(object): def __call__(self, node): self.called = 1 return node.GetTag('found_includes') - def path(self, env, dir, target=None, source=None): + def path(self, env, dir=None, target=None, source=None, kw={}): return () def select(self, node): return self @@ -928,7 +933,7 @@ class NodeTestCase(unittest.TestCase): node.Tag('found_includes', [d1, d2]) # Simple return of the found includes - deps = node.get_implicit_deps(env, s, target) + deps = node.get_implicit_deps(env, s, s.path) assert deps == [d1, d2], deps # By default, our fake scanner recurses @@ -938,24 +943,24 @@ class NodeTestCase(unittest.TestCase): d1.Tag('found_includes', [e, f]) d2.Tag('found_includes', [e, f]) f.Tag('found_includes', [g]) - deps = node.get_implicit_deps(env, s, target) + deps = node.get_implicit_deps(env, s, s.path) assert deps == [d1, d2, e, f, g], list(map(str, deps)) # Recursive scanning eliminates duplicates e.Tag('found_includes', [f]) - deps = node.get_implicit_deps(env, s, target) + deps = node.get_implicit_deps(env, s, s.path) assert deps == [d1, d2, e, f, g], list(map(str, deps)) # Scanner method can select specific nodes to recurse def no_fff(nodes): return [n for n in nodes if str(n)[0] != 'f'] s.recurse_nodes = no_fff - deps = node.get_implicit_deps(env, s, target) + deps = node.get_implicit_deps(env, s, s.path) assert deps == [d1, d2, e, f], list(map(str, deps)) # Scanner method can short-circuit recursing entirely s.recurse_nodes = lambda nodes: [] - deps = node.get_implicit_deps(env, s, target) + deps = node.get_implicit_deps(env, s, s.path) assert deps == [d1, d2], list(map(str, deps)) def test_get_env_scanner(self): diff --git a/test/Fortran/FORTRANSUFFIXES.py b/test/Fortran/FORTRANSUFFIXES.py index 583b71b..9673e6f 100644 --- a/test/Fortran/FORTRANSUFFIXES.py +++ b/test/Fortran/FORTRANSUFFIXES.py @@ -56,51 +56,51 @@ env = Environment(FORTRANPATH = ['.'], env.Append(FORTRANSUFFIXES = ['.x']) env.Object(target = 'test1', source = 'test1.f') env.InstallAs('test1_f', 'test1.f') -env.InstallAs('test1_h', 'test1.h') env.InstallAs('test1_x', 'test1.x') +env.InstallAs('test2_f', 'test2.f') """ % locals()) test.write('test1.f', """\ test1.f 1 - INCLUDE 'test1.h' + INCLUDE 'test2.f' INCLUDE 'test1.x' """) -test.write('test1.h', """\ - test1.h 1 - INCLUDE 'foo.h' +test.write('test2.f', """\ + test2.f 1 + INCLUDE 'foo.f' """) test.write('test1.x', """\ test1.x 1 - INCLUDE 'foo.h' + INCLUDE 'foo.f' """) -test.write('foo.h', """\ - foo.h 1 +test.write('foo.f', """\ + foo.f 1 """) expect = test.wrap_stdout("""\ %(_python_)s myfc.py test1.o test1.f Install file: "test1.f" as "test1_f" -Install file: "test1.h" as "test1_h" Install file: "test1.x" as "test1_x" +Install file: "test2.f" as "test2_f" """ % locals()) test.run(arguments='.', stdout=expect) test.must_match('test1.o', """\ test1.f 1 - test1.h 1 - foo.h 1 + test2.f 1 + foo.f 1 test1.x 1 - foo.h 1 + foo.f 1 """) test.up_to_date(arguments='.') -test.write('foo.h', """\ - foo.h 2 +test.write('foo.f', """\ + foo.f 2 """) expect = test.wrap_stdout("""\ @@ -111,17 +111,17 @@ test.run(arguments='.', stdout=expect) test.must_match('test1.o', """\ test1.f 1 - test1.h 1 - foo.h 2 + test2.f 1 + foo.f 2 test1.x 1 - foo.h 2 + foo.f 2 """) test.up_to_date(arguments='.') test.write('test1.x', """\ test1.x 2 - INCLUDE 'foo.h' + INCLUDE 'foo.f' """) expect = test.wrap_stdout("""\ @@ -133,32 +133,32 @@ test.run(arguments='.', stdout=expect) test.must_match('test1.o', """\ test1.f 1 - test1.h 1 - foo.h 2 + test2.f 1 + foo.f 2 test1.x 2 - foo.h 2 + foo.f 2 """) test.up_to_date(arguments='.') -test.write('test1.h', """\ - test1.h 2 - INCLUDE 'foo.h' +test.write('test2.f', """\ + test2.f 2 + INCLUDE 'foo.f' """) expect = test.wrap_stdout("""\ %(_python_)s myfc.py test1.o test1.f -Install file: "test1.h" as "test1_h" +Install file: "test2.f" as "test2_f" """ % locals()) test.run(arguments='.', stdout=expect) test.must_match('test1.o', """\ test1.f 1 - test1.h 2 - foo.h 2 + test2.f 2 + foo.f 2 test1.x 2 - foo.h 2 + foo.f 2 """) test.up_to_date(arguments='.') diff --git a/test/QT/manual.py b/test/QT/manual.py index ff38f32..d911fb3 100644 --- a/test/QT/manual.py +++ b/test/QT/manual.py @@ -46,13 +46,15 @@ sources = ['aaa.cpp', 'bbb.cpp', 'ddd.cpp', 'eee.cpp', 'main.cpp'] # normal invocation sources.append(env.Moc('include/aaa.h')) -env.Moc('bbb.cpp') +moc = env.Moc('bbb.cpp') +env.Ignore( moc, moc ) sources.extend(env.Uic('ui/ccc.ui')[1:]) # manual target specification sources.append(env.Moc('moc-ddd.cpp', 'include/ddd.h', QT_MOCHPREFIX='')) # Watch out ! -env.Moc('moc_eee.cpp', 'eee.cpp') +moc = env.Moc('moc_eee.cpp', 'eee.cpp') +env.Ignore( moc, moc ) sources.extend(env.Uic(['include/uic_fff.hpp', 'fff.cpp', 'fff.moc.cpp'], 'ui/fff.ui')[1:]) diff --git a/test/Scanner/exception.py b/test/Scanner/exception.py index 1a14152..de0a795 100644 --- a/test/Scanner/exception.py +++ b/test/Scanner/exception.py @@ -83,23 +83,23 @@ env.Cat('bar', bar_in) test.write('foo.k', """foo.k 1 line 1 -include xxx -include yyy +include xxx.k +include yyy.k foo.k 1 line 4 """) test.write('bar.in', -"""include yyy +"""include yyy.k bar.in 1 line 2 bar.in 1 line 3 -include zzz +include zzz.k """) -test.write('xxx', "xxx 1\n") +test.write('xxx.k', "xxx 1\n") -test.write('yyy', "exception yyy 1\n") +test.write('yyy.k', "exception yyy 1\n") -test.write('zzz', "zzz 1\n") +test.write('zzz.k', "zzz 1\n") test.run(arguments = '.', status = 2, diff --git a/test/Scanner/generated.py b/test/Scanner/generated.py index 845111c..b41c7c8 100644 --- a/test/Scanner/generated.py +++ b/test/Scanner/generated.py @@ -338,6 +338,7 @@ class CScannerCounter(object): import SCons.Tool MyCScanner = CScannerCounter(SCons.Script.CScanner) SCons.Tool.SourceFileScanner.add_scanner('.c', MyCScanner) +SCons.Tool.SourceFileScanner.add_scanner('.h', MyCScanner) env = Environment(CPPPATH = ".") l = env.StaticLibrary("g", Split("libg_1.c libg_2.c libg_3.c")) -- cgit v0.12 From 7a6c84894f9251a6c8751f18eaec50993647afa9 Mon Sep 17 00:00:00 2001 From: Dirk Baechle Date: Tue, 2 Jun 2015 13:21:23 +0200 Subject: Fixed license of SVG titlepage files, resolves #2985. This is required in the Debian packaging context, such that the images allow for commercial use too. See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=787356 for the original bug description. --- doc/design/titlepage/SConsBuildBricks_path.svg | 22 ++++++++++------------ doc/man/titlepage/SConsBuildBricks_path.svg | 22 ++++++++++------------ doc/reference/titlepage/SConsBuildBricks_path.svg | 22 ++++++++++------------ doc/user/titlepage/SConsBuildBricks_path.svg | 22 ++++++++++------------ src/CHANGES.txt | 2 ++ 5 files changed, 42 insertions(+), 48 deletions(-) diff --git a/doc/design/titlepage/SConsBuildBricks_path.svg b/doc/design/titlepage/SConsBuildBricks_path.svg index ed0c60d..0d7f63e 100644 --- a/doc/design/titlepage/SConsBuildBricks_path.svg +++ b/doc/design/titlepage/SConsBuildBricks_path.svg @@ -14,9 +14,9 @@ height="80.330002" id="svg2" sodipodi:version="0.32" - inkscape:version="0.48.1 r9760" + inkscape:version="0.48.4 r9939" version="1.0" - sodipodi:docname="SConsBuildBricks.svg" + sodipodi:docname="SConsBuildBricks_path.svg" inkscape:export-filename="Constructs-using-SCons.png" inkscape:export-xdpi="100" inkscape:export-ydpi="100"> @@ -77,24 +77,22 @@ + rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/" /> + rdf:about="http://creativecommons.org/licenses/by-sa/3.0/"> + rdf:resource="http://creativecommons.org/ns#Reproduction" /> + rdf:resource="http://creativecommons.org/ns#Distribution" /> + rdf:resource="http://creativecommons.org/ns#Notice" /> - + rdf:resource="http://creativecommons.org/ns#Attribution" /> + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> + rdf:resource="http://creativecommons.org/ns#ShareAlike" /> diff --git a/doc/man/titlepage/SConsBuildBricks_path.svg b/doc/man/titlepage/SConsBuildBricks_path.svg index ed0c60d..0d7f63e 100644 --- a/doc/man/titlepage/SConsBuildBricks_path.svg +++ b/doc/man/titlepage/SConsBuildBricks_path.svg @@ -14,9 +14,9 @@ height="80.330002" id="svg2" sodipodi:version="0.32" - inkscape:version="0.48.1 r9760" + inkscape:version="0.48.4 r9939" version="1.0" - sodipodi:docname="SConsBuildBricks.svg" + sodipodi:docname="SConsBuildBricks_path.svg" inkscape:export-filename="Constructs-using-SCons.png" inkscape:export-xdpi="100" inkscape:export-ydpi="100"> @@ -77,24 +77,22 @@ + rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/" /> + rdf:about="http://creativecommons.org/licenses/by-sa/3.0/"> + rdf:resource="http://creativecommons.org/ns#Reproduction" /> + rdf:resource="http://creativecommons.org/ns#Distribution" /> + rdf:resource="http://creativecommons.org/ns#Notice" /> - + rdf:resource="http://creativecommons.org/ns#Attribution" /> + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> + rdf:resource="http://creativecommons.org/ns#ShareAlike" /> diff --git a/doc/reference/titlepage/SConsBuildBricks_path.svg b/doc/reference/titlepage/SConsBuildBricks_path.svg index ed0c60d..0d7f63e 100644 --- a/doc/reference/titlepage/SConsBuildBricks_path.svg +++ b/doc/reference/titlepage/SConsBuildBricks_path.svg @@ -14,9 +14,9 @@ height="80.330002" id="svg2" sodipodi:version="0.32" - inkscape:version="0.48.1 r9760" + inkscape:version="0.48.4 r9939" version="1.0" - sodipodi:docname="SConsBuildBricks.svg" + sodipodi:docname="SConsBuildBricks_path.svg" inkscape:export-filename="Constructs-using-SCons.png" inkscape:export-xdpi="100" inkscape:export-ydpi="100"> @@ -77,24 +77,22 @@ + rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/" /> + rdf:about="http://creativecommons.org/licenses/by-sa/3.0/"> + rdf:resource="http://creativecommons.org/ns#Reproduction" /> + rdf:resource="http://creativecommons.org/ns#Distribution" /> + rdf:resource="http://creativecommons.org/ns#Notice" /> - + rdf:resource="http://creativecommons.org/ns#Attribution" /> + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> + rdf:resource="http://creativecommons.org/ns#ShareAlike" /> diff --git a/doc/user/titlepage/SConsBuildBricks_path.svg b/doc/user/titlepage/SConsBuildBricks_path.svg index ed0c60d..0d7f63e 100644 --- a/doc/user/titlepage/SConsBuildBricks_path.svg +++ b/doc/user/titlepage/SConsBuildBricks_path.svg @@ -14,9 +14,9 @@ height="80.330002" id="svg2" sodipodi:version="0.32" - inkscape:version="0.48.1 r9760" + inkscape:version="0.48.4 r9939" version="1.0" - sodipodi:docname="SConsBuildBricks.svg" + sodipodi:docname="SConsBuildBricks_path.svg" inkscape:export-filename="Constructs-using-SCons.png" inkscape:export-xdpi="100" inkscape:export-ydpi="100"> @@ -77,24 +77,22 @@ + rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/" /> + rdf:about="http://creativecommons.org/licenses/by-sa/3.0/"> + rdf:resource="http://creativecommons.org/ns#Reproduction" /> + rdf:resource="http://creativecommons.org/ns#Distribution" /> + rdf:resource="http://creativecommons.org/ns#Notice" /> - + rdf:resource="http://creativecommons.org/ns#Attribution" /> + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> + rdf:resource="http://creativecommons.org/ns#ShareAlike" /> diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 42108de..2a2c21f 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -25,6 +25,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER From Dirk Baechle: - Added new method rentry_exists_on_disk to Node.FS (PR #193). + - Fixed license of SVG titlepage files in the context of Debian + packaging, such that they allow for commercial use too (#2985). From Russel Winder: - Fixed several D tests under the different OS. -- cgit v0.12 From 5260437c85052289702664c6a1025202eaf7111a Mon Sep 17 00:00:00 2001 From: William Blevins Date: Mon, 29 Jun 2015 16:12:02 -0400 Subject: Issue 2264: Corrected comment description of new output validation function. --- QMTest/TestCommon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QMTest/TestCommon.py b/QMTest/TestCommon.py index 275d4f2..c4a5373 100644 --- a/QMTest/TestCommon.py +++ b/QMTest/TestCommon.py @@ -36,7 +36,7 @@ provided by the TestCommon class: test.must_contain('file', 'required text\n') - test.must_contain_all(output, lines, ['title', find]) + test.must_contain_all(output, input, ['title', find]) test.must_contain_all_lines(output, lines, ['title', find]) -- cgit v0.12 From e5ac090e378fd5cda31dd70f762ea2792eed7dc7 Mon Sep 17 00:00:00 2001 From: William Blevins Date: Mon, 29 Jun 2015 23:32:45 -0400 Subject: Issue 2264: Updated behaviour when scanning included dependencies for nodes without scanner_key mappings. --- src/engine/SCons/Node/NodeTests.py | 2 ++ src/engine/SCons/Node/__init__.py | 63 +++++++++++++++++++++++++++----------- test/Scanner/exception.py | 14 ++++----- 3 files changed, 54 insertions(+), 25 deletions(-) diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index 4639cf9..1478419 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -121,6 +121,8 @@ class Environment(object): self._dict.update(kw) def __getitem__(self, key): return self._dict[key] + def get(self, key, default = None): + return self._dict.get(key, default) def Dictionary(self, *args): return {} def Override(self, overrides): diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 5721442..64a513b 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -916,7 +916,7 @@ class Node(object): """ return [] - def get_implicit_deps(self, env, scanner, path, kw = {}): + def get_implicit_deps(self, env, initial_scanner, path_func, kw = {}): """Return a list of implicit dependencies for this node. This method exists to handle recursive invocation of the scanner @@ -926,31 +926,58 @@ class Node(object): nodes = [self] seen = {} seen[self] = 1 - deps = [] + dependencies = [] + + root_node_scanner = self._get_scanner(env, initial_scanner, None, kw) + while nodes: - n = nodes.pop(0) + node = nodes.pop(0) - if not scanner: - s = n.get_env_scanner(env, kw) - if s: - s = s.select(n) - else: - s = scanner.select(n) + scanner = node._get_scanner(env, initial_scanner, root_node_scanner, kw) - if not s: + if not scanner: continue - p = path(s) + path = path_func(scanner) - d = [x for x in n.get_found_includes(env, s, p) if x not in seen] - if d: - deps.extend(d) - for n in d: - seen[n] = 1 - nodes.extend(s.recurse_nodes(d)) + included_deps = [x for x in node.get_found_includes(env, scanner, path) if x not in seen] + if included_deps: + dependencies.extend(included_deps) + for dep in included_deps: + seen[dep] = 1 + nodes.extend(scanner.recurse_nodes(included_deps)) - return deps + return dependencies + def _get_scanner(self, env, initial_scanner, root_node_scanner, kw): + if not initial_scanner: + # handle implicit scanner case + scanner = self.get_env_scanner(env, kw) + if scanner: + scanner = scanner.select(self) + else: + # handle explicit scanner case + scanner = initial_scanner.select(self) + + if not scanner: + # no scanner could be found for the given node's scanner key; + # thus, make an attempt at using a default. + + # check for a user specified scanner hint + scanner = env.get( 'SCANNER_HINT' ) + + if scanner: + # Ensure scanner hint returned a valid Scanner object + if not instanceof( scanner, SCons.Scanner.Base ): + raise SCons.Error.UserError( + 'SCANNER_HINT object must be instance of ' + str(SCons.Scanner.Base) + ) + else: + # no scanner hint, so do best guess (IE. return the root's scanner). + scanner = root_node_scanner + + return scanner + def get_env_scanner(self, env, kw={}): return env.get_scanner(self.scanner_key()) diff --git a/test/Scanner/exception.py b/test/Scanner/exception.py index de0a795..1a14152 100644 --- a/test/Scanner/exception.py +++ b/test/Scanner/exception.py @@ -83,23 +83,23 @@ env.Cat('bar', bar_in) test.write('foo.k', """foo.k 1 line 1 -include xxx.k -include yyy.k +include xxx +include yyy foo.k 1 line 4 """) test.write('bar.in', -"""include yyy.k +"""include yyy bar.in 1 line 2 bar.in 1 line 3 -include zzz.k +include zzz """) -test.write('xxx.k', "xxx 1\n") +test.write('xxx', "xxx 1\n") -test.write('yyy.k', "exception yyy 1\n") +test.write('yyy', "exception yyy 1\n") -test.write('zzz.k', "zzz 1\n") +test.write('zzz', "zzz 1\n") test.run(arguments = '.', status = 2, -- cgit v0.12 From 829492d37c7b85e22c169e1171265abdf4841af6 Mon Sep 17 00:00:00 2001 From: William Blevins Date: Tue, 30 Jun 2015 01:12:48 -0400 Subject: Issue 2264: Added test for SCANNER_HINT support, plus bug fixes. --- src/engine/SCons/Node/__init__.py | 4 +- test/Scanner/ScannerHint.py | 119 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 test/Scanner/ScannerHint.py diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 64a513b..d709f11 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -968,8 +968,8 @@ class Node(object): if scanner: # Ensure scanner hint returned a valid Scanner object - if not instanceof( scanner, SCons.Scanner.Base ): - raise SCons.Error.UserError( + if not isinstance( scanner, SCons.Scanner.Base ): + raise SCons.Errors.UserError( 'SCANNER_HINT object must be instance of ' + str(SCons.Scanner.Base) ) else: diff --git a/test/Scanner/ScannerHint.py b/test/Scanner/ScannerHint.py new file mode 100644 index 0000000..b12b847 --- /dev/null +++ b/test/Scanner/ScannerHint.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# 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. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import TestSCons + +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons() + +# Test behavior of Scanners when evaluating implicit dependencies +# for nodes that do not have mappings from their scanner_key +# to a scanner instance + +test.write('SConstruct', """ +import re + +include_re = re.compile(r'^include\s+(\S+)$', re.M) + +def scan(node, env, scanpaths, arg): + contents = node.get_text_contents() + includes = include_re.findall(contents) + return includes + +def kfile_scan(node, env, scanpaths, arg): + print 'kscan: ' + str(node) + return scan(node, env, scanpaths, arg) + +def k2file_scan(node, env, scanpaths, arg): + print 'k2scan: ' + str(node) + return scan(node, env, scanpaths, arg) + +kscan = Scanner(name = 'kfile', + function = kfile_scan, + argument = None, + skeys = ['.k'], + recursive = True) + +k2scan = Scanner(name = 'k2', + function = k2file_scan, + argument = None, + skeys = ['.k2']) + +env1 = Environment() +env1.Append(SCANNERS = [ kscan, k2scan ] ) +env1.Command( 'k', 'foo.k', Copy( '$TARGET', '$SOURCE' ) ) + +env2 = env1.Clone() +env2.Replace(SCANNER_HINT = k2scan) +env2.Command( 'k2', 'foo.k', Copy( '$TARGET', '$SOURCE' ) ) + +env3 = env1.Clone() +env3.Replace(SCANNER_HINT = 'raise') +env3.Command( 'raise', 'foo.k', Copy( '$TARGET', '$SOURCE' ) ) +""") + +test.write('foo.k', +"""foo.k 1 line 1 +include xxx.k +include yyy +foo.k 1 line 4 +""") + +test.write('xxx.k', "xxx.k 1\n") +test.write('yyy', "yyy 1\n") +test.write('yyy.k2', "yyy.k2 1\n") + +expected_stdout = test.wrap_stdout("""\ +kscan: foo.k +kscan: xxx.k +kscan: yyy +Copy("k", "foo.k") +kscan: foo.k +kscan: xxx.k +k2scan: yyy +Copy("k2", "foo.k") +""") + +test.run(arguments='k k2', stdout=expected_stdout) + +expected_stdout = test.wrap_stdout("""\ +kscan: foo.k +kscan: xxx.k +""", error = True) + +expected_stderr = """\ +scons: *** [raise] SCANNER_HINT object must be instance of +""" + +test.run(arguments='raise', stderr=expected_stderr, stdout=expected_stdout, status = 2) +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From 27ae977d3fa04e29166e172fa64f7b5439d9f0c8 Mon Sep 17 00:00:00 2001 From: William Blevins Date: Fri, 7 Aug 2015 00:25:40 -0400 Subject: Issue 2264: Removed redundant SCANNER_HINT for preference of SCANNERS. Also possibly SCons.Tool.SourceFileScanner (global only). Updated test to reflect with case using SCANNERS plus root node default. --- src/engine/SCons/Node/__init__.py | 14 +--- test/Scanner/CrossLanguageNoExtension.py | 110 ++++++++++++++++++++++++++++ test/Scanner/ScannerHint.py | 119 ------------------------------- 3 files changed, 111 insertions(+), 132 deletions(-) create mode 100644 test/Scanner/CrossLanguageNoExtension.py delete mode 100644 test/Scanner/ScannerHint.py diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index d709f11..5aa9600 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -962,19 +962,7 @@ class Node(object): if not scanner: # no scanner could be found for the given node's scanner key; # thus, make an attempt at using a default. - - # check for a user specified scanner hint - scanner = env.get( 'SCANNER_HINT' ) - - if scanner: - # Ensure scanner hint returned a valid Scanner object - if not isinstance( scanner, SCons.Scanner.Base ): - raise SCons.Errors.UserError( - 'SCANNER_HINT object must be instance of ' + str(SCons.Scanner.Base) - ) - else: - # no scanner hint, so do best guess (IE. return the root's scanner). - scanner = root_node_scanner + scanner = root_node_scanner return scanner diff --git a/test/Scanner/CrossLanguageNoExtension.py b/test/Scanner/CrossLanguageNoExtension.py new file mode 100644 index 0000000..5bf205f --- /dev/null +++ b/test/Scanner/CrossLanguageNoExtension.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# 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. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import TestSCons + +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons() + +# Test behavior of Scanners when evaluating implicit dependencies +# for nodes that do not have mappings from their scanner_key +# to a scanner instance + +test.write('SConstruct', """ +import re + +include_re = re.compile(r'^include\s+(\S+)$', re.M) + +def scan(node, env, scanpaths, arg): + contents = node.get_text_contents() + includes = include_re.findall(contents) + return includes + +def kfile_scan(node, env, scanpaths, arg): + print 'kscan: ' + str(node) + return scan(node, env, scanpaths, arg) + +def k2file_scan(node, env, scanpaths, arg): + print 'k2scan: ' + str(node) + return scan(node, env, scanpaths, arg) + +kscan = Scanner(name = 'kfile', + function = kfile_scan, + argument = None, + skeys = ['.k'], + recursive = True) + +k2scan = Scanner(name = 'k2', + function = k2file_scan, + argument = None, + skeys = ['.k2']) + +k2scan2 = Scanner(name = 'k2', + function = k2file_scan, + argument = None, + skeys = ['']) + +env1 = Environment() +env1.Append(SCANNERS = [ kscan, k2scan ] ) +env1.Command( 'k', 'foo.k', Copy( '$TARGET', '$SOURCE' ) ) + +env2 = env1.Clone() +env2.Append(SCANNERS = [ k2scan2 ] ) +env2.Command( 'k2', 'foo.k', Copy( '$TARGET', '$SOURCE' ) ) +""") + +test.write('foo.k', +"""foo.k 1 line 1 +include xxx.k +include yyy +foo.k 1 line 4 +""") + +test.write('xxx.k', "xxx.k 1\n") +test.write('yyy', "yyy 1\n") +test.write('yyy.k2', "yyy.k2 1\n") + +expected_stdout = test.wrap_stdout("""\ +kscan: foo.k +kscan: xxx.k +kscan: yyy +Copy("k", "foo.k") +kscan: foo.k +kscan: xxx.k +k2scan: yyy +Copy("k2", "foo.k") +""") + +test.run(arguments='k k2', stdout=expected_stdout) + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Scanner/ScannerHint.py b/test/Scanner/ScannerHint.py deleted file mode 100644 index b12b847..0000000 --- a/test/Scanner/ScannerHint.py +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env python -# -# __COPYRIGHT__ -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# 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. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -import TestSCons - -_python_ = TestSCons._python_ - -test = TestSCons.TestSCons() - -# Test behavior of Scanners when evaluating implicit dependencies -# for nodes that do not have mappings from their scanner_key -# to a scanner instance - -test.write('SConstruct', """ -import re - -include_re = re.compile(r'^include\s+(\S+)$', re.M) - -def scan(node, env, scanpaths, arg): - contents = node.get_text_contents() - includes = include_re.findall(contents) - return includes - -def kfile_scan(node, env, scanpaths, arg): - print 'kscan: ' + str(node) - return scan(node, env, scanpaths, arg) - -def k2file_scan(node, env, scanpaths, arg): - print 'k2scan: ' + str(node) - return scan(node, env, scanpaths, arg) - -kscan = Scanner(name = 'kfile', - function = kfile_scan, - argument = None, - skeys = ['.k'], - recursive = True) - -k2scan = Scanner(name = 'k2', - function = k2file_scan, - argument = None, - skeys = ['.k2']) - -env1 = Environment() -env1.Append(SCANNERS = [ kscan, k2scan ] ) -env1.Command( 'k', 'foo.k', Copy( '$TARGET', '$SOURCE' ) ) - -env2 = env1.Clone() -env2.Replace(SCANNER_HINT = k2scan) -env2.Command( 'k2', 'foo.k', Copy( '$TARGET', '$SOURCE' ) ) - -env3 = env1.Clone() -env3.Replace(SCANNER_HINT = 'raise') -env3.Command( 'raise', 'foo.k', Copy( '$TARGET', '$SOURCE' ) ) -""") - -test.write('foo.k', -"""foo.k 1 line 1 -include xxx.k -include yyy -foo.k 1 line 4 -""") - -test.write('xxx.k', "xxx.k 1\n") -test.write('yyy', "yyy 1\n") -test.write('yyy.k2', "yyy.k2 1\n") - -expected_stdout = test.wrap_stdout("""\ -kscan: foo.k -kscan: xxx.k -kscan: yyy -Copy("k", "foo.k") -kscan: foo.k -kscan: xxx.k -k2scan: yyy -Copy("k2", "foo.k") -""") - -test.run(arguments='k k2', stdout=expected_stdout) - -expected_stdout = test.wrap_stdout("""\ -kscan: foo.k -kscan: xxx.k -""", error = True) - -expected_stderr = """\ -scons: *** [raise] SCANNER_HINT object must be instance of -""" - -test.run(arguments='raise', stderr=expected_stderr, stdout=expected_stdout, status = 2) -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From 352c0ef0203f0f09de077d1662f95d896f08ff1c Mon Sep 17 00:00:00 2001 From: William Blevins Date: Fri, 7 Aug 2015 10:29:05 -0400 Subject: Issue 2264: removed implicit dependency recursion from install targets. Resolves performance issue with implicit dependencies (without builders) reinstalling. Example (C++): A.h includes B.h and both are installed somewhere. B.h is updated so both A.h and B.h would be reinstalled because B.h changed. A.h didn't need to be reinstalled for obvious reasons. Background info: this was already an issue for any scanner added to SCANNERS environment. Did not occur originally because default scanners not in SCANNERS environment. --- src/engine/SCons/Tool/install.py | 1 + test/IDL/IDLSUFFIXES.py | 5 ----- test/explain/basic.py | 25 +++++++++++-------------- test/explain/save-info.py | 7 ++----- 4 files changed, 14 insertions(+), 24 deletions(-) diff --git a/src/engine/SCons/Tool/install.py b/src/engine/SCons/Tool/install.py index 9f2e937..847af34 100644 --- a/src/engine/SCons/Tool/install.py +++ b/src/engine/SCons/Tool/install.py @@ -447,6 +447,7 @@ def generate(env): source_factory = env.fs.Entry, multi = 1, emitter = [ add_targets_to_INSTALLED_FILES, ], + source_scanner = SCons.Scanner.Base( {}, name = 'Install', recursive = False ), name = 'InstallBuilder') global BaseVersionedInstallBuilder diff --git a/test/IDL/IDLSUFFIXES.py b/test/IDL/IDLSUFFIXES.py index f71ceba..0a9a50c 100644 --- a/test/IDL/IDLSUFFIXES.py +++ b/test/IDL/IDLSUFFIXES.py @@ -60,11 +60,6 @@ test.up_to_date(arguments='.') test.write('foo.h', "foo.h 2\n") -test.run(arguments='.', stdout=test.wrap_stdout("""\ -Install file: "foo.idl" as "foo_idl" -Install file: "foo.x" as "foo_x" -""")) - test.up_to_date(arguments='.') test.pass_test() diff --git a/test/explain/basic.py b/test/explain/basic.py index 5e31cfd..1072ac4 100644 --- a/test/explain/basic.py +++ b/test/explain/basic.py @@ -169,10 +169,18 @@ test.write(['src', 'file6.in'], "file6.in 1\n") test.write(['src', 'subdir', 'file7.in'], "subdir/file7.in 1\n") -args = '--debug=explain .' +args = '--debug=explain ..' expect = test.wrap_stdout("""\ +scons: building `%(inc_aaa)s' because it doesn't exist +Install file: "aaa" as "%(inc_aaa)s" +scons: building `%(inc_bbb_k)s' because it doesn't exist +Install file: "bbb.k" as "%(inc_bbb_k)s" +scons: building `%(inc_ddd)s' because it doesn't exist +Install file: "ddd" as "%(inc_ddd)s" +scons: building `%(inc_eee)s' because it doesn't exist +Install file: "eee.in" as "%(inc_eee)s" scons: building `file1' because it doesn't exist %(_python_)s %(cat_py)s file1 file1.in scons: building `file2' because it doesn't exist @@ -181,14 +189,6 @@ scons: building `file3' because it doesn't exist %(_python_)s %(cat_py)s file3 xxx yyy zzz scons: building `file4' because it doesn't exist %(_python_)s %(cat_py)s file4 - file4.in -scons: building `%(inc_aaa)s' because it doesn't exist -Install file: "aaa" as "%(inc_aaa)s" -scons: building `%(inc_ddd)s' because it doesn't exist -Install file: "ddd" as "%(inc_ddd)s" -scons: building `%(inc_eee)s' because it doesn't exist -Install file: "eee.in" as "%(inc_eee)s" -scons: building `%(inc_bbb_k)s' because it doesn't exist -Install file: "bbb.k" as "%(inc_bbb_k)s" scons: building `file5' because it doesn't exist %(_python_)s %(cat_py)s file5 file5.k scons: building `file6' because it doesn't exist @@ -236,6 +236,8 @@ test_value = '"second"' WriteInitialTest( locals() ) expect = test.wrap_stdout("""\ +scons: rebuilding `%(inc_bbb_k)s' because `bbb.k' changed +Install file: "bbb.k" as "%(inc_bbb_k)s" scons: rebuilding `file1' because `file1.in' changed %(_python_)s %(cat_py)s file1 file1.in scons: rebuilding `file2' because `yyy' changed @@ -244,11 +246,6 @@ scons: rebuilding `file3' because: `yyy' changed `zzz' changed %(_python_)s %(cat_py)s file3 xxx yyy zzz -scons: rebuilding `%(inc_bbb_k)s' because: - `%(inc_ddd)s' is no longer a dependency - `%(inc_eee)s' is no longer a dependency - `bbb.k' changed -Install file: "bbb.k" as "%(inc_bbb_k)s" scons: rebuilding `file5' because `%(inc_bbb_k)s' changed %(_python_)s %(cat_py)s file5 file5.k scons: rebuilding `file6' because AlwaysBuild() is specified diff --git a/test/explain/save-info.py b/test/explain/save-info.py index d2ffc7d..af4c3f5 100644 --- a/test/explain/save-info.py +++ b/test/explain/save-info.py @@ -141,7 +141,7 @@ file5.k 1 line 4 test.write(['src', 'subdir', 'file6.in'], "subdir/file6.in 1\n") # -test.run(chdir='src', arguments='.') +test.run(chdir='src', arguments='..') test.must_match(['src', 'file1'], "file1.in 1\n") test.must_match(['src', 'file2'], """\ @@ -176,10 +176,7 @@ scons: rebuilding `file3' because: `yyy' changed `zzz' changed %(_python_)s %(cat_py)s file3 xxx yyy zzz -scons: rebuilding `%(inc_bbb_k)s' because: - `%(inc_ddd)s' is no longer a dependency - `%(inc_eee)s' is no longer a dependency - `bbb.k' changed +scons: rebuilding `%(inc_bbb_k)s' because `bbb.k' changed Install file: "bbb.k" as "%(inc_bbb_k)s" scons: rebuilding `file5' because `%(inc_bbb_k)s' changed %(_python_)s %(cat_py)s file5 file5.k -- cgit v0.12 From 04b306103a2c37b90f2d764112c0cb5527313849 Mon Sep 17 00:00:00 2001 From: William Blevins Date: Fri, 7 Aug 2015 18:04:38 -0400 Subject: Issue 2264: Update announcement and change logs. --- src/Announce.txt | 27 +++++++++++++++++++++++++++ src/CHANGES.txt | 6 ++++++ 2 files changed, 33 insertions(+) diff --git a/src/Announce.txt b/src/Announce.txt index f96e703..ab278ec 100644 --- a/src/Announce.txt +++ b/src/Announce.txt @@ -18,6 +18,33 @@ So that everyone using SCons can help each other learn how to use it more effectively, please go to http://scons.org/lists.php#users to sign up for the scons-users mailing list. +==============IMPORTANT NOTICE FOR NEXT VERSION V2.X.X========== + +PLEASE READ. CHANGES COMING IN NEXT MAJOR RELEASE V2.X.X + +We're enhancing implicit language scanning functionality to improve +correctness. SCons now honors scanner keys for implicit +dependencies and correctly changes scanner type (if necessary) when +traversing implicit dependency trees. This enhancement resolves +missing dependencies with built-in scanners including SWIG (#2264) +and QT: +* http://scons.tigris.org/issues/show_bug.cgi?id=2264 + +This enhancement broadens the horizon for handling heterogeneous +data flow environments (E.G. software builds): +* http://article.gmane.org/gmane.comp.programming.tools.scons.user/26596 + +Notes: +* SCons may find new (and correct) dependencies in cross-langauge contexts. +** Update may cause rebuilds, especially in heterogeneous data environments. +** Update may find previously missed dependencies errors (E.G. cycles). +*** Discovered in some QT test cases. +* SCons handles the SCANNERS variable differently. +** Previously, the Install builder would scan implicit dependencies for + a scanner found in SCANNERS (but not for built-in scanners), but now + the Install builder will not scan recursively regardless in order + to optimize Install behaviour and bring orthogonality to previous behaviour. + ==============IMPORTANT NOTICE FOR NEXT VERSION V2.4.0=========== PLEASE READ. CHANGES COMING IN NEXT MAJOR RELEASE V2.4.0 diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 977d00f..89bf7b5 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -6,6 +6,12 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER + From William Blevins: + - Added support for cross-language dependency scanning; + SCons now respects scanner keys for implicit dependencies. + - Resolved missing cross-language dependencies for + SWIG bindings (fixes #2264). + From Dirk Baechle: - Switched several core classes to using "slots", for reducing the overall memory consumption in large -- cgit v0.12 From 67e838665e0520c7d7e53b2aeb85ca0c89e86b69 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 14 Sep 2015 13:24:04 -0700 Subject: Updated generated docs prior to 2.4.0 release --- doc/generated/examples/caching_ex-random_1.xml | 4 ++-- doc/generated/examples/troubleshoot_explain1_3.xml | 2 +- doc/generated/tools.gen | 12 ++++++------ doc/generated/tools.mod | 4 ++-- doc/generated/variables.gen | 6 ++---- 5 files changed, 13 insertions(+), 15 deletions(-) diff --git a/doc/generated/examples/caching_ex-random_1.xml b/doc/generated/examples/caching_ex-random_1.xml index 6f64f8f..18b04eb 100644 --- a/doc/generated/examples/caching_ex-random_1.xml +++ b/doc/generated/examples/caching_ex-random_1.xml @@ -1,9 +1,9 @@ % scons -Q -cc -o f2.o -c f2.c -cc -o f4.o -c f4.c cc -o f3.o -c f3.c cc -o f5.o -c f5.c +cc -o f4.o -c f4.c +cc -o f2.o -c f2.c cc -o f1.o -c f1.c cc -o prog f1.o f2.o f3.o f4.o f5.o diff --git a/doc/generated/examples/troubleshoot_explain1_3.xml b/doc/generated/examples/troubleshoot_explain1_3.xml index 246ee56..3d8592d 100644 --- a/doc/generated/examples/troubleshoot_explain1_3.xml +++ b/doc/generated/examples/troubleshoot_explain1_3.xml @@ -3,5 +3,5 @@ cp file.in file.oout scons: warning: Cannot find target file.out after building -File "/home/bdbaddog/scons/as_scons/bootstrap/src/script/scons.py", line 199, in <module> +File "/scons/as_scons/bootstrap/src/script/scons.py", line 199, in <module> diff --git a/doc/generated/tools.gen b/doc/generated/tools.gen index db89475..4613333 100644 --- a/doc/generated/tools.gen +++ b/doc/generated/tools.gen @@ -772,19 +772,19 @@ Sets construction variables for the Sets: &cv-link-AS;, &cv-link-ASCOM;, &cv-link-ASFLAGS;, &cv-link-ASPPCOM;, &cv-link-ASPPFLAGS;.Uses: &cv-link-ASCOMSTR;, &cv-link-ASPPCOMSTR;. - - packaging + + Packaging -A framework for building binary and source packages. +Sets construction variables for the Package Builder. - - Packaging + + packaging -Sets construction variables for the Package Builder. +A framework for building binary and source packages. diff --git a/doc/generated/tools.mod b/doc/generated/tools.mod index 5a5795a..4ebffb9 100644 --- a/doc/generated/tools.mod +++ b/doc/generated/tools.mod @@ -77,8 +77,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. mwcc"> mwld"> nasm"> -packaging"> Packaging"> +packaging"> pdf"> pdflatex"> pdftex"> @@ -187,8 +187,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. mwcc"> mwld"> nasm"> -packaging"> Packaging"> +packaging"> pdf"> pdflatex"> pdftex"> diff --git a/doc/generated/variables.gen b/doc/generated/variables.gen index bf18796..04c3efe 100644 --- a/doc/generated/variables.gen +++ b/doc/generated/variables.gen @@ -6753,9 +6753,7 @@ and translated into the The list of directories that the scripting language wrapper and interface generate will search for included files. The SWIG implicit dependency scanner will search these -directories for include files. -The default is to use the same path -specified as $CPPPATH. +directories for include files. The default value is an empty list. @@ -6802,7 +6800,7 @@ include $_SWIGINCFLAGS: -env = Environment(SWIGCOM="my_swig -o $TARGET $_SWIGINCFLAGS $SORUCES") +env = Environment(SWIGCOM="my_swig -o $TARGET $_SWIGINCFLAGS $SOURCES") -- cgit v0.12 From 1dc8c086aae30f3ff3e31506875550ee6916922f Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 14 Sep 2015 13:36:50 -0700 Subject: updates to release, announce, changes, debian/changelog for 2.4.0 release --- debian/changelog | 7 +++++++ src/Announce.txt | 13 +++++-------- src/RELEASE.txt | 56 +++++++++++++++----------------------------------------- 3 files changed, 27 insertions(+), 49 deletions(-) diff --git a/debian/changelog b/debian/changelog index b161db1..0b5f17e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ + +scons (2.3.6) unstable; urgency=low + + * Maintenance release. + + -- William Deegan Mon, 14 Sep 2015 21:07:32 -0700 + scons (2.3.6) unstable; urgency=low * Maintenance release. diff --git a/src/Announce.txt b/src/Announce.txt index f96e703..5f121af 100644 --- a/src/Announce.txt +++ b/src/Announce.txt @@ -18,14 +18,7 @@ So that everyone using SCons can help each other learn how to use it more effectively, please go to http://scons.org/lists.php#users to sign up for the scons-users mailing list. -==============IMPORTANT NOTICE FOR NEXT VERSION V2.4.0=========== - -PLEASE READ. CHANGES COMING IN NEXT MAJOR RELEASE V2.4.0 -As has been pre-announced in SCons's mailing lists: - -* https://pairlist4.pair.net/pipermail/scons-users/2014-July/002734.html , -* https://pairlist2.pair.net/pipermail/scons-dev/2014-December/002107.html -* https://pairlist4.pair.net/pipermail/scons-users/2015-February/003454.html +==============IMPORTANT NOTICE FOR VERSION V2.4.0=========== We're planning to switch the Node class to using "slots" in the core sources, mainly to reduce memory consumption by up to 35% in large build projects. @@ -45,6 +38,10 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER changes. + Please note the following important changes since release 2.3.6: + - Switch Node class to using "slots" should reduce memory usage + and speed up builds. + Please note the following important changes since release 2.3.5: - Support for Visual Studio 2015 diff --git a/src/RELEASE.txt b/src/RELEASE.txt index 83212a7..74d955e 100644 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -1,72 +1,46 @@ - A new SCons checkpoint release, 2.3.8.alpha.yyyymmdd, is now available - on the SCons download page: + A new SCons release, 2.4.0 , is now available on the SCons download page: http://www.scons.org/download.php - XXX The primary purpose of this release ... XXX - - A SCons "checkpoint release" is intended to provide early access to - new features so they can be tested in the field before being released - for adoption by other software distributions. - - Note that a checkpoint release is developed using the same test-driven - development methodology as all SCons releases. Existing SCons - functionality should all work as it does in previous releases (except - for any changes identified in the release notes) and early adopters - should be able to use a checkpoint release safely for production work - with existing SConscript files. If not, it represents not only a bug - in SCons but also a hole in the regression test suite, and we want to - hear about it. - - New features may be more lightly tested than in past releases, - especially as concerns their interaction with all of the other - functionality in SCons. We are especially interested in hearing bug - reports about new functionality. - - We do not recommend that downstream distributions (Debian, Fedora, - etc.) package a checkpoint release, mainly to avoid confusing the - "public" release numbering with the long checkpoint release names. - - Here is a summary of the changes since 1.3.0: + Here is a summary of the changes since 2.3.6: NEW FUNCTIONALITY - - List new features (presumably why a checkpoint is being released) + - None DEPRECATED FUNCTIONALITY - - List anything that's been deprecated since the last release + - None CHANGED/ENHANCED EXISTING FUNCTIONALITY - - List modifications to existing features, where the previous behavior - wouldn't actually be considered a bug + - Switched several core classes to using "slots", for + reducing the overall memory consumption in large + projects (fixes #2180, #2178, #2198) + - Memoizer counting uses decorators now, instead of + the old metaclasses approach. FIXES - - List fixes of outright bugs + - 2180, 2178, 2198 (See above) IMPROVEMENTS - - List improvements that wouldn't be visible to the user in the - documentation: performance improvements (describe the circumstances - under which they would be observed), or major code cleanups + - See CHANGED/ENHANCED EXISTING FUNCTIONALITY above PACKAGING - - List changes in the way SCons is packaged and/or released + - None DOCUMENTATION - - List any significant changes to the documentation (not individual - typo fixes, even if they're mentioned in src/CHANGES.txt to give - the contributor credit) + - Bug 2504 - Fixed incorrect default SWIGPATH in documentation DEVELOPMENT - - List visible changes in the way SCons is developed + - None - Thanks to CURLY, LARRY, and MOE for their contributions to this release. + Thanks to Dirk Baechle, and Andrew Featherstone for their contributions to this release. Contributors are listed alphabetically by their last name. __COPYRIGHT__ -- cgit v0.12 From 95266ff25dd0be222e1838a439190317c60601d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carn=C3=AB=20Draug?= Date: Fri, 18 Sep 2015 01:39:38 +0100 Subject: Add configure check CheckProg, to check for existence of a program. --- src/engine/SCons/Conftest.py | 16 ++++++++++++++++ src/engine/SCons/SConf.py | 9 +++++++++ src/engine/SCons/SConfTests.py | 18 ++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/src/engine/SCons/Conftest.py b/src/engine/SCons/Conftest.py index e9702ff..87a3022 100644 --- a/src/engine/SCons/Conftest.py +++ b/src/engine/SCons/Conftest.py @@ -684,6 +684,22 @@ return 0; return ret +def CheckProg(context, prog_name): + """ + Configure check for a specific program. + + Check whether program prog_name exists in path. If it is found, + returns the path for it, otherwise returns None. + """ + context.Display("Checking whether %s program exists..." % prog_name) + path = context.env.WhereIs(prog_name) + if path: + context.Display(path + "\n") + else: + context.Display("no\n") + return path + + # # END OF PUBLIC FUNCTIONS # diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index 8bce8ce..987b8ea 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -444,6 +444,7 @@ class SConfBase(object): 'CheckCXXHeader' : CheckCXXHeader, 'CheckLib' : CheckLib, 'CheckLibWithHeader' : CheckLibWithHeader, + 'CheckProg' : CheckProg, } self.AddTests(default_tests) self.AddTests(custom_tests) @@ -1047,6 +1048,14 @@ def CheckLibWithHeader(context, libs, header, language, context.did_show_result = 1 return not res +def CheckProg(context, prog_name): + """Simple check if a program exists in the path. Returns the path + for the application, or None if not found. + """ + res = SCons.Conftest.CheckProg(context, prog_name) + context.did_show_result = 1 + return res + # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/src/engine/SCons/SConfTests.py b/src/engine/SCons/SConfTests.py index 233ee78..57a9d04 100644 --- a/src/engine/SCons/SConfTests.py +++ b/src/engine/SCons/SConfTests.py @@ -611,6 +611,24 @@ int main() { finally: sconf.Finish() + def test_CheckProg(self): + """Test SConf.CheckProg() + """ + self._resetSConfState() + sconf = self.SConf.SConf(self.scons_env, + conf_dir=self.test.workpath('config.tests'), + log_file=self.test.workpath('config.log')) + + try: + r = sconf.CheckProg('sh') + assert r, "/bin/sh" + r = sconf.CheckProg('hopefully-not-a-program') + assert r is None + + finally: + sconf.Finish() + + def test_Define(self): """Test SConf.Define() """ -- cgit v0.12 From 72d8407c28fc02cb986fa561c793e1b202e53867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carn=C3=AB=20Draug?= Date: Sat, 26 Sep 2015 19:01:04 +0100 Subject: Add new CheckProg configure method to documentation and list of changes. --- doc/scons.mod | 1 + doc/user/sconf.xml | 20 ++++++++++++++++++++ src/CHANGES.txt | 4 ++++ 3 files changed, 25 insertions(+) diff --git a/doc/scons.mod b/doc/scons.mod index 72dc7ff..8d64054 100644 --- a/doc/scons.mod +++ b/doc/scons.mod @@ -276,6 +276,7 @@ CheckHeader"> CheckLib"> CheckLibWithHeader"> +CheckProg"> CheckType"> CheckTypeSize"> TryAction"> diff --git a/doc/user/sconf.xml b/doc/user/sconf.xml index 569ab1a..fe933f1 100644 --- a/doc/user/sconf.xml +++ b/doc/user/sconf.xml @@ -304,6 +304,26 @@ scons: `.' is up to date.
+ Checking for the Presence of a program + + + + Check for the presence of a program + by using the &CheckProg; method: + + + + +env = Environment() +conf = Configure(env) +if not conf.CheckProg('foobar'): + print 'Unable to find the program foobar on the system' + Exit(1) +env = conf.Finish() + + +
+
Adding Your Own Custom Checks diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 977d00f..3869621 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -13,6 +13,10 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Memoizer counting uses decorators now, instead of the old metaclasses approach. + From Carnë Draug: + - Added new configure check, CheckProg, to check for + existence of a program. + RELEASE 2.3.6 - Mon, 31 Jul 2015 14:35:03 -0700 From Rob Smith: -- cgit v0.12 From 699440f601523b736d98cfef8f1bddcc2f184a39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carn=C3=AB=20Draug?= Date: Sat, 26 Sep 2015 20:42:53 +0100 Subject: doc: do not recommend os.popen which is deprecated in python --- doc/user/tasks.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/user/tasks.xml b/doc/user/tasks.xml index 0bdf678..8026a53 100644 --- a/doc/user/tasks.xml +++ b/doc/user/tasks.xml @@ -96,8 +96,8 @@ filenames = [x for x in filenames if os.path.splitext(x)[1] in extensions] The "backtick function": run a shell command and capture the output -import os -output = os.popen(command).read() +import subprocess +output = subprocess.check_output(command) -- cgit v0.12 From 60ec8bc52b7c15a3f017a898b20644810609d185 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 28 Sep 2015 10:05:31 -0700 Subject: fix spelling mistakes found by debian lintian tool list here: https://lintian.debian.org/full/debian@jff-webhosting.net.html#scons_2.3.6-1 --- doc/man/scons.xml | 2 +- doc/user/build-install.xml | 2 +- src/engine/SCons/Environment.py | 2 +- src/engine/SCons/Script/SConsOptions.py | 2 +- src/engine/SCons/Tool/gettext.xml | 2 +- src/engine/SCons/Tool/midl.xml | 2 +- src/engine/SCons/Tool/msgmerge.xml | 2 +- src/engine/SCons/Tool/msvc.xml | 2 +- src/engine/SCons/Tool/packaging/rpm.py | 2 +- src/engine/SCons/Tool/xgettext.xml | 2 +- test/TEX/variant_dir_newglossary.py | 2 +- test/packaging/guess-package-name.py | 2 +- test/packaging/msi/explicit-target.py | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index c3abb64..5c832c2 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -7040,7 +7040,7 @@ env.Program('MyApp', ['Foo.cpp', 'Bar.cpp']) For more information see the document for the PCH builder, and the PCH and PCHSTOP construction variables. To learn about the details of precompiled -headers consult the MSDN documention for /Yc, /Yu, and /Yp. +headers consult the MSDN documentation for /Yc, /Yu, and /Yp. diff --git a/doc/user/build-install.xml b/doc/user/build-install.xml index d107b4a..3e66172 100644 --- a/doc/user/build-install.xml +++ b/doc/user/build-install.xml @@ -231,7 +231,7 @@ Python 2.5.1 Or, you can use a graphical RPM package manager. - See your package manager application's documention + See your package manager application's documentation for specific instructions about how to use it to install a downloaded RPM. diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 8db743b..7e2f896 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -612,7 +612,7 @@ class SubstitutionEnvironment(object): def Override(self, overrides): """ - Produce a modified environment whose variables are overriden by + Produce a modified environment whose variables are overridden by the overrides dictionaries. "overrides" is a dictionary that will override the variables of this environment. diff --git a/src/engine/SCons/Script/SConsOptions.py b/src/engine/SCons/Script/SConsOptions.py index 8ecc093..68c60cc 100644 --- a/src/engine/SCons/Script/SConsOptions.py +++ b/src/engine/SCons/Script/SConsOptions.py @@ -268,7 +268,7 @@ class SConsOptionParser(optparse.OptionParser): preserve_unknown_options = False def error(self, msg): - # overriden OptionValueError exception handler + # overridden OptionValueError exception handler self.print_usage(sys.stderr) sys.stderr.write("SCons Error: %s\n" % msg) sys.exit(2) diff --git a/src/engine/SCons/Tool/gettext.xml b/src/engine/SCons/Tool/gettext.xml index 96e467a..f9f8b81 100644 --- a/src/engine/SCons/Tool/gettext.xml +++ b/src/engine/SCons/Tool/gettext.xml @@ -27,7 +27,7 @@ See its __doc__ string for a discussion of the format. This is actually a toolset, which supports internationalization and -localization of sofware being constructed with SCons. The toolset loads +localization of software being constructed with SCons. The toolset loads following tools: diff --git a/src/engine/SCons/Tool/midl.xml b/src/engine/SCons/Tool/midl.xml index 1420978..efd83cc 100644 --- a/src/engine/SCons/Tool/midl.xml +++ b/src/engine/SCons/Tool/midl.xml @@ -44,7 +44,7 @@ Sets construction variables for the Microsoft IDL compiler. Builds a Windows type library (.tlb) file from an input IDL file (.idl). -In addition, it will build the associated inteface stub and +In addition, it will build the associated interface stub and proxy source files, naming them according to the base name of the .idl file. For example, diff --git a/src/engine/SCons/Tool/msgmerge.xml b/src/engine/SCons/Tool/msgmerge.xml index 2bfc6df..139b21c 100644 --- a/src/engine/SCons/Tool/msgmerge.xml +++ b/src/engine/SCons/Tool/msgmerge.xml @@ -64,7 +64,7 @@ Target nodes defined through &b-POUpdate; are not built by default (they're Ignored from '.' node). Instead, they are added automatically to special Alias ('po-update' by default). The alias name may be changed -through the &cv-link-POUPDATE_ALIAS; construction variable. You can easilly +through the &cv-link-POUPDATE_ALIAS; construction variable. You can easily update PO files in your project by scons po-update. diff --git a/src/engine/SCons/Tool/msvc.xml b/src/engine/SCons/Tool/msvc.xml index 793784f..2b4619e 100644 --- a/src/engine/SCons/Tool/msvc.xml +++ b/src/engine/SCons/Tool/msvc.xml @@ -86,7 +86,7 @@ file as the second element. Normally the object file is ignored. This builder method is only provided when Microsoft Visual C++ is being used as the compiler. The PCH builder method is generally used in -conjuction with the PCH construction variable to force object files to use +conjunction with the PCH construction variable to force object files to use the precompiled header: diff --git a/src/engine/SCons/Tool/packaging/rpm.py b/src/engine/SCons/Tool/packaging/rpm.py index 656d8fb..92977d0 100644 --- a/src/engine/SCons/Tool/packaging/rpm.py +++ b/src/engine/SCons/Tool/packaging/rpm.py @@ -168,7 +168,7 @@ def build_specfile_sections(spec): 'X_RPM_POSTUNINSTALL' : '%%postun\n%s\n\n', 'X_RPM_VERIFY' : '%%verify\n%s\n\n', - # These are for internal use but could possibly be overriden + # These are for internal use but could possibly be overridden 'X_RPM_PREP' : '%%prep\n%s\n\n', 'X_RPM_BUILD' : '%%build\n%s\n\n', 'X_RPM_INSTALL' : '%%install\n%s\n\n', diff --git a/src/engine/SCons/Tool/xgettext.xml b/src/engine/SCons/Tool/xgettext.xml index 6e28a9d..380f92a 100644 --- a/src/engine/SCons/Tool/xgettext.xml +++ b/src/engine/SCons/Tool/xgettext.xml @@ -108,7 +108,7 @@ the results shall be as the comments above say. Example 2. The &b-POTUpdate; builder may be used with no target specified, in which case default target messages.pot will be used. The -default target may also be overriden by setting &cv-link-POTDOMAIN; construction +default target may also be overridden by setting &cv-link-POTDOMAIN; construction variable or providing it as an override to &b-POTUpdate; builder: diff --git a/test/TEX/variant_dir_newglossary.py b/test/TEX/variant_dir_newglossary.py index 8604270..5a28ed4 100644 --- a/test/TEX/variant_dir_newglossary.py +++ b/test/TEX/variant_dir_newglossary.py @@ -25,7 +25,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ -Validate the use of \newglossary in TeX source files in conjuction +Validate the use of \newglossary in TeX source files in conjunction with variant_dir. Test configuration contributed by Kendrick Boyd. diff --git a/test/packaging/guess-package-name.py b/test/packaging/guess-package-name.py index 9c85b9a..33c3329 100644 --- a/test/packaging/guess-package-name.py +++ b/test/packaging/guess-package-name.py @@ -86,7 +86,7 @@ test.run(stderr = None) test.must_exist( 'src.tar.gz' ) # -# TEST: default package name creation with overriden packager. +# TEST: default package name creation with overridden packager. # test.write('SConstruct', """ diff --git a/test/packaging/msi/explicit-target.py b/test/packaging/msi/explicit-target.py index bc786ee..85bfa85 100644 --- a/test/packaging/msi/explicit-target.py +++ b/test/packaging/msi/explicit-target.py @@ -26,7 +26,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ Test the ability to use a explicit target package name and the use -of FindInstalledFiles() in conjuction with .msi packages. +of FindInstalledFiles() in conjunction with .msi packages. """ import TestSCons -- cgit v0.12 From b2b1d5d272bdcfe1f9dc7c4bc57b8c8927fe7784 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 28 Sep 2015 11:08:40 -0700 Subject: added .DS_Store to hgignore --- .hgignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgignore b/.hgignore index 27c728a..dcc9505 100644 --- a/.hgignore +++ b/.hgignore @@ -9,6 +9,7 @@ syntax:glob *~ *.xcodeproj *.orig +*.DS_Store doc/user/scons-user doc/user/scons_db.xml -- cgit v0.12 From 8474df368aeed8807eb4b9ca20041676f42e69c6 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 28 Sep 2015 11:39:22 -0700 Subject: fixed syntax error from previous pull request #256 --- src/engine/SCons/Tool/__init__.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/SCons/Tool/__init__.xml b/src/engine/SCons/Tool/__init__.xml index 358ff1e..69cc597 100644 --- a/src/engine/SCons/Tool/__init__.xml +++ b/src/engine/SCons/Tool/__init__.xml @@ -489,7 +489,7 @@ is created by &b-link-LoadableModule; builder. This activates the &cv-link-_LDMODULEVERSIONFLAGS; and thus modifies the &cv-link-LDMODULECOM; as required, adds the version number to the library name, and creates the symlinks that are needed. &cv-link-LDMODULEVERSION; versions should exist in the same -format as &cv-link-SHLIBVERSION. +format as &cv-link-SHLIBVERSION;. -- cgit v0.12 From 3359572ab98baf9f408c7e86ad0d2df9a50594a4 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 28 Sep 2015 13:01:37 -0700 Subject: exit with non-zero exit code if validation fails --- bin/docs-validate.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/docs-validate.py b/bin/docs-validate.py index c445c3f..f888c21 100644 --- a/bin/docs-validate.py +++ b/bin/docs-validate.py @@ -25,3 +25,4 @@ if __name__ == "__main__": print "OK" else: print "Validation failed! Please correct the errors above and try again." + sys.exit(1) -- cgit v0.12 From 898fa44b70ce4998801db843dbe5b263f4d34a18 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 28 Sep 2015 13:57:59 -0700 Subject: Added help for pull request #226 --- doc/generated/builders.gen | 35 ++-- doc/generated/examples/caching_ex-random_1.xml | 4 +- .../examples/commandline_Variables_Help_1.xml | 2 + doc/generated/examples/output_ex1_1.xml | 2 + doc/generated/examples/output_ex2_1.xml | 2 + doc/generated/examples/output_ex2_2.xml | 2 + doc/generated/examples/troubleshoot_Dump_1.xml | 4 + doc/generated/examples/troubleshoot_Dump_2.xml | 4 + doc/generated/examples/troubleshoot_explain1_3.xml | 2 +- doc/generated/functions.gen | 18 +- doc/generated/tools.gen | 16 +- doc/generated/tools.mod | 2 + doc/generated/variables.gen | 184 ++++++++++++++++++++- doc/generated/variables.mod | 32 ++++ doc/user/output.xml | 22 +++ src/engine/SCons/Script/SConscript.xml | 16 +- 16 files changed, 302 insertions(+), 45 deletions(-) diff --git a/doc/generated/builders.gen b/doc/generated/builders.gen index 02dc04b..d49156f 100644 --- a/doc/generated/builders.gen +++ b/doc/generated/builders.gen @@ -505,20 +505,13 @@ env.InstallAs(target = ['../lib/libfoo.a', '../lib/libbar.a'], -Installs a versioned shared library. The $SHLIBVERSION -construction variable should be defined in the environment -to confirm the version number in the library name. -If $SHLIBVERSION is not defined a warning will be issued -and the name of the library will be parsed to derive the version. -The symlinks appropriate to the architecture will be generated. +Installs a versioned shared library. The symlinks appropriate to the +architecture will be generated based on symlinks of the source library. env.InstallVersionedLib(target = '/usr/local/bin/foo', source = 'libxyz.1.5.2.so') -env.InstallVersionedLib(target = '/usr/local/bin/foo', - source = 'libxyz.1.5.2.so', - SHLIBVERSION='1.5.2') @@ -1257,7 +1250,7 @@ file as the second element. Normally the object file is ignored. This builder method is only provided when Microsoft Visual C++ is being used as the compiler. The PCH builder method is generally used in -conjuction with the PCH construction variable to force object files to use +conjunction with the PCH construction variable to force object files to use the precompiled header: @@ -1490,7 +1483,7 @@ the results shall be as the comments above say. Example 2. The POTUpdate builder may be used with no target specified, in which case default target messages.pot will be used. The -default target may also be overriden by setting $POTDOMAIN construction +default target may also be overridden by setting $POTDOMAIN construction variable or providing it as an override to POTUpdate builder: @@ -1623,7 +1616,7 @@ Target nodes defined through P (they're Ignored from '.' node). Instead, they are added automatically to special Alias ('po-update' by default). The alias name may be changed -through the $POUPDATE_ALIAS construction variable. You can easilly +through the $POUPDATE_ALIAS construction variable. You can easily update PO files in your project by scons po-update. @@ -1995,22 +1988,20 @@ For maximum portability, use the $SHLIBVERSION construction variable is defined a versioned shared library is created. This modifies the $SHLINKFLAGS as required, adds the version number to the library name, and creates the symlinks that -are needed. $SHLIBVERSION needs to be of the form X.Y.Z, where X -and Y are numbers, and Z is a number but can also contain letters to designate -alpha, beta, or release candidate patch levels. +are needed. env.SharedLibrary(target = 'bar', source = ['bar.c', 'foo.o'], SHLIBVERSION='1.5.2') - -This builder may create multiple links to the library. On a POSIX system, -for the shared library libbar.so.2.3.1, the links created would be -libbar.so and libbar.so.2; on a Darwin (OSX) system -the library would be libbar.2.3.1.dylib and the link would be -libbar.dylib. +On a POSIX system, versions with a single token create exactly one symlink: +libbar.so.6 would have symlinks libbar.so only. +On a POSIX system, versions with two or more +tokens create exactly two symlinks: libbar.so.2.3.1 would have symlinks +libbar.so and libbar.so.2; on a Darwin (OSX) system the library would be +libbar.2.3.1.dylib and the link would be libbar.dylib. @@ -2564,7 +2555,7 @@ running scons '.'. Builds a Windows type library (.tlb) file from an input IDL file (.idl). -In addition, it will build the associated inteface stub and +In addition, it will build the associated interface stub and proxy source files, naming them according to the base name of the .idl file. For example, diff --git a/doc/generated/examples/caching_ex-random_1.xml b/doc/generated/examples/caching_ex-random_1.xml index e7aa631..904e1dd 100644 --- a/doc/generated/examples/caching_ex-random_1.xml +++ b/doc/generated/examples/caching_ex-random_1.xml @@ -1,9 +1,9 @@ % scons -Q -cc -o f4.o -c f4.c -cc -o f5.o -c f5.c cc -o f2.o -c f2.c +cc -o f5.o -c f5.c cc -o f3.o -c f3.c +cc -o f4.o -c f4.c cc -o f1.o -c f1.c cc -o prog f1.o f2.o f3.o f4.o f5.o diff --git a/doc/generated/examples/commandline_Variables_Help_1.xml b/doc/generated/examples/commandline_Variables_Help_1.xml index db171eb..76f13c5 100644 --- a/doc/generated/examples/commandline_Variables_Help_1.xml +++ b/doc/generated/examples/commandline_Variables_Help_1.xml @@ -1,6 +1,8 @@ % scons -Q -h +Local Build Variables: + RELEASE: Set to 1 to build for release default: 0 actual: 0 diff --git a/doc/generated/examples/output_ex1_1.xml b/doc/generated/examples/output_ex1_1.xml index 535960b..2607243 100644 --- a/doc/generated/examples/output_ex1_1.xml +++ b/doc/generated/examples/output_ex1_1.xml @@ -3,6 +3,8 @@ scons: Reading SConscript files ... scons: done reading SConscript files. +Local Build Variables: + Type: 'scons program' to build the production program, 'scons debug' to build the debug version. diff --git a/doc/generated/examples/output_ex2_1.xml b/doc/generated/examples/output_ex2_1.xml index e951c3a..74d7192 100644 --- a/doc/generated/examples/output_ex2_1.xml +++ b/doc/generated/examples/output_ex2_1.xml @@ -3,6 +3,8 @@ scons: Reading SConscript files ... scons: done reading SConscript files. +Local Build Variables: + Type: 'scons program' to build the production program. Type: 'scons windebug' to build the Windows debug version. diff --git a/doc/generated/examples/output_ex2_2.xml b/doc/generated/examples/output_ex2_2.xml index 8dca6c3..9130d5a 100644 --- a/doc/generated/examples/output_ex2_2.xml +++ b/doc/generated/examples/output_ex2_2.xml @@ -3,6 +3,8 @@ scons: Reading SConscript files ... scons: done reading SConscript files. +Local Build Variables: + Type: 'scons program' to build the production program. Use scons -H for help about command-line options. diff --git a/doc/generated/examples/troubleshoot_Dump_1.xml b/doc/generated/examples/troubleshoot_Dump_1.xml index 248e85c..bf141a0 100644 --- a/doc/generated/examples/troubleshoot_Dump_1.xml +++ b/doc/generated/examples/troubleshoot_Dump_1.xml @@ -64,7 +64,11 @@ scons: Reading SConscript files ... '_LIBDIRFLAGS': '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', '_LIBFLAGS': '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}', '__DRPATH': '$_DRPATH', + '__DSHLIBVERSIONFLAGS': '${__libversionflags(__env__,"DSHLIBVERSION","_DSHLIBVERSIONFLAGS")}', + '__LDMODULEVERSIONFLAGS': '${__libversionflags(__env__,"LDMODULEVERSION","_LDMODULEVERSIONFLAGS")}', '__RPATH': '$_RPATH', + '__SHLIBVERSIONFLAGS': '${__libversionflags(__env__,"SHLIBVERSION","_SHLIBVERSIONFLAGS")}', + '__libversionflags': <function __libversionflags at 0x700000&gt;, '_concat': <function _concat at 0x700000&gt;, '_defines': <function _defines at 0x700000&gt;, '_stripixes': <function _stripixes at 0x700000&gt;} diff --git a/doc/generated/examples/troubleshoot_Dump_2.xml b/doc/generated/examples/troubleshoot_Dump_2.xml index d6fa404..0ae8fe1 100644 --- a/doc/generated/examples/troubleshoot_Dump_2.xml +++ b/doc/generated/examples/troubleshoot_Dump_2.xml @@ -97,6 +97,10 @@ scons: Reading SConscript files ... '_LIBDIRFLAGS': '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', '_LIBFLAGS': '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}', '_MSVC_OUTPUT_FLAG': <function msvc_output_flag at 0x700000&gt;, + '__DSHLIBVERSIONFLAGS': '${__libversionflags(__env__,"DSHLIBVERSION","_DSHLIBVERSIONFLAGS")}', + '__LDMODULEVERSIONFLAGS': '${__libversionflags(__env__,"LDMODULEVERSION","_LDMODULEVERSIONFLAGS")}', + '__SHLIBVERSIONFLAGS': '${__libversionflags(__env__,"SHLIBVERSION","_SHLIBVERSIONFLAGS")}', + '__libversionflags': <function __libversionflags at 0x700000&gt;, '_concat': <function _concat at 0x700000&gt;, '_defines': <function _defines at 0x700000&gt;, '_stripixes': <function _stripixes at 0x700000&gt;} diff --git a/doc/generated/examples/troubleshoot_explain1_3.xml b/doc/generated/examples/troubleshoot_explain1_3.xml index 246ee56..9763efe 100644 --- a/doc/generated/examples/troubleshoot_explain1_3.xml +++ b/doc/generated/examples/troubleshoot_explain1_3.xml @@ -3,5 +3,5 @@ cp file.in file.oout scons: warning: Cannot find target file.out after building -File "/home/bdbaddog/scons/as_scons/bootstrap/src/script/scons.py", line 199, in <module> +File "/home/bdbaddog/scons/scons/bootstrap/src/script/scons.py", line 199, in <module> diff --git a/doc/generated/functions.gen b/doc/generated/functions.gen index 3ad36e5..e80c1c9 100644 --- a/doc/generated/functions.gen +++ b/doc/generated/functions.gen @@ -2565,10 +2565,10 @@ sources = Glob('*.cpp', exclude=['os_*_specific_*.cpp']) + Glob('os_%s_specific_ - Help(text) + Help(text, append=False) - env.Help(text) + env.Help(text, append=False) @@ -2576,12 +2576,18 @@ This specifies help text to be printed if the argument is given to scons. -If +If Help -is called multiple times, the text is appended together in the order -that +is called multiple times, the text is appended together in the order that Help -is called. +is called. With append set to False, any +Help +text generated with +AddOption +is clobbered. If append is True, the AddOption help is prepended to the help +string, thus preserving the + +message. diff --git a/doc/generated/tools.gen b/doc/generated/tools.gen index db89475..fcb7587 100644 --- a/doc/generated/tools.gen +++ b/doc/generated/tools.gen @@ -129,6 +129,14 @@ Sets construction variables for generic POSIX C++ compilers. Sets: &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-CXX;, &cv-link-CXXCOM;, &cv-link-CXXFILESUFFIX;, &cv-link-CXXFLAGS;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;, &cv-link-OBJSUFFIX;, &cv-link-SHCXX;, &cv-link-SHCXXCOM;, &cv-link-SHCXXFLAGS;, &cv-link-SHOBJSUFFIX;.Uses: &cv-link-CXXCOMSTR;. + + cyglink + + +Set construction variables for cygwin linker/loader. + +Sets: &cv-link-IMPLIBPREFIX;, &cv-link-IMPLIBSUFFIX;, &cv-link-LDMODULEVERSIONFLAGS;, &cv-link-LINKFLAGS;, &cv-link-RPATHPREFIX;, &cv-link-RPATHSUFFIX;, &cv-link-SHLIBPREFIX;, &cv-link-SHLIBSUFFIX;, &cv-link-SHLIBVERSIONFLAGS;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-_LDMODULEVERSIONFLAGS;, &cv-link-_SHLIBVERSIONFLAGS;. + default @@ -395,7 +403,7 @@ Sets construction variables for the D language compiler GDC. This is actually a toolset, which supports internationalization and -localization of sofware being constructed with SCons. The toolset loads +localization of software being constructed with SCons. The toolset loads following tools: @@ -454,7 +462,7 @@ Sets construction variables for the GNU F95/F2003 GNU compiler. Set construction variables for GNU linker/loader. -Sets: &cv-link-RPATHPREFIX;, &cv-link-RPATHSUFFIX;, &cv-link-SHLINKFLAGS;. +Sets: &cv-link-LDMODULEVERSIONFLAGS;, &cv-link-RPATHPREFIX;, &cv-link-RPATHSUFFIX;, &cv-link-SHLIBVERSIONFLAGS;, &cv-link-SHLINKFLAGS;, &cv-link-_LDMODULESONAME;, &cv-link-_SHLIBSONAME;. gs @@ -623,7 +631,7 @@ Sets construction variables for the Sets construction variables for generic POSIX linkers. -Sets: &cv-link-LDMODULE;, &cv-link-LDMODULECOM;, &cv-link-LDMODULEFLAGS;, &cv-link-LDMODULEPREFIX;, &cv-link-LDMODULESUFFIX;, &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-LINKFLAGS;, &cv-link-SHLIBSUFFIX;, &cv-link-SHLINK;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;.Uses: &cv-link-LDMODULECOMSTR;, &cv-link-LINKCOMSTR;, &cv-link-SHLINKCOMSTR;. +Sets: &cv-link-LDMODULE;, &cv-link-LDMODULECOM;, &cv-link-LDMODULEFLAGS;, &cv-link-LDMODULENOVERSIONSYMLINKS;, &cv-link-LDMODULEPREFIX;, &cv-link-LDMODULESUFFIX;, &cv-link-LDMODULEVERSION;, &cv-link-LDMODULEVERSIONFLAGS;, &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-LINKFLAGS;, &cv-link-SHLIBSUFFIX;, &cv-link-SHLINK;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-__LDMODULEVERSIONFLAGS;, &cv-link-__SHLIBVERSIONFLAGS;.Uses: &cv-link-LDMODULECOMSTR;, &cv-link-LINKCOMSTR;, &cv-link-SHLINKCOMSTR;. linkloc @@ -901,7 +909,7 @@ Sets construction variables for the SGI linker. Sets construction variables for the Sun library archiver. -Sets: &cv-link-AR;, &cv-link-ARCOM;, &cv-link-ARFLAGS;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;, &cv-link-SHLINK;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;.Uses: &cv-link-ARCOMSTR;, &cv-link-SHLINKCOMSTR;. +Sets: &cv-link-AR;, &cv-link-ARCOM;, &cv-link-ARFLAGS;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;.Uses: &cv-link-ARCOMSTR;. sunc++ diff --git a/doc/generated/tools.mod b/doc/generated/tools.mod index 5a5795a..1191e6a 100644 --- a/doc/generated/tools.mod +++ b/doc/generated/tools.mod @@ -22,6 +22,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. cvf"> CVS"> cXX"> +cyglink"> default"> dmd"> docbook"> @@ -132,6 +133,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. cvf"> CVS"> cXX"> +cyglink"> default"> dmd"> docbook"> diff --git a/doc/generated/variables.gen b/doc/generated/variables.gen index 04c3efe..3d8a87a 100644 --- a/doc/generated/variables.gen +++ b/doc/generated/variables.gen @@ -13,6 +13,24 @@ ]> + + __LDMODULEVERSIONFLAGS + + +This construction variable automatically introduces $_LDMODULEVERSIONFLAGS +if $LDMODULEVERSION is set. Othervise it evaluates to an empty string. + + + + + __SHLIBVERSIONFLAGS + + +This construction variable automatically introduces $_SHLIBVERSIONFLAGS +if $SHLIBVERSION is set. Othervise it evaluates to an empty string. + + + AR @@ -2874,6 +2892,52 @@ The default list is: + + IMPLIBNOVERSIONSYMLINKS + + +Used to override $SHLIBNOVERSIONSYMLINKS/$LDMODULENOVERSIONSYMLINKS when +creating versioned import library for a shared library/loadable module. If not defined, +then $SHLIBNOVERSIONSYMLINKS/$LDMODULENOVERSIONSYMLINKS is used to determine +whether to disable symlink generation or not. + + + + + IMPLIBPREFIX + + +The prefix used for import library names. For example, cygwin uses import +libraries (libfoo.dll.a) in pair with dynamic libraries +(cygfoo.dll). The cyglink linker sets +$IMPLIBPREFIX to 'lib' and $SHLIBPREFIX +to 'cyg'. + + + + + IMPLIBSUFFIX + + +The suffix used for import library names. For example, cygwin uses import +libraries (libfoo.dll.a) in pair with dynamic libraries +(cygfoo.dll). The cyglink linker sets +$IMPLIBSUFFIX to '.dll.a' and $SHLIBSUFFIX +to '.dll'. + + + + + IMPLIBVERSION + + +Used to override $SHLIBVERSION/$LDMODULEVERSION when +generating versioned import library for a shared library/loadable module. If +undefined, the $SHLIBVERSION/$LDMODULEVERSION is used to +determine the version of versioned import library. + + + IMPLICIT_COMMAND_DEPENDENCIES @@ -3408,6 +3472,15 @@ General user options passed to the linker for building loadable modules. + + LDMODULENOVERSIONSYMLINKS + + +Instructs the LoadableModule builder to not automatically create symlinks +for versioned modules. Defaults to $SHLIBNOVERSIONSYMLINKS + + + LDMODULEPREFIX @@ -3419,6 +3492,16 @@ the same as + _LDMODULESONAME + + +A macro that automatically generates loadable module's SONAME based on $TARGET, +$LDMODULEVERSION and $LDMODULESUFFIX. Used by LoadableModule builder +when the linker tool supports SONAME (e.g. gnulink). + + + LDMODULESUFFIX @@ -3430,6 +3513,42 @@ the same as $SHLIBSUFFIX. + + LDMODULEVERSION + + +When this construction variable is defined, a versioned loadable module +is created by LoadableModule builder. This activates the +$_LDMODULEVERSIONFLAGS and thus modifies the $LDMODULECOM as +required, adds the version number to the library name, and creates the symlinks +that are needed. $LDMODULEVERSION versions should exist in the same +format as $SHLIBVERSION. + + + + + LDMODULEVERSIONFLAGS + + +Extra flags added to $LDMODULECOM when building versioned +LoadableModule. These flags are only used when $LDMODULEVERSION is +set. + + + + + _LDMODULEVERSIONFLAGS + + +This macro automatically introduces extra flags to $LDMODULECOM when +building versioned LoadableModule (that is when +$LDMODULEVERSION is set). _LDMODULEVERSIONFLAGS +usually adds $SHLIBVERSIONFLAGS and some extra dynamically generated +options (such as -Wl,-soname=$_LDMODULESONAME). It is unused +by plain (unversioned) loadable modules. + + + LEX @@ -6385,6 +6504,15 @@ TODO + + SHLIBNOVERSIONSYMLINKS + + +Instructs the SharedLibrary builder to not create symlinks for versioned +shared libraries. + + + SHLIBPREFIX @@ -6393,6 +6521,16 @@ The prefix used for shared library file names. + + _SHLIBSONAME + + +A macro that automatically generates shared library's SONAME based on $TARGET, +$SHLIBVERSION and $SHLIBSUFFIX. Used by SharedLibrary builder when +the linker tool supports SONAME (e.g. gnulink). + + + SHLIBSUFFIX @@ -6406,11 +6544,35 @@ The suffix used for shared library file names. When this construction variable is defined, a versioned shared library -is created. This modifies the $SHLINKFLAGS as required, adds -the version number to the library name, and creates the symlinks that -are needed. $SHLIBVERSION needs to be of the form X.Y.Z, -where X and Y are numbers, and Z is a number but can also contain -letters to designate alpha, beta, or release candidate patch levels. +is created by SharedLibrary builder. This activates the +$_SHLIBVERSIONFLAGS and thus modifies the $SHLINKCOM as +required, adds the version number to the library name, and creates the symlinks +that are needed. $SHLIBVERSION versions should exist as alpha-numeric, +decimal-delimited values as defined by the regular expression "\w+[\.\w+]*". +Example $SHLIBVERSION values include '1', '1.2.3', and '1.2.gitaa412c8b'. + + + + + SHLIBVERSIONFLAGS + + +Extra flags added to $SHLINKCOM when building versioned +SharedLibrary. These flags are only used when $SHLIBVERSION is +set. + + + + + _SHLIBVERSIONFLAGS + + +This macro automatically introduces extra flags to $SHLINKCOM when +building versioned SharedLibrary (that is when $SHLIBVERSION +is set). _SHLIBVERSIONFLAGS usually adds $SHLIBVERSIONFLAGS +and some extra dynamically generated options (such as +-Wl,-soname=$_SHLIBSONAME. It is unused by "plain" +(unversioned) shared libraries. @@ -6484,6 +6646,18 @@ The suffix used for shared object file names. + + SONAME + + +Variable used to hard-code SONAME for versioned shared library/loadable module. + +env.SharedLibrary('test', 'test.c', SHLIBVERSION='0.1.2', SONAME='libtest.so.2') + +The variable is used, for example, by gnulink linker tool. + + + SOURCE diff --git a/doc/generated/variables.mod b/doc/generated/variables.mod index fc12a92..f7303f2 100644 --- a/doc/generated/variables.mod +++ b/doc/generated/variables.mod @@ -8,6 +8,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. --> +$__LDMODULEVERSIONFLAGS"> +$__SHLIBVERSIONFLAGS"> $AR"> $ARCHITECTURE"> $ARCOM"> @@ -216,6 +218,10 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $HOST_ARCH"> $HOST_OS"> $IDLSUFFIXES"> +$IMPLIBNOVERSIONSYMLINKS"> +$IMPLIBPREFIX"> +$IMPLIBSUFFIX"> +$IMPLIBVERSION"> $IMPLICIT_COMMAND_DEPENDENCIES"> $INCPREFIX"> $INCSUFFIX"> @@ -253,8 +259,13 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $LDMODULECOM"> $LDMODULECOMSTR"> $LDMODULEFLAGS"> +$LDMODULENOVERSIONSYMLINKS"> $LDMODULEPREFIX"> +$_LDMODULESONAME"> $LDMODULESUFFIX"> +$LDMODULEVERSION"> +$LDMODULEVERSIONFLAGS"> +$_LDMODULEVERSIONFLAGS"> $LEX"> $LEXCOM"> $LEXCOMSTR"> @@ -505,15 +516,20 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $SHFORTRANPPCOM"> $SHFORTRANPPCOMSTR"> $SHLIBEMITTER"> +$SHLIBNOVERSIONSYMLINKS"> $SHLIBPREFIX"> +$_SHLIBSONAME"> $SHLIBSUFFIX"> $SHLIBVERSION"> +$SHLIBVERSIONFLAGS"> +$_SHLIBVERSIONFLAGS"> $SHLINK"> $SHLINKCOM"> $SHLINKCOMSTR"> $SHLINKFLAGS"> $SHOBJPREFIX"> $SHOBJSUFFIX"> +$SONAME"> $SOURCE"> $SOURCE_URL"> $SOURCES"> @@ -646,6 +662,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. --> +$__LDMODULEVERSIONFLAGS"> +$__SHLIBVERSIONFLAGS"> $AR"> $ARCHITECTURE"> $ARCOM"> @@ -854,6 +872,10 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $HOST_ARCH"> $HOST_OS"> $IDLSUFFIXES"> +$IMPLIBNOVERSIONSYMLINKS"> +$IMPLIBPREFIX"> +$IMPLIBSUFFIX"> +$IMPLIBVERSION"> $IMPLICIT_COMMAND_DEPENDENCIES"> $INCPREFIX"> $INCSUFFIX"> @@ -891,8 +913,13 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $LDMODULECOM"> $LDMODULECOMSTR"> $LDMODULEFLAGS"> +$LDMODULENOVERSIONSYMLINKS"> $LDMODULEPREFIX"> +$_LDMODULESONAME"> $LDMODULESUFFIX"> +$LDMODULEVERSION"> +$LDMODULEVERSIONFLAGS"> +$_LDMODULEVERSIONFLAGS"> $LEX"> $LEXCOM"> $LEXCOMSTR"> @@ -1143,15 +1170,20 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $SHFORTRANPPCOM"> $SHFORTRANPPCOMSTR"> $SHLIBEMITTER"> +$SHLIBNOVERSIONSYMLINKS"> $SHLIBPREFIX"> +$_SHLIBSONAME"> $SHLIBSUFFIX"> $SHLIBVERSION"> +$SHLIBVERSIONFLAGS"> +$_SHLIBVERSIONFLAGS"> $SHLINK"> $SHLINKCOM"> $SHLINKCOMSTR"> $SHLINKFLAGS"> $SHOBJPREFIX"> $SHOBJSUFFIX"> +$SONAME"> $SOURCE"> $SOURCE_URL"> $SOURCES"> diff --git a/doc/user/output.xml b/doc/user/output.xml index cdb28d7..78dcca4 100644 --- a/doc/user/output.xml +++ b/doc/user/output.xml @@ -83,6 +83,21 @@ Type: 'scons program' to build the production program, + Optionally, one can specify the append flag: + + + + + +Help(""" +Type: 'scons program' to build the production program, + 'scons debug' to build the debug version. +""", append=True) + + + + + (Note the above use of the Python triple-quote syntax, which comes in very handy for specifying multi-line strings like help text.) @@ -120,6 +135,13 @@ Type: 'scons program' to build the production program, + When used with &AddOption; Help("text", append=False) will clobber any help output associated with AddOption(). + To preserve the help output from AddOption(), set append=True. + + + + + Another use would be to make the help text conditional on some variable. For example, suppose you only want to display diff --git a/src/engine/SCons/Script/SConscript.xml b/src/engine/SCons/Script/SConscript.xml index c74ad5e..8553fbe 100644 --- a/src/engine/SCons/Script/SConscript.xml +++ b/src/engine/SCons/Script/SConscript.xml @@ -240,7 +240,7 @@ file is found. -(text) +(text, append=False) @@ -248,12 +248,18 @@ This specifies help text to be printed if the argument is given to &scons;. -If +If &f-Help; -is called multiple times, the text is appended together in the order -that +is called multiple times, the text is appended together in the order that &f-Help; -is called. +is called. With append set to False, any +&f-Help; +text generated with +&f-AddOption; +is clobbered. If append is True, the AddOption help is prepended to the help +string, thus preserving the + +message. -- cgit v0.12 From 0a76f5e2f9a3b55995014fc18881bdb068765817 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 29 Sep 2015 08:52:43 -0700 Subject: Removed 'Local Build Variables:' from output when append flag for help is True. This change breaks a bunch of tests and isn't core to the bug itself --- src/engine/SCons/Script/__init__.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py index 4dcd055..6bfc36f 100644 --- a/src/engine/SCons/Script/__init__.py +++ b/src/engine/SCons/Script/__init__.py @@ -269,10 +269,16 @@ def HelpFunction(text, append=False): help_text = s.getvalue() s.close() else: - help_text = "" - help_text = help_text + "\nLocal Build Variables:\n" + text - else: - help_text = help_text + text + help_text = "" +# +# Was in original patch but this text is arbitrary and breaks tests +# so I removed it (Deegan) +# help_text = help_text + "\nLocal Build Variables:\n" + text +# else: +# help_text = help_text + text + + help_text= help_text + text + # # Will be non-zero if we are reading an SConscript file. -- cgit v0.12 From a0a71904847f0ea0434bdce3a93dd730bd2a0bbb Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 29 Sep 2015 08:54:32 -0700 Subject: test for pull request #226 bug #2831 --- test/Help.py | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/test/Help.py b/test/Help.py index 747fe59..693fd28 100644 --- a/test/Help.py +++ b/test/Help.py @@ -82,6 +82,69 @@ Use scons -H for help about command-line options. test.run(arguments = '-h', stdout = expect) +# Bug #2831 - append flag to Help doesn't wipe out addoptions and variables used together +test.write('SConstruct', r""" + +AddOption('--debugging', + dest='debugging', + action='store_true', + default=False, + metavar='BDEBUGGING', + help='Compile with debugging symbols') + +vars = Variables() +vars.Add(ListVariable('buildmod', 'List of modules to build', 'none', + ['python'])) + +env = Environment() + +Help(vars.GenerateHelpText(env),append=True) +""") + +expect = ".*--debugging.*Compile with debugging symbols.*buildmod: List of modules to build.*" + +test.run(arguments = '-h', stdout = expect, match=TestSCons.match_re_dotall) + + +# Bug 2831 +# This test checks to verify that append=False doesn't include anything +# but the expected help for the specified Variable() + +test.write('SConstruct', r""" + +AddOption('--debugging', + dest='debugging', + action='store_true', + default=False, + metavar='BDEBUGGING', + help='Compile with debugging symbols') + +vars = Variables() +vars.Add(ListVariable('buildmod', 'List of modules to build', 'none', + ['python'])) + +env = Environment() + +Help(vars.GenerateHelpText(env),append=False) +""") + +expect = """\ +scons: Reading SConscript files ... +scons: done reading SConscript files. + +buildmod: List of modules to build + (all|none|comma-separated list of names) + allowed names: python + default: none + actual: None + +Use scons -H for help about command-line options. +""" + +test.run(arguments = '-h', stdout = expect) + + + test.pass_test() # Local Variables: -- cgit v0.12 From 47dfbcf847f63eb6b22c8579cf125b54d3166414 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 29 Sep 2015 08:59:18 -0700 Subject: Moved Dirks changes.txt change for fixin SVG license into the 2.4.1 section of CHANGES.txt --- src/CHANGES.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 11fdeba..bafd0d1 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -43,6 +43,11 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Library versioning is currently implemented for the following linker tools: 'cyglink', 'gnulink', 'sunlink'. + From Dirk Baechle: + - Fixed license of SVG titlepage files in the context of Debian + packaging, such that they allow for commercial use too (#2985). + + RELEASE 2.4.0 - Mon, 21 Sep 2015 08:56:00 -0700 From Dirk Baechle: @@ -81,8 +86,6 @@ RELEASE 2.3.5 - Mon, 17 Jun 2015 21:07:32 -0700 From Dirk Baechle: - Added new method rentry_exists_on_disk to Node.FS (PR #193). - - Fixed license of SVG titlepage files in the context of Debian - packaging, such that they allow for commercial use too (#2985). From Russel Winder: - Fixed several D tests under the different OS. -- cgit v0.12 From 935b462d736bc8d9622bd9719a83cacf5d406d53 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 29 Sep 2015 09:36:48 -0700 Subject: fix test which was verifying that PrintHelp wasn't in SCons.script because at some point in the past there was such a function which was removed. Pull request #226 for bug #2831 restored/recreated a same named function and broke this test --- test/Script-import.py | 1 - 1 file changed, 1 deletion(-) diff --git a/test/Script-import.py b/test/Script-import.py index 98ae271..504de0e 100644 --- a/test/Script-import.py +++ b/test/Script-import.py @@ -62,7 +62,6 @@ SCons.Script.CleanTask SCons.Script.QuestionTask old_SCons_Script_variables = [ - 'PrintHelp', 'OptParser', 'keep_going_on_error', 'print_explanations', -- cgit v0.12 From 739878908fb7b8ffae09804369069ee33056dec5 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 29 Sep 2015 09:53:39 -0700 Subject: added emacs temp files to hgignore --- .hgignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgignore b/.hgignore index dcc9505..a56960d 100644 --- a/.hgignore +++ b/.hgignore @@ -10,6 +10,7 @@ syntax:glob *.xcodeproj *.orig *.DS_Store +*# doc/user/scons-user doc/user/scons_db.xml -- cgit v0.12 From 089b32203cb485b9115f03f35d2b437e848c78da Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 29 Sep 2015 11:22:17 -0700 Subject: Fix failing LEX/live.py because no return type was specified for main and apple compiler/flex complains about it in stderr --- test/LEX/live.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/LEX/live.py b/test/LEX/live.py index f50b06f..e4b4dfb 100644 --- a/test/LEX/live.py +++ b/test/LEX/live.py @@ -68,6 +68,7 @@ yywrap() return 1; } +int main() { yylex(); -- cgit v0.12 From 2355e88c9637174f10c3dec3efb15ee6626fb3e5 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 29 Sep 2015 12:05:35 -0700 Subject: fix test to run on macosx by fixing C99 non compliance --- test/RANLIB/RANLIB.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/RANLIB/RANLIB.py b/test/RANLIB/RANLIB.py index c9fc10f..fbfe36c 100644 --- a/test/RANLIB/RANLIB.py +++ b/test/RANLIB/RANLIB.py @@ -81,6 +81,10 @@ library_function(void) test.write('main.c', r""" #include + +void +library_function(void); + int main(int argc, char *argv[]) { -- cgit v0.12 From 6ea319bd567743546bb77c6440ddb80d9a63b3cb Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 29 Sep 2015 12:35:18 -0700 Subject: fix C99 non compliance --- test/RANLIB/RANLIBFLAGS.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/RANLIB/RANLIBFLAGS.py b/test/RANLIB/RANLIBFLAGS.py index 636059b..86e5283 100644 --- a/test/RANLIB/RANLIBFLAGS.py +++ b/test/RANLIB/RANLIBFLAGS.py @@ -82,6 +82,10 @@ library_function(void) test.write('main.c', r""" #include +void +library_function(void); + + int main(int argc, char *argv[]) { -- cgit v0.12 From f067b35d278ddafcc4e48668f0eade10c71a69c0 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 29 Sep 2015 13:18:21 -0700 Subject: add another possible path for JAVA_HOME on OSX --- QMTest/TestSCons.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/QMTest/TestSCons.py b/QMTest/TestSCons.py index 06fa575..75bf395 100644 --- a/QMTest/TestSCons.py +++ b/QMTest/TestSCons.py @@ -714,6 +714,9 @@ class TestSCons(TestCommon): home = '/System/Library/Frameworks/JavaVM.framework/Home' else: home = '/System/Library/Frameworks/JavaVM.framework/Versions/%s/Home' % version + if not os.path.exists(home): + # This works on OSX 10.10 + home = '/System/Library/Frameworks/JavaVM.framework/Versions/Current/' else: jar = self.java_where_jar(version) home = os.path.normpath('%s/..'%jar) -- cgit v0.12 From c4fc0ad2e86ca03de81332cc984db0e0ccd98959 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 29 Sep 2015 13:22:24 -0700 Subject: Pull request # 234 (Bug #2840) code checkin. No tests yet --- src/engine/SCons/Builder.py | 6 +++--- test/CPPDEFINES/pkg-config.py | 11 ++++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py index 769b15d..52a592b 100644 --- a/src/engine/SCons/Builder.py +++ b/src/engine/SCons/Builder.py @@ -292,9 +292,9 @@ def _node_errors(builder, env, tlist, slist): if t.has_explicit_builder(): if not t.env is None and not t.env is env: action = t.builder.action - t_contents = action.get_contents(tlist, slist, t.env) - contents = action.get_contents(tlist, slist, env) - + t_contents = t.builder.action.get_contents(tlist, slist, t.env) + contents = builder.action.get_contents(tlist, slist, env) + if t_contents == contents: msg = "Two different environments were specified for target %s,\n\tbut they appear to have the same action: %s" % (t, action.genstring(tlist, slist, t.env)) SCons.Warnings.warn(SCons.Warnings.DuplicateEnvironmentWarning, msg) diff --git a/test/CPPDEFINES/pkg-config.py b/test/CPPDEFINES/pkg-config.py index 0656900..1b308d3 100644 --- a/test/CPPDEFINES/pkg-config.py +++ b/test/CPPDEFINES/pkg-config.py @@ -32,7 +32,8 @@ import TestSCons test = TestSCons.TestSCons() -if not test.where_is('pkg-config'): +pkg_config_path = test.where_is('pkg-config') +if not pkg_config_path: test.skip_test("Could not find 'pkg-config' in system PATH, skipping test.\n") test.write('bug.pc', """\ @@ -58,7 +59,7 @@ test.write('SConstruct', """\ # http://scons.tigris.org/issues/show_bug.cgi?id=2671 # Passing test cases env_1 = Environment(CPPDEFINES=[('DEBUG','1'), 'TEST']) -env_1.ParseConfig('PKG_CONFIG_PATH=. pkg-config --cflags bug') +env_1.ParseConfig('PKG_CONFIG_PATH=. %(pkg_config_path)s --cflags bug') print env_1.subst('$_CPPDEFFLAGS') env_2 = Environment(CPPDEFINES=[('DEBUG','1'), 'TEST']) @@ -67,7 +68,7 @@ print env_2.subst('$_CPPDEFFLAGS') # Failing test cases env_3 = Environment(CPPDEFINES={'DEBUG':1, 'TEST':None}) -env_3.ParseConfig('PKG_CONFIG_PATH=. pkg-config --cflags bug') +env_3.ParseConfig('PKG_CONFIG_PATH=. %(pkg_config_path)s --cflags bug') print env_3.subst('$_CPPDEFFLAGS') env_4 = Environment(CPPDEFINES={'DEBUG':1, 'TEST':None}) @@ -76,10 +77,10 @@ print env_4.subst('$_CPPDEFFLAGS') # http://scons.tigris.org/issues/show_bug.cgi?id=1738 env_1738_1 = Environment(tools=['default']) -env_1738_1.ParseConfig('PKG_CONFIG_PATH=. pkg-config --cflags --libs bug') +env_1738_1.ParseConfig('PKG_CONFIG_PATH=. %(pkg_config_path)s --cflags --libs bug') env_1738_1.Append(CPPDEFINES={'value' : '1'}) print env_1738_1.subst('$_CPPDEFFLAGS') -""") +"""%locals() ) expect_print_output="""\ -DDEBUG=1 -DTEST -DSOMETHING -DVARIABLE=2 -- cgit v0.12 From 9794cbe901096e0835bd4db0958826ec9ed316f4 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 29 Sep 2015 15:20:11 -0700 Subject: Revised pull request #234 fixing bug 2840. Andrew Featherstone had code changes, but no test --- src/CHANGES.txt | 5 ++++ src/engine/SCons/Builder.py | 1 + test/Builder/different-actions.py | 56 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 test/Builder/different-actions.py diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 47a3f97..e27f978 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -18,6 +18,11 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Added new configure check, CheckProg, to check for existence of a program. + From Andrew Featherstone: + - Fix for issue #2840 - Fix for two environments specifying same target with different + actions not throwing hard error. Instead SCons was incorrectly issuing a warning + and continuing. + From Florian Miedniak: - Fixed tigris issue #3011: Glob() excludes didn't work when used with VariantDir(duplicate=0) diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py index 52a592b..c86012b 100644 --- a/src/engine/SCons/Builder.py +++ b/src/engine/SCons/Builder.py @@ -292,6 +292,7 @@ def _node_errors(builder, env, tlist, slist): if t.has_explicit_builder(): if not t.env is None and not t.env is env: action = t.builder.action + t_contents = t.builder.action.get_contents(tlist, slist, t.env) contents = builder.action.get_contents(tlist, slist, env) diff --git a/test/Builder/different-actions.py b/test/Builder/different-actions.py new file mode 100644 index 0000000..33a1363 --- /dev/null +++ b/test/Builder/different-actions.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# 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. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that two builders in two environments with different +actions generate an error. +""" + +import TestSCons + +test = TestSCons.TestSCons(match=TestSCons.match_re) + +test.write('SConstruct', """\ +e1 = Environment() +e2 = Environment() + +e1.Command('out.txt', [], 'echo 1 > $TARGET') +e2.Command('out.txt', [], 'echo 2 > $TARGET') +""") + +expect = TestSCons.re_escape(""" +scons: *** Two environments with different actions were specified for the same target: out.txt +""") + TestSCons.file_expr + +test.run(arguments='out.txt', status=2, stderr=expect) + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From 7a02c48b0d3e29f4f24b0a3fec8fc566a131a66d Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 29 Sep 2015 15:58:10 -0700 Subject: fix CheckProg test to work on win32 --- src/engine/SCons/SConfTests.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/engine/SCons/SConfTests.py b/src/engine/SCons/SConfTests.py index 57a9d04..c9df0be 100644 --- a/src/engine/SCons/SConfTests.py +++ b/src/engine/SCons/SConfTests.py @@ -620,8 +620,14 @@ int main() { log_file=self.test.workpath('config.log')) try: - r = sconf.CheckProg('sh') - assert r, "/bin/sh" + if os.name != 'nt': + r = sconf.CheckProg('sh') + assert r, "/bin/sh" + else: + r = sconf.CheckProg('cmd.exe') + assertIn('cmd.exe',r) + + r = sconf.CheckProg('hopefully-not-a-program') assert r is None -- cgit v0.12 From 94c7bf6f844758f8f9a3b993bae88e91fc1fe452 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 30 Sep 2015 19:42:56 -0400 Subject: fix broken on windows test in SConfTest.py --- src/engine/SCons/SConfTests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/SCons/SConfTests.py b/src/engine/SCons/SConfTests.py index c9df0be..9bdfceb 100644 --- a/src/engine/SCons/SConfTests.py +++ b/src/engine/SCons/SConfTests.py @@ -625,7 +625,7 @@ int main() { assert r, "/bin/sh" else: r = sconf.CheckProg('cmd.exe') - assertIn('cmd.exe',r) + self.assertIn('cmd.exe',r) r = sconf.CheckProg('hopefully-not-a-program') -- cgit v0.12 From 615a3429f4ad7aef9d3ffb19a56c26ebb8a2b1cf Mon Sep 17 00:00:00 2001 From: William Blevins Date: Thu, 1 Oct 2015 13:31:34 +0100 Subject: Corrected hgignore regex for emacs temporary files. --- .hgignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.hgignore b/.hgignore index a56960d..3e16531 100644 --- a/.hgignore +++ b/.hgignore @@ -10,7 +10,7 @@ syntax:glob *.xcodeproj *.orig *.DS_Store -*# +*\# doc/user/scons-user doc/user/scons_db.xml -- cgit v0.12 From 4bac666bb4f85f0efe0b4002a527c9f4b510c306 Mon Sep 17 00:00:00 2001 From: William Blevins Date: Thu, 1 Oct 2015 13:37:41 +0100 Subject: Code cleanup: removed function for supporting relpath in pre-2.6 python. --- src/engine/SCons/Tool/GettextCommon.py | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/src/engine/SCons/Tool/GettextCommon.py b/src/engine/SCons/Tool/GettextCommon.py index cd2f306..bdd52c0 100644 --- a/src/engine/SCons/Tool/GettextCommon.py +++ b/src/engine/SCons/Tool/GettextCommon.py @@ -306,23 +306,6 @@ class RPaths(object): - Tuple of strings, which represent paths relative to current working directory (for given environment). """ - # os.path.relpath is available only on python >= 2.6. We use our own - # implementation. It's taken from BareNecessities package: - # http://jimmyg.org/work/code/barenecessities/index.html - from posixpath import curdir - def relpath(path, start=curdir): - import posixpath - """Return a relative version of a path""" - if not path: - raise ValueError("no path specified") - start_list = posixpath.abspath(start).split(posixpath.sep) - path_list = posixpath.abspath(path).split(posixpath.sep) - # Work out how much of the filepath is shared by start and path. - i = len(posixpath.commonprefix([start_list, path_list])) - rel_list = [posixpath.pardir] * (len(start_list)-i) + path_list[i:] - if not rel_list: - return posixpath.curdir - return posixpath.join(*rel_list) import os import SCons.Node.FS rpaths = () @@ -330,7 +313,7 @@ class RPaths(object): for node in nodes: rpath = None if isinstance(node, SCons.Node.FS.Base): - rpath = relpath(node.get_abspath(), cwd) + rpath = os.path.relpath(node.get_abspath(), cwd) # FIXME: Other types possible here? if rpath is not None: rpaths += (rpath,) -- cgit v0.12 From 139c0c0bf9e1d5a789a05628dee7efddd5dfbfbe Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 1 Oct 2015 17:44:15 -0400 Subject: Bug # 2791 - minor change to setup.py makes the package installable with jython. Seems better to check if the current system has the capabilities needed by the logic than to look for posix --- src/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/setup.py b/src/setup.py index fb16bdd..91b7752 100644 --- a/src/setup.py +++ b/src/setup.py @@ -343,7 +343,7 @@ class install_scripts(_install_scripts): self.copy_scons(src, scons_version_bat) # --- distutils copy/paste --- - if os.name == 'posix': + if hasattr(os, 'chmod') and hasattr(os,'stat'): # Set the executable bits (owner, group, and world) on # all the scripts we just installed. for file in self.get_outputs(): -- cgit v0.12 From e906e28a107c1db871d79745de2798a3d0992900 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 1 Oct 2015 18:16:59 -0400 Subject: update Changes for bug 2791 --- src/CHANGES.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index e27f978..5c2d8d3 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -6,6 +6,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER + From Arfrever Frehtes Taifersar Arahesis: + - Fix for Bug # 2791 - Setup.py fails unnecessarily under Jython. + From Dirk Baechle: - Fixed license of SVG titlepage files in the context of Debian packaging, such that they allow for commercial use too (#2985). -- cgit v0.12 From 080663ec198503579048f297f2a4c154d13d169d Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 2 Oct 2015 10:16:00 -0400 Subject: Add changelog for pull request #222 --- src/CHANGES.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 5c2d8d3..e67de21 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -26,6 +26,10 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER actions not throwing hard error. Instead SCons was incorrectly issuing a warning and continuing. + From Hiroaki Itoh : + - Add support `Microsoft Visual C++ Compiler for Python 2.7' + Compiler can be obtained at: https://www.microsoft.com/en-us/download/details.aspx?id=44266 + From Florian Miedniak: - Fixed tigris issue #3011: Glob() excludes didn't work when used with VariantDir(duplicate=0) -- cgit v0.12 From ee7a6695240de8f36b24d2bd024da76617ec7890 Mon Sep 17 00:00:00 2001 From: Pawel Tomulik Date: Sat, 17 Oct 2015 09:25:16 +0200 Subject: small enchancement to swig tool --- src/engine/SCons/Tool/swig.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/engine/SCons/Tool/swig.py b/src/engine/SCons/Tool/swig.py index a315182..8828ef1 100644 --- a/src/engine/SCons/Tool/swig.py +++ b/src/engine/SCons/Tool/swig.py @@ -44,6 +44,8 @@ import SCons.Tool import SCons.Util import SCons.Node +swigs = [ 'swig', 'swig3.0', 'swig2.0' ] + SwigAction = SCons.Action.Action('$SWIGCOM', '$SWIGCOMSTR') def swigSuffixEmitter(env, source): @@ -160,7 +162,8 @@ def generate(env): java_file.add_action('.i', SwigAction) java_file.add_emitter('.i', _swigEmitter) - env['SWIG'] = 'swig' + if 'SWIG' not in env: + env['SWIG'] = env.Detect(swigs) or swigs[0] env['SWIGVERSION'] = _get_swig_version(env) env['SWIGFLAGS'] = SCons.Util.CLVar('') env['SWIGDIRECTORSUFFIX'] = '_wrap.h' -- cgit v0.12 From bf2c481c10c280ecc352c7ea0ca45d8304a5f7d3 Mon Sep 17 00:00:00 2001 From: Pawel Tomulik Date: Sun, 18 Oct 2015 17:57:26 +0200 Subject: add blurb to src/CHANGES.txt for PR #270 --- src/CHANGES.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index e67de21..823eb4b 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -6,6 +6,10 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER + From Paweł Tomulik: + - Fix to swig tool - pick-up 'swig', 'swig3.0' and 'swig2.0' (in order). + - Fix to swig tool - respect env['SWIG'] provided by user. + From Arfrever Frehtes Taifersar Arahesis: - Fix for Bug # 2791 - Setup.py fails unnecessarily under Jython. -- cgit v0.12 From 3cde69b6fb17c84aaf4fca368feb63cefd44ce97 Mon Sep 17 00:00:00 2001 From: Pawel Tomulik Date: Mon, 19 Oct 2015 20:11:36 +0200 Subject: edit test/SWIG/SWIG.py to covert PR #270 --- test/SWIG/SWIG.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/test/SWIG/SWIG.py b/test/SWIG/SWIG.py index 96e00e7..d53fa49 100644 --- a/test/SWIG/SWIG.py +++ b/test/SWIG/SWIG.py @@ -43,10 +43,20 @@ if not python: test.write('myswig.py', r""" import getopt import sys -opts, args = getopt.getopt(sys.argv[1:], 'c:o:') +opts, args = getopt.getopt(sys.argv[1:], 'c:o:v:') for opt, arg in opts: if opt == '-c': pass elif opt == '-o': out = arg + elif opt == '-v' and arg == 'ersion': + print "" + print "SWIG Version 0.1.2" + print "" + print "Compiled with g++ [x86_64-pc-linux-gnu]" + print "" + print "Configured options: +pcre" + print "" + print "Please see http://www.swig.org for reporting bugs and further information" + sys.exit(0) infile = open(args[0], 'rb') outfile = open(out, 'wb') for l in infile.readlines(): @@ -58,6 +68,7 @@ sys.exit(0) test.write('SConstruct', """ env = Environment(tools=['default', 'swig'], SWIG = [r'%(python)s', 'myswig.py']) +print env.subst("Using SWIG $SWIGVERSION") env.Program(target = 'test1', source = 'test1.i') env.CFile(target = 'test2', source = 'test2.i') env.Clone(SWIGFLAGS = '-c++').Program(target = 'test3', source = 'test3.i') @@ -91,7 +102,7 @@ main(int argc, char *argv[]) { swig """) -test.run(arguments = '.', stderr = None) +test.run(arguments = '.', stderr = None, stdout = r'.*Using SWIG 0.1.2.*', match = TestSCons.match_re_dotall) test.run(program = test.workpath('test1' + _exe), stdout = "test1.i\n") test.must_exist(test.workpath('test1_wrap.c')) -- cgit v0.12 From f1f51552641c5137d5196b962446dfe2f7236995 Mon Sep 17 00:00:00 2001 From: Pawel Tomulik Date: Mon, 19 Oct 2015 20:13:55 +0200 Subject: fix swig tool to properly retrieve swig version --- src/engine/SCons/Tool/swig.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/engine/SCons/Tool/swig.py b/src/engine/SCons/Tool/swig.py index 8828ef1..44686ef 100644 --- a/src/engine/SCons/Tool/swig.py +++ b/src/engine/SCons/Tool/swig.py @@ -130,9 +130,10 @@ def _swigEmitter(target, source, env): target.extend(java_files) return (target, source) -def _get_swig_version(env): +def _get_swig_version(env, swig): """Run the SWIG command line tool to get and return the version number""" - pipe = SCons.Action._subproc(env, [env['SWIG'], '-version'], + swig = env.subst(swig) + pipe = SCons.Action._subproc(env, SCons.Util.CLVar(swig) + ['-version'], stdin = 'devnull', stderr = 'devnull', stdout = subprocess.PIPE) @@ -164,7 +165,7 @@ def generate(env): if 'SWIG' not in env: env['SWIG'] = env.Detect(swigs) or swigs[0] - env['SWIGVERSION'] = _get_swig_version(env) + env['SWIGVERSION'] = _get_swig_version(env, env['SWIG']) env['SWIGFLAGS'] = SCons.Util.CLVar('') env['SWIGDIRECTORSUFFIX'] = '_wrap.h' env['SWIGCFILESUFFIX'] = '_wrap$CFILESUFFIX' -- cgit v0.12 From c2428e8d97e15df9ca267f2dc574158cd9a0d8ac Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 21 Oct 2015 17:53:28 -0700 Subject: Kick buildbot --- README.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/README.rst b/README.rst index 05be712..35ead76 100644 --- a/README.rst +++ b/README.rst @@ -750,3 +750,4 @@ many contributors, including but not at all limited to: Copyright (c) 2001 - 2015 The SCons Foundation + -- cgit v0.12 From 8fb4d9a12e7924c40357ba748d1ce71981cb975f Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 22 Oct 2015 07:41:51 -0700 Subject: Kick buildbot --- README.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/README.rst b/README.rst index 35ead76..05be712 100644 --- a/README.rst +++ b/README.rst @@ -750,4 +750,3 @@ many contributors, including but not at all limited to: Copyright (c) 2001 - 2015 The SCons Foundation - -- cgit v0.12 From dec3978a72f6d65a0a8c8e4e180ff7b658c9f630 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 9 Nov 2015 09:30:07 -0800 Subject: merge changes from 2.4.1 release to default --- QMTest/TestSCons.py | 2 +- README.rst | 34 ++++----- ReleaseConfig | 2 +- SConstruct | 4 +- debian/changelog | 6 ++ doc/generated/examples/caching_ex-random_1.xml | 2 +- .../examples/commandline_Variables_Help_1.xml | 2 - doc/generated/examples/output_ex1_1.xml | 2 - doc/generated/examples/output_ex2_1.xml | 2 - doc/generated/examples/output_ex2_2.xml | 2 - doc/generated/examples/troubleshoot_explain1_3.xml | 2 +- doc/generated/tools.gen | 12 +-- doc/generated/tools.mod | 4 +- doc/generated/variables.gen | 20 ++--- doc/generated/variables.mod | 4 +- src/Announce.txt | 79 ++++++++++++++++--- src/CHANGES.txt | 8 +- src/RELEASE.txt | 88 +++++++++++----------- 18 files changed, 161 insertions(+), 114 deletions(-) diff --git a/QMTest/TestSCons.py b/QMTest/TestSCons.py index 75bf395..ef70261 100644 --- a/QMTest/TestSCons.py +++ b/QMTest/TestSCons.py @@ -34,7 +34,7 @@ from TestCmd import PIPE # here provides some independent verification that what we packaged # conforms to what we expect. -default_version = '2.4.0' +default_version = '2.4.1' python_version_unsupported = (2, 3, 0) python_version_deprecated = (2, 7, 0) diff --git a/README.rst b/README.rst index 05be712..a2b15a6 100644 --- a/README.rst +++ b/README.rst @@ -156,7 +156,7 @@ Or on Windows:: By default, the above commands will do the following: -- Install the version-numbered "scons-2.4.0" and "sconsign-2.4.0" scripts in +- Install the version-numbered "scons-2.4.1" and "sconsign-2.4.1" scripts in the default system script directory (/usr/bin or C:\\Python\*\\Scripts, for example). This can be disabled by specifying the "--no-version-script" option on the command line. @@ -168,16 +168,16 @@ By default, the above commands will do the following: before making it the default on your system. On UNIX or Linux systems, you can have the "scons" and "sconsign" scripts be - hard links or symbolic links to the "scons-2.4.0" and "sconsign-2.4.0" + hard links or symbolic links to the "scons-2.4.1" and "sconsign-2.4.1" scripts by specifying the "--hardlink-scons" or "--symlink-scons" options on the command line. -- Install "scons-2.4.0.bat" and "scons.bat" wrapper scripts in the Python +- Install "scons-2.4.1.bat" and "scons.bat" wrapper scripts in the Python prefix directory on Windows (C:\\Python\*, for example). This can be disabled by specifying the "--no-install-bat" option on the command line. On UNIX or Linux systems, the "--install-bat" option may be specified to - have "scons-2.4.0.bat" and "scons.bat" files installed in the default system + have "scons-2.4.1.bat" and "scons.bat" files installed in the default system script directory, which is useful if you want to install SCons in a shared file system directory that can be used to execute SCons from both UNIX/Linux and Windows systems. @@ -462,7 +462,7 @@ running all of "runtest.py -a". Building Packages ================= -We use SCons (version 2.4.0 or later) to build its own packages. If you +We use SCons (version 2.4.1 or later) to build its own packages. If you already have an appropriate version of SCons installed on your system, you can build everything by simply running it:: @@ -477,18 +477,18 @@ about `Executing SCons Without Installing`_):: Depending on the utilities installed on your system, any or all of the following packages will be built:: - build/dist/scons-2.4.0-1.noarch.rpm - build/dist/scons-2.4.0-1.src.rpm - build/dist/scons-2.4.0.linux-i686.tar.gz - build/dist/scons-2.4.0.tar.gz - build/dist/scons-2.4.0.win32.exe - build/dist/scons-2.4.0.zip - build/dist/scons-doc-2.4.0.tar.gz - build/dist/scons-local-2.4.0.tar.gz - build/dist/scons-local-2.4.0.zip - build/dist/scons-src-2.4.0.tar.gz - build/dist/scons-src-2.4.0.zip - build/dist/scons_2.4.0-1_all.deb + build/dist/scons-2.4.1-1.noarch.rpm + build/dist/scons-2.4.1-1.src.rpm + build/dist/scons-2.4.1.linux-i686.tar.gz + build/dist/scons-2.4.1.tar.gz + build/dist/scons-2.4.1.win32.exe + build/dist/scons-2.4.1.zip + build/dist/scons-doc-2.4.1.tar.gz + build/dist/scons-local-2.4.1.tar.gz + build/dist/scons-local-2.4.1.zip + build/dist/scons-src-2.4.1.tar.gz + build/dist/scons-src-2.4.1.zip + build/dist/scons_2.4.1-1_all.deb The SConstruct file is supposed to be smart enough to avoid trying to build packages for which you don't have the proper utilities installed. For diff --git a/ReleaseConfig b/ReleaseConfig index 6194438..4396248 100644 --- a/ReleaseConfig +++ b/ReleaseConfig @@ -32,7 +32,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" # 'final', the patchlevel is set to the release date. This value is # mandatory and must be present in this file. #version_tuple = (2, 2, 0, 'final', 0) -version_tuple = (2, 4, 1, 'alpha', 0) +version_tuple = (2, 4, 1) # Python versions prior to unsupported_python_version cause a fatal error # when that version is used. Python versions prior to deprecate_python_version diff --git a/SConstruct b/SConstruct index 4bff134..79249e9 100644 --- a/SConstruct +++ b/SConstruct @@ -6,7 +6,7 @@ copyright_years = '2001 - 2015' # This gets inserted into the man pages to reflect the month of release. -month_year = 'September 2015' +month_year = 'November 2015' # # __COPYRIGHT__ @@ -43,7 +43,7 @@ import tempfile import bootstrap project = 'scons' -default_version = '2.4.0' +default_version = '2.4.1' copyright = "Copyright (c) %s The SCons Foundation" % copyright_years platform = distutils.util.get_platform() diff --git a/debian/changelog b/debian/changelog index 7311f78..9d60e3a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +scons (2.4.1) unstable; urgency=low + + * Maintenance release. + + -- William Deegan Sat, 07 Nov 2015 08:56:00 -0700 + scons (2.4.0) unstable; urgency=low * Maintenance release. diff --git a/doc/generated/examples/caching_ex-random_1.xml b/doc/generated/examples/caching_ex-random_1.xml index 904e1dd..6a0337b 100644 --- a/doc/generated/examples/caching_ex-random_1.xml +++ b/doc/generated/examples/caching_ex-random_1.xml @@ -1,9 +1,9 @@ % scons -Q cc -o f2.o -c f2.c +cc -o f1.o -c f1.c cc -o f5.o -c f5.c cc -o f3.o -c f3.c cc -o f4.o -c f4.c -cc -o f1.o -c f1.c cc -o prog f1.o f2.o f3.o f4.o f5.o diff --git a/doc/generated/examples/commandline_Variables_Help_1.xml b/doc/generated/examples/commandline_Variables_Help_1.xml index 76f13c5..db171eb 100644 --- a/doc/generated/examples/commandline_Variables_Help_1.xml +++ b/doc/generated/examples/commandline_Variables_Help_1.xml @@ -1,8 +1,6 @@ % scons -Q -h -Local Build Variables: - RELEASE: Set to 1 to build for release default: 0 actual: 0 diff --git a/doc/generated/examples/output_ex1_1.xml b/doc/generated/examples/output_ex1_1.xml index 2607243..535960b 100644 --- a/doc/generated/examples/output_ex1_1.xml +++ b/doc/generated/examples/output_ex1_1.xml @@ -3,8 +3,6 @@ scons: Reading SConscript files ... scons: done reading SConscript files. -Local Build Variables: - Type: 'scons program' to build the production program, 'scons debug' to build the debug version. diff --git a/doc/generated/examples/output_ex2_1.xml b/doc/generated/examples/output_ex2_1.xml index 74d7192..e951c3a 100644 --- a/doc/generated/examples/output_ex2_1.xml +++ b/doc/generated/examples/output_ex2_1.xml @@ -3,8 +3,6 @@ scons: Reading SConscript files ... scons: done reading SConscript files. -Local Build Variables: - Type: 'scons program' to build the production program. Type: 'scons windebug' to build the Windows debug version. diff --git a/doc/generated/examples/output_ex2_2.xml b/doc/generated/examples/output_ex2_2.xml index 9130d5a..8dca6c3 100644 --- a/doc/generated/examples/output_ex2_2.xml +++ b/doc/generated/examples/output_ex2_2.xml @@ -3,8 +3,6 @@ scons: Reading SConscript files ... scons: done reading SConscript files. -Local Build Variables: - Type: 'scons program' to build the production program. Use scons -H for help about command-line options. diff --git a/doc/generated/examples/troubleshoot_explain1_3.xml b/doc/generated/examples/troubleshoot_explain1_3.xml index 9763efe..3d8592d 100644 --- a/doc/generated/examples/troubleshoot_explain1_3.xml +++ b/doc/generated/examples/troubleshoot_explain1_3.xml @@ -3,5 +3,5 @@ cp file.in file.oout scons: warning: Cannot find target file.out after building -File "/home/bdbaddog/scons/scons/bootstrap/src/script/scons.py", line 199, in <module> +File "/scons/as_scons/bootstrap/src/script/scons.py", line 199, in <module> diff --git a/doc/generated/tools.gen b/doc/generated/tools.gen index fcb7587..ba12966 100644 --- a/doc/generated/tools.gen +++ b/doc/generated/tools.gen @@ -780,19 +780,19 @@ Sets construction variables for the Sets: &cv-link-AS;, &cv-link-ASCOM;, &cv-link-ASFLAGS;, &cv-link-ASPPCOM;, &cv-link-ASPPFLAGS;.Uses: &cv-link-ASCOMSTR;, &cv-link-ASPPCOMSTR;. - - packaging + + Packaging -A framework for building binary and source packages. +Sets construction variables for the Package Builder. - - Packaging + + packaging -Sets construction variables for the Package Builder. +A framework for building binary and source packages. diff --git a/doc/generated/tools.mod b/doc/generated/tools.mod index 1191e6a..2ee2270 100644 --- a/doc/generated/tools.mod +++ b/doc/generated/tools.mod @@ -78,8 +78,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. mwcc"> mwld"> nasm"> -packaging"> Packaging"> +packaging"> pdf"> pdflatex"> pdftex"> @@ -189,8 +189,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. mwcc"> mwld"> nasm"> -packaging"> Packaging"> +packaging"> pdf"> pdflatex"> pdftex"> diff --git a/doc/generated/variables.gen b/doc/generated/variables.gen index 3d8a87a..b377102 100644 --- a/doc/generated/variables.gen +++ b/doc/generated/variables.gen @@ -6553,16 +6553,6 @@ Example - - SHLIBVERSIONFLAGS - - -Extra flags added to $SHLINKCOM when building versioned -SharedLibrary. These flags are only used when $SHLIBVERSION is -set. - - - _SHLIBVERSIONFLAGS @@ -6576,6 +6566,16 @@ and some extra dynamically generated options (such as + + SHLIBVERSIONFLAGS + + +Extra flags added to $SHLINKCOM when building versioned +SharedLibrary. These flags are only used when $SHLIBVERSION is +set. + + + SHLINK diff --git a/doc/generated/variables.mod b/doc/generated/variables.mod index f7303f2..955a9eb 100644 --- a/doc/generated/variables.mod +++ b/doc/generated/variables.mod @@ -521,8 +521,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $_SHLIBSONAME"> $SHLIBSUFFIX"> $SHLIBVERSION"> -$SHLIBVERSIONFLAGS"> $_SHLIBVERSIONFLAGS"> +$SHLIBVERSIONFLAGS"> $SHLINK"> $SHLINKCOM"> $SHLINKCOMSTR"> @@ -1175,8 +1175,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $_SHLIBSONAME"> $SHLIBSUFFIX"> $SHLIBVERSION"> -$SHLIBVERSIONFLAGS"> $_SHLIBVERSIONFLAGS"> +$SHLIBVERSIONFLAGS"> $SHLINK"> $SHLINKCOM"> $SHLINKCOMSTR"> diff --git a/src/Announce.txt b/src/Announce.txt index 7a13b81..719b4d7 100644 --- a/src/Announce.txt +++ b/src/Announce.txt @@ -18,31 +18,86 @@ So that everyone using SCons can help each other learn how to use it more effectively, please go to http://scons.org/lists.php#users to sign up for the scons-users mailing list. -==============IMPORTANT NOTICE=========== +==============IMPORTANT NOTICE FOR NEXT VERSION V2.5.0========== +PLEASE READ. CHANGES COMING IN NEXT MAJOR RELEASE V2.5.0 -As has been pre-announced in SCons's mailing lists: +We're enhancing implicit language scanning functionality to improve +correctness. SCons now honors scanner keys for implicit dependencies +and correctly changes scanner type (if necessary) when traversing +implicit dependency trees. -* https://pairlist4.pair.net/pipermail/scons-users/2014-July/002734.html , -* https://pairlist2.pair.net/pipermail/scons-dev/2014-December/002107.html -* https://pairlist4.pair.net/pipermail/scons-users/2015-February/003454.html +This enhancement resolves missing dependencies +with built-in scanners including SWIG (#2264) and QT: +* http://scons.tigris.org/issues/show_bug.cgi?id=2264 -We're planning to switch the Node class to using "slots" in the core sources, -mainly to reduce memory consumption by up to 35% in large build projects. +This enhancement broadens the horizon for handling heterogeneous +data flow environments (E.G. software builds): +* http://article.gmane.org/gmane.comp.programming.tools.scons.user/26596 +Notes: -This feature has been tested extensively and we don't expect any problems for you. -However as with all major changes it would be wise to test V2.4.0 when it is -released. Especially if you are directly using the Node class. +* SCons may find new (and correct) dependencies in cross-langauge contexts. +** Update may cause rebuilds, especially in heterogeneous data environments. +** Update may find previously missed dependencies errors (E.G. cycles). +*** Discovered in some QT test cases. +* SCons handles the SCANNERS variable differently. +** Previously, the Install builder would scan implicit dependencies for + a scanner found in SCANNERS (but not for built-in scanners), but now + the Install builder will not scan recursively regardless in order + to optimize Install behaviour and bring orthogonality to previous behaviour. -================================================================= ++================================================================= -RELEASE VERSION/DATE TO BE FILLED IN LATER +RELEASE 2.4.1 - Mon, 07 Nov 2015 10:37:21 -0700 Please consult the RELEASE.txt file for a summary of changes since the last release and consult the CHANGES.txt file for complete a list of changes since last release. This announcement highlights only the important changes. + Please note the following important changes since release 2.4.0: + - Fix to swig tool - pick-up 'swig', 'swig3.0' and 'swig2.0' (in order). + - Fix to swig tool - respect env['SWIG'] provided by user. + - Fix for Bug # 2791 - Setup.py fails unnecessarily under Jython. + - Fixed license of SVG titlepage files in the context of Debian + packaging, such that they allow for commercial use too (#2985). + - InstallVersionedLib now available in the DefaultEnvironment context. + - Improves orthogonality of use cases between different Install functions. + - Added new configure check, CheckProg, to check for + existence of a program. + - Fix for issue #2840 - Fix for two environments specifying same target with different + actions not throwing hard error. Instead SCons was incorrectly issuing a warning + and continuing. + - Add support `Microsoft Visual C++ Compiler for Python 2.7' + Compiler can be obtained at: https://www.microsoft.com/en-us/download/details.aspx?id=44266 + - Fixed tigris issue #3011: Glob() excludes didn't work when used with VariantDir(duplicate=0) + - Fix bug 2831 and allow Help() text to be appended to AddOption() help. + - Reimplemented versioning for shared libraries, with the following effects + - Fixed tigris issues #3001, #3006. + - Fixed several other issues not reported to tigris, including: + issues with versioned libraries in subdirectories with tricky names, + issues with versioned libraries and variant directories, + issue with soname not being injected to library when using D linkers, + - Switched to direct symlinks instead of daisy-chained ones -- soname and + development symlinks point directly to the versioned shared library now), + for rationale see: + https://www.debian.org/doc/debian-policy/ch-sharedlibs.html + https://fedoraproject.org/wiki/Packaging:Guidelines#Devel_Packages + https://bitbucket.org/scons/scons/pull-requests/247/new-versioned-libraries-gnulink-cyglink/diff#comment-10063929 + - New construction variables to allow override default behavior: SONAME, + SHLIBVERSIONFLAGS, _SHLIBVERSIONFLAGS, SHLIBNOVERSIONSYMLINKS, + LDMODULEVERSION, LDMODULEVERSIONFLAGS, _LDMODULEVERSIONFLAGS, + LDMODULENOVERSIONSYMLINKS. + - Changed logic used to configure the versioning machinery from + platform-centric to linker-oriented. + - The SHLIBVERSION/LDMODULEVERSION variables are no longer validated by + SCons (more freedom to users). + - InstallVersionedLib() doesn't use SHLIBVERSION anymore. + - Enchanced docs for the library versioning stuff. + - New tests for versioned libraries. + - Library versioning is currently implemented for the following linker + tools: 'cyglink', 'gnulink', 'sunlink'. + Please note the following important changes since release 2.3.6: - Switch several core classes to use "slots" to reduce memory usage. (PR #2180, #2178, #2198) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 823eb4b..40245a8 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -4,11 +4,7 @@ Change Log -RELEASE VERSION/DATE TO BE FILLED IN LATER - - From Paweł Tomulik: - - Fix to swig tool - pick-up 'swig', 'swig3.0' and 'swig2.0' (in order). - - Fix to swig tool - respect env['SWIG'] provided by user. +RELEASE 2.4.1 - Mon, 07 Nov 2015 10:37:21 -0700 From Arfrever Frehtes Taifersar Arahesis: - Fix for Bug # 2791 - Setup.py fails unnecessarily under Jython. @@ -66,6 +62,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - New tests for versioned libraries. - Library versioning is currently implemented for the following linker tools: 'cyglink', 'gnulink', 'sunlink'. + - Fix to swig tool - pick-up 'swig', 'swig3.0' and 'swig2.0' (in order). + - Fix to swig tool - respect env['SWIG'] provided by user. diff --git a/src/RELEASE.txt b/src/RELEASE.txt index 1bf2eb1..baf3283 100644 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -1,72 +1,68 @@ - A new SCons checkpoint release, 2.3.13.alpha.yyyymmdd, is now available + A new SCons release, 2.4.1, is now available on the SCons download page: http://www.scons.org/download.php - XXX The primary purpose of this release ... XXX - - A SCons "checkpoint release" is intended to provide early access to - new features so they can be tested in the field before being released - for adoption by other software distributions. - - Note that a checkpoint release is developed using the same test-driven - development methodology as all SCons releases. Existing SCons - functionality should all work as it does in previous releases (except - for any changes identified in the release notes) and early adopters - should be able to use a checkpoint release safely for production work - with existing SConscript files. If not, it represents not only a bug - in SCons but also a hole in the regression test suite, and we want to - hear about it. - - New features may be more lightly tested than in past releases, - especially as concerns their interaction with all of the other - functionality in SCons. We are especially interested in hearing bug - reports about new functionality. - - We do not recommend that downstream distributions (Debian, Fedora, - etc.) package a checkpoint release, mainly to avoid confusing the - "public" release numbering with the long checkpoint release names. - - Here is a summary of the changes since 1.3.0: + Here is a summary of the changes since 2.4.0: NEW FUNCTIONALITY - - - List new features (presumably why a checkpoint is being released) + - InstallVersionedLib now available in the DefaultEnvironment context. + - Added new configure check, CheckProg, to check for existence of a program. + - Add support `Microsoft Visual C++ Compiler for Python 2.7' + Compiler can be obtained at: https://www.microsoft.com/en-us/download/details.aspx?id=44266 DEPRECATED FUNCTIONALITY - - List anything that's been deprecated since the last release - CHANGED/ENHANCED EXISTING FUNCTIONALITY - - List modifications to existing features, where the previous behavior - wouldn't actually be considered a bug + - Reimplemented versioning for shared libraries, with the following effects + - Fixed tigris issues #3001, #3006. + - Fixed several other issues not reported to tigris, including: + issues with versioned libraries in subdirectories with tricky names, + issues with versioned libraries and variant directories, + issue with soname not being injected to library when using D linkers, + - Switched to direct symlinks instead of daisy-chained ones -- soname and + development symlinks point directly to the versioned shared library now), + for rationale see: + https://www.debian.org/doc/debian-policy/ch-sharedlibs.html + https://fedoraproject.org/wiki/Packaging:Guidelines#Devel_Packages + https://bitbucket.org/scons/scons/pull-requests/247/new-versioned-libraries-gnulink-cyglink/diff#comment-10063929 + - New construction variables to allow override default behavior: SONAME, + SHLIBVERSIONFLAGS, _SHLIBVERSIONFLAGS, SHLIBNOVERSIONSYMLINKS, + LDMODULEVERSION, LDMODULEVERSIONFLAGS, _LDMODULEVERSIONFLAGS, + LDMODULENOVERSIONSYMLINKS. + - Changed logic used to configure the versioning machinery from + platform-centric to linker-oriented. + - The SHLIBVERSION/LDMODULEVERSION variables are no longer validated by + SCons (more freedom to users). + - InstallVersionedLib() doesn't use SHLIBVERSION anymore. + - Enchanced docs for the library versioning stuff. + - New tests for versioned libraries. + - Library versioning is currently implemented for the following linker + tools: 'cyglink', 'gnulink', 'sunlink'. FIXES - - List fixes of outright bugs + - Fix for issue #2840 - Fix for two environments specifying same target with different + actions not throwing hard error. Instead SCons was incorrectly issuing a warning + and continuing. + - Fix to swig tool - pick-up 'swig', 'swig3.0' and 'swig2.0' (in order). + - Fix to swig tool - respect env['SWIG'] provided by user. + - Fix for Bug # 2791 - Setup.py fails unnecessarily under Jython. + - Fixed license of SVG titlepage files in the context of Debian + packaging, such that they allow for commercial use too (#2985). + - Fixed tigris issue #3011: Glob() excludes didn't work when used with VariantDir(duplicate=0) + - Fix bug 2831 and allow Help() text to be appended to AddOption() help. IMPROVEMENTS - - List improvements that wouldn't be visible to the user in the - documentation: performance improvements (describe the circumstances - under which they would be observed), or major code cleanups - PACKAGING - - List changes in the way SCons is packaged and/or released - DOCUMENTATION - - List any significant changes to the documentation (not individual - typo fixes, even if they're mentioned in src/CHANGES.txt to give - the contributor credit) - DEVELOPMENT - - List visible changes in the way SCons is developed - - Thanks to CURLY, LARRY, and MOE for their contributions to this release. + Thanks to Arfrever Frehtes Taifersar Arahesis, Dirk Baechle, William Blevins, Carnë Draug, Andrew Featherstone, Hiroaki Itoh, Florian Miedniak, William Roberts, Paweł Tomulik for their contributions to this release. Contributors are listed alphabetically by their last name. __COPYRIGHT__ -- cgit v0.12 From 2d6ae148c1a3c49fb8400f7de0787e1179aab53c Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 9 Nov 2015 09:31:05 -0800 Subject: post 2.4.1 release changes --- ReleaseConfig | 2 +- src/Announce.txt | 2 +- src/CHANGES.txt | 7 +++++ src/RELEASE.txt | 88 +++++++++++++++++++++++++++++--------------------------- 4 files changed, 55 insertions(+), 44 deletions(-) diff --git a/ReleaseConfig b/ReleaseConfig index 4396248..ced44c6 100644 --- a/ReleaseConfig +++ b/ReleaseConfig @@ -32,7 +32,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" # 'final', the patchlevel is set to the release date. This value is # mandatory and must be present in this file. #version_tuple = (2, 2, 0, 'final', 0) -version_tuple = (2, 4, 1) +version_tuple = (2, 4, 2, 'alpha', 0) # Python versions prior to unsupported_python_version cause a fatal error # when that version is used. Python versions prior to deprecate_python_version diff --git a/src/Announce.txt b/src/Announce.txt index 719b4d7..c20d7df 100644 --- a/src/Announce.txt +++ b/src/Announce.txt @@ -48,7 +48,7 @@ Notes: +================================================================= -RELEASE 2.4.1 - Mon, 07 Nov 2015 10:37:21 -0700 +RELEASE VERSION/DATE TO BE FILLED IN LATER Please consult the RELEASE.txt file for a summary of changes since the last release and consult the CHANGES.txt file for complete a list of changes diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 40245a8..02afa43 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -4,6 +4,13 @@ Change Log +RELEASE VERSION/DATE TO BE FILLED IN LATER + + From John Doe: + + - Whatever John Doe did. + + RELEASE 2.4.1 - Mon, 07 Nov 2015 10:37:21 -0700 From Arfrever Frehtes Taifersar Arahesis: diff --git a/src/RELEASE.txt b/src/RELEASE.txt index baf3283..ed17984 100644 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -1,68 +1,72 @@ - A new SCons release, 2.4.1, is now available + A new SCons checkpoint release, 2.4.2.alpha.yyyymmdd, is now available on the SCons download page: http://www.scons.org/download.php - Here is a summary of the changes since 2.4.0: + XXX The primary purpose of this release ... XXX + + A SCons "checkpoint release" is intended to provide early access to + new features so they can be tested in the field before being released + for adoption by other software distributions. + + Note that a checkpoint release is developed using the same test-driven + development methodology as all SCons releases. Existing SCons + functionality should all work as it does in previous releases (except + for any changes identified in the release notes) and early adopters + should be able to use a checkpoint release safely for production work + with existing SConscript files. If not, it represents not only a bug + in SCons but also a hole in the regression test suite, and we want to + hear about it. + + New features may be more lightly tested than in past releases, + especially as concerns their interaction with all of the other + functionality in SCons. We are especially interested in hearing bug + reports about new functionality. + + We do not recommend that downstream distributions (Debian, Fedora, + etc.) package a checkpoint release, mainly to avoid confusing the + "public" release numbering with the long checkpoint release names. + + Here is a summary of the changes since 1.3.0: NEW FUNCTIONALITY - - InstallVersionedLib now available in the DefaultEnvironment context. - - Added new configure check, CheckProg, to check for existence of a program. - - Add support `Microsoft Visual C++ Compiler for Python 2.7' - Compiler can be obtained at: https://www.microsoft.com/en-us/download/details.aspx?id=44266 + + - List new features (presumably why a checkpoint is being released) DEPRECATED FUNCTIONALITY + - List anything that's been deprecated since the last release + CHANGED/ENHANCED EXISTING FUNCTIONALITY - - Reimplemented versioning for shared libraries, with the following effects - - Fixed tigris issues #3001, #3006. - - Fixed several other issues not reported to tigris, including: - issues with versioned libraries in subdirectories with tricky names, - issues with versioned libraries and variant directories, - issue with soname not being injected to library when using D linkers, - - Switched to direct symlinks instead of daisy-chained ones -- soname and - development symlinks point directly to the versioned shared library now), - for rationale see: - https://www.debian.org/doc/debian-policy/ch-sharedlibs.html - https://fedoraproject.org/wiki/Packaging:Guidelines#Devel_Packages - https://bitbucket.org/scons/scons/pull-requests/247/new-versioned-libraries-gnulink-cyglink/diff#comment-10063929 - - New construction variables to allow override default behavior: SONAME, - SHLIBVERSIONFLAGS, _SHLIBVERSIONFLAGS, SHLIBNOVERSIONSYMLINKS, - LDMODULEVERSION, LDMODULEVERSIONFLAGS, _LDMODULEVERSIONFLAGS, - LDMODULENOVERSIONSYMLINKS. - - Changed logic used to configure the versioning machinery from - platform-centric to linker-oriented. - - The SHLIBVERSION/LDMODULEVERSION variables are no longer validated by - SCons (more freedom to users). - - InstallVersionedLib() doesn't use SHLIBVERSION anymore. - - Enchanced docs for the library versioning stuff. - - New tests for versioned libraries. - - Library versioning is currently implemented for the following linker - tools: 'cyglink', 'gnulink', 'sunlink'. + - List modifications to existing features, where the previous behavior + wouldn't actually be considered a bug FIXES - - Fix for issue #2840 - Fix for two environments specifying same target with different - actions not throwing hard error. Instead SCons was incorrectly issuing a warning - and continuing. - - Fix to swig tool - pick-up 'swig', 'swig3.0' and 'swig2.0' (in order). - - Fix to swig tool - respect env['SWIG'] provided by user. - - Fix for Bug # 2791 - Setup.py fails unnecessarily under Jython. - - Fixed license of SVG titlepage files in the context of Debian - packaging, such that they allow for commercial use too (#2985). - - Fixed tigris issue #3011: Glob() excludes didn't work when used with VariantDir(duplicate=0) - - Fix bug 2831 and allow Help() text to be appended to AddOption() help. + - List fixes of outright bugs IMPROVEMENTS + - List improvements that wouldn't be visible to the user in the + documentation: performance improvements (describe the circumstances + under which they would be observed), or major code cleanups + PACKAGING + - List changes in the way SCons is packaged and/or released + DOCUMENTATION + - List any significant changes to the documentation (not individual + typo fixes, even if they're mentioned in src/CHANGES.txt to give + the contributor credit) + DEVELOPMENT - Thanks to Arfrever Frehtes Taifersar Arahesis, Dirk Baechle, William Blevins, Carnë Draug, Andrew Featherstone, Hiroaki Itoh, Florian Miedniak, William Roberts, Paweł Tomulik for their contributions to this release. + - List visible changes in the way SCons is developed + + Thanks to CURLY, LARRY, and MOE for their contributions to this release. Contributors are listed alphabetically by their last name. __COPYRIGHT__ -- cgit v0.12 From ebc3286289111b5134032f03c29cb8a0ef7d5d34 Mon Sep 17 00:00:00 2001 From: anatoly techtonik Date: Wed, 11 Nov 2015 21:44:46 +0300 Subject: Document SCons.Debug.caller_trace() behavior --- src/CHANGES.txt | 12 +++++++++--- src/engine/SCons/Debug.py | 11 +++++++++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 02afa43..23fd49b 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -4,17 +4,20 @@ Change Log + RELEASE VERSION/DATE TO BE FILLED IN LATER From John Doe: - - Whatever John Doe did. + From Anatoly Techtonik: + - Document SCons.Debug.caller_trace() behavior. + RELEASE 2.4.1 - Mon, 07 Nov 2015 10:37:21 -0700 From Arfrever Frehtes Taifersar Arahesis: - - Fix for Bug # 2791 - Setup.py fails unnecessarily under Jython. + - Fix for Bug # 2791 - setup.py fails unnecessarily under Jython. From Dirk Baechle: - Fixed license of SVG titlepage files in the context of Debian @@ -73,7 +76,6 @@ RELEASE 2.4.1 - Mon, 07 Nov 2015 10:37:21 -0700 - Fix to swig tool - respect env['SWIG'] provided by user. - RELEASE 2.4.0 - Mon, 21 Sep 2015 08:56:00 -0700 From Dirk Baechle: @@ -86,6 +88,8 @@ RELEASE 2.4.0 - Mon, 21 Sep 2015 08:56:00 -0700 From Andrew Featherstone - Fixed typo in SWIGPATH description + + RELEASE 2.3.6 - Mon, 31 Jul 2015 14:35:03 -0700 From Rob Smith: @@ -379,6 +383,8 @@ RELEASE 2.3.0 - Mon, 02 Mar 2013 13:22:29 -0400 Add builder InstallVersionedLib to create the required symlinks installing a versioned shared library. + + RELEASE 2.2.0 - Mon, 05 Aug 2012 15:37:48 +0000 From dubcanada on Bitbucket: diff --git a/src/engine/SCons/Debug.py b/src/engine/SCons/Debug.py index b47c24c..9e520ff 100644 --- a/src/engine/SCons/Debug.py +++ b/src/engine/SCons/Debug.py @@ -1,7 +1,10 @@ """SCons.Debug Code for debugging SCons internal things. Shouldn't be -needed by most users. +needed by most users. Quick shortcuts: + +from SCons.Debug import caller_trace +caller_trace() """ @@ -137,8 +140,12 @@ def caller_stack(): caller_bases = {} caller_dicts = {} -# trace a caller's stack def caller_trace(back=0): + """ + Trace caller stack and save info into global dicts, which + are printed automatically at the end of SCons execution. + """ + global caller_bases, caller_dicts import traceback tb = traceback.extract_stack(limit=3+back) tb.reverse() -- cgit v0.12 From 046f1eba099033932261d60b90e8a7cd140adb17 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 11 Nov 2015 17:53:13 -0500 Subject: change release config files to post release state --- QMTest/TestSCons.py | 2 +- README.rst | 16 ++++++++-------- SConstruct | 4 ++-- src/CHANGES.txt | 7 +++++++ src/RELEASE.txt | 55 ++++++++++++++++++++++++++++++++++++++--------------- 5 files changed, 58 insertions(+), 26 deletions(-) diff --git a/QMTest/TestSCons.py b/QMTest/TestSCons.py index ef70261..a9fd6a0 100644 --- a/QMTest/TestSCons.py +++ b/QMTest/TestSCons.py @@ -34,7 +34,7 @@ from TestCmd import PIPE # here provides some independent verification that what we packaged # conforms to what we expect. -default_version = '2.4.1' +default_version = '2.4.2.alpha.yyyymmdd' python_version_unsupported = (2, 3, 0) python_version_deprecated = (2, 7, 0) diff --git a/README.rst b/README.rst index a2b15a6..5710586 100644 --- a/README.rst +++ b/README.rst @@ -480,14 +480,14 @@ following packages will be built:: build/dist/scons-2.4.1-1.noarch.rpm build/dist/scons-2.4.1-1.src.rpm build/dist/scons-2.4.1.linux-i686.tar.gz - build/dist/scons-2.4.1.tar.gz - build/dist/scons-2.4.1.win32.exe - build/dist/scons-2.4.1.zip - build/dist/scons-doc-2.4.1.tar.gz - build/dist/scons-local-2.4.1.tar.gz - build/dist/scons-local-2.4.1.zip - build/dist/scons-src-2.4.1.tar.gz - build/dist/scons-src-2.4.1.zip + build/dist/scons-2.4.2.alpha.yyyymmdd.tar.gz + build/dist/scons-2.4.2.alpha.yyyymmdd.win32.exe + build/dist/scons-2.4.2.alpha.yyyymmdd.zip + build/dist/scons-doc-2.4.2.alpha.yyyymmdd.tar.gz + build/dist/scons-local-2.4.2.alpha.yyyymmdd.tar.gz + build/dist/scons-local-2.4.2.alpha.yyyymmdd.zip + build/dist/scons-src-2.4.2.alpha.yyyymmdd.tar.gz + build/dist/scons-src-2.4.2.alpha.yyyymmdd.zip build/dist/scons_2.4.1-1_all.deb The SConstruct file is supposed to be smart enough to avoid trying to build diff --git a/SConstruct b/SConstruct index 79249e9..3bbaca6 100644 --- a/SConstruct +++ b/SConstruct @@ -6,7 +6,7 @@ copyright_years = '2001 - 2015' # This gets inserted into the man pages to reflect the month of release. -month_year = 'November 2015' +month_year = 'MONTH YEAR' # # __COPYRIGHT__ @@ -43,7 +43,7 @@ import tempfile import bootstrap project = 'scons' -default_version = '2.4.1' +default_version = '2.4.2.alpha.yyyymmdd' copyright = "Copyright (c) %s The SCons Foundation" % copyright_years platform = distutils.util.get_platform() diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 02afa43..685a6ae 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -11,6 +11,13 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Whatever John Doe did. +RELEASE 2.4.2.alpha.yyyymmdd - NEW DATE WILL BE INSERTED HERE + + From John Doe: + + - Whatever John Doe did. + + RELEASE 2.4.1 - Mon, 07 Nov 2015 10:37:21 -0700 From Arfrever Frehtes Taifersar Arahesis: diff --git a/src/RELEASE.txt b/src/RELEASE.txt index 114b4f5..3bff366 100644 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -1,47 +1,72 @@ - A new SCons checkpoint release, 2.4.2.alpha.yyyymmdd, is now available + A new SCons checkpoint release, 2.4.3.alpha.yyyymmdd, is now available on the SCons download page: http://www.scons.org/download.php - Here is a summary of the changes since 2.3.6: + XXX The primary purpose of this release ... XXX + + A SCons "checkpoint release" is intended to provide early access to + new features so they can be tested in the field before being released + for adoption by other software distributions. + + Note that a checkpoint release is developed using the same test-driven + development methodology as all SCons releases. Existing SCons + functionality should all work as it does in previous releases (except + for any changes identified in the release notes) and early adopters + should be able to use a checkpoint release safely for production work + with existing SConscript files. If not, it represents not only a bug + in SCons but also a hole in the regression test suite, and we want to + hear about it. + + New features may be more lightly tested than in past releases, + especially as concerns their interaction with all of the other + functionality in SCons. We are especially interested in hearing bug + reports about new functionality. + + We do not recommend that downstream distributions (Debian, Fedora, + etc.) package a checkpoint release, mainly to avoid confusing the + "public" release numbering with the long checkpoint release names. + + Here is a summary of the changes since 1.3.0: NEW FUNCTIONALITY - - None + - List new features (presumably why a checkpoint is being released) DEPRECATED FUNCTIONALITY - - None + - List anything that's been deprecated since the last release CHANGED/ENHANCED EXISTING FUNCTIONALITY - - Switched several core classes to using "slots", for - reducing the overall memory consumption in large - projects (fixes #2180, #2178, #2198) - - Memoizer counting uses decorators now, instead of - the old metaclasses approach. + - List modifications to existing features, where the previous behavior + wouldn't actually be considered a bug FIXES - - 2180, 2178, 2198 (See above) + - List fixes of outright bugs IMPROVEMENTS - - See CHANGED/ENHANCED EXISTING FUNCTIONALITY above + - List improvements that wouldn't be visible to the user in the + documentation: performance improvements (describe the circumstances + under which they would be observed), or major code cleanups PACKAGING - - None + - List changes in the way SCons is packaged and/or released DOCUMENTATION - - Bug 2504 - Fixed incorrect default SWIGPATH in documentation + - List any significant changes to the documentation (not individual + typo fixes, even if they're mentioned in src/CHANGES.txt to give + the contributor credit) DEVELOPMENT - - None + - List visible changes in the way SCons is developed - Thanks to Dirk Baechle, and Andrew Featherstone for their contributions to this release. + Thanks to CURLY, LARRY, and MOE for their contributions to this release. Contributors are listed alphabetically by their last name. __COPYRIGHT__ -- cgit v0.12 From c2d974ea65afe9ab1968a16c797155fd799527ca Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 12 Nov 2015 23:49:22 -0500 Subject: minor changes to fix too many files open when trying to run with pypy --- bootstrap.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/bootstrap.py b/bootstrap.py index f3bc105..90917dc 100755 --- a/bootstrap.py +++ b/bootstrap.py @@ -27,6 +27,8 @@ import os.path import sys import glob import subprocess +import filecmp +import shutil __doc__ = """bootstrap.py @@ -127,7 +129,7 @@ def main(): def must_copy(dst, src): if not os.path.exists(dst): return 1 - return open(dst, 'rb').read() != open(src, 'rb').read() + return filecmp.cmp(dst,src) # Note: We don't use the getopt module to process the command-line # arguments because we'd have to teach it about all of the SCons options. @@ -195,7 +197,8 @@ def main(): os.makedirs(dir) try: os.unlink(dst) except: pass - open(dst, 'wb').write( open(src, 'rb').read() ) + + shutil.copyfile(src,dst) if update_only: sys.exit(0) -- cgit v0.12 From 5ea93b2da34adbb831d8c88d894c0cdb98e9452e Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 13 Nov 2015 20:03:54 -0500 Subject: need to add new SWIG.py scanner to manifest to get it to install --- src/engine/MANIFEST.in | 1 + 1 file changed, 1 insertion(+) diff --git a/src/engine/MANIFEST.in b/src/engine/MANIFEST.in index f62d16e..f7d5aa7 100644 --- a/src/engine/MANIFEST.in +++ b/src/engine/MANIFEST.in @@ -39,6 +39,7 @@ SCons/Scanner/IDL.py SCons/Scanner/LaTeX.py SCons/Scanner/Prog.py SCons/Scanner/RC.py +SCons/Scanner/SWIG.py SCons/SConf.py SCons/SConsign.py SCons/Script/__init__.py -- cgit v0.12 From 781d31e33c51d2e18435706fb2cb7f051e02a384 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 19 Nov 2015 10:37:07 -0800 Subject: remove compat module for subprocess. No longer needed as we are only going to run on python 2.7.x --- src/engine/SCons/compat/__init__.py | 6 - src/engine/SCons/compat/_scons_subprocess.py | 1281 -------------------------- 2 files changed, 1287 deletions(-) delete mode 100644 src/engine/SCons/compat/_scons_subprocess.py diff --git a/src/engine/SCons/compat/__init__.py b/src/engine/SCons/compat/__init__.py index c870fbc..281392c 100644 --- a/src/engine/SCons/compat/__init__.py +++ b/src/engine/SCons/compat/__init__.py @@ -186,12 +186,6 @@ rename_module('winreg', '_winreg') try: - import subprocess -except ImportError: - # Pre-2.4 Python has no subprocess module. - import_as('_scons_subprocess', 'subprocess') - -try: sys.intern except AttributeError: # Pre-2.6 Python has no sys.intern() function. diff --git a/src/engine/SCons/compat/_scons_subprocess.py b/src/engine/SCons/compat/_scons_subprocess.py deleted file mode 100644 index eebe53d..0000000 --- a/src/engine/SCons/compat/_scons_subprocess.py +++ /dev/null @@ -1,1281 +0,0 @@ -# subprocess - Subprocesses with accessible I/O streams -# -# For more information about this module, see PEP 324. -# -# This module should remain compatible with Python 2.2, see PEP 291. -# -# Copyright (c) 2003-2005 by Peter Astrand -# -# Licensed to PSF under a Contributor Agreement. -# See http://www.python.org/2.4/license for licensing details. - -r"""subprocess - Subprocesses with accessible I/O streams - -This module allows you to spawn processes, connect to their -input/output/error pipes, and obtain their return codes. This module -intends to replace several other, older modules and functions, like: - -os.system -os.spawn* -os.popen* -popen2.* -commands.* - -Information about how the subprocess module can be used to replace these -modules and functions can be found below. - - - -Using the subprocess module -=========================== -This module defines one class called Popen: - -class Popen(args, bufsize=0, executable=None, - stdin=None, stdout=None, stderr=None, - preexec_fn=None, close_fds=False, shell=False, - cwd=None, env=None, universal_newlines=False, - startupinfo=None, creationflags=0): - - -Arguments are: - -args should be a string, or a sequence of program arguments. The -program to execute is normally the first item in the args sequence or -string, but can be explicitly set by using the executable argument. - -On UNIX, with shell=False (default): In this case, the Popen class -uses os.execvp() to execute the child program. args should normally -be a sequence. A string will be treated as a sequence with the string -as the only item (the program to execute). - -On UNIX, with shell=True: If args is a string, it specifies the -command string to execute through the shell. If args is a sequence, -the first item specifies the command string, and any additional items -will be treated as additional shell arguments. - -On Windows: the Popen class uses CreateProcess() to execute the child -program, which operates on strings. If args is a sequence, it will be -converted to a string using the list2cmdline method. Please note that -not all MS Windows applications interpret the command line the same -way: The list2cmdline is designed for applications using the same -rules as the MS C runtime. - -bufsize, if given, has the same meaning as the corresponding argument -to the built-in open() function: 0 means unbuffered, 1 means line -buffered, any other positive value means use a buffer of -(approximately) that size. A negative bufsize means to use the system -default, which usually means fully buffered. The default value for -bufsize is 0 (unbuffered). - -stdin, stdout and stderr specify the executed programs' standard -input, standard output and standard error file handles, respectively. -Valid values are PIPE, an existing file descriptor (a positive -integer), an existing file object, and None. PIPE indicates that a -new pipe to the child should be created. With None, no redirection -will occur; the child's file handles will be inherited from the -parent. Additionally, stderr can be STDOUT, which indicates that the -stderr data from the applications should be captured into the same -file handle as for stdout. - -If preexec_fn is set to a callable object, this object will be called -in the child process just before the child is executed. - -If close_fds is true, all file descriptors except 0, 1 and 2 will be -closed before the child process is executed. - -if shell is true, the specified command will be executed through the -shell. - -If cwd is not None, the current directory will be changed to cwd -before the child is executed. - -If env is not None, it defines the environment variables for the new -process. - -If universal_newlines is true, the file objects stdout and stderr are -opened as a text files, but lines may be terminated by any of '\n', -the Unix end-of-line convention, '\r', the Macintosh convention or -'\r\n', the Windows convention. All of these external representations -are seen as '\n' by the Python program. Note: This feature is only -available if Python is built with universal newline support (the -default). Also, the newlines attribute of the file objects stdout, -stdin and stderr are not updated by the communicate() method. - -The startupinfo and creationflags, if given, will be passed to the -underlying CreateProcess() function. They can specify things such as -appearance of the main window and priority for the new process. -(Windows only) - - -This module also defines two shortcut functions: - -call(*popenargs, **kwargs): - Run command with arguments. Wait for command to complete, then - return the returncode attribute. - - The arguments are the same as for the Popen constructor. Example: - - retcode = call(["ls", "-l"]) - -check_call(*popenargs, **kwargs): - Run command with arguments. Wait for command to complete. If the - exit code was zero then return, otherwise raise - CalledProcessError. The CalledProcessError object will have the - return code in the returncode attribute. - - The arguments are the same as for the Popen constructor. Example: - - check_call(["ls", "-l"]) - -Exceptions ----------- -Exceptions raised in the child process, before the new program has -started to execute, will be re-raised in the parent. Additionally, -the exception object will have one extra attribute called -'child_traceback', which is a string containing traceback information -from the childs point of view. - -The most common exception raised is OSError. This occurs, for -example, when trying to execute a non-existent file. Applications -should prepare for OSErrors. - -A ValueError will be raised if Popen is called with invalid arguments. - -check_call() will raise CalledProcessError, if the called process -returns a non-zero return code. - - -Security --------- -Unlike some other popen functions, this implementation will never call -/bin/sh implicitly. This means that all characters, including shell -metacharacters, can safely be passed to child processes. - - -Popen objects -============= -Instances of the Popen class have the following methods: - -poll() - Check if child process has terminated. Returns returncode - attribute. - -wait() - Wait for child process to terminate. Returns returncode attribute. - -communicate(input=None) - Interact with process: Send data to stdin. Read data from stdout - and stderr, until end-of-file is reached. Wait for process to - terminate. The optional stdin argument should be a string to be - sent to the child process, or None, if no data should be sent to - the child. - - communicate() returns a tuple (stdout, stderr). - - Note: The data read is buffered in memory, so do not use this - method if the data size is large or unlimited. - -The following attributes are also available: - -stdin - If the stdin argument is PIPE, this attribute is a file object - that provides input to the child process. Otherwise, it is None. - -stdout - If the stdout argument is PIPE, this attribute is a file object - that provides output from the child process. Otherwise, it is - None. - -stderr - If the stderr argument is PIPE, this attribute is file object that - provides error output from the child process. Otherwise, it is - None. - -pid - The process ID of the child process. - -returncode - The child return code. A None value indicates that the process - hasn't terminated yet. A negative value -N indicates that the - child was terminated by signal N (UNIX only). - - -Replacing older functions with the subprocess module -==================================================== -In this section, "a ==> b" means that b can be used as a replacement -for a. - -Note: All functions in this section fail (more or less) silently if -the executed program cannot be found; this module raises an OSError -exception. - -In the following examples, we assume that the subprocess module is -imported with "from subprocess import *". - - -Replacing /bin/sh shell backquote ---------------------------------- -output=`mycmd myarg` -==> -output = Popen(["mycmd", "myarg"], stdout=PIPE).communicate()[0] - - -Replacing shell pipe line -------------------------- -output=`dmesg | grep hda` -==> -p1 = Popen(["dmesg"], stdout=PIPE) -p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) -output = p2.communicate()[0] - - -Replacing os.system() ---------------------- -sts = os.system("mycmd" + " myarg") -==> -p = Popen("mycmd" + " myarg", shell=True) -pid, sts = os.waitpid(p.pid, 0) - -Note: - -* Calling the program through the shell is usually not required. - -* It's easier to look at the returncode attribute than the - exitstatus. - -A more real-world example would look like this: - -try: - retcode = call("mycmd" + " myarg", shell=True) - if retcode < 0: - print >>sys.stderr, "Child was terminated by signal", -retcode - else: - print >>sys.stderr, "Child returned", retcode -except OSError, e: - print >>sys.stderr, "Execution failed:", e - - -Replacing os.spawn* -------------------- -P_NOWAIT example: - -pid = os.spawnlp(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg") -==> -pid = Popen(["/bin/mycmd", "myarg"]).pid - - -P_WAIT example: - -retcode = os.spawnlp(os.P_WAIT, "/bin/mycmd", "mycmd", "myarg") -==> -retcode = call(["/bin/mycmd", "myarg"]) - - -Vector example: - -os.spawnvp(os.P_NOWAIT, path, args) -==> -Popen([path] + args[1:]) - - -Environment example: - -os.spawnlpe(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg", env) -==> -Popen(["/bin/mycmd", "myarg"], env={"PATH": "/usr/bin"}) - - -Replacing os.popen* -------------------- -pipe = os.popen(cmd, mode='r', bufsize) -==> -pipe = Popen(cmd, shell=True, bufsize=bufsize, stdout=PIPE).stdout - -pipe = os.popen(cmd, mode='w', bufsize) -==> -pipe = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE).stdin - - -(child_stdin, child_stdout) = os.popen2(cmd, mode, bufsize) -==> -p = Popen(cmd, shell=True, bufsize=bufsize, - stdin=PIPE, stdout=PIPE, close_fds=True) -(child_stdin, child_stdout) = (p.stdin, p.stdout) - - -(child_stdin, - child_stdout, - child_stderr) = os.popen3(cmd, mode, bufsize) -==> -p = Popen(cmd, shell=True, bufsize=bufsize, - stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True) -(child_stdin, - child_stdout, - child_stderr) = (p.stdin, p.stdout, p.stderr) - - -(child_stdin, child_stdout_and_stderr) = os.popen4(cmd, mode, bufsize) -==> -p = Popen(cmd, shell=True, bufsize=bufsize, - stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True) -(child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout) - - -Replacing popen2.* ------------------- -Note: If the cmd argument to popen2 functions is a string, the command -is executed through /bin/sh. If it is a list, the command is directly -executed. - -(child_stdout, child_stdin) = popen2.popen2("somestring", bufsize, mode) -==> -p = Popen(["somestring"], shell=True, bufsize=bufsize - stdin=PIPE, stdout=PIPE, close_fds=True) -(child_stdout, child_stdin) = (p.stdout, p.stdin) - - -(child_stdout, child_stdin) = popen2.popen2(["mycmd", "myarg"], bufsize, mode) -==> -p = Popen(["mycmd", "myarg"], bufsize=bufsize, - stdin=PIPE, stdout=PIPE, close_fds=True) -(child_stdout, child_stdin) = (p.stdout, p.stdin) - -The popen2.Popen3 and popen3.Popen4 basically works as subprocess.Popen, -except that: - -* subprocess.Popen raises an exception if the execution fails -* the capturestderr argument is replaced with the stderr argument. -* stdin=PIPE and stdout=PIPE must be specified. -* popen2 closes all filedescriptors by default, but you have to specify - close_fds=True with subprocess.Popen. - - -""" - -import sys -mswindows = (sys.platform == "win32") - -import os -import types -import traceback - -# Exception classes used by this module. -class CalledProcessError(Exception): - """This exception is raised when a process run by check_call() returns - a non-zero exit status. The exit status will be stored in the - returncode attribute.""" - def __init__(self, returncode, cmd): - self.returncode = returncode - self.cmd = cmd - def __str__(self): - return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode) - - -if mswindows: - try: - import threading - except ImportError: - # SCons: the threading module is only used by the communicate() - # method, which we don't actually use, so don't worry if we - # can't import it. - pass - import msvcrt - try: - # Try to get _subprocess - from _subprocess import * - class STARTUPINFO(object): - dwFlags = 0 - hStdInput = None - hStdOutput = None - hStdError = None - wShowWindow = 0 - class pywintypes(object): - error = IOError - except ImportError: - # If not there, then drop back to requiring pywin32 - # TODO: Should this be wrapped in try as well? To notify user to install - # pywin32 ? With URL to it? - import pywintypes - from win32api import GetStdHandle, STD_INPUT_HANDLE, \ - STD_OUTPUT_HANDLE, STD_ERROR_HANDLE - from win32api import GetCurrentProcess, DuplicateHandle, \ - GetModuleFileName, GetVersion - from win32con import DUPLICATE_SAME_ACCESS, SW_HIDE - from win32pipe import CreatePipe - from win32process import CreateProcess, STARTUPINFO, \ - GetExitCodeProcess, STARTF_USESTDHANDLES, \ - STARTF_USESHOWWINDOW, CREATE_NEW_CONSOLE - from win32event import WaitForSingleObject, INFINITE, WAIT_OBJECT_0 - - -else: - import select - import errno - import fcntl - import pickle - - try: - fcntl.F_GETFD - except AttributeError: - fcntl.F_GETFD = 1 - - try: - fcntl.F_SETFD - except AttributeError: - fcntl.F_SETFD = 2 - -__all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call", "CalledProcessError"] - -try: - MAXFD = os.sysconf("SC_OPEN_MAX") -except KeyboardInterrupt: - raise # SCons: don't swallow keyboard interrupts -except: - MAXFD = 256 - -try: - isinstance(1, int) -except TypeError: - def is_int(obj): - return isinstance(obj, type(1)) - def is_int_or_long(obj): - return type(obj) in (type(1), type(1L)) -else: - def is_int(obj): - return isinstance(obj, int) - def is_int_or_long(obj): - return isinstance(obj, (int, long)) - -try: - types.StringTypes -except AttributeError: - try: - types.StringTypes = (str, unicode) - except NameError: - types.StringTypes = (str,) -def is_string(obj): - return isinstance(obj, types.StringTypes) - -_active = [] - -def _cleanup(): - for inst in _active[:]: - if inst.poll(_deadstate=sys.maxsize) >= 0: - try: - _active.remove(inst) - except ValueError: - # This can happen if two threads create a new Popen instance. - # It's harmless that it was already removed, so ignore. - pass - -PIPE = -1 -STDOUT = -2 - - -def call(*popenargs, **kwargs): - """Run command with arguments. Wait for command to complete, then - return the returncode attribute. - - The arguments are the same as for the Popen constructor. Example: - - retcode = call(["ls", "-l"]) - """ - return apply(Popen, popenargs, kwargs).wait() - - -def check_call(*popenargs, **kwargs): - """Run command with arguments. Wait for command to complete. If - the exit code was zero then return, otherwise raise - CalledProcessError. The CalledProcessError object will have the - return code in the returncode attribute. - - The arguments are the same as for the Popen constructor. Example: - - check_call(["ls", "-l"]) - """ - retcode = call(*popenargs, **kwargs) - cmd = kwargs.get("args") - if cmd is None: - cmd = popenargs[0] - if retcode: - raise CalledProcessError(retcode, cmd) - return retcode - - -def list2cmdline(seq): - """ - Translate a sequence of arguments into a command line - string, using the same rules as the MS C runtime: - - 1) Arguments are delimited by white space, which is either a - space or a tab. - - 2) A string surrounded by double quotation marks is - interpreted as a single argument, regardless of white space - contained within. A quoted string can be embedded in an - argument. - - 3) A double quotation mark preceded by a backslash is - interpreted as a literal double quotation mark. - - 4) Backslashes are interpreted literally, unless they - immediately precede a double quotation mark. - - 5) If backslashes immediately precede a double quotation mark, - every pair of backslashes is interpreted as a literal - backslash. If the number of backslashes is odd, the last - backslash escapes the next double quotation mark as - described in rule 3. - """ - - # See - # http://msdn.microsoft.com/library/en-us/vccelng/htm/progs_12.asp - result = [] - needquote = False - for arg in seq: - bs_buf = [] - - # Add a space to separate this argument from the others - if result: - result.append(' ') - - needquote = (" " in arg) or ("\t" in arg) - if needquote: - result.append('"') - - for c in arg: - if c == '\\': - # Don't know if we need to double yet. - bs_buf.append(c) - elif c == '"': - # Double backspaces. - result.append('\\' * len(bs_buf)*2) - bs_buf = [] - result.append('\\"') - else: - # Normal char - if bs_buf: - result.extend(bs_buf) - bs_buf = [] - result.append(c) - - # Add remaining backspaces, if any. - if bs_buf: - result.extend(bs_buf) - - if needquote: - result.extend(bs_buf) - result.append('"') - - return ''.join(result) - -class Popen(object): - def __init__(self, args, bufsize=0, executable=None, - stdin=None, stdout=None, stderr=None, - preexec_fn=None, close_fds=False, shell=False, - cwd=None, env=None, universal_newlines=False, - startupinfo=None, creationflags=0): - """Create new Popen instance.""" - _cleanup() - - self._child_created = False - if not is_int_or_long(bufsize): - raise TypeError("bufsize must be an integer") - - if mswindows: - if preexec_fn is not None: - raise ValueError("preexec_fn is not supported on Windows " - "platforms") - if close_fds: - raise ValueError("close_fds is not supported on Windows " - "platforms") - else: - # POSIX - if startupinfo is not None: - raise ValueError("startupinfo is only supported on Windows " - "platforms") - if creationflags != 0: - raise ValueError("creationflags is only supported on Windows " - "platforms") - - self.stdin = None - self.stdout = None - self.stderr = None - self.pid = None - self.returncode = None - self.universal_newlines = universal_newlines - - # Input and output objects. The general principle is like - # this: - # - # Parent Child - # ------ ----- - # p2cwrite ---stdin---> p2cread - # c2pread <--stdout--- c2pwrite - # errread <--stderr--- errwrite - # - # On POSIX, the child objects are file descriptors. On - # Windows, these are Windows file handles. The parent objects - # are file descriptors on both platforms. The parent objects - # are None when not using PIPEs. The child objects are None - # when not redirecting. - - (p2cread, p2cwrite, - c2pread, c2pwrite, - errread, errwrite) = self._get_handles(stdin, stdout, stderr) - - self._execute_child(args, executable, preexec_fn, close_fds, - cwd, env, universal_newlines, - startupinfo, creationflags, shell, - p2cread, p2cwrite, - c2pread, c2pwrite, - errread, errwrite) - - if p2cwrite: - self.stdin = os.fdopen(p2cwrite, 'wb', bufsize) - if c2pread: - if universal_newlines: - self.stdout = os.fdopen(c2pread, 'rU', bufsize) - else: - self.stdout = os.fdopen(c2pread, 'rb', bufsize) - if errread: - if universal_newlines: - self.stderr = os.fdopen(errread, 'rU', bufsize) - else: - self.stderr = os.fdopen(errread, 'rb', bufsize) - - - def _translate_newlines(self, data): - data = data.replace("\r\n", "\n") - data = data.replace("\r", "\n") - return data - - - def __del__(self): - if not self._child_created: - # We didn't get to successfully create a child process. - return - # In case the child hasn't been waited on, check if it's done. - self.poll(_deadstate=sys.maxsize) - if self.returncode is None and _active is not None: - # Child is still running, keep us alive until we can wait on it. - _active.append(self) - - - def communicate(self, input=None): - """Interact with process: Send data to stdin. Read data from - stdout and stderr, until end-of-file is reached. Wait for - process to terminate. The optional input argument should be a - string to be sent to the child process, or None, if no data - should be sent to the child. - - communicate() returns a tuple (stdout, stderr).""" - - # Optimization: If we are only using one pipe, or no pipe at - # all, using select() or threads is unnecessary. - if [self.stdin, self.stdout, self.stderr].count(None) >= 2: - stdout = None - stderr = None - if self.stdin: - if input: - self.stdin.write(input) - self.stdin.close() - elif self.stdout: - stdout = self.stdout.read() - elif self.stderr: - stderr = self.stderr.read() - self.wait() - return (stdout, stderr) - - return self._communicate(input) - - - if mswindows: - # - # Windows methods - # - def _get_handles(self, stdin, stdout, stderr): - """Construct and return tupel with IO objects: - p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite - """ - if stdin is None and stdout is None and stderr is None: - return (None, None, None, None, None, None) - - p2cread, p2cwrite = None, None - c2pread, c2pwrite = None, None - errread, errwrite = None, None - - if stdin is None: - p2cread = GetStdHandle(STD_INPUT_HANDLE) - elif stdin == PIPE: - p2cread, p2cwrite = CreatePipe(None, 0) - # Detach and turn into fd - p2cwrite = p2cwrite.Detach() - p2cwrite = msvcrt.open_osfhandle(p2cwrite, 0) - elif is_int(stdin): - p2cread = msvcrt.get_osfhandle(stdin) - else: - # Assuming file-like object - p2cread = msvcrt.get_osfhandle(stdin.fileno()) - p2cread = self._make_inheritable(p2cread) - - if stdout is None: - c2pwrite = GetStdHandle(STD_OUTPUT_HANDLE) - elif stdout == PIPE: - c2pread, c2pwrite = CreatePipe(None, 0) - # Detach and turn into fd - c2pread = c2pread.Detach() - c2pread = msvcrt.open_osfhandle(c2pread, 0) - elif is_int(stdout): - c2pwrite = msvcrt.get_osfhandle(stdout) - else: - # Assuming file-like object - c2pwrite = msvcrt.get_osfhandle(stdout.fileno()) - c2pwrite = self._make_inheritable(c2pwrite) - - if stderr is None: - errwrite = GetStdHandle(STD_ERROR_HANDLE) - elif stderr == PIPE: - errread, errwrite = CreatePipe(None, 0) - # Detach and turn into fd - errread = errread.Detach() - errread = msvcrt.open_osfhandle(errread, 0) - elif stderr == STDOUT: - errwrite = c2pwrite - elif is_int(stderr): - errwrite = msvcrt.get_osfhandle(stderr) - else: - # Assuming file-like object - errwrite = msvcrt.get_osfhandle(stderr.fileno()) - errwrite = self._make_inheritable(errwrite) - - return (p2cread, p2cwrite, - c2pread, c2pwrite, - errread, errwrite) - - - def _make_inheritable(self, handle): - """Return a duplicate of handle, which is inheritable""" - return DuplicateHandle(GetCurrentProcess(), handle, - GetCurrentProcess(), 0, 1, - DUPLICATE_SAME_ACCESS) - - - def _find_w9xpopen(self): - """Find and return absolut path to w9xpopen.exe""" - w9xpopen = os.path.join(os.path.dirname(GetModuleFileName(0)), - "w9xpopen.exe") - if not os.path.exists(w9xpopen): - # Eeek - file-not-found - possibly an embedding - # situation - see if we can locate it in sys.exec_prefix - w9xpopen = os.path.join(os.path.dirname(sys.exec_prefix), - "w9xpopen.exe") - if not os.path.exists(w9xpopen): - raise RuntimeError("Cannot locate w9xpopen.exe, which is " - "needed for Popen to work with your " - "shell or platform.") - return w9xpopen - - - def _execute_child(self, args, executable, preexec_fn, close_fds, - cwd, env, universal_newlines, - startupinfo, creationflags, shell, - p2cread, p2cwrite, - c2pread, c2pwrite, - errread, errwrite): - """Execute program (MS Windows version)""" - - if not isinstance(args, types.StringTypes): - args = list2cmdline(args) - - # Process startup details - if startupinfo is None: - startupinfo = STARTUPINFO() - if None not in (p2cread, c2pwrite, errwrite): - startupinfo.dwFlags = startupinfo.dwFlags | STARTF_USESTDHANDLES - startupinfo.hStdInput = p2cread - startupinfo.hStdOutput = c2pwrite - startupinfo.hStdError = errwrite - - if shell: - startupinfo.dwFlags = startupinfo.dwFlags | STARTF_USESHOWWINDOW - startupinfo.wShowWindow = SW_HIDE - comspec = os.environ.get("COMSPEC", "cmd.exe") - args = comspec + " /c " + args - if (GetVersion() >= 0x80000000L or - os.path.basename(comspec).lower() == "command.com"): - # Win9x, or using command.com on NT. We need to - # use the w9xpopen intermediate program. For more - # information, see KB Q150956 - # (http://web.archive.org/web/20011105084002/http://support.microsoft.com/support/kb/articles/Q150/9/56.asp) - w9xpopen = self._find_w9xpopen() - args = '"%s" %s' % (w9xpopen, args) - # Not passing CREATE_NEW_CONSOLE has been known to - # cause random failures on win9x. Specifically a - # dialog: "Your program accessed mem currently in - # use at xxx" and a hopeful warning about the - # stability of your system. Cost is Ctrl+C wont - # kill children. - creationflags = creationflags | CREATE_NEW_CONSOLE - - # Start the process - try: - hp, ht, pid, tid = CreateProcess(executable, args, - # no special security - None, None, - # must inherit handles to pass std - # handles - 1, - creationflags, - env, - cwd, - startupinfo) - except pywintypes.error, e: - # Translate pywintypes.error to WindowsError, which is - # a subclass of OSError. FIXME: We should really - # translate errno using _sys_errlist (or simliar), but - # how can this be done from Python? - raise WindowsError(*e.args) - - # Retain the process handle, but close the thread handle - self._child_created = True - self._handle = hp - self.pid = pid - ht.Close() - - # Child is launched. Close the parent's copy of those pipe - # handles that only the child should have open. You need - # to make sure that no handles to the write end of the - # output pipe are maintained in this process or else the - # pipe will not close when the child process exits and the - # ReadFile will hang. - if p2cread is not None: - p2cread.Close() - if c2pwrite is not None: - c2pwrite.Close() - if errwrite is not None: - errwrite.Close() - - - def poll(self, _deadstate=None): - """Check if child process has terminated. Returns returncode - attribute.""" - if self.returncode is None: - if WaitForSingleObject(self._handle, 0) == WAIT_OBJECT_0: - self.returncode = GetExitCodeProcess(self._handle) - return self.returncode - - - def wait(self): - """Wait for child process to terminate. Returns returncode - attribute.""" - if self.returncode is None: - obj = WaitForSingleObject(self._handle, INFINITE) - self.returncode = GetExitCodeProcess(self._handle) - return self.returncode - - - def _readerthread(self, fh, buffer): - buffer.append(fh.read()) - - - def _communicate(self, input): - stdout = None # Return - stderr = None # Return - - if self.stdout: - stdout = [] - stdout_thread = threading.Thread(target=self._readerthread, - args=(self.stdout, stdout)) - stdout_thread.setDaemon(True) - stdout_thread.start() - if self.stderr: - stderr = [] - stderr_thread = threading.Thread(target=self._readerthread, - args=(self.stderr, stderr)) - stderr_thread.setDaemon(True) - stderr_thread.start() - - if self.stdin: - if input is not None: - self.stdin.write(input) - self.stdin.close() - - if self.stdout: - stdout_thread.join() - if self.stderr: - stderr_thread.join() - - # All data exchanged. Translate lists into strings. - if stdout is not None: - stdout = stdout[0] - if stderr is not None: - stderr = stderr[0] - - # Translate newlines, if requested. We cannot let the file - # object do the translation: It is based on stdio, which is - # impossible to combine with select (unless forcing no - # buffering). - if self.universal_newlines and hasattr(file, 'newlines'): - if stdout: - stdout = self._translate_newlines(stdout) - if stderr: - stderr = self._translate_newlines(stderr) - - self.wait() - return (stdout, stderr) - - else: - # - # POSIX methods - # - def _get_handles(self, stdin, stdout, stderr): - """Construct and return tupel with IO objects: - p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite - """ - p2cread, p2cwrite = None, None - c2pread, c2pwrite = None, None - errread, errwrite = None, None - - if stdin is None: - pass - elif stdin == PIPE: - p2cread, p2cwrite = os.pipe() - elif is_int(stdin): - p2cread = stdin - else: - # Assuming file-like object - p2cread = stdin.fileno() - - if stdout is None: - pass - elif stdout == PIPE: - c2pread, c2pwrite = os.pipe() - elif is_int(stdout): - c2pwrite = stdout - else: - # Assuming file-like object - c2pwrite = stdout.fileno() - - if stderr is None: - pass - elif stderr == PIPE: - errread, errwrite = os.pipe() - elif stderr == STDOUT: - errwrite = c2pwrite - elif is_int(stderr): - errwrite = stderr - else: - # Assuming file-like object - errwrite = stderr.fileno() - - return (p2cread, p2cwrite, - c2pread, c2pwrite, - errread, errwrite) - - - def _set_cloexec_flag(self, fd): - try: - cloexec_flag = fcntl.FD_CLOEXEC - except AttributeError: - cloexec_flag = 1 - - old = fcntl.fcntl(fd, fcntl.F_GETFD) - fcntl.fcntl(fd, fcntl.F_SETFD, old | cloexec_flag) - - - def _close_fds(self, but): - for i in range(3, MAXFD): - if i == but: - continue - try: - os.close(i) - except KeyboardInterrupt: - raise # SCons: don't swallow keyboard interrupts - except: - pass - - - def _execute_child(self, args, executable, preexec_fn, close_fds, - cwd, env, universal_newlines, - startupinfo, creationflags, shell, - p2cread, p2cwrite, - c2pread, c2pwrite, - errread, errwrite): - """Execute program (POSIX version)""" - - if is_string(args): - args = [args] - - if shell: - args = ["/bin/sh", "-c"] + args - - if executable is None: - executable = args[0] - - # For transferring possible exec failure from child to parent - # The first char specifies the exception type: 0 means - # OSError, 1 means some other error. - errpipe_read, errpipe_write = os.pipe() - self._set_cloexec_flag(errpipe_write) - - self.pid = os.fork() - self._child_created = True - if self.pid == 0: - # Child - try: - # Close parent's pipe ends - if p2cwrite: - os.close(p2cwrite) - if c2pread: - os.close(c2pread) - if errread: - os.close(errread) - os.close(errpipe_read) - - # Dup fds for child - if p2cread: - os.dup2(p2cread, 0) - if c2pwrite: - os.dup2(c2pwrite, 1) - if errwrite: - os.dup2(errwrite, 2) - - # Close pipe fds. Make sure we don't close the same - # fd more than once, or standard fds. - try: - set - except NameError: - # Fall-back for earlier Python versions, so epydoc - # can use this module directly to execute things. - if p2cread: - os.close(p2cread) - if c2pwrite and c2pwrite not in (p2cread,): - os.close(c2pwrite) - if errwrite and errwrite not in (p2cread, c2pwrite): - os.close(errwrite) - else: - for fd in set((p2cread, c2pwrite, errwrite))-set((0,1,2)): - if fd: os.close(fd) - - # Close all other fds, if asked for - if close_fds: - self._close_fds(but=errpipe_write) - - if cwd is not None: - os.chdir(cwd) - - if preexec_fn: - apply(preexec_fn) - - if env is None: - os.execvp(executable, args) - else: - os.execvpe(executable, args, env) - - except KeyboardInterrupt: - raise # SCons: don't swallow keyboard interrupts - - except: - exc_type, exc_value, tb = sys.exc_info() - # Save the traceback and attach it to the exception object - exc_lines = traceback.format_exception(exc_type, - exc_value, - tb) - exc_value.child_traceback = ''.join(exc_lines) - os.write(errpipe_write, pickle.dumps(exc_value)) - - # This exitcode won't be reported to applications, so it - # really doesn't matter what we return. - os._exit(255) - - # Parent - os.close(errpipe_write) - if p2cread and p2cwrite: - os.close(p2cread) - if c2pwrite and c2pread: - os.close(c2pwrite) - if errwrite and errread: - os.close(errwrite) - - # Wait for exec to fail or succeed; possibly raising exception - data = os.read(errpipe_read, 1048576) # Exceptions limited to 1 MB - os.close(errpipe_read) - if data != "": - os.waitpid(self.pid, 0) - child_exception = pickle.loads(data) - raise child_exception - - - def _handle_exitstatus(self, sts): - if os.WIFSIGNALED(sts): - self.returncode = -os.WTERMSIG(sts) - elif os.WIFEXITED(sts): - self.returncode = os.WEXITSTATUS(sts) - else: - # Should never happen - raise RuntimeError("Unknown child exit status!") - - - def poll(self, _deadstate=None): - """Check if child process has terminated. Returns returncode - attribute.""" - if self.returncode is None: - try: - pid, sts = os.waitpid(self.pid, os.WNOHANG) - if pid == self.pid: - self._handle_exitstatus(sts) - except os.error: - if _deadstate is not None: - self.returncode = _deadstate - return self.returncode - - - def wait(self): - """Wait for child process to terminate. Returns returncode - attribute.""" - if self.returncode is None: - pid, sts = os.waitpid(self.pid, 0) - self._handle_exitstatus(sts) - return self.returncode - - - def _communicate(self, input): - read_set = [] - write_set = [] - stdout = None # Return - stderr = None # Return - - if self.stdin: - # Flush stdio buffer. This might block, if the user has - # been writing to .stdin in an uncontrolled fashion. - self.stdin.flush() - if input: - write_set.append(self.stdin) - else: - self.stdin.close() - if self.stdout: - read_set.append(self.stdout) - stdout = [] - if self.stderr: - read_set.append(self.stderr) - stderr = [] - - input_offset = 0 - while read_set or write_set: - rlist, wlist, xlist = select.select(read_set, write_set, []) - - if self.stdin in wlist: - # When select has indicated that the file is writable, - # we can write up to PIPE_BUF bytes without risk - # blocking. POSIX defines PIPE_BUF >= 512 - m = memoryview(input)[input_offset:input_offset+512] - bytes_written = os.write(self.stdin.fileno(), m) - input_offset = input_offset + bytes_written - if input_offset >= len(input): - self.stdin.close() - write_set.remove(self.stdin) - - if self.stdout in rlist: - data = os.read(self.stdout.fileno(), 1024) - if data == "": - self.stdout.close() - read_set.remove(self.stdout) - stdout.append(data) - - if self.stderr in rlist: - data = os.read(self.stderr.fileno(), 1024) - if data == "": - self.stderr.close() - read_set.remove(self.stderr) - stderr.append(data) - - # All data exchanged. Translate lists into strings. - if stdout is not None: - stdout = ''.join(stdout) - if stderr is not None: - stderr = ''.join(stderr) - - # Translate newlines, if requested. We cannot let the file - # object do the translation: It is based on stdio, which is - # impossible to combine with select (unless forcing no - # buffering). - if self.universal_newlines and hasattr(file, 'newlines'): - if stdout: - stdout = self._translate_newlines(stdout) - if stderr: - stderr = self._translate_newlines(stderr) - - self.wait() - return (stdout, stderr) - - -def _demo_posix(): - # - # Example 1: Simple redirection: Get process list - # - plist = Popen(["ps"], stdout=PIPE).communicate()[0] - print "Process list:" - print plist - - # - # Example 2: Change uid before executing child - # - if os.getuid() == 0: - p = Popen(["id"], preexec_fn=lambda: os.setuid(100)) - p.wait() - - # - # Example 3: Connecting several subprocesses - # - print "Looking for 'hda'..." - p1 = Popen(["dmesg"], stdout=PIPE) - p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) - print repr(p2.communicate()[0]) - - # - # Example 4: Catch execution error - # - print - print "Trying a weird file..." - try: - print Popen(["/this/path/does/not/exist"]).communicate() - except OSError, e: - if e.errno == errno.ENOENT: - print "The file didn't exist. I thought so..." - print "Child traceback:" - print e.child_traceback - else: - print "Error", e.errno - else: - sys.stderr.write( "Gosh. No error.\n" ) - - -def _demo_windows(): - # - # Example 1: Connecting several subprocesses - # - print "Looking for 'PROMPT' in set output..." - p1 = Popen("set", stdout=PIPE, shell=True) - p2 = Popen('find "PROMPT"', stdin=p1.stdout, stdout=PIPE) - print repr(p2.communicate()[0]) - - # - # Example 2: Simple execution of program - # - print "Executing calc..." - p = Popen("calc") - p.wait() - - -if __name__ == "__main__": - if mswindows: - _demo_windows() - else: - _demo_posix() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From 63a9014d1023fd2fdd256cd42e4c4843e5bdcee0 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 19 Nov 2015 10:41:35 -0800 Subject: removing compat for sets. python 2.7 supports sets --- src/engine/SCons/compat/__init__.py | 8 - src/engine/SCons/compat/_scons_sets.py | 563 --------------------------------- 2 files changed, 571 deletions(-) delete mode 100644 src/engine/SCons/compat/_scons_sets.py diff --git a/src/engine/SCons/compat/__init__.py b/src/engine/SCons/compat/__init__.py index 281392c..ab21faf 100644 --- a/src/engine/SCons/compat/__init__.py +++ b/src/engine/SCons/compat/__init__.py @@ -103,14 +103,6 @@ except ImportError: # can fall back to using timestamp. pass -try: - set -except NameError: - # Pre-2.4 Python has no native set type - import_as('_scons_sets', 'sets') - import builtins, sets - builtins.set = sets.Set - try: import collections diff --git a/src/engine/SCons/compat/_scons_sets.py b/src/engine/SCons/compat/_scons_sets.py deleted file mode 100644 index 0fde994..0000000 --- a/src/engine/SCons/compat/_scons_sets.py +++ /dev/null @@ -1,563 +0,0 @@ -"""Classes to represent arbitrary sets (including sets of sets). - -This module implements sets using dictionaries whose values are -ignored. The usual operations (union, intersection, deletion, etc.) -are provided as both methods and operators. - -Important: sets are not sequences! While they support 'x in s', -'len(s)', and 'for x in s', none of those operations are unique for -sequences; for example, mappings support all three as well. The -characteristic operation for sequences is subscripting with small -integers: s[i], for i in range(len(s)). Sets don't support -subscripting at all. Also, sequences allow multiple occurrences and -their elements have a definite order; sets on the other hand don't -record multiple occurrences and don't remember the order of element -insertion (which is why they don't support s[i]). - -The following classes are provided: - -BaseSet -- All the operations common to both mutable and immutable - sets. This is an abstract class, not meant to be directly - instantiated. - -Set -- Mutable sets, subclass of BaseSet; not hashable. - -ImmutableSet -- Immutable sets, subclass of BaseSet; hashable. - An iterable argument is mandatory to create an ImmutableSet. - -_TemporarilyImmutableSet -- A wrapper around a Set, hashable, - giving the same hash value as the immutable set equivalent - would have. Do not use this class directly. - -Only hashable objects can be added to a Set. In particular, you cannot -really add a Set as an element to another Set; if you try, what is -actually added is an ImmutableSet built from it (it compares equal to -the one you tried adding). - -When you ask if `x in y' where x is a Set and y is a Set or -ImmutableSet, x is wrapped into a _TemporarilyImmutableSet z, and -what's tested is actually `z in y'. - -""" - -# Code history: -# -# - Greg V. Wilson wrote the first version, using a different approach -# to the mutable/immutable problem, and inheriting from dict. -# -# - Alex Martelli modified Greg's version to implement the current -# Set/ImmutableSet approach, and make the data an attribute. -# -# - Guido van Rossum rewrote much of the code, made some API changes, -# and cleaned up the docstrings. -# -# - Raymond Hettinger added a number of speedups and other -# improvements. - -# protect this import from the fixers... -exec('from itertools import ifilterfalse as filterfalse') - -__all__ = ['BaseSet', 'Set', 'ImmutableSet'] - -class BaseSet(object): - """Common base class for mutable and immutable sets.""" - - __slots__ = ['_data'] - - # Constructor - - def __init__(self): - """This is an abstract class.""" - # Don't call this from a concrete subclass! - if self.__class__ is BaseSet: - raise TypeError("BaseSet is an abstract class. " - "Use Set or ImmutableSet.") - - # Standard protocols: __len__, __repr__, __str__, __iter__ - - def __len__(self): - """Return the number of elements of a set.""" - return len(self._data) - - def __repr__(self): - """Return string representation of a set. - - This looks like 'Set([])'. - """ - return self._repr() - - # __str__ is the same as __repr__ - __str__ = __repr__ - - def _repr(self, sort_them=False): - elements = list(self._data.keys()) - if sort_them: - elements.sort() - return '%s(%r)' % (self.__class__.__name__, elements) - - def __iter__(self): - """Return an iterator over the elements or a set. - - This is the keys iterator for the underlying dict. - """ - # Wrapping name in () prevents fixer from "fixing" this - return (self._data.iterkeys)() - - # Three-way comparison is not supported. However, because __eq__ is - # tried before __cmp__, if Set x == Set y, x.__eq__(y) returns True and - # then cmp(x, y) returns 0 (Python doesn't actually call __cmp__ in this - # case). - - def __cmp__(self, other): - raise TypeError("can't compare sets using cmp()") - - # Equality comparisons using the underlying dicts. Mixed-type comparisons - # are allowed here, where Set == z for non-Set z always returns False, - # and Set != z always True. This allows expressions like "x in y" to - # give the expected result when y is a sequence of mixed types, not - # raising a pointless TypeError just because y contains a Set, or x is - # a Set and y contain's a non-set ("in" invokes only __eq__). - # Subtle: it would be nicer if __eq__ and __ne__ could return - # NotImplemented instead of True or False. Then the other comparand - # would get a chance to determine the result, and if the other comparand - # also returned NotImplemented then it would fall back to object address - # comparison (which would always return False for __eq__ and always - # True for __ne__). However, that doesn't work, because this type - # *also* implements __cmp__: if, e.g., __eq__ returns NotImplemented, - # Python tries __cmp__ next, and the __cmp__ here then raises TypeError. - - def __eq__(self, other): - if isinstance(other, BaseSet): - return self._data == other._data - else: - return False - - def __ne__(self, other): - if isinstance(other, BaseSet): - return self._data != other._data - else: - return True - - # Copying operations - - def copy(self): - """Return a shallow copy of a set.""" - result = self.__class__() - result._data.update(self._data) - return result - - __copy__ = copy # For the copy module - - def __deepcopy__(self, memo): - """Return a deep copy of a set; used by copy module.""" - # This pre-creates the result and inserts it in the memo - # early, in case the deep copy recurses into another reference - # to this same set. A set can't be an element of itself, but - # it can certainly contain an object that has a reference to - # itself. - from copy import deepcopy - result = self.__class__() - memo[id(self)] = result - data = result._data - value = True - for elt in self: - data[deepcopy(elt, memo)] = value - return result - - # Standard set operations: union, intersection, both differences. - # Each has an operator version (e.g. __or__, invoked with |) and a - # method version (e.g. union). - # Subtle: Each pair requires distinct code so that the outcome is - # correct when the type of other isn't suitable. For example, if - # we did "union = __or__" instead, then Set().union(3) would return - # NotImplemented instead of raising TypeError (albeit that *why* it - # raises TypeError as-is is also a bit subtle). - - def __or__(self, other): - """Return the union of two sets as a new set. - - (I.e. all elements that are in either set.) - """ - if not isinstance(other, BaseSet): - return NotImplemented - return self.union(other) - - def union(self, other): - """Return the union of two sets as a new set. - - (I.e. all elements that are in either set.) - """ - result = self.__class__(self) - result._update(other) - return result - - def __and__(self, other): - """Return the intersection of two sets as a new set. - - (I.e. all elements that are in both sets.) - """ - if not isinstance(other, BaseSet): - return NotImplemented - return self.intersection(other) - - def intersection(self, other): - """Return the intersection of two sets as a new set. - - (I.e. all elements that are in both sets.) - """ - if not isinstance(other, BaseSet): - other = Set(other) - if len(self) <= len(other): - little, big = self, other - else: - little, big = other, self - common = iter(filter(big._data.has_key, little)) - return self.__class__(common) - - def __xor__(self, other): - """Return the symmetric difference of two sets as a new set. - - (I.e. all elements that are in exactly one of the sets.) - """ - if not isinstance(other, BaseSet): - return NotImplemented - return self.symmetric_difference(other) - - def symmetric_difference(self, other): - """Return the symmetric difference of two sets as a new set. - - (I.e. all elements that are in exactly one of the sets.) - """ - result = self.__class__() - data = result._data - value = True - selfdata = self._data - try: - otherdata = other._data - except AttributeError: - otherdata = Set(other)._data - for elt in filterfalse(otherdata.has_key, selfdata): - data[elt] = value - for elt in filterfalse(selfdata.has_key, otherdata): - data[elt] = value - return result - - def __sub__(self, other): - """Return the difference of two sets as a new Set. - - (I.e. all elements that are in this set and not in the other.) - """ - if not isinstance(other, BaseSet): - return NotImplemented - return self.difference(other) - - def difference(self, other): - """Return the difference of two sets as a new Set. - - (I.e. all elements that are in this set and not in the other.) - """ - result = self.__class__() - data = result._data - try: - otherdata = other._data - except AttributeError: - otherdata = Set(other)._data - value = True - for elt in filterfalse(otherdata.has_key, self): - data[elt] = value - return result - - # Membership test - - def __contains__(self, element): - """Report whether an element is a member of a set. - - (Called in response to the expression `element in self'.) - """ - try: - return element in self._data - except TypeError: - transform = getattr(element, "__as_temporarily_immutable__", None) - if transform is None: - raise # re-raise the TypeError exception we caught - return transform() in self._data - - # Subset and superset test - - def issubset(self, other): - """Report whether another set contains this set.""" - self._binary_sanity_check(other) - if len(self) > len(other): # Fast check for obvious cases - return False - for elt in filterfalse(other._data.has_key, self): - return False - return True - - def issuperset(self, other): - """Report whether this set contains another set.""" - self._binary_sanity_check(other) - if len(self) < len(other): # Fast check for obvious cases - return False - for elt in filterfalse(self._data.has_key, other): - return False - return True - - # Inequality comparisons using the is-subset relation. - __le__ = issubset - __ge__ = issuperset - - def __lt__(self, other): - self._binary_sanity_check(other) - return len(self) < len(other) and self.issubset(other) - - def __gt__(self, other): - self._binary_sanity_check(other) - return len(self) > len(other) and self.issuperset(other) - - # Assorted helpers - - def _binary_sanity_check(self, other): - # Check that the other argument to a binary operation is also - # a set, raising a TypeError otherwise. - if not isinstance(other, BaseSet): - raise TypeError("Binary operation only permitted between sets") - - def _compute_hash(self): - # Calculate hash code for a set by xor'ing the hash codes of - # the elements. This ensures that the hash code does not depend - # on the order in which elements are added to the set. This is - # not called __hash__ because a BaseSet should not be hashable; - # only an ImmutableSet is hashable. - result = 0 - for elt in self: - result ^= hash(elt) - return result - - def _update(self, iterable): - # The main loop for update() and the subclass __init__() methods. - data = self._data - - # Use the fast update() method when a dictionary is available. - if isinstance(iterable, BaseSet): - data.update(iterable._data) - return - - value = True - - if type(iterable) in (list, tuple, xrange): - # Optimized: we know that __iter__() and next() can't - # raise TypeError, so we can move 'try:' out of the loop. - it = iter(iterable) - while True: - try: - for element in it: - data[element] = value - return - except TypeError: - transform = getattr(element, "__as_immutable__", None) - if transform is None: - raise # re-raise the TypeError exception we caught - data[transform()] = value - else: - # Safe: only catch TypeError where intended - for element in iterable: - try: - data[element] = value - except TypeError: - transform = getattr(element, "__as_immutable__", None) - if transform is None: - raise # re-raise the TypeError exception we caught - data[transform()] = value - - -class ImmutableSet(BaseSet): - """Immutable set class.""" - - __slots__ = ['_hashcode'] - - # BaseSet + hashing - - def __init__(self, iterable=None): - """Construct an immutable set from an optional iterable.""" - self._hashcode = None - self._data = {} - if iterable is not None: - self._update(iterable) - - def __hash__(self): - if self._hashcode is None: - self._hashcode = self._compute_hash() - return self._hashcode - - def __getstate__(self): - return self._data, self._hashcode - - def __setstate__(self, state): - self._data, self._hashcode = state - -class Set(BaseSet): - """ Mutable set class.""" - - __slots__ = [] - - # BaseSet + operations requiring mutability; no hashing - - def __init__(self, iterable=None): - """Construct a set from an optional iterable.""" - self._data = {} - if iterable is not None: - self._update(iterable) - - def __getstate__(self): - # getstate's results are ignored if it is not - return self._data, - - def __setstate__(self, data): - self._data, = data - - def __hash__(self): - """A Set cannot be hashed.""" - # We inherit object.__hash__, so we must deny this explicitly - raise TypeError("Can't hash a Set, only an ImmutableSet.") - - # In-place union, intersection, differences. - # Subtle: The xyz_update() functions deliberately return None, - # as do all mutating operations on built-in container types. - # The __xyz__ spellings have to return self, though. - - def __ior__(self, other): - """Update a set with the union of itself and another.""" - self._binary_sanity_check(other) - self._data.update(other._data) - return self - - def union_update(self, other): - """Update a set with the union of itself and another.""" - self._update(other) - - def __iand__(self, other): - """Update a set with the intersection of itself and another.""" - self._binary_sanity_check(other) - self._data = (self & other)._data - return self - - def intersection_update(self, other): - """Update a set with the intersection of itself and another.""" - if isinstance(other, BaseSet): - self &= other - else: - self._data = (self.intersection(other))._data - - def __ixor__(self, other): - """Update a set with the symmetric difference of itself and another.""" - self._binary_sanity_check(other) - self.symmetric_difference_update(other) - return self - - def symmetric_difference_update(self, other): - """Update a set with the symmetric difference of itself and another.""" - data = self._data - value = True - if not isinstance(other, BaseSet): - other = Set(other) - if self is other: - self.clear() - for elt in other: - if elt in data: - del data[elt] - else: - data[elt] = value - - def __isub__(self, other): - """Remove all elements of another set from this set.""" - self._binary_sanity_check(other) - self.difference_update(other) - return self - - def difference_update(self, other): - """Remove all elements of another set from this set.""" - data = self._data - if not isinstance(other, BaseSet): - other = Set(other) - if self is other: - self.clear() - for elt in filter(data.has_key, other): - del data[elt] - - # Python dict-like mass mutations: update, clear - - def update(self, iterable): - """Add all values from an iterable (such as a list or file).""" - self._update(iterable) - - def clear(self): - """Remove all elements from this set.""" - self._data.clear() - - # Single-element mutations: add, remove, discard - - def add(self, element): - """Add an element to a set. - - This has no effect if the element is already present. - """ - try: - self._data[element] = True - except TypeError: - transform = getattr(element, "__as_immutable__", None) - if transform is None: - raise # re-raise the TypeError exception we caught - self._data[transform()] = True - - def remove(self, element): - """Remove an element from a set; it must be a member. - - If the element is not a member, raise a KeyError. - """ - try: - del self._data[element] - except TypeError: - transform = getattr(element, "__as_temporarily_immutable__", None) - if transform is None: - raise # re-raise the TypeError exception we caught - del self._data[transform()] - - def discard(self, element): - """Remove an element from a set if it is a member. - - If the element is not a member, do nothing. - """ - try: - self.remove(element) - except KeyError: - pass - - def pop(self): - """Remove and return an arbitrary set element.""" - return self._data.popitem()[0] - - def __as_immutable__(self): - # Return a copy of self as an immutable set - return ImmutableSet(self) - - def __as_temporarily_immutable__(self): - # Return self wrapped in a temporarily immutable set - return _TemporarilyImmutableSet(self) - - -class _TemporarilyImmutableSet(BaseSet): - # Wrap a mutable set as if it was temporarily immutable. - # This only supplies hashing and equality comparisons. - - def __init__(self, set): - self._set = set - self._data = set._data # Needed by ImmutableSet.__eq__() - - def __hash__(self): - return self._set._compute_hash() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From e806691e1e680d003c47ef6212ca7bf74e437c5b Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 19 Nov 2015 10:43:43 -0800 Subject: remove compat collections. python 2.7 supports collections --- src/engine/SCons/compat/__init__.py | 26 ---------------- src/engine/SCons/compat/_scons_collections.py | 45 --------------------------- 2 files changed, 71 deletions(-) delete mode 100644 src/engine/SCons/compat/_scons_collections.py diff --git a/src/engine/SCons/compat/__init__.py b/src/engine/SCons/compat/__init__.py index ab21faf..06cee57 100644 --- a/src/engine/SCons/compat/__init__.py +++ b/src/engine/SCons/compat/__init__.py @@ -105,32 +105,6 @@ except ImportError: try: - import collections -except ImportError: - # Pre-2.4 Python has no collections module. - import_as('_scons_collections', 'collections') -else: - try: - collections.UserDict - except AttributeError: - exec('from UserDict import UserDict as _UserDict') - collections.UserDict = _UserDict - del _UserDict - try: - collections.UserList - except AttributeError: - exec('from UserList import UserList as _UserList') - collections.UserList = _UserList - del _UserList - try: - collections.UserString - except AttributeError: - exec('from UserString import UserString as _UserString') - collections.UserString = _UserString - del _UserString - - -try: import io except ImportError: # Pre-2.6 Python has no io module. diff --git a/src/engine/SCons/compat/_scons_collections.py b/src/engine/SCons/compat/_scons_collections.py deleted file mode 100644 index 1591b2e..0000000 --- a/src/engine/SCons/compat/_scons_collections.py +++ /dev/null @@ -1,45 +0,0 @@ -# -# __COPYRIGHT__ -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# 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. -# - -__doc__ = """ -collections compatibility module for older (pre-2.4) Python versions - -This does not not NOT (repeat, *NOT*) provide complete collections -functionality. It only wraps the portions of collections functionality -used by SCons, in an interface that looks enough like collections for -our purposes. -""" - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -# Use exec to hide old names from fixers. -exec("""if True: - from UserDict import UserDict - from UserList import UserList - from UserString import UserString""") - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From 20bbea44264012aa96806c661f904b38ba5639d4 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 19 Nov 2015 10:49:06 -0800 Subject: remove compat io. python 2.7 supports io --- src/engine/SCons/compat/__init__.py | 7 ------ src/engine/SCons/compat/_scons_io.py | 45 ------------------------------------ 2 files changed, 52 deletions(-) delete mode 100644 src/engine/SCons/compat/_scons_io.py diff --git a/src/engine/SCons/compat/__init__.py b/src/engine/SCons/compat/__init__.py index 06cee57..68fb9e4 100644 --- a/src/engine/SCons/compat/__init__.py +++ b/src/engine/SCons/compat/__init__.py @@ -105,13 +105,6 @@ except ImportError: try: - import io -except ImportError: - # Pre-2.6 Python has no io module. - import_as('_scons_io', 'io') - - -try: os.devnull except AttributeError: # Pre-2.4 Python has no os.devnull attribute diff --git a/src/engine/SCons/compat/_scons_io.py b/src/engine/SCons/compat/_scons_io.py deleted file mode 100644 index 538afb7..0000000 --- a/src/engine/SCons/compat/_scons_io.py +++ /dev/null @@ -1,45 +0,0 @@ -# -# __COPYRIGHT__ -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# 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. -# - -__doc__ = """ -io compatibility module for older (pre-2.6) Python versions - -This does not not NOT (repeat, *NOT*) provide complete io -functionality. It only wraps the portions of io functionality used -by SCons, in an interface that looks enough like io for our purposes. -""" - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -# Use the "imp" module to protect the imports below from fixers. -import imp - -_cStringIO = imp.load_module('cStringIO', *imp.find_module('cStringIO')) -StringIO = _cStringIO.StringIO -del _cStringIO - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From 861479b454d614af5a7739c5410117aabe01122f Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 19 Nov 2015 10:51:34 -0800 Subject: remove compat os.devnull. python 2.7 supports it --- src/engine/SCons/compat/__init__.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/engine/SCons/compat/__init__.py b/src/engine/SCons/compat/__init__.py index 68fb9e4..42c2eaa 100644 --- a/src/engine/SCons/compat/__init__.py +++ b/src/engine/SCons/compat/__init__.py @@ -103,17 +103,6 @@ except ImportError: # can fall back to using timestamp. pass - -try: - os.devnull -except AttributeError: - # Pre-2.4 Python has no os.devnull attribute - _names = sys.builtin_module_names - if 'posix' in _names: - os.devnull = '/dev/null' - elif 'nt' in _names: - os.devnull = 'nul' - os.path.devnull = os.devnull try: os.path.lexists except AttributeError: -- cgit v0.12 From 7715bd898ba997cdd61de2b7404889862601962e Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 19 Nov 2015 11:24:01 -0800 Subject: fix broken cleanup of collections removal from compat --- src/engine/SCons/compat/__init__.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/engine/SCons/compat/__init__.py b/src/engine/SCons/compat/__init__.py index 42c2eaa..249d008 100644 --- a/src/engine/SCons/compat/__init__.py +++ b/src/engine/SCons/compat/__init__.py @@ -146,6 +146,35 @@ except AttributeError: return x sys.intern = intern del intern + + +# Preparing for 3.x. UserDict, UserList, UserString are in +# collections for 3.x, but standalone in 2.7.x +import collections +try: + collections.UserDict +except AttributeError: + exec('from UserDict import UserDict as _UserDict') + collections.UserDict = _UserDict + del _UserDict + +try: + collections.UserList +except AttributeError: + exec('from UserList import UserList as _UserList') + collections.UserList = _UserList + del _UserList + +try: + collections.UserString +except AttributeError: + exec('from UserString import UserString as _UserString') + collections.UserString = _UserString + del _UserString + + + + try: sys.maxsize except AttributeError: -- cgit v0.12 From b828f5d4434615042e81c81051fe5dde3fe4304b Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 19 Nov 2015 11:28:01 -0800 Subject: remove sys.maxsize from compat module. 2.7 has it --- src/engine/SCons/compat/__init__.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/engine/SCons/compat/__init__.py b/src/engine/SCons/compat/__init__.py index 249d008..1bbc1e7 100644 --- a/src/engine/SCons/compat/__init__.py +++ b/src/engine/SCons/compat/__init__.py @@ -174,15 +174,6 @@ except AttributeError: - -try: - sys.maxsize -except AttributeError: - # Pre-2.6 Python has no sys.maxsize attribute - # Wrapping sys in () is silly, but protects it from 2to3 renames fixer - sys.maxsize = (sys).maxint - - if os.environ.get('SCONS_HORRIBLE_REGRESSION_TEST_HACK') is not None: # We can't apply the 'callable' fixer until the floor is 2.6, but the # '-3' option to Python 2.6 and 2.7 generates almost ten thousand -- cgit v0.12 From 2fea16ec321622be084cb511b001e57f7c1bf6d3 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 19 Nov 2015 11:29:45 -0800 Subject: remove os.path.lexists from compat module. 2.7 has it --- src/engine/SCons/compat/__init__.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/engine/SCons/compat/__init__.py b/src/engine/SCons/compat/__init__.py index 1bbc1e7..1ef2b25 100644 --- a/src/engine/SCons/compat/__init__.py +++ b/src/engine/SCons/compat/__init__.py @@ -103,13 +103,6 @@ except ImportError: # can fall back to using timestamp. pass -try: - os.path.lexists -except AttributeError: - # Pre-2.4 Python has no os.path.lexists function - def lexists(path): - return os.path.exists(path) or os.path.islink(path) - os.path.lexists = lexists # When we're using the '-3' option during regression tests, importing -- cgit v0.12 From 69d99ab6717f017e85da21b11e6898de18023616 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 19 Nov 2015 11:35:22 -0800 Subject: update logic for sys.intern in compat module. Don't need to support pre 2.7 anymore --- src/engine/SCons/compat/__init__.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/engine/SCons/compat/__init__.py b/src/engine/SCons/compat/__init__.py index 1ef2b25..3d5c835 100644 --- a/src/engine/SCons/compat/__init__.py +++ b/src/engine/SCons/compat/__init__.py @@ -126,19 +126,17 @@ rename_module('queue', 'Queue') rename_module('winreg', '_winreg') +# Python 3 moved builtin intern() to sys package +# To make porting easier, make intern always live +# in sys package (for python 2.7.x) try: sys.intern except AttributeError: - # Pre-2.6 Python has no sys.intern() function. + # We must be using python 2.7.x so monkey patch + # intern into the sys package import builtins - try: - sys.intern = builtins.intern - except AttributeError: - # Pre-2.x Python has no builtin intern() function. - def intern(x): - return x - sys.intern = intern - del intern + sys.intern = builtins.intern + # Preparing for 3.x. UserDict, UserList, UserString are in -- cgit v0.12 From abf1f461c7d34a00fd2a7348c3d91f10bf382c43 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 20 Nov 2015 13:54:09 -0800 Subject: fix bootstrap.py issue where changes weren't updating bootstrap dir. filecmp.cmp(a,b) returns False when files aren't equal. The opposite of the expected return value --- bootstrap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap.py b/bootstrap.py index 90917dc..08df11d 100755 --- a/bootstrap.py +++ b/bootstrap.py @@ -129,7 +129,7 @@ def main(): def must_copy(dst, src): if not os.path.exists(dst): return 1 - return filecmp.cmp(dst,src) + return not filecmp.cmp(dst,src) # Note: We don't use the getopt module to process the command-line # arguments because we'd have to teach it about all of the SCons options. -- cgit v0.12 From 6d8c18bc0b10a41d64296d42214e92e338a9270b Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 24 Nov 2015 09:26:03 -0800 Subject: Fix warning message when running SCons with a python built without sha256 or other required hashlib. Previously it would say no module SCons.Warnings. I can't find an effective way to test for this. --- src/engine/SCons/CacheDir.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/engine/SCons/CacheDir.py b/src/engine/SCons/CacheDir.py index f32b326..3b7d06f 100644 --- a/src/engine/SCons/CacheDir.py +++ b/src/engine/SCons/CacheDir.py @@ -32,6 +32,7 @@ import stat import sys import SCons.Action +import SCons.Warnings cache_enabled = True cache_debug = False -- cgit v0.12 From 647154f4cc4c3a515927de11229a95d666d8b4d6 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 24 Nov 2015 09:45:52 -0800 Subject: remove logic to get revision from subversion. Long since obsoleted for SCons development --- SConstruct | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/SConstruct b/SConstruct index 3bbaca6..6ad6dd9 100644 --- a/SConstruct +++ b/SConstruct @@ -88,7 +88,6 @@ fakeroot = whereis('fakeroot') gzip = whereis('gzip') rpmbuild = whereis('rpmbuild') hg = os.path.exists('.hg') and whereis('hg') -svn = os.path.exists('.svn') and whereis('svn') unzip = whereis('unzip') zip = whereis('zip') @@ -117,16 +116,11 @@ if not version: version = default_version hg_status_lines = [] -svn_status_lines = [] if hg: cmd = "%s status --all 2> /dev/null" % hg hg_status_lines = os.popen(cmd, "r").readlines() -if svn: - cmd = "%s status --verbose 2> /dev/null" % svn - svn_status_lines = os.popen(cmd, "r").readlines() - revision = ARGUMENTS.get('REVISION', '') def generate_build_id(revision): return revision @@ -145,17 +139,6 @@ if not revision and hg: result = result + '[MODIFIED]' return result -if not revision and svn: - svn_info = os.popen("%s info 2> /dev/null" % svn, "r").read() - m = re.search('Revision: (\d+)', svn_info) - if m: - revision = m.group(1) - def generate_build_id(revision): - result = 'r' + revision - if [l for l in svn_status_lines if l[0] in 'ACDMR']: - result = result + '[MODIFIED]' - return result - checkpoint = ARGUMENTS.get('CHECKPOINT', '') if checkpoint: if checkpoint == 'd': @@ -236,7 +219,7 @@ command_line_variables = [ ("REVISION=", "The revision number of the source being built. " + "The default is the Subversion revision returned " + - "'svn info', with an appended string of " + + "'hg heads', with an appended string of " + "'[MODIFIED]' if there are any changes in the " + "working copy."), @@ -1234,12 +1217,8 @@ sfiles = None if hg_status_lines: slines = [l for l in hg_status_lines if l[0] in 'ACM'] sfiles = [l.split()[-1] for l in slines] -elif svn_status_lines: - slines = [l for l in svn_status_lines if l[0] in ' MA'] - sentries = [l.split()[-1] for l in slines] - sfiles = list(filter(os.path.isfile, sentries)) else: - print "Not building in a Mercurial or Subversion tree; skipping building src package." + print "Not building in a Mercurial tree; skipping building src package." if sfiles: remove_patterns = [ -- cgit v0.12 From e7de9d22c9503cf29e5d8b5e7813f060d59a00e5 Mon Sep 17 00:00:00 2001 From: Dirk Baechle Date: Thu, 10 Dec 2015 18:01:37 +0100 Subject: removed several pre-2.7 methods and imports, including some basic refactorings --- QMTest/TestCmd.py | 14 --- QMTest/TestCommon.py | 25 ----- ReleaseConfig | 2 +- bin/scons-proc.py | 6 +- runtest.py | 15 +-- src/engine/SCons/Action.py | 13 +-- src/engine/SCons/ActionTests.py | 81 ----------------- src/engine/SCons/Environment.py | 19 ---- src/engine/SCons/EnvironmentTests.py | 25 ----- src/engine/SCons/Executor.py | 3 - src/engine/SCons/Job.py | 10 +- src/engine/SCons/Node/FS.py | 53 +---------- src/engine/SCons/Node/FSTests.py | 10 -- src/engine/SCons/Node/NodeTests.py | 2 - src/engine/SCons/Node/__init__.py | 7 +- src/engine/SCons/PathList.py | 2 +- src/engine/SCons/Platform/__init__.py | 2 +- src/engine/SCons/Platform/win32.py | 10 +- src/engine/SCons/SConf.py | 19 +--- src/engine/SCons/SConfTests.py | 5 +- src/engine/SCons/Scanner/C.py | 2 +- src/engine/SCons/Scanner/IDL.py | 2 +- src/engine/SCons/Scanner/RC.py | 2 +- src/engine/SCons/Script/Interactive.py | 6 -- src/engine/SCons/Script/Main.py | 42 ++------- src/engine/SCons/Script/SConsOptions.py | 52 +---------- src/engine/SCons/Script/SConscript.py | 12 +-- src/engine/SCons/Script/__init__.py | 6 -- src/engine/SCons/Subst.py | 9 -- src/engine/SCons/SubstTests.py | 11 --- src/engine/SCons/Taskmaster.py | 12 +-- src/engine/SCons/Tool/BitKeeper.py | 1 - src/engine/SCons/Tool/CVS.py | 1 - src/engine/SCons/Tool/GettextCommon.py | 4 +- src/engine/SCons/Tool/MSCommon/common.py | 31 +------ src/engine/SCons/Tool/MSCommon/netframework.py | 3 +- src/engine/SCons/Tool/MSCommon/sdk.py | 30 +----- src/engine/SCons/Tool/MSCommon/vc.py | 4 +- src/engine/SCons/Tool/MSCommon/vs.py | 8 +- src/engine/SCons/Tool/Perforce.py | 6 +- src/engine/SCons/Tool/PharLapCommon.py | 38 ++------ src/engine/SCons/Tool/PharLapCommonTests.py | 69 -------------- src/engine/SCons/Tool/RCS.py | 1 - src/engine/SCons/Tool/SCCS.py | 1 - src/engine/SCons/Tool/Subversion.py | 1 - src/engine/SCons/Tool/__init__.py | 2 +- src/engine/SCons/Tool/aixf77.py | 2 +- src/engine/SCons/Tool/cyglink.py | 2 +- src/engine/SCons/Tool/docbook/__init__.py | 36 +++----- src/engine/SCons/Tool/gnulink.py | 2 +- src/engine/SCons/Tool/icl.py | 2 +- src/engine/SCons/Tool/install.py | 16 ++-- src/engine/SCons/Tool/intelc.py | 17 +--- src/engine/SCons/Tool/mslink.py | 2 +- src/engine/SCons/Tool/msvs.py | 44 +-------- src/engine/SCons/Tool/packaging/__init__.py | 7 +- src/engine/SCons/Tool/packaging/ipk.py | 8 +- src/engine/SCons/Tool/packaging/msi.py | 16 ++-- src/engine/SCons/Tool/packaging/rpm.py | 20 +--- src/engine/SCons/Tool/sunar.py | 2 +- src/engine/SCons/Tool/tex.py | 6 -- src/engine/SCons/Tool/textfile.py | 4 +- src/engine/SCons/Tool/xgettext.py | 6 +- src/engine/SCons/Tool/yacc.py | 10 +- src/engine/SCons/Util.py | 116 +++++++++++++++--------- src/engine/SCons/UtilTests.py | 43 ++++++--- src/engine/SCons/Variables/BoolVariable.py | 4 +- src/engine/SCons/Variables/EnumVariable.py | 4 +- src/engine/SCons/Variables/ListVariable.py | 8 +- src/engine/SCons/Variables/PackageVariable.py | 10 +- src/engine/SCons/Variables/PathVariable.py | 9 +- src/engine/SCons/Variables/__init__.py | 7 +- src/engine/SCons/compat/__init__.py | 56 +----------- src/engine/SCons/compat/_scons_builtins.py | 107 ---------------------- src/engine/SCons/compat/_scons_hashlib.py | 76 ---------------- src/engine/SCons/cppTests.py | 3 - src/engine/SCons/dblite.py | 8 +- src/script/scons-time.py | 45 +-------- src/script/sconsign.py | 35 ++++++- test/TEX/bibliography.py | 3 - test/compat/all.py | 65 ------------- test/compat/any.py | 63 ------------- test/option/profile.py | 21 ++--- test/sconsign/script/bad.py | 6 +- test/update-release-info/update-release-info.py | 12 +-- 85 files changed, 306 insertions(+), 1276 deletions(-) delete mode 100644 src/engine/SCons/Tool/PharLapCommonTests.py delete mode 100644 src/engine/SCons/compat/_scons_builtins.py delete mode 100644 src/engine/SCons/compat/_scons_hashlib.py delete mode 100644 test/compat/all.py delete mode 100644 test/compat/any.py diff --git a/QMTest/TestCmd.py b/QMTest/TestCmd.py index 3048973..cd559b7 100644 --- a/QMTest/TestCmd.py +++ b/QMTest/TestCmd.py @@ -317,20 +317,6 @@ except ImportError: exec('from UserList import UserList') exec('from UserString import UserString') -try: - # pre-2.7 doesn't have the memoryview() built-in - memoryview -except NameError: - class memoryview: - def __init__(self, obj): - # wrapping buffer in () keeps the fixer from changing it - self.obj = (buffer)(obj) - def __getitem__(self, indx): - if isinstance(indx, slice): - return self.obj[indx.start:indx.stop] - else: - return self.obj[indx] - __all__ = [ 'diff_re', 'fail_test', diff --git a/QMTest/TestCommon.py b/QMTest/TestCommon.py index c4a5373..dc4c97c 100644 --- a/QMTest/TestCommon.py +++ b/QMTest/TestCommon.py @@ -123,31 +123,6 @@ __all__.extend([ 'TestCommon', 'dll_suffix', ]) -try: - sorted -except NameError: - # Pre-2.4 Python has no sorted() function. - # - # The pre-2.4 Python list.sort() method does not support - # list.sort(key=) nor list.sort(reverse=) keyword arguments, so - # we must implement the functionality of those keyword arguments - # by hand instead of passing them to list.sort(). - def sorted(iterable, cmp=None, key=None, reverse=False): - if key is not None: - result = [(key(x), x) for x in iterable] - else: - result = iterable[:] - if cmp is None: - # Pre-2.3 Python does not support list.sort(None). - result.sort() - else: - result.sort(cmp) - if key is not None: - result = [t1 for t0,t1 in result] - if reverse: - result.reverse() - return result - # Variables that describe the prefixes and suffixes on this system. if sys.platform == 'win32': exe_suffix = '.exe' diff --git a/ReleaseConfig b/ReleaseConfig index ced44c6..e1f462a 100644 --- a/ReleaseConfig +++ b/ReleaseConfig @@ -38,7 +38,7 @@ version_tuple = (2, 4, 2, 'alpha', 0) # when that version is used. Python versions prior to deprecate_python_version # cause a warning to be issued (assuming it's not disabled). These values are # mandatory and must be present in the configuration file. -unsupported_python_version = (2, 3, 0) +unsupported_python_version = (2, 6, 0) deprecated_python_version = (2, 7, 0) # If release_date is (yyyy, mm, dd, hh, mm, ss), that is used as the release diff --git a/bin/scons-proc.py b/bin/scons-proc.py index 9567db8..d6a770b 100644 --- a/bin/scons-proc.py +++ b/bin/scons-proc.py @@ -14,11 +14,7 @@ import os import re import string import sys -try: - from io import StringIO # usable as of 2.6; takes unicode only -except ImportError: - # No 'io' module or no StringIO in io - exec('from cStringIO import StringIO') +from io import StringIO # usable as of 2.6; takes unicode only import SConsDoc from SConsDoc import tf as stf diff --git a/runtest.py b/runtest.py index b7cbdc6..1b5c7dd 100755 --- a/runtest.py +++ b/runtest.py @@ -17,8 +17,6 @@ # build directory and sets PYTHONPATH to reference modules unpacked # during build process for testing purposes (build/test-*). # -# -3 Run with the python -3 option, -# # -a Run all tests found under the current directory. # It is also possible to specify a list of # subdirectories to search. @@ -108,7 +106,6 @@ list_only = None printcommand = 1 package = None print_passed_summary = None -python3incompatibilities = None scons = None scons_exec = None testlistfile = None @@ -128,7 +125,6 @@ Usage: runtest.py [OPTIONS] [TEST ...] """ helpstr = usagestr + """\ Options: - -3 Warn about Python 3.x incompatibilities. -a --all Run all tests. -b --baseline BASE Run test scripts against baseline BASE. --builddir DIR Directory in which packages were built. @@ -210,7 +206,7 @@ parser.add_option('--xml', #print "args:", args -opts, args = getopt.getopt(args, "3b:def:hj:klnP:p:qsv:Xx:t", +opts, args = getopt.getopt(args, "b:def:hj:klnP:p:qsv:Xx:t", ['baseline=', 'builddir=', 'debug', 'external', 'file=', 'help', 'no-progress', 'jobs=', @@ -223,9 +219,7 @@ opts, args = getopt.getopt(args, "3b:def:hj:klnP:p:qsv:Xx:t", 'verbose=']) for o, a in opts: - if o in ['-3']: - python3incompatibilities = 1 - elif o in ['-b', '--baseline']: + if o in ['-b', '--baseline']: baseline = a elif o in ['--builddir']: builddir = a @@ -634,9 +628,6 @@ if old_pythonpath: os.pathsep + \ old_pythonpath -if python3incompatibilities: - os.environ['SCONS_HORRIBLE_REGRESSION_TEST_HACK'] = '1' - # ---[ test discovery ]------------------------------------ @@ -769,8 +760,6 @@ def run_test(t, io_lock, async=True): global tests_completed header = "" command_args = ['-tt'] - if python3incompatibilities: - command_args.append('-3') if debug: command_args.append(debug) command_args.append(t.path) diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index 5a34825..4dfde31 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -235,11 +235,7 @@ def _code_contents(code): # The code contents depends on the number of local variables # but not their actual names. contents.append("%s,%s" % (code.co_argcount, len(code.co_varnames))) - try: - contents.append(",%s,%s" % (len(code.co_cellvars), len(code.co_freevars))) - except AttributeError: - # Older versions of Python do not support closures. - contents.append(",0,0") + contents.append(",%s,%s" % (len(code.co_cellvars), len(code.co_freevars))) # The code contents depends on any constants accessed by the # function. Note that we have to call _object_contents on each @@ -276,11 +272,7 @@ def _function_contents(func): contents.append(',()') # The function contents depends on the closure captured cell values. - try: - closure = func.func_closure or [] - except AttributeError: - # Older versions of Python do not support closures. - closure = [] + closure = func.func_closure or [] #xxx = [_object_contents(x.cell_contents) for x in closure] try: @@ -946,7 +938,6 @@ class LazyAction(CommandGeneratorAction, CommandAction): def __init__(self, var, kw): if SCons.Debug.track_instances: logInstanceCreation(self, 'Action.LazyAction') - #FUTURE CommandAction.__init__(self, '${'+var+'}', **kw) CommandAction.__init__(self, '${'+var+'}', **kw) self.var = SCons.Util.to_String(var) self.gen_kw = kw diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py index e069d51..631d7c1 100644 --- a/src/engine/SCons/ActionTests.py +++ b/src/engine/SCons/ActionTests.py @@ -229,7 +229,6 @@ def test_varlist(pos_call, str_call, cmd, cmdstrfunc, **kw): def test_positional_args(pos_callback, cmd, **kw): """Test that Action() returns the expected type and that positional args work. """ - #FUTURE act = SCons.Action.Action(cmd, **kw) act = SCons.Action.Action(cmd, **kw) pos_callback(act) assert act.varlist is (), act.varlist @@ -237,7 +236,6 @@ def test_positional_args(pos_callback, cmd, **kw): if not isinstance(act, SCons.Action._ActionAction): # only valid cmdstrfunc is None def none(a): pass - #FUTURE test_varlist(pos_callback, none, cmd, None, **kw) test_varlist(pos_callback, none, cmd, None, **kw) else: # _ActionAction should have set these @@ -251,25 +249,21 @@ def test_positional_args(pos_callback, cmd, **kw): def cmdstr(a): assert hasattr(a, 'strfunction') assert a.cmdstr == 'cmdstr', a.cmdstr - #FUTURE test_varlist(pos_callback, cmdstr, cmd, 'cmdstr', **kw) test_varlist(pos_callback, cmdstr, cmd, 'cmdstr', **kw) def fun(): pass def strfun(a, fun=fun): assert a.strfunction is fun, a.strfunction assert a.cmdstr == _null, a.cmdstr - #FUTURE test_varlist(pos_callback, strfun, cmd, fun, **kw) test_varlist(pos_callback, strfun, cmd, fun, **kw) def none(a): assert hasattr(a, 'strfunction') assert a.cmdstr is None, a.cmdstr - #FUTURE test_varlist(pos_callback, none, cmd, None, **kw) test_varlist(pos_callback, none, cmd, None, **kw) """Test handling of bad cmdstrfunc arguments """ try: - #FUTURE a = SCons.Action.Action(cmd, [], **kw) a = SCons.Action.Action(cmd, [], **kw) except SCons.Errors.UserError, e: s = str(e) @@ -1193,81 +1187,6 @@ class CommandActionTestCase(unittest.TestCase): r = act([], [], env) assert r == 0, r - def _DO_NOT_EXECUTE_test_pipe_execute(self): - """Test capturing piped output from an action - - We used to have PIPE_BUILD support built right into - Action.execute() for the benefit of the SConf subsystem, but we've - moved that logic back into SConf itself. We'll leave this code - here, just in case we ever want to resurrect this functionality - in the future, but change the name of the test so it doesn't - get executed as part of the normal test suite. - """ - pipe = open( pipe_file, "w" ) - self.env = Environment(ENV = {'ACTPY_PIPE' : '1'}, PIPE_BUILD = 1, - PSTDOUT = pipe, PSTDERR = pipe) - # everything should also work when piping output - self.test_execute() - self.env['PSTDOUT'].close() - pipe_out = test.read( pipe_file ) - - act_out = "act.py: stdout: executed act.py" - act_err = "act.py: stderr: executed act.py" - - # Since we are now using select(), stdout and stderr can be - # intermixed, so count the lines separately. - outlines = re.findall(act_out, pipe_out) - errlines = re.findall(act_err, pipe_out) - assert len(outlines) == 6, pipe_out + repr(outlines) - assert len(errlines) == 6, pipe_out + repr(errlines) - - # test redirection operators - def test_redirect(self, redir, stdout_msg, stderr_msg): - cmd = r'%s %s %s xyzzy %s' % (_python_, act_py, outfile, redir) - # Write the output and error messages to files because - # Windows can't handle strings that are too big in its - # external environment (os.spawnve() returns EINVAL, - # "Invalid argument"). - stdout_file = test.workpath('stdout_msg') - stderr_file = test.workpath('stderr_msg') - open(stdout_file, 'w').write(stdout_msg) - open(stderr_file, 'w').write(stderr_msg) - pipe = open( pipe_file, "w" ) - act = SCons.Action.CommandAction(cmd) - env = Environment( ENV = {'ACTPY_PIPE' : '1', - 'PIPE_STDOUT_FILE' : stdout_file, - 'PIPE_STDERR_FILE' : stderr_file}, - PIPE_BUILD = 1, - PSTDOUT = pipe, PSTDERR = pipe ) - r = act([], [], env) - pipe.close() - assert r == 0 - return (test.read(outfile2, 'r'), test.read(pipe_file, 'r')) - - (redirected, pipe_out) = test_redirect(self,'> %s' % outfile2, - act_out, act_err) - assert redirected == act_out - assert pipe_out == act_err - - (redirected, pipe_out) = test_redirect(self,'2> %s' % outfile2, - act_out, act_err) - assert redirected == act_err - assert pipe_out == act_out - - (redirected, pipe_out) = test_redirect(self,'> %s 2>&1' % outfile2, - act_out, act_err) - assert (redirected == act_out + act_err or - redirected == act_err + act_out) - assert pipe_out == "" - - act_err = "Long Command Output\n"*3000 - # the size of the string should exceed the system's default block size - act_out = "" - (redirected, pipe_out) = test_redirect(self,'> %s' % outfile2, - act_out, act_err) - assert (redirected == act_out) - assert (pipe_out == act_err) - def test_set_handler(self): """Test setting the command handler... """ diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 7e2f896..45b24c5 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -857,25 +857,6 @@ class SubstitutionEnvironment(object): self[key] = t return self -# def MergeShellPaths(self, args, prepend=1): -# """ -# Merge the dict in args into the shell environment in env['ENV']. -# Shell path elements are appended or prepended according to prepend. - -# Uses Pre/AppendENVPath, so it always appends or prepends uniquely. - -# Example: env.MergeShellPaths({'LIBPATH': '/usr/local/lib'}) -# prepends /usr/local/lib to env['ENV']['LIBPATH']. -# """ - -# for pathname, pathval in args.items(): -# if not pathval: -# continue -# if prepend: -# self.PrependENVPath(pathname, pathval) -# else: -# self.AppendENVPath(pathname, pathval) - def default_decide_source(dependency, target, prev_ni): f = SCons.Defaults.DefaultEnvironment().decide_source diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index 9a9d2b0..0567906 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -862,31 +862,6 @@ sys.exit(0) assert env['A'] == ['aaa'], env['A'] assert env['B'] == ['bbb'], env['B'] -# def test_MergeShellPaths(self): -# """Test the MergeShellPaths() method -# """ -# env = Environment() -# env.MergeShellPaths({}) -# assert not env['ENV'].has_key('INCLUDE'), env['INCLUDE'] -# env.MergeShellPaths({'INCLUDE': r'c:\Program Files\Stuff'}) -# assert env['ENV']['INCLUDE'] == r'c:\Program Files\Stuff', env['ENV']['INCLUDE'] -# env.MergeShellPaths({'INCLUDE': r'c:\Program Files\Stuff'}) -# assert env['ENV']['INCLUDE'] == r'c:\Program Files\Stuff', env['ENV']['INCLUDE'] -# env.MergeShellPaths({'INCLUDE': r'xyz'}) -# assert env['ENV']['INCLUDE'] == r'xyz%sc:\Program Files\Stuff'%os.pathsep, env['ENV']['INCLUDE'] - -# env = Environment() -# env['ENV']['INCLUDE'] = 'xyz' -# env.MergeShellPaths({'INCLUDE':['c:/inc1', 'c:/inc2']} ) -# assert env['ENV']['INCLUDE'] == r'c:/inc1%sc:/inc2%sxyz'%(os.pathsep, os.pathsep), env['ENV']['INCLUDE'] - -# # test prepend=0 -# env = Environment() -# env.MergeShellPaths({'INCLUDE': r'c:\Program Files\Stuff'}, prepend=0) -# assert env['ENV']['INCLUDE'] == r'c:\Program Files\Stuff', env['ENV']['INCLUDE'] -# env.MergeShellPaths({'INCLUDE': r'xyz'}, prepend=0) -# assert env['ENV']['INCLUDE'] == r'c:\Program Files\Stuff%sxyz'%os.pathsep, env['ENV']['INCLUDE'] - class BaseTestCase(unittest.TestCase,TestEnvironmentFixture): diff --git a/src/engine/SCons/Executor.py b/src/engine/SCons/Executor.py index 59e57e3..71671bf 100644 --- a/src/engine/SCons/Executor.py +++ b/src/engine/SCons/Executor.py @@ -122,7 +122,6 @@ def execute_action_list(obj, target, kw): kw = obj.get_kw(kw) status = 0 for act in obj.get_action_list(): - #args = (self.get_all_targets(), self.get_all_sources(), env) args = ([], [], env) status = act(*args, **kw) if isinstance(status, SCons.Errors.BuildError): @@ -244,14 +243,12 @@ class Executor(object): return self._changed_targets_list def _get_source(self, *args, **kw): - #return SCons.Util.NodeList([rfile(self.batches[0].sources[0]).get_subst_proxy()]) return rfile(self.batches[0].sources[0]).get_subst_proxy() def _get_sources(self, *args, **kw): return SCons.Util.NodeList([rfile(n).get_subst_proxy() for n in self.get_all_sources()]) def _get_target(self, *args, **kw): - #return SCons.Util.NodeList([self.batches[0].targets[0].get_subst_proxy()]) return self.batches[0].targets[0].get_subst_proxy() def _get_targets(self, *args, **kw): diff --git a/src/engine/SCons/Job.py b/src/engine/SCons/Job.py index 184f5ba..42b009e 100644 --- a/src/engine/SCons/Job.py +++ b/src/engine/SCons/Job.py @@ -70,7 +70,7 @@ class Jobs(object): def __init__(self, num, taskmaster): """ - create 'num' jobs using the given taskmaster. + Create 'num' jobs using the given taskmaster. If 'num' is 1 or less, then a serial job will be used, otherwise a parallel job with 'num' worker threads will @@ -126,10 +126,10 @@ class Jobs(object): c) SIGHUP: Controlling shell exiting We handle all of these cases by stopping the taskmaster. It - turns out that it very difficult to stop the build process + turns out that it's very difficult to stop the build process by throwing asynchronously an exception such as KeyboardInterrupt. For example, the python Condition - variables (threading.Condition) and queue's do not seem to + variables (threading.Condition) and queues do not seem to be asynchronous-exception-safe. It would require adding a whole bunch of try/finally block and except KeyboardInterrupt all over the place. @@ -177,7 +177,7 @@ class Serial(object): The taskmaster's next_task() method should return the next task that needs to be executed, or None if there are no more tasks. The taskmaster's executed() method will be called for each task when it - is successfully executed or failed() will be called if it failed to + is successfully executed, or failed() will be called if it failed to execute (e.g. execute() raised an exception).""" self.taskmaster = taskmaster @@ -351,7 +351,7 @@ else: The taskmaster's next_task() method should return the next task that needs to be executed, or None if there are no more tasks. The taskmaster's executed() method will be called - for each task when it is successfully executed or failed() + for each task when it is successfully executed, or failed() will be called if the task failed to execute (i.e. execute() raised an exception). diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 4e78852..4a4942b 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -186,7 +186,7 @@ needs_normpath_check = re.compile( # We need to renormalize the path if it contains a '.' # directory, but NOT if it is a single '.' '/' characters. We # do not want to match a single '.' because this case is checked - # for explicitely since this is common enough case. + # for explicitly since this is common enough case. # # Note that we check for all the following cases: # @@ -1165,15 +1165,6 @@ class LocalFS(object): return '' -#class RemoteFS: -# # Skeleton for the obvious methods we might need from the -# # abstraction layer for a remote filesystem. -# def upload(self, local_src, remote_dst): -# pass -# def download(self, remote_src, local_dst): -# pass - - class FS(LocalFS): def __init__(self, path = None): @@ -2234,7 +2225,6 @@ class Dir(Base): # the overall list will also be filtered later, # after we exit this loop. if pattern[0] != '.': - #disk_names = [ d for d in disk_names if d[0] != '.' ] disk_names = [x for x in disk_names if x[0] != '.'] disk_names = fnmatch.filter(disk_names, pattern) dirEntry = dir.Entry @@ -2627,13 +2617,6 @@ class File(Base): the directory of this file.""" return self.dir.File(name) - #def generate_build_dict(self): - # """Return an appropriate dictionary of values for building - # this File.""" - # return {'Dir' : self.Dir, - # 'File' : self.File, - # 'RDirs' : self.RDirs} - def _morph(self): """Turn a file system node into a File object.""" self.scanner_paths = {} @@ -2907,9 +2890,7 @@ class File(Base): pass if scanner: - # result = [n.disambiguate() for n in scanner(self, env, path)] - result = scanner(self, env, path) - result = [N.disambiguate() for N in result] + result = [n.disambiguate() for n in scanner(self, env, path)] else: result = [] @@ -3519,36 +3500,6 @@ class FileFinder(object): filedir, filename = os.path.split(filename) if filedir: - # More compact code that we can't use until we drop - # support for Python 1.5.2: - # - #def filedir_lookup(p, fd=filedir): - # """ - # A helper function that looks up a directory for a file - # we're trying to find. This only creates the Dir Node - # if it exists on-disk, since if the directory doesn't - # exist we know we won't find any files in it... :-) - # """ - # dir, name = os.path.split(fd) - # if dir: - # p = filedir_lookup(p, dir) - # if not p: - # return None - # norm_name = _my_normcase(name) - # try: - # node = p.entries[norm_name] - # except KeyError: - # return p.dir_on_disk(name) - # if isinstance(node, Dir): - # return node - # if isinstance(node, Entry): - # node.must_be_same(Dir) - # return node - # if isinstance(node, Dir) or isinstance(node, Entry): - # return node - # return None - #paths = [_f for _f in map(filedir_lookup, paths) if _f] - self.default_filedir = filedir paths = [_f for _f in map(self.filedir_lookup, paths) if _f] diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 0c1e71f..fc27859 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -751,16 +751,6 @@ class FileNodeInfoTestCase(_tempdirTestCase): size = st[stat.ST_SIZE] assert ni.size != size, (ni.size, size) - #fff.clear() - #ni.update(fff) - - #st = os.stat('fff') - - #mtime = st[stat.ST_MTIME] - #assert ni.timestamp == mtime, (ni.timestamp, mtime) - #size = st[stat.ST_SIZE] - #assert ni.size == size, (ni.size, size) - class FileBuildInfoTestCase(_tempdirTestCase): def test___init__(self): """Test File.BuildInfo initialization""" diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index 1478419..3802f8c 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -358,8 +358,6 @@ class NodeTestCase(unittest.TestCase): ggg.path = "ggg" fff.sources = ["hhh", "iii"] ggg.sources = ["hhh", "iii"] - # [Charles C. 1/7/2002] Uhhh, why are there no asserts here? - # [SK, 15 May 2003] I dunno, let's add some... built_it = None fff.build() assert built_it diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 5aa9600..40ee8f0 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -577,7 +577,7 @@ class Node(object): self.always_build = None self.includes = None self.attributes = self.Attrs() # Generic place to stick information about the Node. - self.side_effect = 0 # true iff this node is a side effect + self.side_effect = 0 # true if this node is a side effect self.side_effects = [] # the side effects of building this target self.linked = 0 # is this node linked to the variant directory? self.changed_since_last_build = 0 @@ -1281,11 +1281,6 @@ class Node(object): def _add_child(self, collection, set, child): """Adds 'child' to 'collection', first checking 'set' to see if it's already present.""" - #if type(child) is not type([]): - # child = [child] - #for c in child: - # if not isinstance(c, Node): - # raise TypeError, c added = None for c in child: if c not in set: diff --git a/src/engine/SCons/PathList.py b/src/engine/SCons/PathList.py index 350e1ac..77e30c4 100644 --- a/src/engine/SCons/PathList.py +++ b/src/engine/SCons/PathList.py @@ -27,7 +27,7 @@ __doc__ = """SCons.PathList A module for handling lists of directory paths (the sort of things that get set as CPPPATH, LIBPATH, etc.) with as much caching of data and -efficiency as we can while still keeping the evaluation delayed so that we +efficiency as we can, while still keeping the evaluation delayed so that we Do the Right Thing (almost) regardless of how the variable is specified. """ diff --git a/src/engine/SCons/Platform/__init__.py b/src/engine/SCons/Platform/__init__.py index 653f722..7f3e90b 100644 --- a/src/engine/SCons/Platform/__init__.py +++ b/src/engine/SCons/Platform/__init__.py @@ -12,7 +12,7 @@ environment. Consequently, we'll examine both sys.platform and os.name (and anything else that might come in to play) in order to return some specification which is unique enough for our purposes. -Note that because this subsysem just *selects* a callable that can +Note that because this subsystem just *selects* a callable that can modify a construction environment, it's possible for people to define their own "platform specification" in an arbitrary callable function. No one needs to use or tie in to this subsystem in order to roll diff --git a/src/engine/SCons/Platform/win32.py b/src/engine/SCons/Platform/win32.py index 5f20685..4cfabea 100644 --- a/src/engine/SCons/Platform/win32.py +++ b/src/engine/SCons/Platform/win32.py @@ -60,10 +60,8 @@ except AttributeError: else: parallel_msg = None - import builtins - - _builtin_file = builtins.file - _builtin_open = builtins.open + _builtin_file = file + _builtin_open = open class _scons_file(_builtin_file): def __init__(self, *args, **kw): @@ -78,8 +76,8 @@ else: 0) return fp - builtins.file = _scons_file - builtins.open = _scons_open + file = _scons_file + open = _scons_open try: import threading diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index 987b8ea..286f230 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -254,14 +254,7 @@ class SConfBuildTask(SCons.Taskmaster.AlwaysTask): else: self.display('Caught exception while building "%s":\n' % self.targets[0]) - try: - excepthook = sys.excepthook - except AttributeError: - # Earlier versions of Python don't have sys.excepthook... - def excepthook(type, value, tb): - traceback.print_tb(tb) - print type, value - excepthook(*self.exc_info()) + sys.excepthook(*self.exc_info()) return SCons.Taskmaster.Task.failed(self) def collect_node_states(self): @@ -355,8 +348,6 @@ class SConfBuildTask(SCons.Taskmaster.AlwaysTask): raise SCons.Errors.ExplicitExit(self.targets[0],exc_value.code) except Exception, e: for t in self.targets: - #binfo = t.get_binfo() - #binfo.__class__ = SConfBuildInfo binfo = SConfBuildInfo() binfo.merge(t.get_binfo()) binfo.set_build_result(1, s.getvalue()) @@ -375,8 +366,6 @@ class SConfBuildTask(SCons.Taskmaster.AlwaysTask): raise e else: for t in self.targets: - #binfo = t.get_binfo() - #binfo.__class__ = SConfBuildInfo binfo = SConfBuildInfo() binfo.merge(t.get_binfo()) binfo.set_build_result(0, s.getvalue()) @@ -399,16 +388,16 @@ class SConfBase(object): tests, be sure to call the Finish() method, which returns the modified environment. Some words about caching: In most cases, it is not necessary to cache - Test results explicitely. Instead, we use the scons dependency checking + Test results explicitly. Instead, we use the scons dependency checking mechanism. For example, if one wants to compile a test program (SConf.TryLink), the compiler is only called, if the program dependencies have changed. However, if the program could not be compiled in a former - SConf run, we need to explicitely cache this error. + SConf run, we need to explicitly cache this error. """ def __init__(self, env, custom_tests = {}, conf_dir='$CONFIGUREDIR', log_file='$CONFIGURELOG', config_h = None, _depth = 0): - """Constructor. Pass additional tests in the custom_tests-dictinary, + """Constructor. Pass additional tests in the custom_tests-dictionary, e.g. custom_tests={'CheckPrivate':MyPrivateTest}, where MyPrivateTest defines a custom test. Note also the conf_dir and log_file arguments (you may want to diff --git a/src/engine/SCons/SConfTests.py b/src/engine/SCons/SConfTests.py index 9bdfceb..f9ee0d0 100644 --- a/src/engine/SCons/SConfTests.py +++ b/src/engine/SCons/SConfTests.py @@ -100,11 +100,10 @@ class SConfTestCase(unittest.TestCase): # original builtin functions whenever we have to reset # all of our global state. - import builtins import SCons.Platform.win32 - builtins.file = SCons.Platform.win32._builtin_file - builtins.open = SCons.Platform.win32._builtin_open + file = SCons.Platform.win32._builtin_file + open = SCons.Platform.win32._builtin_open def _baseTryXXX(self, TryFunc): # TryCompile and TryLink are much the same, so we can test them diff --git a/src/engine/SCons/Scanner/C.py b/src/engine/SCons/Scanner/C.py index 3311a09..e6ac720 100644 --- a/src/engine/SCons/Scanner/C.py +++ b/src/engine/SCons/Scanner/C.py @@ -1,6 +1,6 @@ """SCons.Scanner.C -This module implements the depenency scanner for C/C++ code. +This module implements the dependency scanner for C/C++ code. """ diff --git a/src/engine/SCons/Scanner/IDL.py b/src/engine/SCons/Scanner/IDL.py index 18084e8..86ee006 100644 --- a/src/engine/SCons/Scanner/IDL.py +++ b/src/engine/SCons/Scanner/IDL.py @@ -1,6 +1,6 @@ """SCons.Scanner.IDL -This module implements the depenency scanner for IDL (Interface +This module implements the dependency scanner for IDL (Interface Definition Language) files. """ diff --git a/src/engine/SCons/Scanner/RC.py b/src/engine/SCons/Scanner/RC.py index 437b861..61393ae 100644 --- a/src/engine/SCons/Scanner/RC.py +++ b/src/engine/SCons/Scanner/RC.py @@ -1,6 +1,6 @@ """SCons.Scanner.RC -This module implements the depenency scanner for RC (Interface +This module implements the dependency scanner for RC (Interface Definition Language) files. """ diff --git a/src/engine/SCons/Script/Interactive.py b/src/engine/SCons/Script/Interactive.py index ffb5096..5450ff5 100644 --- a/src/engine/SCons/Script/Interactive.py +++ b/src/engine/SCons/Script/Interactive.py @@ -304,14 +304,8 @@ class SConsInteractiveCmd(cmd.Cmd): return self._strip_initial_spaces(doc) def _strip_initial_spaces(self, s): - #lines = s.split('\n') lines = s.split('\n') spaces = re.match(' *', lines[0]).group(0) - #def strip_spaces(l): - # if l.startswith(spaces): - # l = l[len(spaces):] - # return l - #return '\n'.join([ strip_spaces(l) for l in lines ]) def strip_spaces(l, spaces=spaces): if l[:len(spaces)] == spaces: l = l[len(spaces):] diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index bd227bd..05c0d75 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -10,7 +10,7 @@ some other module. If it's specific to the "scons" script invocation, it goes here. """ -unsupported_python_version = (2, 3, 0) +unsupported_python_version = (2, 6, 0) deprecated_python_version = (2, 7, 0) # __COPYRIGHT__ @@ -43,15 +43,6 @@ import sys import time import traceback -# Strip the script directory from sys.path() so on case-insensitive -# (Windows) systems Python doesn't think that the "scons" script is the -# "SCons" package. Replace it with our own version directory so, if -# if they're there, we pick up the right version of the build engine -# modules. -#sys.path = [os.path.join(sys.prefix, -# 'lib', -# 'scons-%d' % SCons.__version__)] + sys.path[1:] - import SCons.CacheDir import SCons.Debug import SCons.Defaults @@ -74,7 +65,7 @@ def fetch_win32_parallel_msg(): # so we don't have to pull it in on all platforms, and so that an # in-line "import" statement in the _main() function below doesn't # cause warnings about local names shadowing use of the 'SCons' - # globl in nest scopes and UnboundLocalErrors and the like in some + # global in nest scopes and UnboundLocalErrors and the like in some # versions (2.1) of Python. import SCons.Platform.win32 return SCons.Platform.win32.parallel_msg @@ -368,7 +359,7 @@ class CleanTask(SCons.Taskmaster.AlwaysTask): # issue, an IOError would indicate something like # the file not existing. In either case, print a # message and keep going to try to remove as many - # targets aa possible. + # targets as possible. print "scons: Could not remove '%s':" % str(t), e.strerror else: if removed: @@ -383,7 +374,7 @@ class CleanTask(SCons.Taskmaster.AlwaysTask): # we don't want, like store .sconsign information. executed = SCons.Taskmaster.Task.executed_without_callbacks - # Have the taskmaster arrange to "execute" all of the targets, because + # Have the Taskmaster arrange to "execute" all of the targets, because # we'll figure out ourselves (in remove() or show() above) whether # anything really needs to be done. make_ready = SCons.Taskmaster.Task.make_ready_all @@ -487,7 +478,6 @@ def SetOption(name, value): def PrintHelp(file=None): OptionsParser.print_help(file=file) -# class Stats(object): def __init__(self): self.stats = [] @@ -711,7 +701,6 @@ def _load_site_scons_dir(topdir, site_dir_name=None): site_tools_dir = os.path.join(site_dir, site_tools_dirname) if os.path.exists(site_init_file): import imp, re - # TODO(2.4): turn this into try:-except:-finally: try: try: fp, pathname, description = imp.find_module(site_init_modname, @@ -1024,7 +1013,7 @@ def _main(parser): # the SConscript file. # # We delay enabling the PythonVersionWarning class until here so that, - # if they explicity disabled it in either in the command line or in + # if they explicitly disabled it in either in the command line or in # $SCONSFLAGS, or in the SConscript file, then the search through # the list of deprecated warning classes will find that disabling # first and not issue the warning. @@ -1232,13 +1221,8 @@ def _build_targets(fs, options, targets, target_top): def order(dependencies): """Randomize the dependencies.""" import random - # This is cribbed from the implementation of - # random.shuffle() in Python 2.X. - d = dependencies - for i in range(len(d)-1, 0, -1): - j = int(random.random() * (i+1)) - d[i], d[j] = d[j], d[i] - return d + random.shuffle(dependencies) + return dependencies else: def order(dependencies): """Leave the order of dependencies alone.""" @@ -1316,18 +1300,6 @@ def _exec_main(parser, values): # compat layer imports "cProfile" for us if it's available. from profile import Profile - # Some versions of Python 2.4 shipped a profiler that had the - # wrong 'c_exception' entry in its dispatch table. Make sure - # we have the right one. (This may put an unnecessary entry - # in the table in earlier versions of Python, but its presence - # shouldn't hurt anything). - try: - dispatch = Profile.dispatch - except AttributeError: - pass - else: - dispatch['c_exception'] = Profile.trace_dispatch_return - prof = Profile() try: prof.runcall(_main, parser) diff --git a/src/engine/SCons/Script/SConsOptions.py b/src/engine/SCons/Script/SConsOptions.py index 68c60cc..f56504a 100644 --- a/src/engine/SCons/Script/SConsOptions.py +++ b/src/engine/SCons/Script/SConsOptions.py @@ -426,7 +426,7 @@ class SConsOptionParser(optparse.OptionParser): result = group.add_option(*args, **kw) if result: - # The option was added succesfully. We now have to add the + # The option was added successfully. We now have to add the # default value to our object that holds the default values # (so that an attempt to fetch the option's attribute will # yield the default value when not overridden) and then @@ -449,11 +449,6 @@ class SConsIndentedHelpFormatter(optparse.IndentedHelpFormatter): "SCons Options." Unfortunately, we have to do this here, because those titles are hard-coded in the optparse calls. """ - if heading == 'options': - # The versions of optparse.py shipped with Pythons 2.3 and - # 2.4 pass this in uncapitalized; override that so we get - # consistent output on all versions. - heading = "Options" if heading == 'Options': heading = "SCons Options" return optparse.IndentedHelpFormatter.format_heading(self, heading) @@ -488,13 +483,7 @@ class SConsIndentedHelpFormatter(optparse.IndentedHelpFormatter): # read data from FILENAME result = [] - try: - opts = self.option_strings[option] - except AttributeError: - # The Python 2.3 version of optparse attaches this to - # to the option argument, not to this object. - opts = option.option_strings - + opts = self.option_strings[option] opt_width = self.help_position - self.current_indent - 2 if len(opts) > opt_width: wrapper = textwrap.TextWrapper(width=self.width, @@ -509,14 +498,7 @@ class SConsIndentedHelpFormatter(optparse.IndentedHelpFormatter): result.append(opts) if option.help: - try: - expand_default = self.expand_default - except AttributeError: - # The HelpFormatter base class in the Python 2.3 version - # of optparse has no expand_default() method. - help_text = option.help - else: - help_text = expand_default(option) + help_text = self.expand_default(option) # SCons: indent every line of the help text but the first. wrapper = textwrap.TextWrapper(width=self.help_width, @@ -530,34 +512,6 @@ class SConsIndentedHelpFormatter(optparse.IndentedHelpFormatter): result.append("\n") return "".join(result) - # For consistent help output across Python versions, we provide a - # subclass copy of format_option_strings() and these two variables. - # This is necessary (?) for Python2.3, which otherwise concatenates - # a short option with its metavar. - _short_opt_fmt = "%s %s" - _long_opt_fmt = "%s=%s" - - def format_option_strings(self, option): - """Return a comma-separated list of option strings & metavariables.""" - if option.takes_value(): - metavar = option.metavar or option.dest.upper() - short_opts = [] - for sopt in option._short_opts: - short_opts.append(self._short_opt_fmt % (sopt, metavar)) - long_opts = [] - for lopt in option._long_opts: - long_opts.append(self._long_opt_fmt % (lopt, metavar)) - else: - short_opts = option._short_opts - long_opts = option._long_opts - - if self.short_first: - opts = short_opts + long_opts - else: - opts = long_opts + short_opts - - return ", ".join(opts) - def Parser(version): """ Returns an options parser object initialized with the standard diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py index b832ff7..e696cfa 100644 --- a/src/engine/SCons/Script/SConscript.py +++ b/src/engine/SCons/Script/SConscript.py @@ -52,16 +52,6 @@ import re import sys import traceback -# The following variables used to live in this module. Some -# SConscript files out there may have referred to them directly as -# SCons.Script.SConscript.*. This is now supported by some special -# handling towards the bottom of the SConscript.__init__.py module. -#Arguments = {} -#ArgList = [] -#BuildTargets = TargetList() -#CommandLineTargets = [] -#DefaultTargets = [] - class SConscriptReturn(Exception): pass @@ -446,7 +436,7 @@ class SConsEnvironment(SCons.Environment.Base): # # Public methods of an SConsEnvironment. These get - # entry points in the global name space so they can be called + # entry points in the global namespace so they can be called # as global functions. # diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py index 6bfc36f..a0c61c5 100644 --- a/src/engine/SCons/Script/__init__.py +++ b/src/engine/SCons/Script/__init__.py @@ -270,12 +270,6 @@ def HelpFunction(text, append=False): s.close() else: help_text = "" -# -# Was in original patch but this text is arbitrary and breaks tests -# so I removed it (Deegan) -# help_text = help_text + "\nLocal Build Variables:\n" + text -# else: -# help_text = help_text + text help_text= help_text + text diff --git a/src/engine/SCons/Subst.py b/src/engine/SCons/Subst.py index 318d7d9..236b08e 100644 --- a/src/engine/SCons/Subst.py +++ b/src/engine/SCons/Subst.py @@ -344,7 +344,6 @@ _remove = re.compile(r'\$\([^\$]*(\$[^\)][^\$]*)*\$\)') _regex_remove = [ _rm, None, _remove ] def _rm_list(list): - #return [ l for l in list if not l in ('$(', '$)') ] return [l for l in list if not l in ('$(', '$)')] def _remove_list(list): @@ -580,8 +579,6 @@ def scons_subst(strSubst, env, mode=SUBST_RAW, target=None, source=None, gvars={ return result -#Subst_List_Strings = {} - def scons_subst_list(strSubst, env, mode=SUBST_RAW, target=None, source=None, gvars={}, lvars={}, conv=None): """Substitute construction variables in a string (or list or other object) and separate the arguments into a command list. @@ -590,12 +587,6 @@ def scons_subst_list(strSubst, env, mode=SUBST_RAW, target=None, source=None, gv substitutions within strings, so see that function instead if that's what you're looking for. """ -# try: -# Subst_List_Strings[strSubst] = Subst_List_Strings[strSubst] + 1 -# except KeyError: -# Subst_List_Strings[strSubst] = 1 -# import SCons.Debug -# SCons.Debug.caller_trace(1) class ListSubber(collections.UserList): """A class to construct the results of a scons_subst_list() call. diff --git a/src/engine/SCons/SubstTests.py b/src/engine/SCons/SubstTests.py index 6f2eb3f..e625cc7 100644 --- a/src/engine/SCons/SubstTests.py +++ b/src/engine/SCons/SubstTests.py @@ -604,17 +604,6 @@ class scons_subst_TestCase(SubstTestCase): node = scons_subst("$NODE", env, mode=SUBST_SIG, conv=s, gvars=gvars) assert node is n1, node - #def test_subst_function_return(self): - # """Test scons_subst(): returning a function""" - # env = DummyEnv({'FUNCTION' : foo}) - # gvars = env.Dictionary() - # func = scons_subst("$FUNCTION", env, mode=SUBST_RAW, call=None, gvars=gvars) - # assert func is function_foo, func - # func = scons_subst("$FUNCTION", env, mode=SUBST_CMD, call=None, gvars=gvars) - # assert func is function_foo, func - # func = scons_subst("$FUNCTION", env, mode=SUBST_SIG, call=None, gvars=gvars) - # assert func is function_foo, func - def test_subst_overriding_gvars(self): """Test scons_subst(): supplying an overriding gvars dictionary""" env = DummyEnv({'XXX' : 'xxx'}) diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py index 345534e..069ac90 100644 --- a/src/engine/SCons/Taskmaster.py +++ b/src/engine/SCons/Taskmaster.py @@ -122,7 +122,7 @@ class Task(object): aspects of controlling a build, so any given application *should* be able to do what it wants by sub-classing this class and overriding methods as appropriate. If an application - needs to customze something by sub-classing Taskmaster (or + needs to customize something by sub-classing Taskmaster (or some other build engine class), we should first try to migrate that functionality into this class. @@ -147,7 +147,7 @@ class Task(object): This hook gets called as part of preparing a task for execution (that is, a Node to be built). As part of figuring out what Node - should be built next, the actually target list may be altered, + should be built next, the actual target list may be altered, along with a message describing the alteration. The calling interface can subclass Task and provide a concrete implementation of this method to see those messages. @@ -664,9 +664,9 @@ class Taskmaster(object): its parent node. A pending child can occur when the Taskmaster completes a loop - through a cycle. For example, lets imagine a graph made of - three node (A, B and C) making a cycle. The evaluation starts - at node A. The taskmaster first consider whether node A's + through a cycle. For example, let's imagine a graph made of + three nodes (A, B and C) making a cycle. The evaluation starts + at node A. The Taskmaster first considers whether node A's child B is up-to-date. Then, recursively, node B needs to check whether node C is up-to-date. This leaves us with a dependency graph looking like: @@ -951,7 +951,7 @@ class Taskmaster(object): task.make_ready() except: # We had a problem just trying to get this task ready (like - # a child couldn't be linked in to a VariantDir when deciding + # a child couldn't be linked to a VariantDir when deciding # whether this node is current). Arrange to raise the # exception when the Task is "executed." self.ready_exc = sys.exc_info() diff --git a/src/engine/SCons/Tool/BitKeeper.py b/src/engine/SCons/Tool/BitKeeper.py index 191879f..44632d7 100644 --- a/src/engine/SCons/Tool/BitKeeper.py +++ b/src/engine/SCons/Tool/BitKeeper.py @@ -49,7 +49,6 @@ def generate(env): act = SCons.Action.Action("$BITKEEPERCOM", "$BITKEEPERCOMSTR") return SCons.Builder.Builder(action = act, env = env) - #setattr(env, 'BitKeeper', BitKeeperFactory) env.BitKeeper = BitKeeperFactory env['BITKEEPER'] = 'bk' diff --git a/src/engine/SCons/Tool/CVS.py b/src/engine/SCons/Tool/CVS.py index a506231..08cf04c 100644 --- a/src/engine/SCons/Tool/CVS.py +++ b/src/engine/SCons/Tool/CVS.py @@ -55,7 +55,6 @@ def generate(env): CVSREPOSITORY = repos, CVSMODULE = module) - #setattr(env, 'CVS', CVSFactory) env.CVS = CVSFactory env['CVS'] = 'cvs' diff --git a/src/engine/SCons/Tool/GettextCommon.py b/src/engine/SCons/Tool/GettextCommon.py index bdd52c0..f01371a 100644 --- a/src/engine/SCons/Tool/GettextCommon.py +++ b/src/engine/SCons/Tool/GettextCommon.py @@ -251,7 +251,7 @@ class RPaths(object): recently re-created. For such reason, we need a function, which always returns relative paths. This is the purpose of `RPaths` callable object. - The `__call__` method returns paths relative to current woking directory, but + The `__call__` method returns paths relative to current working directory, but we assume, that *xgettext(1)* is run from the directory, where target file is going to be created. @@ -330,7 +330,7 @@ def _init_po_files(target, source, env): autoinit = False # Well, if everything outside works well, this loop should do single # iteration. Otherwise we are rebuilding all the targets even, if just - # one has changed (but is this out fault?). + # one has changed (but is this our fault?). for tgt in target: if not tgt.exists(): if autoinit: diff --git a/src/engine/SCons/Tool/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py index 9549a66..be890e2 100644 --- a/src/engine/SCons/Tool/MSCommon/common.py +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -93,7 +93,7 @@ def has_reg(value): try: SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, value) ret = True - except WindowsError: + except SCons.Util.WinError: ret = False return ret @@ -180,7 +180,7 @@ def get_output(vcbat, args = None, env = None): stdout = popen.stdout.read() stderr = popen.stderr.read() - # Extra debug logic, uncomment if necessar + # Extra debug logic, uncomment if necessary # debug('get_output():stdout:%s'%stdout) # debug('get_output():stderr:%s'%stderr) @@ -226,33 +226,6 @@ def parse_output(output, keep = ("INCLUDE", "LIB", "LIBPATH", "PATH")): return dkeep -# TODO(sgk): unused -def output_to_dict(output): - """Given an output string, parse it to find env variables. - - Return a dict where keys are variables names, and values their content""" - envlinem = re.compile(r'^([a-zA-z0-9]+)=([\S\s]*)$') - parsedenv = {} - for line in output.splitlines(): - m = envlinem.match(line) - if m: - parsedenv[m.group(1)] = m.group(2) - return parsedenv - -# TODO(sgk): unused -def get_new(l1, l2): - """Given two list l1 and l2, return the items in l2 which are not in l1. - Order is maintained.""" - - # We don't try to be smart: lists are small, and this is not the bottleneck - # is any case - new = [] - for i in l2: - if i not in l1: - new.append(i) - - return new - # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/src/engine/SCons/Tool/MSCommon/netframework.py b/src/engine/SCons/Tool/MSCommon/netframework.py index 6124e5b..8fa3c43 100644 --- a/src/engine/SCons/Tool/MSCommon/netframework.py +++ b/src/engine/SCons/Tool/MSCommon/netframework.py @@ -27,6 +27,7 @@ __doc__ = """ import os import re +import SCons.Util from common import read_reg, debug @@ -40,7 +41,7 @@ def find_framework_root(): try: froot = read_reg(_FRAMEWORKDIR_HKEY_ROOT) debug("Found framework install root in registry: %s" % froot) - except WindowsError, e: + except SCons.Util.WinError, e: debug("Could not read reg key %s" % _FRAMEWORKDIR_HKEY_ROOT) return None diff --git a/src/engine/SCons/Tool/MSCommon/sdk.py b/src/engine/SCons/Tool/MSCommon/sdk.py index afb37fe..b8b71a6 100644 --- a/src/engine/SCons/Tool/MSCommon/sdk.py +++ b/src/engine/SCons/Tool/MSCommon/sdk.py @@ -80,7 +80,7 @@ class SDKDefinition(object): try: sdk_dir = common.read_reg(hkey) - except WindowsError, e: + except SCons.Util.WinError, e: debug('find_sdk_dir(): no SDK registry key %s' % repr(hkey)) return None @@ -168,7 +168,7 @@ SDK70VCSetupScripts = { 'x86' : r'bin\vcvars32.bat', # # The first SDK found in the list is the one used by default if there # are multiple SDKs installed. Barring good reasons to the contrary, -# this means we should list SDKs with from most recent to oldest. +# this means we should list SDKs from most recent to oldest. # # If you update this list, update the documentation in Tool/mssdk.xml. SupportedSDKList = [ @@ -306,29 +306,6 @@ def set_sdk_by_directory(env, sdk_dir): for variable, directory in env_tuple_list: env.PrependENVPath(variable, directory) - -# TODO(sgk): currently unused; remove? -def get_cur_sdk_dir_from_reg(): - """Try to find the platform sdk directory from the registry. - - Return None if failed or the directory does not exist""" - if not SCons.Util.can_read_reg: - debug('SCons cannot read registry') - return None - - try: - val = common.read_reg(_CURINSTALLED_SDK_HKEY_ROOT) - debug("Found current sdk dir in registry: %s" % val) - except WindowsError, e: - debug("Did not find current sdk in registry") - return None - - if not os.path.exists(val): - debug("Current sdk dir %s not on fs" % val) - return None - - return val - def get_sdk_by_version(mssdk): if mssdk not in SupportedSDKMap: msg = "SDK version %s is not supported" % repr(mssdk) @@ -343,9 +320,6 @@ def get_default_sdk(): return None return InstalledSDKList[0] - - - def mssdk_setup_env(env): debug('sdk.py:mssdk_setup_env()') if 'MSSDK_DIR' in env: diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index 4fb0d5a..97e2ffc 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -244,13 +244,13 @@ def find_vc_pdir(msvc_version): try: # ordinally at win64, try Wow6432Node first. comps = common.read_reg(root + 'Wow6432Node\\' + key, hkroot) - except WindowsError, e: + except SCons.Util.WinError, e: # at Microsoft Visual Studio for Python 2.7, value is not in Wow6432Node pass if not comps: # not Win64, or Microsoft Visual Studio for Python 2.7 comps = common.read_reg(root + key, hkroot) - except WindowsError, e: + except SCons.Util.WinError, e: debug('find_vc_dir(): no VC registry key %s' % repr(key)) else: debug('find_vc_dir(): found VC in registry: %s' % comps) diff --git a/src/engine/SCons/Tool/MSCommon/vs.py b/src/engine/SCons/Tool/MSCommon/vs.py index d9eb1e3..0bdbf0c 100644 --- a/src/engine/SCons/Tool/MSCommon/vs.py +++ b/src/engine/SCons/Tool/MSCommon/vs.py @@ -52,8 +52,6 @@ class VisualStudio(object): self.__dict__.update(kw) self._cache = {} - # - def find_batch_file(self): vs_dir = self.get_vs_dir() if not vs_dir: @@ -85,7 +83,7 @@ class VisualStudio(object): key = root + key try: comps = read_reg(key) - except WindowsError, e: + except SCons.Util.WinError, e: debug('find_vs_dir_by_reg(): no VS registry key %s' % repr(key)) else: debug('find_vs_dir_by_reg(): found VS in registry: %s' % comps) @@ -116,8 +114,6 @@ class VisualStudio(object): return None return executable - # - def get_batch_file(self): try: return self._cache['batch_file'] @@ -471,7 +467,7 @@ def get_default_version(env): """Returns the default version string to use for MSVS. If no version was requested by the user through the MSVS environment - variable, query all the available the visual studios through + variable, query all the available visual studios through get_installed_visual_studios, and take the highest one. Return diff --git a/src/engine/SCons/Tool/Perforce.py b/src/engine/SCons/Tool/Perforce.py index 15dd83f..c8cf931 100644 --- a/src/engine/SCons/Tool/Perforce.py +++ b/src/engine/SCons/Tool/Perforce.py @@ -38,9 +38,6 @@ import SCons.Builder import SCons.Node.FS import SCons.Util -# This function should maybe be moved to SCons.Util? -from SCons.Tool.PharLapCommon import addPathIfNotExists - # Variables that we want to import from the base OS environment. _import_env = [ 'P4PORT', 'P4CLIENT', 'P4USER', 'USER', 'USERNAME', 'P4PASSWD', @@ -58,7 +55,6 @@ def generate(env): W.warn(W.DeprecatedSourceCodeWarning, """The Perforce() factory is deprecated and there is no replacement.""") return SCons.Builder.Builder(action = PerforceAction, env = env) - #setattr(env, 'Perforce', PerforceFactory) env.Perforce = PerforceFactory env['P4'] = 'p4' @@ -87,7 +83,7 @@ def generate(env): k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE, 'Software\\Perforce\\environment') val, tok = SCons.Util.RegQueryValueEx(k, 'P4INSTROOT') - addPathIfNotExists(environ, 'PATH', val) + SCons.Util.AddPathIfNotExists(environ, 'PATH', val) except SCons.Util.RegError: # Can't detect where Perforce is, hope the user has it set in the # PATH. diff --git a/src/engine/SCons/Tool/PharLapCommon.py b/src/engine/SCons/Tool/PharLapCommon.py index 9f925b9..864a185 100644 --- a/src/engine/SCons/Tool/PharLapCommon.py +++ b/src/engine/SCons/Tool/PharLapCommon.py @@ -85,28 +85,6 @@ def getPharLapVersion(): # Default return for Phar Lap 9.1 return 910 -def addPathIfNotExists(env_dict, key, path, sep=os.pathsep): - """This function will take 'key' out of the dictionary - 'env_dict', then add the path 'path' to that key if it is not - already there. This treats the value of env_dict[key] as if it - has a similar format to the PATH variable...a list of paths - separated by tokens. The 'path' will get added to the list if it - is not already there.""" - try: - is_list = 1 - paths = env_dict[key] - if not SCons.Util.is_List(env_dict[key]): - paths = paths.split(sep) - is_list = 0 - if os.path.normcase(path) not in list(map(os.path.normcase, paths)): - paths = [ path ] + paths - if is_list: - env_dict[key] = paths - else: - env_dict[key] = sep.join(paths) - except KeyError: - env_dict[key] = path - def addPharLapPaths(env): """This function adds the path to the Phar Lap binaries, includes, and libraries, if they are not already there.""" @@ -117,14 +95,14 @@ def addPharLapPaths(env): except KeyError: env_dict = {} env['ENV'] = env_dict - addPathIfNotExists(env_dict, 'PATH', - os.path.join(ph_path, 'bin')) - addPathIfNotExists(env_dict, 'INCLUDE', - os.path.join(ph_path, 'include')) - addPathIfNotExists(env_dict, 'LIB', - os.path.join(ph_path, 'lib')) - addPathIfNotExists(env_dict, 'LIB', - os.path.join(ph_path, os.path.normpath('lib/vclib'))) + SCons.Util.AddPathIfNotExists(env_dict, 'PATH', + os.path.join(ph_path, 'bin')) + SCons.Util.AddPathIfNotExists(env_dict, 'INCLUDE', + os.path.join(ph_path, 'include')) + SCons.Util.AddPathIfNotExists(env_dict, 'LIB', + os.path.join(ph_path, 'lib')) + SCons.Util.AddPathIfNotExists(env_dict, 'LIB', + os.path.join(ph_path, os.path.normpath('lib/vclib'))) env['PHARLAP_PATH'] = getPharLapPath() env['PHARLAP_VERSION'] = str(getPharLapVersion()) diff --git a/src/engine/SCons/Tool/PharLapCommonTests.py b/src/engine/SCons/Tool/PharLapCommonTests.py deleted file mode 100644 index e67d426..0000000 --- a/src/engine/SCons/Tool/PharLapCommonTests.py +++ /dev/null @@ -1,69 +0,0 @@ -# -# __COPYRIGHT__ -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# 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. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -import unittest -import os.path -import os -import sys - -import TestUnit - -import SCons.Errors -from SCons.Tool.PharLapCommon import * - -class PharLapCommonTestCase(unittest.TestCase): - def test_addPathIfNotExists(self): - """Test the addPathIfNotExists() function""" - env_dict = { 'FOO' : os.path.normpath('/foo/bar') + os.pathsep + \ - os.path.normpath('/baz/blat'), - 'BAR' : os.path.normpath('/foo/bar') + os.pathsep + \ - os.path.normpath('/baz/blat'), - 'BLAT' : [ os.path.normpath('/foo/bar'), - os.path.normpath('/baz/blat') ] } - addPathIfNotExists(env_dict, 'FOO', os.path.normpath('/foo/bar')) - addPathIfNotExists(env_dict, 'BAR', os.path.normpath('/bar/foo')) - addPathIfNotExists(env_dict, 'BAZ', os.path.normpath('/foo/baz')) - addPathIfNotExists(env_dict, 'BLAT', os.path.normpath('/baz/blat')) - addPathIfNotExists(env_dict, 'BLAT', os.path.normpath('/baz/foo')) - - assert env_dict['FOO'] == os.path.normpath('/foo/bar') + os.pathsep + \ - os.path.normpath('/baz/blat'), env_dict['FOO'] - assert env_dict['BAR'] == os.path.normpath('/bar/foo') + os.pathsep + \ - os.path.normpath('/foo/bar') + os.pathsep + \ - os.path.normpath('/baz/blat'), env_dict['BAR'] - assert env_dict['BAZ'] == os.path.normpath('/foo/baz'), env_dict['BAZ'] - assert env_dict['BLAT'] == [ os.path.normpath('/baz/foo'), - os.path.normpath('/foo/bar'), - os.path.normpath('/baz/blat') ], env_dict['BLAT' ] - -if __name__ == "__main__": - suite = unittest.makeSuite(PharLapCommonTestCase, 'test_') - TestUnit.run(suite) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Tool/RCS.py b/src/engine/SCons/Tool/RCS.py index 6ac1a33..e24b89a 100644 --- a/src/engine/SCons/Tool/RCS.py +++ b/src/engine/SCons/Tool/RCS.py @@ -46,7 +46,6 @@ def generate(env): act = SCons.Action.Action('$RCS_COCOM', '$RCS_COCOMSTR') return SCons.Builder.Builder(action = act, env = env) - #setattr(env, 'RCS', RCSFactory) env.RCS = RCSFactory env['RCS'] = 'rcs' diff --git a/src/engine/SCons/Tool/SCCS.py b/src/engine/SCons/Tool/SCCS.py index 7653468..92ded51 100644 --- a/src/engine/SCons/Tool/SCCS.py +++ b/src/engine/SCons/Tool/SCCS.py @@ -46,7 +46,6 @@ def generate(env): act = SCons.Action.Action('$SCCSCOM', '$SCCSCOMSTR') return SCons.Builder.Builder(action = act, env = env) - #setattr(env, 'SCCS', SCCSFactory) env.SCCS = SCCSFactory env['SCCS'] = 'sccs' diff --git a/src/engine/SCons/Tool/Subversion.py b/src/engine/SCons/Tool/Subversion.py index ee70925..f1b3708 100644 --- a/src/engine/SCons/Tool/Subversion.py +++ b/src/engine/SCons/Tool/Subversion.py @@ -54,7 +54,6 @@ def generate(env): SVNREPOSITORY = repos, SVNMODULE = module) - #setattr(env, 'Subversion', SubversionFactory) env.Subversion = SubversionFactory env['SVN'] = 'svn' diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index 0594798..f16e9e2 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -108,7 +108,7 @@ class Tool(object): self.options = module.options def _tool_module(self): - # TODO: Interchange zipimport with normal initilization for better error reporting + # TODO: Interchange zipimport with normal initialization for better error reporting oldpythonpath = sys.path sys.path = self.toolpath + sys.path diff --git a/src/engine/SCons/Tool/aixf77.py b/src/engine/SCons/Tool/aixf77.py index a667e84..cf07a0b 100644 --- a/src/engine/SCons/Tool/aixf77.py +++ b/src/engine/SCons/Tool/aixf77.py @@ -41,7 +41,7 @@ import f77 # It would be good to look for the AIX F77 package the same way we're now # looking for the C and C++ packages. This should be as easy as supplying # the correct package names in the following list and uncommenting the -# SCons.Platform.aix_get_xlc() call the in the function below. +# SCons.Platform.aix_get_xlc() call in the function below. packages = [] def get_xlf77(env): diff --git a/src/engine/SCons/Tool/cyglink.py b/src/engine/SCons/Tool/cyglink.py index 5230910..921f0eb 100644 --- a/src/engine/SCons/Tool/cyglink.py +++ b/src/engine/SCons/Tool/cyglink.py @@ -143,7 +143,7 @@ def _versioned_implib_name(env, libnode, version, prefix, suffix, **kw): implib_libtype=kw['libtype']) def _versioned_implib_symlinks(env, libnode, version, prefix, suffix, **kw): - """Generate link names that should be created for a versioned shared lirbrary. + """Generate link names that should be created for a versioned shared library. Returns a list in the form [ (link, linktarget), ... ] """ Verbose = False diff --git a/src/engine/SCons/Tool/docbook/__init__.py b/src/engine/SCons/Tool/docbook/__init__.py index aead43c..71e93a7 100644 --- a/src/engine/SCons/Tool/docbook/__init__.py +++ b/src/engine/SCons/Tool/docbook/__init__.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001-7,2010 The SCons Foundation +# __COPYRIGHT__ # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -852,30 +852,16 @@ def generate(env): ) _detect(env) - try: - env.AddMethod(DocbookEpub, "DocbookEpub") - env.AddMethod(DocbookHtml, "DocbookHtml") - env.AddMethod(DocbookHtmlChunked, "DocbookHtmlChunked") - env.AddMethod(DocbookHtmlhelp, "DocbookHtmlhelp") - env.AddMethod(DocbookPdf, "DocbookPdf") - env.AddMethod(DocbookMan, "DocbookMan") - env.AddMethod(DocbookSlidesPdf, "DocbookSlidesPdf") - env.AddMethod(DocbookSlidesHtml, "DocbookSlidesHtml") - env.AddMethod(DocbookXInclude, "DocbookXInclude") - env.AddMethod(DocbookXslt, "DocbookXslt") - except AttributeError: - # Looks like we use a pre-0.98 version of SCons... - from SCons.Script.SConscript import SConsEnvironment - SConsEnvironment.DocbookEpub = DocbookEpub - SConsEnvironment.DocbookHtml = DocbookHtml - SConsEnvironment.DocbookHtmlChunked = DocbookHtmlChunked - SConsEnvironment.DocbookHtmlhelp = DocbookHtmlhelp - SConsEnvironment.DocbookPdf = DocbookPdf - SConsEnvironment.DocbookMan = DocbookMan - SConsEnvironment.DocbookSlidesPdf = DocbookSlidesPdf - SConsEnvironment.DocbookSlidesHtml = DocbookSlidesHtml - SConsEnvironment.DocbookXInclude = DocbookXInclude - SConsEnvironment.DocbookXslt = DocbookXslt + env.AddMethod(DocbookEpub, "DocbookEpub") + env.AddMethod(DocbookHtml, "DocbookHtml") + env.AddMethod(DocbookHtmlChunked, "DocbookHtmlChunked") + env.AddMethod(DocbookHtmlhelp, "DocbookHtmlhelp") + env.AddMethod(DocbookPdf, "DocbookPdf") + env.AddMethod(DocbookMan, "DocbookMan") + env.AddMethod(DocbookSlidesPdf, "DocbookSlidesPdf") + env.AddMethod(DocbookSlidesHtml, "DocbookSlidesHtml") + env.AddMethod(DocbookXInclude, "DocbookXInclude") + env.AddMethod(DocbookXslt, "DocbookXslt") def exists(env): diff --git a/src/engine/SCons/Tool/gnulink.py b/src/engine/SCons/Tool/gnulink.py index 6b0d5b3..2f1aa03 100644 --- a/src/engine/SCons/Tool/gnulink.py +++ b/src/engine/SCons/Tool/gnulink.py @@ -60,7 +60,7 @@ def generate(env): link._setup_versioned_lib_variables(env, tool = 'gnulink', use_soname = use_soname) env['LINKCALLBACKS'] = link._versioned_lib_callbacks() - # For backward-compatiblity with older SCons versions + # For backward-compatibility with older SCons versions env['SHLIBVERSIONFLAGS'] = SCons.Util.CLVar('-Wl,-Bsymbolic') def exists(env): diff --git a/src/engine/SCons/Tool/icl.py b/src/engine/SCons/Tool/icl.py index caa2281..a0bad31 100644 --- a/src/engine/SCons/Tool/icl.py +++ b/src/engine/SCons/Tool/icl.py @@ -35,7 +35,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Tool.intelc -# This has been completely superceded by intelc.py, which can +# This has been completely superseded by intelc.py, which can # handle both Windows and Linux versions. def generate(*args, **kw): diff --git a/src/engine/SCons/Tool/install.py b/src/engine/SCons/Tool/install.py index 4226d56..e84ec7a 100644 --- a/src/engine/SCons/Tool/install.py +++ b/src/engine/SCons/Tool/install.py @@ -39,7 +39,7 @@ import stat import SCons.Action import SCons.Tool -from SCons.Util import make_path_relative +import SCons.Util # # We keep track of *all* installed files. @@ -91,7 +91,7 @@ def scons_copytree(src, dst, symlinks=False): errors.extend(err.args[0]) try: shutil.copystat(src, dst) - except WindowsError: + except SCons.Util.WinError: # can't copy file access times on Windows pass except OSError, why: @@ -225,7 +225,7 @@ def stringFunc(target, source, env): # Emitter functions # def add_targets_to_INSTALLED_FILES(target, source, env): - """ an emitter that adds all target files to the list stored in the + """ An emitter that adds all target files to the list stored in the _INSTALLED_FILES global variable. This way all installed files of one scons call will be collected. """ @@ -236,7 +236,7 @@ def add_targets_to_INSTALLED_FILES(target, source, env): return (target, source) def add_versioned_targets_to_INSTALLED_FILES(target, source, env): - """ an emitter that adds all target files to the list stored in the + """ An emitter that adds all target files to the list stored in the _INSTALLED_FILES global variable. This way all installed files of one scons call will be collected. """ @@ -254,7 +254,7 @@ def add_versioned_targets_to_INSTALLED_FILES(target, source, env): return (target, source) class DESTDIR_factory(object): - """ a node factory, where all files will be relative to the dir supplied + """ A node factory, where all files will be relative to the dir supplied in the constructor. """ def __init__(self, env, dir): @@ -262,11 +262,11 @@ class DESTDIR_factory(object): self.dir = env.arg2nodes( dir, env.fs.Dir )[0] def Entry(self, name): - name = make_path_relative(name) + name = SCons.Util.make_path_relative(name) return self.dir.Entry(name) def Dir(self, name): - name = make_path_relative(name) + name = SCons.Util.make_path_relative(name) return self.dir.Dir(name) # @@ -304,14 +304,12 @@ def InstallBuilderWrapper(env, target=None, source=None, dir=None, **kw): # '#' on the file name portion as meaning the Node should # be relative to the top-level SConstruct directory. target = env.fs.Entry('.'+os.sep+src.name, dnode) - #tgt.extend(BaseInstallBuilder(env, target, src, **kw)) tgt.extend(BaseInstallBuilder(env, target, src, **kw)) return tgt def InstallAsBuilderWrapper(env, target=None, source=None, **kw): result = [] for src, tgt in map(lambda x, y: (x, y), source, target): - #result.extend(BaseInstallBuilder(env, tgt, src, **kw)) result.extend(BaseInstallBuilder(env, tgt, src, **kw)) return result diff --git a/src/engine/SCons/Tool/intelc.py b/src/engine/SCons/Tool/intelc.py index 57258f3..b1cb5e3 100644 --- a/src/engine/SCons/Tool/intelc.py +++ b/src/engine/SCons/Tool/intelc.py @@ -62,15 +62,6 @@ class MissingDirError(IntelCError): # dir not found class NoRegistryModuleError(IntelCError): # can't read registry at all pass -def uniquify(s): - """Return a sequence containing only one copy of each unique element from input sequence s. - Does not preserve order. - Input sequence must be hashable (i.e. must be usable as a dictionary key).""" - u = {} - for x in s: - u[x] = 1 - return list(u.keys()) - def linux_ver_normalize(vstr): """Normalize a Linux compiler version number. Intel changed from "80" to "9.0" in 2005, so we assume if the number @@ -191,7 +182,7 @@ def get_intel_registry_value(valuename, version=None, abi=None): except SCons.Util.RegError: raise MissingRegistryError("%s was not found in the registry, for Intel compiler version %s, abi='%s'"%(K, version,abi)) - except WindowsError: + except SCons.Util.WinError: raise MissingRegistryError("%s was not found in the registry, for Intel compiler version %s, abi='%s'"%(K, version,abi)) # Get the value: @@ -215,7 +206,7 @@ def get_all_compiler_versions(): try: k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, keyname) - except WindowsError: + except SCons.Util.WinError: # For version 13 or later, check for default instance UUID if is_win64: keyname = 'Software\\WoW6432Node\\Intel\\Suites' @@ -224,7 +215,7 @@ def get_all_compiler_versions(): try: k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, keyname) - except WindowsError: + except SCons.Util.WinError: return [] i = 0 versions = [] @@ -302,7 +293,7 @@ def get_all_compiler_versions(): """Given a dot-separated version string, return a tuple of ints representing it.""" return [int(x) for x in str.split('.')] # split into ints, sort, then remove dups - return sorted(uniquify(versions), key=keyfunc, reverse=True) + return sorted(SCons.Util.unique(versions), key=keyfunc, reverse=True) def get_intel_compiler_top(version, abi): """ diff --git a/src/engine/SCons/Tool/mslink.py b/src/engine/SCons/Tool/mslink.py index 1390c20..74c20d0 100644 --- a/src/engine/SCons/Tool/mslink.py +++ b/src/engine/SCons/Tool/mslink.py @@ -305,7 +305,7 @@ def generate(env): # if the manifest actually exists before trying to run mt with it. env['MTEXECOM'] = '-$MT $MTFLAGS -manifest ${TARGET}.manifest $_MANIFEST_SOURCES -outputresource:$TARGET;1' env['MTSHLIBCOM'] = '-$MT $MTFLAGS -manifest ${TARGET}.manifest $_MANIFEST_SOURCES -outputresource:$TARGET;2' - # Future work garyo 27-Feb-11 + # TODO Future work garyo 27-Feb-11 env['_MANIFEST_SOURCES'] = None # _windowsManifestSources # Set-up ms tools paths diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py index 355eeed..113f859 100644 --- a/src/engine/SCons/Tool/msvs.py +++ b/src/engine/SCons/Tool/msvs.py @@ -100,42 +100,6 @@ def msvs_parse_version(s): num, suite = version_re.match(s).groups() return float(num), suite -# os.path.relpath has been introduced in Python 2.6 -# We define it locally for earlier versions of Python -def relpath(path, start=os.path.curdir): - """Return a relative version of a path""" - import sys - if not path: - raise ValueError("no path specified") - start_list = os.path.abspath(start).split(os.sep) - path_list = os.path.abspath(path).split(os.sep) - if 'posix' in sys.builtin_module_names: - # Work out how much of the filepath is shared by start and path. - i = len(os.path.commonprefix([start_list, path_list])) - else: - if start_list[0].lower() != path_list[0].lower(): - unc_path, rest = os.path.splitunc(path) - unc_start, rest = os.path.splitunc(start) - if bool(unc_path) ^ bool(unc_start): - raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)" - % (path, start)) - else: - raise ValueError("path is on drive %s, start on drive %s" - % (path_list[0], start_list[0])) - # Work out how much of the filepath is shared by start and path. - for i in range(min(len(start_list), len(path_list))): - if start_list[i].lower() != path_list[i].lower(): - break - else: - i += 1 - rel_list = [os.pardir] * (len(start_list)-i) + path_list[i:] - if not rel_list: - return os.path.curdir - return os.path.join(*rel_list) - -if not "relpath" in os.path.__all__: - os.path.relpath = relpath - # This is how we re-invoke SCons from inside MSVS Project files. # The problem is that we might have been invoked as either scons.bat # or scons.py. If we were invoked directly as scons.py, then we could @@ -204,7 +168,7 @@ class _UserGenerator(object): Base class for .dsp.user file generator ''' # Default instance values. - # Ok ... a bit defensive, but it does not seems reasonable to crash the + # Ok ... a bit defensive, but it does not seem reasonable to crash the # build for a workspace user file. :-) usrhead = None usrdebg = None @@ -212,7 +176,7 @@ class _UserGenerator(object): createfile = False def __init__(self, dspfile, source, env): # DebugSettings should be a list of debug dictionary sorted in the same order - # than the target list and variants + # as the target list and variants if 'variant' not in env: raise SCons.Errors.InternalError("You must specify a 'variant' argument (i.e. 'Debug' or " +\ "'Release') to create an MSVSProject.") @@ -543,9 +507,7 @@ class _DSPGenerator(object): self.sources[t[0]].append(self.env[t[1]]) for n in sourcenames: - #TODO 2.4: compat layer supports sorted(key=) but not sort(key=) - #TODO 2.4: self.sources[n].sort(key=lambda a: a.lower()) - self.sources[n] = sorted(self.sources[n], key=lambda a: a.lower()) + self.sources[n].sort(key=lambda a: a.lower()) def AddConfig(self, variant, buildtarget, outdir, runfile, cmdargs, dspfile=dspfile): config = Config() diff --git a/src/engine/SCons/Tool/packaging/__init__.py b/src/engine/SCons/Tool/packaging/__init__.py index 1a979ab..0f9a93d 100644 --- a/src/engine/SCons/Tool/packaging/__init__.py +++ b/src/engine/SCons/Tool/packaging/__init__.py @@ -77,7 +77,6 @@ def Tag(env, target, source, *more_tags, **kw_tags): # differentiate between "normal" object attributes and the # packaging attributes. As the user should not be bothered with # that, the prefix will be added here if missing. - #if not k.startswith('PACKAGING_'): if k[:10] != 'PACKAGING_': k='PACKAGING_'+k t.Tag(k, v) @@ -175,7 +174,7 @@ def Package(env, target=None, source=None, **kw): args=[x for x in args if x not in kw] if len(args)==0: - raise # must be a different error, so reraise + raise # must be a different error, so re-raise elif len(args)==1: raise SCons.Errors.UserError( "Missing Packagetag '%s' for %s packager"\ % (args[0],packager.__name__) ) @@ -232,8 +231,6 @@ def options(opts): def copy_attr(f1, f2): """ copies the special packaging file attributes from f1 to f2. """ - #pattrs = [x for x in dir(f1) if not hasattr(f2, x) and\ - # x.startswith('PACKAGING_')] copyit = lambda x: not hasattr(f2, x) and x[:10] == 'PACKAGING_' if f1._tags: pattrs = list(filter(copyit, f1._tags)) @@ -278,7 +275,7 @@ def putintopackageroot(target, source, env, pkgroot, honor_install_location=1): return (target, new_source) def stripinstallbuilder(target, source, env): - """ strips the install builder action from the source list and stores + """ Strips the install builder action from the source list and stores the final installation location as the "PACKAGING_INSTALL_LOCATION" of the source of the source file. This effectively removes the final installed files from the source list while remembering the installation location. diff --git a/src/engine/SCons/Tool/packaging/ipk.py b/src/engine/SCons/Tool/packaging/ipk.py index 84f4e20..c666033 100644 --- a/src/engine/SCons/Tool/packaging/ipk.py +++ b/src/engine/SCons/Tool/packaging/ipk.py @@ -35,7 +35,7 @@ from SCons.Tool.packaging import stripinstallbuilder, putintopackageroot def package(env, target, source, PACKAGEROOT, NAME, VERSION, DESCRIPTION, SUMMARY, X_IPK_PRIORITY, X_IPK_SECTION, SOURCE_URL, X_IPK_MAINTAINER, X_IPK_DEPENDS, **kw): - """ this function prepares the packageroot directory for packaging with the + """ This function prepares the packageroot directory for packaging with the ipkg builder. """ SCons.Tool.Tool('ipkg').generate(env) @@ -45,7 +45,7 @@ def package(env, target, source, PACKAGEROOT, NAME, VERSION, DESCRIPTION, target, source = stripinstallbuilder(target, source, env) target, source = putintopackageroot(target, source, env, PACKAGEROOT) - # This should be overridable from the construction environment, + # This should be overrideable from the construction environment, # which it is by using ARCHITECTURE=. # Guessing based on what os.uname() returns at least allows it # to work for both i386 and x86_64 Linux systems. @@ -61,7 +61,7 @@ def package(env, target, source, PACKAGEROOT, NAME, VERSION, DESCRIPTION, if 'ARCHITECTURE' in kw: buildarchitecture = kw['ARCHITECTURE'] - # setup the kw to contain the mandatory arguments to this fucntion. + # setup the kw to contain the mandatory arguments to this function. # do this before calling any builder or setup function loc=locals() del loc['kw'] @@ -104,7 +104,7 @@ def gen_ipk_dir(proot, source, env, kw): return proot def build_specfiles(source, target, env): - """ filter the targets for the needed files and use the variables in env + """ Filter the targets for the needed files and use the variables in env to create the specfile. """ # diff --git a/src/engine/SCons/Tool/packaging/msi.py b/src/engine/SCons/Tool/packaging/msi.py index 172038f..41b7ab7 100644 --- a/src/engine/SCons/Tool/packaging/msi.py +++ b/src/engine/SCons/Tool/packaging/msi.py @@ -70,7 +70,7 @@ def convert_to_id(s, id_set): try: return id_set[id][s] except KeyError: - # no we did not so initialize with the id + # no we did not, so initialize with the id if id not in id_set: id_set[id] = { s : id } # there is a collision, generate an id which is unique by appending # the collision number @@ -79,7 +79,7 @@ def convert_to_id(s, id_set): return id_set[id][s] def is_dos_short_file_name(file): - """ examine if the given file is in the 8.3 form. + """ Examine if the given file is in the 8.3 form. """ fname, ext = os.path.splitext(file) proper_ext = len(ext) == 0 or (2 <= len(ext) <= 4) # the ext contains the dot @@ -88,7 +88,7 @@ def is_dos_short_file_name(file): return proper_ext and proper_fname def gen_dos_short_file_name(file, filename_set): - """ see http://support.microsoft.com/default.aspx?scid=kb;en-us;Q142982 + """ See http://support.microsoft.com/default.aspx?scid=kb;en-us;Q142982 These are no complete 8.3 dos short names. The ~ char is missing and replaced with one character from the filename. WiX warns about such @@ -186,7 +186,7 @@ def string_wxsfile(target, source, env): return "building WiX file %s"%( target[0].path ) def build_wxsfile(target, source, env): - """ compiles a .wxs file from the keywords given in env['msi_spec'] and + """ Compiles a .wxs file from the keywords given in env['msi_spec'] and by analyzing the tree of source nodes and their tags. """ file = open(target[0].get_abspath(), 'w') @@ -268,7 +268,7 @@ def create_default_directory_layout(root, NAME, VERSION, VENDOR, filename_set): # mandatory and optional file tags # def build_wxsfile_file_section(root, files, NAME, VERSION, VENDOR, filename_set, id_set): - """ builds the Component sections of the wxs file with their included files. + """ Builds the Component sections of the wxs file with their included files. Files need to be specified in 8.3 format and in the long name format, long filenames will be converted automatically. @@ -280,7 +280,7 @@ def build_wxsfile_file_section(root, files, NAME, VERSION, VENDOR, filename_set, factory = Document() def get_directory( node, dir ): - """ returns the node under the given node representing the directory. + """ Returns the node under the given node representing the directory. Returns the component node if dir is None or empty. """ @@ -415,7 +415,7 @@ def build_wxsfile_features_section(root, files, NAME, VERSION, SUMMARY, id_set): root.getElementsByTagName('Product')[0].childNodes.append(Feature) def build_wxsfile_default_gui(root): - """ this function adds a default GUI to the wxs file + """ This function adds a default GUI to the wxs file """ factory = Document() Product = root.getElementsByTagName('Product')[0] @@ -429,7 +429,7 @@ def build_wxsfile_default_gui(root): Product.childNodes.append(UIRef) def build_license_file(directory, spec): - """ creates a License.rtf file with the content of "X_MSI_LICENSE_TEXT" + """ Creates a License.rtf file with the content of "X_MSI_LICENSE_TEXT" in the given directory """ name, text = '', '' diff --git a/src/engine/SCons/Tool/packaging/rpm.py b/src/engine/SCons/Tool/packaging/rpm.py index 92977d0..0750113 100644 --- a/src/engine/SCons/Tool/packaging/rpm.py +++ b/src/engine/SCons/Tool/packaging/rpm.py @@ -72,7 +72,6 @@ def package(env, target, source, PACKAGEROOT, NAME, VERSION, # if no "SOURCE_URL" tag is given add a default one. if 'SOURCE_URL' not in kw: - #kw['SOURCE_URL']=(str(target[0])+".tar.gz").replace('.rpm', '') kw['SOURCE_URL']=(str(target[0])+".tar.gz").replace('.rpm', '') # mangle the source and target list for the rpmbuild @@ -86,26 +85,21 @@ def package(env, target, source, PACKAGEROOT, NAME, VERSION, def collectintargz(target, source, env): """ Puts all source files into a tar.gz file. """ - # the rpm tool depends on a source package, until this is chagned + # the rpm tool depends on a source package, until this is changed # this hack needs to be here that tries to pack all sources in. sources = env.FindSourceFiles() # filter out the target we are building the source list for. - #sources = [s for s in sources if not (s in target)] sources = [s for s in sources if s not in target] # find the .spec file for rpm and add it since it is not necessarily found # by the FindSourceFiles function. - #sources.extend( [s for s in source if str(s).rfind('.spec')!=-1] ) - spec_file = lambda s: str(s).rfind('.spec') != -1 - sources.extend( list(filter(spec_file, source)) ) + sources.extend( [s for s in source if str(s).rfind('.spec')!=-1] ) # as the source contains the url of the source package this rpm package # is built from, we extract the target name - #tarball = (str(target[0])+".tar.gz").replace('.rpm', '') tarball = (str(target[0])+".tar.gz").replace('.rpm', '') try: - #tarball = env['SOURCE_URL'].split('/')[-1] tarball = env['SOURCE_URL'].split('/')[-1] except KeyError, e: raise SCons.Errors.UserError( "Missing PackageTag '%s' for RPM packager" % e.args[0] ) @@ -194,7 +188,7 @@ def build_specfile_sections(spec): return str def build_specfile_header(spec): - """ Builds all section but the %file of a rpm specfile + """ Builds all sections but the %file of a rpm specfile """ str = "" @@ -312,11 +306,10 @@ class SimpleTagCompiler(object): self.mandatory = mandatory def compile(self, values): - """ compiles the tagset and returns a str containing the result + """ Compiles the tagset and returns a str containing the result """ def is_international(tag): - #return tag.endswith('_') - return tag[-1:] == '_' + return tag.endswith('_') def get_country_code(tag): return tag[-2:] @@ -327,7 +320,6 @@ class SimpleTagCompiler(object): replacements = list(self.tagset.items()) str = "" - #domestic = [ (k,v) for k,v in replacements if not is_international(k) ] domestic = [t for t in replacements if not is_international(t[0])] for key, replacement in domestic: try: @@ -336,11 +328,9 @@ class SimpleTagCompiler(object): if self.mandatory: raise e - #international = [ (k,v) for k,v in replacements if is_international(k) ] international = [t for t in replacements if is_international(t[0])] for key, replacement in international: try: - #int_values_for_key = [ (get_country_code(k),v) for k,v in values.items() if strip_country_code(k) == key ] x = [t for t in values.items() if strip_country_code(t[0]) == key] int_values_for_key = [(get_country_code(t[0]),t[1]) for t in x] for v in int_values_for_key: diff --git a/src/engine/SCons/Tool/sunar.py b/src/engine/SCons/Tool/sunar.py index eb58457..ec076c8 100644 --- a/src/engine/SCons/Tool/sunar.py +++ b/src/engine/SCons/Tool/sunar.py @@ -2,7 +2,7 @@ Tool-specific initialization for Solaris (Forte) ar (library archive). If CC exists, static libraries should be built with it, so that template -instantians can be resolved. +instantiations can be resolved. There normally shouldn't be any need to import this module directly. It will usually be imported through the generic SCons.Tool.Tool() diff --git a/src/engine/SCons/Tool/tex.py b/src/engine/SCons/Tool/tex.py index 053d85d..3d429c9 100644 --- a/src/engine/SCons/Tool/tex.py +++ b/src/engine/SCons/Tool/tex.py @@ -700,12 +700,6 @@ def tex_emitter_core(target, source, env, graphics_extensions): content = source[0].get_text_contents() - # These variables are no longer used. - #idx_exists = os.path.isfile(targetbase + '.idx') - #nlo_exists = os.path.isfile(targetbase + '.nlo') - #glo_exists = os.path.isfile(targetbase + '.glo') - #acr_exists = os.path.isfile(targetbase + '.acn') - # set up list with the regular expressions # we use to find features used file_tests_search = [auxfile_re, diff --git a/src/engine/SCons/Tool/textfile.py b/src/engine/SCons/Tool/textfile.py index 8dc8f4b..76efbd7 100644 --- a/src/engine/SCons/Tool/textfile.py +++ b/src/engine/SCons/Tool/textfile.py @@ -40,8 +40,8 @@ Textfile/Substfile builder for SCons. expanded (its keys are not expanded). If a value of SUBST_DICT is a python callable function, it is called and the result is expanded as the value. Values are substituted in a "random" order; if any - substitution could be further expanded by another subsitition, it - is unpredictible whether the expansion will occur. + substitution could be further expanded by another substitution, it + is unpredictable whether the expansion will occur. """ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/src/engine/SCons/Tool/xgettext.py b/src/engine/SCons/Tool/xgettext.py index 64436b8..b8a88dc 100644 --- a/src/engine/SCons/Tool/xgettext.py +++ b/src/engine/SCons/Tool/xgettext.py @@ -76,7 +76,7 @@ def _update_pot_file(target, source, env): nop = lambda target, source, env : 0 # Save scons cwd and os cwd (NOTE: they may be different. After the job, we - # revert ech one to its original state). + # revert each one to its original state). save_cwd = env.fs.getcwd() save_os_cwd = os.getcwd() chdir = target[0].dir @@ -134,7 +134,7 @@ def _update_pot_file(target, source, env): explain = "new file" if needs_update: # Print message employing SCons.Action.Action for that. - msg = "Writting " + repr(str(target[0])) + " (" + explain + ")" + msg = "Writing " + repr(str(target[0])) + " (" + explain + ")" env.Execute(SCons.Action.Action(nop, msg)) f = open(str(target[0]),"w") f.write(new_content) @@ -142,7 +142,7 @@ def _update_pot_file(target, source, env): return 0 else: # Print message employing SCons.Action.Action for that. - msg = "Not writting " + repr(str(target[0])) + " (" + explain + ")" + msg = "Not writing " + repr(str(target[0])) + " (" + explain + ")" env.Execute(SCons.Action.Action(nop, msg)) return 0 ############################################################################# diff --git a/src/engine/SCons/Tool/yacc.py b/src/engine/SCons/Tool/yacc.py index 5896cbe..648433b 100644 --- a/src/engine/SCons/Tool/yacc.py +++ b/src/engine/SCons/Tool/yacc.py @@ -61,7 +61,7 @@ def _yaccEmitter(target, source, env, ysuf, hsuf): base, ext = os.path.splitext(SCons.Util.to_String(source[0])) target.append(base + env.subst("$YACCVCGFILESUFFIX")) - # If -v is specirfied yacc will create the output debug file + # If -v is specified yacc will create the output debug file # which is not really source for any process, but should # be noted and also be cleaned # Bug #2558 @@ -118,14 +118,6 @@ def generate(env): env['YACCCOM'] = '$YACC $YACCFLAGS -o $TARGET $SOURCES' env['YACCHFILESUFFIX'] = '.h' - # Apparently, OS X now creates file.hpp like everybody else - # I have no idea when it changed; it was fixed in 10.4 - #if env['PLATFORM'] == 'darwin': - # # Bison on Mac OS X just appends ".h" to the generated target .cc - # # or .cpp file name. Hooray for delayed expansion of variables. - # env['YACCHXXFILESUFFIX'] = '${TARGET.suffix}.h' - #else: - # env['YACCHXXFILESUFFIX'] = '.hpp' env['YACCHXXFILESUFFIX'] = '.hpp' env['YACCVCGFILESUFFIX'] = '.vcg' diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 4890ba2..a834726 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -92,7 +92,7 @@ def splitext(path): def updrive(path): """ Make the drive letter (if any) upper case. - This is useful because Windows is inconsitent on the case + This is useful because Windows is inconsistent on the case of the drive letter, which can cause inconsistencies when calculating command signatures. """ @@ -207,7 +207,7 @@ def render_tree(root, child_func, prune=0, margin=[0], visited={}): IDX = lambda N: N and 1 or 0 -def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited={}): +def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited=None): """ Print a tree of nodes. This is like render_tree, except it prints lines directly instead of creating a string representation in memory, @@ -224,6 +224,10 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited={}): """ rname = str(root) + + # Initialize 'visited' dict, if required + if visited is None: + visited = {} if showtags: @@ -291,7 +295,7 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited={}): # often too slow. # We are using the following trick to speed up these -# functions. Default arguments are used to take a snapshot of the +# functions. Default arguments are used to take a snapshot of # the global functions and constants used by these functions. This # transforms accesses to global variable into local variables # accesses (i.e. LOAD_FAST instead of LOAD_GLOBAL). @@ -301,11 +305,11 @@ ListTypes = (list, UserList) SequenceTypes = (list, tuple, UserList) # Note that profiling data shows a speed-up when comparing -# explicitely with str and unicode instead of simply comparing +# explicitly with str and unicode instead of simply comparing # with basestring. (at least on Python 2.5.1) StringTypes = (str, unicode, UserString) -# Empirically, it is faster to check explicitely for str and +# Empirically, it is faster to check explicitly for str and # unicode than for basestring. BaseStringTypes = (str, unicode) @@ -326,11 +330,11 @@ def is_String(obj, isinstance=isinstance, StringTypes=StringTypes): def is_Scalar(obj, isinstance=isinstance, StringTypes=StringTypes, SequenceTypes=SequenceTypes): # Profiling shows that there is an impressive speed-up of 2x - # when explicitely checking for strings instead of just not + # when explicitly checking for strings instead of just not # sequence when the argument (i.e. obj) is already a string. # But, if obj is a not string then it is twice as fast to # check only for 'not sequence'. The following code therefore - # assumes that the obj argument is a string must of the time. + # assumes that the obj argument is a string most of the time. return isinstance(obj, StringTypes) or not isinstance(obj, SequenceTypes) def do_flatten(sequence, result, isinstance=isinstance, @@ -431,7 +435,7 @@ def to_String_for_signature(obj, to_String_for_subst=to_String_for_subst, # # A special case is any object that has a __semi_deepcopy__() method, # which we invoke to create the copy. Currently only used by -# BuilderDict to actually prevent the copy operation (as invalid on that object) +# BuilderDict to actually prevent the copy operation (as invalid on that object). # # The dispatch table approach used here is a direct rip-off from the # normal Python copy module. @@ -571,6 +575,15 @@ except ImportError: pass RegError = _NoError +WinError = None +# Make sure we have a definition of WindowsError so we can +# run platform-independent tests of Windows functionality on +# platforms other than Windows. (WindowsError is, in fact, an +# OSError subclass on Windows.) +class PlainWindowsError(OSError): + pass + + if can_read_reg: HKEY_CLASSES_ROOT = hkey_mod.HKEY_CLASSES_ROOT HKEY_LOCAL_MACHINE = hkey_mod.HKEY_LOCAL_MACHINE @@ -605,18 +618,9 @@ if can_read_reg: return RegQueryValueEx(k,val) else: try: - e = WindowsError + WinError = WindowsError except NameError: - # Make sure we have a definition of WindowsError so we can - # run platform-independent tests of Windows functionality on - # platforms other than Windows. (WindowsError is, in fact, an - # OSError subclass on Windows.) - class WindowsError(OSError): - pass - import builtins - builtins.WindowsError = WindowsError - else: - del e + WinError = PlainWindowsError HKEY_CLASSES_ROOT = None HKEY_LOCAL_MACHINE = None @@ -624,10 +628,10 @@ else: HKEY_USERS = None def RegGetValue(root, key): - raise WindowsError + raise WinError def RegOpenKeyEx(root, key): - raise WindowsError + raise WinError if sys.platform == 'win32': @@ -889,6 +893,28 @@ def AppendPath(oldpath, newpath, sep = os.pathsep, else: return sep.join(paths) +def AddPathIfNotExists(env_dict, key, path, sep=os.pathsep): + """This function will take 'key' out of the dictionary + 'env_dict', then add the path 'path' to that key if it is not + already there. This treats the value of env_dict[key] as if it + has a similar format to the PATH variable...a list of paths + separated by tokens. The 'path' will get added to the list if it + is not already there.""" + try: + is_list = 1 + paths = env_dict[key] + if not is_List(env_dict[key]): + paths = paths.split(sep) + is_list = 0 + if os.path.normcase(path) not in list(map(os.path.normcase, paths)): + paths = [ path ] + paths + if is_list: + env_dict[key] = paths + else: + env_dict[key] = sep.join(paths) + except KeyError: + env_dict[key] = path + if sys.platform == 'cygwin': def get_native_path(path): """Transforms an absolute path into a native path for the system. In @@ -1156,38 +1182,40 @@ def uniquer_hashables(seq): return result +# Recipe 19.11 "Reading Lines with Continuation Characters", +# by Alex Martelli, straight from the Python CookBook (2nd edition). +def logical_lines(physical_lines, joiner=''.join): + logical_line = [] + for line in physical_lines: + stripped = line.rstrip() + if stripped.endswith('\\'): + # a line which continues w/the next physical line + logical_line.append(stripped[:-1]) + else: + # a line which does not continue, end of logical line + logical_line.append(line) + yield joiner(logical_line) + logical_line = [] + if logical_line: + # end of sequence implies end of last logical line + yield joiner(logical_line) -# Much of the logic here was originally based on recipe 4.9 from the -# Python CookBook, but we had to dumb it way down for Python 1.5.2. -class LogicalLines(object): +class LogicalLines(object): + """ Wrapper class for the logical_lines method. + + Allows us to read all "logical" lines at once from a + given file object. + """ + def __init__(self, fileobj): self.fileobj = fileobj - def readline(self): - result = [] - while True: - line = self.fileobj.readline() - if not line: - break - if line[-2:] == '\\\n': - result.append(line[:-2]) - else: - result.append(line) - break - return ''.join(result) - def readlines(self): - result = [] - while True: - line = self.readline() - if not line: - break - result.append(line) + result = [l for l in logical_lines(self.fileobj)] return result - class UniqueList(UserList): def __init__(self, seq = []): UserList.__init__(self, seq) diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py index 795bc46..d59d40c 100644 --- a/src/engine/SCons/UtilTests.py +++ b/src/engine/SCons/UtilTests.py @@ -190,16 +190,7 @@ class UtilTestCase(unittest.TestCase): assert expect == actual, (expect, actual) sys.stdout = io.StringIO() - # The following call should work here: - # print_tree(node, get_children, 1, showtags=1) - # For some reason I don't understand, though, *this* - # time that we call print_tree, the visited dictionary - # is still populated with the values from the last call! - # I can't see why this would be, short of a bug in Python, - # and rather than continue banging my head against the - # brick wall for a *test*, we're going to going with - # the cheap, easy workaround: - print_tree(node, get_children, 1, showtags=1, visited={}) + print_tree(node, get_children, 1, showtags=1) actual = sys.stdout.getvalue() assert withtags == actual, (withtags, actual) finally: @@ -487,6 +478,30 @@ class UtilTestCase(unittest.TestCase): p1 = AppendPath(p1,r'C:\dir\num\three',sep = ';') assert(p1 == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three') + def test_addPathIfNotExists(self): + """Test the AddPathIfNotExists() function""" + env_dict = { 'FOO' : os.path.normpath('/foo/bar') + os.pathsep + \ + os.path.normpath('/baz/blat'), + 'BAR' : os.path.normpath('/foo/bar') + os.pathsep + \ + os.path.normpath('/baz/blat'), + 'BLAT' : [ os.path.normpath('/foo/bar'), + os.path.normpath('/baz/blat') ] } + AddPathIfNotExists(env_dict, 'FOO', os.path.normpath('/foo/bar')) + AddPathIfNotExists(env_dict, 'BAR', os.path.normpath('/bar/foo')) + AddPathIfNotExists(env_dict, 'BAZ', os.path.normpath('/foo/baz')) + AddPathIfNotExists(env_dict, 'BLAT', os.path.normpath('/baz/blat')) + AddPathIfNotExists(env_dict, 'BLAT', os.path.normpath('/baz/foo')) + + assert env_dict['FOO'] == os.path.normpath('/foo/bar') + os.pathsep + \ + os.path.normpath('/baz/blat'), env_dict['FOO'] + assert env_dict['BAR'] == os.path.normpath('/bar/foo') + os.pathsep + \ + os.path.normpath('/foo/bar') + os.pathsep + \ + os.path.normpath('/baz/blat'), env_dict['BAR'] + assert env_dict['BAZ'] == os.path.normpath('/foo/baz'), env_dict['BAZ'] + assert env_dict['BLAT'] == [ os.path.normpath('/baz/foo'), + os.path.normpath('/foo/bar'), + os.path.normpath('/baz/blat') ], env_dict['BLAT' ] + def test_CLVar(self): """Test the command-line construction variable class""" f = SCons.Util.CLVar('a b') @@ -679,11 +694,8 @@ bling \ bling \ bling bling """ - try: - fobj = io.StringIO(content) - except TypeError: - # Python 2.7 and beyond require unicode strings. - fobj = io.StringIO(unicode(content)) + # Python 2.7 and beyond require unicode strings. + fobj = io.StringIO(unicode(content)) lines = LogicalLines(fobj).readlines() assert lines == [ @@ -780,6 +792,7 @@ class flattenTestCase(unittest.TestCase): result = flatten('xyz') assert result == ['xyz'], result + if __name__ == "__main__": suite = unittest.TestSuite() tclasses = [ dictifyTestCase, diff --git a/src/engine/SCons/Variables/BoolVariable.py b/src/engine/SCons/Variables/BoolVariable.py index 6bc66bb..c005a62 100644 --- a/src/engine/SCons/Variables/BoolVariable.py +++ b/src/engine/SCons/Variables/BoolVariable.py @@ -51,7 +51,7 @@ def _text2bool(val): will be returned. See '__true_strings' and '__false_strings' for values considered - 'true' or 'false respectivly. + 'true' or 'false respectively. This is usable as 'converter' for SCons' Variables. """ @@ -74,7 +74,7 @@ def _validator(key, val, env): def BoolVariable(key, help, default): """ - The input parameters describe a boolen option, thus they are + The input parameters describe a boolean option, thus they are returned with the correct converter and validator appended. The 'help' text will by appended by '(yes|no) to show the valid valued. The result is usable for input to opts.Add(). diff --git a/src/engine/SCons/Variables/EnumVariable.py b/src/engine/SCons/Variables/EnumVariable.py index 582be27..9448ba9 100644 --- a/src/engine/SCons/Variables/EnumVariable.py +++ b/src/engine/SCons/Variables/EnumVariable.py @@ -52,7 +52,7 @@ def _validator(key, val, env, vals): def EnumVariable(key, help, default, allowed_values, map={}, ignorecase=0): """ - The input parameters describe a option with only certain values + The input parameters describe an option with only certain values allowed. They are returned with an appropriate converter and validator appended. The result is usable for input to Variables.Add(). @@ -65,7 +65,7 @@ def EnumVariable(key, help, default, allowed_values, map={}, ignorecase=0): for this option. The 'map'-dictionary may be used for converting the input value - into canonical values (eg. for aliases). + into canonical values (e.g. for aliases). 'ignorecase' defines the behaviour of the validator: diff --git a/src/engine/SCons/Variables/ListVariable.py b/src/engine/SCons/Variables/ListVariable.py index 413aacb..f2fdc18 100644 --- a/src/engine/SCons/Variables/ListVariable.py +++ b/src/engine/SCons/Variables/ListVariable.py @@ -4,7 +4,7 @@ This file defines the option type for SCons implementing 'lists'. A 'list' option may either be 'all', 'none' or a list of names separated by comma. After the option has been processed, the option -value holds either the named list elements, all list elemens or no +value holds either the named list elements, all list elements or no list elements at all. Usage example: @@ -48,7 +48,7 @@ Usage example: __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -# Know Bug: This should behave like a Set-Type, but does not really, +# Known Bug: This should behave like a Set-Type, but does not really, # since elements can occur twice. __all__ = ['ListVariable',] @@ -106,14 +106,14 @@ def _converter(val, allowedElems, mapdict): ## def _validator(key, val, env): ## """ ## """ -## # todo: write validater for pgk list +## # todo: write validator for pgk list ## return 1 def ListVariable(key, help, default, names, map={}): """ The input parameters describe a 'package list' option, thus they - are returned with the correct converter and validater appended. The + are returned with the correct converter and validator appended. The result is usable for input to opts.Add() . A 'package list' option may either be 'all', 'none' or a list of diff --git a/src/engine/SCons/Variables/PackageVariable.py b/src/engine/SCons/Variables/PackageVariable.py index 440d0f6..4ab0856 100644 --- a/src/engine/SCons/Variables/PackageVariable.py +++ b/src/engine/SCons/Variables/PackageVariable.py @@ -11,7 +11,7 @@ Usage example: Examples: x11=no (disables X11 support) x11=yes (will search for the package installation dir) - x11=/usr/local/X11 (will check this path for existance) + x11=/usr/local/X11 (will check this path for existence) To replace autoconf's --with-xxx=yyy @@ -70,10 +70,10 @@ def _converter(val): def _validator(key, val, env, searchfunc): - # NB: searchfunc is currenty undocumented and unsupported + # NB: searchfunc is currently undocumented and unsupported """ """ - # todo: write validator, check for path + # TODO write validator, check for path import os if env[key] is True: if searchfunc: @@ -84,14 +84,14 @@ def _validator(key, val, env, searchfunc): def PackageVariable(key, help, default, searchfunc=None): - # NB: searchfunc is currenty undocumented and unsupported + # NB: searchfunc is currently undocumented and unsupported """ The input parameters describe a 'package list' option, thus they are returned with the correct converter and validator appended. The result is usable for input to opts.Add() . A 'package list' option may either be 'all', 'none' or a list of - package names (seperated by space). + package names (separated by space). """ help = '\n '.join( (help, '( yes | no | /path/to/%s )' % key)) diff --git a/src/engine/SCons/Variables/PathVariable.py b/src/engine/SCons/Variables/PathVariable.py index 951fc75..e615a53 100644 --- a/src/engine/SCons/Variables/PathVariable.py +++ b/src/engine/SCons/Variables/PathVariable.py @@ -2,7 +2,7 @@ This file defines an option type for SCons implementing path settings. -To be used whenever a a user-specified path override should be allowed. +To be used whenever a user-specified path override should be allowed. Arguments to PathVariable are: option-name = name of this option on the command line (e.g. "prefix") @@ -22,7 +22,7 @@ Arguments to PathVariable are: is valid. The arguments to the validator function are: (key, val, env). The key is the name of the option, the val is the path specified for the option, - and the env is the env to which the Otions have been + and the env is the env to which the Options have been added. Usage example: @@ -102,7 +102,7 @@ class _PathVariableClass(object): os.makedirs(val) def PathIsFile(self, key, val, env): - """validator to check if Path is a file""" + """Validator to check if Path is a file""" if not os.path.isfile(val): if os.path.isdir(val): m = 'File path for option %s is a directory: %s' @@ -111,13 +111,12 @@ class _PathVariableClass(object): raise SCons.Errors.UserError(m % (key, val)) def PathExists(self, key, val, env): - """validator to check if Path exists""" + """Validator to check if Path exists""" if not os.path.exists(val): m = 'Path for option %s does not exist: %s' raise SCons.Errors.UserError(m % (key, val)) def __call__(self, key, help, default, validator=None): - # NB: searchfunc is currenty undocumented and unsupported """ The input parameters describe a 'path list' option, thus they are returned with the correct converter and validator appended. The diff --git a/src/engine/SCons/Variables/__init__.py b/src/engine/SCons/Variables/__init__.py index ede7480..10f9cb2 100644 --- a/src/engine/SCons/Variables/__init__.py +++ b/src/engine/SCons/Variables/__init__.py @@ -50,12 +50,17 @@ class Variables(object): Holds all the options, updates the environment with the variables, and renders the help text. """ - def __init__(self, files=[], args={}, is_global=1): + def __init__(self, files=None, args=None, is_global=1): """ files - [optional] List of option configuration files to load (backward compatibility) If a single string is passed it is automatically placed in a file list """ + # initialize arguments + if files is None: + files = [] + if args is None: + args = {} self.options = [] self.args = args if not SCons.Util.is_List(files): diff --git a/src/engine/SCons/compat/__init__.py b/src/engine/SCons/compat/__init__.py index 3d5c835..5f94df2 100644 --- a/src/engine/SCons/compat/__init__.py +++ b/src/engine/SCons/compat/__init__.py @@ -35,9 +35,6 @@ the builtins namespace or the global module list so that the rest of our code can use the objects and names imported here regardless of Python version. -Simply enough, things that go in the builtins name space come from -our _scons_builtins module. - The rest of the things here will be in individual compatibility modules that are either: 1) suitably modified copies of the future modules that we want to use; or 2) backwards compatible re-implementations of the @@ -85,34 +82,8 @@ def rename_module(new, old): except ImportError: return False - -rename_module('builtins', '__builtin__') -import _scons_builtins - - -try: - import hashlib -except ImportError: - # Pre-2.5 Python has no hashlib module. - try: - import_as('_scons_hashlib', 'hashlib') - except ImportError: - # If we failed importing our compatibility module, it probably - # means this version of Python has no md5 module. Don't do - # anything and let the higher layer discover this fact, so it - # can fall back to using timestamp. - pass - - - -# When we're using the '-3' option during regression tests, importing -# cPickle gives a warning no matter how it's done, so always use the -# real profile module, whether it's fast or not. -if os.environ.get('SCONS_HORRIBLE_REGRESSION_TEST_HACK') is None: - # Not a regression test with '-3', so try to use faster version. - # In 3.x, 'pickle' automatically loads the fast version if available. - rename_module('pickle', 'cPickle') - +# In 3.x, 'pickle' automatically loads the fast version if available. +rename_module('pickle', 'cPickle') # In 3.x, 'profile' automatically loads the fast version if available. rename_module('profile', 'cProfile') @@ -134,9 +105,7 @@ try: except AttributeError: # We must be using python 2.7.x so monkey patch # intern into the sys package - import builtins - sys.intern = builtins.intern - + sys.intern = intern # Preparing for 3.x. UserDict, UserList, UserString are in @@ -163,25 +132,6 @@ except AttributeError: collections.UserString = _UserString del _UserString - - -if os.environ.get('SCONS_HORRIBLE_REGRESSION_TEST_HACK') is not None: - # We can't apply the 'callable' fixer until the floor is 2.6, but the - # '-3' option to Python 2.6 and 2.7 generates almost ten thousand - # warnings. This hack allows us to run regression tests with the '-3' - # option by replacing the callable() built-in function with a hack - # that performs the same function but doesn't generate the warning. - # Note that this hack is ONLY intended to be used for regression - # testing, and should NEVER be used for real runs. - from types import ClassType - def callable(obj): - if hasattr(obj, '__call__'): return True - if isinstance(obj, (ClassType, type)): return True - return False - import builtins - builtins.callable = callable - del callable - # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/compat/_scons_builtins.py b/src/engine/SCons/compat/_scons_builtins.py deleted file mode 100644 index 6218cd1..0000000 --- a/src/engine/SCons/compat/_scons_builtins.py +++ /dev/null @@ -1,107 +0,0 @@ -# -# __COPYRIGHT__ -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# 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. -# - -# Portions of the following are derived from the compat.py file in -# Twisted, under the following copyright: -# -# Copyright (c) 2001-2004 Twisted Matrix Laboratories - -__doc__ = """ -Compatibility idioms for builtins names - -This module adds names to the builtins module for things that we want -to use in SCons but which don't show up until later Python versions than -the earliest ones we support. - -This module checks for the following builtins names: - - all() - any() - memoryview() - -Implementations of functions are *NOT* guaranteed to be fully compliant -with these functions in later versions of Python. We are only concerned -with adding functionality that we actually use in SCons, so be wary -if you lift this code for other uses. (That said, making these more -nearly the same as later, official versions is still a desirable goal, -we just don't need to be obsessive about it.) - -If you're looking at this with pydoc and various names don't show up in -the FUNCTIONS or DATA output, that means those names are already built in -to this version of Python and we don't need to add them from this module. -""" - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -import builtins - -try: - all -except NameError: - # Pre-2.5 Python has no all() function. - def all(iterable): - """ - Returns True if all elements of the iterable are true. - """ - for element in iterable: - if not element: - return False - return True - builtins.all = all - all = all - -try: - any -except NameError: - # Pre-2.5 Python has no any() function. - def any(iterable): - """ - Returns True if any element of the iterable is true. - """ - for element in iterable: - if element: - return True - return False - builtins.any = any - any = any - -try: - memoryview -except NameError: - # Pre-2.7 doesn't have the memoryview() built-in. - class memoryview(object): - def __init__(self, obj): - # wrapping buffer in () keeps the fixer from changing it - self.obj = (buffer)(obj) - def __getitem__(self, indx): - if isinstance(indx, slice): - return self.obj[indx.start:indx.stop] - else: - return self.obj[indx] - builtins.memoryview = memoryview - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/compat/_scons_hashlib.py b/src/engine/SCons/compat/_scons_hashlib.py deleted file mode 100644 index 04d31fa..0000000 --- a/src/engine/SCons/compat/_scons_hashlib.py +++ /dev/null @@ -1,76 +0,0 @@ -# -# __COPYRIGHT__ -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# 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. -# - -__doc__ = """ -hashlib backwards-compatibility module for older (pre-2.5) Python versions - -This does not not NOT (repeat, *NOT*) provide complete hashlib -functionality. It only wraps the portions of MD5 functionality used -by SCons, in an interface that looks like hashlib (or enough for our -purposes, anyway). In fact, this module will raise an ImportError if -the underlying md5 module isn't available. -""" - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -import md5 -from string import hexdigits - -class md5obj(object): - - md5_module = md5 - - def __init__(self, name, string=''): - if not name in ('MD5', 'md5'): - raise ValueError("unsupported hash type") - self.name = 'md5' - self.m = self.md5_module.md5() - - def __repr__(self): - return '<%s HASH object @ %#x>' % (self.name, id(self)) - - def copy(self): - import copy - result = copy.copy(self) - result.m = self.m.copy() - return result - - def digest(self): - return self.m.digest() - - def update(self, arg): - return self.m.update(arg) - - def hexdigest(self): - return self.m.hexdigest() - -new = md5obj - -def md5(string=''): - return md5obj('md5', string) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/cppTests.py b/src/engine/SCons/cppTests.py index 37b4aae..9f4b875 100644 --- a/src/engine/SCons/cppTests.py +++ b/src/engine/SCons/cppTests.py @@ -668,15 +668,12 @@ class fileTestCase(unittest.TestCase): _Cleanup.remove(self.tempdir) def strip_initial_spaces(self, s): - #lines = s.split('\n') lines = s.split('\n') spaces = re.match(' *', lines[0]).group(0) def strip_spaces(l, spaces=spaces): - #if l.startswith(spaces): if l[:len(spaces)] == spaces: l = l[len(spaces):] return l - #return '\n'.join([ strip_spaces(l) for l in lines ]) return '\n'.join(map(strip_spaces, lines)) def write(self, file, contents): diff --git a/src/engine/SCons/dblite.py b/src/engine/SCons/dblite.py index f4ba90a..707a4f8 100644 --- a/src/engine/SCons/dblite.py +++ b/src/engine/SCons/dblite.py @@ -3,7 +3,6 @@ import SCons.compat -import builtins import os # compat layer imports "cPickle" for us if it's available. import pickle @@ -44,7 +43,7 @@ class dblite(object): # See the discussion at: # http://mail.python.org/pipermail/python-bugs-list/2003-March/016877.html - _open = builtins.open + _open = open _pickle_dump = staticmethod(pickle.dump) _os_chmod = os.chmod try: @@ -99,7 +98,10 @@ class dblite(object): if (len(p) > 0): try: self._dict = pickle.loads(p) - except (pickle.UnpicklingError, EOFError): + except (pickle.UnpicklingError, EOFError, KeyError): + # Note how we catch KeyErrors too here, which might happen + # when we don't have cPickle available (default pickle + # throws it). if (ignore_corrupt_dbfiles == 0): raise if (ignore_corrupt_dbfiles == 1): corruption_warning(self._file_name) diff --git a/src/script/scons-time.py b/src/script/scons-time.py index 3b215f9..02168d8 100644 --- a/src/script/scons-time.py +++ b/src/script/scons-time.py @@ -43,53 +43,10 @@ import sys import tempfile import time -try: - sorted -except NameError: - # Pre-2.4 Python has no sorted() function. - # - # The pre-2.4 Python list.sort() method does not support - # list.sort(key=) nor list.sort(reverse=) keyword arguments, so - # we must implement the functionality of those keyword arguments - # by hand instead of passing them to list.sort(). - def sorted(iterable, cmp=None, key=None, reverse=False): - if key is not None: - result = [(key(x), x) for x in iterable] - else: - result = iterable[:] - if cmp is None: - # Pre-2.3 Python does not support list.sort(None). - result.sort() - else: - result.sort(cmp) - if key is not None: - result = [t1 for t0,t1 in result] - if reverse: - result.reverse() - return result - -if os.environ.get('SCONS_HORRIBLE_REGRESSION_TEST_HACK') is not None: - # We can't apply the 'callable' fixer until the floor is 2.6, but the - # '-3' option to Python 2.6 and 2.7 generates almost ten thousand - # warnings. This hack allows us to run regression tests with the '-3' - # option by replacing the callable() built-in function with a hack - # that performs the same function but doesn't generate the warning. - # Note that this hack is ONLY intended to be used for regression - # testing, and should NEVER be used for real runs. - from types import ClassType - def callable(obj): - if hasattr(obj, '__call__'): return True - if isinstance(obj, (ClassType, type)): return True - return False - def make_temp_file(**kw): try: result = tempfile.mktemp(**kw) - try: - result = os.path.realpath(result) - except AttributeError: - # Python 2.1 has no os.path.realpath() method. - pass + result = os.path.realpath(result) except TypeError: try: save_template = tempfile.template diff --git a/src/script/sconsign.py b/src/script/sconsign.py index ef32a93..c95bf74 100644 --- a/src/script/sconsign.py +++ b/src/script/sconsign.py @@ -54,6 +54,14 @@ import sys # followed by generic) so we pick up the right version of the build # engine modules if they're in either directory. + +if sys.version_info >= (3,0,0): + msg = "sconsign: *** Version %s does not run under Python version %s.\n\ +Python 3 is not yet supported.\n" + sys.stderr.write(msg % (__version__, sys.version.split()[0])) + sys.exit(1) + + script_dir = sys.path[0] if script_dir in sys.path: @@ -64,6 +72,11 @@ libs = [] if "SCONS_LIB_DIR" in os.environ: libs.append(os.environ["SCONS_LIB_DIR"]) +# - running from source takes priority (since 2.3.2), excluding SCONS_LIB_DIR settings +script_path = os.path.abspath(os.path.dirname(__file__)) +source_path = os.path.join(script_path, '..', 'engine') +libs.append(source_path) + local_version = 'scons-local-' + __version__ local = 'scons-local' if script_dir: @@ -463,12 +476,22 @@ for o, a in opts: elif o in ('-e', '--entry'): Print_Entries.append(a) elif o in ('-f', '--format'): + # Try to map the given DB format to a known module + # name, that we can then try to import... Module_Map = {'dblite' : 'SCons.dblite', 'sconsign' : None} dbm_name = Module_Map.get(a, a) if dbm_name: try: - dbm = my_import(dbm_name) + if dbm_name != "SCons.dblite": + dbm = my_import(dbm_name) + else: + import SCons.dblite + dbm = SCons.dblite + # Ensure that we don't ignore corrupt DB files, + # this was handled by calling my_import('SCons.dblite') + # again in earlier versions... + SCons.dblite.ignore_corrupt_dbfiles = 0 except: sys.stderr.write("sconsign: illegal file format `%s'\n" % a) print helpstr @@ -500,7 +523,15 @@ else: dbm_name = whichdb.whichdb(a) if dbm_name: Map_Module = {'SCons.dblite' : 'dblite'} - dbm = my_import(dbm_name) + if dbm_name != "SCons.dblite": + dbm = my_import(dbm_name) + else: + import SCons.dblite + dbm = SCons.dblite + # Ensure that we don't ignore corrupt DB files, + # this was handled by calling my_import('SCons.dblite') + # again in earlier versions... + SCons.dblite.ignore_corrupt_dbfiles = 0 Do_SConsignDB(Map_Module.get(dbm_name, dbm_name), dbm)(a) else: Do_SConsignDir(a) diff --git a/test/TEX/bibliography.py b/test/TEX/bibliography.py index 5e26f6e..c26b010 100644 --- a/test/TEX/bibliography.py +++ b/test/TEX/bibliography.py @@ -118,9 +118,6 @@ test.must_not_exist(test.workpath('simple.blg')) test.pass_test() - -# FUTURE: - test.write('SConstruct', """\ env = Environment(tools = ['tex', 'latex', 'dvips']) env.PostScript('d00', 'd00.tex') diff --git a/test/compat/all.py b/test/compat/all.py deleted file mode 100644 index ac7a6ea..0000000 --- a/test/compat/all.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python -# -# __COPYRIGHT__ -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# 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. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -""" -Verify that we can use the any() function (in any supported Python -version we happen to be testing). - -This test can be retired at some point in the distant future when Python -2.5 becomes the minimum version supported by SCons. -""" - -import TestSCons - -test = TestSCons.TestSCons() - -test.write('SConstruct', """\ -print all([True, 1]) and "YES" or "NO" -print all([0]) and "YES" or "NO" -SConscript('SConscript') -""") - -test.write('SConscript', """\ -print all([1, False]) and "YES" or "NO" -print all([True, None]) and "YES" or "NO" -""") - -expect = """\ -YES -NO -NO -NO -""" - -test.run(arguments = '-Q -q', stdout = expect) - -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/compat/any.py b/test/compat/any.py deleted file mode 100644 index 3c03807..0000000 --- a/test/compat/any.py +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env python -# -# __COPYRIGHT__ -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# 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. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -""" -Verify that we can use the any() function (in any supported Python -version we happen to be testing). - -This test can be retired at some point in the distant future when Python -2.5 becomes the minimum version supported by SCons. -""" - -import TestSCons - -test = TestSCons.TestSCons() - -test.write('SConstruct', """\ -print any([True, False]) and "YES" or "NO" -print any([1]) and "YES" or "NO" -SConscript('SConscript') -""") - -test.write('SConscript', """\ -print any([0, False]) and "YES" or "NO" -""") - -expect = """\ -YES -YES -NO -""" - -test.run(arguments = '-Q -q', stdout = expect) - -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/option/profile.py b/test/option/profile.py index d53c690..4d6caae 100644 --- a/test/option/profile.py +++ b/test/option/profile.py @@ -24,19 +24,14 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import sys -try: - import io - _StringIO = io.StringIO -except (ImportError, AttributeError): - # Pre-2.6 Python has no "io" module. - exec('from cStringIO import StringIO') -else: - # TODO(2.6): In 2.6 and beyond, the io.StringIO.write() method - # requires unicode strings. This subclass can probably be removed - # when we drop support for Python 2.6. - class StringIO(_StringIO): - def write(self, s): - _StringIO.write(self, unicode(s)) +import io +_StringIO = io.StringIO +# TODO(2.6): In 2.6 and beyond, the io.StringIO.write() method +# requires unicode strings. This subclass can probably be removed +# when we drop support for Python 2.6. +class StringIO(_StringIO): + def write(self, s): + _StringIO.write(self, unicode(s)) import TestSCons diff --git a/test/sconsign/script/bad.py b/test/sconsign/script/bad.py index fc21577..a384748 100644 --- a/test/sconsign/script/bad.py +++ b/test/sconsign/script/bad.py @@ -47,16 +47,16 @@ test.run_sconsign(arguments = "-f dblite bad1.dblite", stderr = "sconsign: \[Errno 2\] No such file or directory: 'bad1.dblite'\n") test.run_sconsign(arguments = "-f dblite bad2", - stderr = "sconsign: ignoring invalid `dblite' file `bad2'\n") + stderr = "sconsign: ignoring invalid `dblite' file `bad2'.*\n") test.run_sconsign(arguments = "-f dblite bad2.dblite", - stderr = "sconsign: ignoring invalid `dblite' file `bad2.dblite'\n") + stderr = "sconsign: ignoring invalid `dblite' file `bad2.dblite'.*\n") test.run_sconsign(arguments = "-f sconsign no_sconsign", stderr = "sconsign: \[Errno 2\] No such file or directory: 'no_sconsign'\n") test.run_sconsign(arguments = "-f sconsign bad3", - stderr = "sconsign: ignoring invalid .sconsign file `bad3'\n") + stderr = "sconsign: ignoring invalid .sconsign file `bad3'.*\n") test.pass_test() diff --git a/test/update-release-info/update-release-info.py b/test/update-release-info/update-release-info.py index e44aa99..970bcce 100644 --- a/test/update-release-info/update-release-info.py +++ b/test/update-release-info/update-release-info.py @@ -60,10 +60,10 @@ combo_strings = [ """version_tuple = (2, 0, 0, 'bad', 0) """, # Index 1: Python version tuple -"""unsupported_python_version = (2, 3) +"""unsupported_python_version = (2, 6) """, # Index 2: Python version tuple -"""deprecated_python_version = (2, 4) +"""deprecated_python_version = (2, 7) """, # Index 3: alpha version tuple """version_tuple = (2, 0, 0, 'alpha', 0) @@ -223,14 +223,14 @@ These files are a part of 33.22.11: test.must_match(TestSCons, """ copyright_years = '%s' default_version = '2.0.0.alpha.yyyymmdd' -python_version_unsupported = (2, 3) -python_version_deprecated = (2, 4) +python_version_unsupported = (2, 6) +python_version_deprecated = (2, 7) """%years, mode = 'r') # should get Python floors from TestSCons module. test.must_match(Main, """ -unsupported_python_version = (2, 3) -deprecated_python_version = (2, 4) +unsupported_python_version = (2, 6) +deprecated_python_version = (2, 7) """, mode = 'r') #TODO: Release option -- cgit v0.12 From 42ac4c63bd25680c49ff9a7fa6f1e1139d589ced Mon Sep 17 00:00:00 2001 From: Dirk Baechle Date: Mon, 14 Dec 2015 22:44:58 +0100 Subject: - fixed render_tree default argument for "visited" as well - added tests for the new "visited" default arguments of the render_tree and print_tree methods - added simple test for the new "None" default arguments in Variables constructor --- src/CHANGES.txt | 9 ++++- src/engine/SCons/Node/__init__.py | 2 +- src/engine/SCons/Util.py | 6 +++- src/engine/SCons/UtilTests.py | 52 ++++++++++++++++++++++++---- src/engine/SCons/Variables/VariablesTests.py | 16 +++++++++ 5 files changed, 75 insertions(+), 10 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 9e9ec42..9e335f9 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -11,7 +11,14 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER SCons now respects scanner keys for implicit dependencies. - Resolved missing cross-language dependencies for SWIG bindings (fixes #2264). - + + From Dirk Baechle: + - Removed a lot of compatibility methods and workarounds + for Python versions < 2.7, in order to prepare the work + towards a combined 2.7/3.x version. (PR #284) + Also fixed the default arguments for the print_tree and + render_tree methods. (PR #284, too) + RELEASE 2.4.1 - Mon, 07 Nov 2015 10:37:21 -0700 diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 40ee8f0..86a5c1d 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -577,7 +577,7 @@ class Node(object): self.always_build = None self.includes = None self.attributes = self.Attrs() # Generic place to stick information about the Node. - self.side_effect = 0 # true if this node is a side effect + self.side_effect = 0 # true iff this node is a side effect self.side_effects = [] # the side effects of building this target self.linked = 0 # is this node linked to the variant directory? self.changed_since_last_build = 0 diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index a834726..cd23e6e 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -167,7 +167,7 @@ class DisplayEngine(object): def set_mode(self, mode): self.print_it = mode -def render_tree(root, child_func, prune=0, margin=[0], visited={}): +def render_tree(root, child_func, prune=0, margin=[0], visited=None): """ Render a tree of nodes into an ASCII tree view. root - the root node of the tree @@ -181,6 +181,10 @@ def render_tree(root, child_func, prune=0, margin=[0], visited={}): rname = str(root) + # Initialize 'visited' dict, if required + if visited is None: + visited = {} + children = child_func(root) retval = "" for pipe in margin[:-1]: diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py index d59d40c..9f80e86 100644 --- a/src/engine/SCons/UtilTests.py +++ b/src/engine/SCons/UtilTests.py @@ -124,7 +124,9 @@ class UtilTestCase(unittest.TestCase): def tree_case_2(self, prune=1): """Fixture for the render_tree() and print_tree() tests.""" - stdlib_h = self.Node("stdlib.h") + types_h = self.Node('types.h') + malloc_h = self.Node('malloc.h') + stdlib_h = self.Node('stdlib.h', [types_h, malloc_h]) bar_h = self.Node('bar.h', [stdlib_h]) blat_h = self.Node('blat.h', [stdlib_h]) blat_c = self.Node('blat.c', [blat_h, bar_h]) @@ -135,13 +137,18 @@ class UtilTestCase(unittest.TestCase): +-blat.c +-blat.h | +-stdlib.h + | +-types.h + | +-malloc.h +-bar.h - +-[stdlib.h] """ - - if not prune: - expect = expect.replace('[', '') - expect = expect.replace(']', '') + if prune: + expect += """ +-[stdlib.h] +""" + else: + expect += """ +-stdlib.h + +-types.h + +-malloc.h +""" lines = expect.split('\n')[:-1] lines = ['[E BSPACN ]'+l for l in lines] @@ -162,6 +169,13 @@ class UtilTestCase(unittest.TestCase): actual = render_tree(node, get_children, 1) assert expect == actual, (expect, actual) + # Ensure that we can call render_tree on the same Node + # again. This wasn't possible in version 2.4.1 and earlier + # due to a bug in render_tree (visited was set to {} as default + # parameter) + actual = render_tree(node, get_children, 1) + assert expect == actual, (expect, actual) + def test_print_tree(self): """Test the print_tree() function""" def get_children(node): @@ -181,9 +195,33 @@ class UtilTestCase(unittest.TestCase): print_tree(node, get_children, showtags=1) actual = sys.stdout.getvalue() assert withtags == actual, (withtags, actual) - + + # Test that explicitly setting prune to zero works + # the same as the default (see above) node, expect, withtags = self.tree_case_2(prune=0) + + sys.stdout = io.StringIO() + print_tree(node, get_children, 0) + actual = sys.stdout.getvalue() + assert expect == actual, (expect, actual) + + sys.stdout = io.StringIO() + print_tree(node, get_children, 0, showtags=1) + actual = sys.stdout.getvalue() + assert withtags == actual, (withtags, actual) + + # Test output with prune=1 + node, expect, withtags = self.tree_case_2(prune=1) + + sys.stdout = io.StringIO() + print_tree(node, get_children, 1) + actual = sys.stdout.getvalue() + assert expect == actual, (expect, actual) + # Ensure that we can call print_tree on the same Node + # again. This wasn't possible in version 2.4.1 and earlier + # due to a bug in print_tree (visited was set to {} as default + # parameter) sys.stdout = io.StringIO() print_tree(node, get_children, 1) actual = sys.stdout.getvalue() diff --git a/src/engine/SCons/Variables/VariablesTests.py b/src/engine/SCons/Variables/VariablesTests.py index d2110c1..50f7d13 100644 --- a/src/engine/SCons/Variables/VariablesTests.py +++ b/src/engine/SCons/Variables/VariablesTests.py @@ -273,6 +273,22 @@ class VariablesTestCase(unittest.TestCase): opts.Update(env, {}) assert 'ANSWER' not in env + def test_noaggregation(self): + """Test that the 'files' and 'args' attributes of the Variables class + don't aggregate entries from one instance to another. + This used to be a bug in SCons version 2.4.1 and earlier. + """ + + opts = SCons.Variables.Variables() + opts.files.append('custom.py') + opts.args['ANSWER'] = 54 + nopts = SCons.Variables.Variables() + + # Ensure that both attributes are initialized to + # an empty list and dict, respectively. + assert len(nopts.files) == 0 + assert len(nopts.args) == 0 + def test_args(self): """Test updating an Environment with arguments overridden""" -- cgit v0.12 From 8a198d3aa488dc02e77a87354a14fd6c5764184b Mon Sep 17 00:00:00 2001 From: Dirk Baechle Date: Wed, 16 Dec 2015 09:16:58 +0100 Subject: - fixed initialization of Util.WinError for Windows --- src/engine/SCons/Util.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index cd23e6e..7bcd6e2 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -586,6 +586,10 @@ WinError = None # OSError subclass on Windows.) class PlainWindowsError(OSError): pass +try: + WinError = WindowsError +except NameError: + WinError = PlainWindowsError if can_read_reg: @@ -621,11 +625,6 @@ if can_read_reg: k = RegOpenKeyEx(root, keyp) return RegQueryValueEx(k,val) else: - try: - WinError = WindowsError - except NameError: - WinError = PlainWindowsError - HKEY_CLASSES_ROOT = None HKEY_LOCAL_MACHINE = None HKEY_CURRENT_USER = None -- cgit v0.12 From 8617739fb8bfb9fee2252a02d47c5de220921ae4 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 16 Dec 2015 17:43:40 -0500 Subject: don't run test for no threading via fake threading.py which throws ImportError on win32. on Win32 other modules import threading and so test fails. This was previously hidden by compat subprocess module which has been removed as obsolete since the base python is being moved to 2.7 --- test/option-j.py | 51 ++++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/test/option-j.py b/test/option-j.py index 3eb7bd3..69ef414 100644 --- a/test/option-j.py +++ b/test/option-j.py @@ -30,9 +30,11 @@ SConscript settable option. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os.path +import sys import TestSCons + _python_ = TestSCons._python_ try: @@ -120,42 +122,41 @@ test.fail_test(start2 < finish1) # succeeds. test.run(arguments='-j 2 out') +if sys.platform != 'win32': + # Test breaks on win32 when using real subprocess is not the only + # package to import threading + # + # Test that we fall back and warn properly if there's no threading.py + # module (simulated), which is the case if this version of Python wasn't + # built with threading support. -# Test that we fall back and warn properly if there's no threading.py -# module (simulated), which is the case if this version of Python wasn't -# built with threading support. + test.subdir('pythonlib') -test.subdir('pythonlib') + test.write(['pythonlib', 'threading.py'], "raise ImportError\n") -test.write(['pythonlib', 'threading.py'], """\ -raise ImportError -""") + save_pythonpath = os.environ.get('PYTHONPATH', '') + os.environ['PYTHONPATH'] = test.workpath('pythonlib') -save_pythonpath = os.environ.get('PYTHONPATH', '') -os.environ['PYTHONPATH'] = test.workpath('pythonlib') + #start2, finish1 = RunTest('-j 2 f1, f2', "fifth") -#start2, finish1 = RunTest('-j 2 f1, f2', "fifth") + test.write('f1.in', 'f1.in pythonlib\n') + test.write('f2.in', 'f2.in pythonlib\n') -test.write('f1.in', 'f1.in pythonlib\n') -test.write('f2.in', 'f2.in pythonlib\n') + test.run(arguments = "-j 2 f1 f2", stderr=None) -test.run(arguments = "-j 2 f1 f2", stderr=None) - -warn = \ -"""scons: warning: parallel builds are unsupported by this version of Python; -\tignoring -j or num_jobs option. -""" -test.must_contain_all_lines(test.stderr(), [warn]) + warn = """scons: warning: parallel builds are unsupported by this version of Python; +\tignoring -j or num_jobs option.""" + test.must_contain_all_lines(test.stderr(), [warn]) -str = test.read("f1") -start1,finish1 = list(map(float, str.split("\n"))) + str = test.read("f1") + start1,finish1 = list(map(float, str.split("\n"))) -str = test.read("f2") -start2,finish2 = list(map(float, str.split("\n"))) + str = test.read("f2") + start2,finish2 = list(map(float, str.split("\n"))) -test.fail_test(start2 < finish1) + test.fail_test(start2 < finish1) -os.environ['PYTHONPATH'] = save_pythonpath + os.environ['PYTHONPATH'] = save_pythonpath # Test SetJobs() with no -j: -- cgit v0.12 From 98b9ca9a3abd8c5c5fae9ff92331b63ba4cedd87 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 17 Dec 2015 09:31:03 -0500 Subject: fix swig test failing on windows due to \r\n line endings --- src/engine/SCons/Tool/swig.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/engine/SCons/Tool/swig.py b/src/engine/SCons/Tool/swig.py index 309585d..ce54e62 100644 --- a/src/engine/SCons/Tool/swig.py +++ b/src/engine/SCons/Tool/swig.py @@ -139,9 +139,13 @@ def _get_swig_version(env, swig): if pipe.wait() != 0: return out = pipe.stdout.read() - match = re.search(r'SWIG Version\s+(\S+)$', out, re.MULTILINE) + match = re.search(r'SWIG Version\s+(\S+).*', out, re.MULTILINE) if match: + # print "Version is:%s"%match.group(1) return match.group(1) + else: + # print "Unable to detect version: [%s]"%out + pass def generate(env): """Add Builders and construction variables for swig to an Environment.""" -- cgit v0.12 From 9d558dd65deacc958edc1f0da2dab1ec56ff4e4e Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 17 Dec 2015 11:02:58 -0500 Subject: added verbose flag to Swig to enable debug output when necessary --- src/engine/SCons/Tool/swig.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/engine/SCons/Tool/swig.py b/src/engine/SCons/Tool/swig.py index ce54e62..3a5a3cc 100644 --- a/src/engine/SCons/Tool/swig.py +++ b/src/engine/SCons/Tool/swig.py @@ -43,6 +43,8 @@ import SCons.Tool import SCons.Util import SCons.Node +verbose = False + swigs = [ 'swig', 'swig3.0', 'swig2.0' ] SwigAction = SCons.Action.Action('$SWIGCOM', '$SWIGCOMSTR') @@ -141,11 +143,10 @@ def _get_swig_version(env, swig): out = pipe.stdout.read() match = re.search(r'SWIG Version\s+(\S+).*', out, re.MULTILINE) if match: - # print "Version is:%s"%match.group(1) + if verbose: print "Version is:%s"%match.group(1) return match.group(1) else: - # print "Unable to detect version: [%s]"%out - pass + if verbose: print "Unable to detect version: [%s]"%out def generate(env): """Add Builders and construction variables for swig to an Environment.""" -- cgit v0.12 From 34cf3bdb1743de9a5534bfd25998d0a01297f004 Mon Sep 17 00:00:00 2001 From: Russel Winder Date: Fri, 1 Jan 2016 13:52:31 +0000 Subject: Run futurize --stage1. --- bin/SConsExamples.py | 128 ++++---- bin/memlogs.py | 3 +- bin/memoicmp.py | 7 +- src/engine/SCons/Action.py | 3 +- src/engine/SCons/EnvironmentTests.py | 3 +- src/engine/SCons/Node/__init__.py | 38 +-- src/engine/SCons/Script/Main.py | 6 +- src/engine/SCons/Script/SConscript.py | 4 +- src/engine/SCons/Tool/cyglink.py | 37 ++- src/engine/SCons/Tool/f08.py | 4 +- src/engine/SCons/Tool/msvs.py | 136 ++++---- src/engine/SCons/Tool/swig.py | 5 +- src/engine/SCons/compat/six.py | 4 +- src/engine/SCons/compat/sixTests.py | 3 +- src/engine/SCons/cppTests.py | 4 +- src/script/scons.py | 2 + src/setup.py | 2 + src/test_interrupts.py | 2 + test/LINK/VersionedLib.py | 574 +++++++++++++++++----------------- test/option/debug-multiple.py | 16 +- test/site_scons/sysdirs.py | 6 +- 21 files changed, 509 insertions(+), 478 deletions(-) diff --git a/bin/SConsExamples.py b/bin/SConsExamples.py index e3a7502..dd9bfaf 100644 --- a/bin/SConsExamples.py +++ b/bin/SConsExamples.py @@ -1,7 +1,7 @@ # !/usr/bin/env python -# +# # Copyright (c) 2010 The SCons Foundation -# +# # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including @@ -9,10 +9,10 @@ # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: -# +# # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. -# +# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -21,18 +21,18 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# +# +# # This script looks for some XML tags that describe SCons example # configurations and commands to execute in those configurations, and # uses TestCmd.py to execute the commands and insert the output from # those commands into the XML that we output. This way, we can run a # script and update all of our example documentation output without # a lot of laborious by-hand checking. -# +# # An "SCons example" looks like this, and essentially describes a set of # input files (program source files as well as SConscript files): -# +# # # # env = Environment() @@ -42,7 +42,7 @@ # int main() { printf("foo.c\n"); } # # -# +# # The contents within the tag will get written # into a temporary directory whenever example output needs to be # generated. By default, the contents are not inserted into text @@ -50,41 +50,43 @@ # in which case they will get inserted within a tag. # This makes it easy to define the example at the appropriate # point in the text where you intend to show the SConstruct file. -# +# # Note that you should usually give the a "name" # attribute so that you can refer to the example configuration later to # run SCons and generate output. -# +# # If you just want to show a file's contents without worry about running # SCons, there's a shorter tag: -# +# # # env = Environment() # env.Program('foo') # -# +# # This is essentially equivalent to , # but it's more straightforward. -# +# # SCons output is generated from the following sort of tag: -# +# # # scons -Q foo # scons -Q foo # -# +# # You tell it which example to use with the "example" attribute, and then # give it a list of tags to execute. You can also # supply an "os" tag, which specifies the type of operating system this # example is intended to show; if you omit this, default value is "posix". -# +# # The generated XML will show the command line (with the appropriate # command-line prompt for the operating system), execute the command in # a temporary directory with the example files, capture the standard # output from SCons, and insert it into the text as appropriate. # Error output gets passed through to your error output so you # can see if there are any problems executing the command. -# +# + +from __future__ import print_function import os import re @@ -94,9 +96,9 @@ import time import SConsDoc from SConsDoc import tf as stf -# +# # The available types for ExampleFile entries -# +# FT_FILE = 0 # a physical file (=) FT_FILEREF = 1 # a reference (=) @@ -106,7 +108,7 @@ class ExampleFile: self.name = '' self.content = '' self.chmod = '' - + def isFileRef(self): return self.type == FT_FILEREF @@ -130,19 +132,19 @@ class ExampleOutput: self.preserve = None self.suffix = '' self.commands = [] - + class ExampleInfo: def __init__(self): self.name = '' self.files = [] self.folders = [] self.outputs = [] - + def getFileContents(self, fname): for f in self.files: if fname == f.name and not f.isFileRef(): return f.content - + return '' def readExampleInfos(fpath, examples): @@ -150,10 +152,10 @@ def readExampleInfos(fpath, examples): global dictionary examples. """ - # Create doctree + # Create doctree t = SConsDoc.SConsDocTree() t.parseXmlFile(fpath) - + # Parse scons_examples for e in stf.findAll(t.root, "scons_example", SConsDoc.dbxid, t.xpath_context, t.nsmap): @@ -164,7 +166,7 @@ def readExampleInfos(fpath, examples): i = ExampleInfo() i.name = n examples[n] = i - + # Parse file and directory entries for f in stf.findAll(e, "file", SConsDoc.dbxid, t.xpath_context, t.nsmap): @@ -199,8 +201,8 @@ def readExampleInfos(fpath, examples): fi.chmod = stf.getAttribute(f, 'chmod') fi.content = stf.getText(f) examples[e].files.append(fi) - - + + # Parse scons_output for o in stf.findAll(t.root, "scons_output", SConsDoc.dbxid, t.xpath_context, t.nsmap): @@ -238,7 +240,7 @@ def readExampleInfos(fpath, examples): examples[n].outputs.append(eout) def readAllExampleInfos(dpath): - """ Scan for XML files in the given directory and + """ Scan for XML files in the given directory and collect together all relevant infos (files/folders, output commands) in a map, which gets returned. """ @@ -249,13 +251,13 @@ def readAllExampleInfos(dpath): fpath = os.path.join(path, f) if SConsDoc.isSConsXml(fpath): readExampleInfos(fpath, examples) - + return examples generated_examples = os.path.join('doc', 'generated', 'examples') def ensureExampleOutputsExist(dpath): - """ Scan for XML files in the given directory and + """ Scan for XML files in the given directory and ensure that for every example output we have a corresponding output file in the 'generated/examples' folder. @@ -263,7 +265,7 @@ def ensureExampleOutputsExist(dpath): # Ensure that the output folder exists if not os.path.isdir(generated_examples): os.mkdir(generated_examples) - + examples = readAllExampleInfos(dpath) for key, value in examples.items(): # Process all scons_output tags @@ -276,7 +278,7 @@ def ensureExampleOutputsExist(dpath): stf.setText(s, "NO OUTPUT YET! Run the script to generate/update all examples.") # Write file stf.writeTree(s, cpath) - + # Process all scons_example_file tags for r in value.files: if r.isFileRef(): @@ -292,14 +294,14 @@ def ensureExampleOutputsExist(dpath): perc = "%" def createAllExampleOutputs(dpath): - """ Scan for XML files in the given directory and + """ Scan for XML files in the given directory and creates all output files for every example in the 'generated/examples' folder. """ # Ensure that the output folder exists if not os.path.isdir(generated_examples): os.mkdir(generated_examples) - + examples = readAllExampleInfos(dpath) total = len(examples) idx = 0 @@ -307,7 +309,7 @@ def createAllExampleOutputs(dpath): # Process all scons_output tags print("%.2f%s (%d/%d) %s" % (float(idx + 1) * 100.0 / float(total), perc, idx + 1, total, key)) - + create_scons_output(value) # Process all scons_example_file tags for r in value.files: @@ -329,10 +331,10 @@ def collectSConsExampleNames(fpath): suffixes = {} failed_suffixes = False - # Create doctree + # Create doctree t = SConsDoc.SConsDocTree() t.parseXmlFile(fpath) - + # Parse it for e in stf.findAll(t.root, "scons_example", SConsDoc.dbxid, t.xpath_context, t.nsmap): @@ -346,7 +348,7 @@ def collectSConsExampleNames(fpath): else: print("Error: Example in file '%s' is missing a name!" % fpath) failed_suffixes = True - + for o in stf.findAll(t.root, "scons_output", SConsDoc.dbxid, t.xpath_context, t.nsmap): n = '' @@ -355,29 +357,29 @@ def collectSConsExampleNames(fpath): else: print("Error: scons_output in file '%s' is missing an example name!" % fpath) failed_suffixes = True - + if n not in suffixes: print("Error: scons_output in file '%s' is referencing non-existent example '%s'!" % (fpath, n)) failed_suffixes = True continue - + s = '' if stf.hasAttribute(o, 'suffix'): s = stf.getAttribute(o, 'suffix') else: print("Error: scons_output in file '%s' (example '%s') is missing a suffix!" % (fpath, n)) failed_suffixes = True - + if s not in suffixes[n]: suffixes[n].append(s) else: print("Error: scons_output in file '%s' (example '%s') is using a duplicate suffix '%s'!" % (fpath, n, s)) failed_suffixes = True - + return names, failed_suffixes def exampleNamesAreUnique(dpath): - """ Scan for XML files in the given directory and + """ Scan for XML files in the given directory and check whether the scons_example names are unique. """ unique = True @@ -394,19 +396,19 @@ def exampleNamesAreUnique(dpath): if i: print("Not unique in %s are: %s" % (fpath, ', '.join(i))) unique = False - + allnames |= names - + return unique # ############################################################### -# +# # In the second half of this module (starting here) # we define the variables and functions that are required # to actually run the examples, collect their output and # write it into the files in doc/generated/examples... # which then get included by our UserGuide. -# +# # ############################################################### sys.path.append(os.path.join(os.getcwd(), 'QMTest')) @@ -430,7 +432,7 @@ Prompt = { } # The magick SCons hackery that makes this work. -# +# # So that our examples can still use the default SConstruct file, we # actually feed the following into SCons via stdin and then have it # SConscript() the SConstruct file. This stdin wrapper creates a set @@ -438,7 +440,7 @@ Prompt = { # Surrogates print output like the real tools and behave like them # without actually having to be on the right platform or have the right # tool installed. -# +# # The upshot: The wrapper transparently changes the world out from # under the top-level SConstruct file in an example just so we can get # the command output. @@ -765,7 +767,7 @@ def ExecuteCommand(args, c, t, dict): def create_scons_output(e): # The real raison d'etre for this script, this is where we # actually execute SCons to fetch the output. - + # Loop over all outputs for the example for o in e.outputs: # Create new test directory @@ -774,19 +776,19 @@ def create_scons_output(e): t.preserve() t.subdir('ROOT', 'WORK') t.rootpath = t.workpath('ROOT').replace('\\', '\\\\') - + for d in e.folders: dir = t.workpath('WORK', d.name) if not os.path.exists(dir): os.makedirs(dir) - + for f in e.files: if f.isFileRef(): continue - # + # # Left-align file's contents, starting on the first # non-empty line - # + # data = f.content.split('\n') i = 0 # Skip empty lines @@ -813,26 +815,26 @@ def create_scons_output(e): if hasattr(f, 'chmod'): if len(f.chmod): os.chmod(path, int(f.chmod, 0)) - + # Regular expressions for making the doc output consistent, # regardless of reported addresses or Python version. - + # Massage addresses in object repr strings to a constant. address_re = re.compile(r' at 0x[0-9a-fA-F]*\>') - + # Massage file names in stack traces (sometimes reported as absolute # paths) to a consistent relative path. engine_re = re.compile(r' File ".*/src/engine/SCons/') - + # Python 2.5 changed the stack trace when the module is read # from standard input from read "... line 7, in ?" to # "... line 7, in ". file_re = re.compile(r'^( *File ".*", line \d+, in) \?$', re.M) - + # Python 2.6 made UserList a new-style class, which changes the # AttributeError message generated by our NodeList subclass. nodelist_re = re.compile(r'(AttributeError:) NodeList instance (has no attribute \S+)') - + # Root element for our subtree sroot = stf.newEtreeNode("screen", True) curchild = None @@ -881,7 +883,7 @@ def create_scons_output(e): curchild.tail = content else: sroot.text = content - + # Construct filename fpath = os.path.join(generated_examples, e.name + '_' + o.suffix + '.xml') diff --git a/bin/memlogs.py b/bin/memlogs.py index 6e68ce0..b450939 100644 --- a/bin/memlogs.py +++ b/bin/memlogs.py @@ -20,7 +20,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 print_function + +from __future__ import print_function import getopt import sys diff --git a/bin/memoicmp.py b/bin/memoicmp.py index 1106ac3..7f0369e 100644 --- a/bin/memoicmp.py +++ b/bin/memoicmp.py @@ -2,7 +2,8 @@ # # A script to compare the --debug=memoizer output found in # two different files. -from future import print_function + +from __future__ import print_function import sys @@ -46,7 +47,7 @@ def memoize_cmp(filea, fileb): mab.sort() ma_o.sort() mb_o.sort() - + for k in mab: hits = cfmt%(ma[k][0], mb[k][0], mb[k][0]-ma[k][0]) miss = cfmt%(ma[k][1], mb[k][1], mb[k][1]-ma[k][1]) @@ -63,7 +64,7 @@ def memoize_cmp(filea, fileb): print('%-24s %-24s %s'%(hits, miss, k)) print('-'*(24+24+1+20)) - + if __name__ == "__main__": if len(sys.argv) != 3: diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index d11f30d..a4e75f3 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -101,7 +101,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import dis import os -# compat layer imports "cPickle" for us if it's available. import pickle import re import sys @@ -272,7 +271,7 @@ def _function_contents(func): contents.append(b',()') # The function contents depends on the closure captured cell values. - closure = func.func_closure or [] + closure = func.__closure__ or [] #xxx = [_object_contents(x.cell_contents) for x in closure] try: diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index 99d169a..4b57763 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -20,6 +20,7 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -1868,7 +1869,7 @@ def generate(env): # test for pull request #150 env = self.TestEnvironment() env._dict.pop('BUILDERS') - assert env.has_key('BUILDERS') is False + assert ('BUILDERS' in env) is False env2 = env.Clone() def test_Copy(self): diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 85e30c2..1a76b60 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -19,6 +19,8 @@ be able to depend on any other type of "thing." """ +from __future__ import print_function + # # __COPYRIGHT__ # @@ -151,7 +153,7 @@ def exists_file(node): # The source file does not exist. Make sure no old # copy remains in the variant directory. if print_duplicate: - print "dup: no src for %s, unlinking old variant copy"%self + print("dup: no src for %s, unlinking old variant copy"%self) if exists_base(node) or node.islink(): node.fs.unlink(node.get_internal_path()) # Return None explicitly because the Base.exists() call @@ -205,13 +207,13 @@ def get_contents_dir(node): contents.append('%s %s\n' % (n.get_csig(), n.name)) return ''.join(contents) -def get_contents_file(node): +def get_contents_file(node): if not node.rexists(): return '' fname = node.rfile().get_abspath() try: contents = open(fname, "rb").read() - except EnvironmentError, e: + except EnvironmentError as e: if not e.filename: e.filename = fname raise @@ -407,21 +409,21 @@ class NodeInfoBase(object): for name in getattr(obj,'__slots__',()): if hasattr(self, name): state[name] = getattr(self, name) - + state['_version_id'] = self.current_version_id try: del state['__weakref__'] except KeyError: pass return state - + def __setstate__(self, state): """ Restore the attributes from a pickled state. The version is discarded. """ # TODO check or discard version del state['_version_id'] - + for key, value in state.items(): if key not in ('__weakref__',): setattr(self, key, value) @@ -456,7 +458,7 @@ class BuildInfoBase(object): """ state = other.__getstate__() self.__setstate__(state) - + def __getstate__(self): """ Return all fields that shall be pickled. Walk the slots in the class @@ -536,7 +538,7 @@ class Node(object): class Attrs(object): __slots__ = ('shared', '__dict__') - + def __init__(self): if SCons.Debug.track_instances: logInstanceCreation(self, 'Node.Node') @@ -588,7 +590,7 @@ class Node(object): self._func_rexists = 1 self._func_get_contents = 0 self._func_target_from_source = 0 - + self.clear_memoized_values() # Let the interface in which the build engine is embedded @@ -776,16 +778,16 @@ class Node(object): def release_target_info(self): """Called just after this node has been marked up-to-date or was built completely. - + This is where we try to release as many target node infos as possible for clean builds and update runs, in order to minimize the overall memory consumption. - + By purging attributes that aren't needed any longer after a Node (=File) got built, we don't have to care that much how many KBytes a Node actually requires...as long as we free the memory shortly afterwards. - + @see: built() and File.release_target_info() """ pass @@ -934,7 +936,7 @@ class Node(object): node = nodes.pop(0) scanner = node._get_scanner(env, initial_scanner, root_node_scanner, kw) - + if not scanner: continue @@ -958,14 +960,14 @@ class Node(object): else: # handle explicit scanner case scanner = initial_scanner.select(self) - + if not scanner: # no scanner could be found for the given node's scanner key; # thus, make an attempt at using a default. scanner = root_node_scanner - + return scanner - + def get_env_scanner(self, env, kw={}): return env.get_scanner(self.scanner_key()) @@ -1422,14 +1424,14 @@ class Node(object): any difference, but we now rely on checking every dependency to make sure that any necessary Node information (for example, the content signature of an #included .h file) is updated. - + The allowcache option was added for supporting the early release of the executor/builder structures, right after a File target was built. When set to true, the return value of this changed method gets cached for File nodes. Like this, the executor isn't needed any longer for subsequent calls to changed(). - + @see: FS.File.changed(), FS.File.release_target_info() """ t = 0 diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index 71d64fc..7cc7d47 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -10,6 +10,8 @@ some other module. If it's specific to the "scons" script invocation, it goes here. """ +from __future__ import print_function + unsupported_python_version = (2, 6, 0) deprecated_python_version = (2, 7, 0) @@ -354,13 +356,13 @@ class CleanTask(SCons.Taskmaster.AlwaysTask): for t in self._get_files_to_clean(): try: removed = t.remove() - except OSError, e: + except OSError as e: # An OSError may indicate something like a permissions # issue, an IOError would indicate something like # the file not existing. In either case, print a # message and keep going to try to remove as many # targets as possible. - print("scons: Could not remove '{}':".format(str(t)), e.strerror) + print(("scons: Could not remove '{}':".format(str(t)), e.strerror)) else: if removed: display("Removed " + str(t)) diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py index ab032be..6480ace 100644 --- a/src/engine/SCons/Script/SConscript.py +++ b/src/engine/SCons/Script/SConscript.py @@ -5,6 +5,8 @@ files. """ +from __future__ import print_function + # # __COPYRIGHT__ # @@ -68,7 +70,7 @@ def get_calling_namespaces(): """Return the locals and globals for the function that called into this module in the current call stack.""" try: 1//0 - except ZeroDivisionError: + except ZeroDivisionError: # Don't start iterating with the current stack-frame to # prevent creating reference cycles (f_back is safe). frame = sys.exc_info()[2].tb_frame.f_back diff --git a/src/engine/SCons/Tool/cyglink.py b/src/engine/SCons/Tool/cyglink.py index 2f54a17..f69b886 100644 --- a/src/engine/SCons/Tool/cyglink.py +++ b/src/engine/SCons/Tool/cyglink.py @@ -7,6 +7,9 @@ It will usually be imported through the generic SCons.Tool.Tool() selection method. """ + +from __future__ import absolute_import, print_function + import re import os @@ -15,8 +18,8 @@ import SCons.Util import SCons.Tool #MAYBE: from . import gnulink -import gnulink -import link +from . import gnulink +from . import link def _lib_generator(target, source, env, for_signature, **kw): try: cmd = kw['cmd'] @@ -59,7 +62,7 @@ def _lib_emitter(target, source, env, **kw): Verbose = False if Verbose: - print "_lib_emitter: target[0]=%r" % target[0].get_path() + print("_lib_emitter: target[0]=%r" % target[0].get_path()) try: vp = kw['varprefix'] except KeyError: vp = 'SHLIB' @@ -71,7 +74,7 @@ def _lib_emitter(target, source, env, **kw): no_import_lib = env.get('no_import_lib', 0) if Verbose: - print "_lib_emitter: dll=%r" % dll.get_path() + print("_lib_emitter: dll=%r" % dll.get_path()) if not dll or len(target) > 1: raise SCons.Errors.UserError("A shared library should have exactly one target with the suffix: %s" % env.subst("$%sSUFFIX" % vp)) @@ -82,14 +85,14 @@ def _lib_emitter(target, source, env, **kw): dll.name = pre + dll.name[len(pre)+3:] if Verbose: - print "_lib_emitter: dll.name=%r" % dll.name + print("_lib_emitter: dll.name=%r" % dll.name) orig_target = target target = [env.fs.File(dll)] target[0].attributes.shared = 1 if Verbose: - print "_lib_emitter: after target=[env.fs.File(dll)]: target[0]=%r" % target[0].get_path() + print("_lib_emitter: after target=[env.fs.File(dll)]: target[0]=%r" % target[0].get_path()) # Append an import lib target if not no_import_lib: @@ -98,11 +101,11 @@ def _lib_emitter(target, source, env, **kw): '%sPREFIX' % vp, '%sSUFFIX' % vp, 'IMPLIBPREFIX', 'IMPLIBSUFFIX') if Verbose: - print "_lib_emitter: target_strings=%r" % target_strings + print("_lib_emitter: target_strings=%r" % target_strings) implib_target = env.fs.File(target_strings) if Verbose: - print "_lib_emitter: implib_target=%r" % implib_target.get_path() + print("_lib_emitter: implib_target=%r" % implib_target.get_path()) implib_target.attributes.shared = 1 target.append(implib_target) @@ -110,7 +113,7 @@ def _lib_emitter(target, source, env, **kw): implib_libtype=libtype, generator_libtype=libtype+'ImpLib') if Verbose: - print "_lib_emitter: implib symlinks=%r" % SCons.Tool.StringizeLibSymlinks(symlinks) + print("_lib_emitter: implib symlinks=%r" % SCons.Tool.StringizeLibSymlinks(symlinks)) if symlinks: SCons.Tool.EmitLibSymlinks(env, symlinks, implib_target, clean_targets = target[0]) implib_target.attributes.shliblinks = symlinks @@ -128,13 +131,13 @@ def _versioned_lib_suffix(env, suffix, version): If suffix='.dll', and version='0.1.2', then it returns '-0-1-2.dll'""" Verbose = False if Verbose: - print "_versioned_lib_suffix: suffix= ", suffix - print "_versioned_lib_suffix: version= ", version + print("_versioned_lib_suffix: suffix= ", suffix) + print("_versioned_lib_suffix: version= ", version) cygversion = re.sub('\.', '-', version) if not suffix.startswith('-' + cygversion): suffix = '-' + cygversion + suffix if Verbose: - print "_versioned_lib_suffix: return suffix= ", suffix + print("_versioned_lib_suffix: return suffix= ", suffix) return suffix def _versioned_implib_name(env, libnode, version, prefix, suffix, **kw): @@ -150,8 +153,8 @@ def _versioned_implib_symlinks(env, libnode, version, prefix, suffix, **kw): Verbose = False if Verbose: - print "_versioned_implib_symlinks: libnode=%r" % libnode.get_path() - print "_versioned_implib_symlinks: version=%r" % version + print("_versioned_implib_symlinks: libnode=%r" % libnode.get_path()) + print("_versioned_implib_symlinks: version=%r" % version) try: libtype = kw['libtype'] except KeyError: libtype = 'ShLib' @@ -159,13 +162,13 @@ def _versioned_implib_symlinks(env, libnode, version, prefix, suffix, **kw): linkdir = os.path.dirname(libnode.get_path()) if Verbose: - print "_versioned_implib_symlinks: linkdir=%r" % linkdir + print("_versioned_implib_symlinks: linkdir=%r" % linkdir) name = SCons.Tool.ImpLibNameGenerator(env, libnode, implib_libtype=libtype, generator_libtype=libtype+'ImpLib') if Verbose: - print "_versioned_implib_symlinks: name=%r" % name + print("_versioned_implib_symlinks: name=%r" % name) major = version.split('.')[0] @@ -173,7 +176,7 @@ def _versioned_implib_symlinks(env, libnode, version, prefix, suffix, **kw): symlinks = [(link0, libnode)] if Verbose: - print "_versioned_implib_symlinks: return symlinks=%r" % SCons.Tool.StringizeLibSymlinks(symlinks) + print("_versioned_implib_symlinks: return symlinks=%r" % SCons.Tool.StringizeLibSymlinks(symlinks)) return symlinks diff --git a/src/engine/SCons/Tool/f08.py b/src/engine/SCons/Tool/f08.py index a45a61d..7fa5872 100644 --- a/src/engine/SCons/Tool/f08.py +++ b/src/engine/SCons/Tool/f08.py @@ -8,6 +8,8 @@ selection method. """ +from __future__ import absolute_import + # # __COPYRIGHT__ # @@ -36,7 +38,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Defaults import SCons.Tool import SCons.Util -import fortran +from . import fortran from SCons.Tool.FortranCommon import add_all_to_env, add_f08_to_env compilers = ['f08'] diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py index efdc8a1..c3c8164 100644 --- a/src/engine/SCons/Tool/msvs.py +++ b/src/engine/SCons/Tool/msvs.py @@ -29,6 +29,7 @@ selection method. # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -39,7 +40,6 @@ import base64 import hashlib import ntpath import os -# compat layer imports "cPickle" for us if it's available. import pickle import re import sys @@ -71,7 +71,7 @@ def xmlify(s): # Returns a tuple of nodes. def processIncludes(includes, env, target, source): return SCons.PathList.PathList(includes).subst_path(env, target, source) - + external_makefile_guid = '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}' @@ -169,15 +169,15 @@ class _UserGenerator(object): Base class for .dsp.user file generator ''' # Default instance values. - # Ok ... a bit defensive, but it does not seem reasonable to crash the + # Ok ... a bit defensive, but it does not seem reasonable to crash the # build for a workspace user file. :-) usrhead = None - usrdebg = None + usrdebg = None usrconf = None - createfile = False + createfile = False def __init__(self, dspfile, source, env): # DebugSettings should be a list of debug dictionary sorted in the same order - # as the target list and variants + # as the target list and variants if 'variant' not in env: raise SCons.Errors.InternalError("You must specify a 'variant' argument (i.e. 'Debug' or " +\ "'Release') to create an MSVSProject.") @@ -185,7 +185,7 @@ class _UserGenerator(object): variants = [env['variant']] elif SCons.Util.is_List(env['variant']): variants = env['variant'] - + if 'DebugSettings' not in env or env['DebugSettings'] == None: dbg_settings = [] elif SCons.Util.is_Dict(env['DebugSettings']): @@ -201,12 +201,12 @@ class _UserGenerator(object): dbg_settings.append({}) else: dbg_settings = [] - + if len(dbg_settings) == 1: dbg_settings = dbg_settings * len(variants) - + self.createfile = self.usrhead and self.usrdebg and self.usrconf and \ - dbg_settings and bool([ds for ds in dbg_settings if ds]) + dbg_settings and bool([ds for ds in dbg_settings if ds]) if self.createfile: dbg_settings = dict(zip(variants, dbg_settings)) @@ -216,22 +216,22 @@ class _UserGenerator(object): for key in [k for k in self.usrdebg.keys() if k in src]: trg[key] = str(src[key]) self.configs[var].debug = trg - + def UserHeader(self): encoding = self.env.subst('$MSVSENCODING') versionstr = self.versionstr self.usrfile.write(self.usrhead % locals()) - + def UserProject(self): pass - + def Build(self): if not self.createfile: return try: filename = self.dspabs +'.user' self.usrfile = open(filename, 'w') - except IOError, detail: + except IOError as detail: raise SCons.Errors.InternalError('Unable to open "' + filename + '" for writing:' + str(detail)) else: self.UserHeader() @@ -291,7 +291,7 @@ class _GenerateV7User(_UserGenerator): self.usrconf = V9UserConfiguration self.usrdebg = V9DebugSettings _UserGenerator.__init__(self, dspfile, source, env) - + def UserProject(self): confkeys = sorted(self.configs.keys()) for kind in confkeys: @@ -299,8 +299,8 @@ class _GenerateV7User(_UserGenerator): platform = self.configs[kind].platform debug = self.configs[kind].debug if debug: - debug_settings = '\n'.join(['\t\t\t\t%s="%s"' % (key, xmlify(value)) - for key, value in debug.items() + debug_settings = '\n'.join(['\t\t\t\t%s="%s"' % (key, xmlify(value)) + for key, value in debug.items() if value is not None]) self.usrfile.write(self.usrconf % locals()) self.usrfile.write('\t\n') @@ -346,7 +346,7 @@ V10DebugSettings = { class _GenerateV10User(_UserGenerator): """Generates a Project'user file for MSVS 2010""" - + def __init__(self, dspfile, source, env): self.versionstr = '4.0' self.usrhead = V10UserHeader @@ -361,8 +361,8 @@ class _GenerateV10User(_UserGenerator): platform = self.configs[kind].platform debug = self.configs[kind].debug if debug: - debug_settings = '\n'.join(['\t\t<%s>%s' % (key, xmlify(value), key) - for key, value in debug.items() + debug_settings = '\n'.join(['\t\t<%s>%s' % (key, xmlify(value), key) + for key, value in debug.items() if value is not None]) self.usrfile.write(self.usrconf % locals()) self.usrfile.write('') @@ -458,7 +458,7 @@ class _DSPGenerator(object): runfile.append(s) self.sconscript = env['MSVSSCONSCRIPT'] - + if 'cmdargs' not in env or env['cmdargs'] == None: cmdargs = [''] * len(variants) elif SCons.Util.is_String(env['cmdargs']): @@ -468,7 +468,7 @@ class _DSPGenerator(object): raise SCons.Errors.InternalError("Sizes of 'cmdargs' and 'variant' lists must be the same.") else: cmdargs = env['cmdargs'] - + self.env = env if 'name' in self.env: @@ -550,16 +550,16 @@ V6DSPHeader = """\ CFG=%(name)s - Win32 %(confkey)s !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "%(name)s.mak". -!MESSAGE +!MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "%(name)s.mak" CFG="%(name)s - Win32 %(confkey)s" -!MESSAGE +!MESSAGE !MESSAGE Possible choices for configuration are: -!MESSAGE +!MESSAGE """ class _GenerateV6DSP(_DSPGenerator): @@ -818,7 +818,7 @@ class _GenerateV7DSP(_DSPGenerator, _GenerateV7User): self.dspheader = V7DSPHeader self.dspconfiguration = V7DSPConfiguration self.file = None - + _GenerateV7User.__init__(self, dspfile, source, env) def PrintHeader(self): @@ -895,7 +895,7 @@ class _GenerateV7DSP(_DSPGenerator, _GenerateV7User): preprocdefs = xmlify(';'.join(processDefines(self.env.get('CPPDEFINES', [])))) includepath_Dirs = processIncludes(self.env.get('CPPPATH', []), self.env, None, None) includepath = xmlify(';'.join([str(x) for x in includepath_Dirs])) - + if not env_has_buildtarget: del self.env['MSVSBUILDTARGET'] @@ -1044,7 +1044,7 @@ class _GenerateV7DSP(_DSPGenerator, _GenerateV7User): self.PrintHeader() self.PrintProject() self.file.close() - + _GenerateV7User.Build(self) V10DSPHeader = """\ @@ -1101,7 +1101,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): self.dspheader = V10DSPHeader self.dspconfiguration = V10DSPProjectConfiguration self.dspglobals = V10DSPGlobals - + _GenerateV10User.__init__(self, dspfile, source, env) def PrintHeader(self): @@ -1132,27 +1132,27 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): '\t\t%s\n' % (scc_project_name, scc_local_path_legacy)) else: self.dspglobals = self.dspglobals.replace('%(scc_attrs)s', '') - + self.file.write(self.dspheader % locals()) - + self.file.write('\t\n') - + confkeys = sorted(self.configs.keys()) for kind in confkeys: variant = self.configs[kind].variant platform = self.configs[kind].platform self.file.write(self.dspconfiguration % locals()) - + self.file.write('\t\n') - + self.file.write(self.dspglobals % locals()) - + def PrintProject(self): name = self.name confkeys = sorted(self.configs.keys()) - + self.file.write('\t\n') - + toolset = '' if 'MSVC_VERSION' in self.env: version_num, suite = msvs_parse_version(self.env['MSVC_VERSION']) @@ -1165,16 +1165,16 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): self.file.write('\t\n') self.file.write('\t\n') self.file.write('\t\n') - + for kind in confkeys: variant = self.configs[kind].variant platform = self.configs[kind].platform self.file.write(V10DSPImportGroupCondition % locals()) - + self.file.write('\t\n') self.file.write('\t\n') self.file.write('\t<_ProjectFileVersion>10.0.30319.1\n') - + for kind in confkeys: variant = self.configs[kind].variant platform = self.configs[kind].platform @@ -1182,7 +1182,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): buildtarget = self.configs[kind].buildtarget runfile = self.configs[kind].runfile cmdargs = self.configs[kind].cmdargs - + env_has_buildtarget = 'MSVSBUILDTARGET' in self.env if not env_has_buildtarget: self.env['MSVSBUILDTARGET'] = buildtarget @@ -1207,29 +1207,29 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): del self.env['MSVSBUILDTARGET'] self.file.write(V10DSPCommandLine % locals()) - + self.file.write('\t\n') - + #filter settings in MSVS 2010 are stored in separate file self.filtersabs = self.dspabs + '.filters' try: self.filters_file = open(self.filtersabs, 'w') except IOError as detail: raise SCons.Errors.InternalError('Unable to open "' + self.filtersabs + '" for writing:' + str(detail)) - + self.filters_file.write('\n' '\n') - + self.PrintSourceFiles() - + self.filters_file.write('') self.filters_file.close() - + self.file.write('\t\n' '\t\n' '\t\n' '\n') - + if self.nokeep == 0: # now we pickle some data and add it to the file -- MSDEV will ignore it. pdata = pickle.dumps(self.configs,1) @@ -1241,7 +1241,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): def printFilters(self, hierarchy, name): sorteditems = sorted(hierarchy.items(), key = lambda a: a[0].lower()) - + for key, value in sorteditems: if SCons.Util.is_Dict(value): filter_name = name + '\\' + key @@ -1249,14 +1249,14 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): '\t\t\t%s\n' '\t\t\n' % (filter_name, _generateGUID(self.dspabs, filter_name))) self.printFilters(value, filter_name) - + def printSources(self, hierarchy, kind, commonprefix, filter_name): keywords = {'Source Files': 'ClCompile', 'Header Files': 'ClInclude', 'Local Headers': 'ClInclude', 'Resource Files': 'None', 'Other Files': 'None'} - + sorteditems = sorted(hierarchy.items(), key = lambda a: a[0].lower()) # First folders, then files @@ -1270,7 +1270,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): if commonprefix: file = os.path.join(commonprefix, value) file = os.path.normpath(file) - + self.file.write('\t\t<%s Include="%s" />\n' % (keywords[kind], file)) self.filters_file.write('\t\t<%s Include="%s">\n' '\t\t\t%s\n' @@ -1282,10 +1282,10 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): 'Local Headers': 'h;hpp;hxx;hm;inl', 'Resource Files': 'r;rc;ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe', 'Other Files': ''} - + cats = sorted([k for k in categories.keys() if self.sources[k]], key = lambda a: a.lower()) - + # print vcxproj.filters file first self.filters_file.write('\t\n') for kind in cats: @@ -1293,7 +1293,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): '\t\t\t{7b42d31d-d53c-4868-8b92-ca2bc9fc052f}\n' '\t\t\t%s\n' '\t\t\n' % (kind, categories[kind])) - + # First remove any common prefix sources = self.sources[kind] commonprefix = None @@ -1306,17 +1306,17 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): # +1 because the filename starts after the separator sources = [s[len(cp)+1:] for s in sources] commonprefix = cp - + hierarchy = makeHierarchy(sources) self.printFilters(hierarchy, kind) - + self.filters_file.write('\t\n') - + # then print files and filters for kind in cats: self.file.write('\t\n') self.filters_file.write('\t\n') - + # First remove any common prefix sources = self.sources[kind] commonprefix = None @@ -1329,13 +1329,13 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): # +1 because the filename starts after the separator sources = [s[len(cp)+1:] for s in sources] commonprefix = cp - + hierarchy = makeHierarchy(sources) self.printSources(hierarchy, kind, commonprefix, kind) - + self.file.write('\t\n') self.filters_file.write('\t\n') - + # add the SConscript file outside of the groups self.file.write('\t\n' '\t\t\n' @@ -1354,7 +1354,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): self.PrintHeader() self.PrintProject() self.file.close() - + _GenerateV10User.Build(self) class _DSWGenerator(object): @@ -1462,7 +1462,7 @@ class _GenerateV7DSW(_DSWGenerator): 'SLN_RELATIVE_FOLDER_PATH': dsp_relative_folder_path, 'SLN_RELATIVE_FILE_PATH': dsp_relative_file_path} self.dspfiles_info.append(dspfile_info) - + self.dspfiles_info = [] GenerateProjectFilesInfo(self) @@ -1508,7 +1508,7 @@ class _GenerateV7DSW(_DSWGenerator): self.file.write('# Visual Studio 2008\n') elif self.version_num >= 8.0: self.file.write('# Visual Studio 2005\n') - + for dspinfo in self.dspfiles_info: name = dspinfo['NAME'] base, suffix = SCons.Util.splitext(name) @@ -1970,7 +1970,7 @@ def generate(env): else: env['MSVS']['PROJECTSUFFIX'] = '.vcxproj' env['MSVS']['SOLUTIONSUFFIX'] = '.sln' - + if (version_num >= 10.0): env['MSVSENCODING'] = 'utf-8' else: diff --git a/src/engine/SCons/Tool/swig.py b/src/engine/SCons/Tool/swig.py index 9d1965d..fa86174 100644 --- a/src/engine/SCons/Tool/swig.py +++ b/src/engine/SCons/Tool/swig.py @@ -7,6 +7,7 @@ It will usually be imported through the generic SCons.Tool.Tool() selection method. """ +from __future__ import print_function # # __COPYRIGHT__ @@ -144,10 +145,10 @@ def _get_swig_version(env, swig): out = pipe.stdout.read() match = re.search(r'SWIG Version\s+(\S+).*', out, re.MULTILINE) if match: - if verbose: print "Version is:%s"%match.group(1) + if verbose: print("Version is:%s"%match.group(1)) return match.group(1) else: - if verbose: print "Unable to detect version: [%s]"%out + if verbose: print("Unable to detect version: [%s]"%out) def generate(env): """Add Builders and construction variables for swig to an Environment.""" diff --git a/src/engine/SCons/compat/six.py b/src/engine/SCons/compat/six.py index 019130f..0e8850c 100755 --- a/src/engine/SCons/compat/six.py +++ b/src/engine/SCons/compat/six.py @@ -43,7 +43,7 @@ if PY3: else: string_types = basestring, integer_types = (int, long) - class_types = (type, types.ClassType) + class_types = (type, type) text_type = unicode binary_type = str @@ -462,7 +462,7 @@ if PY3: Iterator = object else: def get_unbound_function(unbound): - return unbound.im_func + return unbound.__func__ def create_bound_method(func, obj): return types.MethodType(func, obj, obj.__class__) diff --git a/src/engine/SCons/compat/sixTests.py b/src/engine/SCons/compat/sixTests.py index f8c1979..71df78d 100644 --- a/src/engine/SCons/compat/sixTests.py +++ b/src/engine/SCons/compat/sixTests.py @@ -1,3 +1,4 @@ +from __future__ import print_function # # __COPYRIGHT__ # @@ -28,7 +29,7 @@ class sixTestCase(unittest.TestCase): def test_import(self): """Test that six imports correctly.""" import sys - print sys.path + print(sys.path) from SCons.compat.six import PY2, PY3 self.assertTrue(PY2 or PY3) diff --git a/src/engine/SCons/cppTests.py b/src/engine/SCons/cppTests.py index 9f4b875..28a1f5e 100644 --- a/src/engine/SCons/cppTests.py +++ b/src/engine/SCons/cppTests.py @@ -21,6 +21,8 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # +from __future__ import absolute_import + __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import atexit @@ -29,7 +31,7 @@ import unittest import TestUnit -import cpp +from . import cpp diff --git a/src/script/scons.py b/src/script/scons.py index b5476b9..0595717 100644 --- a/src/script/scons.py +++ b/src/script/scons.py @@ -23,6 +23,8 @@ # 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 print_function + __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" __version__ = "__VERSION__" diff --git a/src/setup.py b/src/setup.py index c036fb0..9a02b25 100644 --- a/src/setup.py +++ b/src/setup.py @@ -32,6 +32,8 @@ NOTE: Installed SCons is not importable like usual Python packages. It is below is dedicated to make it happen on various platforms. """ +from __future__ import print_function + __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os diff --git a/src/test_interrupts.py b/src/test_interrupts.py index de3a0db..b81ef3f 100644 --- a/src/test_interrupts.py +++ b/src/test_interrupts.py @@ -21,6 +21,8 @@ # 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 print_function + __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ diff --git a/test/LINK/VersionedLib.py b/test/LINK/VersionedLib.py index 3f4a912..468e3e5 100644 --- a/test/LINK/VersionedLib.py +++ b/test/LINK/VersionedLib.py @@ -1,286 +1,288 @@ -#!/usr/bin/env python -# -# __COPYRIGHT__ -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# 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. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -import os -import sys -import TestSCons - -import SCons.Platform -import SCons.Defaults - -env = SCons.Defaults.DefaultEnvironment() -platform = SCons.Platform.platform_default() -tool_list = SCons.Platform.DefaultToolList(platform, env) - -if 'gnulink' in tool_list: - test_plan = [ - { - 'libversion' : '2', - 'files' : [ 'libtest.so', 'libtest.so.2', 'test.os' ], - 'instfiles' : [ 'libtest.so', 'libtest.so.2' ], - 'symlinks' : [ ('libtest.so', 'libtest.so.2') ], - }, - { - 'libversion' : '2.5', - 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5', 'test.os' ], - 'instfiles' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5' ], - 'symlinks' : [ ('libtest.so', 'libtest.so.2.5'), ('libtest.so.2', 'libtest.so.2.5') ], - }, - { - 'libversion' : '2.5.4', - 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5.4', 'test.os' ], - 'instfiles' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5.4' ], - 'symlinks' : [ ('libtest.so', 'libtest.so.2.5.4'), ('libtest.so.2', 'libtest.so.2.5.4') ], - }, - { - 'libversion' : '2.5.4.7.8', - 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5.4.7.8', 'test.os' ], - 'instfiles' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5.4.7.8' ], - 'symlinks' : [ ('libtest.so', 'libtest.so.2.5.4.7.8'), ('libtest.so.2', 'libtest.so.2.5.4.7.8') ], - }, - { - 'libversion' : 'aabf114f', - 'files' : [ 'libtest.so', 'libtest.so.aabf114f', 'test.os' ], - 'instfiles' : [ 'libtest.so', 'libtest.so.aabf114f' ], - 'symlinks' : [ ('libtest.so', 'libtest.so.aabf114f') ], - }, - { - 'libversion' : '2.dfffa11', - 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.dfffa11', 'test.os' ], - 'instfiles' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.dfffa11' ], - 'symlinks' : [ ('libtest.so', 'libtest.so.2.dfffa11'), ('libtest.so.2', 'libtest.so.2.dfffa11') ], - }, - ] -elif 'applelink' in tool_list: - # All (?) the files we expect will get created in the current directory - test_plan = [ - { - 'libversion' : '2.5.4', - 'files' : [ 'libtest.dylib', 'libtest.2.5.4.dylib', 'test.os' ], - 'instfiles' : [ 'libtest.dylib', 'libtest.2.5.4.dylib' ], - 'symlinks' : [], - }, - ] -elif 'cyglink' in tool_list: - test_plan = [ - { - 'libversion' : '2', - 'files' : [ 'cygtest-2.dll', 'libtest-2.dll.a', 'libtest.dll.a', 'test.os' ], - 'instfiles' : [ 'cygtest-2.dll', 'libtest-2.dll.a', 'libtest.dll.a' ], - 'symlinks' : [ ('libtest.dll.a', 'libtest-2.dll.a') ], - }, - { - 'libversion' : '2.5', - 'files' : [ 'cygtest-2-5.dll', 'libtest-2-5.dll.a', 'libtest.dll.a', 'test.os' ], - 'instfiles' : [ 'cygtest-2-5.dll', 'libtest-2-5.dll.a', 'libtest.dll.a' ], - 'symlinks' : [ ('libtest.dll.a', 'libtest-2-5.dll.a') ], - }, - { - 'libversion' : '2.5.4', - 'files' : [ 'cygtest-2-5-4.dll', 'libtest-2-5-4.dll.a', 'libtest.dll.a', 'test.os' ], - 'instfiles' : [ 'cygtest-2-5-4.dll', 'libtest-2-5-4.dll.a', 'libtest.dll.a' ], - 'symlinks' : [ ('libtest.dll.a', 'libtest-2-5-4.dll.a') ], - }, - { - 'libversion' : '2.5.4.7.8', - 'files' : [ 'cygtest-2-5-4-7-8.dll', 'libtest-2-5-4-7-8.dll.a', 'libtest.dll.a', 'test.os' ], - 'instfiles' : [ 'cygtest-2-5-4-7-8.dll', 'libtest-2-5-4-7-8.dll.a', 'libtest.dll.a' ], - 'symlinks' : [ ('libtest.dll.a', 'libtest-2-5-4-7-8.dll.a') ], - }, - { - 'libversion' : 'aabf114f', - 'files' : [ 'cygtest-aabf114f.dll', 'libtest-aabf114f.dll.a', 'libtest.dll.a', 'test.os' ], - 'instfiles' : [ 'cygtest-aabf114f.dll', 'libtest-aabf114f.dll.a', 'libtest.dll.a' ], - 'symlinks' : [ ('libtest.dll.a', 'libtest-aabf114f.dll.a') ], - }, - { - 'libversion' : '2.dfffa11', - 'files' : [ 'cygtest-2-dfffa11.dll', 'libtest-2-dfffa11.dll.a', 'libtest.dll.a', 'test.os' ], - 'instfiles' : [ 'cygtest-2-dfffa11.dll', 'libtest-2-dfffa11.dll.a', 'libtest.dll.a' ], - 'symlinks' : [ ('libtest.dll.a', 'libtest-2-dfffa11.dll.a') ], - }, - ] -elif 'mslink' in tool_list: - test_plan = [ - { - 'libversion' : '2.5.4', - 'files' : [ 'test.dll', 'test.lib', 'test.obj' ], - 'instfiles' : [ 'test.dll', 'test.lib' ], - 'symlinks' : [], - }, - ] -elif 'sunlink' in tool_list: - test_plan = [ - { - 'libversion' : '2', - 'files' : [ 'libtest.so', 'libtest.so.2', 'so_test.os' ], - 'instfiles' : [ 'libtest.so', 'libtest.so.2' ], - 'symlinks' : [ ('libtest.so', 'libtest.so.2') ], - }, - { - 'libversion' : '2.5', - 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5', 'so_test.os' ], - 'instfiles' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5' ], - 'symlinks' : [ ('libtest.so', 'libtest.so.2.5'), ('libtest.so.2', 'libtest.so.2.5') ], - }, - { - 'libversion' : '2.5.4', - 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5.4', 'so_test.os' ], - 'instfiles' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5.4' ], - 'symlinks' : [ ('libtest.so', 'libtest.so.2.5.4'), ('libtest.so.2', 'libtest.so.2.5.4') ], - }, - { - 'libversion' : '2.5.4.7.8', - 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5.4.7.8', 'so_test.os' ], - 'instfiles' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5.4.7.8' ], - 'symlinks' : [ ('libtest.so', 'libtest.so.2.5.4.7.8'), ('libtest.so.2', 'libtest.so.2.5.4.7.8') ], - }, - { - 'libversion' : 'aabf114f', - 'files' : [ 'libtest.so', 'libtest.so.aabf114f', 'so_test.os' ], - 'instfiles' : [ 'libtest.so', 'libtest.so.aabf114f' ], - 'symlinks' : [ ('libtest.so', 'libtest.so.aabf114f') ], - }, - { - 'libversion' : '2.dfffa11', - 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.dfffa11', 'so_test.os' ], - 'instfiles' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.dfffa11' ], - 'symlinks' : [ ('libtest.so', 'libtest.so.2.dfffa11'), ('libtest.so.2', 'libtest.so.2.dfffa11') ], - }, - ] -else: - test_plan = [ - { - 'libversion' : '2.5.4', - 'files' : [ 'libtest.so', 'test.os' ], - 'instfiles' : [ ], - }, - ] - -test_c_src = """\ -#if _WIN32 -__declspec(dllexport) -#endif -int testlib(int n) { return n+1 ; } -""" - -test_c_src2 = """\ -#if _WIN32 -__declspec(dllexport) -#endif -int testlib(int n) { return n+11 ; } -""" - -testapp_c_src = """\ -#if _WIN32 -__declspec(dllimport) -#endif -int testlib(int n); -#include -int main(int argc, char **argv) -{ -int itest ; - -itest = testlib(2) ; -printf("results: testlib(2) = %d\\n",itest) ; -return 0 ; -} -""" - -for t in test_plan: - - test = TestSCons.TestSCons() - - libversion = t['libversion'] - files = t['files'] - symlinks = t['symlinks'] - instfiles = t['instfiles'] - - test.write('SConstruct', """\ -import os -env = Environment() -objs = env.SharedObject('test.c') -mylib = env.SharedLibrary('test', objs, SHLIBVERSION = '%s') -env.Program('testapp1.c', LIBS = mylib, LIBPATH='.') -env.Program('testapp2.c', LIBS = ['test'], LIBPATH='.') -instnode = env.InstallVersionedLib("#/installtest",mylib) -env.Default(instnode) - -# Extra test to ensure that InstallVersionedLib can be called from the DefaultEnvironment -# Ensures orthogonality where InstallVersionedLib wasn't previously available: SCons gave NameError. -instnode = InstallVersionedLib("defaultenv-installtest",mylib) -Default(instnode) - -""" % libversion) - - test.write('test.c', test_c_src) - test.write('testapp1.c', testapp_c_src) - test.write('testapp2.c', testapp_c_src) - - test.run(arguments = ['--tree=all']) - - for f in files: - test.must_exist([ f]) - for f in instfiles: - test.must_exist(['installtest', f]) - test.must_exist(['defaultenv-installtest', f]) - - wrong_symlinks = [] - for (linkname,expected) in symlinks: - try: - endpoint = os.readlink(linkname) - except OSError, err: - print "%s (expected symlink %r -> %r)" % (err, linkname, expected) - wrong_symlinks.append(linkname) - else: - if endpoint != expected: - print "Wrong symlink: %r -> %r (expected symlink: %r -> %r)" % (linkname, endpoint, linkname, expected) - wrong_symlinks.append(linkname) - - if wrong_symlinks: - test.fail_test(wrong_symlinks) - - # modify test.c and make sure it can recompile when links already exist - test.write('test.c', test_c_src2) - - test.run() - - test.run(arguments = ['-c']) - - for f in files: - test.must_not_exist([ f]) - - for f in instfiles: - test.must_not_exist(['installtest', f]) - test.must_not_exist(['defaultenv-installtest', f]) - -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# 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 print_function + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import os +import sys +import TestSCons + +import SCons.Platform +import SCons.Defaults + +env = SCons.Defaults.DefaultEnvironment() +platform = SCons.Platform.platform_default() +tool_list = SCons.Platform.DefaultToolList(platform, env) + +if 'gnulink' in tool_list: + test_plan = [ + { + 'libversion' : '2', + 'files' : [ 'libtest.so', 'libtest.so.2', 'test.os' ], + 'instfiles' : [ 'libtest.so', 'libtest.so.2' ], + 'symlinks' : [ ('libtest.so', 'libtest.so.2') ], + }, + { + 'libversion' : '2.5', + 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5', 'test.os' ], + 'instfiles' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5' ], + 'symlinks' : [ ('libtest.so', 'libtest.so.2.5'), ('libtest.so.2', 'libtest.so.2.5') ], + }, + { + 'libversion' : '2.5.4', + 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5.4', 'test.os' ], + 'instfiles' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5.4' ], + 'symlinks' : [ ('libtest.so', 'libtest.so.2.5.4'), ('libtest.so.2', 'libtest.so.2.5.4') ], + }, + { + 'libversion' : '2.5.4.7.8', + 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5.4.7.8', 'test.os' ], + 'instfiles' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5.4.7.8' ], + 'symlinks' : [ ('libtest.so', 'libtest.so.2.5.4.7.8'), ('libtest.so.2', 'libtest.so.2.5.4.7.8') ], + }, + { + 'libversion' : 'aabf114f', + 'files' : [ 'libtest.so', 'libtest.so.aabf114f', 'test.os' ], + 'instfiles' : [ 'libtest.so', 'libtest.so.aabf114f' ], + 'symlinks' : [ ('libtest.so', 'libtest.so.aabf114f') ], + }, + { + 'libversion' : '2.dfffa11', + 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.dfffa11', 'test.os' ], + 'instfiles' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.dfffa11' ], + 'symlinks' : [ ('libtest.so', 'libtest.so.2.dfffa11'), ('libtest.so.2', 'libtest.so.2.dfffa11') ], + }, + ] +elif 'applelink' in tool_list: + # All (?) the files we expect will get created in the current directory + test_plan = [ + { + 'libversion' : '2.5.4', + 'files' : [ 'libtest.dylib', 'libtest.2.5.4.dylib', 'test.os' ], + 'instfiles' : [ 'libtest.dylib', 'libtest.2.5.4.dylib' ], + 'symlinks' : [], + }, + ] +elif 'cyglink' in tool_list: + test_plan = [ + { + 'libversion' : '2', + 'files' : [ 'cygtest-2.dll', 'libtest-2.dll.a', 'libtest.dll.a', 'test.os' ], + 'instfiles' : [ 'cygtest-2.dll', 'libtest-2.dll.a', 'libtest.dll.a' ], + 'symlinks' : [ ('libtest.dll.a', 'libtest-2.dll.a') ], + }, + { + 'libversion' : '2.5', + 'files' : [ 'cygtest-2-5.dll', 'libtest-2-5.dll.a', 'libtest.dll.a', 'test.os' ], + 'instfiles' : [ 'cygtest-2-5.dll', 'libtest-2-5.dll.a', 'libtest.dll.a' ], + 'symlinks' : [ ('libtest.dll.a', 'libtest-2-5.dll.a') ], + }, + { + 'libversion' : '2.5.4', + 'files' : [ 'cygtest-2-5-4.dll', 'libtest-2-5-4.dll.a', 'libtest.dll.a', 'test.os' ], + 'instfiles' : [ 'cygtest-2-5-4.dll', 'libtest-2-5-4.dll.a', 'libtest.dll.a' ], + 'symlinks' : [ ('libtest.dll.a', 'libtest-2-5-4.dll.a') ], + }, + { + 'libversion' : '2.5.4.7.8', + 'files' : [ 'cygtest-2-5-4-7-8.dll', 'libtest-2-5-4-7-8.dll.a', 'libtest.dll.a', 'test.os' ], + 'instfiles' : [ 'cygtest-2-5-4-7-8.dll', 'libtest-2-5-4-7-8.dll.a', 'libtest.dll.a' ], + 'symlinks' : [ ('libtest.dll.a', 'libtest-2-5-4-7-8.dll.a') ], + }, + { + 'libversion' : 'aabf114f', + 'files' : [ 'cygtest-aabf114f.dll', 'libtest-aabf114f.dll.a', 'libtest.dll.a', 'test.os' ], + 'instfiles' : [ 'cygtest-aabf114f.dll', 'libtest-aabf114f.dll.a', 'libtest.dll.a' ], + 'symlinks' : [ ('libtest.dll.a', 'libtest-aabf114f.dll.a') ], + }, + { + 'libversion' : '2.dfffa11', + 'files' : [ 'cygtest-2-dfffa11.dll', 'libtest-2-dfffa11.dll.a', 'libtest.dll.a', 'test.os' ], + 'instfiles' : [ 'cygtest-2-dfffa11.dll', 'libtest-2-dfffa11.dll.a', 'libtest.dll.a' ], + 'symlinks' : [ ('libtest.dll.a', 'libtest-2-dfffa11.dll.a') ], + }, + ] +elif 'mslink' in tool_list: + test_plan = [ + { + 'libversion' : '2.5.4', + 'files' : [ 'test.dll', 'test.lib', 'test.obj' ], + 'instfiles' : [ 'test.dll', 'test.lib' ], + 'symlinks' : [], + }, + ] +elif 'sunlink' in tool_list: + test_plan = [ + { + 'libversion' : '2', + 'files' : [ 'libtest.so', 'libtest.so.2', 'so_test.os' ], + 'instfiles' : [ 'libtest.so', 'libtest.so.2' ], + 'symlinks' : [ ('libtest.so', 'libtest.so.2') ], + }, + { + 'libversion' : '2.5', + 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5', 'so_test.os' ], + 'instfiles' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5' ], + 'symlinks' : [ ('libtest.so', 'libtest.so.2.5'), ('libtest.so.2', 'libtest.so.2.5') ], + }, + { + 'libversion' : '2.5.4', + 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5.4', 'so_test.os' ], + 'instfiles' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5.4' ], + 'symlinks' : [ ('libtest.so', 'libtest.so.2.5.4'), ('libtest.so.2', 'libtest.so.2.5.4') ], + }, + { + 'libversion' : '2.5.4.7.8', + 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5.4.7.8', 'so_test.os' ], + 'instfiles' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5.4.7.8' ], + 'symlinks' : [ ('libtest.so', 'libtest.so.2.5.4.7.8'), ('libtest.so.2', 'libtest.so.2.5.4.7.8') ], + }, + { + 'libversion' : 'aabf114f', + 'files' : [ 'libtest.so', 'libtest.so.aabf114f', 'so_test.os' ], + 'instfiles' : [ 'libtest.so', 'libtest.so.aabf114f' ], + 'symlinks' : [ ('libtest.so', 'libtest.so.aabf114f') ], + }, + { + 'libversion' : '2.dfffa11', + 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.dfffa11', 'so_test.os' ], + 'instfiles' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.dfffa11' ], + 'symlinks' : [ ('libtest.so', 'libtest.so.2.dfffa11'), ('libtest.so.2', 'libtest.so.2.dfffa11') ], + }, + ] +else: + test_plan = [ + { + 'libversion' : '2.5.4', + 'files' : [ 'libtest.so', 'test.os' ], + 'instfiles' : [ ], + }, + ] + +test_c_src = """\ +#if _WIN32 +__declspec(dllexport) +#endif +int testlib(int n) { return n+1 ; } +""" + +test_c_src2 = """\ +#if _WIN32 +__declspec(dllexport) +#endif +int testlib(int n) { return n+11 ; } +""" + +testapp_c_src = """\ +#if _WIN32 +__declspec(dllimport) +#endif +int testlib(int n); +#include +int main(int argc, char **argv) +{ +int itest ; + +itest = testlib(2) ; +printf("results: testlib(2) = %d\\n",itest) ; +return 0 ; +} +""" + +for t in test_plan: + + test = TestSCons.TestSCons() + + libversion = t['libversion'] + files = t['files'] + symlinks = t['symlinks'] + instfiles = t['instfiles'] + + test.write('SConstruct', """\ +import os +env = Environment() +objs = env.SharedObject('test.c') +mylib = env.SharedLibrary('test', objs, SHLIBVERSION = '%s') +env.Program('testapp1.c', LIBS = mylib, LIBPATH='.') +env.Program('testapp2.c', LIBS = ['test'], LIBPATH='.') +instnode = env.InstallVersionedLib("#/installtest",mylib) +env.Default(instnode) + +# Extra test to ensure that InstallVersionedLib can be called from the DefaultEnvironment +# Ensures orthogonality where InstallVersionedLib wasn't previously available: SCons gave NameError. +instnode = InstallVersionedLib("defaultenv-installtest",mylib) +Default(instnode) + +""" % libversion) + + test.write('test.c', test_c_src) + test.write('testapp1.c', testapp_c_src) + test.write('testapp2.c', testapp_c_src) + + test.run(arguments = ['--tree=all']) + + for f in files: + test.must_exist([ f]) + for f in instfiles: + test.must_exist(['installtest', f]) + test.must_exist(['defaultenv-installtest', f]) + + wrong_symlinks = [] + for (linkname,expected) in symlinks: + try: + endpoint = os.readlink(linkname) + except OSError as err: + print("%s (expected symlink %r -> %r)" % (err, linkname, expected)) + wrong_symlinks.append(linkname) + else: + if endpoint != expected: + print("Wrong symlink: %r -> %r (expected symlink: %r -> %r)" % (linkname, endpoint, linkname, expected)) + wrong_symlinks.append(linkname) + + if wrong_symlinks: + test.fail_test(wrong_symlinks) + + # modify test.c and make sure it can recompile when links already exist + test.write('test.c', test_c_src2) + + test.run() + + test.run(arguments = ['-c']) + + for f in files: + test.must_not_exist([ f]) + + for f in instfiles: + test.must_not_exist(['installtest', f]) + test.must_not_exist(['defaultenv-installtest', f]) + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/option/debug-multiple.py b/test/option/debug-multiple.py index f5bbdf0..f121a2c 100644 --- a/test/option/debug-multiple.py +++ b/test/option/debug-multiple.py @@ -21,6 +21,8 @@ # 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 print_function + __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ @@ -65,16 +67,16 @@ for args in ['--debug=prepare,count', '--debug=count,prepare']: missing = [o for o in objects if find_object_count(o, stdout) is None] if missing: - print "Missing the following object lines from '%s' output:" % args - print "\t", ' '.join(missing) - print "STDOUT ==========" - print stdout + print("Missing the following object lines from '%s' output:" % args) + print("\t", ' '.join(missing)) + print("STDOUT ==========") + print(stdout) test.fail_test(1) if 'Preparing target file.out...' not in stdout: - print "Missing 'Preparing' lines from '%s' output:" % args - print "STDOUT ==========" - print stdout + print("Missing 'Preparing' lines from '%s' output:" % args) + print("STDOUT ==========") + print(stdout) test.fail_test(1) test.pass_test() diff --git a/test/site_scons/sysdirs.py b/test/site_scons/sysdirs.py index 663700b..60b4f0b 100644 --- a/test/site_scons/sysdirs.py +++ b/test/site_scons/sysdirs.py @@ -22,6 +22,8 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # +from __future__ import print_function + __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import TestSCons @@ -54,10 +56,10 @@ else: dir_to_check_for='.scons' if 'Loading site dir' not in test.stdout(): - print test.stdout() + print(test.stdout()) test.fail_test() if dir_to_check_for not in test.stdout(): - print test.stdout() + print(test.stdout()) test.fail_test() test.pass_test() -- cgit v0.12 From 85aa9baee353e5a7710cb34932ea7ed09a847e39 Mon Sep 17 00:00:00 2001 From: Russel Winder Date: Fri, 1 Jan 2016 14:00:42 +0000 Subject: Amend some missed print functions. --- QMTest/TestCommon.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/QMTest/TestCommon.py b/QMTest/TestCommon.py index 7387e18..f878636 100644 --- a/QMTest/TestCommon.py +++ b/QMTest/TestCommon.py @@ -92,6 +92,7 @@ The TestCommon module also provides the following variables # PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, # AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + from __future__ import print_function __author__ = "Steven Knight " @@ -307,10 +308,10 @@ class TestCommon(TestCmd): if find(output, input) is None: if title is None: title = 'output' - print 'Missing expected input from %s:' % title - print input - print self.banner(title + ' ') - print output + print('Missing expected input from {}:'.format(title)) + print(input) + print(self.banner(title + ' ')) + print(output) self.fail_test() def must_contain_all_lines(self, output, lines, title=None, find=None): -- cgit v0.12 From d49c6b49f2add08d6a1984f9602fa383d698ba96 Mon Sep 17 00:00:00 2001 From: Dirk Baechle Date: Fri, 1 Jan 2016 15:31:19 +0100 Subject: - fixed internal debugging of Taskmaster --- src/engine/SCons/Taskmaster.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py index 069ac90..86cae42 100644 --- a/src/engine/SCons/Taskmaster.py +++ b/src/engine/SCons/Taskmaster.py @@ -107,7 +107,7 @@ fmt = "%(considered)3d "\ def dump_stats(): for n in sorted(StatsNodes, key=lambda a: str(a)): - print (fmt % n.stats.__dict__) + str(n) + print (fmt % n.attributes.stats.__dict__) + str(n) @@ -781,10 +781,10 @@ class Taskmaster(object): # return node if CollectStats: - if not hasattr(node, 'stats'): - node.stats = Stats() + if not hasattr(node.attributes, 'stats'): + node.attributes.stats = Stats() StatsNodes.append(node) - S = node.stats + S = node.attributes.stats S.considered = S.considered + 1 else: S = None -- cgit v0.12 From e9989979ac3411919935afe3a8c8c70ebbc4fd58 Mon Sep 17 00:00:00 2001 From: Russel Winder Date: Fri, 1 Jan 2016 15:01:27 +0000 Subject: Some more print statements to functions. --- SConstruct | 5 +++-- doc/SConscript | 3 ++- src/engine/SCons/SConsign.py | 10 +++++----- src/engine/SCons/compat/sixTests.py | 4 ++-- src/engine/SCons/dblite.py | 1 - src/script/sconsign.py | 3 ++- test/ARGLIST.py | 2 +- test/Actions/pre-post.py | 22 +++++++++++----------- test/AddMethod.py | 8 ++++---- test/AddOption/basic.py | 4 ++-- test/CC/CFLAGS.py | 10 +++++----- .../convenience-functions/image/SConstruct | 5 +++-- 12 files changed, 40 insertions(+), 37 deletions(-) diff --git a/SConstruct b/SConstruct index 8734c2e..1616fc2 100644 --- a/SConstruct +++ b/SConstruct @@ -2,6 +2,7 @@ # SConstruct file to build scons packages during development. # # See the README.rst file for an overview of how SCons is built and tested. + from __future__ import print_function copyright_years = '2001 - 2015' @@ -162,7 +163,7 @@ import distutils.command no_winpack_templates = not os.path.exists(os.path.join(os.path.split(distutils.command.__file__)[0],'wininst-9.0.exe')) skip_win_packages = ARGUMENTS.get('SKIP_WIN_PACKAGES',False) or no_winpack_templates if skip_win_packages: - print "Skipping the build of Windows packages..." + print("Skipping the build of Windows packages...") python_ver = sys.version[0:3] @@ -1049,7 +1050,7 @@ for p in [ scons ]: # The built deb is called just x.y.z, not x.y.z.final.0 so strip those off: deb_version = '.'.join(version.split('.')[0:3]) deb = os.path.join(build_dir, 'dist', "%s_%s_all.deb" % (pkg, deb_version)) - # print "Building deb into %s (version=%s)"%(deb, deb_version) + # print("Building deb into %s (version=%s)"%(deb, deb_version)) for d in p['debian_deps']: b = env.SCons_revision(os.path.join(build, d), d) env.Depends(deb, b) diff --git a/doc/SConscript b/doc/SConscript index 6dbf33d..7e6aaeb 100644 --- a/doc/SConscript +++ b/doc/SConscript @@ -23,6 +23,7 @@ # 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 print_function import os.path @@ -52,7 +53,7 @@ fop = whereis('fop') xep = whereis('xep') if not fop and not xep: - print "doc: No PDF renderer found (fop|xep)!" + print("doc: No PDF renderer found (fop|xep)!") skip_doc = True # diff --git a/src/engine/SCons/SConsign.py b/src/engine/SCons/SConsign.py index 970c35c..cb089aa 100644 --- a/src/engine/SCons/SConsign.py +++ b/src/engine/SCons/SConsign.py @@ -26,6 +26,7 @@ Writing and reading information to the .sconsign file or files. # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -33,7 +34,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.compat import os -# compat layer imports "cPickle" for us if it's available. import pickle import SCons.dblite @@ -125,16 +125,16 @@ class SConsignEntry(object): """ __slots__ = ("binfo", "ninfo", "__weakref__") current_version_id = 2 - + def __init__(self): # Create an object attribute from the class attribute so it ends up # in the pickled data in the .sconsign file. #_version_id = self.current_version_id pass - + def convert_to_sconsign(self): self.binfo.convert_to_sconsign() - + def convert_from_sconsign(self, dir, name): self.binfo.convert_from_sconsign(dir, name) @@ -156,7 +156,7 @@ class SConsignEntry(object): for key, value in state.items(): if key not in ('_version_id','__weakref__'): setattr(self, key, value) - + class Base(object): """ This is the controlling class for the signatures for the collection of diff --git a/src/engine/SCons/compat/sixTests.py b/src/engine/SCons/compat/sixTests.py index 71df78d..8be3572 100644 --- a/src/engine/SCons/compat/sixTests.py +++ b/src/engine/SCons/compat/sixTests.py @@ -1,4 +1,3 @@ -from __future__ import print_function # # __COPYRIGHT__ # @@ -22,6 +21,8 @@ from __future__ import print_function # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # +from __future__ import print_function + import unittest class sixTestCase(unittest.TestCase): @@ -32,4 +33,3 @@ class sixTestCase(unittest.TestCase): print(sys.path) from SCons.compat.six import PY2, PY3 self.assertTrue(PY2 or PY3) - diff --git a/src/engine/SCons/dblite.py b/src/engine/SCons/dblite.py index 3be6cb2..b12d320 100644 --- a/src/engine/SCons/dblite.py +++ b/src/engine/SCons/dblite.py @@ -5,7 +5,6 @@ from __future__ import print_function import SCons.compat import os -# compat layer imports "cPickle" for us if it's available. import pickle import shutil import time diff --git a/src/script/sconsign.py b/src/script/sconsign.py index 1a4caf7..daf088e 100644 --- a/src/script/sconsign.py +++ b/src/script/sconsign.py @@ -22,6 +22,7 @@ # 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 print_function from SCons.compat.six import PY2, PY3 @@ -185,7 +186,7 @@ sys.path = libs + sys.path # END STANDARD SCons SCRIPT HEADER ############################################################################## -import SCons.compat # so pickle will import cPickle instead +import SCons.compat if PY2: import whichdb diff --git a/test/ARGLIST.py b/test/ARGLIST.py index 186ad06..e246ba3 100644 --- a/test/ARGLIST.py +++ b/test/ARGLIST.py @@ -31,7 +31,7 @@ test = TestSCons.TestSCons() test.write('SConstruct', """ i = 0 for key, value in ARGLIST: - print "%d: %s = %s" % (i, key, value) + print("%d: %s = %s" % (i, key, value)) i = i + 1 """) diff --git a/test/Actions/pre-post.py b/test/Actions/pre-post.py index e09ee02..179e914 100644 --- a/test/Actions/pre-post.py +++ b/test/Actions/pre-post.py @@ -118,14 +118,14 @@ def b(target, source, env): env1 = Environment(X='111') env2 = Environment(X='222') B = Builder(action = b, env = env1, multi=1) -print "B =", B -print "B.env =", B.env +print("B =", B) +print("B.env =", B.env) env1.Append(BUILDERS = {'B' : B}) env2.Append(BUILDERS = {'B' : B}) env3 = env1.Clone(X='333') -print "env1 =", env1 -print "env2 =", env2 -print "env3 =", env3 +print("env1 =", env1) +print("env2 =", env2) +print("env3 =", env3) f1 = env1.B(File('file1.out'), []) f2 = env2.B('file2.out', []) f3 = env3.B('file3.out', []) @@ -133,12 +133,12 @@ def do_nothing(env, target, source): pass AddPreAction(f2[0], do_nothing) AddPostAction(f3[0], do_nothing) -print "f1[0].builder =", f1[0].builder -print "f2[0].builder =", f2[0].builder -print "f3[0].builder =", f3[0].builder -print "f1[0].env =", f1[0].env -print "f2[0].env =", f2[0].env -print "f3[0].env =", f3[0].env +print("f1[0].builder =", f1[0].builder) +print("f2[0].builder =", f2[0].builder) +print("f3[0].builder =", f3[0].builder) +print("f1[0].env =", f1[0].env) +print("f2[0].env =", f2[0].env) +print("f3[0].env =", f3[0].env) """) test.run(chdir='work2', arguments = '.') diff --git a/test/AddMethod.py b/test/AddMethod.py index af84cb3..6049ae2 100644 --- a/test/AddMethod.py +++ b/test/AddMethod.py @@ -40,10 +40,10 @@ def foo(self): AddMethod(Environment, foo) env = Environment(FOO = '111') -print env.foo() +print(env.foo()) env = Environment(FOO = '222') -print env.foo() +print(env.foo()) env.AddMethod(foo, 'bar') env['FOO'] = '333' @@ -51,8 +51,8 @@ env['FOO'] = '333' e = env.Clone() e['FOO'] = '444' -print env.bar() -print e.bar() +print(env.bar()) +print(e.bar()) """) expect = """\ diff --git a/test/AddOption/basic.py b/test/AddOption/basic.py index a1bb7b3..b1b8f2e 100644 --- a/test/AddOption/basic.py +++ b/test/AddOption/basic.py @@ -48,8 +48,8 @@ AddOption('--prefix', f = GetOption('force') if f: f = "True" -print f -print GetOption('prefix') +print(f) +print(GetOption('prefix')) """) test.run('-Q -q .', diff --git a/test/CC/CFLAGS.py b/test/CC/CFLAGS.py index 6ea87ad..590d6b5 100644 --- a/test/CC/CFLAGS.py +++ b/test/CC/CFLAGS.py @@ -32,10 +32,10 @@ test = TestSCons.TestSCons() # Make sure CFLAGS is not passed to CXX by just expanding CXXCOM test.write('SConstruct', """ env = Environment(CFLAGS='-xyz', CCFLAGS='-abc') -print env.subst('$CXXCOM') -print env.subst('$CXXCOMSTR') -print env.subst('$SHCXXCOM') -print env.subst('$SHCXXCOMSTR') +print(env.subst('$CXXCOM')) +print(env.subst('$CXXCOMSTR')) +print(env.subst('$SHCXXCOM')) +print(env.subst('$SHCXXCOMSTR')) """) test.run(arguments = '.') test.must_not_contain_any_line(test.stdout(), ["-xyz"]) @@ -46,7 +46,7 @@ _obj = TestSCons._obj # Test passing CFLAGS to C compiler by actually compiling programs if sys.platform == 'win32': import SCons.Tool.MSCommon as msc - + if not msc.msvc_exists(): fooflags = '-DFOO' barflags = '-DBAR' diff --git a/test/packaging/convenience-functions/image/SConstruct b/test/packaging/convenience-functions/image/SConstruct index 461961e..f35c3e3 100644 --- a/test/packaging/convenience-functions/image/SConstruct +++ b/test/packaging/convenience-functions/image/SConstruct @@ -1,3 +1,4 @@ +from __future__ import print_function env = Environment(tools=['default', 'packaging']) prog = env.Install( 'bin/', ["f1", "f2"] ) @@ -6,5 +7,5 @@ env.File( "f3" ) src_files = sorted(map(str, env.FindSourceFiles())) oth_files = sorted(map(str, env.FindInstalledFiles())) -print src_files -print oth_files +print(src_files) +print(oth_files) -- cgit v0.12 From 7b68ccb54e7b4d2200f8ac813eb6f8b2ae3654eb Mon Sep 17 00:00:00 2001 From: Russel Winder Date: Fri, 1 Jan 2016 15:23:41 +0000 Subject: Some more print statements to functions. --- test/Actions/actions.py | 10 +++--- test/AddOption/optional-arg.py | 2 +- test/CPPDEFINES/append.py | 52 ++++++++++++++++---------------- test/CPPDEFINES/basic.py | 6 ++-- test/CPPDEFINES/undefined.py | 4 +-- test/CacheDir/scanner-target.py | 2 +- test/CacheDir/source-scanner.py | 2 +- test/Climb/filename--D.py | 4 +-- test/Climb/filename--U.py | 4 +-- test/Climb/filename-u.py | 4 +-- test/Clone-compatibility.py | 4 +-- test/Configure/Streamer1.py | 2 +- test/Configure/cache-not-ok.py | 2 +- test/ConstructionEnvironment.py | 2 +- test/Deprecated/Options/BoolOption.py | 4 +-- test/Deprecated/Options/Options.py | 26 ++++++++-------- test/Deprecated/Options/PackageOption.py | 2 +- test/Deprecated/Options/PathOption.py | 16 +++++----- test/Deprecated/Options/chdir.py | 2 +- test/Deprecated/Options/help.py | 6 ++-- test/Deprecated/Options/import.py | 2 +- test/Dir/Dir.py | 12 ++++---- 22 files changed, 85 insertions(+), 85 deletions(-) diff --git a/test/Actions/actions.py b/test/Actions/actions.py index 03d67a0..785a0cb 100644 --- a/test/Actions/actions.py +++ b/test/Actions/actions.py @@ -70,7 +70,7 @@ import os def func(env, target, source): cmd = r'%(_python_)s build.py %%s 3 %%s' %% (' '.join(map(str, target)), ' '.join(map(str, source))) - print cmd + print(cmd) return os.system(cmd) B = Builder(action = func) env = Environment(BUILDERS = { 'B' : B }) @@ -91,7 +91,7 @@ class bld(object): self.cmd = r'%(_python_)s build.py %%s 4 %%s' def __call__(self, env, target, source): cmd = self.get_contents(env, target, source) - print cmd + print(cmd) return os.system(cmd) def get_contents(self, env, target, source): return self.cmd %% (' '.join(map(str, target)), @@ -114,9 +114,9 @@ def func(env, target, source): env = Environment(S = Action('foo'), F = Action(func), L = Action(['arg1', 'arg2'])) -print env.subst('$S') -print env.subst('$F') -print env.subst('$L') +print(env.subst('$S')) +print(env.subst('$F')) +print(env.subst('$L')) """) test.run(arguments = '-Q .', stdout = """\ diff --git a/test/AddOption/optional-arg.py b/test/AddOption/optional-arg.py index f976ad9..b88b796 100644 --- a/test/AddOption/optional-arg.py +++ b/test/AddOption/optional-arg.py @@ -43,7 +43,7 @@ AddOption('--install', type='string', metavar='DIR', help='installation directory') -print GetOption('install') +print(GetOption('install')) """) test.run('-Q -q', diff --git a/test/CPPDEFINES/append.py b/test/CPPDEFINES/append.py index 6e69d09..432ab64 100644 --- a/test/CPPDEFINES/append.py +++ b/test/CPPDEFINES/append.py @@ -40,17 +40,17 @@ test.write('SConstruct', """\ env_1738_2 = Environment(CPPDEFPREFIX='-D') env_1738_2['CPPDEFINES'] = ['FOO'] env_1738_2.Append(CPPDEFINES={'value' : '1'}) -print env_1738_2.subst('$_CPPDEFFLAGS') +print(env_1738_2.subst('$_CPPDEFFLAGS')) #env_1738_2.Object('test_1738_2', 'main.c') # http://scons.tigris.org/issues/show_bug.cgi?id=2300 env_2300_1 = Environment(CPPDEFINES = 'foo', CPPDEFPREFIX='-D') env_2300_1.Append(CPPDEFINES='bar') -print env_2300_1.subst('$_CPPDEFFLAGS') +print(env_2300_1.subst('$_CPPDEFFLAGS')) env_2300_2 = Environment(CPPDEFINES = ['foo'], CPPDEFPREFIX='-D') # note the list env_2300_2.Append(CPPDEFINES='bar') -print env_2300_2.subst('$_CPPDEFFLAGS') +print(env_2300_2.subst('$_CPPDEFFLAGS')) # http://scons.tigris.org/issues/show_bug.cgi?id=1152 # http://scons.tigris.org/issues/show_bug.cgi?id=2900 @@ -62,18 +62,18 @@ cases=[('string', 'FOO'), for (t1, c1) in cases: for (t2, c2) in cases: - print "==== Testing CPPDEFINES, appending a %s to a %s"%(t2, t1) - print " orig = %s, append = %s"%(c1, c2) + print("==== Testing CPPDEFINES, appending a %s to a %s"%(t2, t1)) + print(" orig = %s, append = %s"%(c1, c2)) env=Environment(CPPDEFINES = c1, CPPDEFPREFIX='-D') env.Append(CPPDEFINES = c2) final=env.subst('$_CPPDEFFLAGS',source="src", target="tgt") - print 'Append: \\n\\tresult=%s\\n\\tfinal=%s'%\\ - (env['CPPDEFINES'], final) + print('Append: \\n\\tresult=%s\\n\\tfinal=%s'%\\ + (env['CPPDEFINES'], final)) env=Environment(CPPDEFINES = c1, CPPDEFPREFIX='-D') env.AppendUnique(CPPDEFINES = c2) final=env.subst('$_CPPDEFFLAGS',source="src", target="tgt") - print 'AppendUnique:\\n\\tresult=%s\\n\\tfinal=%s'%\\ - (env['CPPDEFINES'], final) + print('AppendUnique:\\n\\tresult=%s\\n\\tfinal=%s'%\\ + (env['CPPDEFINES'], final)) """) @@ -83,7 +83,7 @@ expect_print_output="""\ -Dfoo -Dbar ==== Testing CPPDEFINES, appending a string to a string orig = FOO, append = FOO -Append: +Append: result=['FOO', 'FOO'] final=-DFOO -DFOO AppendUnique: @@ -91,7 +91,7 @@ AppendUnique: final=-DFOO ==== Testing CPPDEFINES, appending a list to a string orig = FOO, append = ['NAME1', 'NAME2'] -Append: +Append: result=['FOO', 'NAME1', 'NAME2'] final=-DFOO -DNAME1 -DNAME2 AppendUnique: @@ -99,7 +99,7 @@ AppendUnique: final=-DFOO -DNAME1 -DNAME2 ==== Testing CPPDEFINES, appending a list-of-2lists to a string orig = FOO, append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] -Append: +Append: result=['FOO', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] final=-DFOO -DNAME1=VAL1 -DNAME2=VAL2 AppendUnique: @@ -107,7 +107,7 @@ AppendUnique: final=-DFOO -DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, appending a dict to a string orig = FOO, append = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} -Append: +Append: result=['FOO', {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}] final=-DFOO -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 AppendUnique: @@ -115,7 +115,7 @@ AppendUnique: final=-DFOO -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a string to a list orig = ['NAME1', 'NAME2'], append = FOO -Append: +Append: result=['NAME1', 'NAME2', 'FOO'] final=-DNAME1 -DNAME2 -DFOO AppendUnique: @@ -123,7 +123,7 @@ AppendUnique: final=-DNAME1 -DNAME2 -DFOO ==== Testing CPPDEFINES, appending a list to a list orig = ['NAME1', 'NAME2'], append = ['NAME1', 'NAME2'] -Append: +Append: result=['NAME1', 'NAME2', 'NAME1', 'NAME2'] final=-DNAME1 -DNAME2 -DNAME1 -DNAME2 AppendUnique: @@ -131,7 +131,7 @@ AppendUnique: final=-DNAME1 -DNAME2 ==== Testing CPPDEFINES, appending a list-of-2lists to a list orig = ['NAME1', 'NAME2'], append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] -Append: +Append: result=['NAME1', 'NAME2', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] final=-DNAME1 -DNAME2 -DNAME1=VAL1 -DNAME2=VAL2 AppendUnique: @@ -139,7 +139,7 @@ AppendUnique: final=-DNAME1 -DNAME2 -DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, appending a dict to a list orig = ['NAME1', 'NAME2'], append = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} -Append: +Append: result=['NAME1', 'NAME2', {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}] final=-DNAME1 -DNAME2 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 AppendUnique: @@ -147,7 +147,7 @@ AppendUnique: final=-DNAME1 -DNAME2 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a string to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = FOO -Append: +Append: result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'FOO'] final=-DNAME1=VAL1 -DNAME2=VAL2 -DFOO AppendUnique: @@ -155,7 +155,7 @@ AppendUnique: final=-DNAME1=VAL1 -DNAME2=VAL2 -DFOO ==== Testing CPPDEFINES, appending a list to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = ['NAME1', 'NAME2'] -Append: +Append: result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'NAME1', 'NAME2'] final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1 -DNAME2 AppendUnique: @@ -163,7 +163,7 @@ AppendUnique: final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1 -DNAME2 ==== Testing CPPDEFINES, appending a list-of-2lists to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] -Append: +Append: result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1=VAL1 -DNAME2=VAL2 AppendUnique: @@ -171,7 +171,7 @@ AppendUnique: final=-DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, appending a dict to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} -Append: +Append: result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}] final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 AppendUnique: @@ -179,7 +179,7 @@ AppendUnique: final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a string to a dict orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, append = FOO -Append: +Append: result={'FOO': None, 'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} final=-DFOO -DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 AppendUnique: @@ -187,7 +187,7 @@ AppendUnique: final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DFOO ==== Testing CPPDEFINES, appending a list to a dict orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, append = ['NAME1', 'NAME2'] -Append: +Append: result=[('NAME2', 'VAL2'), ('NAME3',), ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1 -DNAME2 AppendUnique: @@ -195,7 +195,7 @@ AppendUnique: final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1 -DNAME2 ==== Testing CPPDEFINES, appending a list-of-2lists to a dict orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] -Append: +Append: result=[('NAME2', 'VAL2'), ('NAME3',), ('NAME1', 'VAL1'), ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1=VAL1 -DNAME2=VAL2 AppendUnique: @@ -203,7 +203,7 @@ AppendUnique: final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a dict to a dict orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, append = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} -Append: +Append: result={'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 AppendUnique: @@ -213,7 +213,7 @@ AppendUnique: build_output="scons: `.' is up to date.\n" -expect = test.wrap_stdout(build_str=build_output, +expect = test.wrap_stdout(build_str=build_output, read_str = expect_print_output) test.run(arguments = '.', stdout=expect) test.pass_test() diff --git a/test/CPPDEFINES/basic.py b/test/CPPDEFINES/basic.py index b54a421..57d7260 100644 --- a/test/CPPDEFINES/basic.py +++ b/test/CPPDEFINES/basic.py @@ -41,13 +41,13 @@ test_list = [ ] for i in test_list: env = Environment(CPPDEFPREFIX='-D', CPPDEFSUFFIX='', INTEGER=0) - print env.Clone(CPPDEFINES=i).subst('$_CPPDEFFLAGS') + print(env.Clone(CPPDEFINES=i).subst('$_CPPDEFFLAGS')) for i in test_list: env = Environment(CPPDEFPREFIX='|', CPPDEFSUFFIX='|', INTEGER=1) - print env.Clone(CPPDEFINES=i).subst('$_CPPDEFFLAGS') + print(env.Clone(CPPDEFINES=i).subst('$_CPPDEFFLAGS')) """) -expect = test.wrap_stdout(build_str="scons: `.' is up to date.\n", +expect = test.wrap_stdout(build_str="scons: `.' is up to date.\n", read_str = """\ -Dxyz -Dx -Dy -Dz diff --git a/test/CPPDEFINES/undefined.py b/test/CPPDEFINES/undefined.py index 47825b6..b26b05a 100644 --- a/test/CPPDEFINES/undefined.py +++ b/test/CPPDEFINES/undefined.py @@ -34,10 +34,10 @@ test = TestSCons.TestSCons() test.write('SConstruct', """\ env = Environment() -print env.subst('$_CPPDEFFLAGS') +print(env.subst('$_CPPDEFFLAGS')) """) -expect = test.wrap_stdout(build_str="scons: `.' is up to date.\n", +expect = test.wrap_stdout(build_str="scons: `.' is up to date.\n", read_str = "\n") test.run(arguments = '.', stdout=expect) diff --git a/test/CacheDir/scanner-target.py b/test/CacheDir/scanner-target.py index 645b597..c39042e 100644 --- a/test/CacheDir/scanner-target.py +++ b/test/CacheDir/scanner-target.py @@ -52,7 +52,7 @@ def docopy(target,source,env): f.close() def sillyScanner(node, env, dirs): - print 'This is never called (unless we build file.out)' + print('This is never called (unless we build file.out)') return [] SillyScanner = SCons.Scanner.Base(function = sillyScanner, skeys = ['.res']) diff --git a/test/CacheDir/source-scanner.py b/test/CacheDir/source-scanner.py index e7db5e9..2359872 100644 --- a/test/CacheDir/source-scanner.py +++ b/test/CacheDir/source-scanner.py @@ -54,7 +54,7 @@ def docopy(target,source,env): f.close() def sillyScanner(node, env, dirs): - print 'This is never called (unless we build file.out)' + print('This is never called (unless we build file.out)') return [] SillyScanner = SCons.Scanner.Base(function = sillyScanner, skeys = ['.res']) diff --git a/test/Climb/filename--D.py b/test/Climb/filename--D.py index 06d95e7..6fea9bc 100644 --- a/test/Climb/filename--D.py +++ b/test/Climb/filename--D.py @@ -36,12 +36,12 @@ test = TestSCons.TestSCons() test.subdir('subdir', 'other') test.write('main.scons', """\ -print "main.scons" +print("main.scons") SConscript('subdir/sub.scons') """) test.write(['subdir', 'sub.scons'], """\ -print "subdir/sub.scons" +print("subdir/sub.scons") """) diff --git a/test/Climb/filename--U.py b/test/Climb/filename--U.py index 7f2e60d..49ccc0a 100644 --- a/test/Climb/filename--U.py +++ b/test/Climb/filename--U.py @@ -36,12 +36,12 @@ test = TestSCons.TestSCons() test.subdir('subdir', 'other') test.write('main.scons', """\ -print "main.scons" +print("main.scons") SConscript('subdir/sub.scons') """) test.write(['subdir', 'sub.scons'], """\ -print "subdir/sub.scons" +print("subdir/sub.scons") """) read_str = """\ diff --git a/test/Climb/filename-u.py b/test/Climb/filename-u.py index 7bae153..4485c4b 100644 --- a/test/Climb/filename-u.py +++ b/test/Climb/filename-u.py @@ -36,12 +36,12 @@ test = TestSCons.TestSCons() test.subdir('subdir', 'other') test.write('main.scons', """\ -print "main.scons" +print("main.scons") SConscript('subdir/sub.scons') """) test.write(['subdir', 'sub.scons'], """\ -print "subdir/sub.scons" +print("subdir/sub.scons") """) read_str = """\ diff --git a/test/Clone-compatibility.py b/test/Clone-compatibility.py index 089b7a4..a2f6362 100644 --- a/test/Clone-compatibility.py +++ b/test/Clone-compatibility.py @@ -48,8 +48,8 @@ except AttributeError: env1 = Environment(X = 1) env2 = env1.Clone(X = 2) -print env1['X'] -print env2['X'] +print(env1['X']) +print(env2['X']) """) test.run(arguments = '-q -Q', stdout = "1\n2\n") diff --git a/test/Configure/Streamer1.py b/test/Configure/Streamer1.py index 8f35308..318a936 100644 --- a/test/Configure/Streamer1.py +++ b/test/Configure/Streamer1.py @@ -45,7 +45,7 @@ test.write('SConstruct', """ def hello(target, source, env): import traceback try: - print 'hello!\\n' # this breaks the script + print('hello!\\n') # this breaks the script with open(env.subst('$TARGET', target = target),'w') as f: f.write('yes') except: diff --git a/test/Configure/cache-not-ok.py b/test/Configure/cache-not-ok.py index ccbb7d5..7502f7a 100644 --- a/test/Configure/cache-not-ok.py +++ b/test/Configure/cache-not-ok.py @@ -53,7 +53,7 @@ r1 = conf.CheckCHeader( 'no_std_c_header.h' ) # leads to compile error r2 = conf.CheckLib( 'no_c_library_SAFFDG' ) # leads to link error env = conf.Finish() if not (not r1 and not r2): - print "FAIL: ", r1, r2 + print("FAIL: ", r1, r2) Exit(1) """) diff --git a/test/ConstructionEnvironment.py b/test/ConstructionEnvironment.py index bec46b9..e25f86a 100644 --- a/test/ConstructionEnvironment.py +++ b/test/ConstructionEnvironment.py @@ -38,7 +38,7 @@ import SCons.Defaults SCons.Defaults.ConstructionEnvironment.update({ 'XXX' : 777, }) -print DefaultEnvironment()['XXX'] +print(DefaultEnvironment()['XXX']) """) expect = test.wrap_stdout(read_str = "777\n", diff --git a/test/Deprecated/Options/BoolOption.py b/test/Deprecated/Options/BoolOption.py index 563939b..5d12fc6 100644 --- a/test/Deprecated/Options/BoolOption.py +++ b/test/Deprecated/Options/BoolOption.py @@ -55,8 +55,8 @@ opts.AddOptions( env = Environment(options=opts) Help(opts.GenerateHelpText(env)) -print env['warnings'] -print env['profile'] +print(env['warnings']) +print(env['profile']) Default(env.Alias('dummy', None)) """) diff --git a/test/Deprecated/Options/Options.py b/test/Deprecated/Options/Options.py index 61a12f3..e435b9e 100644 --- a/test/Deprecated/Options/Options.py +++ b/test/Deprecated/Options/Options.py @@ -30,8 +30,8 @@ test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) test.write('SConstruct', """ env = Environment() -print env['CC'] -print " ".join(env['CCFLAGS']) +print(env['CC']) +print(" ".join(env['CCFLAGS'])) Default(env.Alias('dummy', None)) """) test.run() @@ -99,12 +99,12 @@ env = Environment(options=opts, tools=['default', test_tool]) Help('Variables settable in custom.py or on the command line:\\n' + opts.GenerateHelpText(env)) -print env['RELEASE_BUILD'] -print env['DEBUG_BUILD'] -print env['CC'] -print " ".join(env['CCFLAGS']) -print env['VALIDATE'] -print env['valid_key'] +print(env['RELEASE_BUILD']) +print(env['DEBUG_BUILD']) +print(env['CC']) +print(" ".join(env['CCFLAGS'])) +print(env['VALIDATE']) +print(env['valid_key']) # unspecified options should not be set: assert 'UNSPECIFIED' not in env @@ -226,8 +226,8 @@ opts.Add('UNSPECIFIED', env = Environment(options = opts) -print env['RELEASE_BUILD'] -print env['DEBUG_BUILD'] +print(env['RELEASE_BUILD']) +print(env['DEBUG_BUILD']) opts.Save('options.saved', env) """) @@ -282,9 +282,9 @@ opts.Add('LISTOPTION_TEST', env = Environment(options = opts) -print env['RELEASE_BUILD'] -print env['DEBUG_BUILD'] -print env['LISTOPTION_TEST'] +print(env['RELEASE_BUILD']) +print(env['DEBUG_BUILD']) +print(env['LISTOPTION_TEST']) opts.Save('options.saved', env) """) diff --git a/test/Deprecated/Options/PackageOption.py b/test/Deprecated/Options/PackageOption.py index 424e5a7..ec8990c 100644 --- a/test/Deprecated/Options/PackageOption.py +++ b/test/Deprecated/Options/PackageOption.py @@ -59,7 +59,7 @@ opts.AddOptions( env = Environment(options=opts) Help(opts.GenerateHelpText(env)) -print env['x11'] +print(env['x11']) Default(env.Alias('dummy', None)) """) diff --git a/test/Deprecated/Options/PathOption.py b/test/Deprecated/Options/PathOption.py index 4701420..0e6949c 100644 --- a/test/Deprecated/Options/PathOption.py +++ b/test/Deprecated/Options/PathOption.py @@ -25,7 +25,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ -Test the PathOption canned option type, with tests for its +Test the PathOption canned option type, with tests for its various canned validators. """ @@ -65,9 +65,9 @@ opts.AddOptions( env = Environment(options=opts) Help(opts.GenerateHelpText(env)) -print env['qtdir'] -print env['qt_libraries'] -print env.subst('$qt_libraries') +print(env['qtdir']) +print(env['qt_libraries']) +print(env.subst('$qt_libraries')) Default(env.Alias('dummy', None)) """ % (workpath, os.path.join('$qtdir', 'lib') )) @@ -144,7 +144,7 @@ opts.AddOptions( env = Environment(options=opts) -print env['X'] +print(env['X']) Default(env.Alias('dummy', None)) """ % default_subdir) @@ -177,7 +177,7 @@ opts.AddOptions( env = Environment(options=opts) -print env['X'] +print(env['X']) Default(env.Alias('dummy', None)) """ % default_file) @@ -218,7 +218,7 @@ opts.AddOptions( env = Environment(options=opts) -print env['X'] +print(env['X']) Default(env.Alias('dummy', None)) """ % default_subdir) @@ -263,7 +263,7 @@ opts.AddOptions( env = Environment(options=opts) -print env['X'] +print(env['X']) Default(env.Alias('dummy', None)) """ % default_subdir) diff --git a/test/Deprecated/Options/chdir.py b/test/Deprecated/Options/chdir.py index a8fb6c6..977a351 100644 --- a/test/Deprecated/Options/chdir.py +++ b/test/Deprecated/Options/chdir.py @@ -46,7 +46,7 @@ SConscript_contents = """\ Import("opts") env = Environment() opts.Update(env) -print "VARIABLE =", repr(env['VARIABLE']) +print("VARIABLE =", repr(env['VARIABLE'])) """ test.write(['bin', 'opts.cfg'], """\ diff --git a/test/Deprecated/Options/help.py b/test/Deprecated/Options/help.py index 8c240e3..ad8a96b 100644 --- a/test/Deprecated/Options/help.py +++ b/test/Deprecated/Options/help.py @@ -49,7 +49,7 @@ libdirvar_re = re.escape(libdirvar) test.subdir(qtpath) test.subdir(libpath) - + test.write('SConstruct', """ from SCons.Options import BoolOption, EnumOption, ListOption, \ PackageOption, PathOption @@ -86,8 +86,8 @@ opts.AddOptions( env = Environment(options=opts) Help(opts.GenerateHelpText(env)) -print env['warnings'] -print env['profile'] +print(env['warnings']) +print(env['profile']) Default(env.Alias('dummy', None)) """ % locals()) diff --git a/test/Deprecated/Options/import.py b/test/Deprecated/Options/import.py index a4d56b2..b93e6a2 100644 --- a/test/Deprecated/Options/import.py +++ b/test/Deprecated/Options/import.py @@ -48,7 +48,7 @@ SConscript_contents = """\ Import("opts") env = Environment() opts.Update(env) -print "VARIABLE =", env.get('VARIABLE') +print("VARIABLE =", env.get('VARIABLE')) """ test.write(['bin', 'opts.cfg'], """\ diff --git a/test/Dir/Dir.py b/test/Dir/Dir.py index af0a10b..2e8204c 100644 --- a/test/Dir/Dir.py +++ b/test/Dir/Dir.py @@ -36,12 +36,12 @@ test = TestSCons.TestSCons() test.write('SConstruct', """ env = Environment(FOO = 'fff', BAR = 'bbb') -print Dir('ddd') -print Dir('$FOO') -print Dir('${BAR}_$BAR') -print env.Dir('eee') -print env.Dir('$FOO') -print env.Dir('${BAR}_$BAR') +print(Dir('ddd')) +print(Dir('$FOO')) +print(Dir('${BAR}_$BAR')) +print(env.Dir('eee')) +print(env.Dir('$FOO')) +print(env.Dir('${BAR}_$BAR')) """) test.run(stdout = test.wrap_stdout(read_str = """\ -- cgit v0.12 From 3f637329635c089bdca30bb4b0e23334d12866b3 Mon Sep 17 00:00:00 2001 From: Russel Winder Date: Fri, 1 Jan 2016 15:59:23 +0000 Subject: Some more statement to function transforms. --- test/CPPDEFINES/pkg-config.py | 12 +++---- test/Deprecated/Options/EnumOption.py | 6 ++-- test/Deprecated/Options/ListOption.py | 16 ++++----- test/Entry.py | 12 +++---- test/Environment.py | 4 +-- test/Errors/Exception.py | 2 +- test/ExecuteInvalidateCache.py | 4 +-- test/Exit.py | 12 +++---- test/File.py | 16 ++++----- test/FindFile.py | 8 ++--- test/Flatten.py | 8 ++--- test/GetBuildFailures/parallel.py | 6 ++-- test/GetBuildFailures/serial.py | 4 +-- test/GetOption/help.py | 4 +-- test/Libs/SharedLibraryIxes.py | 16 ++++----- test/Mkdir.py | 2 +- test/NodeOps.py | 4 +-- test/ParseConfig.py | 32 +++++++++--------- test/Platform.py | 16 ++++----- test/QT/QTFLAGS.py | 8 ++--- test/QT/manual.py | 6 ++-- test/tool_args.py | 8 ++--- test/toolpath/basic.py | 62 +++++++++++++++++------------------ 23 files changed, 134 insertions(+), 134 deletions(-) diff --git a/test/CPPDEFINES/pkg-config.py b/test/CPPDEFINES/pkg-config.py index 1b308d3..4e81dec 100644 --- a/test/CPPDEFINES/pkg-config.py +++ b/test/CPPDEFINES/pkg-config.py @@ -60,26 +60,26 @@ test.write('SConstruct', """\ # Passing test cases env_1 = Environment(CPPDEFINES=[('DEBUG','1'), 'TEST']) env_1.ParseConfig('PKG_CONFIG_PATH=. %(pkg_config_path)s --cflags bug') -print env_1.subst('$_CPPDEFFLAGS') +print(env_1.subst('$_CPPDEFFLAGS')) env_2 = Environment(CPPDEFINES=[('DEBUG','1'), 'TEST']) env_2.MergeFlags('-DSOMETHING -DVARIABLE=2') -print env_2.subst('$_CPPDEFFLAGS') +print(env_2.subst('$_CPPDEFFLAGS')) # Failing test cases env_3 = Environment(CPPDEFINES={'DEBUG':1, 'TEST':None}) env_3.ParseConfig('PKG_CONFIG_PATH=. %(pkg_config_path)s --cflags bug') -print env_3.subst('$_CPPDEFFLAGS') +print(env_3.subst('$_CPPDEFFLAGS')) env_4 = Environment(CPPDEFINES={'DEBUG':1, 'TEST':None}) env_4.MergeFlags('-DSOMETHING -DVARIABLE=2') -print env_4.subst('$_CPPDEFFLAGS') +print(env_4.subst('$_CPPDEFFLAGS')) # http://scons.tigris.org/issues/show_bug.cgi?id=1738 env_1738_1 = Environment(tools=['default']) env_1738_1.ParseConfig('PKG_CONFIG_PATH=. %(pkg_config_path)s --cflags --libs bug') env_1738_1.Append(CPPDEFINES={'value' : '1'}) -print env_1738_1.subst('$_CPPDEFFLAGS') +print(env_1738_1.subst('$_CPPDEFFLAGS')) """%locals() ) expect_print_output="""\ @@ -92,7 +92,7 @@ expect_print_output="""\ build_output="scons: `.' is up to date.\n" -expect = test.wrap_stdout(build_str=build_output, +expect = test.wrap_stdout(build_str=build_output, read_str = expect_print_output) test.run(arguments = '.', stdout=expect) test.pass_test() diff --git a/test/Deprecated/Options/EnumOption.py b/test/Deprecated/Options/EnumOption.py index 57ae7eb..2b3ed47 100644 --- a/test/Deprecated/Options/EnumOption.py +++ b/test/Deprecated/Options/EnumOption.py @@ -66,9 +66,9 @@ opts.AddOptions( env = Environment(options=opts) Help(opts.GenerateHelpText(env)) -print env['debug'] -print env['guilib'] -print env['some'] +print(env['debug']) +print(env['guilib'] +print(env['some']) Default(env.Alias('dummy', None)) """) diff --git a/test/Deprecated/Options/ListOption.py b/test/Deprecated/Options/ListOption.py index bb3775b..ad804f2 100644 --- a/test/Deprecated/Options/ListOption.py +++ b/test/Deprecated/Options/ListOption.py @@ -67,15 +67,15 @@ env = Environment(options=opts) opts.Save(optsfile, env) Help(opts.GenerateHelpText(env)) -print env['shared'] -if 'ical' in env['shared']: print '1' -else: print '0' +print(env['shared']) +if 'ical' in env['shared']: print('1') +else: print('0') for x in env['shared']: - print x, -print -print env.subst('$shared') + print(x, end='') +print() +print(env.subst('$shared')) # Test subst_path() because it's used in $CPPDEFINES expansions. -print env.subst_path('$shared') +print(env.subst_path('$shared')) Default(env.Alias('dummy', None)) """) @@ -169,7 +169,7 @@ opts.AddOptions( env = Environment(options=opts) Help(opts.GenerateHelpText(env)) -print env['gpib'] +print(env['gpib']) Default(env.Alias('dummy', None)) """) diff --git a/test/Entry.py b/test/Entry.py index 3767cc5..3d3255d 100644 --- a/test/Entry.py +++ b/test/Entry.py @@ -36,12 +36,12 @@ test = TestSCons.TestSCons() test.write('SConstruct', """ env = Environment(FOO = 'fff', BAR = 'bbb') -print Entry('ddd') -print Entry('$FOO') -print Entry('${BAR}_$BAR') -print env.Entry('eee') -print env.Entry('$FOO') -print env.Entry('${BAR}_$BAR') +print(Entry('ddd')) +print(Entry('$FOO')) +print(Entry('${BAR}_$BAR')) +print(env.Entry('eee')) +print(env.Entry('$FOO')) +print(env.Entry('${BAR}_$BAR')) """) test.run(stdout = test.wrap_stdout(read_str = """\ diff --git a/test/Environment.py b/test/Environment.py index 52b6488..6810979 100644 --- a/test/Environment.py +++ b/test/Environment.py @@ -42,8 +42,8 @@ assert Dir('.') == Dir('.').Dir('.') assert target == target.File('foo.out') e2 = env.Environment(XXX='$BAR', YYY='$BLAT') -print e2['XXX'] -print e2['YYY'] +print(e2['XXX']) +print(e2['YYY']) """ % locals()) test.write('build.py', """ diff --git a/test/Errors/Exception.py b/test/Errors/Exception.py index cc36035..30404fc 100644 --- a/test/Errors/Exception.py +++ b/test/Errors/Exception.py @@ -30,7 +30,7 @@ test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) test.write('SConstruct', """\ def foo(env, target, source): - print str(target[0]) + print(str(target[0])) open(str(target[0]), 'wt').write('foo') def exit(env, target, source): diff --git a/test/ExecuteInvalidateCache.py b/test/ExecuteInvalidateCache.py index a22c5ea..6d8063e 100644 --- a/test/ExecuteInvalidateCache.py +++ b/test/ExecuteInvalidateCache.py @@ -40,9 +40,9 @@ subfn = os.path.join('sub', 'foo') test.write('SConstruct', """\ def exists(node): if node.exists(): - print str(node), "exists" + print(str(node), "exists") else: - print str(node), "does not exist" + print(str(node), "does not exist") Execute(Delete('abc')) n1 = File('abc') diff --git a/test/Exit.py b/test/Exit.py index 877a0b6..394ee2f 100644 --- a/test/Exit.py +++ b/test/Exit.py @@ -40,7 +40,7 @@ subdir_foo_in = os.path.join('subdir', 'foo.in') subdir_foo_out = os.path.join('subdir', 'foo.out') test.write('SConstruct', """\ -print "SConstruct, Exit()" +print("SConstruct, Exit()") Exit() """) @@ -51,7 +51,7 @@ SConstruct, Exit() test.write('SConstruct', """\ env = Environment() -print "SConstruct, env.Exit()" +print("SConstruct, env.Exit()") env.Exit() """) @@ -61,7 +61,7 @@ SConstruct, env.Exit() """) test.write('SConstruct', """\ -print "SConstruct" +print("SConstruct") Exit(7) """) @@ -71,12 +71,12 @@ SConstruct """) test.write('SConstruct', """\ -print "SConstruct" +print("SConstruct") SConscript('subdir/SConscript') """) test.write(['subdir', 'SConscript'], """\ -print "subdir/SConscript" +print("subdir/SConscript") Exit() """) @@ -87,7 +87,7 @@ subdir/SConscript """) test.write(['subdir', 'SConscript'], """\ -print "subdir/SConscript" +print("subdir/SConscript") Exit(17) """) diff --git a/test/File.py b/test/File.py index d919884..ec148b2 100644 --- a/test/File.py +++ b/test/File.py @@ -38,16 +38,16 @@ test = TestSCons.TestSCons() test.write('SConstruct', """ env = Environment(FOO = 'fff', BAR = 'bbb') -print File('ddd') -print File('$FOO') -print File('${BAR}_$BAR') -print env.File('eee') -print env.File('$FOO') -print env.File('${BAR}_$BAR') +print(File('ddd')) +print(File('$FOO')) +print(File('${BAR}_$BAR')) +print(env.File('eee')) +print(env.File('$FOO')) +print(env.File('${BAR}_$BAR')) f1 = env.File('f1') -print f1 +print(f1) f2 = f1.File('f2') -print f2 +print(f2) """) expect = test.wrap_stdout(read_str = """\ diff --git a/test/FindFile.py b/test/FindFile.py index 5d198ac..e878172 100644 --- a/test/FindFile.py +++ b/test/FindFile.py @@ -40,13 +40,13 @@ test.write(['bar', 'baz', 'testfile2'], 'test 4\n') test.write('SConstruct', """ env = Environment(FILE = 'file', BAR = 'bar') file1 = FindFile('testfile1', [ 'foo', '.', 'bar', 'bar/baz' ]) -print open(str(file1), 'r').read() +print(open(str(file1), 'r').read()) file2 = env.FindFile('test${FILE}1', [ 'bar', 'foo', '.', 'bar/baz' ]) -print open(str(file2), 'r').read() +print(open(str(file2), 'r').read()) file3 = FindFile('testfile2', [ 'foo', '.', 'bar', 'bar/baz' ]) -print open(str(file3), 'r').read() +print(open(str(file3), 'r').read()) file4 = env.FindFile('testfile2', [ '$BAR/baz', 'foo', '.', 'bar' ]) -print open(str(file4), 'r').read() +print(open(str(file4), 'r').read()) """) expect = test.wrap_stdout(read_str = """test 1 diff --git a/test/Flatten.py b/test/Flatten.py index b41c4fe..fd9943d 100644 --- a/test/Flatten.py +++ b/test/Flatten.py @@ -44,15 +44,15 @@ def cat(env, source, target): env = Environment(BUILDERS={'Cat':Builder(action=cat)}) f1 = env.Cat('../file1.out', 'file1.in') f2 = env.Cat('../file2.out', ['file2a.in', 'file2b.in']) -print list(map(str, Flatten(['begin', f1, 'middle', f2, 'end']))) -print list(map(str, env.Flatten([f1, [['a', 'b'], 'c'], f2]))) +print(list(map(str, Flatten(['begin', f1, 'middle', f2, 'end'])))) +print(list(map(str, env.Flatten([f1, [['a', 'b'], 'c'], f2])))) SConscript('SConscript', "env") """) test.write(['work', 'SConscript'], """ Import("env") -print Flatten([1, [2, 3], 4]) -print env.Flatten([[[[1], 2], 3], 4]) +print(Flatten([1, [2, 3], 4])) +print(env.Flatten([[[[1], 2], 3], 4])) """) test.write('file1.in', "file1.in\n") diff --git a/test/GetBuildFailures/parallel.py b/test/GetBuildFailures/parallel.py index e746d53..ee0e831 100644 --- a/test/GetBuildFailures/parallel.py +++ b/test/GetBuildFailures/parallel.py @@ -81,7 +81,7 @@ Command('f6', 'f6.in', r'@%(_python_)s mypass.py f5 - $TARGET $SOURCE') def print_build_failures(): from SCons.Script import GetBuildFailures for bf in sorted(GetBuildFailures(), key=lambda t: t.filename): - print "%%s failed: %%s" %% (bf.node, bf.errstr) + print("%%s failed: %%s" %% (bf.node, bf.errstr)) import atexit atexit.register(print_build_failures) @@ -96,7 +96,7 @@ test.run(arguments = '-Q -j 4 .', status = 2, stderr = None) -f4_error = "scons: *** [f4] Error 1\n" +f4_error = "scons: *** [f4] Error 1\n" f5_error = "scons: *** [f5] Error 1\n" error_45 = f4_error + f5_error @@ -129,7 +129,7 @@ if test.stdout() not in [failed_45, failed_54]: test.must_match(test.workpath('f3'), 'f3.in\n') test.must_not_exist(test.workpath('f4')) test.must_not_exist(test.workpath('f5')) -test.must_match(test.workpath('f6'), 'f6.in\n') +test.must_match(test.workpath('f6'), 'f6.in\n') diff --git a/test/GetBuildFailures/serial.py b/test/GetBuildFailures/serial.py index 9c56bb1..fb59c7c 100644 --- a/test/GetBuildFailures/serial.py +++ b/test/GetBuildFailures/serial.py @@ -91,9 +91,9 @@ def print_build_failures(): from SCons.Script import GetBuildFailures for bf in sorted(GetBuildFailures(), key=lambda t: str(t.node)): assert( isinstance(bf, SCons.Errors.BuildError) ) - print "BF: %%s failed (%%s): %%s" %% (bf.node, bf.status, bf.errstr) + print("BF: %%s failed (%%s): %%s" %% (bf.node, bf.status, bf.errstr)) if bf.command: - print "BF: %%s" %% " ".join(Flatten(bf.command)) + print("BF: %%s" %% " ".join(Flatten(bf.command))) import atexit atexit.register(print_build_failures) diff --git a/test/GetOption/help.py b/test/GetOption/help.py index e2eeef7..4f15fe6 100644 --- a/test/GetOption/help.py +++ b/test/GetOption/help.py @@ -34,9 +34,9 @@ test = TestSCons.TestSCons() test.write('SConstruct', """\ if GetOption('help'): - print "GetOption('help') set" + print("GetOption('help') set") else: - print "no help for you" + print("no help for you") """) test.run(arguments = '-q -Q', stdout = "no help for you\n") diff --git a/test/Libs/SharedLibraryIxes.py b/test/Libs/SharedLibraryIxes.py index 6924769..93d67ea 100644 --- a/test/Libs/SharedLibraryIxes.py +++ b/test/Libs/SharedLibraryIxes.py @@ -102,7 +102,7 @@ def nameInLib(source, lib, libname): # When using non-standard prefixes and suffixes, one has to # provide the full name of the library since scons can not know # which of the non-standard extension to use. - # + # # Note that this is not necessarily SHLIBPREFIX and # SHLIBSUFFIX. These are the ixes of the target library, not the # ixes of the library that we are linking against. @@ -130,7 +130,7 @@ def buildAndlinkAgainst(builder, target, source, method, lib, libname, **kw): # for the linker command line... if (isMingw or isCygwin) and len(lib) > 1: lib = lib[1:] - + # Apply the naming method to be tested and call the specified Builder. (source, LIBS) = method(source, lib, libname) #build = builder(target=target, source=source, LIBS=LIBS, **kw) @@ -153,8 +153,8 @@ def buildAndlinkAgainst(builder, target, source, method, lib, libname, **kw): (list(map(str,lib)), list(map(str, build[0].children())), method.__name__, libname, shlibsuffix) return build -def prog(i, - goomethod, goolibprefix, goolibsuffix, +def prog(i, + goomethod, goolibprefix, goolibsuffix, foomethod, foolibprefix, foolibsuffix): '''Build a program @@ -166,7 +166,7 @@ def prog(i, foo_name = foolibprefix+'foo'+str(i)+foolibsuffix prog_name = progprefix+'prog'+str(i)+progsuffix - print 'Prog: %d, %s, %s, %s' % (i, goo_name, foo_name, prog_name) + print('Prog: %d, %s, %s, %s' % (i, goo_name, foo_name, prog_name)) # On Windows, we have to link against the .lib file. if isWindows: @@ -179,7 +179,7 @@ def prog(i, goo_lib = env.SharedLibrary( goo_name, goo_obj, SHLIBSUFFIX=goolibsuffix) foo_lib = buildAndlinkAgainst( - env.SharedLibrary, foo_name, foo_obj, + env.SharedLibrary, foo_name, foo_obj, goomethod, goo_lib, goo_libname, SHLIBSUFFIX=foolibsuffix) prog = buildAndlinkAgainst(env.Program, prog_name, prog_obj, foomethod, foo_lib, foo_libname) @@ -199,8 +199,8 @@ for foolibprefix in prefixes: for goolibsuffix in suffixes: for goomethod in libmethods: tests.append( - (i, - goomethod, goolibprefix, goolibsuffix, + (i, + goomethod, goolibprefix, goolibsuffix, foomethod, foolibprefix, foolibsuffix)) i = i + 1 diff --git a/test/Mkdir.py b/test/Mkdir.py index 4d309bb..8ace476 100644 --- a/test/Mkdir.py +++ b/test/Mkdir.py @@ -178,7 +178,7 @@ test.write(['work3', 'sub1', 'sub11', 'SConscript'], """\ #/sub1/sub11/SConscript------------------------- Import('env test1') test11 = test1 + '/test11' -print 'test11 = ' + test11 +print('test11 = ' + test11) env.Command(Dir(test11), '', Mkdir('$TARGET')) """) diff --git a/test/NodeOps.py b/test/NodeOps.py index 5062b72..1f856c3 100644 --- a/test/NodeOps.py +++ b/test/NodeOps.py @@ -43,7 +43,7 @@ _lib = TestSCons._lib _obj = TestSCons._obj dll_ = TestSCons.dll_ _dll = TestSCons._dll - + if os.name == 'posix': os.environ['LD_LIBRARY_PATH'] = '.' if sys.platform.find('irix') > -1: @@ -71,7 +71,7 @@ if %(_E)s: exists = [N.exists() for N in Nodes] real2 = [os.path.exists(str(N)) for N in Nodes] for N,D,R,E,F in zip(Nodes, derived, real1, exists, real2): - print '%%s: %%s %%s %%s %%s'%%(N,D,R,E,F) + print('%%s: %%s %%s %%s %%s'%%(N,D,R,E,F)) foo.SharedLibrary(target = 'foo', source = 'foo%(_obj)s') bar.SharedLibrary(target = 'bar', source = 'bar%(_obj)s') diff --git a/test/ParseConfig.py b/test/ParseConfig.py index 9bcc440..efb3a75 100644 --- a/test/ParseConfig.py +++ b/test/ParseConfig.py @@ -38,17 +38,17 @@ test_config3 = test.workpath('test-config3') # File node. # It used to be returned as the 'static_libs' output of ParseConfig. test.write(test_config1, """\ -print "-I/usr/include/fum -Ibar -X -arch i386" -print "-L/usr/fax -Lfoo -lxxx abc" +print("-I/usr/include/fum -Ibar -X -arch i386") +print("-L/usr/fax -Lfoo -lxxx abc") """) test.write(test_config2, """\ -print "-L foo -L lib_dir" +print("-L foo -L lib_dir") """) # This is like what wxWidgets does on OSX w/ Universal Binaries test.write(test_config3, """\ -print "-L foo -L lib_dir -isysroot /tmp -arch ppc -arch i386" +print("-L foo -L lib_dir -isysroot /tmp -arch ppc -arch i386") """) test.write('SConstruct1', """ @@ -56,10 +56,10 @@ env = Environment(CPPPATH = [], LIBPATH = [], LIBS = [], CCFLAGS = '-pipe -Wall') env.ParseConfig([r'%(_python_)s', r"%(test_config1)s", "--libs --cflags"]) env.ParseConfig([r'%(_python_)s', r"%(test_config2)s", "--libs --cflags"]) -print env['CPPPATH'] -print env['LIBPATH'] -print [str(x) for x in env['LIBS']] -print env['CCFLAGS'] +print(env['CPPPATH']) +print(env['LIBPATH']) +print([str(x) for x in env['LIBS']]) +print(env['CCFLAGS']) """ % locals()) test.write('SConstruct2', """ @@ -68,10 +68,10 @@ env = Environment(CPPPATH = [], LIBPATH = [], LIBS = [], PYTHON = r'%(_python_)s') env.ParseConfig(r"$PYTHON %(test_config1)s --libs --cflags") env.ParseConfig(r"$PYTHON %(test_config2)s --libs --cflags") -print env['CPPPATH'] -print env['LIBPATH'] -print [str(x) for x in env['LIBS']] -print env['CCFLAGS'] +print(env['CPPPATH']) +print(env['LIBPATH']) +print([str(x) for x in env['LIBS']]) +print(env['CCFLAGS']) """ % locals()) test.write('SConstruct3', """ @@ -79,10 +79,10 @@ env = Environment(CPPPATH = [], LIBPATH = [], LIBS = [], CCFLAGS = '-pipe -Wall', PYTHON = r'%(_python_)s') env.ParseConfig(r"$PYTHON %(test_config3)s --libs --cflags") -print env['CPPPATH'] -print env['LIBPATH'] -print [str(x) for x in env['LIBS']] -print env['CCFLAGS'] +print(env['CPPPATH']) +print(env['LIBPATH']) +print([str(x) for x in env['LIBS']]) +print(env['CCFLAGS']) """ % locals()) good_stdout = """\ diff --git a/test/Platform.py b/test/Platform.py index 23068c4..924dbc7 100644 --- a/test/Platform.py +++ b/test/Platform.py @@ -31,27 +31,27 @@ test = TestSCons.TestSCons() test.write('SConstruct', """ env = Environment() Platform('cygwin')(env) -print "'%s'" % env['PROGSUFFIX'] +print("'%s'" % env['PROGSUFFIX']) assert env['SHELL'] == 'sh' Platform('os2')(env) -print "'%s'" % env['PROGSUFFIX'] +print("'%s'" % env['PROGSUFFIX']) env.Platform('posix') -print "'%s'" % env['PROGSUFFIX'] +print("'%s'" % env['PROGSUFFIX']) Platform('win32')(env) -print "'%s'" % env['PROGSUFFIX'] +print("'%s'" % env['PROGSUFFIX']) SConscript('SConscript') """) test.write('SConscript', """ env = Environment() Platform('cygwin')(env) -print "'%s'" % env['LIBSUFFIX'] +print("'%s'" % env['LIBSUFFIX']) Platform('os2')(env) -print "'%s'" % env['LIBSUFFIX'] +print("'%s'" % env['LIBSUFFIX']) env.Platform('posix') -print "'%s'" % env['LIBSUFFIX'] +print("'%s'" % env['LIBSUFFIX']) Platform('win32')(env) -print "'%s'" % env['LIBSUFFIX'] +print("'%s'" % env['LIBSUFFIX']) """) expect = test.wrap_stdout(read_str = """'.exe' diff --git a/test/QT/QTFLAGS.py b/test/QT/QTFLAGS.py index 008397a..f6aa00f 100644 --- a/test/QT/QTFLAGS.py +++ b/test/QT/QTFLAGS.py @@ -136,7 +136,7 @@ int main() { """) test.run(chdir = 'work1', arguments = "mytest" + _exe) - + test.must_exist(['work1', 'mmmmocFromH.cxx'], ['work1', 'mocmocFromCpp.inl'], ['work1', 'an_ui_file.cxx'], @@ -168,15 +168,15 @@ env1 = Environment(tools=['qt'], cpppath = env1.subst('$CPPPATH') if os.path.normpath(cpppath) != os.path.join(r'%(QTDIR)s', 'h64'): - print cpppath + print(cpppath) Exit(1) libpath = env1.subst('$LIBPATH') if os.path.normpath(libpath) != os.path.join(r'%(QTDIR)s', 'lib64'): - print libpath + print(libpath) Exit(2) qt_moc = env1.subst('$QT_MOC') if os.path.normpath(qt_moc) != os.path.join(r'%(QTDIR)s', 'bin64', 'moc'): - print qt_moc + print(qt_moc) Exit(3) env2 = Environment(tools=['default', 'qt'], diff --git a/test/QT/manual.py b/test/QT/manual.py index d911fb3..1f140ae 100644 --- a/test/QT/manual.py +++ b/test/QT/manual.py @@ -58,7 +58,7 @@ env.Ignore( moc, moc ) sources.extend(env.Uic(['include/uic_fff.hpp', 'fff.cpp', 'fff.moc.cpp'], 'ui/fff.ui')[1:]) -print list(map(str,sources)) +print(list(map(str,sources))) env.Program(target='aaa', source=sources, CPPPATH=['$CPPPATH', './include'], @@ -68,7 +68,7 @@ env.Program(target='aaa', test.write('aaa.cpp', r""" #include "aaa.h" """) - + test.write(['include', 'aaa.h'], r""" #include "my_qobject.h" void aaa(void) Q_OBJECT; @@ -91,7 +91,7 @@ void ccc(void) test.write('ddd.cpp', r""" #include "ddd.h" """) - + test.write(['include', 'ddd.h'], r""" #include "my_qobject.h" void ddd(void) Q_OBJECT; diff --git a/test/tool_args.py b/test/tool_args.py index 692f6a5..b0f69ef 100644 --- a/test/tool_args.py +++ b/test/tool_args.py @@ -38,13 +38,13 @@ test = TestSCons.TestSCons() test.write('SConstruct', """ # Test passing kw args to Tool constructor env1 = Environment(tools=[Tool('FooTool', toolpath=['.'], kw1='kw1val')]) -print "env1['TOOL_FOO'] =", env1.get('TOOL_FOO') -print "env1['kw1'] =", env1.get('kw1') +print("env1['TOOL_FOO'] =", env1.get('TOOL_FOO')) +print("env1['kw1'] =", env1.get('kw1')) # Test apply_tools taking a list of (name, kwargs_dict) env2 = Environment(tools=[('FooTool', {'kw2':'kw2val'})], toolpath=['.']) -print "env2['TOOL_FOO'] =", env2.get('TOOL_FOO') -print "env2['kw2'] =", env2.get('kw2') +print("env2['TOOL_FOO'] =", env2.get('TOOL_FOO')) +print("env2['kw2'] =", env2.get('kw2')) """) diff --git a/test/toolpath/basic.py b/test/toolpath/basic.py index e1e6f3c..eedd06e 100644 --- a/test/toolpath/basic.py +++ b/test/toolpath/basic.py @@ -33,63 +33,63 @@ test = TestSCons.TestSCons() test.write('SConstruct', """ def foo(env): env['TOOL_FOO'] = 1 - + env1 = Environment(tools=[foo, 'bar'], toolpath=['tools']) -print "env1['TOOL_FOO'] =", env1.get('TOOL_FOO') -print "env1['TOOL_BAR'] =", env1.get('TOOL_BAR') +print("env1['TOOL_FOO'] =", env1.get('TOOL_FOO')) +print("env1['TOOL_BAR'] =", env1.get('TOOL_BAR')) # pick a built-in tool with pretty simple behavior env2 = Environment(tools=['SCCS']) -print "env2['SCCS'] =", env2.get('SCCS') -print "env2['TOOL_SCCS1'] =", env2.get('TOOL_SCCS1') -print "env2['TOOL_SCCS2'] =", env2.get('TOOL_SCCS2') +print("env2['SCCS'] =", env2.get('SCCS') +print("env2['TOOL_SCCS1'] =", env2.get('TOOL_SCCS1')) +print("env2['TOOL_SCCS2'] =", env2.get('TOOL_SCCS2')) env3 = Environment(tools=['SCCS'], toolpath=['.']) -print "env3['SCCS'] =", env3.get('SCCS') -print "env3['TOOL_SCCS1'] =", env3.get('TOOL_SCCS1') -print "env3['TOOL_SCCS2'] =", env3.get('TOOL_SCCS2') +print("env3['SCCS'] =", env3.get('SCCS') +print("env3['TOOL_SCCS1'] =", env3.get('TOOL_SCCS1')) +print("env3['TOOL_SCCS2'] =", env3.get('TOOL_SCCS2')) env4 = Environment(tools=['SCCS'], toolpath=['tools']) -print "env4['SCCS'] =", env4.get('SCCS') -print "env4['TOOL_SCCS1'] =", env4.get('TOOL_SCCS1') -print "env4['TOOL_SCCS2'] =", env4.get('TOOL_SCCS2') +print("env4['SCCS'] =", env4.get('SCCS')) +print("env4['TOOL_SCCS1'] =", env4.get('TOOL_SCCS1')) +print("env4['TOOL_SCCS2'] =", env4.get('TOOL_SCCS2')) env5 = Environment(tools=['SCCS'], toolpath=['tools', '.']) -print "env5['SCCS'] =", env5.get('SCCS') -print "env5['TOOL_SCCS1'] =", env5.get('TOOL_SCCS1') -print "env5['TOOL_SCCS2'] =", env5.get('TOOL_SCCS2') +print("env5['SCCS'] =", env5.get('SCCS')) +print("env5['TOOL_SCCS1'] =", env5.get('TOOL_SCCS1')) +print("env5['TOOL_SCCS2'] =", env5.get('TOOL_SCCS2')) env6 = Environment(tools=['SCCS'], toolpath=['.', 'tools']) -print "env6['SCCS'] =", env6.get('SCCS') -print "env6['TOOL_SCCS1'] =", env6.get('TOOL_SCCS1') -print "env6['TOOL_SCCS2'] =", env6.get('TOOL_SCCS2') +print("env6['SCCS'] =", env6.get('SCCS')) +print("env6['TOOL_SCCS1'] =", env6.get('TOOL_SCCS1')) +print("env6['TOOL_SCCS2'] =", env6.get('TOOL_SCCS2')) env7 = Environment(TOOLPATH="tools", tools=['SCCS'], toolpath=['$TOOLPATH']) -print "env7['SCCS'] =", env7.get('SCCS') -print "env7['TOOL_SCCS1'] =", env7.get('TOOL_SCCS1') -print "env7['TOOL_SCCS2'] =", env7.get('TOOL_SCCS2') +print("env7['SCCS'] =", env7.get('SCCS')) +print("env7['TOOL_SCCS1'] =", env7.get('TOOL_SCCS1')) +print("env7['TOOL_SCCS2'] =", env7.get('TOOL_SCCS2')) env8 = Environment(tools=[]) env8.Tool('SCCS', toolpath=['tools']) -print "env8['SCCS'] =", env8.get('SCCS') -print "env8['TOOL_SCCS1'] =", env8.get('TOOL_SCCS1') -print "env8['TOOL_SCCS2'] =", env8.get('TOOL_SCCS2') +print("env8['SCCS'] =", env8.get('SCCS')) +print("env8['TOOL_SCCS1'] =", env8.get('TOOL_SCCS1')) +print("env8['TOOL_SCCS2'] =", env8.get('TOOL_SCCS2')) env9 = Environment(tools=[]) Tool('SCCS', toolpath=['tools'])(env9) -print "env9['SCCS'] =", env9.get('SCCS') -print "env9['TOOL_SCCS1'] =", env9.get('TOOL_SCCS1') -print "env9['TOOL_SCCS2'] =", env9.get('TOOL_SCCS2') +print("env9['SCCS'] =", env9.get('SCCS')) +print("env9['TOOL_SCCS1'] =", env9.get('TOOL_SCCS1')) +print("env9['TOOL_SCCS2'] =", env9.get('TOOL_SCCS2')) env0 = Environment(TOOLPATH='tools', tools=[]) env0.Tool('SCCS', toolpath=['$TOOLPATH']) -print "env0['SCCS'] =", env0.get('SCCS') -print "env0['TOOL_SCCS1'] =", env0.get('TOOL_SCCS1') -print "env0['TOOL_SCCS2'] =", env0.get('TOOL_SCCS2') +print("env0['SCCS'] =", env0.get('SCCS')) +print("env0['TOOL_SCCS1'] =", env0.get('TOOL_SCCS1')) +print("env0['TOOL_SCCS2'] =", env0.get('TOOL_SCCS2')) base = Environment(tools=[], toolpath=['tools']) derived = base.Clone(tools=['bar']) -print "derived['TOOL_BAR'] =", derived.get('TOOL_BAR') +print("derived['TOOL_BAR'] =", derived.get('TOOL_BAR')) """) test.write('SCCS.py', r"""\ -- cgit v0.12 From 7a6018983cf716374f2c7bf3b48e3f386bcaadd9 Mon Sep 17 00:00:00 2001 From: Russel Winder Date: Fri, 1 Jan 2016 16:21:10 +0000 Subject: Some more statement to function transforms. --- QMTest/TestSCons.py | 12 ++++++------ test/Repository/Default.py | 2 +- test/Repository/Local.py | 4 ++-- test/Repository/VariantDir.py | 2 +- test/Repository/option-c.py | 2 +- test/Repository/option-n.py | 2 +- test/Repository/targets.py | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/QMTest/TestSCons.py b/QMTest/TestSCons.py index d98b155..3857da5 100644 --- a/QMTest/TestSCons.py +++ b/QMTest/TestSCons.py @@ -929,7 +929,7 @@ if ARGUMENTS.get('variant_dir', 0): else: builddir = 'build' VariantDir(builddir, '.', duplicate=dup) - print builddir, dup + print(builddir, dup) sconscript = Dir(builddir).File('SConscript') else: sconscript = File('SConscript') @@ -1142,12 +1142,12 @@ except AttributeError: try: import distutils.sysconfig exec_prefix = distutils.sysconfig.EXEC_PREFIX - print distutils.sysconfig.get_python_inc() - print os.path.join(exec_prefix, 'libs') + print(distutils.sysconfig.get_python_inc()) + print(os.path.join(exec_prefix, 'libs')) except: - print os.path.join(sys.prefix, 'include', py_ver) - print os.path.join(sys.prefix, 'lib', py_ver, 'config') -print py_ver + print(os.path.join(sys.prefix, 'include', py_ver) + print(os.path.join(sys.prefix, 'lib', py_ver, 'config')) +print(py_ver) """) return [python] + self.stdout().strip().split('\n') diff --git a/test/Repository/Default.py b/test/Repository/Default.py index 127c29a..44aecfb 100644 --- a/test/Repository/Default.py +++ b/test/Repository/Default.py @@ -46,7 +46,7 @@ test.write(['repository', 'SConstruct'], r""" def copy(env, source, target): source = str(source[0]) target = str(target[0]) - print 'copy() < %s > %s' % (source, target) + print('copy() < %s > %s' % (source, target)) open(target, "wb").write(open(source, "rb").read()) Build = Builder(action=copy) diff --git a/test/Repository/Local.py b/test/Repository/Local.py index 1b63345..ea03281 100644 --- a/test/Repository/Local.py +++ b/test/Repository/Local.py @@ -48,7 +48,7 @@ test.write(['repository', 'SConstruct'], r""" def copy(env, source, target): source = str(source[0]) target = str(target[0]) - print 'copy() < %s > %s' % (source, target) + print('copy() < %s > %s' % (source, target)) open(target, "wb").write(open(source, "rb").read()) Build = Builder(action=copy) @@ -65,7 +65,7 @@ SConscript('build/SConscript') test.write(['repository', 'src', 'SConscript'], r""" def bbb_copy(env, source, target): target = str(target[0]) - print 'bbb_copy()' + print('bbb_copy()') open(target, "wb").write(open('build/bbb.1', "rb").read()) Import("env") diff --git a/test/Repository/VariantDir.py b/test/Repository/VariantDir.py index ec723c8..0258ff5 100644 --- a/test/Repository/VariantDir.py +++ b/test/Repository/VariantDir.py @@ -48,7 +48,7 @@ test.write(['repository', 'src', 'SConscript'], r""" def cat(env, source, target): target = str(target[0]) source = list(map(str, source)) - print 'cat(%s) > %s' % (source, target) + print('cat(%s) > %s' % (source, target)) f = open(target, "wb") for src in source: f.write(open(src, "rb").read()) diff --git a/test/Repository/option-c.py b/test/Repository/option-c.py index ea989c2..c06c7d8 100644 --- a/test/Repository/option-c.py +++ b/test/Repository/option-c.py @@ -65,7 +65,7 @@ test.write(['repository', 'SConstruct'], r""" def copy(env, source, target): source = str(source[0]) target = str(target[0]) - print 'copy() < %s > %s' % (source, target) + print('copy() < %s > %s' % (source, target)) open(target, "wb").write(open(source, "rb").read()) Build = Builder(action=copy) diff --git a/test/Repository/option-n.py b/test/Repository/option-n.py index 220baad..2a0ae5d 100644 --- a/test/Repository/option-n.py +++ b/test/Repository/option-n.py @@ -48,7 +48,7 @@ test.write(['repository', 'SConstruct'], r""" def copy(env, source, target): source = str(source[0]) target = str(target[0]) - print 'copy() < %s > %s' % (source, target) + print('copy() < %s > %s' % (source, target)) open(target, "wb").write(open(source, "rb").read()) Build = Builder(action=copy) diff --git a/test/Repository/targets.py b/test/Repository/targets.py index 62f4785..0fbc896 100644 --- a/test/Repository/targets.py +++ b/test/Repository/targets.py @@ -43,7 +43,7 @@ test.write(['repository', 'SConstruct'], """ def cat(env, source, target): target = str(target[0]) source = list(map(str, source)) - print 'cat(%s) > %s' % (source, target) + print('cat(%s) > %s' % (source, target)) f = open(target, "wb") for src in source: f.write(open(src, "rb").read()) -- cgit v0.12 From 5f0194ba83727df2cea55f0af67633e8f02b5982 Mon Sep 17 00:00:00 2001 From: Adarsh Sanjeev Date: Sun, 3 Jan 2016 16:02:25 +0500 Subject: String support for Chmod added --- src/engine/SCons/Defaults.py | 56 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/src/engine/SCons/Defaults.py b/src/engine/SCons/Defaults.py index c1bd902..0fbd097 100644 --- a/src/engine/SCons/Defaults.py +++ b/src/engine/SCons/Defaults.py @@ -169,15 +169,65 @@ def get_paths_str(dest): else: return '"' + str(dest) + '"' +permission_dic = { + 'u':{ + 'r':stat.S_IRUSR, + 'w':stat.S_IWUSR, + 'x':stat.S_IXUSR + }, + 'g':{ + 'r':stat.S_IRGRP, + 'w':stat.S_IWGRP, + 'x':stat.S_IXGRP + }, + 'o':{ + 'r':stat.S_IROTH, + 'w':stat.S_IWOTH, + 'x':stat.S_IXOTH + } +} + def chmod_func(dest, mode): SCons.Node.FS.invalidate_node_memos(dest) if not SCons.Util.is_List(dest): dest = [dest] - for element in dest: - os.chmod(str(element), mode) + if str(mode).isdigit(): + for element in dest: + os.chmod(str(element), mode) + else: + mode = str(mode) + for operation in mode.split(","): + if "=" in operation: + operator = "=" + elif "+" in operation: + operator = "+" + elif "-" in operation: + operator = "-" + else: + raise SyntaxError("Could not find +, - or =") + user = operation.split(operator)[0].strip().replace("a", "ugo") + permission = operation.split(operator)[1].strip() + new_perm = 0 + for u in user: + for p in permission: + try: + new_perm = new_perm | permission_dic[u][p] + except KeyError: + raise SyntaxError("Unrecognized user or permission format") + for element in dest: + curr_perm = os.stat(str(element)).st_mode + if operator == "=": + os.chmod(str(element), new_perm) + elif operator == "+": + os.chmod(str(element), curr_perm | new_perm) + elif operator == "-": + os.chmod(str(element), curr_perm & ~new_perm) def chmod_strfunc(dest, mode): - return 'Chmod(%s, 0%o)' % (get_paths_str(dest), mode) + if str(mode).isdigit(): + return 'Chmod(%s, 0%o)' % (get_paths_str(dest), mode) + else: + return 'Chmod(%s, "%s")' % (get_paths_str(dest), str(mode)) Chmod = ActionFactory(chmod_func, chmod_strfunc) -- cgit v0.12 From 9ee508ee318cb51f3ff7194a0385a2ba74dcedd9 Mon Sep 17 00:00:00 2001 From: Adarsh Sanjeev Date: Sun, 3 Jan 2016 16:05:58 +0500 Subject: Tests for Chmod updated --- test/Chmod.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/test/Chmod.py b/test/Chmod.py index c00aea0..762d286 100644 --- a/test/Chmod.py +++ b/test/Chmod.py @@ -64,6 +64,11 @@ env.Command('f7.out', 'f7.in', [Cat, env = Environment(FILE = 'f9') env.Command('f8.out', 'f8.in', [Chmod(['$FILE', File('f10')], 0666), Cat]) Execute(Chmod(['d11', Dir('d12')], 0777)) +Execute(Chmod('f13', "go=rw")) +Execute(Chmod('f14', "u-r")) +Execute(Chmod('f15', "a+x")) +Execute(Chmod('d16', "uo=x")) +Execute(Chmod(['d17', 'd18'], "o-wx")) """) test.write('f1', "f1\n") @@ -86,6 +91,12 @@ test.write('f9', "f9\n") test.write('f10', "f10\n") test.subdir('d11') test.subdir('d12') +test.write('f13', "f13\n") +test.write('f14', "f14\n") +test.write('f15', "f15\n") +test.subdir('d16') +test.subdir('d17') +test.subdir('d18') os.chmod(test.workpath('f1'), 0444) os.chmod(test.workpath('f1-File'), 0444) @@ -100,6 +111,12 @@ os.chmod(test.workpath('f9'), 0444) os.chmod(test.workpath('f10'), 0444) os.chmod(test.workpath('d11'), 0555) os.chmod(test.workpath('d12'), 0555) +os.chmod(test.workpath('f13'), 0444) +os.chmod(test.workpath('f14'), 0444) +os.chmod(test.workpath('f15'), 0444) +os.chmod(test.workpath('d16'), 0555) +os.chmod(test.workpath('d17'), 0555) +os.chmod(test.workpath('d18'), 0555) expect = test.wrap_stdout(read_str = """\ Chmod("f1", 0666) @@ -107,6 +124,11 @@ Chmod("f1-File", 0666) Chmod("d2", 0777) Chmod("d2-Dir", 0777) Chmod(["d11", "d12"], 0777) +Chmod("f13", "go=rw") +Chmod("f14", "u-r") +Chmod("f15", "a+x") +Chmod("d16", "uo=x") +Chmod(["d17", "d18"], "o-wx") """, build_str = """\ cat(["bar.out"], ["bar.in"]) @@ -152,6 +174,18 @@ s = stat.S_IMODE(os.stat(test.workpath('d11'))[stat.ST_MODE]) test.fail_test(s != 0555) s = stat.S_IMODE(os.stat(test.workpath('d12'))[stat.ST_MODE]) test.fail_test(s != 0555) +s = stat.S_IMODE(os.stat(test.workpath('f13'))[stat.ST_MODE]) +test.fail_test(s != 0444) +s = stat.S_IMODE(os.stat(test.workpath('f14'))[stat.ST_MODE]) +test.fail_test(s != 0444) +s = stat.S_IMODE(os.stat(test.workpath('f15'))[stat.ST_MODE]) +test.fail_test(s != 0444) +s = stat.S_IMODE(os.stat(test.workpath('d16'))[stat.ST_MODE]) +test.fail_test(s != 0555) +s = stat.S_IMODE(os.stat(test.workpath('d17'))[stat.ST_MODE]) +test.fail_test(s != 0555) +s = stat.S_IMODE(os.stat(test.workpath('d18'))[stat.ST_MODE]) +test.fail_test(s != 0555) test.run() @@ -185,6 +219,18 @@ s = stat.S_IMODE(os.stat(test.workpath('d11'))[stat.ST_MODE]) test.fail_test(s != 0777) s = stat.S_IMODE(os.stat(test.workpath('d12'))[stat.ST_MODE]) test.fail_test(s != 0777) +s = stat.S_IMODE(os.stat(test.workpath('f13'))[stat.ST_MODE]) +test.fail_test(s != 0066) +s = stat.S_IMODE(os.stat(test.workpath('f14'))[stat.ST_MODE]) +test.fail_test(s != 0044) +s = stat.S_IMODE(os.stat(test.workpath('f15'))[stat.ST_MODE]) +test.fail_test(s != 0555) +s = stat.S_IMODE(os.stat(test.workpath('d16'))[stat.ST_MODE]) +test.fail_test(s != 0101) +s = stat.S_IMODE(os.stat(test.workpath('d17'))[stat.ST_MODE]) +test.fail_test(s != 0554) +s = stat.S_IMODE(os.stat(test.workpath('d18'))[stat.ST_MODE]) +test.fail_test(s != 0554) test.pass_test() -- cgit v0.12 From ea232cd3c7b8af29de3fa2619a20e7a24886cdcb Mon Sep 17 00:00:00 2001 From: Adarsh Sanjeev Date: Mon, 4 Jan 2016 22:50:59 +0500 Subject: Changed as per review --- src/engine/SCons/Defaults.py | 16 ++++++++++++---- test/Chmod.py | 32 ++++++++++++++++---------------- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/engine/SCons/Defaults.py b/src/engine/SCons/Defaults.py index 0fbd097..6344975 100644 --- a/src/engine/SCons/Defaults.py +++ b/src/engine/SCons/Defaults.py @@ -188,10 +188,14 @@ permission_dic = { } def chmod_func(dest, mode): + import SCons.Util + from string import digits SCons.Node.FS.invalidate_node_memos(dest) if not SCons.Util.is_List(dest): dest = [dest] - if str(mode).isdigit(): + if SCons.Util.is_String(mode) and not 0 in [i in digits for i in mode]: + mode = int(mode, 8) + if not SCons.Util.is_String(mode): for element in dest: os.chmod(str(element), mode) else: @@ -205,8 +209,11 @@ def chmod_func(dest, mode): operator = "-" else: raise SyntaxError("Could not find +, - or =") - user = operation.split(operator)[0].strip().replace("a", "ugo") - permission = operation.split(operator)[1].strip() + operation_list = operation.split(operator) + if len(operation_list) is not 2: + raise SyntaxError("More than one operator found") + user = operation_list[0].strip().replace("a", "ugo") + permission = operation_list[1].strip() new_perm = 0 for u in user: for p in permission: @@ -224,7 +231,8 @@ def chmod_func(dest, mode): os.chmod(str(element), curr_perm & ~new_perm) def chmod_strfunc(dest, mode): - if str(mode).isdigit(): + import SCons.Util + if not SCons.Util.is_String(mode): return 'Chmod(%s, 0%o)' % (get_paths_str(dest), mode) else: return 'Chmod(%s, "%s")' % (get_paths_str(dest), str(mode)) diff --git a/test/Chmod.py b/test/Chmod.py index 762d286..c5b2a8d 100644 --- a/test/Chmod.py +++ b/test/Chmod.py @@ -64,11 +64,11 @@ env.Command('f7.out', 'f7.in', [Cat, env = Environment(FILE = 'f9') env.Command('f8.out', 'f8.in', [Chmod(['$FILE', File('f10')], 0666), Cat]) Execute(Chmod(['d11', Dir('d12')], 0777)) -Execute(Chmod('f13', "go=rw")) -Execute(Chmod('f14', "u-r")) -Execute(Chmod('f15', "a+x")) -Execute(Chmod('d16', "uo=x")) -Execute(Chmod(['d17', 'd18'], "o-wx")) +Execute(Chmod('f13', "a=r")) +Execute(Chmod('f14', "ogu+w")) +Execute(Chmod('f15', "ug=rw, go+ rw")) +Execute(Chmod('d16', "0777")) +Execute(Chmod(['d17', 'd18'], "ogu = rwx")) """) test.write('f1', "f1\n") @@ -124,11 +124,11 @@ Chmod("f1-File", 0666) Chmod("d2", 0777) Chmod("d2-Dir", 0777) Chmod(["d11", "d12"], 0777) -Chmod("f13", "go=rw") -Chmod("f14", "u-r") -Chmod("f15", "a+x") -Chmod("d16", "uo=x") -Chmod(["d17", "d18"], "o-wx") +Chmod("f13", "a=r") +Chmod("f14", "ogu+w") +Chmod("f15", "ug=rw, go+ rw") +Chmod("d16", "0777") +Chmod(["d17", "d18"], "ogu = rwx") """, build_str = """\ cat(["bar.out"], ["bar.in"]) @@ -220,17 +220,17 @@ test.fail_test(s != 0777) s = stat.S_IMODE(os.stat(test.workpath('d12'))[stat.ST_MODE]) test.fail_test(s != 0777) s = stat.S_IMODE(os.stat(test.workpath('f13'))[stat.ST_MODE]) -test.fail_test(s != 0066) +test.fail_test(s != 0444) s = stat.S_IMODE(os.stat(test.workpath('f14'))[stat.ST_MODE]) -test.fail_test(s != 0044) +test.fail_test(s != 0666) s = stat.S_IMODE(os.stat(test.workpath('f15'))[stat.ST_MODE]) -test.fail_test(s != 0555) +test.fail_test(s != 0666) s = stat.S_IMODE(os.stat(test.workpath('d16'))[stat.ST_MODE]) -test.fail_test(s != 0101) +test.fail_test(s != 0777) s = stat.S_IMODE(os.stat(test.workpath('d17'))[stat.ST_MODE]) -test.fail_test(s != 0554) +test.fail_test(s != 0777) s = stat.S_IMODE(os.stat(test.workpath('d18'))[stat.ST_MODE]) -test.fail_test(s != 0554) +test.fail_test(s != 0777) test.pass_test() -- cgit v0.12 From 3909c2e02d5497858dcb509f09fe5766a9aa0b4d Mon Sep 17 00:00:00 2001 From: Adarsh Sanjeev Date: Tue, 5 Jan 2016 00:37:04 +0500 Subject: Updated documentation --- doc/generated/examples/caching_ex-random_1.xml | 4 +-- doc/generated/examples/tasks_ex1_1.xml | 2 +- doc/generated/examples/troubleshoot_Dump_1.xml | 2 +- doc/generated/examples/troubleshoot_Dump_2.xml | 2 +- doc/generated/examples/troubleshoot_explain1_3.xml | 2 +- .../examples/troubleshoot_stacktrace_2.xml | 4 +-- doc/generated/tools.gen | 12 +++---- doc/generated/tools.mod | 4 +-- doc/generated/variables.gen | 40 +++++++++++----------- doc/man/scons.xml | 9 ++++- src/CHANGES.txt | 2 ++ 11 files changed, 46 insertions(+), 37 deletions(-) diff --git a/doc/generated/examples/caching_ex-random_1.xml b/doc/generated/examples/caching_ex-random_1.xml index 6a0337b..cb14259 100644 --- a/doc/generated/examples/caching_ex-random_1.xml +++ b/doc/generated/examples/caching_ex-random_1.xml @@ -1,9 +1,9 @@ % scons -Q -cc -o f2.o -c f2.c cc -o f1.o -c f1.c +cc -o f4.o -c f4.c cc -o f5.o -c f5.c cc -o f3.o -c f3.c -cc -o f4.o -c f4.c +cc -o f2.o -c f2.c cc -o prog f1.o f2.o f3.o f4.o f5.o diff --git a/doc/generated/examples/tasks_ex1_1.xml b/doc/generated/examples/tasks_ex1_1.xml index 5760a45..4885fde 100644 --- a/doc/generated/examples/tasks_ex1_1.xml +++ b/doc/generated/examples/tasks_ex1_1.xml @@ -1,7 +1,7 @@ % scons -Q +cat < test.bar > test.h cc -o app main.cpp cat < foo.bar2 > foo.cpp cc -o app2 main2.cpp foo.cpp -cat < test.bar > test.h diff --git a/doc/generated/examples/troubleshoot_Dump_1.xml b/doc/generated/examples/troubleshoot_Dump_1.xml index bf141a0..99d1399 100644 --- a/doc/generated/examples/troubleshoot_Dump_1.xml +++ b/doc/generated/examples/troubleshoot_Dump_1.xml @@ -47,7 +47,7 @@ scons: Reading SConscript files ... 'PROGSUFFIX': '', 'PSPAWN': <function piped_env_spawn at 0x700000&gt;, 'RDirs': <SCons.Defaults.Variable_Method_Caller object at 0x700000&gt;, - 'SCANNERS': [], + 'SCANNERS': [<SCons.Scanner.Base object at 0x700000&gt;], 'SHELL': 'sh', 'SHLIBPREFIX': '$LIBPREFIX', 'SHLIBSUFFIX': '.so', diff --git a/doc/generated/examples/troubleshoot_Dump_2.xml b/doc/generated/examples/troubleshoot_Dump_2.xml index 0ae8fe1..a621422 100644 --- a/doc/generated/examples/troubleshoot_Dump_2.xml +++ b/doc/generated/examples/troubleshoot_Dump_2.xml @@ -71,7 +71,7 @@ scons: Reading SConscript files ... 'RCFLAGS': [], 'RCSUFFIXES': ['.rc', '.rc2'], 'RDirs': <SCons.Defaults.Variable_Method_Caller object at 0x700000&gt;, - 'SCANNERS': [], + 'SCANNERS': [<SCons.Scanner.Base object at 0x700000&gt;], 'SHCC': '$CC', 'SHCCCOM': <SCons.Action.FunctionAction object at 0x700000&gt;, 'SHCCFLAGS': ['$CCFLAGS'], diff --git a/doc/generated/examples/troubleshoot_explain1_3.xml b/doc/generated/examples/troubleshoot_explain1_3.xml index 3d8592d..7e495ea 100644 --- a/doc/generated/examples/troubleshoot_explain1_3.xml +++ b/doc/generated/examples/troubleshoot_explain1_3.xml @@ -3,5 +3,5 @@ cp file.in file.oout scons: warning: Cannot find target file.out after building -File "/scons/as_scons/bootstrap/src/script/scons.py", line 199, in <module> +File "/home/ghost/projects/scons/bootstrap/src/script/scons.py", line 199, in <module> diff --git a/doc/generated/examples/troubleshoot_stacktrace_2.xml b/doc/generated/examples/troubleshoot_stacktrace_2.xml index add59ff..1de0dcf 100644 --- a/doc/generated/examples/troubleshoot_stacktrace_2.xml +++ b/doc/generated/examples/troubleshoot_stacktrace_2.xml @@ -4,10 +4,10 @@ scons: *** [prog.o] Source `prog.c' not found, needed by target `prog.o'. scons: internal stack trace: File "bootstrap/src/engine/SCons/Job.py", line 199, in start task.prepare() - File "bootstrap/src/engine/SCons/Script/Main.py", line 173, in prepare + File "bootstrap/src/engine/SCons/Script/Main.py", line 164, in prepare return SCons.Taskmaster.OutOfDateTask.prepare(self) File "bootstrap/src/engine/SCons/Taskmaster.py", line 191, in prepare executor.prepare() - File "bootstrap/src/engine/SCons/Executor.py", line 430, in prepare + File "bootstrap/src/engine/SCons/Executor.py", line 427, in prepare raise SCons.Errors.StopError(msg % (s, self.batches[0].targets[0])) diff --git a/doc/generated/tools.gen b/doc/generated/tools.gen index ba12966..fcb7587 100644 --- a/doc/generated/tools.gen +++ b/doc/generated/tools.gen @@ -780,19 +780,19 @@ Sets construction variables for the Sets: &cv-link-AS;, &cv-link-ASCOM;, &cv-link-ASFLAGS;, &cv-link-ASPPCOM;, &cv-link-ASPPFLAGS;.Uses: &cv-link-ASCOMSTR;, &cv-link-ASPPCOMSTR;. - - Packaging + + packaging -Sets construction variables for the Package Builder. +A framework for building binary and source packages. - - packaging + + Packaging -A framework for building binary and source packages. +Sets construction variables for the Package Builder. diff --git a/doc/generated/tools.mod b/doc/generated/tools.mod index 2ee2270..1191e6a 100644 --- a/doc/generated/tools.mod +++ b/doc/generated/tools.mod @@ -78,8 +78,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. mwcc"> mwld"> nasm"> -Packaging"> packaging"> +Packaging"> pdf"> pdflatex"> pdftex"> @@ -189,8 +189,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. mwcc"> mwld"> nasm"> -Packaging"> packaging"> +Packaging"> pdf"> pdflatex"> pdftex"> diff --git a/doc/generated/variables.gen b/doc/generated/variables.gen index b377102..b64eb5a 100644 --- a/doc/generated/variables.gen +++ b/doc/generated/variables.gen @@ -2838,15 +2838,6 @@ is -dNOPAUSE -dBATCH -sDEVICE=pdfwrite HOST_ARCH - The name of the host hardware architecture used to create the Environment. - If a platform is specified when creating the Environment, then - that Platform's logic will handle setting this value. - This value is immutable, and should not be changed by the user after - the Environment is initialized. - Currently only set for Win32. - - - Sets the host architecture for Visual Studio compiler. If not set, default to the detected host architecture: note that this may depend on the python you are using. @@ -2862,7 +2853,16 @@ Valid values are the same as for This is currently only used on Windows, but in the future it will be used on other OSes as well. - + + + The name of the host hardware architecture used to create the Environment. + If a platform is specified when creating the Environment, then + that Platform's logic will handle setting this value. + This value is immutable, and should not be changed by the user after + the Environment is initialized. + Currently only set for Win32. + + HOST_OS @@ -3104,7 +3104,7 @@ The command line used to call the Java archive tool. The string displayed when the Java archive tool is called -If this is not set, then $JARCOM (the command line) is displayed. +If this is not set, then $JARCOM (the command line) is displayed. @@ -3114,7 +3114,7 @@ env = Environment(JARCOMSTR = "JARchiving $SOURCES into $TARGET") The string displayed when the Java archive tool is called -If this is not set, then $JARCOM (the command line) is displayed. +If this is not set, then $JARCOM (the command line) is displayed. @@ -7038,13 +7038,6 @@ that may not be set or used in a construction environment. TARGET_ARCH - The name of the target hardware architecture for the compiled objects - created by this Environment. - This defaults to the value of HOST_ARCH, and the user can override it. - Currently only set for Win32. - - - Sets the target architecture for Visual Studio compiler (i.e. the arch of the binaries generated by the compiler). If not set, default to $HOST_ARCH, or, if that is unset, to the architecture of the @@ -7069,7 +7062,14 @@ and ia64 (Itanium). For example, if you want to compile 64-bit binaries, you would set TARGET_ARCH='x86_64' in your SCons environment. - + + + The name of the target hardware architecture for the compiled objects + created by this Environment. + This defaults to the value of HOST_ARCH, and the user can override it. + Currently only set for Win32. + + TARGET_OS diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 5c832c2..c72178e 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -5630,7 +5630,8 @@ env.Command('foo.out', 'foo.in', changes the permissions on the specified dest file or directory to the specified -mode. +mode +which can be octal or string, similar to the bash command. Examples: @@ -5639,6 +5640,12 @@ Execute(Chmod('file', 0755)) env.Command('foo.out', 'foo.in', [Copy('$TARGET', '$SOURCE'), Chmod('$TARGET', 0755)]) + +Execute(Chmod('file', "ugo+w")) + +env.Command('foo.out', 'foo.in', + [Copy('$TARGET', '$SOURCE'), + Chmod('$TARGET', "ugo+w")]) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 9e335f9..1a3ee63 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -19,6 +19,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER Also fixed the default arguments for the print_tree and render_tree methods. (PR #284, too) + From Adarsh Sanjeev: + - Fix for issue #2494: Added string support for Chmod function. RELEASE 2.4.1 - Mon, 07 Nov 2015 10:37:21 -0700 -- cgit v0.12 From 543495e2fe3353396225b973e7fe64fb8e566f64 Mon Sep 17 00:00:00 2001 From: Russel Winder Date: Sun, 10 Jan 2016 15:21:22 +0000 Subject: Remove relative import. --- src/engine/SCons/cppTests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/SCons/cppTests.py b/src/engine/SCons/cppTests.py index 28a1f5e..40236e4 100644 --- a/src/engine/SCons/cppTests.py +++ b/src/engine/SCons/cppTests.py @@ -31,7 +31,7 @@ import unittest import TestUnit -from . import cpp +import cpp -- cgit v0.12 From 2bffdfc4addbc1565c2f21f35b73ab09ef4f3105 Mon Sep 17 00:00:00 2001 From: Russel Winder Date: Sun, 10 Jan 2016 15:29:55 +0000 Subject: Remove spurious space causing test fail. --- test/CPPDEFINES/append.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CPPDEFINES/append.py b/test/CPPDEFINES/append.py index 432ab64..14ea7b3 100644 --- a/test/CPPDEFINES/append.py +++ b/test/CPPDEFINES/append.py @@ -67,7 +67,7 @@ for (t1, c1) in cases: env=Environment(CPPDEFINES = c1, CPPDEFPREFIX='-D') env.Append(CPPDEFINES = c2) final=env.subst('$_CPPDEFFLAGS',source="src", target="tgt") - print('Append: \\n\\tresult=%s\\n\\tfinal=%s'%\\ + print('Append:\\n\\tresult=%s\\n\\tfinal=%s'%\\ (env['CPPDEFINES'], final)) env=Environment(CPPDEFINES = c1, CPPDEFPREFIX='-D') env.AppendUnique(CPPDEFINES = c2) -- cgit v0.12 From 31c24bc7e328fb2e8d75893c675f63e37dc2e6dc Mon Sep 17 00:00:00 2001 From: Russel Winder Date: Sun, 10 Jan 2016 15:55:12 +0000 Subject: Refactor of test, but it still fails due to missing output from SCons. --- test/Clean/mkfifo.py | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/test/Clean/mkfifo.py b/test/Clean/mkfifo.py index 0ef7662..01e4d98 100644 --- a/test/Clean/mkfifo.py +++ b/test/Clean/mkfifo.py @@ -38,35 +38,40 @@ test = TestSCons.TestSCons() if not hasattr(os, 'mkfifo'): test.skip_test('No os.mkfifo() function; skipping test\n') +test_dir_name = 'testdir' +pipe_path = os.path.join(test_dir_name, 'namedpipe') + test.write('SConstruct', """\ -Execute(Mkdir("testdir")) -dir = Dir("testdir") -Clean(dir, 'testdir') -""") +Execute(Mkdir("{0}")) +dir = Dir("{0}") +Clean(dir, '{0}') +""".format(test_dir_name)) + +test.run(arguments='-Q -q', stdout='Mkdir("{0}")\n'.format(test_dir_name)) -test.run(arguments='-Q -q', stdout='Mkdir("testdir")\n') +os.mkfifo(pipe_path) -os.mkfifo('testdir/namedpipe') +test.must_exist(test.workpath(pipe_path)) expect1 = """\ -Mkdir("testdir") -Path '%s' exists but isn't a file or directory. -scons: Could not remove 'testdir': Directory not empty -""" % os.path.join('testdir', 'namedpipe') +Mkdir("{0}") +Path '{1}' exists but isn't a file or directory. +scons: Could not remove '{0}': Directory not empty +""".format(test_dir_name, pipe_path) expect2 = """\ -Mkdir("testdir") -Path '%s' exists but isn't a file or directory. -scons: Could not remove 'testdir': File exists -""" % os.path.join('testdir', 'namedpipe') +Mkdir("{0}") +Path '{1}' exists but isn't a file or directory. +scons: Could not remove '{0}': File exists +""".format(test_dir_name, pipe_path) test.run(arguments='-c -Q -q') +test.must_exist(test.workpath(pipe_path)) + if test.stdout() not in [expect1, expect2]: test.diff(expect1, test.stdout(), 'STDOUT ') test.fail_test() - -test.must_exist(test.workpath('testdir/namedpipe')) test.pass_test() -- cgit v0.12 From 82857f4e863cc754cd02e4aee8507d888afc377e Mon Sep 17 00:00:00 2001 From: Russel Winder Date: Sun, 10 Jan 2016 17:37:41 +0000 Subject: Amend the message. --- test/D/SharedObjects/Common/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/D/SharedObjects/Common/common.py b/test/D/SharedObjects/Common/common.py index e81cf5b..280c6f2 100644 --- a/test/D/SharedObjects/Common/common.py +++ b/test/D/SharedObjects/Common/common.py @@ -46,7 +46,7 @@ def testForTool(tool): test.skip_test("Required executable for tool '{0}' not found, skipping test.\n".format(tool)) if tool == 'gdc': - test.skip_test('gdc does not, as at version 4.9.1, support shared libraries.\n') + test.skip_test('gdc in GCC distribution does not, as at version 5.3.1, support shared libraries.\n') if tool == 'dmd' and Base()['DC'] == 'gdmd': test.skip_test('gdmd does not recognize the -shared option so cannot support linking of shared objects.\n') -- cgit v0.12 From 79d11adfb4ae11260ab644e8968843058e091ab4 Mon Sep 17 00:00:00 2001 From: Russel Winder Date: Sun, 10 Jan 2016 18:07:35 +0000 Subject: Output changed so changed expected results. --- src/engine/SCons/ActionTests.py | 42 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py index f56948f..3eee4b6 100644 --- a/src/engine/SCons/ActionTests.py +++ b/src/engine/SCons/ActionTests.py @@ -556,7 +556,7 @@ class _ActionActionTestCase(unittest.TestCase): assert isinstance(source, list), type(source) return 9 b = SCons.Action.Action([firstfunc, execfunc, lastfunc]) - + sio = io.StringIO() sys.stdout = sio result = a("out", "in", env) @@ -699,7 +699,7 @@ class _ActionActionTestCase(unittest.TestCase): env['PRINT_CMD_LINE_FUNC'] = my_print_cmd_line a("output", "input", env) assert result == ["execfunc(['output'], ['input'])"], result - + finally: sys.stdout = save_stdout @@ -942,7 +942,7 @@ class CommandActionTestCase(unittest.TestCase): act = SCons.Action.CommandAction('xyzzy $TARGETS $SOURCES', cmdstr='cmdstr\t$TARGETS\n$SOURCES ') - + s = act.strfunction([], [], env) assert s == 'cmdstr\t\n ', s s = act.strfunction([t1], [s1], env) @@ -1429,13 +1429,13 @@ class CommandGeneratorActionTestCase(unittest.TestCase): pass func_matches = [ - b"0,0,0,0,(),(),(d\000\000S),(),()", - b"0,0,0,0,(),(),(d\x00\x00S),(),()", + b"0, 0, 0, 0,(),(),(d\000\000S),(),()", + b"0, 0, 0, 0,(),(),(d\x00\x00S),(),()", ] - + meth_matches = [ - b"1,1,0,0,(),(),(d\000\000S),(),()", - b"1,1,0,0,(),(),(d\x00\x00S),(),()", + b"1, 1, 0, 0,(),(),(d\000\000S),(),()", + b"1, 1, 0, 0,(),(),(d\x00\x00S),(),()", ] def f_global(target, source, env, for_signature): @@ -1588,13 +1588,13 @@ class FunctionActionTestCase(unittest.TestCase): pass func_matches = [ - b"0,0,0,0,(),(),(d\000\000S),(),()", - b"0,0,0,0,(),(),(d\x00\x00S),(),()", + b"0, 0, 0, 0,(),(),(d\000\000S),(),()", + b"0, 0, 0, 0,(),(),(d\x00\x00S),(),()", ] - + meth_matches = [ - b"1,1,0,0,(),(),(d\000\000S),(),()", - b"1,1,0,0,(),(),(d\x00\x00S),(),()", + b"1, 1, 0, 0,(),(),(d\000\000S),(),()", + b"1, 1, 0, 0,(),(),(d\x00\x00S),(),()", ] def factory(act, **kw): @@ -1801,13 +1801,13 @@ class LazyActionTestCase(unittest.TestCase): pass func_matches = [ - b"0,0,0,0,(),(),(d\000\000S),(),()", - b"0,0,0,0,(),(),(d\x00\x00S),(),()", + b"0, 0, 0, 0,(),(),(d\000\000S),(),()", + b"0, 0, 0, 0,(),(),(d\x00\x00S),(),()", ] - + meth_matches = [ - b"1,1,0,0,(),(),(d\000\000S),(),()", - b"1,1,0,0,(),(),(d\x00\x00S),(),()", + b"1, 1, 0, 0,(),(),(d\000\000S),(),()", + b"1, 1, 0, 0,(),(),(d\x00\x00S),(),()", ] def factory(act, **kw): @@ -1999,16 +1999,16 @@ class ActionCompareTestCase(unittest.TestCase): especially two builders that can generate the same suffix, where one of the builders has a suffix dictionary with a None key.""" - + foo = SCons.Builder.Builder(action = '$FOO', suffix = '.foo') bar = SCons.Builder.Builder(action = {}, suffix={None:'.bar'}) bar.add_action('.cow', "$MOO") dog = SCons.Builder.Builder(suffix = '.bar') - + env = Environment( BUILDERS = {'FOO' : foo, 'BAR' : bar, 'DOG' : dog} ) - + assert foo.get_name(env) == 'FOO', foo.get_name(env) assert bar.get_name(env) == 'BAR', bar.get_name(env) assert dog.get_name(env) == 'DOG', dog.get_name(env) -- cgit v0.12 From 9ded0e7a074de768f76d945ed74ee9714d5d8001 Mon Sep 17 00:00:00 2001 From: William Blevins Date: Mon, 11 Jan 2016 01:32:04 +0000 Subject: Added intel 2016 support for intelc tool. --- src/engine/SCons/Tool/intelc.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/engine/SCons/Tool/intelc.py b/src/engine/SCons/Tool/intelc.py index b1cb5e3..c28532c 100644 --- a/src/engine/SCons/Tool/intelc.py +++ b/src/engine/SCons/Tool/intelc.py @@ -289,6 +289,12 @@ def get_all_compiler_versions(): m = re.search(r'([0-9]{0,4})(?:_sp\d*)?\.([0-9][0-9.]*)$', d) if m: versions.append("%s.%s"%(m.group(1), m.group(2))) + for d in glob.glob('/opt/intel/compilers_and_libraries_*'): + # JPA: For the new version of Intel compiler 2016.1. + m = re.search(r'([0-9]{0,4})(?:_sp\d*)?\.([0-9][0-9.]*)$', d) + if m: + versions.append("%s.%s"%(m.group(1), m,group(2))) + def keyfunc(str): """Given a dot-separated version string, return a tuple of ints representing it.""" return [int(x) for x in str.split('.')] @@ -370,7 +376,16 @@ def get_intel_compiler_top(version, abi): top = d break return top - top = find_in_2011style_dir(version) or find_in_2010style_dir(version) or find_in_2008style_dir(version) + def find_in_2016style_dir(version): + # The 2016 (compiler v16) dirs are inconsistent from previous. + top = None + for d in glob.glob('/opt/intel/compilers_and_libraries_%s/linux'%version): + if os.path.exists(os.path.join(d, "bin", "ia32", "icc")) or os.path.exists(os.path.join(d, "bin", "intel64", "icc")): + top = d + break + return top + + top = find_in_2016style_dir(version) or find_in_2011style_dir(version) or find_in_2010style_dir(version) or find_in_2008style_dir(version) # print "INTELC: top=",top if not top: raise MissingDirError("Can't find version %s Intel compiler in %s (abi='%s')"%(version,top, abi)) -- cgit v0.12 From ecb75f53e36ae33fa4874b3d8df478628b47018e Mon Sep 17 00:00:00 2001 From: William Blevins Date: Mon, 11 Jan 2016 12:28:49 +0000 Subject: Added intel 2016 tool update credits to CHANGES.txt. --- src/CHANGES.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 9e335f9..13a1697 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -6,6 +6,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER + From Jakub Pola: + - Intel Compiler 2016 (Linux/Mac) update for tool directories. + From William Blevins: - Added support for cross-language dependency scanning; SCons now respects scanner keys for implicit dependencies. -- cgit v0.12 From efe586285488a4b2087631c54e14b5c07f6f7909 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 13 Jan 2016 16:20:00 -0800 Subject: Fix bug 2081: Better messaging for different actions for same target in two environments --- src/engine/SCons/Builder.py | 2 +- test/Builder/different-actions.py | 2 ++ test/Builder/multi/different-environments.py | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py index b457d1e..80dcaca 100644 --- a/src/engine/SCons/Builder.py +++ b/src/engine/SCons/Builder.py @@ -299,7 +299,7 @@ def _node_errors(builder, env, tlist, slist): msg = "Two different environments were specified for target %s,\n\tbut they appear to have the same action: %s" % (t, action.genstring(tlist, slist, t.env)) SCons.Warnings.warn(SCons.Warnings.DuplicateEnvironmentWarning, msg) else: - msg = "Two environments with different actions were specified for the same target: %s" % t + msg = "Two environments with different actions were specified for the same target: %s\n(action 1: %s)\n(action 2: %s)" % (t,t_contents,contents) raise UserError(msg) if builder.multi: if t.builder != builder: diff --git a/test/Builder/different-actions.py b/test/Builder/different-actions.py index 33a1363..d84a9f9 100644 --- a/test/Builder/different-actions.py +++ b/test/Builder/different-actions.py @@ -43,6 +43,8 @@ e2.Command('out.txt', [], 'echo 2 > $TARGET') expect = TestSCons.re_escape(""" scons: *** Two environments with different actions were specified for the same target: out.txt +(action 1: echo 1 > out.txt) +(action 2: echo 2 > out.txt) """) + TestSCons.file_expr test.run(arguments='out.txt', status=2, stderr=expect) diff --git a/test/Builder/multi/different-environments.py b/test/Builder/multi/different-environments.py index ad5154a..68749cf 100644 --- a/test/Builder/multi/different-environments.py +++ b/test/Builder/multi/different-environments.py @@ -57,6 +57,8 @@ test.write('file03b.in', 'file03b.in\n') expect = TestSCons.re_escape(""" scons: *** Two environments with different actions were specified for the same target: file03.out +(action 1: /usr/bin/python build.py 1 file03.out file03b.in) +(action 2: /usr/bin/python build.py 2 file03.out file03b.in) """) + TestSCons.file_expr test.run(arguments='file03.out', status=2, stderr=expect) -- cgit v0.12 From 004f199b69e50f4418edacb57d6aafbdfa990d15 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 13 Jan 2016 16:21:50 -0800 Subject: Fix bug 2081: Better messaging for different actions for same target in two environments --- src/CHANGES.txt | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 13a1697..f59eaaf 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -6,8 +6,12 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - From Jakub Pola: - - Intel Compiler 2016 (Linux/Mac) update for tool directories. + From Dirk Baechle: + - Removed a lot of compatibility methods and workarounds + for Python versions < 2.7, in order to prepare the work + towards a combined 2.7/3.x version. (PR #284) + Also fixed the default arguments for the print_tree and + render_tree methods. (PR #284, too) From William Blevins: - Added support for cross-language dependency scanning; @@ -15,12 +19,12 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Resolved missing cross-language dependencies for SWIG bindings (fixes #2264). - From Dirk Baechle: - - Removed a lot of compatibility methods and workarounds - for Python versions < 2.7, in order to prepare the work - towards a combined 2.7/3.x version. (PR #284) - Also fixed the default arguments for the print_tree and - render_tree methods. (PR #284, too) + From William Deegan: + - Add better messaging when two environments have + different actions for the same target (Bug #2024) + + From Jakub Pola: + - Intel Compiler 2016 (Linux/Mac) update for tool directories. RELEASE 2.4.1 - Mon, 07 Nov 2015 10:37:21 -0700 -- cgit v0.12 From 4ab77641ede6bdb2d6b30c4038b3691cc36d0450 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 14 Jan 2016 16:50:47 +0000 Subject: README.rst edited online with Bitbucket --- README.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.rst b/README.rst index 5710586..ca71f44 100644 --- a/README.rst +++ b/README.rst @@ -1,6 +1,10 @@ SCons - a software construction tool #################################### +.. image:: https://img.shields.io/badge/IRC-pyinstalller-blue.svg + :target: http://webchat.freenode.net/?channels=%23scons&uio=d4 + :alt: IRC + Welcome to the SCons development tree. The real purpose of this tree is to package SCons for production distribution in a variety of formats, not just to hack SCons code. -- cgit v0.12 From 6a98fffc60e1789b37627181b71dbb0d4f01674d Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 14 Jan 2016 16:56:23 +0000 Subject: Added shields from shields.io.. --- README.rst | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index ca71f44..b4b24b7 100644 --- a/README.rst +++ b/README.rst @@ -1,9 +1,17 @@ SCons - a software construction tool #################################### -.. image:: https://img.shields.io/badge/IRC-pyinstalller-blue.svg +.. image:: https://img.shields.io/badge/IRC-scons-blue.svg :target: http://webchat.freenode.net/?channels=%23scons&uio=d4 :alt: IRC + +.. image:: https://img.shields.io/sourceforge/dm/scons.svg + :target: https://sourceforge.net/projects/scons + :alt: Sourceforge Monthly Downloads + +.. image:: https://img.shields.io/sourceforge/dt/scons.svg + :target: https://sourceforge.net/projects/scons + :alt: Sourceforge Total Downloads Welcome to the SCons development tree. The real purpose of this tree is to package SCons for production distribution in a variety of formats, not just to -- cgit v0.12 From 447fe1ef8e8974b1862fa87fa730b38a50db0c7f Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 14 Jan 2016 11:38:14 -0800 Subject: fix test which was expecting a given location for python binary running the test --- test/Builder/multi/different-environments.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/Builder/multi/different-environments.py b/test/Builder/multi/different-environments.py index 68749cf..783b7f9 100644 --- a/test/Builder/multi/different-environments.py +++ b/test/Builder/multi/different-environments.py @@ -30,6 +30,7 @@ but the overrides don't appear to affect the build operation. """ import TestSCons +import sys test = TestSCons.TestSCons(match=TestSCons.match_re) @@ -57,9 +58,9 @@ test.write('file03b.in', 'file03b.in\n') expect = TestSCons.re_escape(""" scons: *** Two environments with different actions were specified for the same target: file03.out -(action 1: /usr/bin/python build.py 1 file03.out file03b.in) -(action 2: /usr/bin/python build.py 2 file03.out file03b.in) -""") + TestSCons.file_expr +(action 1: %s build.py 1 file03.out file03b.in) +(action 2: %s build.py 2 file03.out file03b.in) +""" % (sys.executable, sys.executable )) + TestSCons.file_expr test.run(arguments='file03.out', status=2, stderr=expect) -- cgit v0.12 From 291dffd00518f6fd49f36b4f174000e264f81f2f Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 15 Jan 2016 21:41:29 -0800 Subject: add testcase for tigris bug # 2622 - AlwaysBuild / MSVC regression --- test/Batch/SConstruct_changed_sources_alwaysBuild | 8 ++++ test/Batch/changed_sources_alwaysbuild.py | 50 +++++++++++++++++++++++ test/Batch/changed_sources_main.cpp | 7 ++++ 3 files changed, 65 insertions(+) create mode 100644 test/Batch/SConstruct_changed_sources_alwaysBuild create mode 100644 test/Batch/changed_sources_alwaysbuild.py create mode 100644 test/Batch/changed_sources_main.cpp diff --git a/test/Batch/SConstruct_changed_sources_alwaysBuild b/test/Batch/SConstruct_changed_sources_alwaysBuild new file mode 100644 index 0000000..c260316 --- /dev/null +++ b/test/Batch/SConstruct_changed_sources_alwaysBuild @@ -0,0 +1,8 @@ +# Testcase for tigris bug 2622 + +object = Object('changed_sources_main.cpp') +AlwaysBuild(object) + +program = Program('test', source = [object]) + +Default(program) diff --git a/test/Batch/changed_sources_alwaysbuild.py b/test/Batch/changed_sources_alwaysbuild.py new file mode 100644 index 0000000..e726d04 --- /dev/null +++ b/test/Batch/changed_sources_alwaysbuild.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# 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. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that files marked AlwaysBuild also get put into CHANGED_SOURCES. +Tigris bug 2622 +""" + +import TestSCons + +test = TestSCons.TestSCons() +test.file_fixture('SConstruct_changed_sources_alwaysBuild','SConstruct') +test.file_fixture('changed_sources_main.cpp') +# always works on first run +test.run() + +# second run prior to fix, the file hasn't changes and so never +# makes it into CHANGED_SOURCES. +# Compile is triggered because SCons knows it needs to build it +test.run() +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Batch/changed_sources_main.cpp b/test/Batch/changed_sources_main.cpp new file mode 100644 index 0000000..038fea3 --- /dev/null +++ b/test/Batch/changed_sources_main.cpp @@ -0,0 +1,7 @@ + +#include + +int main() +{ + std::cout << "Hello, world!\n"; +} -- cgit v0.12 From b75991844f53e4f9aeb9b0ae2909fd452aee113d Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 15 Jan 2016 21:45:26 -0800 Subject: fix for tigris bug # 2622 - AlwaysBuild / MSVC regression - Make sure files marked AlwaysBuild don't get added to unchanged list, but instead always are added to changes lists created in _get_changes in Executor --- src/CHANGES.txt | 4 ++++ src/engine/SCons/Executor.py | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index f59eaaf..ad88f3d 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -22,6 +22,10 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER From William Deegan: - Add better messaging when two environments have different actions for the same target (Bug #2024) + - Fix issue only with MSVC and Always build where targets + marked AlwaysBuild wouldn't make it into CHANNGED_SOURCES + and thus yield an empty compile command line. (Bug #2622) + From Jakub Pola: - Intel Compiler 2016 (Linux/Mac) update for tool directories. diff --git a/src/engine/SCons/Executor.py b/src/engine/SCons/Executor.py index 71671bf..b6d4cb6 100644 --- a/src/engine/SCons/Executor.py +++ b/src/engine/SCons/Executor.py @@ -217,7 +217,9 @@ class Executor(object): us = [] ut = [] for b in self.batches: - if b.targets[0].is_up_to_date(): + # don't add targets marked always build to unchanged lists + # add to changed list as they always need to build + if not b.targets[0].always_build and b.targets[0].is_up_to_date(): us.extend(list(map(rfile, b.sources))) ut.extend(b.targets) else: -- cgit v0.12 From 76d5b4adc2716abf159f64b351bc7f3915b44e08 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 17 Jan 2016 10:49:28 -0800 Subject: fix text to say 'tex' instead of 'text' specifying which tools were missing when the test is skipped --- test/DVIPDF/makeindex.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/DVIPDF/makeindex.py b/test/DVIPDF/makeindex.py index 22a31be..00c57c4 100644 --- a/test/DVIPDF/makeindex.py +++ b/test/DVIPDF/makeindex.py @@ -34,7 +34,7 @@ dvipdf = test.where_is('dvipdf') tex = test.where_is('tex') if not dvipdf or not tex: - test.skip_test('Could not find dvipdf or text; skipping test(s).\n') + test.skip_test('Could not find dvipdf or tex; skipping test(s).\n') -- cgit v0.12 From 49bb971fdcb7c54c5044f5854de3c177a6f41d1f Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 17 Jan 2016 13:21:15 -0800 Subject: fix C code in yacc file to be pass default compiler warnings --- test/YACC/live.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/test/YACC/live.py b/test/YACC/live.py index d567ec3..f6733da 100644 --- a/test/YACC/live.py +++ b/test/YACC/live.py @@ -61,20 +61,23 @@ foo.CFile(target = 'not_foo', source = 'foo.y') yacc = r""" %%{ #include +extern int yyparse(); +int yyerror(char *s); +int yylex(); -main() +int main() { - yyparse(); + return yyparse(); } -yyerror(s) +int yyerror(s) char *s; { fprintf(stderr, "%%s\n", s); return 0; } -yylex() +int yylex() { int c; -- cgit v0.12 From 87d2714f989ab8082dc5bd4111c9d5212e81b1a9 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 17 Jan 2016 14:02:32 -0800 Subject: changes to skip tests on ubuntu-next when gcj and not real java, and also when no latex is available --- QMTest/TestSCons.py | 7 +++++++ test/DVIPDF/makeindex.py | 11 +++++++++-- test/DVIPS/DVIPS.py | 3 +++ test/DVIPS/DVIPSFLAGS.py | 3 +++ test/Java/JAVAH.py | 4 ++-- test/Java/multi-step.py | 4 ++++ test/Java/nested-classes.py | 4 ++++ test/TEX/TEX.py | 3 +++ test/TEX/bibliography.py | 12 ++++++++++-- test/TEX/multi-run.py | 2 ++ 10 files changed, 47 insertions(+), 6 deletions(-) diff --git a/QMTest/TestSCons.py b/QMTest/TestSCons.py index a9fd6a0..43832e8 100644 --- a/QMTest/TestSCons.py +++ b/QMTest/TestSCons.py @@ -201,6 +201,7 @@ class TestSCons(TestCommon): """ scons_version = SConsVersion + javac_is_gcj = False def __init__(self, **kw): """Initialize an SCons testing object. @@ -768,8 +769,13 @@ class TestSCons(TestCommon): m = re.search(r'javac (\d\.\d)', self.stderr()) if m: version = m.group(1) + self.javac_is_gcj = False + elif self.stderr().find('gcj'): + version='1.2' + self.javac_is_gcj = True else: version = None + self.javac_is_gcj = False return where_javac, version def java_where_javah(self, version=None): @@ -792,6 +798,7 @@ class TestSCons(TestCommon): self.skip_test("Could not find Java rmic, skipping non-simulated test(s).\n") return where_rmic + def java_get_class_files(self, dir): result = [] for dirpath, dirnames, filenames in os.walk(dir): diff --git a/test/DVIPDF/makeindex.py b/test/DVIPDF/makeindex.py index 22a31be..b4ac2d0 100644 --- a/test/DVIPDF/makeindex.py +++ b/test/DVIPDF/makeindex.py @@ -31,10 +31,17 @@ test = TestSCons.TestSCons() dvipdf = test.where_is('dvipdf') +if not dvipdf: + test.skip_test('Could not find dvipdf; skipping test(s).\n') + tex = test.where_is('tex') +if not tex: + test.skip_test('Could not find tex; skipping test(s).\n') + +latex = test.where_is('latex') +if not latex: + test.skip_test('Could not find latex; skipping test(s).\n') -if not dvipdf or not tex: - test.skip_test('Could not find dvipdf or text; skipping test(s).\n') diff --git a/test/DVIPS/DVIPS.py b/test/DVIPS/DVIPS.py index e28a121..b243bfc 100644 --- a/test/DVIPS/DVIPS.py +++ b/test/DVIPS/DVIPS.py @@ -114,6 +114,9 @@ test.must_match('test3.ps', "This is a .ltx test.\n") test.must_match('test4.ps', "This is a .latex test.\n") +have_latex = test.where_is('latex') +if not have_latex: + test.skip_test('Could not find latex; skipping test(s).\n') dvips = test.where_is('dvips') diff --git a/test/DVIPS/DVIPSFLAGS.py b/test/DVIPS/DVIPSFLAGS.py index 285c729..4ab1b53 100644 --- a/test/DVIPS/DVIPSFLAGS.py +++ b/test/DVIPS/DVIPSFLAGS.py @@ -120,6 +120,9 @@ test.must_match('test3.ps', " -x\nThis is a .ltx test.\n") test.must_match('test4.ps', " -x\nThis is a .latex test.\n") +have_latex = test.where_is('latex') +if not have_latex: + test.skip_test('Could not find latex; skipping test(s).\n') dvips = test.where_is('dvips') diff --git a/test/Java/JAVAH.py b/test/Java/JAVAH.py index f7c9dcc..df0ec2d 100644 --- a/test/Java/JAVAH.py +++ b/test/Java/JAVAH.py @@ -93,14 +93,14 @@ line 3 test.must_match('test2.h', "test2.JAVA\nline 3\n") - where_javac, java_version = test.java_where_javac() where_javah = test.java_where_javah() if java_version: java_version = repr(java_version) - +if test.javac_is_gcj: + test.skip_test('Test not valid for gcj (gnu java); skipping test(s).\n') test.write("wrapper.py", """\ import os diff --git a/test/Java/multi-step.py b/test/Java/multi-step.py index a8efcd4..4675895 100644 --- a/test/Java/multi-step.py +++ b/test/Java/multi-step.py @@ -43,6 +43,10 @@ swig = test.where_is('swig') if not swig: test.skip_test('Can not find installed "swig", skipping test.\n') +if test.javac_is_gcj: + test.skip_test('Test not valid for gcj (gnu java); skipping test(s).\n') + + test.subdir(['src'], diff --git a/test/Java/nested-classes.py b/test/Java/nested-classes.py index 2b1b5db..8126157 100644 --- a/test/Java/nested-classes.py +++ b/test/Java/nested-classes.py @@ -40,6 +40,10 @@ where_javac, java_version = test.java_where_javac() # Work around javac 1.4 not reporting its version: java_version = java_version or "1.4" +if test.javac_is_gcj: + test.skip_test('Test not valid for gcj (gnu java); skipping test(s).\n') + + test.write('SConstruct', """ env = Environment() env['JAVAVERSION'] = '%(java_version)s' diff --git a/test/TEX/TEX.py b/test/TEX/TEX.py index 24d4bdd..42c1903 100644 --- a/test/TEX/TEX.py +++ b/test/TEX/TEX.py @@ -35,6 +35,9 @@ _python_ = TestSCons._python_ test = TestSCons.TestSCons() +have_latex = test.where_is('latex') +if not have_latex: + test.skip_test('Could not find latex; skipping test(s).\n') test.write('mytex.py', r""" diff --git a/test/TEX/bibliography.py b/test/TEX/bibliography.py index c26b010..9e79320 100644 --- a/test/TEX/bibliography.py +++ b/test/TEX/bibliography.py @@ -36,11 +36,19 @@ import TestSCons test = TestSCons.TestSCons() dvips = test.where_is('dvips') + +if not dvips: + test.skip_test("Could not find dvips; skipping test(s).\n") + bibtex = test.where_is('bibtex') +if not bibtex: + test.skip_test("Could not find bibtex; skipping test(s).\n") -if not dvips or not bibtex: - test.skip_test("Could not find dvips or bibtex; skipping test(s).\n") +have_latex = test.where_is('latex') +if not have_latex: + test.skip_test('Could not find latex; skipping test(s).\n') + test.write('SConstruct', """\ import os env = Environment(tools = ['tex', 'latex', 'dvips']) diff --git a/test/TEX/multi-run.py b/test/TEX/multi-run.py index 7e94be3..37a839b 100644 --- a/test/TEX/multi-run.py +++ b/test/TEX/multi-run.py @@ -39,6 +39,8 @@ test = TestSCons.TestSCons() tex = test.where_is('tex') latex = test.where_is('latex') +if not latex: + test.skip_test("Could not find latex; skipping test(s).\n") if not tex and not latex: test.skip_test("Could not find tex or latex; skipping test(s).\n") -- cgit v0.12 From 04d57cfde1553cb10638a4f2d066c1c7f17a5d6f Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 17 Jan 2016 15:33:39 -0800 Subject: added comment per William Blevins comment on pull request to indicate why we're skipping some tests for gcj --- test/Java/JAVAH.py | 3 +++ test/Java/multi-step.py | 3 +++ test/Java/nested-classes.py | 3 +++ 3 files changed, 9 insertions(+) diff --git a/test/Java/JAVAH.py b/test/Java/JAVAH.py index df0ec2d..81582d7 100644 --- a/test/Java/JAVAH.py +++ b/test/Java/JAVAH.py @@ -99,6 +99,9 @@ where_javah = test.java_where_javah() if java_version: java_version = repr(java_version) +# Skip this test as SCons doesn't (currently) predict the generated +# inner/anonymous class generated .class files generated by gcj +# and so will always fail if test.javac_is_gcj: test.skip_test('Test not valid for gcj (gnu java); skipping test(s).\n') diff --git a/test/Java/multi-step.py b/test/Java/multi-step.py index 4675895..160c523 100644 --- a/test/Java/multi-step.py +++ b/test/Java/multi-step.py @@ -43,6 +43,9 @@ swig = test.where_is('swig') if not swig: test.skip_test('Can not find installed "swig", skipping test.\n') +# Skip this test as SCons doesn't (currently) predict the generated +# inner/anonymous class generated .class files generated by gcj +# and so will always fail if test.javac_is_gcj: test.skip_test('Test not valid for gcj (gnu java); skipping test(s).\n') diff --git a/test/Java/nested-classes.py b/test/Java/nested-classes.py index 8126157..a764054 100644 --- a/test/Java/nested-classes.py +++ b/test/Java/nested-classes.py @@ -40,6 +40,9 @@ where_javac, java_version = test.java_where_javac() # Work around javac 1.4 not reporting its version: java_version = java_version or "1.4" +# Skip this test as SCons doesn't (currently) predict the generated +# inner/anonymous class generated .class files generated by gcj +# and so will always fail if test.javac_is_gcj: test.skip_test('Test not valid for gcj (gnu java); skipping test(s).\n') -- cgit v0.12 From 6cc2ad09d86e6da5812485b0e50a820e2560b31b Mon Sep 17 00:00:00 2001 From: Russel Winder Date: Tue, 19 Jan 2016 10:46:38 +0000 Subject: Correct the Issue number. Amend the test to use an option valid for dmd, ldc2, and gdc. --- .../Issues/2944/D_changed_DFLAGS_not_rebuilding.py | 23 ---------------------- test/D/Issues/2944/image/SConstruct | 11 ----------- test/D/Issues/2944/image/main.d | 11 ----------- .../Issues/2994/D_changed_DFLAGS_not_rebuilding.py | 23 ++++++++++++++++++++++ test/D/Issues/2994/image/SConstruct | 9 +++++++++ test/D/Issues/2994/image/main.d | 11 +++++++++++ 6 files changed, 43 insertions(+), 45 deletions(-) delete mode 100644 test/D/Issues/2944/D_changed_DFLAGS_not_rebuilding.py delete mode 100644 test/D/Issues/2944/image/SConstruct delete mode 100644 test/D/Issues/2944/image/main.d create mode 100644 test/D/Issues/2994/D_changed_DFLAGS_not_rebuilding.py create mode 100644 test/D/Issues/2994/image/SConstruct create mode 100644 test/D/Issues/2994/image/main.d diff --git a/test/D/Issues/2944/D_changed_DFLAGS_not_rebuilding.py b/test/D/Issues/2944/D_changed_DFLAGS_not_rebuilding.py deleted file mode 100644 index 1d9854f..0000000 --- a/test/D/Issues/2944/D_changed_DFLAGS_not_rebuilding.py +++ /dev/null @@ -1,23 +0,0 @@ -# Test to check for issue reported in tigris bug 2994 -# http://scons.tigris.org/issues/show_bug.cgi?id=2994 -# - -import TestSCons - -test = TestSCons.TestSCons() - -dmd_present = test.detect_tool('dmd', prog='dmd') -ldc_present = test.detect_tool('ldc',prog='ldc2') -gdc_present = test.detect_tool('gdc',prog='gdc') - -if not (dmd_present or ldc_present or gdc_present): - test.skip_test("Could not load dmd ldc or gdc Tool; skipping test(s).\n") - - -test.dir_fixture('image') -test.run() -test.fail_test('main.o' not in test.stdout()) -test.run(arguments='change=1') -test.fail_test('is up to date' in test.stdout()) - -test.pass_test() diff --git a/test/D/Issues/2944/image/SConstruct b/test/D/Issues/2944/image/SConstruct deleted file mode 100644 index 2c7deee..0000000 --- a/test/D/Issues/2944/image/SConstruct +++ /dev/null @@ -1,11 +0,0 @@ -# -*- codig:utf-8; -*- - -env=Environment() - -change = ARGUMENTS.get('change', 0) -if int(change): - env.Append(DFLAGS = '-d') - -env.Program('proj', ['main.d']) - - diff --git a/test/D/Issues/2944/image/main.d b/test/D/Issues/2944/image/main.d deleted file mode 100644 index f0aa23a..0000000 --- a/test/D/Issues/2944/image/main.d +++ /dev/null @@ -1,11 +0,0 @@ -/* This program prints a - hello world message - to the console. */ - -import std.stdio; - -void main() -{ - writeln("Hello, World!"); -} - diff --git a/test/D/Issues/2994/D_changed_DFLAGS_not_rebuilding.py b/test/D/Issues/2994/D_changed_DFLAGS_not_rebuilding.py new file mode 100644 index 0000000..1d9854f --- /dev/null +++ b/test/D/Issues/2994/D_changed_DFLAGS_not_rebuilding.py @@ -0,0 +1,23 @@ +# Test to check for issue reported in tigris bug 2994 +# http://scons.tigris.org/issues/show_bug.cgi?id=2994 +# + +import TestSCons + +test = TestSCons.TestSCons() + +dmd_present = test.detect_tool('dmd', prog='dmd') +ldc_present = test.detect_tool('ldc',prog='ldc2') +gdc_present = test.detect_tool('gdc',prog='gdc') + +if not (dmd_present or ldc_present or gdc_present): + test.skip_test("Could not load dmd ldc or gdc Tool; skipping test(s).\n") + + +test.dir_fixture('image') +test.run() +test.fail_test('main.o' not in test.stdout()) +test.run(arguments='change=1') +test.fail_test('is up to date' in test.stdout()) + +test.pass_test() diff --git a/test/D/Issues/2994/image/SConstruct b/test/D/Issues/2994/image/SConstruct new file mode 100644 index 0000000..3d059e7 --- /dev/null +++ b/test/D/Issues/2994/image/SConstruct @@ -0,0 +1,9 @@ +# -*- coding:utf-8; -*- + +env=Environment() + +change = ARGUMENTS.get('change', 0) +if int(change): + env.Append(DFLAGS = '-I.') + +env.Program('proj', ['main.d']) diff --git a/test/D/Issues/2994/image/main.d b/test/D/Issues/2994/image/main.d new file mode 100644 index 0000000..f0aa23a --- /dev/null +++ b/test/D/Issues/2994/image/main.d @@ -0,0 +1,11 @@ +/* This program prints a + hello world message + to the console. */ + +import std.stdio; + +void main() +{ + writeln("Hello, World!"); +} + -- cgit v0.12 From 36d36e8dbf9e43c412f7a52a38dc1f9d9e8bb078 Mon Sep 17 00:00:00 2001 From: William Blevins Date: Sun, 24 Jan 2016 16:36:12 +0000 Subject: Resolving a batch of failing tests for python 2.7. Note: please evaluate python 3.X compliance. --- src/engine/SCons/Script/Main.py | 6 ++---- test/Split.py | 16 ++++++++-------- test/TARGETS.py | 28 ++++++++++++++-------------- test/Variables/BoolVariable.py | 4 ++-- test/Variables/EnumVariable.py | 6 +++--- test/Variables/PackageVariable.py | 2 +- test/Variables/PathVariable.py | 14 +++++++------- test/Variables/Variables.py | 26 +++++++++++++------------- test/Variables/chdir.py | 2 +- test/Variables/help.py | 4 ++-- test/Variables/import.py | 2 +- test/WhereIs.py | 24 ++++++++++++------------ test/_CPPINCFLAGS.py | 6 +++--- test/custom-concat.py | 2 +- test/exitfns.py | 6 +++--- test/import.py | 7 +++---- test/no-arguments.py | 2 +- test/option--C.py | 6 +++--- test/option--I.py | 4 ++-- test/option-f.py | 8 ++++---- test/overrides.py | 6 +++--- test/preserve-source.py | 2 +- test/site_scons/basic.py | 4 ++-- test/site_scons/no-site-dir.py | 4 ++-- test/site_scons/override.py | 2 +- test/site_scons/site-dir.py | 4 ++-- test/site_scons/site_init.py | 8 ++++---- 27 files changed, 101 insertions(+), 104 deletions(-) diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index 7cc7d47..997d701 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -10,8 +10,6 @@ some other module. If it's specific to the "scons" script invocation, it goes here. """ -from __future__ import print_function - unsupported_python_version = (2, 6, 0) deprecated_python_version = (2, 7, 0) @@ -330,7 +328,7 @@ class CleanTask(SCons.Taskmaster.AlwaysTask): except SCons.Errors.UserError as e: print(e) except (IOError, OSError) as e: - print_("scons: Could not remove '%s':" % pathstr, e.strerror) + print("scons: Could not remove '%s':" % pathstr, e.strerror) def _get_files_to_clean(self): result = [] @@ -794,7 +792,7 @@ def _load_all_site_scons_dirs(topdir, verbose=None): dirs=sysdirs + [topdir] for d in dirs: if verbose: # this is used by unit tests. - print_("Loading site dir ", d) + print("Loading site dir ", d) _load_site_scons_dir(d) def test_load_all_site_scons_dirs(d): diff --git a/test/Split.py b/test/Split.py index e98e299..c0533fa 100644 --- a/test/Split.py +++ b/test/Split.py @@ -30,19 +30,19 @@ test = TestSCons.TestSCons() test.write('SConstruct', """ env = Environment(BBB = 'bbb', CCC = 'ccc') -print Split('aaa') -print Split('aaa $BBB') -print env.Split('bbb $CCC') -print env.Split('$BBB ccc') -print Split(['ddd', 'eee']) +print(Split('aaa')) +print(Split('aaa $BBB')) +print(env.Split('bbb $CCC')) +print(env.Split('$BBB ccc')) +print(Split(['ddd', 'eee'])) SConscript('SConscript') """) test.write('SConscript', """ env = Environment(FFF='fff', JJJ='jjj') -print env.Split('${FFF}.f') -print Split('ggg hhh') -print env.Split(['iii', '$JJJ']) +print(env.Split('${FFF}.f')) +print(Split('ggg hhh')) +print(env.Split(['iii', '$JJJ'])) """) expect = """\ diff --git a/test/TARGETS.py b/test/TARGETS.py index 5b36c49..0ffc3b6 100644 --- a/test/TARGETS.py +++ b/test/TARGETS.py @@ -35,11 +35,11 @@ test = TestSCons.TestSCons() test.write('SConstruct', """ -print COMMAND_LINE_TARGETS -print list(map(str, BUILD_TARGETS)) +print(COMMAND_LINE_TARGETS) +print(list(map(str, BUILD_TARGETS))) Default('.') -print COMMAND_LINE_TARGETS -print list(map(str, BUILD_TARGETS)) +print(COMMAND_LINE_TARGETS) +print(list(map(str, BUILD_TARGETS))) """) test.write('aaa', 'aaa\n') @@ -68,17 +68,17 @@ test.run(arguments = 'bbb ccc=xyz -n aaa', stdout = expect) test.write('SConstruct', """ env = Environment() -print list(map(str, DEFAULT_TARGETS)) -print list(map(str, BUILD_TARGETS)) +print(list(map(str, DEFAULT_TARGETS))) +print(list(map(str, BUILD_TARGETS))) Default('aaa') -print list(map(str, DEFAULT_TARGETS)) -print list(map(str, BUILD_TARGETS)) +print(list(map(str, DEFAULT_TARGETS))) +print(list(map(str, BUILD_TARGETS))) env.Default('bbb') -print list(map(str, DEFAULT_TARGETS)) -print list(map(str, BUILD_TARGETS)) +print(list(map(str, DEFAULT_TARGETS))) +print(list(map(str, BUILD_TARGETS))) env.Default(None) -print list(map(str, DEFAULT_TARGETS)) -print list(map(str, BUILD_TARGETS)) +print(list(map(str, DEFAULT_TARGETS))) +print(list(map(str, BUILD_TARGETS))) env.Default('ccc') """) @@ -113,9 +113,9 @@ test.run(arguments = '.', stdout = expect) test.write('SConstruct', """\ -print list(map(str, BUILD_TARGETS)) +print(list(map(str, BUILD_TARGETS))) SConscript('SConscript') -print list(map(str, BUILD_TARGETS)) +print(list(map(str, BUILD_TARGETS))) """) test.write('SConscript', """\ diff --git a/test/Variables/BoolVariable.py b/test/Variables/BoolVariable.py index 365567e..d259984 100644 --- a/test/Variables/BoolVariable.py +++ b/test/Variables/BoolVariable.py @@ -57,8 +57,8 @@ opts.AddVariables( env = Environment(variables=opts) Help(opts.GenerateHelpText(env)) -print env['warnings'] -print env['profile'] +print(env['warnings']) +print(env['profile']) Default(env.Alias('dummy', None)) """) diff --git a/test/Variables/EnumVariable.py b/test/Variables/EnumVariable.py index c04b396..cf35b9b 100644 --- a/test/Variables/EnumVariable.py +++ b/test/Variables/EnumVariable.py @@ -66,9 +66,9 @@ opts.AddVariables( env = Environment(variables=opts) Help(opts.GenerateHelpText(env)) -print env['debug'] -print env['guilib'] -print env['some'] +print(env['debug']) +print(env['guilib']) +print(env['some']) Default(env.Alias('dummy', None)) """) diff --git a/test/Variables/PackageVariable.py b/test/Variables/PackageVariable.py index 322bc9b..b3fd10a 100644 --- a/test/Variables/PackageVariable.py +++ b/test/Variables/PackageVariable.py @@ -59,7 +59,7 @@ opts.AddVariables( env = Environment(variables=opts) Help(opts.GenerateHelpText(env)) -print env['x11'] +print(env['x11']) Default(env.Alias('dummy', None)) """) diff --git a/test/Variables/PathVariable.py b/test/Variables/PathVariable.py index bfe82ba..753aa11 100644 --- a/test/Variables/PathVariable.py +++ b/test/Variables/PathVariable.py @@ -64,9 +64,9 @@ opts.AddVariables( env = Environment(variables=opts) Help(opts.GenerateHelpText(env)) -print env['qtdir'] -print env['qt_libraries'] -print env.subst('$qt_libraries') +print(env['qtdir']) +print(env['qt_libraries']) +print(env.subst('$qt_libraries')) Default(env.Alias('dummy', None)) """ % (workpath, os.path.join('$qtdir', 'lib') )) @@ -132,7 +132,7 @@ opts.AddVariables( env = Environment(variables=opts) -print env['X'] +print(env['X']) Default(env.Alias('dummy', None)) """ % default_subdir) @@ -165,7 +165,7 @@ opts.AddVariables( env = Environment(variables=opts) -print env['X'] +print(env['X']) Default(env.Alias('dummy', None)) """ % default_file) @@ -211,7 +211,7 @@ opts.AddVariables( env = Environment(variables=opts) -print env['X'] +print(env['X']) Default(env.Alias('dummy', None)) """ % default_subdir) @@ -259,7 +259,7 @@ opts.AddVariables( env = Environment(variables=opts) -print env['X'] +print(env['X']) Default(env.Alias('dummy', None)) """ % default_subdir) diff --git a/test/Variables/Variables.py b/test/Variables/Variables.py index d0bf432..1c60635 100644 --- a/test/Variables/Variables.py +++ b/test/Variables/Variables.py @@ -30,8 +30,8 @@ test = TestSCons.TestSCons() test.write('SConstruct', """ env = Environment() -print env['CC'] -print " ".join(env['CCFLAGS']) +print(env['CC']) +print(" ".join(env['CCFLAGS'])) Default(env.Alias('dummy', None)) """) test.run() @@ -99,12 +99,12 @@ env = Environment(variables=opts, tools=['default', test_tool]) Help('Variables settable in custom.py or on the command line:\\n' + opts.GenerateHelpText(env)) -print env['RELEASE_BUILD'] -print env['DEBUG_BUILD'] -print env['CC'] -print " ".join(env['CCFLAGS']) -print env['VALIDATE'] -print env['valid_key'] +print(env['RELEASE_BUILD']) +print(env['DEBUG_BUILD']) +print(env['CC']) +print(" ".join(env['CCFLAGS'])) +print(env['VALIDATE']) +print(env['valid_key']) # unspecified variables should not be set: assert 'UNSPECIFIED' not in env @@ -220,8 +220,8 @@ opts.Add('UNSPECIFIED', env = Environment(variables = opts) -print env['RELEASE_BUILD'] -print env['DEBUG_BUILD'] +print(env['RELEASE_BUILD']) +print(env['DEBUG_BUILD']) opts.Save('variables.saved', env) """) @@ -276,9 +276,9 @@ opts.Add('LISTOPTION_TEST', env = Environment(variables = opts) -print env['RELEASE_BUILD'] -print env['DEBUG_BUILD'] -print env['LISTOPTION_TEST'] +print(env['RELEASE_BUILD']) +print(env['DEBUG_BUILD']) +print(env['LISTOPTION_TEST']) opts.Save('variables.saved', env) """) diff --git a/test/Variables/chdir.py b/test/Variables/chdir.py index 621e166..2d097d5 100644 --- a/test/Variables/chdir.py +++ b/test/Variables/chdir.py @@ -46,7 +46,7 @@ SConscript_contents = """\ Import("opts") env = Environment() opts.Update(env) -print "VARIABLE =", repr(env['VARIABLE']) +print("VARIABLE =", repr(env['VARIABLE'])) """ test.write(['bin', 'opts.cfg'], """\ diff --git a/test/Variables/help.py b/test/Variables/help.py index f04f962..bee6011 100644 --- a/test/Variables/help.py +++ b/test/Variables/help.py @@ -81,8 +81,8 @@ opts.AddVariables( env = Environment(variables=opts) Help(opts.GenerateHelpText(env)) -print env['warnings'] -print env['profile'] +print(env['warnings']) +print(env['profile']) Default(env.Alias('dummy', None)) """ % locals()) diff --git a/test/Variables/import.py b/test/Variables/import.py index 7cdd274..2da670a 100644 --- a/test/Variables/import.py +++ b/test/Variables/import.py @@ -48,7 +48,7 @@ SConscript_contents = """\ Import("opts") env = Environment() opts.Update(env) -print "VARIABLE =", env.get('VARIABLE') +print("VARIABLE =", env.get('VARIABLE')) """ test.write(['bin', 'opts.cfg'], """\ diff --git a/test/WhereIs.py b/test/WhereIs.py index 07c3f6c..c765848 100644 --- a/test/WhereIs.py +++ b/test/WhereIs.py @@ -67,14 +67,14 @@ pathdirs_1243 = [ test.workpath('sub1'), test.write('SConstruct', """ SConscript('%s') env = Environment() -print WhereIs('xxx.exe') -print WhereIs('xxx.exe', %s) -print env.WhereIs('xxx.exe', %s) -print WhereIs('xxx.exe', %s) -print WhereIs('xxx.exe', %s) -print WhereIs('xxx.exe', %s, reject=%s) +print(WhereIs('xxx.exe')) +print(WhereIs('xxx.exe', %s)) +print(env.WhereIs('xxx.exe', %s)) +print(WhereIs('xxx.exe', %s)) +print(WhereIs('xxx.exe', %s)) +print(WhereIs('xxx.exe', %s, reject=%s)) env.Replace( XXXNAME='xxx.exe' ) -print env.WhereIs( '$XXXNAME', %s ) +print(env.WhereIs( '$XXXNAME', %s )) """ % (subdir_SConscript, repr(os.pathsep.join(pathdirs_1234)), repr(os.pathsep.join(pathdirs_1243)), @@ -87,11 +87,11 @@ print env.WhereIs( '$XXXNAME', %s ) test.write(subdir_SConscript, """ env = Environment() -print WhereIs('xxx.exe') -print WhereIs('xxx.exe', %s) -print env.WhereIs('xxx.exe', %s) -print WhereIs('xxx.exe', %s) -print WhereIs('xxx.exe', %s) +print(WhereIs('xxx.exe')) +print(WhereIs('xxx.exe', %s)) +print(env.WhereIs('xxx.exe', %s)) +print(WhereIs('xxx.exe', %s)) +print(WhereIs('xxx.exe', %s)) """ % (repr(os.pathsep.join(pathdirs_1234)), repr(os.pathsep.join(pathdirs_1243)), repr(pathdirs_1234), diff --git a/test/_CPPINCFLAGS.py b/test/_CPPINCFLAGS.py index ccf5e79..c5096ba 100644 --- a/test/_CPPINCFLAGS.py +++ b/test/_CPPINCFLAGS.py @@ -39,9 +39,9 @@ env=Environment(CPPPATH=['tmp'], INCPREFIX='-I') d=Entry('foo.d') e=Entry('foo.e') f=File('foo.f') -print env.subst('$_CPPINCFLAGS', target=e, source=f) -print env.subst('$_CPPINCFLAGS', target=d, source=f) -print env.subst('$_CPPINCFLAGS', target=f, source=d) +print(env.subst('$_CPPINCFLAGS', target=e, source=f)) +print(env.subst('$_CPPINCFLAGS', target=d, source=f)) +print(env.subst('$_CPPINCFLAGS', target=f, source=d)) """) expect = """\ diff --git a/test/custom-concat.py b/test/custom-concat.py index 56c7f64..730e6cd 100644 --- a/test/custom-concat.py +++ b/test/custom-concat.py @@ -44,7 +44,7 @@ env1 = Environment(MYFLAGS=myflags, _concat = my_concat1, MYPREFIX='p', MYSUFFIX='s', STRIPPREFIX='xxx', STRIPSUFFIX='yyy', LIST=['a', 'xxxb', 'cyyy', 'd']) -print env1.subst('$MYFLAGS') +print(env1.subst('$MYFLAGS')) """) expect = test.wrap_stdout(read_str = "mypas1 mypbs1 mypcs1 mypds1\n", diff --git a/test/exitfns.py b/test/exitfns.py index f64969b..d1bda3a 100644 --- a/test/exitfns.py +++ b/test/exitfns.py @@ -32,11 +32,11 @@ sconstruct = """ from SCons.exitfuncs import * def x1(): - print "running x1" + print("running x1") def x2(n): - print "running x2(%s)" % repr(n) + print("running x2(%s)" % repr(n)) def x3(n, kwd=None): - print "running x3(%s, kwd=%s)" % (repr(n), repr(kwd)) + print("running x3(%s, kwd=%s)" % (repr(n), repr(kwd))) register(x3, "no kwd args") register(x1) diff --git a/test/import.py b/test/import.py index d1e1ecf..c23657a 100644 --- a/test/import.py +++ b/test/import.py @@ -21,7 +21,6 @@ # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -64,7 +63,7 @@ platforms = [ for platform in platforms: test.write('SConstruct', """ -print "Platform %(platform)s" +print("Platform %(platform)s") env = Environment(platform = '%(platform)s') import SCons.Platform.%(platform)s x = SCons.Platform.%(platform)s.generate @@ -151,7 +150,7 @@ error_output = { # An SConstruct for importing Tool names that have illegal characters # for Python variable names. indirect_import = """\ -print "Tool %(tool)s (indirect)" +print("Tool %(tool)s (indirect)") env = Environment(tools = ['%(tool)s']) SCons = __import__('SCons.Tool.%(tool)s', globals(), locals(), []) @@ -162,7 +161,7 @@ m.generate(env) # An SConstruct for importing Tool names "normally." direct_import = """\ -print "Tool %(tool)s (direct)" +print("Tool %(tool)s (direct)") env = Environment(tools = ['%(tool)s']) import SCons.Tool.%(tool)s diff --git a/test/no-arguments.py b/test/no-arguments.py index e447ff6..953d827 100644 --- a/test/no-arguments.py +++ b/test/no-arguments.py @@ -40,7 +40,7 @@ test.write('SConstruct', r""" def cat(env, source, target): target = str(target[0]) source = list(map(str, source)) - print 'cat(%s) > %s' % (source, target) + print('cat(%s) > %s' % (source, target)) f = open(target, "wb") for src in source: f.write(open(src, "rb").read()) diff --git a/test/option--C.py b/test/option--C.py index 27f4950..1df3c1a 100644 --- a/test/option--C.py +++ b/test/option--C.py @@ -51,18 +51,18 @@ test.subdir('sub', ['sub', 'dir']) test.write('SConstruct', """ import os -print "SConstruct", os.getcwd() +print("SConstruct", os.getcwd()) """) test.write(['sub', 'SConstruct'], """ import os -print GetBuildPath('..') +print(GetBuildPath('..')) """) test.write(['sub', 'dir', 'SConstruct'], """ import os env = Environment(FOO='foo', BAR='bar') -print env.GetBuildPath('../$FOO/$BAR') +print(env.GetBuildPath('../$FOO/$BAR')) """) test.run(arguments = '-C sub .', diff --git a/test/option--I.py b/test/option--I.py index d65349a..0ca262d 100644 --- a/test/option--I.py +++ b/test/option--I.py @@ -44,9 +44,9 @@ variable = "sub2/bar" test.write('SConstruct', """ import foo -print foo.variable +print(foo.variable) import bar -print bar.variable +print(bar.variable) """) test.run(arguments = '-I sub1 -I sub2 .', diff --git a/test/option-f.py b/test/option-f.py index 2a238d3..9fd1a57 100644 --- a/test/option-f.py +++ b/test/option-f.py @@ -36,17 +36,17 @@ subdir_BuildThis = os.path.join('subdir', 'Buildthis') test.write('SConscript', """ import os -print "SConscript " + os.getcwd() +print("SConscript " + os.getcwd()) """) test.write(subdir_BuildThis, """ import os -print "subdir/BuildThis", os.getcwd() +print("subdir/BuildThis", os.getcwd()) """) test.write('Build2', """ import os -print "Build2", os.getcwd() +print("Build2", os.getcwd()) """) wpath = test.workpath() @@ -85,7 +85,7 @@ test.run(arguments = '--sconstruct=%s .' % subdir_BuildThis, test.run(arguments = '-f - .', stdin = """ import os -print "STDIN " + os.getcwd() +print("STDIN " + os.getcwd()) """, stdout = test.wrap_stdout(read_str = 'STDIN %s\n' % wpath, build_str = "scons: `.' is up to date.\n")) diff --git a/test/overrides.py b/test/overrides.py index d706ab7..69d5207 100644 --- a/test/overrides.py +++ b/test/overrides.py @@ -35,9 +35,9 @@ _python_ = TestSCons._python_ test.write('SConstruct', """ env = Environment(CCFLAGS='-DFOO', LIBS=['a']) def build(target, source, env): - print "env['CC'] =", env['CC'] - print "env['CCFLAGS'] =", env['CCFLAGS'] - print "env['LIBS'] =", env['LIBS'] + print("env['CC'] =", env['CC']) + print("env['CCFLAGS'] =", env['CCFLAGS']) + print("env['LIBS'] =", env['LIBS']) builder = Builder(action=build, CC='buildcc', LIBS='buildlibs') env['BUILDERS']['Build'] = builder diff --git a/test/preserve-source.py b/test/preserve-source.py index 6e09073..b7eccd1 100644 --- a/test/preserve-source.py +++ b/test/preserve-source.py @@ -35,7 +35,7 @@ test.write('SConstruct', r""" def cat(env, source, target): target = str(target[0]) source = list(map(str, source)) - print 'cat(%s) > %s' % (source, target) + print('cat(%s) > %s' % (source, target)) f = open(target, "wb") for src in source: f.write(open(src, "rb").read()) diff --git a/test/site_scons/basic.py b/test/site_scons/basic.py index 1868723..b3ae9f2 100644 --- a/test/site_scons/basic.py +++ b/test/site_scons/basic.py @@ -40,7 +40,7 @@ test.subdir('site_scons', ['site_scons', 'site_tools']) test.write(['site_scons', 'site_init.py'], """ from SCons.Script import * -print "Hi there, I am in site_scons/site_init.py!" +print("Hi there, I am in site_scons/site_init.py!") """) test.write(['site_scons', 'site_tools', 'mytool.py'], """ @@ -54,7 +54,7 @@ def exists(env): test.write('SConstruct', """ e=Environment(tools=['default', 'mytool']) -print e.subst('My site tool is $MYTOOL') +print(e.subst('My site tool is $MYTOOL')) """) test.run(arguments = '-Q .', diff --git a/test/site_scons/no-site-dir.py b/test/site_scons/no-site-dir.py index d01d419..c31ec94 100644 --- a/test/site_scons/no-site-dir.py +++ b/test/site_scons/no-site-dir.py @@ -37,7 +37,7 @@ test.subdir('site_scons', ['site_scons', 'site_tools']) test.write(['site_scons', 'site_init.py'], """ from SCons.Script import * -print "Hi there, I am in site_scons/site_init.py!" +print("Hi there, I am in site_scons/site_init.py!") """) test.write(['site_scons', 'site_tools', 'mytool.py'], """ @@ -68,7 +68,7 @@ test.run(arguments = '-Q --no-site-dir .', test.write('SConstruct', """ e=Environment() -print e.subst('no site: M4 is $M4, M4_MINE is $M4_MINE') +print(e.subst('no site: M4 is $M4, M4_MINE is $M4_MINE')) """) test.run(arguments = '-Q --no-site-dir .') diff --git a/test/site_scons/override.py b/test/site_scons/override.py index e33bb88..d65c09e 100644 --- a/test/site_scons/override.py +++ b/test/site_scons/override.py @@ -49,7 +49,7 @@ def exists(env): test.write('SConstruct', """ e=Environment(tools=['m4']) -print e.subst('M4 is $M4, M4_MINE is $M4_MINE') +print(e.subst('M4 is $M4, M4_MINE is $M4_MINE')) """) test.run(arguments = '-Q .', stdout = """M4 is my_m4, M4_MINE is 1 diff --git a/test/site_scons/site-dir.py b/test/site_scons/site-dir.py index 8e82e94..d60e7d9 100644 --- a/test/site_scons/site-dir.py +++ b/test/site_scons/site-dir.py @@ -38,7 +38,7 @@ test.subdir('site_scons', ['site_scons', 'site_tools']) test.write(['site_scons', 'site_init.py'], """ from SCons.Script import * -print "Hi there, I am in site_scons/site_init.py!" +print("Hi there, I am in site_scons/site_init.py!") """) test.write(['site_scons', 'site_tools', 'mytool.py'], """ @@ -55,7 +55,7 @@ test.subdir('alt_site', ['alt_site', 'site_tools']) test.write(['alt_site', 'site_init.py'], """ from SCons.Script import * -print "Hi there, I am in alt_site/site_init.py!" +print("Hi there, I am in alt_site/site_init.py!") """) test.write('SConstruct', """ diff --git a/test/site_scons/site_init.py b/test/site_scons/site_init.py index 45201ac..27768a9 100644 --- a/test/site_scons/site_init.py +++ b/test/site_scons/site_init.py @@ -58,10 +58,10 @@ for x in list(globals().keys()): continue special.append(x) -print sorted(special) -print __doc__ -print os.path.realpath(__file__) -print __name__ +print(sorted(special)) +print(__doc__) +print(os.path.realpath(__file__)) +print(__name__) """) test.write('SConstruct', "\n") -- cgit v0.12 From 664c1a40e20c38842a7dc8097ba32638c8925dde Mon Sep 17 00:00:00 2001 From: Russel Winder Date: Mon, 25 Jan 2016 07:46:43 +0000 Subject: Add a Shippable build file. --- shippable.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 shippable.yml diff --git a/shippable.yml b/shippable.yml new file mode 100644 index 0000000..b7e363a --- /dev/null +++ b/shippable.yml @@ -0,0 +1,7 @@ +language: python + +python: + - "2.7" + - "3.4" + +script: python runtest.py -a -- cgit v0.12 From 531b6617dcb0bfae3335eead483459651b4a47a0 Mon Sep 17 00:00:00 2001 From: Russel Winder Date: Mon, 25 Jan 2016 08:16:47 +0000 Subject: Add a dummy file to trigger a Codeship build. --- dummy.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 dummy.txt diff --git a/dummy.txt b/dummy.txt new file mode 100644 index 0000000..e69de29 -- cgit v0.12 From 6a42327dfce9dba97ad9643b519e5c93907a45be Mon Sep 17 00:00:00 2001 From: Russel Winder Date: Mon, 25 Jan 2016 09:06:57 +0000 Subject: Remove dummy file. --- dummy.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 dummy.txt diff --git a/dummy.txt b/dummy.txt deleted file mode 100644 index e69de29..0000000 -- cgit v0.12 From 601af04ff6048bc51478c166295cb55105b91803 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 25 Jan 2016 20:20:17 -0800 Subject: change test to verify that the source file name is in the output. Though test will fail if it is not as compile line will miss source file name. --- test/Batch/changed_sources_alwaysbuild.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Batch/changed_sources_alwaysbuild.py b/test/Batch/changed_sources_alwaysbuild.py index e726d04..4446f2d 100644 --- a/test/Batch/changed_sources_alwaysbuild.py +++ b/test/Batch/changed_sources_alwaysbuild.py @@ -41,6 +41,7 @@ test.run() # makes it into CHANGED_SOURCES. # Compile is triggered because SCons knows it needs to build it test.run() +test.must_contain_all_lines(test.stdout(),['changed_sources_main.cpp']) test.pass_test() # Local Variables: -- cgit v0.12 From 04ffc9290157c8643f25404b6469b423589ee72d Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 26 Jan 2016 08:18:40 -0800 Subject: Minor nit fixes. Typos and better comments --- src/CHANGES.txt | 2 +- test/Batch/changed_sources_alwaysbuild.py | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index ad88f3d..dc8a281 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -23,7 +23,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Add better messaging when two environments have different actions for the same target (Bug #2024) - Fix issue only with MSVC and Always build where targets - marked AlwaysBuild wouldn't make it into CHANNGED_SOURCES + marked AlwaysBuild wouldn't make it into CHANGED_SOURCES and thus yield an empty compile command line. (Bug #2622) diff --git a/test/Batch/changed_sources_alwaysbuild.py b/test/Batch/changed_sources_alwaysbuild.py index 4446f2d..ba947d6 100644 --- a/test/Batch/changed_sources_alwaysbuild.py +++ b/test/Batch/changed_sources_alwaysbuild.py @@ -37,9 +37,12 @@ test.file_fixture('changed_sources_main.cpp') # always works on first run test.run() -# second run prior to fix, the file hasn't changes and so never +# On second run prior to fix the file hasn't changed and so never # makes it into CHANGED_SOURCES. -# Compile is triggered because SCons knows it needs to build it +# Compile is triggered because SCons knows it needs to build it. +# This tests that on second run the source file is in the scons +# output. Also prior to fix the compile would fail because +# it would produce a compile command line lacking a source file. test.run() test.must_contain_all_lines(test.stdout(),['changed_sources_main.cpp']) test.pass_test() -- cgit v0.12 From a88dd02a03343dd0a0e17f6ad589148bf77d0493 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 30 Jan 2016 22:35:38 +0000 Subject: Change the cache to use the first two characters of the md5 for the directory name (more smaller directories, because they tend to get huge otherwise) --- src/engine/SCons/CacheDir.py | 2 +- src/engine/SCons/CacheDirTests.py | 2 +- src/script/scons-rename-cachedirs.py | 62 ++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 src/script/scons-rename-cachedirs.py diff --git a/src/engine/SCons/CacheDir.py b/src/engine/SCons/CacheDir.py index 3b7d06f..be0163d 100644 --- a/src/engine/SCons/CacheDir.py +++ b/src/engine/SCons/CacheDir.py @@ -164,7 +164,7 @@ class CacheDir(object): return None, None sig = node.get_cachedir_bsig() - subdir = sig[0].upper() + subdir = sig[:2].upper() dir = os.path.join(self.path, subdir) return dir, os.path.join(dir, sig) diff --git a/src/engine/SCons/CacheDirTests.py b/src/engine/SCons/CacheDirTests.py index 7ac97ef..3b99d41 100644 --- a/src/engine/SCons/CacheDirTests.py +++ b/src/engine/SCons/CacheDirTests.py @@ -100,7 +100,7 @@ class CacheDirTestCase(BaseTestCase): try: f5 = self.File("cd.f5", 'a_fake_bsig') result = self._CacheDir.cachepath(f5) - dirname = os.path.join('cache', 'A') + dirname = os.path.join('cache', 'A_') filename = os.path.join(dirname, 'a_fake_bsig') assert result == (dirname, filename), result finally: diff --git a/src/script/scons-rename-cachedirs.py b/src/script/scons-rename-cachedirs.py new file mode 100644 index 0000000..dd76a42 --- /dev/null +++ b/src/script/scons-rename-cachedirs.py @@ -0,0 +1,62 @@ +#! /usr/bin/env python +# +# SCons - a Software Constructor +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# 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. + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +__version__ = "__VERSION__" + +__build__ = "__BUILD__" + +__buildsys__ = "__BUILDSYS__" + +__date__ = "__DATE__" + +__developer__ = "__DEVELOPER__" + +import glob +import os + +# The entire purpose of this script is to rename the files in the specified +# cache directory from the 16 single hex digit directories to 256 2 hex digit +# directories. + +# You run this in the cache directory. +expected = ['{:X}'.format(x) for x in range(0, 16)] +# check there are 16 directories, 0 - 9, A - F +if sorted(glob.glob('*')) != [x]: + raise RuntimeError("This doesn't look like a cache directory") +dirs = set() +for file in glob.iglob(os.path.join('*', '*')): + name = os.path.basename(file) + dir = name[:2].upper() + print dir, name + if dir not in dirs: + os.mkdir(dir) + dirs.add(dir) + os.rename(file, os.path.join(dir, name)) + + # Now delete the original directories + for dir in expected: + os.rmdir(dir) \ No newline at end of file -- cgit v0.12 From 7f5d85d7f4428fb2fb7271952a00c87dc8c66533 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 30 Jan 2016 22:39:17 +0000 Subject: Fix for backslash being treated as an escape character On my windows system, my python is in c:\apps\32\python. Theres a lot of places where that \32 gets turned into an ascii character and the unit tests don't run. --- QMTest/TestCmd.py | 1 + test/Actions/pre-post.py | 2 +- test/Builder/multi/different-environments.py | 2 +- test/Builder/multi/same-overrides.py | 2 +- test/Builder/srcdir.py | 2 +- test/CacheDir/option--cs.py | 3 ++- test/Command.py | 6 +++--- test/Configure/Builder-call.py | 2 +- test/Configure/custom-tests.py | 4 ++-- test/Deprecated/SourceCode/BitKeeper/BITKEEPERCOM.py | 2 +- test/Deprecated/SourceCode/BitKeeper/BITKEEPERCOMSTR.py | 2 +- test/Deprecated/SourceCode/CVS/CVSCOM.py | 2 +- test/Deprecated/SourceCode/CVS/CVSCOMSTR.py | 2 +- test/Deprecated/SourceCode/Perforce/P4COM.py | 2 +- test/Deprecated/SourceCode/Perforce/P4COMSTR.py | 2 +- test/Deprecated/SourceCode/RCS/RCS_COCOM.py | 2 +- test/Deprecated/SourceCode/RCS/RCS_COCOMSTR.py | 2 +- test/Deprecated/SourceCode/SCCS/SCCSCOM.py | 2 +- test/Deprecated/SourceCode/SCCS/SCCSCOMSTR.py | 2 +- test/ESCAPE.py | 2 +- test/Execute.py | 16 ++++++++-------- test/MSVC/batch.py | 4 ++-- test/Parallel/duplicate-children.py | 4 ++-- test/SConsignFile/default.py | 2 +- test/SConsignFile/explicit-file.py | 2 +- test/SConsignFile/use-dbhash.py | 2 +- test/SConsignFile/use-dumbdbm.py | 2 +- test/ignore-command.py | 14 +++++++------- test/option/debug-findlibs.py | 2 +- test/redirection.py | 8 ++++---- test/silent-command.py | 14 +++++++------- test/special-filenames.py | 2 +- test/srcchange.py | 2 +- test/subdir.py | 2 +- 34 files changed, 62 insertions(+), 60 deletions(-) diff --git a/QMTest/TestCmd.py b/QMTest/TestCmd.py index cd559b7..547522e 100644 --- a/QMTest/TestCmd.py +++ b/QMTest/TestCmd.py @@ -328,6 +328,7 @@ __all__ = [ 'match_re_dotall', 'python', '_python_', +# '_esc_python_', 'TestCmd' ] diff --git a/test/Actions/pre-post.py b/test/Actions/pre-post.py index e09ee02..38a55df 100644 --- a/test/Actions/pre-post.py +++ b/test/Actions/pre-post.py @@ -188,7 +188,7 @@ def post_action(target, source, env): env = Environment() o = env.Command(['pre-post', 'file.out'], 'file.in', - '%(_python_)s build.py ${TARGETS[1]} $SOURCE') + r'%(_python_)s build.py ${TARGETS[1]} $SOURCE') env.AddPreAction(o, pre_action) env.AddPostAction(o, post_action) """ % locals()) diff --git a/test/Builder/multi/different-environments.py b/test/Builder/multi/different-environments.py index 783b7f9..c3e96c2 100644 --- a/test/Builder/multi/different-environments.py +++ b/test/Builder/multi/different-environments.py @@ -47,7 +47,7 @@ build(sys.argv[1],sys.argv[2],sys.argv[3:]) """) test.write('SConstruct', """\ -B = Builder(action='%(_python_)s build.py $foo $TARGET $SOURCES', multi=1) +B = Builder(action=r'%(_python_)s build.py $foo $TARGET $SOURCES', multi=1) env = Environment(BUILDERS = { 'B' : B }) env.B(target = 'file03.out', source = 'file03a.in', foo=1) env.B(target = 'file03.out', source = 'file03b.in', foo=2) diff --git a/test/Builder/multi/same-overrides.py b/test/Builder/multi/same-overrides.py index 33c4e7b..ee169e4 100644 --- a/test/Builder/multi/same-overrides.py +++ b/test/Builder/multi/same-overrides.py @@ -45,7 +45,7 @@ build(sys.argv[1],sys.argv[2],sys.argv[3:]) """) test.write('SConstruct', """\ -B = Builder(action='%(_python_)s build.py $foo $TARGET $SOURCES', multi=1) +B = Builder(action=r'%(_python_)s build.py $foo $TARGET $SOURCES', multi=1) env = Environment(BUILDERS = { 'B' : B }) env.B(target = 'file4.out', source = 'file4a.in', foo=3) env.B(target = 'file4.out', source = 'file4b.in', foo=3) diff --git a/test/Builder/srcdir.py b/test/Builder/srcdir.py index 63732d7..669c5e1 100644 --- a/test/Builder/srcdir.py +++ b/test/Builder/srcdir.py @@ -50,7 +50,7 @@ o.close() test.write(['src', 'SConstruct'], """\ Command('output', ['file1', File('file2'), r'%(file3)s', 'file4'], - '%(_python_)s cat.py $TARGET $SOURCES', + r'%(_python_)s cat.py $TARGET $SOURCES', srcdir='foo') """ % locals()) diff --git a/test/CacheDir/option--cs.py b/test/CacheDir/option--cs.py index b6bb52a..6d22814 100644 --- a/test/CacheDir/option--cs.py +++ b/test/CacheDir/option--cs.py @@ -35,6 +35,7 @@ import shutil import TestSCons _python_ = TestSCons._python_ + _exe = TestSCons._exe _obj = TestSCons._obj @@ -62,7 +63,7 @@ def cat(env, source, target): f.write(open(str(src), "rb").read()) f.close() env = Environment(BUILDERS={'Internal':Builder(action=cat), - 'External':Builder(action='%(_python_)s build.py $TARGET $SOURCES')}) + 'External':Builder(action=r'%(_python_)s build.py $TARGET $SOURCES')}) env.External('aaa.out', 'aaa.in') env.External('bbb.out', 'bbb.in') env.Internal('ccc.out', 'ccc.in') diff --git a/test/Command.py b/test/Command.py index 74046b1..5f72c94 100644 --- a/test/Command.py +++ b/test/Command.py @@ -63,15 +63,15 @@ def sub(env, target, source): t.close() return 0 -env = Environment(COPY_THROUGH_TEMP = '%(_python_)s build.py .tmp $SOURCE\\n%(_python_)s build.py $TARGET .tmp', +env = Environment(COPY_THROUGH_TEMP = r'%(_python_)s build.py .tmp $SOURCE' + '\\n' + r'%(_python_)s build.py $TARGET .tmp', EXPAND = '$COPY_THROUGH_TEMP') env.Command(target = 'f1.out', source = 'f1.in', action = buildIt) env.Command(target = 'f2.out', source = 'f2.in', action = r'%(_python_)s build.py temp2 $SOURCES' + '\\n' + r'%(_python_)s build.py $TARGET temp2') env.Command(target = 'f3.out', source = 'f3.in', - action = [ [ r'%(python)s', 'build.py', 'temp3', '$SOURCES' ], - [ r'%(python)s', 'build.py', '$TARGET', 'temp3'] ]) + action = [ [ r'%(_python_)s', 'build.py', 'temp3', '$SOURCES' ], + [ r'%(_python_)s', 'build.py', '$TARGET', 'temp3'] ]) Command(target = 'f4.out', source = 'sub', action = sub) env.Command(target = 'f5.out', source = 'f5.in', action = buildIt, XYZZY='XYZZY is set') diff --git a/test/Configure/Builder-call.py b/test/Configure/Builder-call.py index 037a2c7..b85b039 100644 --- a/test/Configure/Builder-call.py +++ b/test/Configure/Builder-call.py @@ -48,7 +48,7 @@ def CustomTest(*args): return 0 conf = env.Configure(custom_tests = {'MyTest' : CustomTest}) if not conf.MyTest(): - env.Command("hello", [], '%(_python_)s mycommand.py $TARGET') + env.Command("hello", [], r'%(_python_)s mycommand.py $TARGET') env = conf.Finish() """ % locals()) diff --git a/test/Configure/custom-tests.py b/test/Configure/custom-tests.py index 687ba48..503eb4e 100644 --- a/test/Configure/custom-tests.py +++ b/test/Configure/custom-tests.py @@ -63,8 +63,8 @@ def CheckCustom(test): retLinkFAIL = test.TryLink( '%(linkFAIL)s', '.c' ) (retRunOK, outputRunOK) = test.TryRun( '%(runOK)s', '.c' ) (retRunFAIL, outputRunFAIL) = test.TryRun( '%(runFAIL)s', '.c' ) - (retActOK, outputActOK) = test.TryAction( '%(_python_)s pyAct.py 0 > $TARGET' ) - (retActFAIL, outputActFAIL) = test.TryAction( '%(_python_)s pyAct.py 1 > $TARGET' ) + (retActOK, outputActOK) = test.TryAction( r'%(_python_)s pyAct.py 0 > $TARGET' ) + (retActFAIL, outputActFAIL) = test.TryAction( r'%(_python_)s pyAct.py 1 > $TARGET' ) resOK = retCompileOK and retLinkOK and retRunOK and outputRunOK=="Hello" resOK = resOK and retActOK and int(outputActOK)==0 resFAIL = retCompileFAIL or retLinkFAIL or retRunFAIL or outputRunFAIL!="" diff --git a/test/Deprecated/SourceCode/BitKeeper/BITKEEPERCOM.py b/test/Deprecated/SourceCode/BitKeeper/BITKEEPERCOM.py index d5af0ea..8ff4ced 100644 --- a/test/Deprecated/SourceCode/BitKeeper/BITKEEPERCOM.py +++ b/test/Deprecated/SourceCode/BitKeeper/BITKEEPERCOM.py @@ -74,7 +74,7 @@ def cat(env, source, target): f.close() env = Environment(TOOLS = ['default', 'BitKeeper'], BUILDERS={'Cat':Builder(action=cat)}, - BITKEEPERCOM='%(_python_)s my-bk-get.py $TARGET') + BITKEEPERCOM=r'%(_python_)s my-bk-get.py $TARGET') env.Cat('aaa.out', 'aaa.in') env.Cat('bbb.out', 'bbb.in') env.Cat('ccc.out', 'ccc.in') diff --git a/test/Deprecated/SourceCode/BitKeeper/BITKEEPERCOMSTR.py b/test/Deprecated/SourceCode/BitKeeper/BITKEEPERCOMSTR.py index ef70cb8..5bbdea2 100644 --- a/test/Deprecated/SourceCode/BitKeeper/BITKEEPERCOMSTR.py +++ b/test/Deprecated/SourceCode/BitKeeper/BITKEEPERCOMSTR.py @@ -74,7 +74,7 @@ def cat(env, source, target): f.close() env = Environment(tools = ['default', 'BitKeeper'], BUILDERS={'Cat':Builder(action=cat)}, - BITKEEPERCOM='%(_python_)s my-bk-get.py $TARGET', + BITKEEPERCOM=r'%(_python_)s my-bk-get.py $TARGET', BITKEEPERCOMSTR='Checking out $TARGET from our fake BitKeeper') env.Cat('aaa.out', 'aaa.in') env.Cat('bbb.out', 'bbb.in') diff --git a/test/Deprecated/SourceCode/CVS/CVSCOM.py b/test/Deprecated/SourceCode/CVS/CVSCOM.py index a0f8400..f3bd29d 100644 --- a/test/Deprecated/SourceCode/CVS/CVSCOM.py +++ b/test/Deprecated/SourceCode/CVS/CVSCOM.py @@ -74,7 +74,7 @@ def cat(env, source, target): f.close() env = Environment(TOOLS = ['default', 'CVS'], BUILDERS={'Cat':Builder(action=cat)}, - CVSCOM='%(_python_)s my-cvs-co-.py $TARGET') + CVSCOM=r'%(_python_)s my-cvs-co-.py $TARGET') env.Cat('aaa.out', 'aaa.in') env.Cat('bbb.out', 'bbb.in') env.Cat('ccc.out', 'ccc.in') diff --git a/test/Deprecated/SourceCode/CVS/CVSCOMSTR.py b/test/Deprecated/SourceCode/CVS/CVSCOMSTR.py index f793d66..483a0ae 100644 --- a/test/Deprecated/SourceCode/CVS/CVSCOMSTR.py +++ b/test/Deprecated/SourceCode/CVS/CVSCOMSTR.py @@ -74,7 +74,7 @@ def cat(env, source, target): f.close() env = Environment(TOOLS = ['default', 'CVS'], BUILDERS={'Cat':Builder(action=cat)}, - CVSCOM='%(_python_)s my-cvs-co.py $TARGET', + CVSCOM=r'%(_python_)s my-cvs-co.py $TARGET', CVSCOMSTR='Checking out $TARGET from our fake CVS') env.Cat('aaa.out', 'aaa.in') env.Cat('bbb.out', 'bbb.in') diff --git a/test/Deprecated/SourceCode/Perforce/P4COM.py b/test/Deprecated/SourceCode/Perforce/P4COM.py index 9b9bab1..e58cb60 100644 --- a/test/Deprecated/SourceCode/Perforce/P4COM.py +++ b/test/Deprecated/SourceCode/Perforce/P4COM.py @@ -74,7 +74,7 @@ def cat(env, source, target): f.close() env = Environment(TOOLS = ['default', 'Perforce'], BUILDERS={'Cat':Builder(action=cat)}, - P4COM='%(_python_)s my-p4.py $TARGET') + P4COM=r'%(_python_)s my-p4.py $TARGET') env.Cat('aaa.out', 'aaa.in') env.Cat('bbb.out', 'bbb.in') env.Cat('ccc.out', 'ccc.in') diff --git a/test/Deprecated/SourceCode/Perforce/P4COMSTR.py b/test/Deprecated/SourceCode/Perforce/P4COMSTR.py index 7a24021..7b2fbba 100644 --- a/test/Deprecated/SourceCode/Perforce/P4COMSTR.py +++ b/test/Deprecated/SourceCode/Perforce/P4COMSTR.py @@ -75,7 +75,7 @@ def cat(env, source, target): f.close() env = Environment(TOOLS = ['default', 'Perforce'], BUILDERS={'Cat':Builder(action=cat)}, - P4COM='%(_python_)s my-p4.py $TARGET', + P4COM=r'%(_python_)s my-p4.py $TARGET', P4COMSTR='Checking out $TARGET from our fake Perforce') env.Cat('aaa.out', 'aaa.in') env.Cat('bbb.out', 'bbb.in') diff --git a/test/Deprecated/SourceCode/RCS/RCS_COCOM.py b/test/Deprecated/SourceCode/RCS/RCS_COCOM.py index 765c88c..c5934ac 100644 --- a/test/Deprecated/SourceCode/RCS/RCS_COCOM.py +++ b/test/Deprecated/SourceCode/RCS/RCS_COCOM.py @@ -74,7 +74,7 @@ def cat(env, source, target): f.close() env = Environment(TOOLS = ['default', 'RCS'], BUILDERS={'Cat':Builder(action=cat)}, - RCS_COCOM='%(_python_)s my-rcs-co.py $TARGET') + RCS_COCOM=r'%(_python_)s my-rcs-co.py $TARGET') env.Cat('aaa.out', 'aaa.in') env.Cat('bbb.out', 'bbb.in') env.Cat('ccc.out', 'ccc.in') diff --git a/test/Deprecated/SourceCode/RCS/RCS_COCOMSTR.py b/test/Deprecated/SourceCode/RCS/RCS_COCOMSTR.py index 57088fa..cb54202 100644 --- a/test/Deprecated/SourceCode/RCS/RCS_COCOMSTR.py +++ b/test/Deprecated/SourceCode/RCS/RCS_COCOMSTR.py @@ -74,7 +74,7 @@ def cat(env, source, target): f.close() env = Environment(TOOLS = ['default', 'RCS'], BUILDERS={'Cat':Builder(action=cat)}, - RCS_COCOM='%(_python_)s my-rcs-co.py $TARGET', + RCS_COCOM=r'%(_python_)s my-rcs-co.py $TARGET', RCS_COCOMSTR='Checking out $TARGET from our fake RCS') env.Cat('aaa.out', 'aaa.in') env.Cat('bbb.out', 'bbb.in') diff --git a/test/Deprecated/SourceCode/SCCS/SCCSCOM.py b/test/Deprecated/SourceCode/SCCS/SCCSCOM.py index 6ad02ac..ba89d87 100644 --- a/test/Deprecated/SourceCode/SCCS/SCCSCOM.py +++ b/test/Deprecated/SourceCode/SCCS/SCCSCOM.py @@ -74,7 +74,7 @@ def cat(env, source, target): f.close() env = Environment(TOOLS = ['default', 'SCCS'], BUILDERS={'Cat':Builder(action=cat)}, - SCCSCOM='%(_python_)s my-sccs-get.py $TARGET') + SCCSCOM=r'%(_python_)s my-sccs-get.py $TARGET') env.Cat('aaa.out', 'aaa.in') env.Cat('bbb.out', 'bbb.in') env.Cat('ccc.out', 'ccc.in') diff --git a/test/Deprecated/SourceCode/SCCS/SCCSCOMSTR.py b/test/Deprecated/SourceCode/SCCS/SCCSCOMSTR.py index a757495..2351c05 100644 --- a/test/Deprecated/SourceCode/SCCS/SCCSCOMSTR.py +++ b/test/Deprecated/SourceCode/SCCS/SCCSCOMSTR.py @@ -74,7 +74,7 @@ def cat(env, source, target): f.close() env = Environment(tools = ['default', 'SCCS'], BUILDERS={'Cat':Builder(action=cat)}, - SCCSCOM='%(_python_)s my-sccs-get.py $TARGET', + SCCSCOM=r'%(_python_)s my-sccs-get.py $TARGET', SCCSCOMSTR='Checking out $TARGET from our fake SCCS') env.Cat('aaa.out', 'aaa.in') env.Cat('bbb.out', 'bbb.in') diff --git a/test/ESCAPE.py b/test/ESCAPE.py index 0651b92..819d60b 100644 --- a/test/ESCAPE.py +++ b/test/ESCAPE.py @@ -51,7 +51,7 @@ def my_escape(s): s = s.replace('file.in', 'file.xxx') return orig_escape(s) env = Environment(ESCAPE = my_escape) -env.Command('file.out', 'file.in', '%(_python_)s cat.py $TARGET $SOURCES') +env.Command('file.out', 'file.in', r'%(_python_)s cat.py $TARGET $SOURCES') """ % locals()) test.write('file.in', "file.in\n") diff --git a/test/Execute.py b/test/Execute.py index 2e53444..e63cad5 100644 --- a/test/Execute.py +++ b/test/Execute.py @@ -45,18 +45,18 @@ sys.exit(exitval) """) test.write('SConstruct', """\ -Execute('%(_python_)s my_copy.py a.in a.out') -Execute(Action('%(_python_)s my_copy.py b.in b.out')) +Execute(r'%(_python_)s my_copy.py a.in a.out') +Execute(Action(r'%(_python_)s my_copy.py b.in b.out')) env = Environment(COPY = 'my_copy.py') -env.Execute('%(_python_)s my_copy.py c.in c.out') -env.Execute(Action('%(_python_)s my_copy.py d.in d.out')) -v = env.Execute('%(_python_)s $COPY e.in e.out') +env.Execute(r'%(_python_)s my_copy.py c.in c.out') +env.Execute(Action(r'%(_python_)s my_copy.py d.in d.out')) +v = env.Execute(r'%(_python_)s $COPY e.in e.out') assert v == 0, v -v = env.Execute(Action('%(_python_)s $COPY f.in f.out')) +v = env.Execute(Action(r'%(_python_)s $COPY f.in f.out')) assert v == 0, v -v = env.Execute('%(_python_)s $COPY g.in g.out 1') +v = env.Execute(r'%(_python_)s $COPY g.in g.out 1') assert v == 1, v -v = env.Execute(Action('%(_python_)s $COPY h.in h.out 2')) +v = env.Execute(Action(r'%(_python_)s $COPY h.in h.out 2')) assert v == 2, v import shutil Execute(lambda target, source, env: shutil.copy('i.in', 'i.out')) diff --git a/test/MSVC/batch.py b/test/MSVC/batch.py index fbb3218..8648292 100644 --- a/test/MSVC/batch.py +++ b/test/MSVC/batch.py @@ -72,8 +72,8 @@ for infile in sys.argv[2:]: """) test.write('SConstruct', """ -cccom = '%(_python_)s fake_cl.py $_MSVC_OUTPUT_FLAG $CHANGED_SOURCES' -linkcom = '%(_python_)s fake_link.py ${TARGET.windows} $SOURCES' +cccom = r'%(_python_)s fake_cl.py $_MSVC_OUTPUT_FLAG $CHANGED_SOURCES' +linkcom = r'%(_python_)s fake_link.py ${TARGET.windows} $SOURCES' env = Environment(tools=['msvc', 'mslink'], CCCOM=cccom, LINKCOM=linkcom, diff --git a/test/Parallel/duplicate-children.py b/test/Parallel/duplicate-children.py index c6c5c29..8b8f4cd 100644 --- a/test/Parallel/duplicate-children.py +++ b/test/Parallel/duplicate-children.py @@ -53,8 +53,8 @@ test.write('SConstruct', """ # Test case for SCons issue #1608 # Create a file "foo.in" in the current directory before running scons. env = Environment() -env.Command('foo.out', ['foo.in'], '%(_python_)s cat.py $TARGET $SOURCE && %(_python_)s sleep.py 3') -env.Command('foobar', ['foo.out'], '%(_python_)s cat.py $TARGET $SOURCES') +env.Command('foo.out', ['foo.in'], r'%(_python_)s cat.py $TARGET $SOURCE && %(_python_)s sleep.py 3') +env.Command('foobar', ['foo.out'], r'%(_python_)s cat.py $TARGET $SOURCES') env.Depends('foobar', 'foo.out') """ % locals()) diff --git a/test/SConsignFile/default.py b/test/SConsignFile/default.py index f38aec8..4d56a5e 100644 --- a/test/SConsignFile/default.py +++ b/test/SConsignFile/default.py @@ -49,7 +49,7 @@ sys.exit(0) # test.write('SConstruct', """ SConsignFile() -B = Builder(action = '%(_python_)s build.py $TARGETS $SOURCES') +B = Builder(action = r'%(_python_)s build.py $TARGETS $SOURCES') env = Environment(BUILDERS = { 'B' : B }) env.B(target = 'f1.out', source = 'f1.in') env.B(target = 'f2.out', source = 'f2.in') diff --git a/test/SConsignFile/explicit-file.py b/test/SConsignFile/explicit-file.py index 33963c2..90c2241 100644 --- a/test/SConsignFile/explicit-file.py +++ b/test/SConsignFile/explicit-file.py @@ -49,7 +49,7 @@ file.close() test.write('SConstruct', """ e = Environment(XXX = 'scons') e.SConsignFile('my_${XXX}ign') -B = Builder(action = '%(_python_)s build.py $TARGETS $SOURCES') +B = Builder(action = r'%(_python_)s build.py $TARGETS $SOURCES') env = Environment(BUILDERS = { 'B' : B }) env.B(target = 'f5.out', source = 'f5.in') env.B(target = 'f6.out', source = 'f6.in') diff --git a/test/SConsignFile/use-dbhash.py b/test/SConsignFile/use-dbhash.py index 45e3e36..bf9868b 100644 --- a/test/SConsignFile/use-dbhash.py +++ b/test/SConsignFile/use-dbhash.py @@ -55,7 +55,7 @@ test.write('SConstruct', """ import sys import dbhash SConsignFile('.sconsign', dbhash) -B = Builder(action = '%(_python_)s build.py $TARGETS $SOURCES') +B = Builder(action = r'%(_python_)s build.py $TARGETS $SOURCES') env = Environment(BUILDERS = { 'B' : B }) env.B(target = 'f1.out', source = 'f1.in') env.B(target = 'f2.out', source = 'f2.in') diff --git a/test/SConsignFile/use-dumbdbm.py b/test/SConsignFile/use-dumbdbm.py index 9d48fe5..434435a 100644 --- a/test/SConsignFile/use-dumbdbm.py +++ b/test/SConsignFile/use-dumbdbm.py @@ -55,7 +55,7 @@ test.write('SConstruct', """ import sys import dumbdbm SConsignFile('.sconsign', dumbdbm) -B = Builder(action = '%(_python_)s build.py $TARGETS $SOURCES') +B = Builder(action = r'%(_python_)s build.py $TARGETS $SOURCES') env = Environment(BUILDERS = { 'B' : B }) env.B(target = 'f1.out', source = 'f1.in') env.B(target = 'f2.out', source = 'f2.in') diff --git a/test/ignore-command.py b/test/ignore-command.py index 1343145..9fd24ab 100644 --- a/test/ignore-command.py +++ b/test/ignore-command.py @@ -49,13 +49,13 @@ sys.exit(1) test.write('SConstruct', """\ env = Environment() -f1 = env.Command('f1.out', 'f1.in', '%(_python_)s build.py $TARGET $SOURCE') -f2 = env.Command('f2.out', 'f2.in', '-%(_python_)s build.py $TARGET $SOURCE') -f3 = env.Command('f3.out', 'f3.in', '- %(_python_)s build.py $TARGET $SOURCE') -f4 = env.Command('f4.out', 'f4.in', '@-%(_python_)s build.py $TARGET $SOURCE') -f5 = env.Command('f5.out', 'f5.in', '@- %(_python_)s build.py $TARGET $SOURCE') -f6 = env.Command('f6.out', 'f6.in', '-@%(_python_)s build.py $TARGET $SOURCE') -f7 = env.Command('f7.out', 'f7.in', '-@ %(_python_)s build.py $TARGET $SOURCE') +f1 = env.Command('f1.out', 'f1.in', r'%(_python_)s build.py $TARGET $SOURCE') +f2 = env.Command('f2.out', 'f2.in', r'-%(_python_)s build.py $TARGET $SOURCE') +f3 = env.Command('f3.out', 'f3.in', r'- %(_python_)s build.py $TARGET $SOURCE') +f4 = env.Command('f4.out', 'f4.in', r'@-%(_python_)s build.py $TARGET $SOURCE') +f5 = env.Command('f5.out', 'f5.in', r'@- %(_python_)s build.py $TARGET $SOURCE') +f6 = env.Command('f6.out', 'f6.in', r'-@%(_python_)s build.py $TARGET $SOURCE') +f7 = env.Command('f7.out', 'f7.in', r'-@ %(_python_)s build.py $TARGET $SOURCE') Default(f2, f3, f4, f5, f6, f7) """ % locals()) diff --git a/test/option/debug-findlibs.py b/test/option/debug-findlibs.py index ce97199..9d5c82a 100644 --- a/test/option/debug-findlibs.py +++ b/test/option/debug-findlibs.py @@ -47,7 +47,7 @@ env = Environment(OBJSUFFIX = '.ooo', PROGSUFFIX = '.xxx', LIBS = ['iii', 'jjj', 'kkk', 'lll', 'mmm'], LIBPREFIXES = ['a-', 'b-', 'c-'], LIBSUFFIXES = ['.aaa', '.bbb', '.ccc'], - LINKCOM = '%(_python_)s cat.py $TARGET $SOURCES') + LINKCOM = r'%(_python_)s cat.py $TARGET $SOURCES') env.Program('foo', 'a.ooo',) """ % locals()) diff --git a/test/redirection.py b/test/redirection.py index 55ffeae..98bfc04 100644 --- a/test/redirection.py +++ b/test/redirection.py @@ -43,13 +43,13 @@ sys.exit(0) test.write('SConstruct', r""" env = Environment() env.Command(target='foo1', source='bar1', - action= '%(_python_)s cat.py $SOURCES > $TARGET') + action= r'%(_python_)s cat.py $SOURCES > $TARGET') env.Command(target='foo2', source='bar2', - action= '%(_python_)s cat.py < $SOURCES > $TARGET') + action= r'%(_python_)s cat.py < $SOURCES > $TARGET') env.Command(target='foo3', source='bar3', - action='%(_python_)s cat.py $SOURCES | %(_python_)s cat.py > $TARGET') + action=r'%(_python_)s cat.py $SOURCES | %(_python_)s cat.py > $TARGET') env.Command(target='foo4', source='bar4', - action='%(_python_)s cat.py <$SOURCES |%(_python_)s cat.py >$TARGET') + action=r'%(_python_)s cat.py <$SOURCES |%(_python_)s cat.py >$TARGET') """ % locals()) test.write('bar1', 'bar1\r\n') diff --git a/test/silent-command.py b/test/silent-command.py index 7704ee5..b0e4a2e 100644 --- a/test/silent-command.py +++ b/test/silent-command.py @@ -48,13 +48,13 @@ fp.close() test.write('SConstruct', """\ env = Environment() -env.Command('f1.out', 'f1.in', '%(_python_)s build.py $TARGET $SOURCE') -env.Command('f2.out', 'f2.in', '@%(_python_)s build.py $TARGET $SOURCE') -env.Command('f3.out', 'f3.in', '@ %(_python_)s build.py $TARGET $SOURCE') -env.Command('f4.out', 'f4.in', '@-%(_python_)s build.py $TARGET $SOURCE') -env.Command('f5.out', 'f5.in', '@- %(_python_)s build.py $TARGET $SOURCE') -env.Command('f6.out', 'f6.in', '-@%(_python_)s build.py $TARGET $SOURCE') -env.Command('f7.out', 'f7.in', '-@ %(_python_)s build.py $TARGET $SOURCE') +env.Command('f1.out', 'f1.in', r'%(_python_)s build.py $TARGET $SOURCE') +env.Command('f2.out', 'f2.in', r'@%(_python_)s build.py $TARGET $SOURCE') +env.Command('f3.out', 'f3.in', r'@ %(_python_)s build.py $TARGET $SOURCE') +env.Command('f4.out', 'f4.in', r'@-%(_python_)s build.py $TARGET $SOURCE') +env.Command('f5.out', 'f5.in', r'@- %(_python_)s build.py $TARGET $SOURCE') +env.Command('f6.out', 'f6.in', r'-@%(_python_)s build.py $TARGET $SOURCE') +env.Command('f7.out', 'f7.in', r'-@ %(_python_)s build.py $TARGET $SOURCE') """ % locals()) test.write('f1.in', "f1.in\n") diff --git a/test/special-filenames.py b/test/special-filenames.py index 00e4a3d..de09a52 100644 --- a/test/special-filenames.py +++ b/test/special-filenames.py @@ -69,7 +69,7 @@ def buildFileStr(fn): xxx = '\n'.join(map(buildFileStr, file_names)) test.write("SConstruct", """ -env=Environment(BUILDERS = {'Build' : Builder(action = '%(_python_)s cat.py $TARGET $SOURCE')}) +env=Environment(BUILDERS = {'Build' : Builder(action = r'%(_python_)s cat.py $TARGET $SOURCE')}) %(xxx)s """ % locals()) diff --git a/test/srcchange.py b/test/srcchange.py index d181297..f2fde91 100644 --- a/test/srcchange.py +++ b/test/srcchange.py @@ -63,7 +63,7 @@ SubRevision = Action(subrevision) env=Environment() content_env=env.Clone() -content_env.Command('revision.in', [], '%(_python_)s getrevision > $TARGET') +content_env.Command('revision.in', [], r'%(_python_)s getrevision > $TARGET') content_env.AlwaysBuild('revision.in') env.Precious('main.c') env.Command('main.c', 'revision.in', SubRevision) diff --git a/test/subdir.py b/test/subdir.py index fa10cff..22d0912 100644 --- a/test/subdir.py +++ b/test/subdir.py @@ -42,7 +42,7 @@ file.close() """) test.write('SConstruct', """ -B = Builder(action = '%(_python_)s build.py $TARGETS $SOURCES') +B = Builder(action = r'%(_python_)s build.py $TARGETS $SOURCES') env = Environment(BUILDERS = { 'B' : B }) env.B(target = 'subdir/f1.out', source = 'subdir/f1.in') env.B(target = 'subdir/f2.out', source = 'subdir/f2.in') -- cgit v0.12 From 56db17b7c0f733d1b33e07148f927149263bfc02 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 31 Jan 2016 07:44:47 +0000 Subject: *sigh* Remove commented out code which I couldn't do with an amend --- QMTest/TestCmd.py | 1 - 1 file changed, 1 deletion(-) diff --git a/QMTest/TestCmd.py b/QMTest/TestCmd.py index 547522e..cd559b7 100644 --- a/QMTest/TestCmd.py +++ b/QMTest/TestCmd.py @@ -328,7 +328,6 @@ __all__ = [ 'match_re_dotall', 'python', '_python_', -# '_esc_python_', 'TestCmd' ] -- cgit v0.12 From 193c96046004369ba13fb9b4fc0e992513cc8f78 Mon Sep 17 00:00:00 2001 From: Russel Winder Date: Tue, 2 Feb 2016 17:56:18 +0000 Subject: Remove all the six stuff. --- QMTest/TestCmd.py | 4 - QMTest/TestCmdTests.py | 12 +- bin/install_scons.py | 8 +- src/engine/SCons/MemoizeTests.py | 1 - src/engine/SCons/Tool/xgettext.py | 6 +- src/engine/SCons/Util.py | 24 +- src/engine/SCons/UtilTests.py | 1 - src/engine/SCons/compat/six.py | 646 ------------------------------------ src/engine/SCons/compat/sixTests.py | 35 -- src/script/sconsign.py | 10 +- 10 files changed, 17 insertions(+), 730 deletions(-) delete mode 100755 src/engine/SCons/compat/six.py delete mode 100644 src/engine/SCons/compat/sixTests.py diff --git a/QMTest/TestCmd.py b/QMTest/TestCmd.py index d645731..f8c4e69 100644 --- a/QMTest/TestCmd.py +++ b/QMTest/TestCmd.py @@ -287,8 +287,6 @@ version. # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. from __future__ import division, print_function -from SCons.compat.six import PY3 - __author__ = "Steven Knight " __revision__ = "TestCmd.py 1.3.D001 2010/06/03 12:58:27 knight" __version__ = "1.3" @@ -1730,8 +1728,6 @@ class TestCmd(object): exist. The I/O mode for the file may be specified; it must begin with a 'w'. The default is 'wb' (binary write). """ - if PY3: - content = re.sub(r'print (.+)', r'print(\1)', content) file = self.canonicalize(file) if mode[0] != 'w': raise ValueError("mode must begin with 'w'") diff --git a/QMTest/TestCmdTests.py b/QMTest/TestCmdTests.py index a2e7022..cd62d9f 100644 --- a/QMTest/TestCmdTests.py +++ b/QMTest/TestCmdTests.py @@ -19,8 +19,6 @@ AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. """ -from SCons.compat.six import PY3 - __author__ = "Steven Knight " __revision__ = "TestCmdTests.py 1.3.D001 2010/06/03 12:58:27 knight" @@ -28,19 +26,13 @@ import os import shutil import signal import stat -if PY3: - from io import StringIO -else: - from StringIO import StringIO +from StringIO import StringIO import sys import tempfile import time import types import unittest -if PY3: - from collections import UserList -else: - from UserList import UserList +from UserList import UserList # Strip the current directory so we get the right TestCmd.py module. diff --git a/bin/install_scons.py b/bin/install_scons.py index 55e327d..ac79fd3 100644 --- a/bin/install_scons.py +++ b/bin/install_scons.py @@ -17,19 +17,15 @@ # This was written for a Linux system (specifically Ubuntu) but should # be reasonably generic to any POSIX-style system with a /usr/local # hierarchy. -from __future__ import print_function -from SCons.compat.six import PY3 +from __future__ import print_function import getopt import os import shutil import sys import tarfile -if PY3: - from urllib.request import urlretrieve -else: - from urllib import urlretrieve +from urllib import urlretrieve from Command import CommandRunner, Usage diff --git a/src/engine/SCons/MemoizeTests.py b/src/engine/SCons/MemoizeTests.py index ba866d2..3ce9a11 100644 --- a/src/engine/SCons/MemoizeTests.py +++ b/src/engine/SCons/MemoizeTests.py @@ -20,7 +20,6 @@ # 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 SCons.compat.six import add_metaclass __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/src/engine/SCons/Tool/xgettext.py b/src/engine/SCons/Tool/xgettext.py index ff45989..e9b49b7 100644 --- a/src/engine/SCons/Tool/xgettext.py +++ b/src/engine/SCons/Tool/xgettext.py @@ -23,7 +23,6 @@ Tool specific initialization of `xgettext` tool. # 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 SCons.compat.six import u __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -33,7 +32,7 @@ class _CmdRunner(object): variables. It also provides `strfunction()` method, which shall be used by scons Action objects to print command string. """ - def __init__( self, command, commandstr = None): + def __init__(self, command, commandstr = None): self.out = None self.err = None self.status = None @@ -56,7 +55,8 @@ class _CmdRunner(object): proc = SCons.Action._subproc(env, command, **kw) self.out, self.err = proc.communicate() self.status = proc.wait() - if self.err: sys.stderr.write(u(self.err)) + if self.err: + sys.stderr.write(unicode(self.err)) return self.status def strfunction(self, target, source, env): diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index a66f92a..5b11f83 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -23,7 +23,6 @@ Various utility functions go here. # 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 SCons.compat.six import PY2, PY3, u __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -33,16 +32,13 @@ import copy import re import types -if PY3: - from collections import UserDict, UserList, UserString -else: - from UserDict import UserDict - from UserList import UserList - from UserString import UserString +from UserDict import UserDict +from UserList import UserList +from UserString import UserString # Don't "from types import ..." these because we need to get at the # types module later to look for UnicodeType. -InstanceType = types.InstanceType if PY2 else None +InstanceType = types.InstanceType MethodType = types.MethodType FunctionType = types.FunctionType try: unicode @@ -162,7 +158,7 @@ class DisplayEngine(object): return if append_newline: text = text + '\n' try: - sys.stdout.write(u(text)) + sys.stdout.write(unicode(text)) except IOError: # Stdout might be connected to a pipe that has been closed # by now. The most likely reason for the pipe being closed @@ -256,7 +252,7 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited=None): ' N = no clean\n' + ' H = no cache\n' + '\n') - sys.stdout.write(u(legend)) + sys.stdout.write(unicode(legend)) tags = ['['] tags.append(' E'[IDX(root.exists())]) @@ -1413,15 +1409,11 @@ def AddMethod(obj, function, name=None): if hasattr(obj, '__class__') and obj.__class__ is not type: # "obj" is an instance, so it gets a bound method. - if PY3: - method = MethodType(function, obj) - else: - method = MethodType(function, obj, obj.__class__) + method = MethodType(function, obj, obj.__class__) setattr(obj, name, method) else: # "obj" is a class, so it gets an unbound method. - if PY2: - function = MethodType(function, None, obj) + function = MethodType(function, None, obj) setattr(obj, name, function) def RenameFunction(function, name): diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py index 1e56dc0..9ebb924 100644 --- a/src/engine/SCons/UtilTests.py +++ b/src/engine/SCons/UtilTests.py @@ -20,7 +20,6 @@ # 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 SCons.compat.six import u __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/src/engine/SCons/compat/six.py b/src/engine/SCons/compat/six.py deleted file mode 100755 index 0e8850c..0000000 --- a/src/engine/SCons/compat/six.py +++ /dev/null @@ -1,646 +0,0 @@ -"""Utilities for writing code that runs on Python 2 and 3""" - -# Copyright (c) 2010-2014 Benjamin Peterson -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE 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. - -import operator -import sys -import types - -__author__ = "Benjamin Peterson " -__version__ = "1.6.1" - - -# Useful for very coarse version differentiation. -PY2 = sys.version_info[0] == 2 -PY3 = sys.version_info[0] == 3 - -if PY3: - string_types = str, - integer_types = int, - class_types = type, - text_type = str - binary_type = bytes - - MAXSIZE = sys.maxsize -else: - string_types = basestring, - integer_types = (int, long) - class_types = (type, type) - text_type = unicode - binary_type = str - - if sys.platform.startswith("java"): - # Jython always uses 32 bits. - MAXSIZE = int((1 << 31) - 1) - else: - # It's possible to have sizeof(long) != sizeof(Py_ssize_t). - class X(object): - def __len__(self): - return 1 << 31 - try: - len(X()) - except OverflowError: - # 32-bit - MAXSIZE = int((1 << 31) - 1) - else: - # 64-bit - MAXSIZE = int((1 << 63) - 1) - del X - - -def _add_doc(func, doc): - """Add documentation to a function.""" - func.__doc__ = doc - - -def _import_module(name): - """Import module, returning the module after the last dot.""" - __import__(name) - return sys.modules[name] - - -class _LazyDescr(object): - - def __init__(self, name): - self.name = name - - def __get__(self, obj, tp): - try: - result = self._resolve() - except ImportError: - # See the nice big comment in MovedModule.__getattr__. - raise AttributeError("%s could not be imported " % self.name) - setattr(obj, self.name, result) # Invokes __set__. - # This is a bit ugly, but it avoids running this again. - delattr(obj.__class__, self.name) - return result - - -class MovedModule(_LazyDescr): - - def __init__(self, name, old, new=None): - super(MovedModule, self).__init__(name) - if PY3: - if new is None: - new = name - self.mod = new - else: - self.mod = old - - def _resolve(self): - return _import_module(self.mod) - - def __getattr__(self, attr): - # It turns out many Python frameworks like to traverse sys.modules and - # try to load various attributes. This causes problems if this is a - # platform-specific module on the wrong platform, like _winreg on - # Unixes. Therefore, we silently pretend unimportable modules do not - # have any attributes. See issues #51, #53, #56, and #63 for the full - # tales of woe. - # - # First, if possible, avoid loading the module just to look at __file__, - # __name__, or __path__. - if (attr in ("__file__", "__name__", "__path__") and - self.mod not in sys.modules): - raise AttributeError(attr) - try: - _module = self._resolve() - except ImportError: - raise AttributeError(attr) - value = getattr(_module, attr) - setattr(self, attr, value) - return value - - -class _LazyModule(types.ModuleType): - - def __init__(self, name): - super(_LazyModule, self).__init__(name) - self.__doc__ = self.__class__.__doc__ - - def __dir__(self): - attrs = ["__doc__", "__name__"] - attrs += [attr.name for attr in self._moved_attributes] - return attrs - - # Subclasses should override this - _moved_attributes = [] - - -class MovedAttribute(_LazyDescr): - - def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): - super(MovedAttribute, self).__init__(name) - if PY3: - if new_mod is None: - new_mod = name - self.mod = new_mod - if new_attr is None: - if old_attr is None: - new_attr = name - else: - new_attr = old_attr - self.attr = new_attr - else: - self.mod = old_mod - if old_attr is None: - old_attr = name - self.attr = old_attr - - def _resolve(self): - module = _import_module(self.mod) - return getattr(module, self.attr) - - - -class _MovedItems(_LazyModule): - """Lazy loading of moved objects""" - - -_moved_attributes = [ - MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), - MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), - MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), - MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), - MovedAttribute("map", "itertools", "builtins", "imap", "map"), - MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), - MovedAttribute("reload_module", "__builtin__", "imp", "reload"), - MovedAttribute("reduce", "__builtin__", "functools"), - MovedAttribute("StringIO", "StringIO", "io"), - MovedAttribute("UserString", "UserString", "collections"), - MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), - MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), - MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), - - MovedModule("builtins", "__builtin__"), - MovedModule("configparser", "ConfigParser"), - MovedModule("copyreg", "copy_reg"), - MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), - MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), - MovedModule("http_cookies", "Cookie", "http.cookies"), - MovedModule("html_entities", "htmlentitydefs", "html.entities"), - MovedModule("html_parser", "HTMLParser", "html.parser"), - MovedModule("http_client", "httplib", "http.client"), - MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), - MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), - MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), - MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), - MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), - MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), - MovedModule("cPickle", "cPickle", "pickle"), - MovedModule("queue", "Queue"), - MovedModule("reprlib", "repr"), - MovedModule("socketserver", "SocketServer"), - MovedModule("_thread", "thread", "_thread"), - MovedModule("tkinter", "Tkinter"), - MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), - MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), - MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), - MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), - MovedModule("tkinter_tix", "Tix", "tkinter.tix"), - MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), - MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), - MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), - MovedModule("tkinter_colorchooser", "tkColorChooser", - "tkinter.colorchooser"), - MovedModule("tkinter_commondialog", "tkCommonDialog", - "tkinter.commondialog"), - MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), - MovedModule("tkinter_font", "tkFont", "tkinter.font"), - MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), - MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", - "tkinter.simpledialog"), - MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), - MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), - MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), - MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), - MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), - MovedModule("xmlrpc_server", "xmlrpclib", "xmlrpc.server"), - MovedModule("winreg", "_winreg"), -] -for attr in _moved_attributes: - setattr(_MovedItems, attr.name, attr) - if isinstance(attr, MovedModule): - sys.modules[__name__ + ".moves." + attr.name] = attr -del attr - -_MovedItems._moved_attributes = _moved_attributes - -moves = sys.modules[__name__ + ".moves"] = _MovedItems(__name__ + ".moves") - - -class Module_six_moves_urllib_parse(_LazyModule): - """Lazy loading of moved objects in six.moves.urllib_parse""" - - -_urllib_parse_moved_attributes = [ - MovedAttribute("ParseResult", "urlparse", "urllib.parse"), - MovedAttribute("SplitResult", "urlparse", "urllib.parse"), - MovedAttribute("parse_qs", "urlparse", "urllib.parse"), - MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), - MovedAttribute("urldefrag", "urlparse", "urllib.parse"), - MovedAttribute("urljoin", "urlparse", "urllib.parse"), - MovedAttribute("urlparse", "urlparse", "urllib.parse"), - MovedAttribute("urlsplit", "urlparse", "urllib.parse"), - MovedAttribute("urlunparse", "urlparse", "urllib.parse"), - MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), - MovedAttribute("quote", "urllib", "urllib.parse"), - MovedAttribute("quote_plus", "urllib", "urllib.parse"), - MovedAttribute("unquote", "urllib", "urllib.parse"), - MovedAttribute("unquote_plus", "urllib", "urllib.parse"), - MovedAttribute("urlencode", "urllib", "urllib.parse"), - MovedAttribute("splitquery", "urllib", "urllib.parse"), -] -for attr in _urllib_parse_moved_attributes: - setattr(Module_six_moves_urllib_parse, attr.name, attr) -del attr - -Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes - -sys.modules[__name__ + ".moves.urllib_parse"] = sys.modules[__name__ + ".moves.urllib.parse"] = Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse") - - -class Module_six_moves_urllib_error(_LazyModule): - """Lazy loading of moved objects in six.moves.urllib_error""" - - -_urllib_error_moved_attributes = [ - MovedAttribute("URLError", "urllib2", "urllib.error"), - MovedAttribute("HTTPError", "urllib2", "urllib.error"), - MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), -] -for attr in _urllib_error_moved_attributes: - setattr(Module_six_moves_urllib_error, attr.name, attr) -del attr - -Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes - -sys.modules[__name__ + ".moves.urllib_error"] = sys.modules[__name__ + ".moves.urllib.error"] = Module_six_moves_urllib_error(__name__ + ".moves.urllib.error") - - -class Module_six_moves_urllib_request(_LazyModule): - """Lazy loading of moved objects in six.moves.urllib_request""" - - -_urllib_request_moved_attributes = [ - MovedAttribute("urlopen", "urllib2", "urllib.request"), - MovedAttribute("install_opener", "urllib2", "urllib.request"), - MovedAttribute("build_opener", "urllib2", "urllib.request"), - MovedAttribute("pathname2url", "urllib", "urllib.request"), - MovedAttribute("url2pathname", "urllib", "urllib.request"), - MovedAttribute("getproxies", "urllib", "urllib.request"), - MovedAttribute("Request", "urllib2", "urllib.request"), - MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), - MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), - MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), - MovedAttribute("BaseHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), - MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), - MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), - MovedAttribute("FileHandler", "urllib2", "urllib.request"), - MovedAttribute("FTPHandler", "urllib2", "urllib.request"), - MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), - MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), - MovedAttribute("urlretrieve", "urllib", "urllib.request"), - MovedAttribute("urlcleanup", "urllib", "urllib.request"), - MovedAttribute("URLopener", "urllib", "urllib.request"), - MovedAttribute("FancyURLopener", "urllib", "urllib.request"), - MovedAttribute("proxy_bypass", "urllib", "urllib.request"), -] -for attr in _urllib_request_moved_attributes: - setattr(Module_six_moves_urllib_request, attr.name, attr) -del attr - -Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes - -sys.modules[__name__ + ".moves.urllib_request"] = sys.modules[__name__ + ".moves.urllib.request"] = Module_six_moves_urllib_request(__name__ + ".moves.urllib.request") - - -class Module_six_moves_urllib_response(_LazyModule): - """Lazy loading of moved objects in six.moves.urllib_response""" - - -_urllib_response_moved_attributes = [ - MovedAttribute("addbase", "urllib", "urllib.response"), - MovedAttribute("addclosehook", "urllib", "urllib.response"), - MovedAttribute("addinfo", "urllib", "urllib.response"), - MovedAttribute("addinfourl", "urllib", "urllib.response"), -] -for attr in _urllib_response_moved_attributes: - setattr(Module_six_moves_urllib_response, attr.name, attr) -del attr - -Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes - -sys.modules[__name__ + ".moves.urllib_response"] = sys.modules[__name__ + ".moves.urllib.response"] = Module_six_moves_urllib_response(__name__ + ".moves.urllib.response") - - -class Module_six_moves_urllib_robotparser(_LazyModule): - """Lazy loading of moved objects in six.moves.urllib_robotparser""" - - -_urllib_robotparser_moved_attributes = [ - MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), -] -for attr in _urllib_robotparser_moved_attributes: - setattr(Module_six_moves_urllib_robotparser, attr.name, attr) -del attr - -Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes - -sys.modules[__name__ + ".moves.urllib_robotparser"] = sys.modules[__name__ + ".moves.urllib.robotparser"] = Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser") - - -class Module_six_moves_urllib(types.ModuleType): - """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" - parse = sys.modules[__name__ + ".moves.urllib_parse"] - error = sys.modules[__name__ + ".moves.urllib_error"] - request = sys.modules[__name__ + ".moves.urllib_request"] - response = sys.modules[__name__ + ".moves.urllib_response"] - robotparser = sys.modules[__name__ + ".moves.urllib_robotparser"] - - def __dir__(self): - return ['parse', 'error', 'request', 'response', 'robotparser'] - - -sys.modules[__name__ + ".moves.urllib"] = Module_six_moves_urllib(__name__ + ".moves.urllib") - - -def add_move(move): - """Add an item to six.moves.""" - setattr(_MovedItems, move.name, move) - - -def remove_move(name): - """Remove item from six.moves.""" - try: - delattr(_MovedItems, name) - except AttributeError: - try: - del moves.__dict__[name] - except KeyError: - raise AttributeError("no such move, %r" % (name,)) - - -if PY3: - _meth_func = "__func__" - _meth_self = "__self__" - - _func_closure = "__closure__" - _func_code = "__code__" - _func_defaults = "__defaults__" - _func_globals = "__globals__" - - _iterkeys = "keys" - _itervalues = "values" - _iteritems = "items" - _iterlists = "lists" -else: - _meth_func = "im_func" - _meth_self = "im_self" - - _func_closure = "func_closure" - _func_code = "func_code" - _func_defaults = "func_defaults" - _func_globals = "func_globals" - - _iterkeys = "iterkeys" - _itervalues = "itervalues" - _iteritems = "iteritems" - _iterlists = "iterlists" - - -try: - advance_iterator = next -except NameError: - def advance_iterator(it): - return it.next() -next = advance_iterator - - -try: - callable = callable -except NameError: - def callable(obj): - return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) - - -if PY3: - def get_unbound_function(unbound): - return unbound - - create_bound_method = types.MethodType - - Iterator = object -else: - def get_unbound_function(unbound): - return unbound.__func__ - - def create_bound_method(func, obj): - return types.MethodType(func, obj, obj.__class__) - - class Iterator(object): - - def next(self): - return type(self).__next__(self) - - callable = callable -_add_doc(get_unbound_function, - """Get the function out of a possibly unbound function""") - - -get_method_function = operator.attrgetter(_meth_func) -get_method_self = operator.attrgetter(_meth_self) -get_function_closure = operator.attrgetter(_func_closure) -get_function_code = operator.attrgetter(_func_code) -get_function_defaults = operator.attrgetter(_func_defaults) -get_function_globals = operator.attrgetter(_func_globals) - - -def iterkeys(d, **kw): - """Return an iterator over the keys of a dictionary.""" - return iter(getattr(d, _iterkeys)(**kw)) - -def itervalues(d, **kw): - """Return an iterator over the values of a dictionary.""" - return iter(getattr(d, _itervalues)(**kw)) - -def iteritems(d, **kw): - """Return an iterator over the (key, value) pairs of a dictionary.""" - return iter(getattr(d, _iteritems)(**kw)) - -def iterlists(d, **kw): - """Return an iterator over the (key, [values]) pairs of a dictionary.""" - return iter(getattr(d, _iterlists)(**kw)) - - -if PY3: - def b(s): - return s.encode("latin-1") - def u(s): - return s - unichr = chr - if sys.version_info[1] <= 1: - def int2byte(i): - return bytes((i,)) - else: - # This is about 2x faster than the implementation above on 3.2+ - int2byte = operator.methodcaller("to_bytes", 1, "big") - byte2int = operator.itemgetter(0) - indexbytes = operator.getitem - iterbytes = iter - import io - StringIO = io.StringIO - BytesIO = io.BytesIO -else: - def b(s): - return s - # Workaround for standalone backslash - def u(s): - return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") - unichr = unichr - int2byte = chr - def byte2int(bs): - return ord(bs[0]) - def indexbytes(buf, i): - return ord(buf[i]) - def iterbytes(buf): - return (ord(byte) for byte in buf) - import StringIO - StringIO = BytesIO = StringIO.StringIO -_add_doc(b, """Byte literal""") -_add_doc(u, """Text literal""") - - -if PY3: - exec_ = getattr(moves.builtins, "exec") - - - def reraise(tp, value, tb=None): - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value - -else: - def exec_(_code_, _globs_=None, _locs_=None): - """Execute code in a namespace.""" - if _globs_ is None: - frame = sys._getframe(1) - _globs_ = frame.f_globals - if _locs_ is None: - _locs_ = frame.f_locals - del frame - elif _locs_ is None: - _locs_ = _globs_ - exec("""exec _code_ in _globs_, _locs_""") - - - exec_("""def reraise(tp, value, tb=None): - raise tp, value, tb -""") - - -print_ = getattr(moves.builtins, "print", None) -if print_ is None: - def print_(*args, **kwargs): - """The new-style print function for Python 2.4 and 2.5.""" - fp = kwargs.pop("file", sys.stdout) - if fp is None: - return - def write(data): - if not isinstance(data, basestring): - data = str(data) - # If the file has an encoding, encode unicode with it. - if (isinstance(fp, file) and - isinstance(data, unicode) and - fp.encoding is not None): - errors = getattr(fp, "errors", None) - if errors is None: - errors = "strict" - data = data.encode(fp.encoding, errors) - fp.write(data) - want_unicode = False - sep = kwargs.pop("sep", None) - if sep is not None: - if isinstance(sep, unicode): - want_unicode = True - elif not isinstance(sep, str): - raise TypeError("sep must be None or a string") - end = kwargs.pop("end", None) - if end is not None: - if isinstance(end, unicode): - want_unicode = True - elif not isinstance(end, str): - raise TypeError("end must be None or a string") - if kwargs: - raise TypeError("invalid keyword arguments to print()") - if not want_unicode: - for arg in args: - if isinstance(arg, unicode): - want_unicode = True - break - if want_unicode: - newline = unicode("\n") - space = unicode(" ") - else: - newline = "\n" - space = " " - if sep is None: - sep = space - if end is None: - end = newline - for i, arg in enumerate(args): - if i: - write(sep) - write(arg) - write(end) - -_add_doc(reraise, """Reraise an exception.""") - - -def with_metaclass(meta, *bases): - """Create a base class with a metaclass.""" - return meta("NewBase", bases, {}) - -def add_metaclass(metaclass): - """Class decorator for creating a class with a metaclass.""" - def wrapper(cls): - orig_vars = cls.__dict__.copy() - orig_vars.pop('__dict__', None) - orig_vars.pop('__weakref__', None) - slots = orig_vars.get('__slots__') - if slots is not None: - if isinstance(slots, str): - slots = [slots] - for slots_var in slots: - orig_vars.pop(slots_var) - return metaclass(cls.__name__, cls.__bases__, orig_vars) - return wrapper diff --git a/src/engine/SCons/compat/sixTests.py b/src/engine/SCons/compat/sixTests.py deleted file mode 100644 index 8be3572..0000000 --- a/src/engine/SCons/compat/sixTests.py +++ /dev/null @@ -1,35 +0,0 @@ -# -# __COPYRIGHT__ -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# 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 print_function - -import unittest - -class sixTestCase(unittest.TestCase): - - def test_import(self): - """Test that six imports correctly.""" - import sys - print(sys.path) - from SCons.compat.six import PY2, PY3 - self.assertTrue(PY2 or PY3) diff --git a/src/script/sconsign.py b/src/script/sconsign.py index daf088e..6f49858 100644 --- a/src/script/sconsign.py +++ b/src/script/sconsign.py @@ -25,8 +25,6 @@ from __future__ import print_function -from SCons.compat.six import PY2, PY3 - __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" __version__ = "__VERSION__" @@ -188,8 +186,7 @@ sys.path = libs + sys.path import SCons.compat -if PY2: - import whichdb +import whichdb import dbm import time import pickle @@ -208,10 +205,7 @@ def my_whichdb(filename): pass return _orig_whichdb(filename) -if PY3: - _orig_whichdb = dbm.whichdb -else: - _orig_whichdb = whichdb.whichdb +_orig_whichdb = whichdb.whichdb dbm.whichdb = my_whichdb def my_import(mname): -- cgit v0.12 From 437864c0853d584341536694dd5a6f42708cc4ec Mon Sep 17 00:00:00 2001 From: William Blevins Date: Fri, 19 Feb 2016 17:22:44 +0000 Subject: Issue 2959: Corrected typo in User Guide for Scanner keyword. --- doc/user/scanners.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user/scanners.xml b/doc/user/scanners.xml index 14733db..1506254 100644 --- a/doc/user/scanners.xml +++ b/doc/user/scanners.xml @@ -395,7 +395,7 @@ cat kscan = Scanner(function = kfile_scan, skeys = ['.k'], - path=FindPathDirs('KPATH')) + path_function = FindPathDirs('KPATH')) -- cgit v0.12 From b77d536c21e85818d44b974e3c40a95f9e5e39eb Mon Sep 17 00:00:00 2001 From: William Blevins Date: Fri, 19 Feb 2016 17:25:27 +0000 Subject: Issue 2959: Update CHANGES.txt information. --- src/CHANGES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index c68b89c..b100e9b 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -18,6 +18,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER SCons now respects scanner keys for implicit dependencies. - Resolved missing cross-language dependencies for SWIG bindings (fixes #2264). + - Corrected typo in User Guide for Scanner keyword. (PR #2959) From William Deegan: - Add better messaging when two environments have -- cgit v0.12 From c4ed216120606c40aa95017e50dbbdcb6f649f16 Mon Sep 17 00:00:00 2001 From: William Blevins Date: Mon, 22 Feb 2016 20:10:56 +0000 Subject: Issue 2264: Updated CHANGES.txt to include Cross Language notes. --- src/CHANGES.txt | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index c68b89c..dfd2b9d 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -16,8 +16,19 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER From William Blevins: - Added support for cross-language dependency scanning; SCons now respects scanner keys for implicit dependencies. + - Notes for SCons users with heterogeneous systems. + - May find new (previously missed) dependencies. + - May cause rebuild after upgrade due to dependency changes. + - May find new dependency errors (EG. cycles). + - Discovered in some of the SCons QT tests. - Resolved missing cross-language dependencies for - SWIG bindings (fixes #2264). + SWIG bindings (PR #2264). + - Install builder interacts with scanner found in SCANNERS differently. + - Previous: Install builder recursively scanned implicit dependencies + for scanners from SCANNER, but not for built-in (default) scanners. + - Current: Install builder will not scan for implicit dependencies via + either scanner source. This optimizes some Install builder behavior + and brings orthogonality to Install builder scanning behavior. From William Deegan: - Add better messaging when two environments have -- cgit v0.12 From ed53a2e548f6e5623bf6cb700994c5f17dceb7d0 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 28 Feb 2016 19:41:36 -0800 Subject: Fix for bug # 2225. This undoes the changes to posix special escape characters added in patch for bug 1689 --- src/engine/SCons/Platform/PlatformTests.py | 20 +++++++++++++++++++- src/engine/SCons/Platform/posix.py | 6 ++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/engine/SCons/Platform/PlatformTests.py b/src/engine/SCons/Platform/PlatformTests.py index 38ea55a..3432e94 100644 --- a/src/engine/SCons/Platform/PlatformTests.py +++ b/src/engine/SCons/Platform/PlatformTests.py @@ -187,11 +187,29 @@ class TempFileMungeTestCase(unittest.TestCase): assert cmd != defined_cmd, cmd assert cmd == getattr(target[0].attributes, 'tempfile_cmdlist', None) +class PlatformEscapeTestCase(unittest.TestCase): + def test_posix_escape(self): + """ Check that paths with parens are escaped properly + """ + import SCons.Platform.posix + + test_string = "/my (really) great code/main.cpp" + output = SCons.Platform.posix.escape(test_string) + + # We expect the escape function to wrap the string + # in quotes, but not escape any internal characters + # in the test_string. (Parens doesn't require shell + # escaping if their quoted) + assert output[1:-1] == test_string + + if __name__ == "__main__": suite = unittest.TestSuite() tclasses = [ PlatformTestCase, - TempFileMungeTestCase ] + TempFileMungeTestCase, + PlatformEscapeTestCase, + ] for tclass in tclasses: names = unittest.getTestCaseNames(tclass, 'test_') suite.addTests(list(map(tclass, names))) diff --git a/src/engine/SCons/Platform/posix.py b/src/engine/SCons/Platform/posix.py index 7e69a7c..190a2a6 100644 --- a/src/engine/SCons/Platform/posix.py +++ b/src/engine/SCons/Platform/posix.py @@ -48,16 +48,18 @@ exitvalmap = { } def escape(arg): - "escape shell special characters" + "escape shell special characters" slash = '\\' - special = '"$()' + special = '"$' arg = arg.replace(slash, slash+slash) for c in special: arg = arg.replace(c, slash+c) + # print "ESCAPE RESULT: %s"%arg return '"' + arg + '"' + def exec_subprocess(l, env): proc = subprocess.Popen(l, env = env, close_fds = True) return proc.wait() -- cgit v0.12 From 538146ca65d4fee9ac14011c3c0b0e988b114d37 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 28 Feb 2016 19:47:41 -0800 Subject: Fix for bug # 2225. This undoes the changes to posix special escape characters added in patch for bug 1689 --- src/CHANGES.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index c68b89c..ac264e3 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -25,6 +25,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Fix issue only with MSVC and Always build where targets marked AlwaysBuild wouldn't make it into CHANGED_SOURCES and thus yield an empty compile command line. (Bug #2622) + - Fix posix platform escaping logic to properly handle paths + with parens in them "()". (Bug #2225) From Jakub Pola: -- cgit v0.12 From 453f69278a6ca7f32ab733167d38ea101804f3fb Mon Sep 17 00:00:00 2001 From: anatoly techtonik Date: Wed, 2 Mar 2016 14:09:57 +0300 Subject: script/scons.py - improve error message on missing engine files --- src/script/scons.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/script/scons.py b/src/script/scons.py index e522f57..1b9a824 100644 --- a/src/script/scons.py +++ b/src/script/scons.py @@ -188,8 +188,8 @@ sys.path = libs + sys.path if __name__ == "__main__": try: import SCons.Script - except: - print("Import failed. Unable to find SCons files in:") + except ImportError: + print("SCons import failed. Unable to find engine files in:") for path in libs: print(" %s" % path) raise -- cgit v0.12 From 11cea9c954aff5ce81d85de454dd4547e980b705 Mon Sep 17 00:00:00 2001 From: anatoly techtonik Date: Wed, 2 Mar 2016 14:11:19 +0300 Subject: Fix formatting in SConf check example --- src/engine/SCons/SConf.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index 286f230..94027ec 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -755,10 +755,10 @@ class CheckContext(object): A typical test is just a callable with an instance of CheckContext as first argument: - def CheckCustom(context, ...) - context.Message('Checking my weird test ... ') - ret = myWeirdTestFunction(...) - context.Result(ret) + def CheckCustom(context, ...): + context.Message('Checking my weird test ... ') + ret = myWeirdTestFunction(...) + context.Result(ret) Often, myWeirdTestFunction will be one of context.TryCompile/context.TryLink/context.TryRun. The results of -- cgit v0.12 From a014c40490ca3353d82476ca6a1db2ad80ca57fe Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 12 Mar 2016 23:28:47 +0000 Subject: improve behaviour --- src/engine/SCons/CacheDir.py | 43 ++++++++++++++++++++++++++++++------ src/engine/SCons/CacheDirTests.py | 13 ++++++++--- src/script/scons-rename-cachedirs.py | 30 +++++++++++++++++++------ test/CacheDir/CacheDir.py | 3 ++- test/CacheDir/environment.py | 3 ++- 5 files changed, 73 insertions(+), 19 deletions(-) diff --git a/src/engine/SCons/CacheDir.py b/src/engine/SCons/CacheDir.py index be0163d..728871f 100644 --- a/src/engine/SCons/CacheDir.py +++ b/src/engine/SCons/CacheDir.py @@ -27,7 +27,10 @@ __doc__ = """ CacheDir support """ -import os.path +from collections import defaultdict + +import json +import os import stat import sys @@ -72,7 +75,8 @@ CacheRetrieve = SCons.Action.Action(CacheRetrieveFunc, CacheRetrieveString) CacheRetrieveSilent = SCons.Action.Action(CacheRetrieveFunc, None) def CachePushFunc(target, source, env): - if cache_readonly: return + if cache_readonly: + return t = target[0] if t.nocache: @@ -133,11 +137,36 @@ class CacheDir(object): except ImportError: msg = "No hashlib or MD5 module available, CacheDir() not supported" SCons.Warnings.warn(SCons.Warnings.NoMD5ModuleWarning, msg) - self.path = None - else: - self.path = path + path = None + self.path = path self.current_cache_debug = None self.debugFP = None + self.config = defaultdict() + if path is None: + return + # See if there's a config file in the cache directory + config_file = os.path.join(path, 'config') + if not os.path.exists(config_file): + # If the directory exists we're likely version 1, otherwise + # assume we're latest. + # A note: There is a race hazard here, if two processes start and + # attempt to create the cache directory at the same time. However, + # python doesn't really give you the option to do exclusive file + # creation (it doesn't even give you the option to error on opening + # an existing file for writing...). The ordering of events here + # as an attempt to alleviate this, on the basis that it's a pretty + # unlikely occurence (it'd require two builds with a brand new cache + # directory) + if os.path.isdir(path): + self.config['prefix_len'] = 1 + else: + os.makedirs(path) + self.config['prefix_len'] = 2 + if not os.path.exists(config_file): + with open(config_file, 'w') as config: + self.config = json.dump(self.config, config) + with open(config_file) as config: + self.config = json.load(config) def CacheDebug(self, fmt, target, cachefile): if cache_debug != self.current_cache_debug: @@ -152,7 +181,7 @@ class CacheDir(object): self.debugFP.write(fmt % (target, os.path.split(cachefile)[1])) def is_enabled(self): - return (cache_enabled and not self.path is None) + return cache_enabled and not self.path is None def is_readonly(self): return cache_readonly @@ -164,7 +193,7 @@ class CacheDir(object): return None, None sig = node.get_cachedir_bsig() - subdir = sig[:2].upper() + subdir = sig[:self.config['prefix_len']].upper() dir = os.path.join(self.path, subdir) return dir, os.path.join(dir, sig) diff --git a/src/engine/SCons/CacheDirTests.py b/src/engine/SCons/CacheDirTests.py index 3b99d41..82fba8f 100644 --- a/src/engine/SCons/CacheDirTests.py +++ b/src/engine/SCons/CacheDirTests.py @@ -83,6 +83,11 @@ class BaseTestCase(unittest.TestCase): #node.binfo.ninfo.bsig = bsig return node + def tearDown(self): + os.remove(os.path.join(self._CacheDir.path, 'config')) + os.rmdir(self._CacheDir.path) + # Should that be shutil.rmtree? + class CacheDirTestCase(BaseTestCase): """ Test calling CacheDir code directly. @@ -98,10 +103,12 @@ class CacheDirTestCase(BaseTestCase): SCons.Util.MD5collect = my_collect try: - f5 = self.File("cd.f5", 'a_fake_bsig') + name = 'a_fake_bsig' + f5 = self.File("cd.f5", name) result = self._CacheDir.cachepath(f5) - dirname = os.path.join('cache', 'A_') - filename = os.path.join(dirname, 'a_fake_bsig') + len = self._CacheDir.config['prefix_len'] + dirname = os.path.join('cache', name.upper()[:len]) + filename = os.path.join(dirname, name) assert result == (dirname, filename), result finally: SCons.Util.MD5collect = save_collect diff --git a/src/script/scons-rename-cachedirs.py b/src/script/scons-rename-cachedirs.py index dd76a42..24897d1 100644 --- a/src/script/scons-rename-cachedirs.py +++ b/src/script/scons-rename-cachedirs.py @@ -36,6 +36,7 @@ __date__ = "__DATE__" __developer__ = "__DEVELOPER__" import glob +import json import os # The entire purpose of this script is to rename the files in the specified @@ -43,20 +44,35 @@ import os # directories. # You run this in the cache directory. + expected = ['{:X}'.format(x) for x in range(0, 16)] -# check there are 16 directories, 0 - 9, A - F -if sorted(glob.glob('*')) != [x]: - raise RuntimeError("This doesn't look like a cache directory") + +if not os.path.exists('config'): + # check there are 16 directories, 0 - 9, A - F + if sorted(glob.glob('*')) != expected: + raise RuntimeError("This doesn't look like a (version 1) cache directory") + config = { 'prefix_len' : 1 } +else: + with open('config') as conf: + config = json.load(conf) + if config['prefix_len'] != 1: + raise RuntimeError("This doesn't look like a (version 1) cache directory") + dirs = set() for file in glob.iglob(os.path.join('*', '*')): name = os.path.basename(file) dir = name[:2].upper() - print dir, name if dir not in dirs: os.mkdir(dir) dirs.add(dir) os.rename(file, os.path.join(dir, name)) - # Now delete the original directories - for dir in expected: - os.rmdir(dir) \ No newline at end of file +# Now delete the original directories +for dir in expected: + if os.path.exists(dir): + os.rmdir(dir) + +# and write a config file +config['prefix_len'] = 2 +with open('config', 'w') as conf: + json.dump(config, conf) \ No newline at end of file diff --git a/test/CacheDir/CacheDir.py b/test/CacheDir/CacheDir.py index 9abe0e0..4c05634 100644 --- a/test/CacheDir/CacheDir.py +++ b/test/CacheDir/CacheDir.py @@ -82,7 +82,8 @@ test.must_not_exist(src_aaa_out) test.must_not_exist(src_bbb_out) test.must_not_exist(src_ccc_out) test.must_not_exist(src_all) -test.fail_test(len(os.listdir(cache))) +# Even if you do -n, the cache will be configured. +test.fail_test(os.listdir(cache) != ['config']) # Verify that a normal build works correctly, and clean up. # This should populate the cache with our derived files. diff --git a/test/CacheDir/environment.py b/test/CacheDir/environment.py index 4fb9b51..1378bb2 100644 --- a/test/CacheDir/environment.py +++ b/test/CacheDir/environment.py @@ -85,7 +85,8 @@ test.must_not_exist(src_aaa_out) test.must_not_exist(src_bbb_out) test.must_not_exist(src_ccc_out) test.must_not_exist(src_all) -test.fail_test(len(os.listdir(cache))) +# Even if you do -n, the cache will be configured. +test.fail_test(os.listdir(cache) != ['config']) # Verify that a normal build works correctly, and clean up. # This should populate the cache with our derived files. -- cgit v0.12 From 2a1cc4e5bc95abe0cf43b811ad75bff6015fb45b Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 13 Mar 2016 09:55:01 +0000 Subject: Update to produce warning message. This also means an existing empty cache directory will be treated as v2 (which is probably a good idea...) --- doc/man/scons.xml | 10 ++++++++++ src/CHANGES.txt | 7 +++++++ src/engine/SCons/CacheDir.py | 24 +++++++++++++++++++----- src/engine/SCons/Warnings.py | 4 +++- 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 5c832c2..59ac678 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -1707,6 +1707,16 @@ specifies the type of warnings to be enabled or disabled: + --warn=cache-v1, --warn=no-cache-v1 + +Enables or disables warnings about the cache directory being in the +original (v1) layout. +CacheDir(). +These warnings are enabled by default. + + + + --warn=cache-write-error, --warn=no-cache-write-error Enables or disables warnings about errors trying to diff --git a/src/CHANGES.txt b/src/CHANGES.txt index dc8a281..52cff62 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -6,6 +6,13 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER + From Tom Tanner: + - change cache to use 2 character subdirectories, rather than one character. + For existing caches, you will need to run the scons-rename-cachedirs.py + script to update them to the new format. You will get a warning for this + every time you build. + - Fix a bunch of unit tests on windows + From Dirk Baechle: - Removed a lot of compatibility methods and workarounds for Python versions < 2.7, in order to prepare the work diff --git a/src/engine/SCons/CacheDir.py b/src/engine/SCons/CacheDir.py index 728871f..5b60bae 100644 --- a/src/engine/SCons/CacheDir.py +++ b/src/engine/SCons/CacheDir.py @@ -129,6 +129,10 @@ def CachePushFunc(target, source, env): CachePush = SCons.Action.Action(CachePushFunc, None) +# Nasty hack to cut down to one warning for each cachedir path that needs +# upgrading. +warned = dict() + class CacheDir(object): def __init__(self, path): @@ -147,8 +151,8 @@ class CacheDir(object): # See if there's a config file in the cache directory config_file = os.path.join(path, 'config') if not os.path.exists(config_file): - # If the directory exists we're likely version 1, otherwise - # assume we're latest. + # If the directory exists and is not empty, we're likely version 1. + # # A note: There is a race hazard here, if two processes start and # attempt to create the cache directory at the same time. However, # python doesn't really give you the option to do exclusive file @@ -157,16 +161,26 @@ class CacheDir(object): # as an attempt to alleviate this, on the basis that it's a pretty # unlikely occurence (it'd require two builds with a brand new cache # directory) - if os.path.isdir(path): + if os.path.isdir(path) and len(os.listdir(path)) != 0: self.config['prefix_len'] = 1 - else: - os.makedirs(path) + else: + if not os.path.isdir(path): + os.makedirs(path) self.config['prefix_len'] = 2 if not os.path.exists(config_file): with open(config_file, 'w') as config: self.config = json.dump(self.config, config) with open(config_file) as config: self.config = json.load(config) + # When building the project I was testing this on, this was output + # over 20 times. That seems excessive + global warned + if self.config['prefix_len'] == 1 and self.path not in warned: + msg = "Please update your cache by going into " + self.path +\ + " and running scons-rename-cachedirs.py" + SCons.Warnings.warn(SCons.Warnings.CacheV1Warning, msg) + warned[self.path] = True + def CacheDebug(self, fmt, target, cachefile): if cache_debug != self.current_cache_debug: diff --git a/src/engine/SCons/Warnings.py b/src/engine/SCons/Warnings.py index 5c27825..16319b9 100644 --- a/src/engine/SCons/Warnings.py +++ b/src/engine/SCons/Warnings.py @@ -41,10 +41,12 @@ class WarningOnByDefault(Warning): # NOTE: If you add a new warning class, add it to the man page, too! - class TargetNotBuiltWarning(Warning): # Should go to OnByDefault pass +class CacheV1Warning(WarningOnByDefault): + pass + class CacheWriteErrorWarning(Warning): pass -- cgit v0.12 From b0e44d9dc69b224e75c2ce755ec1a0b7f5585e49 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 19 Mar 2016 10:59:38 +0000 Subject: Cleanup of code/comments and rename and rewrite of upgrade script --- doc/man/scons.xml | 6 +- src/CHANGES.txt | 10 +-- src/engine/SCons/CacheDir.py | 35 +++++----- src/engine/SCons/Warnings.py | 2 +- src/script/scons-configure-cache.py | 123 +++++++++++++++++++++++++++++++++++ src/script/scons-rename-cachedirs.py | 78 ---------------------- 6 files changed, 151 insertions(+), 103 deletions(-) create mode 100644 src/script/scons-configure-cache.py delete mode 100644 src/script/scons-rename-cachedirs.py diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 59ac678..27cf8b7 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -1707,10 +1707,10 @@ specifies the type of warnings to be enabled or disabled: - --warn=cache-v1, --warn=no-cache-v1 + --warn=cache-version, --warn=no-cache-version -Enables or disables warnings about the cache directory being in the -original (v1) layout. +Enables or disables warnings about the cache directory not using +the latest configuration information CacheDir(). These warnings are enabled by default. diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 52cff62..2057199 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -7,10 +7,12 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER From Tom Tanner: - - change cache to use 2 character subdirectories, rather than one character. - For existing caches, you will need to run the scons-rename-cachedirs.py - script to update them to the new format. You will get a warning for this - every time you build. + - change cache to use 2 character subdirectories, rather than one character, + so as not to give huge directories for large caches, a situation which + causes issues for NFS. + For existing caches, you will need to run the scons-configure-cache.py + script to update them to the new format. You will get a warning every time + you build until you co this. - Fix a bunch of unit tests on windows From Dirk Baechle: diff --git a/src/engine/SCons/CacheDir.py b/src/engine/SCons/CacheDir.py index 5b60bae..a941986 100644 --- a/src/engine/SCons/CacheDir.py +++ b/src/engine/SCons/CacheDir.py @@ -148,11 +148,12 @@ class CacheDir(object): self.config = defaultdict() if path is None: return - # See if there's a config file in the cache directory + # See if there's a config file in the cache directory. If there is, + # use it. If there isn't, and the directory exists and isn't empty, + # produce a warning. If the directory doesn't exist or is empty, + # write a config file. config_file = os.path.join(path, 'config') if not os.path.exists(config_file): - # If the directory exists and is not empty, we're likely version 1. - # # A note: There is a race hazard here, if two processes start and # attempt to create the cache directory at the same time. However, # python doesn't really give you the option to do exclusive file @@ -163,24 +164,24 @@ class CacheDir(object): # directory) if os.path.isdir(path) and len(os.listdir(path)) != 0: self.config['prefix_len'] = 1 + # When building the project I was testing this on, the warning + # was output over 20 times. That seems excessive + global warned + if self.path not in warned: + msg = "Please upgrade your cache by running " +\ + " scons-upgrade-cache.py " + self.path + SCons.Warnings.warn(SCons.Warnings.CacheVersionWarning, msg) + warned[self.path] = True else: if not os.path.isdir(path): os.makedirs(path) self.config['prefix_len'] = 2 - if not os.path.exists(config_file): - with open(config_file, 'w') as config: - self.config = json.dump(self.config, config) - with open(config_file) as config: - self.config = json.load(config) - # When building the project I was testing this on, this was output - # over 20 times. That seems excessive - global warned - if self.config['prefix_len'] == 1 and self.path not in warned: - msg = "Please update your cache by going into " + self.path +\ - " and running scons-rename-cachedirs.py" - SCons.Warnings.warn(SCons.Warnings.CacheV1Warning, msg) - warned[self.path] = True - + if not os.path.exists(config_file): + with open(config_file, 'w') as config: + self.config = json.dump(self.config, config) + else: + with open(config_file) as config: + self.config = json.load(config) def CacheDebug(self, fmt, target, cachefile): if cache_debug != self.current_cache_debug: diff --git a/src/engine/SCons/Warnings.py b/src/engine/SCons/Warnings.py index 16319b9..2495b89 100644 --- a/src/engine/SCons/Warnings.py +++ b/src/engine/SCons/Warnings.py @@ -44,7 +44,7 @@ class WarningOnByDefault(Warning): class TargetNotBuiltWarning(Warning): # Should go to OnByDefault pass -class CacheV1Warning(WarningOnByDefault): +class CacheVersionWarning(WarningOnByDefault): pass class CacheWriteErrorWarning(Warning): diff --git a/src/script/scons-configure-cache.py b/src/script/scons-configure-cache.py new file mode 100644 index 0000000..ec3a940 --- /dev/null +++ b/src/script/scons-configure-cache.py @@ -0,0 +1,123 @@ +#! /usr/bin/env python +# +# SCons - a Software Constructor +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# 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. + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +__version__ = "__VERSION__" + +__build__ = "__BUILD__" + +__buildsys__ = "__BUILDSYS__" + +__date__ = "__DATE__" + +__developer__ = "__DEVELOPER__" + +import argparse +import glob +import json +import os + +def rearrange_cache_entries(current_prefix_len, new_prefix_len): + print 'Changing prefix length from', current_prefix_len, 'to', new_prefix_len + dirs = set() + old_dirs = set() + for file in glob.iglob(os.path.join('*', '*')): + name = os.path.basename(file) + dir = name[:current_prefix_len].upper() + if dir not in old_dirs: + print 'Migrating', dir + old_dirs.add(dir) + dir = name[:new_prefix_len].upper() + if dir not in dirs: + os.mkdir(dir) + dirs.add(dir) + os.rename(file, os.path.join(dir, name)) + + # Now delete the original directories + for dir in old_dirs: + os.rmdir(dir) + +parser = argparse.ArgumentParser( + description = 'Modify the configuration of an scons cache directory', + epilog = ''' + Unless you specify an option, it will not be changed (if it is + already set in the cache config), or changed to an appropriate + default (it it is not set). + ''' + ) + +parser.add_argument('cache-dir', help='Path to scons cache directory') +parser.add_argument('--prefix-len', + help='Length of cache file name used as subdirectory prefix', + metavar = '', + type=int) +parser.add_argument('--version', action='version', version='%(prog)s 1.0') + +# Get the command line as a dict without any of the unspecified entries. +args = dict(filter(lambda x: x[1], vars(parser.parse_args()).items())) + +# It seems somewhat strange to me, but positional arguments don't get the - +# in the name changed to _, whereas optional arguments do... +os.chdir(args['cache-dir']) +del args['cache-dir'] + +# If a value isn't currently configured, this contains the way it behaves +# currently (implied), and the way it should behave afer running this script +# (default) +# FIXME: I should use this to construct the parameter list and supply an +# upgrade function +implicit = { + 'prefix_len' : { 'implied' : 1, 'default' : 2 } +} + +if not os.path.exists('config'): + # Validate the only files in the directory are directories 0-9, a-f + expected = [ '{:X}'.format(x) for x in range(0, 16) ] + if not set(os.listdir('.')).issubset(expected): + raise RuntimeError("This doesn't look like a version 1 cache directory") + config = dict() +else: + with open('config') as conf: + config = json.load(conf) + +# Find any keys that aren't currently set but should be +for key in implicit: + if key not in config: + config[key] = implicit[key]['implied'] + if key not in args: + args[key] = implicit[key]['default'] + +#Now we go through each entry in args to see if it changes an existing config +#setting. +for key in args: + if args[key] != config[key]: + if key == 'prefix_len': + rearrange_cache_entries(config[key], args[key]) + config[key] = args[key] + +# and write the updated config file +with open('config', 'w') as conf: + json.dump(config, conf) \ No newline at end of file diff --git a/src/script/scons-rename-cachedirs.py b/src/script/scons-rename-cachedirs.py deleted file mode 100644 index 24897d1..0000000 --- a/src/script/scons-rename-cachedirs.py +++ /dev/null @@ -1,78 +0,0 @@ -#! /usr/bin/env python -# -# SCons - a Software Constructor -# -# __COPYRIGHT__ -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# 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. - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -__version__ = "__VERSION__" - -__build__ = "__BUILD__" - -__buildsys__ = "__BUILDSYS__" - -__date__ = "__DATE__" - -__developer__ = "__DEVELOPER__" - -import glob -import json -import os - -# The entire purpose of this script is to rename the files in the specified -# cache directory from the 16 single hex digit directories to 256 2 hex digit -# directories. - -# You run this in the cache directory. - -expected = ['{:X}'.format(x) for x in range(0, 16)] - -if not os.path.exists('config'): - # check there are 16 directories, 0 - 9, A - F - if sorted(glob.glob('*')) != expected: - raise RuntimeError("This doesn't look like a (version 1) cache directory") - config = { 'prefix_len' : 1 } -else: - with open('config') as conf: - config = json.load(conf) - if config['prefix_len'] != 1: - raise RuntimeError("This doesn't look like a (version 1) cache directory") - -dirs = set() -for file in glob.iglob(os.path.join('*', '*')): - name = os.path.basename(file) - dir = name[:2].upper() - if dir not in dirs: - os.mkdir(dir) - dirs.add(dir) - os.rename(file, os.path.join(dir, name)) - -# Now delete the original directories -for dir in expected: - if os.path.exists(dir): - os.rmdir(dir) - -# and write a config file -config['prefix_len'] = 2 -with open('config', 'w') as conf: - json.dump(config, conf) \ No newline at end of file -- cgit v0.12 From 2bc0caa0e5df6d5602c5640cb54abbacbc74f15c Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 19 Mar 2016 13:09:56 +0000 Subject: Add some error recovery, cleanup scons-configure-cache --- src/engine/SCons/CacheDir.py | 28 +++++++++++++++----- src/script/scons-configure-cache.py | 52 ++++++++++++++++++++++++------------- 2 files changed, 56 insertions(+), 24 deletions(-) diff --git a/src/engine/SCons/CacheDir.py b/src/engine/SCons/CacheDir.py index a941986..aaf3c12 100644 --- a/src/engine/SCons/CacheDir.py +++ b/src/engine/SCons/CacheDir.py @@ -169,19 +169,35 @@ class CacheDir(object): global warned if self.path not in warned: msg = "Please upgrade your cache by running " +\ - " scons-upgrade-cache.py " + self.path + " scons-configure-cache.py " + self.path SCons.Warnings.warn(SCons.Warnings.CacheVersionWarning, msg) warned[self.path] = True else: if not os.path.isdir(path): - os.makedirs(path) + try: + os.makedirs(path) + except OSError: + # If someone else is trying to create the directory at + # the same time as me, bad things will happen + msg = "Failed to create cache directory " + path + raise SCons.Errors.EnvironmentError(msg) + self.config['prefix_len'] = 2 if not os.path.exists(config_file): - with open(config_file, 'w') as config: - self.config = json.dump(self.config, config) + try: + with open(config_file, 'w') as config: + self.config = json.dump(self.config, config) + except: + msg = "Failed to write cache configuration for " + path + raise SCons.Errors.EnvironmentError(msg) else: - with open(config_file) as config: - self.config = json.load(config) + try: + with open(config_file) as config: + self.config = json.load(config) + except ValueError: + msg = "Failed to read cache configuration for " + path + raise SCons.Errors.EnvironmentError(msg) + def CacheDebug(self, fmt, target, cachefile): if cache_debug != self.current_cache_debug: diff --git a/src/script/scons-configure-cache.py b/src/script/scons-configure-cache.py index ec3a940..c1b7d59 100644 --- a/src/script/scons-configure-cache.py +++ b/src/script/scons-configure-cache.py @@ -60,6 +60,29 @@ def rearrange_cache_entries(current_prefix_len, new_prefix_len): for dir in old_dirs: os.rmdir(dir) +# This dictionary should have one entry per entry in the cache config +# Each entry should have the following: +# implicit - (optional) This is to allow adding a new config entry and also +# changing the behaviour of the system at the same time. This +# indicates the value the config entry would have had if it had been +# specified. +# default - The value the config entry should have if it wasn't previously +# specified +# command-line - parameters to pass to ArgumentParser.add_argument +# converter - (optional) Function to call if it's necessary to do some work +# if this configuration entry changes +config_entries = { + 'prefix_len' : { + 'implicit' : 1, + 'default' : 2 , + 'command-line' : { + 'help' : 'Length of cache file name used as subdirectory prefix', + 'metavar' : '', + 'type' : int + }, + 'converter' : rearrange_cache_entries + } +} parser = argparse.ArgumentParser( description = 'Modify the configuration of an scons cache directory', epilog = ''' @@ -70,10 +93,9 @@ parser = argparse.ArgumentParser( ) parser.add_argument('cache-dir', help='Path to scons cache directory') -parser.add_argument('--prefix-len', - help='Length of cache file name used as subdirectory prefix', - metavar = '', - type=int) +for param in config_entries: + parser.add_argument('--' + param.replace('_', '-'), + **config_entries[param]['command-line']) parser.add_argument('--version', action='version', version='%(prog)s 1.0') # Get the command line as a dict without any of the unspecified entries. @@ -84,15 +106,6 @@ args = dict(filter(lambda x: x[1], vars(parser.parse_args()).items())) os.chdir(args['cache-dir']) del args['cache-dir'] -# If a value isn't currently configured, this contains the way it behaves -# currently (implied), and the way it should behave afer running this script -# (default) -# FIXME: I should use this to construct the parameter list and supply an -# upgrade function -implicit = { - 'prefix_len' : { 'implied' : 1, 'default' : 2 } -} - if not os.path.exists('config'): # Validate the only files in the directory are directories 0-9, a-f expected = [ '{:X}'.format(x) for x in range(0, 16) ] @@ -104,18 +117,21 @@ else: config = json.load(conf) # Find any keys that aren't currently set but should be -for key in implicit: +for key in config_entries: if key not in config: - config[key] = implicit[key]['implied'] + if 'implicit' in config_entries[key]: + config[key] = config_entries[key]['implicit'] + else: + config[key] = config_entries[key]['default'] if key not in args: - args[key] = implicit[key]['default'] + args[key] = config_entries[key]['default'] #Now we go through each entry in args to see if it changes an existing config #setting. for key in args: if args[key] != config[key]: - if key == 'prefix_len': - rearrange_cache_entries(config[key], args[key]) + if 'converter' in config_entries[key]: + config_entries[key]['converter'](config[key], args[key]) config[key] = args[key] # and write the updated config file -- cgit v0.12 From acb2487f98360aaab390c0bbc9d9f41faab14502 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 19 Mar 2016 17:11:19 +0000 Subject: oopa --- src/engine/SCons/CacheDir.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/engine/SCons/CacheDir.py b/src/engine/SCons/CacheDir.py index aaf3c12..1690674 100644 --- a/src/engine/SCons/CacheDir.py +++ b/src/engine/SCons/CacheDir.py @@ -27,8 +27,6 @@ __doc__ = """ CacheDir support """ -from collections import defaultdict - import json import os import stat @@ -145,7 +143,7 @@ class CacheDir(object): self.path = path self.current_cache_debug = None self.debugFP = None - self.config = defaultdict() + self.config = dict() if path is None: return # See if there's a config file in the cache directory. If there is, @@ -186,7 +184,7 @@ class CacheDir(object): if not os.path.exists(config_file): try: with open(config_file, 'w') as config: - self.config = json.dump(self.config, config) + json.dump(self.config, config) except: msg = "Failed to write cache configuration for " + path raise SCons.Errors.EnvironmentError(msg) -- cgit v0.12 From 55ff2ce640dc465833dca3c95ce4cdd2b95428aa Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sat, 19 Mar 2016 19:20:26 +0000 Subject: Add some release notes --- src/RELEASE.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/RELEASE.txt b/src/RELEASE.txt index 3bff366..51f2af6 100644 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -32,6 +32,9 @@ NEW FUNCTIONALITY - List new features (presumably why a checkpoint is being released) + - Addition of script scons-configure-cache which allows you to configure + information about a specific cache directly (currently it only supports + determining how the cache files are divided into subdirectories). DEPRECATED FUNCTIONALITY @@ -41,6 +44,11 @@ - List modifications to existing features, where the previous behavior wouldn't actually be considered a bug + - Cache files are now stored in 256 subdirectories in the cache directory + by default (this stresses NFS less). Existing cache directories will + remain as current, but scons will prompt you to run scons-configure-cache + which will allow you to use the new layour, or confirm you want to use the + existing layout. FIXES -- cgit v0.12 From 8f9ad5d0e91468cbe918a7e67affae6be63ac6d5 Mon Sep 17 00:00:00 2001 From: Thomas Tanner Date: Sun, 20 Mar 2016 07:19:59 +0000 Subject: Migrate stuff to the right place --- src/Announce.txt | 8 ++++++++ src/RELEASE.txt | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Announce.txt b/src/Announce.txt index c20d7df..0b58958 100644 --- a/src/Announce.txt +++ b/src/Announce.txt @@ -44,6 +44,12 @@ Notes: a scanner found in SCANNERS (but not for built-in scanners), but now the Install builder will not scan recursively regardless in order to optimize Install behaviour and bring orthogonality to previous behaviour. +* SCons handles cache directories a bit differently/ +** Cache files are now stored in 256 subdirectories in the cache directory by + default (this stresses NFS less). Existing cache directories will remain as + current, but SCons will prompt you to run scons-configure-cache which will + allow you to migrate to the new layout, or confirm you want to use the + existing layout. +================================================================= @@ -56,6 +62,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER changes. Please note the following important changes since release 2.4.0: + - New external tool scons-configurecache which allows some configuration of + how files in the cache are controlled. - Fix to swig tool - pick-up 'swig', 'swig3.0' and 'swig2.0' (in order). - Fix to swig tool - respect env['SWIG'] provided by user. - Fix for Bug # 2791 - Setup.py fails unnecessarily under Jython. diff --git a/src/RELEASE.txt b/src/RELEASE.txt index 51f2af6..3bff366 100644 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -32,9 +32,6 @@ NEW FUNCTIONALITY - List new features (presumably why a checkpoint is being released) - - Addition of script scons-configure-cache which allows you to configure - information about a specific cache directly (currently it only supports - determining how the cache files are divided into subdirectories). DEPRECATED FUNCTIONALITY @@ -44,11 +41,6 @@ - List modifications to existing features, where the previous behavior wouldn't actually be considered a bug - - Cache files are now stored in 256 subdirectories in the cache directory - by default (this stresses NFS less). Existing cache directories will - remain as current, but scons will prompt you to run scons-configure-cache - which will allow you to use the new layour, or confirm you want to use the - existing layout. FIXES -- cgit v0.12 From b0511d03a4939ca9dfd42e14fc39dfced6c5527c Mon Sep 17 00:00:00 2001 From: Tom Plunket Date: Wed, 23 Mar 2016 13:09:38 -0700 Subject: Rewrite file-names.py test so that it runs successfully. --- test/file-names.py | 92 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 35 deletions(-) diff --git a/test/file-names.py b/test/file-names.py index 95b4e4e..2311f38 100644 --- a/test/file-names.py +++ b/test/file-names.py @@ -24,6 +24,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" +import sys import TestSCons test = TestSCons.TestSCons() @@ -38,55 +39,76 @@ test = TestSCons.TestSCons() # parsing and interpretation of redirection and piping. But that # means we have to find ways to work with *all* of their quoting # conventions. -# -# Until we sort that all out, short-circuit this test so we can -# check it in and avoid having to re-invent this wheel later. -test.pass_test() def contents(c): return "|" + c + "|\n" +invalid_chars = '/\0' + if sys.platform == 'win32': - def bad_char(c): - return c in '/\\:' -else: - def bad_char(c): - return c in '/' + invalid_chars = set(invalid_chars) -# Only worry about ASCII characters right now. -# Someone with more Unicode knowledge should enhance this later. -for i in range(1, 255): - c = chr(i) - if not bad_char(c): - test.write("in" + c + "in", contents(c)) + # See the 'naming conventions' section of + # https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx + invalid_chars.update([ chr(c) for c in range(32) ]) + invalid_chars.update(r'\/:*?"<>|') + invalid_chars.update(chr(127)) -test.write('SConstruct', r""" -import sys -if sys.platform == 'win32': + # Win32 filesystems are case insensitive so don't do half the alphabet. + import string + invalid_chars.update(string.lowercase) + + # See the 'naming conventions' section of + # https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx def bad_char(c): - return (c == '/' or c == '\\' or c == ':') + return c in invalid_chars + def invalid_leading_char(c): + # the hash character as a leading character is interpreted to mean the project root + return c in ' #' + def invalid_trailing_char(c): + return c in ' .' + commandString = "copy $SOURCE $TARGET" else: def bad_char(c): - return (c == '/') -env = Environment() -for i in range(1, 255): - c = chr(i) - if not bad_char(c): - if c in '$': - c = '\\' + c - infile = "in" + c + "in" - env.Command(c + "out", infile, "cp $SOURCE $TARGET") - env.Command("out" + c + "out", infile, "cp $SOURCE $TARGET") - env.Command("out" + c, infile, "cp $SOURCE $TARGET") -""") + return c in invalid_chars + def invalid_leading_char(c): + # the hash character as a leading character is interpreted to mean the project root + return c in '#' + def invalid_trailing_char(c): + return False + commandString = "cp $SOURCE $TARGET" + +goodChars = [ chr(c) for c in range(1, 128) if not bad_char(chr(c)) ] + +for c in goodChars: + test.write("in" + c + "in", contents(c)) + +def create_command(a, b, c): + a = ('', 'out')[a] + b = ('', 'out')[b] + return 'env.Command("' + a + c + b + '", "in' + c + 'in", "' + commandString + '")' + +sconstruct = [ 'import sys', 'env = Environment()' ] +for c in goodChars: + if c == '$': + c = '$$' + if c == '"': + c = r'\"' + infile = "in" + c + "in" + if not invalid_leading_char(c): + sconstruct.append(create_command(False, True, c)) + sconstruct.append(create_command(True, True, c)) + if not invalid_trailing_char(c): + sconstruct.append(create_command(True, False, c)) +test.write('SConstruct', '\n'.join(sconstruct)) test.run(arguments = '.') -for i in range(1, 255): - c = chr(i) - if not bad_char(c): +for c in goodChars: + if not invalid_leading_char(c): test.fail_test(test.read(c + "out") != contents(c)) - test.fail_test(test.read("out" + c + "out") != contents(c)) + test.fail_test(test.read("out" + c + "out") != contents(c)) + if not invalid_trailing_char(c): test.fail_test(test.read("out" + c) != contents(c)) test.pass_test() -- cgit v0.12 From af54b28d29b7c1474ba0c35c47783b67709f2702 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 2 Apr 2016 20:51:55 -0700 Subject: fix issues with bad characters and got it working on macosx --- test/file-names.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/test/file-names.py b/test/file-names.py index 2311f38..d9f9c63 100644 --- a/test/file-names.py +++ b/test/file-names.py @@ -69,6 +69,13 @@ if sys.platform == 'win32': return c in ' .' commandString = "copy $SOURCE $TARGET" else: + invalid_chars = set(invalid_chars) + invalid_chars.add(chr(10)) + invalid_chars.add(chr(13)) + invalid_chars.add(chr(92)) # forward slash (dirsep) + invalid_chars.add(chr(96)) # backtick + + def bad_char(c): return c in invalid_chars def invalid_leading_char(c): @@ -80,13 +87,16 @@ else: goodChars = [ chr(c) for c in range(1, 128) if not bad_char(chr(c)) ] +def get_filename(ftype,c): + return ftype+"%d"%ord(c[-1])+c+ftype + for c in goodChars: - test.write("in" + c + "in", contents(c)) + test.write(get_filename("in",c), contents(c)) def create_command(a, b, c): a = ('', 'out')[a] b = ('', 'out')[b] - return 'env.Command("' + a + c + b + '", "in' + c + 'in", "' + commandString + '")' + return 'env.Command("' + a + get_filename('',c) + b + '", "'+get_filename("in",c)+ '","' + commandString + '")' sconstruct = [ 'import sys', 'env = Environment()' ] for c in goodChars: @@ -94,7 +104,7 @@ for c in goodChars: c = '$$' if c == '"': c = r'\"' - infile = "in" + c + "in" + infile = get_filename("in",c) if not invalid_leading_char(c): sconstruct.append(create_command(False, True, c)) sconstruct.append(create_command(True, True, c)) @@ -105,11 +115,14 @@ test.write('SConstruct', '\n'.join(sconstruct)) test.run(arguments = '.') for c in goodChars: +# print "Checking %d "%ord(c) + + c_str = ("%d"%ord(c[-1]))+c if not invalid_leading_char(c): - test.fail_test(test.read(c + "out") != contents(c)) - test.fail_test(test.read("out" + c + "out") != contents(c)) + test.fail_test(test.read(c_str + "out") != contents(c)) + test.fail_test(test.read("out" + c_str + "out") != contents(c)) if not invalid_trailing_char(c): - test.fail_test(test.read("out" + c) != contents(c)) + test.fail_test(test.read("out" + c_str) != contents(c)) test.pass_test() -- cgit v0.12 -- cgit v0.12 -- cgit v0.12 From e694eed46affff41ec7a9b58b61874b534d4e822 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 9 Apr 2016 10:50:38 -0700 Subject: Regenerated docs for 2.5.0 release --- doc/generated/examples/caching_ex-random_1.xml | 4 +-- doc/generated/examples/troubleshoot_explain1_3.xml | 2 +- .../examples/troubleshoot_stacktrace_2.xml | 4 +-- doc/generated/tools.gen | 12 +++---- doc/generated/tools.mod | 4 +-- doc/generated/variables.gen | 40 +++++++++++----------- 6 files changed, 33 insertions(+), 33 deletions(-) diff --git a/doc/generated/examples/caching_ex-random_1.xml b/doc/generated/examples/caching_ex-random_1.xml index cb14259..232e96f 100644 --- a/doc/generated/examples/caching_ex-random_1.xml +++ b/doc/generated/examples/caching_ex-random_1.xml @@ -1,9 +1,9 @@ % scons -Q -cc -o f1.o -c f1.c cc -o f4.o -c f4.c +cc -o f2.o -c f2.c +cc -o f1.o -c f1.c cc -o f5.o -c f5.c cc -o f3.o -c f3.c -cc -o f2.o -c f2.c cc -o prog f1.o f2.o f3.o f4.o f5.o diff --git a/doc/generated/examples/troubleshoot_explain1_3.xml b/doc/generated/examples/troubleshoot_explain1_3.xml index 7e495ea..3d8592d 100644 --- a/doc/generated/examples/troubleshoot_explain1_3.xml +++ b/doc/generated/examples/troubleshoot_explain1_3.xml @@ -3,5 +3,5 @@ cp file.in file.oout scons: warning: Cannot find target file.out after building -File "/home/ghost/projects/scons/bootstrap/src/script/scons.py", line 199, in <module> +File "/scons/as_scons/bootstrap/src/script/scons.py", line 199, in <module> diff --git a/doc/generated/examples/troubleshoot_stacktrace_2.xml b/doc/generated/examples/troubleshoot_stacktrace_2.xml index 1de0dcf..add59ff 100644 --- a/doc/generated/examples/troubleshoot_stacktrace_2.xml +++ b/doc/generated/examples/troubleshoot_stacktrace_2.xml @@ -4,10 +4,10 @@ scons: *** [prog.o] Source `prog.c' not found, needed by target `prog.o'. scons: internal stack trace: File "bootstrap/src/engine/SCons/Job.py", line 199, in start task.prepare() - File "bootstrap/src/engine/SCons/Script/Main.py", line 164, in prepare + File "bootstrap/src/engine/SCons/Script/Main.py", line 173, in prepare return SCons.Taskmaster.OutOfDateTask.prepare(self) File "bootstrap/src/engine/SCons/Taskmaster.py", line 191, in prepare executor.prepare() - File "bootstrap/src/engine/SCons/Executor.py", line 427, in prepare + File "bootstrap/src/engine/SCons/Executor.py", line 430, in prepare raise SCons.Errors.StopError(msg % (s, self.batches[0].targets[0])) diff --git a/doc/generated/tools.gen b/doc/generated/tools.gen index fcb7587..ba12966 100644 --- a/doc/generated/tools.gen +++ b/doc/generated/tools.gen @@ -780,19 +780,19 @@ Sets construction variables for the Sets: &cv-link-AS;, &cv-link-ASCOM;, &cv-link-ASFLAGS;, &cv-link-ASPPCOM;, &cv-link-ASPPFLAGS;.Uses: &cv-link-ASCOMSTR;, &cv-link-ASPPCOMSTR;. - - packaging + + Packaging -A framework for building binary and source packages. +Sets construction variables for the Package Builder. - - Packaging + + packaging -Sets construction variables for the Package Builder. +A framework for building binary and source packages. diff --git a/doc/generated/tools.mod b/doc/generated/tools.mod index 1191e6a..2ee2270 100644 --- a/doc/generated/tools.mod +++ b/doc/generated/tools.mod @@ -78,8 +78,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. mwcc"> mwld"> nasm"> -packaging"> Packaging"> +packaging"> pdf"> pdflatex"> pdftex"> @@ -189,8 +189,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. mwcc"> mwld"> nasm"> -packaging"> Packaging"> +packaging"> pdf"> pdflatex"> pdftex"> diff --git a/doc/generated/variables.gen b/doc/generated/variables.gen index b64eb5a..b377102 100644 --- a/doc/generated/variables.gen +++ b/doc/generated/variables.gen @@ -2838,6 +2838,15 @@ is -dNOPAUSE -dBATCH -sDEVICE=pdfwrite HOST_ARCH + The name of the host hardware architecture used to create the Environment. + If a platform is specified when creating the Environment, then + that Platform's logic will handle setting this value. + This value is immutable, and should not be changed by the user after + the Environment is initialized. + Currently only set for Win32. + + + Sets the host architecture for Visual Studio compiler. If not set, default to the detected host architecture: note that this may depend on the python you are using. @@ -2853,16 +2862,7 @@ Valid values are the same as for This is currently only used on Windows, but in the future it will be used on other OSes as well. - - - The name of the host hardware architecture used to create the Environment. - If a platform is specified when creating the Environment, then - that Platform's logic will handle setting this value. - This value is immutable, and should not be changed by the user after - the Environment is initialized. - Currently only set for Win32. - - + HOST_OS @@ -3104,7 +3104,7 @@ The command line used to call the Java archive tool. The string displayed when the Java archive tool is called -If this is not set, then $JARCOM (the command line) is displayed. +If this is not set, then $JARCOM (the command line) is displayed. @@ -3114,7 +3114,7 @@ env = Environment(JARCOMSTR = "JARchiving $SOURCES into $TARGET") The string displayed when the Java archive tool is called -If this is not set, then $JARCOM (the command line) is displayed. +If this is not set, then $JARCOM (the command line) is displayed. @@ -7038,6 +7038,13 @@ that may not be set or used in a construction environment. TARGET_ARCH + The name of the target hardware architecture for the compiled objects + created by this Environment. + This defaults to the value of HOST_ARCH, and the user can override it. + Currently only set for Win32. + + + Sets the target architecture for Visual Studio compiler (i.e. the arch of the binaries generated by the compiler). If not set, default to $HOST_ARCH, or, if that is unset, to the architecture of the @@ -7062,14 +7069,7 @@ and ia64 (Itanium). For example, if you want to compile 64-bit binaries, you would set TARGET_ARCH='x86_64' in your SCons environment. - - - The name of the target hardware architecture for the compiled objects - created by this Environment. - This defaults to the value of HOST_ARCH, and the user can override it. - Currently only set for Win32. - - + TARGET_OS -- cgit v0.12 From 8d742588df4f8d7a3a4c65e46cc616634e3151e6 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 9 Apr 2016 11:26:01 -0700 Subject: Updates to Changes, Release, Announce --- debian/changelog | 6 +++++ src/Announce.txt | 70 +++++++++++++++++++++++-------------------------- src/CHANGES.txt | 21 +++++++-------- src/RELEASE.txt | 80 +++++++++++++++++++++++++++++--------------------------- 4 files changed, 91 insertions(+), 86 deletions(-) diff --git a/debian/changelog b/debian/changelog index 9d60e3a..e3ab00c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +scons (2.5.0) unstable; urgency=low + + * Feature Release + + -- William Deegan Sat, 09 Apr 2016 08:56:00 -0700 + scons (2.4.1) unstable; urgency=low * Maintenance release. diff --git a/src/Announce.txt b/src/Announce.txt index 0b58958..266988f 100644 --- a/src/Announce.txt +++ b/src/Announce.txt @@ -18,42 +18,6 @@ So that everyone using SCons can help each other learn how to use it more effectively, please go to http://scons.org/lists.php#users to sign up for the scons-users mailing list. -==============IMPORTANT NOTICE FOR NEXT VERSION V2.5.0========== -PLEASE READ. CHANGES COMING IN NEXT MAJOR RELEASE V2.5.0 - -We're enhancing implicit language scanning functionality to improve -correctness. SCons now honors scanner keys for implicit dependencies -and correctly changes scanner type (if necessary) when traversing -implicit dependency trees. - -This enhancement resolves missing dependencies -with built-in scanners including SWIG (#2264) and QT: -* http://scons.tigris.org/issues/show_bug.cgi?id=2264 - -This enhancement broadens the horizon for handling heterogeneous -data flow environments (E.G. software builds): -* http://article.gmane.org/gmane.comp.programming.tools.scons.user/26596 -Notes: - -* SCons may find new (and correct) dependencies in cross-langauge contexts. -** Update may cause rebuilds, especially in heterogeneous data environments. -** Update may find previously missed dependencies errors (E.G. cycles). -*** Discovered in some QT test cases. -* SCons handles the SCANNERS variable differently. -** Previously, the Install builder would scan implicit dependencies for - a scanner found in SCANNERS (but not for built-in scanners), but now - the Install builder will not scan recursively regardless in order - to optimize Install behaviour and bring orthogonality to previous behaviour. -* SCons handles cache directories a bit differently/ -** Cache files are now stored in 256 subdirectories in the cache directory by - default (this stresses NFS less). Existing cache directories will remain as - current, but SCons will prompt you to run scons-configure-cache which will - allow you to migrate to the new layout, or confirm you want to use the - existing layout. - -+================================================================= - - RELEASE VERSION/DATE TO BE FILLED IN LATER Please consult the RELEASE.txt file for a summary of changes since the last @@ -61,9 +25,41 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER since last release. This announcement highlights only the important changes. - Please note the following important changes since release 2.4.0: + - Please note the following important changes since release 2.4.1: + We're enhancing implicit language scanning functionality to improve + correctness. SCons now honors scanner keys for implicit dependencies + and correctly changes scanner type (if necessary) when traversing + implicit dependency trees. + + This enhancement resolves missing dependencies + with built-in scanners including SWIG (#2264) and QT: + * http://scons.tigris.org/issues/show_bug.cgi?id=2264 + + - This enhancement broadens the horizon for handling heterogeneous + data flow environments (E.G. software builds): + - http://article.gmane.org/gmane.comp.programming.tools.scons.user/26596 + + - SCons may find new (and correct) dependencies in cross-langauge contexts. + - Update may cause rebuilds, especially in heterogeneous data environments. + - Update may find previously missed dependencies errors (E.G. cycles). + - Discovered in some QT test cases. + - SCons handles the SCANNERS variable differently. + - Previously, the Install builder would scan implicit dependencies for + a scanner found in SCANNERS (but not for built-in scanners), but now + the Install builder will not scan recursively regardless in order + to optimize Install behaviour and bring orthogonality to previous behaviour. + + - SCons handles cache directories a bit differently/ + - Cache files are now stored in 256 subdirectories in the cache directory by + default (this stresses NFS less). Existing cache directories will remain as + current, but SCons will prompt you to run scons-configure-cache which will + allow you to migrate to the new layout, or confirm you want to use the + existing layout. + - New external tool scons-configurecache which allows some configuration of how files in the cache are controlled. + + Please note the following important changes since release 2.4.0: - Fix to swig tool - pick-up 'swig', 'swig3.0' and 'swig2.0' (in order). - Fix to swig tool - respect env['SWIG'] provided by user. - Fix for Bug # 2791 - Setup.py fails unnecessarily under Jython. diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 3d2cf1c..7f8da6c 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -6,15 +6,6 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - From Tom Tanner: - - change cache to use 2 character subdirectories, rather than one character, - so as not to give huge directories for large caches, a situation which - causes issues for NFS. - For existing caches, you will need to run the scons-configure-cache.py - script to update them to the new format. You will get a warning every time - you build until you co this. - - Fix a bunch of unit tests on windows - From Dirk Baechle: - Removed a lot of compatibility methods and workarounds for Python versions < 2.7, in order to prepare the work @@ -49,12 +40,20 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Fix posix platform escaping logic to properly handle paths with parens in them "()". (Bug #2225) - From Jakub Pola: - Intel Compiler 2016 (Linux/Mac) update for tool directories. From Adarsh Sanjeev: - - Fix for issue #2494: Added string support for Chmod function. + - Fix for issue #2494: Added string support for Chmod function. + + From Tom Tanner: + - change cache to use 2 character subdirectories, rather than one character, + so as not to give huge directories for large caches, a situation which + causes issues for NFS. + For existing caches, you will need to run the scons-configure-cache.py + script to update them to the new format. You will get a warning every time + you build until you co this. + - Fix a bunch of unit tests on windows RELEASE 2.4.1 - Mon, 07 Nov 2015 10:37:21 -0700 diff --git a/src/RELEASE.txt b/src/RELEASE.txt index 3bff366..2c99cca 100644 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -5,68 +5,72 @@ XXX The primary purpose of this release ... XXX - A SCons "checkpoint release" is intended to provide early access to - new features so they can be tested in the field before being released - for adoption by other software distributions. - - Note that a checkpoint release is developed using the same test-driven - development methodology as all SCons releases. Existing SCons - functionality should all work as it does in previous releases (except - for any changes identified in the release notes) and early adopters - should be able to use a checkpoint release safely for production work - with existing SConscript files. If not, it represents not only a bug - in SCons but also a hole in the regression test suite, and we want to - hear about it. - - New features may be more lightly tested than in past releases, - especially as concerns their interaction with all of the other - functionality in SCons. We are especially interested in hearing bug - reports about new functionality. - - We do not recommend that downstream distributions (Debian, Fedora, - etc.) package a checkpoint release, mainly to avoid confusing the - "public" release numbering with the long checkpoint release names. - - Here is a summary of the changes since 1.3.0: + Here is a summary of the changes since 2.4.1: NEW FUNCTIONALITY - - - List new features (presumably why a checkpoint is being released) + - We're enhancing implicit language scanning functionality to improve + correctness. SCons now honors scanner keys for implicit dependencies + and correctly changes scanner type (if necessary) when traversing + implicit dependency trees. + + This enhancement resolves missing dependencies + with built-in scanners including SWIG (#2264) and QT: + * http://scons.tigris.org/issues/show_bug.cgi?id=2264 + + - This enhancement broadens the horizon for handling heterogeneous + data flow environments (E.G. software builds): + - http://article.gmane.org/gmane.comp.programming.tools.scons.user/26596 + + - SCons may find new (and correct) dependencies in cross-langauge contexts. + - Update may cause rebuilds, especially in heterogeneous data environments. + - Update may find previously missed dependencies errors (E.G. cycles). + - Discovered in some QT test cases. + - SCons handles the SCANNERS variable differently. + - Previously, the Install builder would scan implicit dependencies for + a scanner found in SCANNERS (but not for built-in scanners), but now + the Install builder will not scan recursively regardless in order + to optimize Install behaviour and bring orthogonality to previous behaviour. + + - New external tool scons-configurecache which allows some configuration of + how files in the cache are controlled. DEPRECATED FUNCTIONALITY - - List anything that's been deprecated since the last release + - None CHANGED/ENHANCED EXISTING FUNCTIONALITY - - List modifications to existing features, where the previous behavior - wouldn't actually be considered a bug + - SCons handles cache directories a bit differently/ + - Cache files are now stored in 256 subdirectories in the cache directory by + default (this stresses NFS less). Existing cache directories will remain as + current, but SCons will prompt you to run scons-configure-cache which will + allow you to migrate to the new layout, or confirm you want to use the + existing layout. FIXES - - List fixes of outright bugs + - This enhancement resolves missing dependencies with built-in scanners including + SWIG (#2264) and QT - See New Features above + * http://scons.tigris.org/issues/show_bug.cgi?id=2264 IMPROVEMENTS - - List improvements that wouldn't be visible to the user in the - documentation: performance improvements (describe the circumstances - under which they would be observed), or major code cleanups + - None PACKAGING - - List changes in the way SCons is packaged and/or released + - None DOCUMENTATION - - List any significant changes to the documentation (not individual - typo fixes, even if they're mentioned in src/CHANGES.txt to give - the contributor credit) + - None DEVELOPMENT - - List visible changes in the way SCons is developed + - None - Thanks to CURLY, LARRY, and MOE for their contributions to this release. + Thanks to Dirk Baechle, William Blevins, William Deegan, Jakub Pola, Adarsh Sanjeev, Tom Tanner + for their contributions to this release. Contributors are listed alphabetically by their last name. __COPYRIGHT__ -- cgit v0.12 From d0c6bc8828ecd1e24bed599123fc839cdf5b79dc Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 9 Apr 2016 12:28:47 -0700 Subject: changes for 2.5.0 release --- QMTest/TestSCons.py | 4 ++-- README.rst | 38 +++++++++++++++++++------------------- ReleaseConfig | 4 ++-- SConstruct | 6 +++--- doc/user/main.xml | 4 ++-- src/Announce.txt | 2 +- src/CHANGES.txt | 2 +- src/RELEASE.txt | 2 +- 8 files changed, 31 insertions(+), 31 deletions(-) diff --git a/QMTest/TestSCons.py b/QMTest/TestSCons.py index 43832e8..b71ee62 100644 --- a/QMTest/TestSCons.py +++ b/QMTest/TestSCons.py @@ -34,9 +34,9 @@ from TestCmd import PIPE # here provides some independent verification that what we packaged # conforms to what we expect. -default_version = '2.4.2.alpha.yyyymmdd' +default_version = '2.5.0' -python_version_unsupported = (2, 3, 0) +python_version_unsupported = (2, 6, 0) python_version_deprecated = (2, 7, 0) # In the checked-in source, the value of SConsVersion in the following diff --git a/README.rst b/README.rst index b4b24b7..ba1755f 100644 --- a/README.rst +++ b/README.rst @@ -168,7 +168,7 @@ Or on Windows:: By default, the above commands will do the following: -- Install the version-numbered "scons-2.4.1" and "sconsign-2.4.1" scripts in +- Install the version-numbered "scons-2.5.0" and "sconsign-2.5.0" scripts in the default system script directory (/usr/bin or C:\\Python\*\\Scripts, for example). This can be disabled by specifying the "--no-version-script" option on the command line. @@ -180,23 +180,23 @@ By default, the above commands will do the following: before making it the default on your system. On UNIX or Linux systems, you can have the "scons" and "sconsign" scripts be - hard links or symbolic links to the "scons-2.4.1" and "sconsign-2.4.1" + hard links or symbolic links to the "scons-2.5.0" and "sconsign-2.5.0" scripts by specifying the "--hardlink-scons" or "--symlink-scons" options on the command line. -- Install "scons-2.4.1.bat" and "scons.bat" wrapper scripts in the Python +- Install "scons-2.5.0.bat" and "scons.bat" wrapper scripts in the Python prefix directory on Windows (C:\\Python\*, for example). This can be disabled by specifying the "--no-install-bat" option on the command line. On UNIX or Linux systems, the "--install-bat" option may be specified to - have "scons-2.4.1.bat" and "scons.bat" files installed in the default system + have "scons-2.5.0.bat" and "scons.bat" files installed in the default system script directory, which is useful if you want to install SCons in a shared file system directory that can be used to execute SCons from both UNIX/Linux and Windows systems. - Install the SCons build engine (a Python module) in an appropriate - version-numbered SCons library directory (/usr/lib/scons-2.4.0 or - C:\\Python\*\\scons-2.4.0, for example). See below for more options related to + version-numbered SCons library directory (/usr/lib/scons-2.5.0 or + C:\\Python\*\\scons-2.5.0, for example). See below for more options related to installing the build engine library. - Install the troff-format man pages in an appropriate directory on UNIX or @@ -474,7 +474,7 @@ running all of "runtest.py -a". Building Packages ================= -We use SCons (version 2.4.1 or later) to build its own packages. If you +We use SCons (version 2.5.0 or later) to build its own packages. If you already have an appropriate version of SCons installed on your system, you can build everything by simply running it:: @@ -489,18 +489,18 @@ about `Executing SCons Without Installing`_):: Depending on the utilities installed on your system, any or all of the following packages will be built:: - build/dist/scons-2.4.1-1.noarch.rpm - build/dist/scons-2.4.1-1.src.rpm - build/dist/scons-2.4.1.linux-i686.tar.gz - build/dist/scons-2.4.2.alpha.yyyymmdd.tar.gz - build/dist/scons-2.4.2.alpha.yyyymmdd.win32.exe - build/dist/scons-2.4.2.alpha.yyyymmdd.zip - build/dist/scons-doc-2.4.2.alpha.yyyymmdd.tar.gz - build/dist/scons-local-2.4.2.alpha.yyyymmdd.tar.gz - build/dist/scons-local-2.4.2.alpha.yyyymmdd.zip - build/dist/scons-src-2.4.2.alpha.yyyymmdd.tar.gz - build/dist/scons-src-2.4.2.alpha.yyyymmdd.zip - build/dist/scons_2.4.1-1_all.deb + build/dist/scons-2.5.0-1.noarch.rpm + build/dist/scons-2.5.0-1.src.rpm + build/dist/scons-2.5.0.linux-i686.tar.gz + build/dist/scons-2.5.0.tar.gz + build/dist/scons-2.5.0.win32.exe + build/dist/scons-2.5.0.zip + build/dist/scons-doc-2.5.0.tar.gz + build/dist/scons-local-2.5.0.tar.gz + build/dist/scons-local-2.5.0.zip + build/dist/scons-src-2.5.0.tar.gz + build/dist/scons-src-2.5.0.zip + build/dist/scons_2.5.0-1_all.deb The SConstruct file is supposed to be smart enough to avoid trying to build packages for which you don't have the proper utilities installed. For diff --git a/ReleaseConfig b/ReleaseConfig index e1f462a..a4bfce6 100644 --- a/ReleaseConfig +++ b/ReleaseConfig @@ -32,7 +32,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" # 'final', the patchlevel is set to the release date. This value is # mandatory and must be present in this file. #version_tuple = (2, 2, 0, 'final', 0) -version_tuple = (2, 4, 2, 'alpha', 0) +version_tuple = (2, 5, 0) # Python versions prior to unsupported_python_version cause a fatal error # when that version is used. Python versions prior to deprecate_python_version @@ -51,7 +51,7 @@ deprecated_python_version = (2, 7, 0) #month_year = 'December 2012' # If copyright years is not given, the release year is used as the end. -copyright_years = '2001 - 2015' +copyright_years = '2001 - 2016' # Local Variables: # tab-width:4 diff --git a/SConstruct b/SConstruct index 6ad6dd9..33a8680 100644 --- a/SConstruct +++ b/SConstruct @@ -3,10 +3,10 @@ # # See the README.rst file for an overview of how SCons is built and tested. -copyright_years = '2001 - 2015' +copyright_years = '2001 - 2016' # This gets inserted into the man pages to reflect the month of release. -month_year = 'MONTH YEAR' +month_year = 'April 2016' # # __COPYRIGHT__ @@ -43,7 +43,7 @@ import tempfile import bootstrap project = 'scons' -default_version = '2.4.2.alpha.yyyymmdd' +default_version = '2.5.0' copyright = "Copyright (c) %s The SCons Foundation" % copyright_years platform = distutils.util.get_platform() diff --git a/doc/user/main.xml b/doc/user/main.xml index d2c4c18..451f87d 100644 --- a/doc/user/main.xml +++ b/doc/user/main.xml @@ -74,10 +74,10 @@ Steven Knight and the SCons Development Team - 2004 - 2015 + 2004 - 2016 - 2004 - 2015 + 2004 - 2016 The SCons Foundation diff --git a/src/Announce.txt b/src/Announce.txt index 266988f..b16fb3b 100644 --- a/src/Announce.txt +++ b/src/Announce.txt @@ -18,7 +18,7 @@ So that everyone using SCons can help each other learn how to use it more effectively, please go to http://scons.org/lists.php#users to sign up for the scons-users mailing list. -RELEASE VERSION/DATE TO BE FILLED IN LATER +RELEASE 2.5.0 - Mon, 09 Apr 2016 11:27:42 -0700 Please consult the RELEASE.txt file for a summary of changes since the last release and consult the CHANGES.txt file for complete a list of changes diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 7f8da6c..b5a1fb6 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -4,7 +4,7 @@ Change Log -RELEASE VERSION/DATE TO BE FILLED IN LATER +RELEASE 2.5.0 - Mon, 09 Apr 2016 11:27:42 -0700 From Dirk Baechle: - Removed a lot of compatibility methods and workarounds diff --git a/src/RELEASE.txt b/src/RELEASE.txt index 2c99cca..32d5a08 100644 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -1,4 +1,4 @@ - A new SCons checkpoint release, 2.4.3.alpha.yyyymmdd, is now available + A new SCons checkpoint release, 2.5.0, is now available on the SCons download page: http://www.scons.org/download.php -- cgit v0.12 From 4040b4fa98ddcfbdfc718b0bd7e802afe61bc7b6 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 9 Apr 2016 15:56:56 -0700 Subject: updated copyright on manpage. TODO: fix update-release-files.sh to do this automatically --- doc/man/scons.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 4db5abb..41ef607 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -54,10 +54,10 @@ Steven Knight and the SCons Development Team - 2004 - 2015 + 2004 - 2016 - 2004 - 2015 + 2004 - 2016 The SCons Foundation -- cgit v0.12 From 3e0a831c7fcd60384266e14641a3a15f2cba1ced Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 9 Apr 2016 19:04:42 -0400 Subject: reset files to development mode --- ReleaseConfig | 2 +- src/Announce.txt | 2 +- src/CHANGES.txt | 7 +++++ src/RELEASE.txt | 82 +++++++++++++++++++++++++++----------------------------- 4 files changed, 48 insertions(+), 45 deletions(-) diff --git a/ReleaseConfig b/ReleaseConfig index a4bfce6..7a68f89 100644 --- a/ReleaseConfig +++ b/ReleaseConfig @@ -32,7 +32,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" # 'final', the patchlevel is set to the release date. This value is # mandatory and must be present in this file. #version_tuple = (2, 2, 0, 'final', 0) -version_tuple = (2, 5, 0) +version_tuple = (2, 6, 0, 'alpha', 0) # Python versions prior to unsupported_python_version cause a fatal error # when that version is used. Python versions prior to deprecate_python_version diff --git a/src/Announce.txt b/src/Announce.txt index b16fb3b..266988f 100644 --- a/src/Announce.txt +++ b/src/Announce.txt @@ -18,7 +18,7 @@ So that everyone using SCons can help each other learn how to use it more effectively, please go to http://scons.org/lists.php#users to sign up for the scons-users mailing list. -RELEASE 2.5.0 - Mon, 09 Apr 2016 11:27:42 -0700 +RELEASE VERSION/DATE TO BE FILLED IN LATER Please consult the RELEASE.txt file for a summary of changes since the last release and consult the CHANGES.txt file for complete a list of changes diff --git a/src/CHANGES.txt b/src/CHANGES.txt index b5a1fb6..b6973b7 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -4,6 +4,13 @@ Change Log +RELEASE VERSION/DATE TO BE FILLED IN LATER + + From John Doe: + + - Whatever John Doe did. + + RELEASE 2.5.0 - Mon, 09 Apr 2016 11:27:42 -0700 From Dirk Baechle: diff --git a/src/RELEASE.txt b/src/RELEASE.txt index 32d5a08..ac2b95a 100644 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -1,76 +1,72 @@ - A new SCons checkpoint release, 2.5.0, is now available + A new SCons checkpoint release, 2.6.0.alpha.yyyymmdd, is now available on the SCons download page: http://www.scons.org/download.php XXX The primary purpose of this release ... XXX - Here is a summary of the changes since 2.4.1: + A SCons "checkpoint release" is intended to provide early access to + new features so they can be tested in the field before being released + for adoption by other software distributions. + + Note that a checkpoint release is developed using the same test-driven + development methodology as all SCons releases. Existing SCons + functionality should all work as it does in previous releases (except + for any changes identified in the release notes) and early adopters + should be able to use a checkpoint release safely for production work + with existing SConscript files. If not, it represents not only a bug + in SCons but also a hole in the regression test suite, and we want to + hear about it. + + New features may be more lightly tested than in past releases, + especially as concerns their interaction with all of the other + functionality in SCons. We are especially interested in hearing bug + reports about new functionality. + + We do not recommend that downstream distributions (Debian, Fedora, + etc.) package a checkpoint release, mainly to avoid confusing the + "public" release numbering with the long checkpoint release names. + + Here is a summary of the changes since 1.3.0: NEW FUNCTIONALITY - - We're enhancing implicit language scanning functionality to improve - correctness. SCons now honors scanner keys for implicit dependencies - and correctly changes scanner type (if necessary) when traversing - implicit dependency trees. - - This enhancement resolves missing dependencies - with built-in scanners including SWIG (#2264) and QT: - * http://scons.tigris.org/issues/show_bug.cgi?id=2264 - - - This enhancement broadens the horizon for handling heterogeneous - data flow environments (E.G. software builds): - - http://article.gmane.org/gmane.comp.programming.tools.scons.user/26596 - - - SCons may find new (and correct) dependencies in cross-langauge contexts. - - Update may cause rebuilds, especially in heterogeneous data environments. - - Update may find previously missed dependencies errors (E.G. cycles). - - Discovered in some QT test cases. - - SCons handles the SCANNERS variable differently. - - Previously, the Install builder would scan implicit dependencies for - a scanner found in SCANNERS (but not for built-in scanners), but now - the Install builder will not scan recursively regardless in order - to optimize Install behaviour and bring orthogonality to previous behaviour. - - - New external tool scons-configurecache which allows some configuration of - how files in the cache are controlled. + + - List new features (presumably why a checkpoint is being released) DEPRECATED FUNCTIONALITY - - None + - List anything that's been deprecated since the last release CHANGED/ENHANCED EXISTING FUNCTIONALITY - - SCons handles cache directories a bit differently/ - - Cache files are now stored in 256 subdirectories in the cache directory by - default (this stresses NFS less). Existing cache directories will remain as - current, but SCons will prompt you to run scons-configure-cache which will - allow you to migrate to the new layout, or confirm you want to use the - existing layout. + - List modifications to existing features, where the previous behavior + wouldn't actually be considered a bug FIXES - - This enhancement resolves missing dependencies with built-in scanners including - SWIG (#2264) and QT - See New Features above - * http://scons.tigris.org/issues/show_bug.cgi?id=2264 + - List fixes of outright bugs IMPROVEMENTS - - None + - List improvements that wouldn't be visible to the user in the + documentation: performance improvements (describe the circumstances + under which they would be observed), or major code cleanups PACKAGING - - None + - List changes in the way SCons is packaged and/or released DOCUMENTATION - - None + - List any significant changes to the documentation (not individual + typo fixes, even if they're mentioned in src/CHANGES.txt to give + the contributor credit) DEVELOPMENT - - None + - List visible changes in the way SCons is developed - Thanks to Dirk Baechle, William Blevins, William Deegan, Jakub Pola, Adarsh Sanjeev, Tom Tanner - for their contributions to this release. + Thanks to CURLY, LARRY, and MOE for their contributions to this release. Contributors are listed alphabetically by their last name. __COPYRIGHT__ -- cgit v0.12 From c591da06c1a18873d09323d6700d1469120ad27d Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 8 May 2016 17:21:42 -0700 Subject: Guard checking for subprocess.mswindows by checking if on win32 platform --- QMTest/TestCmd.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/QMTest/TestCmd.py b/QMTest/TestCmd.py index f8c4e69..8cb6fb9 100644 --- a/QMTest/TestCmd.py +++ b/QMTest/TestCmd.py @@ -658,7 +658,7 @@ except AttributeError: PIPE = subprocess.PIPE -if subprocess.mswindows: +if sys.platform == 'win32' and subprocess.mswindows: try: from win32file import ReadFile, WriteFile from win32pipe import PeekNamedPipe @@ -720,7 +720,7 @@ class Popen(subprocess.Popen): getattr(self, which).close() setattr(self, which, None) - if subprocess.mswindows: + if sys.platform == 'win32' and subprocess.mswindows: def send(self, input): if not self.stdin: return None -- cgit v0.12 From 36b38cccb12248c106575753a8f2807bfd88c2fa Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 8 May 2016 20:58:39 -0700 Subject: py2/3 compatibility changes. --- src/engine/SCons/Util.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 5b11f83..a5a92fa 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -32,13 +32,27 @@ import copy import re import types -from UserDict import UserDict -from UserList import UserList -from UserString import UserString +try: + from UserDict import UserDict +except ImportError as e: + from collections import UserDict + +try: + from UserList import UserList +except ImportError as e: + from collections import UserList + +try: + from UserString import UserString +except ImportError as e: + from collections import UserString # Don't "from types import ..." these because we need to get at the # types module later to look for UnicodeType. -InstanceType = types.InstanceType + +# Below not used? +# InstanceType = types.InstanceType + MethodType = types.MethodType FunctionType = types.FunctionType try: unicode -- cgit v0.12 From 70f4e3f26156b33f465fa12ec87b50c5b8f784e4 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 8 May 2016 21:23:37 -0700 Subject: Add from future import print_function to fix broken tests under python2.7 --- src/engine/SCons/Script/Main.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index 997d701..c0b22a7 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -10,9 +10,13 @@ some other module. If it's specific to the "scons" script invocation, it goes here. """ +from __future__ import print_function + + unsupported_python_version = (2, 6, 0) deprecated_python_version = (2, 7, 0) + # __COPYRIGHT__ # # Permission is hereby granted, free of charge, to any person obtaining @@ -36,6 +40,7 @@ deprecated_python_version = (2, 7, 0) __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import SCons.compat import os @@ -360,7 +365,7 @@ class CleanTask(SCons.Taskmaster.AlwaysTask): # the file not existing. In either case, print a # message and keep going to try to remove as many # targets as possible. - print(("scons: Could not remove '{}':".format(str(t)), e.strerror)) + print("scons: Could not remove '{0}'".format(str(t)), e.strerror) else: if removed: display("Removed " + str(t)) -- cgit v0.12 From 1268203d907a4f653abd2f40299490fca9fc5874 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 9 May 2016 15:00:29 -0700 Subject: Fix missing right parent in print () function in generated SConstruct. --- test/Deprecated/Options/EnumOption.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/Deprecated/Options/EnumOption.py b/test/Deprecated/Options/EnumOption.py index 2b3ed47..02afef1 100644 --- a/test/Deprecated/Options/EnumOption.py +++ b/test/Deprecated/Options/EnumOption.py @@ -43,6 +43,7 @@ def check(expect): test.write(SConstruct_path, """\ + from SCons.Options.EnumOption import EnumOption EO = EnumOption @@ -67,7 +68,7 @@ env = Environment(options=opts) Help(opts.GenerateHelpText(env)) print(env['debug']) -print(env['guilib'] +print(env['guilib']) print(env['some']) Default(env.Alias('dummy', None)) -- cgit v0.12 From f4627c480788454ff3e8ab9f2c75966ed999d9cd Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 9 May 2016 15:26:03 -0700 Subject: Fixed usage of linknames which needed to be defined outside of the two methods which share it's value and wasn't. Curious this only fails in python2.7 when __future__ is imported.. --- src/engine/SCons/Tool/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index 9606ac1..26caf2f 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -244,6 +244,9 @@ def createStaticLibBuilder(env): return static_lib +# used by the following two methods +linknames = [] + def _call_linker_cb(env, callback, args, result = None): """Returns the result of env['LINKCALLBACKS'][callback](*args) if env['LINKCALLBACKS'] is a dictionary and env['LINKCALLBACKS'][callback] @@ -268,7 +271,7 @@ def _call_linker_cb(env, callback, args, result = None): if Verbose: print('_call_linker_cb: env["LINKCALLBACKS"][{:r}] found'.format(callback)) print('_call_linker_cb: env["LINKCALLBACKS"][{:r}]={:r}'.format(callback, cbfun)) - if(callable(cbfun)): + if (callable(cbfun)): if Verbose: print("VersionShLibLinkNames: linkname ",linkname, ", target ",libname) linknames.append(linkname) -- cgit v0.12 From b93369681ca5d4fc9a52fecd4d3afafc2dfa7742 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 9 May 2016 15:32:04 -0700 Subject: Fixed embedded SConscript/SConstruct's usage of print. Had no parens. --- test/SConscript/Return.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/test/SConscript/Return.py b/test/SConscript/Return.py index a810c7c..997de9d 100644 --- a/test/SConscript/Return.py +++ b/test/SConscript/Return.py @@ -39,50 +39,50 @@ x = SConscript('SConscript2') y, z = SConscript('SConscript3') a4, b4 = SConscript('SConscript4') foo, bar = SConscript('SConscript5') -print "x =", x -print "y =", y -print "z =", z -print "a4 =", a4 -print "b4 =", b4 -print "foo =", foo -print "bar =", bar +print ("x =", x) +print ("y =", y) +print ("z =", z) +print ("a4 =", a4) +print ("b4 =", b4) +print ("foo =", foo) +print ("bar =", bar) """) test.write('SConscript1', """\ -print "line 1" +print ("line 1") Return() -print "line 2" +print ("line 2") """) test.write('SConscript2', """\ -print "line 3" +print ("line 3") x = 7 Return('x') -print "line 4" +print ("line 4") """) test.write('SConscript3', """\ -print "line 5" +print ("line 5") y = 8 z = 9 Return('y z') -print "line 6" +print ("line 6") """) test.write('SConscript4', """\ a4 = 'aaa' b4 = 'bbb' -print "line 7" +print ("line 7") Return('a4', 'b4', stop=False) b4 = 'b-after' -print "line 8" +print ("line 8") """) test.write('SConscript5', """\ foo = 'foo' bar = 'bar' Return(["foo", "bar"]) -print "line 9" +print ("line 9") """) expect = """\ -- cgit v0.12 From 144d9dd9bd444d5cfab2b1094775d59ccc758882 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 9 May 2016 15:33:18 -0700 Subject: Fixed embedded SConscript/SConstruct's usage of print. Had no parens. --- test/SConscript/SConscript.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/SConscript/SConscript.py b/test/SConscript/SConscript.py index c8453a7..8bc9127 100644 --- a/test/SConscript/SConscript.py +++ b/test/SConscript/SConscript.py @@ -37,7 +37,7 @@ import foo assert foo.foo == 4 -print "SConstruct", os.getcwd() +print ("SConstruct", os.getcwd()) SConscript('SConscript') x1 = "SConstruct x1" @@ -89,7 +89,7 @@ test.write('SConscript', """\ assert "os" not in globals() import os -print "SConscript " + os.getcwd() +print ("SConscript " + os.getcwd()) """) test.write('SConscript1', """ -- cgit v0.12 From 9cc6b7b615b8b22a2a747fbb2d404d87b4091358 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 9 May 2016 15:36:18 -0700 Subject: Fixed embedded SConscript/SConstruct's usage of print. Had no parens. --- test/SConscript/env.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/SConscript/env.py b/test/SConscript/env.py index 42963ff..a16866c 100644 --- a/test/SConscript/env.py +++ b/test/SConscript/env.py @@ -36,7 +36,7 @@ test.subdir('sub1', 'sub2') test.write("SConstruct", """\ env = Environment(SUB1='sub1', SUB2='sub2') -print "SConstruct" +print("SConstruct") x = 'xxx' y = 'yyy' env.Export(["x", "y"]) @@ -49,15 +49,15 @@ env.SConscript(['s3', 's4']) test.write(['sub1', 'SConscript'], """\ env = Environment() env.Import("x") -print "sub1/SConscript" -print "x =", x +print("sub1/SConscript") +print("x =", x) """) test.write(['sub2', 'SConscript'], """\ env = Environment() env.Import("y") -print "sub2/SConscript" -print "y =", y +print("sub2/SConscript") +print("y =", y) """) test.write('s1', "\n") -- cgit v0.12 From 9e56ee19d57f6ecb32d6cb5cd36809fd02cd34c1 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 9 May 2016 15:37:11 -0700 Subject: Fix typo in comment. --- test/SConscript/SConscript.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/SConscript/SConscript.py b/test/SConscript/SConscript.py index 8bc9127..d1e09ce 100644 --- a/test/SConscript/SConscript.py +++ b/test/SConscript/SConscript.py @@ -85,7 +85,7 @@ SConscript('SConscript7') test.write('SConscript', """\ -# os should not be automajically imported: +# os should not be automatically imported: assert "os" not in globals() import os -- cgit v0.12 From d3c4aa79b66572dacc4be76fc7c54354c726ae3b Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 9 May 2016 15:38:08 -0700 Subject: Fixed print()'s --- test/SConscript/white-space.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/SConscript/white-space.py b/test/SConscript/white-space.py index 06acea8..cc8f00e 100644 --- a/test/SConscript/white-space.py +++ b/test/SConscript/white-space.py @@ -38,7 +38,7 @@ SConscript('white space/SConscript') """) test.write(['white space', 'SConscript'], """\ -print "`white space/SConscript'" +print("`white space/SConscript'") """) expect = test.wrap_stdout(read_str = "`white space/SConscript'\n", -- cgit v0.12 From da6d4138160e27aa34f80b6f48ba9e331a69aa77 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 9 May 2016 15:39:27 -0700 Subject: Fixed print()'s --- test/SConstruct.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/SConstruct.py b/test/SConstruct.py index 15e1c1b..9b2807f 100644 --- a/test/SConstruct.py +++ b/test/SConstruct.py @@ -41,7 +41,7 @@ wpath = test.workpath() test.write('sconstruct', """ import os -print "sconstruct", os.getcwd() +print("sconstruct", os.getcwd()) """) test.run(arguments = ".", @@ -51,7 +51,7 @@ test.run(arguments = ".", test.write('Sconstruct', """ import os -print "Sconstruct", os.getcwd() +print("Sconstruct", os.getcwd()) """) test.run(arguments = ".", @@ -60,7 +60,7 @@ test.run(arguments = ".", test.write('SConstruct', """ import os -print "SConstruct", os.getcwd() +print("SConstruct", os.getcwd()) """) test.run(arguments = ".", -- cgit v0.12 From 76aae9b8cb7bbd290fcd82fd6dbaf0c3f51c9bc4 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 9 May 2016 15:41:12 -0700 Subject: Fixed print()'s --- test/SWIG/SWIG.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/SWIG/SWIG.py b/test/SWIG/SWIG.py index d53fa49..38bdc97 100644 --- a/test/SWIG/SWIG.py +++ b/test/SWIG/SWIG.py @@ -48,14 +48,14 @@ for opt, arg in opts: if opt == '-c': pass elif opt == '-o': out = arg elif opt == '-v' and arg == 'ersion': - print "" - print "SWIG Version 0.1.2" - print "" - print "Compiled with g++ [x86_64-pc-linux-gnu]" - print "" - print "Configured options: +pcre" - print "" - print "Please see http://www.swig.org for reporting bugs and further information" + print("") + print("SWIG Version 0.1.2") + print("") + print("Compiled with g++ [x86_64-pc-linux-gnu]") + print("") + print("Configured options: +pcre") + print("") + print("Please see http://www.swig.org for reporting bugs and further information") sys.exit(0) infile = open(args[0], 'rb') outfile = open(out, 'wb') @@ -68,7 +68,7 @@ sys.exit(0) test.write('SConstruct', """ env = Environment(tools=['default', 'swig'], SWIG = [r'%(python)s', 'myswig.py']) -print env.subst("Using SWIG $SWIGVERSION") +print(env.subst("Using SWIG $SWIGVERSION")) env.Program(target = 'test1', source = 'test1.i') env.CFile(target = 'test2', source = 'test2.i') env.Clone(SWIGFLAGS = '-c++').Program(target = 'test3', source = 'test3.i') -- cgit v0.12 From 2efa4c01f3d8010adf98ab2ead5c5a4534544766 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 9 May 2016 15:42:14 -0700 Subject: Fixed print()'s --- test/Scanner/CrossLanguageNoExtension.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Scanner/CrossLanguageNoExtension.py b/test/Scanner/CrossLanguageNoExtension.py index 5bf205f..0016ca5 100644 --- a/test/Scanner/CrossLanguageNoExtension.py +++ b/test/Scanner/CrossLanguageNoExtension.py @@ -45,11 +45,11 @@ def scan(node, env, scanpaths, arg): return includes def kfile_scan(node, env, scanpaths, arg): - print 'kscan: ' + str(node) + print('kscan: ' + str(node)) return scan(node, env, scanpaths, arg) def k2file_scan(node, env, scanpaths, arg): - print 'k2scan: ' + str(node) + print('k2scan: ' + str(node)) return scan(node, env, scanpaths, arg) kscan = Scanner(name = 'kfile', -- cgit v0.12 From ac02a52b31e3e12271a9929e45fbecc10c4113c8 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 9 May 2016 15:43:40 -0700 Subject: Fixed print()'s --- test/Scanner/empty-implicit.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Scanner/empty-implicit.py b/test/Scanner/empty-implicit.py index 0323240..45fe952 100644 --- a/test/Scanner/empty-implicit.py +++ b/test/Scanner/empty-implicit.py @@ -37,7 +37,7 @@ test.write('SConstruct', r""" import os.path def scan(node, env, envkey, arg): - print 'XScanner: node =', os.path.split(str(node))[1] + print('XScanner: node =', os.path.split(str(node))[1]) return [] def exists_check(node, env): @@ -52,7 +52,7 @@ XScanner = Scanner(name = 'XScanner', def echo(env, target, source): t = os.path.split(str(target[0]))[1] s = os.path.split(str(source[0]))[1] - print 'create %s from %s' % (t, s) + print('create %s from %s' % (t, s)) open(t, 'wb').write(open(s, 'rb').read()) Echo = Builder(action = Action(echo, None), -- cgit v0.12 From dea50d86773e279f7b0f13e22285bb0a10eb5c48 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 9 May 2016 15:44:39 -0700 Subject: Fixed print()'s --- test/Scanner/scan-once.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Scanner/scan-once.py b/test/Scanner/scan-once.py index d68f918..eac1f49 100644 --- a/test/Scanner/scan-once.py +++ b/test/Scanner/scan-once.py @@ -36,7 +36,7 @@ test.write('SConstruct', r""" import os.path def scan(node, env, envkey, arg): - print 'XScanner: node =', os.path.split(str(node))[1] + print('XScanner: node =', os.path.split(str(node))[1]) return [] def exists_check(node, env): @@ -51,7 +51,7 @@ XScanner = Scanner(name = 'XScanner', def echo(env, target, source): t = os.path.split(str(target[0]))[1] s = os.path.split(str(source[0]))[1] - print 'create %s from %s' % (t, s) + print('create %s from %s' % (t, s)) Echo = Builder(action = Action(echo, None), src_suffix = '.x', -- cgit v0.12 From 8db3ac9ab52220be897c562c36599897e43af7ee Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 9 May 2016 15:46:20 -0700 Subject: Fixed print()'s --- test/Subst/AllowSubstExceptions.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/Subst/AllowSubstExceptions.py b/test/Subst/AllowSubstExceptions.py index 286f189..7f2a9aa 100644 --- a/test/Subst/AllowSubstExceptions.py +++ b/test/Subst/AllowSubstExceptions.py @@ -52,37 +52,37 @@ assert env.subst_list('${INDEX[999]}') == [[]] AllowSubstExceptions() try: env.subst('$NAME') -except SCons.Errors.UserError, e: print e +except SCons.Errors.UserError, e: print(e) else: raise Exception("did not catch expected SCons.Errors.UserError") try: env.subst('${NAME}') -except SCons.Errors.UserError, e: print e +except SCons.Errors.UserError, e: print(e) else: raise Exception("did not catch expected SCons.Errors.UserError") try: env.subst('${INDEX[999]}') -except SCons.Errors.UserError, e: print e +except SCons.Errors.UserError, e: print(e) else: raise Exception("did not catch expected SCons.Errors.UserError") try: env.subst_list('$NAME') -except SCons.Errors.UserError, e: print e +except SCons.Errors.UserError, e: print(e) else: raise Exception("did not catch expected SCons.Errors.UserError") try: env.subst_list('${NAME}') -except SCons.Errors.UserError, e: print e +except SCons.Errors.UserError, e: print(e) else: raise Exception("did not catch expected SCons.Errors.UserError") try: env.subst_list('${INDEX[999]}') -except SCons.Errors.UserError, e: print e +except SCons.Errors.UserError, e: print(e) else: raise Exception("did not catch expected SCons.Errors.UserError") try: env.subst('${1/0}') -except SCons.Errors.UserError, e: print e +except SCons.Errors.UserError, e: print(e) else: raise Exception("did not catch expected SCons.Errors.UserError") try: env.subst_list('${1/0}') -except SCons.Errors.UserError, e: print e +except SCons.Errors.UserError, e: print(e) else: raise Exception("did not catch expected SCons.Errors.UserError") AllowSubstExceptions(ZeroDivisionError) -- cgit v0.12 From b70ce9026da43a0d659fbc60588e2df471cbba77 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 9 May 2016 15:49:39 -0700 Subject: Fixed print()'s. Still some remaining issues. Check later. --- test/Variables/ListVariable.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/Variables/ListVariable.py b/test/Variables/ListVariable.py index e5be625..c6972c1 100644 --- a/test/Variables/ListVariable.py +++ b/test/Variables/ListVariable.py @@ -66,15 +66,15 @@ env = Environment(variables=opts) opts.Save(optsfile, env) Help(opts.GenerateHelpText(env)) -print env['shared'] -if 'ical' in env['shared']: print '1' -else: print '0' +print(env['shared']) +if 'ical' in env['shared']: print('1') +else: print('0') for x in env['shared']: - print x, -print -print env.subst('$shared') + print (x,) +print() +print(env.subst('$shared')) # Test subst_path() because it's used in $CPPDEFINES expansions. -print env.subst_path('$shared') +print(env.subst_path('$shared')) Default(env.Alias('dummy', None)) """) @@ -162,7 +162,7 @@ opts.AddVariables( env = Environment(variables=opts) Help(opts.GenerateHelpText(env)) -print env['gpib'] +print(env['gpib']) Default(env.Alias('dummy', None)) """) -- cgit v0.12 From ef93655b57fcd93cfda0e21439f5fc60df161238 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 9 May 2016 15:51:31 -0700 Subject: Fixed print()'s. Still some remaining issues. Check later. --- test/toolpath/basic.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/toolpath/basic.py b/test/toolpath/basic.py index eedd06e..509d4cb 100644 --- a/test/toolpath/basic.py +++ b/test/toolpath/basic.py @@ -40,12 +40,12 @@ print("env1['TOOL_BAR'] =", env1.get('TOOL_BAR')) # pick a built-in tool with pretty simple behavior env2 = Environment(tools=['SCCS']) -print("env2['SCCS'] =", env2.get('SCCS') +print("env2['SCCS'] =", env2.get('SCCS')) print("env2['TOOL_SCCS1'] =", env2.get('TOOL_SCCS1')) print("env2['TOOL_SCCS2'] =", env2.get('TOOL_SCCS2')) env3 = Environment(tools=['SCCS'], toolpath=['.']) -print("env3['SCCS'] =", env3.get('SCCS') +print("env3['SCCS'] =", env3.get('SCCS')) print("env3['TOOL_SCCS1'] =", env3.get('TOOL_SCCS1')) print("env3['TOOL_SCCS2'] =", env3.get('TOOL_SCCS2')) -- cgit v0.12 From 67769cb3a7673604be8e1ddcc8af2f3be552d905 Mon Sep 17 00:00:00 2001 From: Pawel Tomulik Date: Wed, 11 May 2016 02:17:30 +0200 Subject: fixed issue with _xxxxxxVERSIONFLAGS --- src/engine/SCons/Defaults.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/SCons/Defaults.py b/src/engine/SCons/Defaults.py index 6344975..37cbc99 100644 --- a/src/engine/SCons/Defaults.py +++ b/src/engine/SCons/Defaults.py @@ -540,10 +540,10 @@ class Variable_Method_Caller(object): frame = frame.f_back return None -# if env[version_var] id defined, returns env[flags_var], otherwise returns None +# if $version_var is not empty, returns env[flags_var], otherwise returns None def __libversionflags(env, version_var, flags_var): try: - if env[version_var]: + if env.subst('$'+version_var): return env[flags_var] except KeyError: pass -- cgit v0.12 From 170105963ce92f49eeb7441739b921198dec0505 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 12 May 2016 07:48:46 -0700 Subject: copy src/engine/SCons/Tool/__init__.py as the merge had issues at some point in the past the the versioned shared library logic got mangled. Then 2to3 that file. Seems to e working now --- src/engine/SCons/Tool/__init__.py | 175 ++++++++++---------------------------- 1 file changed, 43 insertions(+), 132 deletions(-) diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index 26caf2f..4cd242b 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -34,7 +34,6 @@ tool definition. # 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 print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -53,6 +52,7 @@ import SCons.Scanner.D import SCons.Scanner.LaTeX import SCons.Scanner.Prog import SCons.Scanner.SWIG +import collections DefaultToolpath=[] @@ -122,7 +122,7 @@ class Tool(object): if file: file.close() except ImportError as e: - if not str(e).startswith ("No module"): + if str(e)!="No module named %s"%self.name: raise SCons.Errors.EnvironmentError(e) try: import zipimport @@ -152,7 +152,7 @@ class Tool(object): file.close() return module except ImportError as e: - if not str(e).startswith("No module"): + if str(e)!="No module named %s"%self.name: raise SCons.Errors.EnvironmentError(e) try: import zipimport @@ -244,9 +244,6 @@ def createStaticLibBuilder(env): return static_lib -# used by the following two methods -linknames = [] - def _call_linker_cb(env, callback, args, result = None): """Returns the result of env['LINKCALLBACKS'][callback](*args) if env['LINKCALLBACKS'] is a dictionary and env['LINKCALLBACKS'][callback] @@ -258,109 +255,22 @@ def _call_linker_cb(env, callback, args, result = None): Verbose = False if Verbose: - print('_call_linker_cb: args={:r}'.format(args)) - print('_call_linker_cb: callback={:r}'.format(callback)) - + print('_call_linker_cb: args=%r' % args) + print('_call_linker_cb: callback=%r' % callback) + try: cbfun = env['LINKCALLBACKS'][callback] except (KeyError, TypeError): if Verbose: - print('_call_linker_cb: env["LINKCALLBACKS"][{:r}] not found or can not be used'.format(callback)) + print('_call_linker_cb: env["LINKCALLBACKS"][%r] not found or can not be used' % callback) pass else: if Verbose: - print('_call_linker_cb: env["LINKCALLBACKS"][{:r}] found'.format(callback)) - print('_call_linker_cb: env["LINKCALLBACKS"][{:r}]={:r}'.format(callback, cbfun)) - if (callable(cbfun)): - if Verbose: - print("VersionShLibLinkNames: linkname ",linkname, ", target ",libname) - linknames.append(linkname) - # note: no Windows case here (win32 or cygwin); - # MSVC doesn't support this type of versioned shared libs. - # (could probably do something for MinGW though) - return linknames - -def VersionedSharedLibrary(target = None, source= None, env=None): - """Build a shared library. If the environment has SHLIBVERSION -defined make a versioned shared library and create the appropriate -symlinks for the platform we are on""" - Verbose = False - try: - version = env.subst('$SHLIBVERSION') - except KeyError: - version = None - - # libname includes the version number if one was given - libname = target[0].name - platform = env.subst('$PLATFORM') - shlib_suffix = env.subst('$SHLIBSUFFIX') - shlink_flags = SCons.Util.CLVar(env.subst('$SHLINKFLAGS')) - if Verbose: - print("VersionShLib: libname = ",libname) - print("VersionShLib: platform = ",platform) - print("VersionShLib: shlib_suffix = ",shlib_suffix) - print("VersionShLib: target = ",str(target[0])) - - if version: - # set the shared library link flags - if platform == 'posix': - shlink_flags += [ '-Wl,-Bsymbolic' ] - # OpenBSD doesn't usually use SONAME for libraries - if not sys.platform.startswith('openbsd'): - # continue setup of shlink flags for all other POSIX systems - suffix_re = re.escape(shlib_suffix + '.' + version) - (major, age, revision) = version.split(".") - # soname will have only the major version number in it - soname = re.sub(suffix_re, shlib_suffix, libname) + '.' + major - shlink_flags += [ '-Wl,-soname=%s' % soname ] - if Verbose: - print(" soname ",soname,", shlink_flags ",shlink_flags) - elif platform == 'cygwin': - shlink_flags += [ '-Wl,-Bsymbolic', - '-Wl,--out-implib,${TARGET.base}.a' ] - elif platform == 'darwin': - shlink_flags += [ '-current_version', '%s' % version, - '-compatibility_version', '%s' % version, - '-undefined', 'dynamic_lookup' ] - if Verbose: - print("VersionShLib: shlink_flags = ",shlink_flags) - envlink = env.Clone() - envlink['SHLINKFLAGS'] = shlink_flags - else: - envlink = env - - result = SCons.Defaults.ShLinkAction(target, source, envlink) - - if version: - # here we need the full pathname so the links end up in the right directory - libname = target[0].path - linknames = VersionShLibLinkNames(version, libname, env) - if Verbose: - print("VerShLib: linknames ",linknames) - # Here we just need the file name w/o path as the target of the link - lib_ver = target[0].name - # make symlink of adjacent names in linknames - for count in range(len(linknames)): - linkname = linknames[count] - if count > 0: - try: - os.remove(lastlinkname) - except: - pass - os.symlink(os.path.basename(linkname),lastlinkname) - if Verbose: - print("VerShLib: made sym link of %s -> %s" % (lastlinkname,linkname)) - lastlinkname = linkname - # finish chain of sym links with link to the actual library - if len(linknames)>0: - try: - os.remove(lastlinkname) - except: - pass - os.symlink(lib_ver,lastlinkname) + print('_call_linker_cb: env["LINKCALLBACKS"][%r] found' % callback) + print('_call_linker_cb: env["LINKCALLBACKS"][%r]=%r' % (callback, cbfun)) + if(isinstance(cbfun, collections.Callable)): if Verbose: - print("VerShLib: made sym link of %s -> %s" % (linkname, lib_ver)) - print('_call_linker_cb: env["LINKCALLBACKS"][{:r}] is callable'.format(callback)) + print('_call_linker_cb: env["LINKCALLBACKS"][%r] is callable' % callback) result = cbfun(env, *args) return result @@ -479,7 +389,7 @@ class _LibInfoGeneratorBase(object): def generate_versioned_lib_info(self, env, args, result = None, **kw): callback = self.get_versioned_lib_info_generator(**kw) - return _call_linker_cb(env, callback, args, result) + return _call_linker_cb(env, callback, args, result) class _LibPrefixGenerator(_LibInfoGeneratorBase): """Library prefix generator, used as target_prefix in SharedLibrary and @@ -498,17 +408,17 @@ class _LibPrefixGenerator(_LibInfoGeneratorBase): prefix = self.get_lib_prefix(env,**kw2) if Verbose: - print("_LibPrefixGenerator: input prefix={:r}".format(prefix)) + print("_LibPrefixGenerator: input prefix=%r" % prefix) version = self.get_lib_version(env, **kw2) if Verbose: - print("_LibPrefixGenerator: version={:r}".format(version)) + print("_LibPrefixGenerator: version=%r" % version) if version: prefix = self.generate_versioned_lib_info(env, [prefix, version], prefix, **kw2) if Verbose: - print("_LibPrefixGenerator: return prefix={:r}".format(prefix)) + print("_LibPrefixGenerator: return prefix=%r" % prefix) return prefix ShLibPrefixGenerator = _LibPrefixGenerator('ShLib') @@ -532,17 +442,17 @@ class _LibSuffixGenerator(_LibInfoGeneratorBase): suffix = self.get_lib_suffix(env, **kw2) if Verbose: - print("_LibSuffixGenerator: input suffix={:r}".format(suffix)) + print("_LibSuffixGenerator: input suffix=%r" % suffix) version = self.get_lib_version(env, **kw2) if Verbose: - print("_LibSuffixGenerator: version={:r}".format(version)) + print("_LibSuffixGenerator: version=%r" % version) if version: suffix = self.generate_versioned_lib_info(env, [suffix, version], suffix, **kw2) if Verbose: - print("_LibSuffixGenerator: return suffix={:r}".format(suffix)) + print("_LibSuffixGenerator: return suffix=%r" % suffix) return suffix ShLibSuffixGenerator = _LibSuffixGenerator('ShLib') @@ -565,15 +475,15 @@ class _LibSymlinkGenerator(_LibInfoGeneratorBase): kw2 = kw if Verbose: - print("_LibSymLinkGenerator: libnode={:r}".format(libnode.get_path())) + print("_LibSymLinkGenerator: libnode=%r" % libnode.get_path()) symlinks = None version = self.get_lib_version(env, **kw2) disable = self.get_lib_noversionsymlinks(env, **kw2) if Verbose: - print('_LibSymlinkGenerator: version={:r}'.format(version)) - print('_LibSymlinkGenerator: disable={:r}'.format(disable)) + print('_LibSymlinkGenerator: version=%r' % version) + print('_LibSymlinkGenerator: disable=%r' % disable) if version and not disable: prefix = self.get_lib_prefix(env,**kw2) @@ -581,7 +491,7 @@ class _LibSymlinkGenerator(_LibInfoGeneratorBase): symlinks = self.generate_versioned_lib_info(env, [libnode, version, prefix, suffix], **kw2) if Verbose: - print('_LibSymlinkGenerator: return symlinks={:r}'.format(StringizeLibSymlinks(symlinks))) + print('_LibSymlinkGenerator: return symlinks=%r' % StringizeLibSymlinks(symlinks)) return symlinks ShLibSymlinkGenerator = _LibSymlinkGenerator('ShLib') @@ -590,7 +500,7 @@ ImpLibSymlinkGenerator = _LibSymlinkGenerator('ImpLib') class _LibNameGenerator(_LibInfoGeneratorBase): """Generates "unmangled" library name from a library file node. - + Generally, it's thought to revert modifications done by prefix/suffix generators (_LibPrefixGenerator/_LibSuffixGenerator) used by a library builder. For example, on gnulink the suffix generator used by SharedLibrary @@ -600,7 +510,7 @@ class _LibNameGenerator(_LibInfoGeneratorBase): "$SHLIBSUFFIX" in the node's basename. So that, if $SHLIBSUFFIX is ".so", $SHLIBVERSION is "0.1.2" and the node path is "/foo/bar/libfoo.so.0.1.2", the _LibNameGenerator shall return "libfoo.so". Other link tools may - implement it's own way of library name unmangling. + implement it's own way of library name unmangling. """ def __init__(self, libtype): super(_LibNameGenerator, self).__init__(libtype, 'Name') @@ -616,11 +526,11 @@ class _LibNameGenerator(_LibInfoGeneratorBase): kw2 = kw if Verbose: - print("_LibNameGenerator: libnode={:r}".format(libnode.get_path())) + print("_LibNameGenerator: libnode=%r" % libnode.get_path()) version = self.get_lib_version(env, **kw2) if Verbose: - print('_LibNameGenerator: version={:r}'.format(version)) + print('_LibNameGenerator: version=%r' % version) name = None if version: @@ -632,7 +542,7 @@ class _LibNameGenerator(_LibInfoGeneratorBase): name = os.path.basename(libnode.get_path()) if Verbose: - print('_LibNameGenerator: return name={:r}'.format(name)) + print('_LibNameGenerator: return name=%r' % name) return name @@ -641,7 +551,7 @@ LdModNameGenerator = _LibNameGenerator('LdMod') ImpLibNameGenerator = _LibNameGenerator('ImpLib') class _LibSonameGenerator(_LibInfoGeneratorBase): - """Library soname generator. Returns library soname (e.g. libfoo.so.0) for + """Library soname generator. Returns library soname (e.g. libfoo.so.0) for a given node (e.g. /foo/bar/libfoo.so.0.1.2)""" def __init__(self, libtype): super(_LibSonameGenerator, self).__init__(libtype, 'Soname') @@ -657,13 +567,13 @@ class _LibSonameGenerator(_LibInfoGeneratorBase): kw2 = kw if Verbose: - print("_LibSonameGenerator: libnode={:r}".format(libnode.get_path())) + print("_LibSonameGenerator: libnode=%r" % libnode.get_path()) soname = _call_env_subst(env, '$SONAME', **kw2) if not soname: version = self.get_lib_version(env,**kw2) if Verbose: - print("_LibSonameGenerator: version={:r}".format(version)) + print("_LibSonameGenerator: version=%r" % version) if version: prefix = self.get_lib_prefix(env,**kw2) suffix = self.get_lib_suffix(env,**kw2) @@ -673,10 +583,10 @@ class _LibSonameGenerator(_LibInfoGeneratorBase): # fallback to library name (as returned by appropriate _LibNameGenerator) soname = _LibNameGenerator(self.get_libtype())(env, libnode) if Verbose: - print("_LibSonameGenerator: FALLBACK: soname={:r}".format(soname)) + print("_LibSonameGenerator: FALLBACK: soname=%r" % soname) if Verbose: - print("_LibSonameGenerator: return soname={:r}".format(soname)) + print("_LibSonameGenerator: return soname=%r" % soname) return soname @@ -704,39 +614,39 @@ def EmitLibSymlinks(env, symlinks, libnode, **kw): clean_targets = kw.get('clean_targets', []) if not SCons.Util.is_List(clean_targets): clean_targets = [ clean_targets ] - + for link, linktgt in symlinks: env.SideEffect(link, linktgt) if(Verbose): - print("EmitLibSymlinks: SideEffect({:r},{:r})".format(link.get_path(), linktgt.get_path())) - clean_list = filter(lambda x : x != linktgt, nodes) + print("EmitLibSymlinks: SideEffect(%r,%r)" % (link.get_path(), linktgt.get_path())) + clean_list = [x for x in nodes if x != linktgt] env.Clean(list(set([linktgt] + clean_targets)), clean_list) if(Verbose): - print("EmitLibSymlinks: Clean({:r},{:r})".format(linktgt.get_path(), map(lambda x : x.get_path(), clean_list))) + print("EmitLibSymlinks: Clean(%r,%r)" % (linktgt.get_path(), [x.get_path() for x in clean_list])) def CreateLibSymlinks(env, symlinks): """Physically creates symlinks. The symlinks argument must be a list in form [ (link, linktarget), ... ], where link and linktarget are SCons nodes. """ - + Verbose = False for link, linktgt in symlinks: linktgt = link.get_dir().rel_path(linktgt) link = link.get_path() if(Verbose): - print("CreateLibSymlinks: preparing to add symlink {:r} -> {:r}".format(link, linktgt)) + print("CreateLibSymlinks: preparing to add symlink %r -> %r" % (link, linktgt)) # Delete the (previously created) symlink if exists. Let only symlinks # to be deleted to prevent accidental deletion of source files... if env.fs.islink(link): env.fs.unlink(link) if(Verbose): - print("CreateLibSymlinks: removed old symlink {:r}".format(link)) + print("CreateLibSymlinks: removed old symlink %r" % link) # If a file or directory exists with the same name as link, an OSError # will be thrown, which should be enough, I think. env.fs.symlink(linktgt, link) if(Verbose): - print("CreateLibSymlinks: add symlink {:r} -> {:r}".format(link, linktgt)) + print("CreateLibSymlinks: add symlink %r -> %r" % (link, linktgt)) return 0 def LibSymlinksActionFunction(target, source, env): @@ -761,7 +671,7 @@ def LibSymlinksStrFun(target, source, env, *args): else: cmd += ": %s" % linkstr return cmd - + LibSymlinksAction = SCons.Action.Action(LibSymlinksActionFunction, LibSymlinksStrFun) @@ -1040,7 +950,7 @@ class ToolInitializer(object): so we no longer copy and re-bind them when the construction environment gets cloned. """ - for method in self.methods.values(): + for method in list(self.methods.values()): env.RemoveMethod(method) def apply_tools(self, env): @@ -1228,3 +1138,4 @@ def tool_list(platform, env): # indent-tabs-mode:nil # End: # vim: set expandtab tabstop=4 shiftwidth=4: + -- cgit v0.12 From 1d0d856ede1adca42d190ef4a9532df70961da8e Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 12 May 2016 15:08:55 -0400 Subject: fix whitespace in generated dsp file to match expected in test harness. Editor or 2to3 was chopping trailing space --- src/engine/SCons/Tool/msvs.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py index c3c8164..6df4928 100644 --- a/src/engine/SCons/Tool/msvs.py +++ b/src/engine/SCons/Tool/msvs.py @@ -550,16 +550,16 @@ V6DSPHeader = """\ CFG=%(name)s - Win32 %(confkey)s !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "%(name)s.mak". -!MESSAGE +!MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "%(name)s.mak" CFG="%(name)s - Win32 %(confkey)s" -!MESSAGE +!MESSAGE !MESSAGE Possible choices for configuration are: -!MESSAGE +!MESSAGE """ class _GenerateV6DSP(_DSPGenerator): -- cgit v0.12 From e24a73d1a94ac419d3acf6fe0af6d4ce6cfea3c1 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 12 May 2016 15:10:20 -0400 Subject: remove reference to six package.. unused --- test/option/profile.py | 1 - 1 file changed, 1 deletion(-) diff --git a/test/option/profile.py b/test/option/profile.py index 93dad91..4d942cf 100644 --- a/test/option/profile.py +++ b/test/option/profile.py @@ -21,7 +21,6 @@ # 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 SCons.compat.six import u __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -- cgit v0.12 From 5dc3cdfd4df03ca7aa4d7db058e2c0b3926d4c10 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 12 May 2016 15:39:10 -0400 Subject: fix broken test. 2to3 print changes broke some formatting. Changed output to generate same in a different way --- test/Variables/ListVariable.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test/Variables/ListVariable.py b/test/Variables/ListVariable.py index c6972c1..e463840 100644 --- a/test/Variables/ListVariable.py +++ b/test/Variables/ListVariable.py @@ -67,11 +67,14 @@ opts.Save(optsfile, env) Help(opts.GenerateHelpText(env)) print(env['shared']) -if 'ical' in env['shared']: print('1') -else: print('0') -for x in env['shared']: - print (x,) -print() + +if 'ical' in env['shared']: + print('1') +else: + print('0') + +print(" ".join(env['shared'])) + print(env.subst('$shared')) # Test subst_path() because it's used in $CPPDEFINES expansions. print(env.subst_path('$shared')) -- cgit v0.12 From fdd25f581023b3a4a98a4682ee20c64fb7567f90 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 12 May 2016 16:41:15 -0400 Subject: fix error where IOError and OSError exceptions were falling through to the wrong case in Errors.py/convert_to_BuildError().. EnvironmentError is now just an alias in Py3 and it looks like the future module is not properly handling the py3 alias'ing and breaking the py2 exception class hierarchy. --- src/engine/SCons/Errors.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/engine/SCons/Errors.py b/src/engine/SCons/Errors.py index 54e888c..3cc9c6d 100644 --- a/src/engine/SCons/Errors.py +++ b/src/engine/SCons/Errors.py @@ -144,6 +144,7 @@ def convert_to_BuildError(status, exc_info=None): if not exc_info and isinstance(status, Exception): exc_info = (status.__class__, status, None) + if isinstance(status, BuildError): buildError = status buildError.exitstatus = 2 # always exit with 2 on build errors @@ -161,14 +162,17 @@ def convert_to_BuildError(status, exc_info=None): status=2, exitstatus=2, exc_info=exc_info) - elif isinstance(status, EnvironmentError): + elif isinstance(status, (EnvironmentError, OSError, IOError)): # If an IOError/OSError happens, raise a BuildError. # Report the name of the file or directory that caused the # error, which might be different from the target being built # (for example, failure to create the directory in which the # target file will appear). - try: filename = status.filename - except AttributeError: filename = None + try: + filename = status.filename + except AttributeError: + filename = None + buildError = BuildError( errstr=status.strerror, status=status.errno, -- cgit v0.12 From 254e647fbe03e280af8f595fff9606d8ec003972 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 12 May 2016 18:21:29 -0400 Subject: fix print() conversion on test --- test/Deprecated/Options/ListOption.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test/Deprecated/Options/ListOption.py b/test/Deprecated/Options/ListOption.py index ad804f2..42af511 100644 --- a/test/Deprecated/Options/ListOption.py +++ b/test/Deprecated/Options/ListOption.py @@ -68,11 +68,14 @@ opts.Save(optsfile, env) Help(opts.GenerateHelpText(env)) print(env['shared']) -if 'ical' in env['shared']: print('1') -else: print('0') -for x in env['shared']: - print(x, end='') -print() + +if 'ical' in env['shared']: + print('1') +else: + print('0') + +print(" ".join(env['shared'])) + print(env.subst('$shared')) # Test subst_path() because it's used in $CPPDEFINES expansions. print(env.subst_path('$shared')) -- cgit v0.12 From af735035cdaff0fa27fc396539cd51e9effe6e6c Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 12 May 2016 19:05:00 -0400 Subject: Seeems like EnvironmentError is not yielding the proper error output from SCons under __future__. py 3.5 EnvironmentError is an alias for OSError. Changing to OSError makes the test pass --- test/GetBuildFailures/serial.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/GetBuildFailures/serial.py b/test/GetBuildFailures/serial.py index fb59c7c..55a990f 100644 --- a/test/GetBuildFailures/serial.py +++ b/test/GetBuildFailures/serial.py @@ -82,8 +82,8 @@ Command('f08', 'f08.in', raiseExcAction(SCons.Errors.UserError("My User Error")) Command('f09', 'f09.in', returnExcAction(SCons.Errors.UserError("My User Error"))) Command('f10', 'f10.in', raiseExcAction(MyBuildError(errstr="My Build Error", status=7))) Command('f11', 'f11.in', returnExcAction(MyBuildError(errstr="My Build Error", status=7))) -Command('f12', 'f12.in', raiseExcAction(EnvironmentError(123, "My EnvironmentError", "f12"))) -Command('f13', 'f13.in', returnExcAction(EnvironmentError(123, "My EnvironmentError", "f13"))) +Command('f12', 'f12.in', raiseExcAction(OSError(123, "My EnvironmentError", "f12"))) +Command('f13', 'f13.in', returnExcAction(OSError(123, "My EnvironmentError", "f13"))) Command('f14', 'f14.in', raiseExcAction(SCons.Errors.InternalError("My InternalError"))) Command('f15', 'f15.in', returnExcAction(SCons.Errors.InternalError("My InternalError"))) -- cgit v0.12 From ba64112bdae96d643dbe398c0e4b9cd723348fb8 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 12 May 2016 21:39:57 -0400 Subject: fix print statement in embedded string which generates SConstruct --- test/GetBuildFailures/option-k.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/GetBuildFailures/option-k.py b/test/GetBuildFailures/option-k.py index b4e8d54..0ff22e6 100644 --- a/test/GetBuildFailures/option-k.py +++ b/test/GetBuildFailures/option-k.py @@ -65,7 +65,7 @@ Command('f6', 'f6.in', r'@%(_python_)s mypass.py f5 - $TARGET $SOURCE') def print_build_failures(): from SCons.Script import GetBuildFailures for bf in sorted(GetBuildFailures(), key=lambda a: a.filename): - print "%%s failed: %%s" %% (bf.node, bf.errstr) + print("%%s failed: %%s" %% (bf.node, bf.errstr)) import atexit atexit.register(print_build_failures) -- cgit v0.12 From 0a5aa629ffffda4aa6b960399ff19d59b6b76dd6 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 13 May 2016 14:51:22 -0400 Subject: Fixed print()'s. --- QMTest/TestSCons.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QMTest/TestSCons.py b/QMTest/TestSCons.py index 88d0e9c..a515684 100644 --- a/QMTest/TestSCons.py +++ b/QMTest/TestSCons.py @@ -1152,7 +1152,7 @@ try: print(distutils.sysconfig.get_python_inc()) print(os.path.join(exec_prefix, 'libs')) except: - print(os.path.join(sys.prefix, 'include', py_ver) + print(os.path.join(sys.prefix, 'include', py_ver)) print(os.path.join(sys.prefix, 'lib', py_ver, 'config')) print(py_ver) """) -- cgit v0.12 From b8ba51c52564ddf72a4f3dc229c35e081937aafa Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 13 May 2016 16:12:14 -0400 Subject: Restore deleted function _scons_file() in win32.py. This is causing most tests to fail in win32. See if this resolves. --- src/engine/SCons/Platform/win32.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/engine/SCons/Platform/win32.py b/src/engine/SCons/Platform/win32.py index 8ba8218..269007d 100644 --- a/src/engine/SCons/Platform/win32.py +++ b/src/engine/SCons/Platform/win32.py @@ -63,6 +63,13 @@ else: _builtin_file = file _builtin_open = open + class _scons_file(_builtin_file): + def __init__(self, *args, **kw): + _builtin_file.__init__(self, *args, **kw) + win32api.SetHandleInformation(msvcrt.get_osfhandle(self.fileno()), + win32con.HANDLE_FLAG_INHERIT, 0) + + def _scons_open(*args, **kw): fp = _builtin_open(*args, **kw) win32api.SetHandleInformation(msvcrt.get_osfhandle(fp.fileno()), -- cgit v0.12 From 9dc0f8feb825d50da88009c84fc274fb489d3a19 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 13 May 2016 16:30:20 -0700 Subject: fixes for print()'s for win32 --- QMTest/TestSConsMSVS.py | 4 ++-- src/engine/SCons/Action.py | 4 ++-- src/engine/SCons/Taskmaster.py | 6 +++++- test/MSVC/query_vcbat.py | 2 +- test/MSVS/vs-8.0-exec.py | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/QMTest/TestSConsMSVS.py b/QMTest/TestSConsMSVS.py index 7459af0..39dbb5e 100644 --- a/QMTest/TestSConsMSVS.py +++ b/QMTest/TestSConsMSVS.py @@ -1037,8 +1037,8 @@ class TestSConsMSVS(TestSCons): input = """\ import SCons import SCons.Tool.MSCommon -print "self.scons_version =", repr(SCons.__%s__) -print "self._msvs_versions =", str(SCons.Tool.MSCommon.query_versions()) +print("self.scons_version =", repr(SCons.__%s__)) +print("self._msvs_versions =", str(SCons.Tool.MSCommon.query_versions())) """ % 'version' self.run(arguments = '-n -q -Q -f -', stdin = input) diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index a4e75f3..7e1f8f1 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -233,8 +233,8 @@ def _code_contents(code): # The code contents depends on the number of local variables # but not their actual names. - contents.append("{}, {}".format(code.co_argcount, len(code.co_varnames))) - contents.append(", {}, {}".format(len(code.co_cellvars), len(code.co_freevars))) + contents.append(b"{}, {}".format(code.co_argcount, len(code.co_varnames))) + contents.append(b", {}, {}".format(len(code.co_cellvars), len(code.co_freevars))) # The code contents depends on any constants accessed by the # function. Note that we have to call _object_contents on each diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py index 7260071..ddafeb9 100644 --- a/src/engine/SCons/Taskmaster.py +++ b/src/engine/SCons/Taskmaster.py @@ -539,7 +539,11 @@ class Task(object): except ValueError: exc_type, exc_value = exc exc_traceback = None - raise exc_type, exc_value, exc_traceback + # raise exc_type, exc_value, exc_traceback + raise exc_type(exc_value).with_traceback(exc_traceback) + + # raise e.__class__, e.__class__(e), sys.exc_info()[2] + class AlwaysTask(Task): def needs_execute(self): diff --git a/test/MSVC/query_vcbat.py b/test/MSVC/query_vcbat.py index 328345d..428fe56 100644 --- a/test/MSVC/query_vcbat.py +++ b/test/MSVC/query_vcbat.py @@ -49,7 +49,7 @@ DefaultEnvironment(tools = []) # print k, v #MergeMSVSBatFile(env, 9.0) #print env['ENV']['PATH'] -print query_versions() +print(query_versions()) """) test.run(stderr = None) diff --git a/test/MSVS/vs-8.0-exec.py b/test/MSVS/vs-8.0-exec.py index cff7ca2..96c4c29 100644 --- a/test/MSVS/vs-8.0-exec.py +++ b/test/MSVS/vs-8.0-exec.py @@ -55,7 +55,7 @@ if not msvs_version in test.msvs_versions(): test.run(arguments = '-n -q -Q -f -', stdin = """\ env = Environment(tools = ['msvc'], MSVS_VERSION='%(msvs_version)s') -print "os.environ.update(%%s)" %% repr(env['ENV']) +print("os.environ.update(%%s)" %% repr(env['ENV'])) """ % locals()) exec(test.stdout()) -- cgit v0.12 From 547a704c080c97304425fcde1eb2381d9f395352 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 13 May 2016 20:43:15 -0700 Subject: fix default open mode for test.write() to be wb.. it was changed to just w when six was the plan. it causes many tests to fail on win32 --- QMTest/TestCmd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QMTest/TestCmd.py b/QMTest/TestCmd.py index 8cb6fb9..198f586 100644 --- a/QMTest/TestCmd.py +++ b/QMTest/TestCmd.py @@ -1719,7 +1719,7 @@ class TestCmd(object): do_chmod(os.path.join(dirpath, name)) do_chmod(top) - def write(self, file, content, mode = 'w'): + def write(self, file, content, mode = 'wb'): """Writes the specified content text (second argument) to the specified file name (first argument). The file name may be a list, in which case the elements are concatenated with the -- cgit v0.12 From 37eb6eeaa3dc3d850b784b6f808b710836a6c244 Mon Sep 17 00:00:00 2001 From: Pawel Tomulik Date: Sat, 14 May 2016 20:59:00 +0200 Subject: regression tests for #319 --- src/engine/SCons/Script/__init__.py | 1 + test/LINK/LDMODULEVERSIONFLAGS.py | 71 +++++++++++++++++++++++++++++++++++++ test/LINK/SHLIBVERSIONFLAGS.py | 28 ++++++++++----- 3 files changed, 91 insertions(+), 9 deletions(-) create mode 100644 test/LINK/LDMODULEVERSIONFLAGS.py diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py index a0c61c5..be6e5ce 100644 --- a/src/engine/SCons/Script/__init__.py +++ b/src/engine/SCons/Script/__init__.py @@ -354,6 +354,7 @@ GlobalDefaultBuilders = [ 'Java', 'JavaH', 'Library', + 'LoadableModule', 'M4', 'MSVSProject', 'Object', diff --git a/test/LINK/LDMODULEVERSIONFLAGS.py b/test/LINK/LDMODULEVERSIONFLAGS.py new file mode 100644 index 0000000..5a9a847 --- /dev/null +++ b/test/LINK/LDMODULEVERSIONFLAGS.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# 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. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import os +import re + +import TestSCons +import SCons.Platform +import SCons.Defaults + +foo_c_src = "void foo() {}\n" + +env = SCons.Defaults.DefaultEnvironment() +platform = SCons.Platform.platform_default() +tool_list = SCons.Platform.DefaultToolList(platform, env) + + +test = TestSCons.TestSCons() +if 'gnulink' in tool_list: + versionflags = r".+ -Wl,-Bsymbolic -Wl,-soname=libfoo.so.1( .+)+" +elif 'sunlink' in tool_list: + versionflags = r".+ -h libfoo.so.1( .+)+" +else: + test.skip_test('No testable likers found, skipping the test\n') + + +# We expect stdout to not contain LDMODULEVERSIONFLAGS if there is no +# SHLIBVERSION nor LDMODULEVERSION provided +test.write('foo.c', foo_c_src) +test.write('SConstruct', "LoadableModule('foo','foo.c')\n") +test.run() +test.fail_test(test.match_re_dotall(test.stdout(), versionflags)) +test.run(arguments = ['-c']) + +for versionvar in ['SHLIBVERSION', 'LDMODULEVERSION']: + test = TestSCons.TestSCons() + test.write('foo.c', foo_c_src) + test.write('SConstruct', "LoadableModule('foo','foo.c',%s='1.2.3')\n" % versionvar) + test.run(stdout = versionflags, match = TestSCons.match_re_dotall) + test.run(arguments = ['-c']) + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/LINK/SHLIBVERSIONFLAGS.py b/test/LINK/SHLIBVERSIONFLAGS.py index d8fd2e6..7f7975f 100644 --- a/test/LINK/SHLIBVERSIONFLAGS.py +++ b/test/LINK/SHLIBVERSIONFLAGS.py @@ -31,8 +31,6 @@ import TestSCons import SCons.Platform import SCons.Defaults -linkers = [ 'gnulink', 'cyglink', 'sunlink' ] - foo_c_src = "void foo() {}\n" env = SCons.Defaults.DefaultEnvironment() @@ -40,15 +38,27 @@ platform = SCons.Platform.platform_default() tool_list = SCons.Platform.DefaultToolList(platform, env) test = TestSCons.TestSCons() -test.write('foo.c', foo_c_src) -test.write('SConstruct', "SharedLibrary('foo','foo.c',SHLIBVERSION='1.2.3')\n") - if 'gnulink' in tool_list: - test.run(stdout = r".+ -Wl,-Bsymbolic -Wl,-soname=libfoo.so.1( .+)+", match = TestSCons.match_re_dotall) - test.run(arguments = ['-c']) + versionflags = r".+ -Wl,-Bsymbolic -Wl,-soname=libfoo.so.1( .+)+" elif 'sunlink' in tool_list: - test.run(stdout = r".+ -h libfoo.so.1( .+)+", match = TestSCons.match_re_dotall) - test.run(arguments = ['-c']) + versionflags = r".+ -h libfoo.so.1( .+)+" +else: + test.skip_test('No testable likers found, skipping the test\n') + + +# stdout must not contain SHLIBVERSIONFLAGS if there is no SHLIBVERSION provided +test.write('foo.c', foo_c_src) +test.write('SConstruct', "SharedLibrary('foo','foo.c')\n") +test.run() +test.fail_test(test.match_re_dotall(test.stdout(), versionflags)) +test.run(arguments = ['-c']) + +# stdout must contain SHLIBVERSIONFLAGS if there is SHLIBVERSION provided +test = TestSCons.TestSCons() +test.write('foo.c', foo_c_src) +test.write('SConstruct', "SharedLibrary('foo','foo.c',SHLIBVERSION='1.2.3')\n") +test.run(stdout = versionflags, match = TestSCons.match_re_dotall) +test.run(arguments = ['-c']) test.pass_test() -- cgit v0.12 From 96ba1793cf7346a6fdbee6bfd843cdbd3efebedf Mon Sep 17 00:00:00 2001 From: Bill Date: Sat, 14 May 2016 15:37:00 -0700 Subject: Fix re-raising exception so the syntax will work for both python3 and python2. --- src/engine/SCons/Taskmaster.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py index ddafeb9..0f4fd21 100644 --- a/src/engine/SCons/Taskmaster.py +++ b/src/engine/SCons/Taskmaster.py @@ -22,6 +22,8 @@ from __future__ import print_function +import sys + __doc__ = """ Generic Taskmaster module for the SCons build engine. @@ -539,8 +541,11 @@ class Task(object): except ValueError: exc_type, exc_value = exc exc_traceback = None - # raise exc_type, exc_value, exc_traceback - raise exc_type(exc_value).with_traceback(exc_traceback) + + if sys.version_info[0] == 2: + exec("raise exc_type, exc_value, exc_traceback") + else: # sys.version_info[0] == 3: + exec("raise exc_type(exc_value).with_traceback(exc_traceback)") # raise e.__class__, e.__class__(e), sys.exc_info()[2] -- cgit v0.12 From 9f4e808d1b38635151876a6ee513eae279b48c19 Mon Sep 17 00:00:00 2001 From: Bill Date: Sat, 14 May 2016 15:41:52 -0700 Subject: Fix print() --- test/MSVS/vs-10.0-exec.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/MSVS/vs-10.0-exec.py b/test/MSVS/vs-10.0-exec.py index 86b4042..1a4b59a 100644 --- a/test/MSVS/vs-10.0-exec.py +++ b/test/MSVS/vs-10.0-exec.py @@ -55,7 +55,7 @@ if not msvs_version in test.msvs_versions(): test.run(arguments = '-n -q -Q -f -', stdin = """\ env = Environment(tools = ['msvc'], MSVS_VERSION='%(msvs_version)s') -print "os.environ.update(%%s)" %% repr(env['ENV']) +print("os.environ.update(%%s)" %% repr(env['ENV'])) """ % locals()) exec(test.stdout()) -- cgit v0.12 From df76f938024f9d1ee96166bd9660886acd99f5de Mon Sep 17 00:00:00 2001 From: Bill Date: Sat, 14 May 2016 15:42:36 -0700 Subject: Fix print() --- test/Win32/bad-drive.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Win32/bad-drive.py b/test/Win32/bad-drive.py index 4d0d6e9..67a287a 100644 --- a/test/Win32/bad-drive.py +++ b/test/Win32/bad-drive.py @@ -59,7 +59,7 @@ test.write('SConstruct', """ def cat(env, source, target): target = str(target[0]) source = list(map(str, source)) - print 'cat(%%s) > %%s' %% (source, target) + print('cat(%%s) > %%s' %% (source, target)) f = open(target, "wb") for src in source: f.write(open(src, "rb").read()) -- cgit v0.12 From be27b009e8b59ff8b6605459bf39fe8590a37cf0 Mon Sep 17 00:00:00 2001 From: Bill Date: Sat, 14 May 2016 15:43:31 -0700 Subject: Fix print() --- test/Win32/mingw.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Win32/mingw.py b/test/Win32/mingw.py index 6b23314..80067bc 100644 --- a/test/Win32/mingw.py +++ b/test/Win32/mingw.py @@ -47,7 +47,7 @@ from SCons.Tool.mingw import exists import sys env = Environment() if exists(env): - print 'mingw exists' + print('mingw exists') sys.exit(0) """) -- cgit v0.12 From 39d873ea2789008bb153026d730c3a6541331be4 Mon Sep 17 00:00:00 2001 From: William Blevins Date: Sun, 15 May 2016 13:13:31 +0100 Subject: Fixed Fortran tests which were throughing missing include directory warning. Warning added in gcc5. --- test/Fortran/F77FLAGS.py | 5 ++++- test/Fortran/FORTRANFLAGS.py | 5 ++++- test/Fortran/SHF77FLAGS.py | 5 ++++- test/Fortran/SHFORTRANFLAGS.py | 5 ++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/test/Fortran/F77FLAGS.py b/test/Fortran/F77FLAGS.py index b708f9e..342adac 100644 --- a/test/Fortran/F77FLAGS.py +++ b/test/Fortran/F77FLAGS.py @@ -77,6 +77,9 @@ g77 = test.detect_tool(fc) if g77: + directory = 'x' + test.subdir(directory) + test.write("wrapper.py", """import os import sys @@ -87,7 +90,7 @@ os.system(" ".join(sys.argv[1:])) test.write('SConstruct', """ foo = Environment(F77 = '%(fc)s', tools = ['default', 'f77'], F77FILESUFFIXES = [".f"]) f77 = foo.Dictionary('F77') -bar = foo.Clone(F77 = r'%(_python_)s wrapper.py ' + f77, F77FLAGS = '-Ix') +bar = foo.Clone(F77 = r'%(_python_)s wrapper.py ' + f77, F77FLAGS = '-I%(directory)s') foo.Program(target = 'foo', source = 'foo.f') bar.Program(target = 'bar', source = 'bar.f') """ % locals()) diff --git a/test/Fortran/FORTRANFLAGS.py b/test/Fortran/FORTRANFLAGS.py index 8c5e781..150000a 100644 --- a/test/Fortran/FORTRANFLAGS.py +++ b/test/Fortran/FORTRANFLAGS.py @@ -95,6 +95,9 @@ g77 = test.detect_tool(fc) if g77: + directory = 'x' + test.subdir(directory) + test.write("wrapper.py", """import os import sys @@ -105,7 +108,7 @@ os.system(" ".join(sys.argv[1:])) test.write('SConstruct', """ foo = Environment(FORTRAN = '%(fc)s') f77 = foo.Dictionary('FORTRAN') -bar = foo.Clone(FORTRAN = r'%(_python_)s wrapper.py ' + f77, FORTRANFLAGS = '-Ix') +bar = foo.Clone(FORTRAN = r'%(_python_)s wrapper.py ' + f77, FORTRANFLAGS = '-I%(directory)s') foo.Program(target = 'foo', source = 'foo.f') bar.Program(target = 'bar', source = 'bar.f') """ % locals()) diff --git a/test/Fortran/SHF77FLAGS.py b/test/Fortran/SHF77FLAGS.py index 644b827..79e46f3 100644 --- a/test/Fortran/SHF77FLAGS.py +++ b/test/Fortran/SHF77FLAGS.py @@ -75,6 +75,9 @@ g77 = test.detect_tool(fc) if g77: + directory = 'x' + test.subdir(directory) + test.write("wrapper.py", """import os import sys @@ -87,7 +90,7 @@ foo = Environment(SHF77 = '%(fc)s') shf77 = foo.Dictionary('SHF77') bar = foo.Clone(SHF77 = r'%(_python_)s wrapper.py ' + shf77, tools = ["default", 'f77'], F77FILESUFFIXES = [".f"]) -bar.Append(SHF77FLAGS = '-Ix') +bar.Append(SHF77FLAGS = '-I%(directory)s') foo.SharedLibrary(target = 'foo/foo', source = 'foo.f') bar.SharedLibrary(target = 'bar/bar', source = 'bar.f') """ % locals()) diff --git a/test/Fortran/SHFORTRANFLAGS.py b/test/Fortran/SHFORTRANFLAGS.py index 11116f4..8e6f019 100644 --- a/test/Fortran/SHFORTRANFLAGS.py +++ b/test/Fortran/SHFORTRANFLAGS.py @@ -91,6 +91,9 @@ fortran = test.detect_tool(fc) if fortran: + directory = 'x' + test.subdir(directory) + test.write("wrapper.py", """import os import sys @@ -102,7 +105,7 @@ os.system(" ".join(sys.argv[1:])) foo = Environment(SHFORTRAN = '%(fc)s') shfortran = foo.Dictionary('SHFORTRAN') bar = foo.Clone(SHFORTRAN = r'%(_python_)s wrapper.py ' + shfortran) -bar.Append(SHFORTRANFLAGS = '-Ix') +bar.Append(SHFORTRANFLAGS = '-I%(directory)s') foo.SharedLibrary(target = 'foo/foo', source = 'foo.f') bar.SharedLibrary(target = 'bar/bar', source = 'bar.f') """ % locals()) -- cgit v0.12 From 59543b3ca4070ba5b35c055780a244a29beadd8a Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 15 May 2016 07:55:12 -0700 Subject: fix incorrectly updated print formatting --- src/engine/SCons/Node/FS.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index a4dd5d9..d19afa9 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -3082,7 +3082,7 @@ class File(Base): try: self._createDir() except SCons.Errors.StopError as drive: - raise SCons.Errors.StopError("No drive `%s' for target `{}'.".format(drive, self)) + raise SCons.Errors.StopError("No drive `{}' for target `{}'.".format(drive, self)) # # -- cgit v0.12 From 6ea744952d40c63c98f8b04e1b9a8e7ce73992c3 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 15 May 2016 11:44:48 -0700 Subject: Update logic to pull files from mercurial --- bin/scons_dev_master.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/scons_dev_master.py b/bin/scons_dev_master.py index a8862ea..71842aa 100644 --- a/bin/scons_dev_master.py +++ b/bin/scons_dev_master.py @@ -11,7 +11,7 @@ import sys from Command import CommandRunner, Usage INITIAL_PACKAGES = [ - 'subversion', + 'mercurial', ] INSTALL_PACKAGES = [ @@ -123,7 +123,7 @@ Usage: scons_dev_master.py [-hnqy] [--password PASSWORD] [--username USER] buildbot Install packages for running BuildBot """ - scons_url = 'http://scons.tigris.org/svn/scons/trunk' + scons_url = 'https://bdbaddog@bitbucket.org/scons/scons' sudo = 'sudo' password = '""' username = 'guest' @@ -171,7 +171,7 @@ Usage: scons_dev_master.py [-hnqy] [--password PASSWORD] [--username USER] cmd.run('%(sudo)s apt-get %(yesflag)s upgrade') elif arg == 'checkout': cmd.run('%(sudo)s apt-get %(yesflag)s install %(initial_packages)s') - cmd.run('svn co --username guest --password "" %(scons_url)s') + cmd.run('hg clone" %(scons_url)s') elif arg == 'building': cmd.run('%(sudo)s apt-get %(yesflag)s install %(building_packages)s') elif arg == 'testing': -- cgit v0.12 From c5e30d23ebc878acb8e16e025b6f55aaab43f3a5 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 15 May 2016 12:27:51 -0700 Subject: change to handle py3 changes to byte/string for open().write() --- QMTest/TestCmd.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/QMTest/TestCmd.py b/QMTest/TestCmd.py index 198f586..2fba0a0 100644 --- a/QMTest/TestCmd.py +++ b/QMTest/TestCmd.py @@ -1731,7 +1731,11 @@ class TestCmd(object): file = self.canonicalize(file) if mode[0] != 'w': raise ValueError("mode must begin with 'w'") - open(file, mode).write(content) + try: + open(file, mode).write(content) + except TypeError as e: + # python 3 default strings are not bytes, but unicode + open(file, mode).write(bytes(content,'utf-8')) # Local Variables: # tab-width:4 -- cgit v0.12 From d64346001c83adce8bdfd6f9e8df191762d11c44 Mon Sep 17 00:00:00 2001 From: Pawel Tomulik Date: Mon, 16 May 2016 00:11:59 +0200 Subject: add blurb to src/CHANGES.txt for #319 --- src/CHANGES.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index b6973b7..25f982a 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -11,6 +11,15 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Whatever John Doe did. + From Paweł Tomulik: + - Fixed the issue with LDMODULEVERSIONFLAGS reported by Tim Jennes + (https://pairlist4.pair.net/pipermail/scons-users/2016-May/004893.html). + An error was causing “-Wl,Bsymbolic” being added to linker's command-line + even when there was no specified value in LDMODULEVERSION and thus no + need for the flags to be specified. + - Added LoadableModule to the list of global functions (DefaultEnvironment + builders). + RELEASE 2.5.0 - Mon, 09 Apr 2016 11:27:42 -0700 From Dirk Baechle: -- cgit v0.12 From fd9c768bf1b749a15d56481a49f7d60dd22a7ef6 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 15 May 2016 15:16:34 -0700 Subject: revert some py3 changes which fail no py2 on windows and any platform/python without dbm module installed. Revisit py3 issues after we get py2 working again --- src/script/sconsign.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/script/sconsign.py b/src/script/sconsign.py index 6f49858..e046a2c 100644 --- a/src/script/sconsign.py +++ b/src/script/sconsign.py @@ -187,7 +187,9 @@ sys.path = libs + sys.path import SCons.compat import whichdb -import dbm + +# was added for py3, but breaks py2 on windows.. +#import dbm import time import pickle import imp @@ -205,8 +207,14 @@ def my_whichdb(filename): pass return _orig_whichdb(filename) + +# Should work on python2 _orig_whichdb = whichdb.whichdb -dbm.whichdb = my_whichdb +whichdb.whichdb = my_whichdb + +# was changed for python3 +#_orig_whichdb = whichdb.whichdb +#dbm.whichdb = my_whichdb def my_import(mname): if '.' in mname: @@ -523,7 +531,9 @@ if Do_Call: Do_Call(a) else: for a in args: - dbm_name = dbm.whichdb(a) + # changed for py3 compat, broke py2 on windows + # dbm_name = dbm.whichdb(a) + dbm_name = whichdb.whichdb(a) if dbm_name: Map_Module = {'SCons.dblite' : 'dblite'} if dbm_name != "SCons.dblite": -- cgit v0.12 From 013d87ae5921b0bb55232a38257433ca256ee197 Mon Sep 17 00:00:00 2001 From: ptomulik Date: Mon, 16 May 2016 11:01:17 +0200 Subject: correct typos in test/LINK/{SHLIB,LDMODULE}VERSIONFLAGS.py --- test/LINK/LDMODULEVERSIONFLAGS.py | 2 +- test/LINK/SHLIBVERSIONFLAGS.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/LINK/LDMODULEVERSIONFLAGS.py b/test/LINK/LDMODULEVERSIONFLAGS.py index 5a9a847..0683b72 100644 --- a/test/LINK/LDMODULEVERSIONFLAGS.py +++ b/test/LINK/LDMODULEVERSIONFLAGS.py @@ -44,7 +44,7 @@ if 'gnulink' in tool_list: elif 'sunlink' in tool_list: versionflags = r".+ -h libfoo.so.1( .+)+" else: - test.skip_test('No testable likers found, skipping the test\n') + test.skip_test('No testable linkers found, skipping the test\n') # We expect stdout to not contain LDMODULEVERSIONFLAGS if there is no diff --git a/test/LINK/SHLIBVERSIONFLAGS.py b/test/LINK/SHLIBVERSIONFLAGS.py index 7f7975f..aae8843 100644 --- a/test/LINK/SHLIBVERSIONFLAGS.py +++ b/test/LINK/SHLIBVERSIONFLAGS.py @@ -43,7 +43,7 @@ if 'gnulink' in tool_list: elif 'sunlink' in tool_list: versionflags = r".+ -h libfoo.so.1( .+)+" else: - test.skip_test('No testable likers found, skipping the test\n') + test.skip_test('No testable linkers found, skipping the test\n') # stdout must not contain SHLIBVERSIONFLAGS if there is no SHLIBVERSION provided -- cgit v0.12 From b763362d906af8e23409a1f5d3dc782b0ca3cc91 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 18 May 2016 19:09:05 -0700 Subject: Fix py2/3 StringIO import --- src/engine/SCons/Script/__init__.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py index 974841c..66120e4 100644 --- a/src/engine/SCons/Script/__init__.py +++ b/src/engine/SCons/Script/__init__.py @@ -41,7 +41,12 @@ start_time = time.time() import collections import os -import StringIO + +try: + from StringIO import StringIO +except ImportError: + from io import StringIO + import sys # Special chicken-and-egg handling of the "--debug=memoizer" flag: -- cgit v0.12 From 7d7012b21a1434ab03cead57e4b8926c8b5ef153 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 18 May 2016 19:58:51 -0700 Subject: fix for module loading to us importlib instead of imp (which no longer works in pyton3) --- src/engine/SCons/Tool/__init__.py | 68 +++++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index 4cd242b..87ebb98 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -38,11 +38,13 @@ tool definition. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import imp +import importlib import sys import re import os import shutil + import SCons.Builder import SCons.Errors import SCons.Node.FS @@ -114,30 +116,56 @@ class Tool(object): sys.path = self.toolpath + sys.path try: + # Try site_tools first + return importlib.import_module(self.name) + except ImportError as e: + # Then try modules in main distribution + return importlib.import_module('SCons.Tool.'+self.name) + except ImportError as e: + if str(e) != "No module named %s" % self.name: + raise SCons.Errors.EnvironmentError(e) try: - file, path, desc = imp.find_module(self.name, self.toolpath) - try: - return imp.load_module(self.name, file, path, desc) - finally: - if file: - file.close() - except ImportError as e: - if str(e)!="No module named %s"%self.name: - raise SCons.Errors.EnvironmentError(e) - try: - import zipimport - except ImportError: - pass - else: - for aPath in self.toolpath: - try: - importer = zipimport.zipimporter(aPath) - return importer.load_module(self.name) - except ImportError as e: - pass + import zipimport + except ImportError: + pass + else: + for aPath in self.toolpath: + try: + importer = zipimport.zipimporter(aPath) + return importer.load_module(self.name) + except ImportError as e: + pass + finally: sys.path = oldpythonpath + # old code + # try: + # try: + # file, path, desc = imp.find_module(self.name, self.toolpath) + # try: + # return imp.load_module(self.name, file, path, desc) + # + # finally: + # if file: + # file.close() + # except ImportError as e: + # if str(e)!="No module named %s"%self.name: + # raise SCons.Errors.EnvironmentError(e) + # try: + # import zipimport + # except ImportError: + # pass + # else: + # for aPath in self.toolpath: + # try: + # importer = zipimport.zipimporter(aPath) + # return importer.load_module(self.name) + # except ImportError as e: + # pass + # finally: + # sys.path = oldpythonpath + full_name = 'SCons.Tool.' + self.name try: return sys.modules[full_name] -- cgit v0.12 From 01ab580ffdd90459f729d44efa6a3f0cc733fbf5 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 19 May 2016 09:03:06 -0700 Subject: Fix unicode type code to handle py2/3 --- src/engine/SCons/Util.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index a5a92fa..0be6196 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -55,9 +55,13 @@ except ImportError as e: MethodType = types.MethodType FunctionType = types.FunctionType -try: unicode -except NameError: UnicodeType = None -else: UnicodeType = unicode + +try: + unicode +except NameError: + UnicodeType = str +else: + UnicodeType = unicode def dictify(keys, values, result={}): for k, v in zip(keys, values): @@ -172,7 +176,7 @@ class DisplayEngine(object): return if append_newline: text = text + '\n' try: - sys.stdout.write(unicode(text)) + sys.stdout.write(UnicodeType(text)) except IOError: # Stdout might be connected to a pipe that has been closed # by now. The most likely reason for the pipe being closed -- cgit v0.12 From 6cb5d61fa6244c37b2aeb0255e47b9b749d3f4d1 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 19 May 2016 09:10:34 -0700 Subject: minor improvement to Tool loading code for py2/3 compat --- src/engine/SCons/Tool/__init__.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index 87ebb98..1590053 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -120,21 +120,22 @@ class Tool(object): return importlib.import_module(self.name) except ImportError as e: # Then try modules in main distribution - return importlib.import_module('SCons.Tool.'+self.name) - except ImportError as e: - if str(e) != "No module named %s" % self.name: - raise SCons.Errors.EnvironmentError(e) try: - import zipimport - except ImportError: - pass - else: - for aPath in self.toolpath: - try: - importer = zipimport.zipimporter(aPath) - return importer.load_module(self.name) - except ImportError as e: - pass + return importlib.import_module('SCons.Tool.'+self.name) + except ImportError as e: + if str(e) != "No module named %s" % self.name: + raise SCons.Errors.EnvironmentError(e) + try: + import zipimport + except ImportError: + pass + else: + for aPath in self.toolpath: + try: + importer = zipimport.zipimporter(aPath) + return importer.load_module(self.name) + except ImportError as e: + pass finally: sys.path = oldpythonpath -- cgit v0.12 From 2b20141f5bc6fb7aedd9a24e4c8079e82d52d260 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 19 May 2016 10:53:46 -0700 Subject: Fixing StringIO usage. --- src/engine/SCons/Script/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py index 66120e4..291c108 100644 --- a/src/engine/SCons/Script/__init__.py +++ b/src/engine/SCons/Script/__init__.py @@ -269,7 +269,7 @@ def HelpFunction(text, append=False): global help_text if help_text is None: if append: - s = StringIO.StringIO() + s = StringIO() PrintHelp(s) help_text = s.getvalue() s.close() -- cgit v0.12 From 561eda349061019df9c8aa904de62896b12472c0 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 23 May 2016 10:00:43 -0700 Subject: use old tool loading code for py2, and new code (not quite working yet) for py3 --- src/engine/SCons/Tool/__init__.py | 101 ++++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 48 deletions(-) diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index 1590053..d75d7ca 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -115,57 +115,62 @@ class Tool(object): oldpythonpath = sys.path sys.path = self.toolpath + sys.path - try: - # Try site_tools first - return importlib.import_module(self.name) - except ImportError as e: - # Then try modules in main distribution + + if False and sys.version_info[0] < 3: + # Py 2 code try: - return importlib.import_module('SCons.Tool.'+self.name) + try: + file, path, desc = imp.find_module(self.name, self.toolpath) + try: + return imp.load_module(self.name, file, path, desc) + + finally: + if file: + file.close() + except ImportError as e: + if str(e)!="No module named %s"%self.name: + raise SCons.Errors.EnvironmentError(e) + try: + import zipimport + except ImportError: + pass + else: + for aPath in self.toolpath: + try: + importer = zipimport.zipimporter(aPath) + return importer.load_module(self.name) + except ImportError as e: + pass + finally: + sys.path = oldpythonpath + else: + # Py 3 code + try: + # Try site_tools first + return importlib.import_module(self.name) except ImportError as e: - if str(e) != "No module named %s" % self.name: - raise SCons.Errors.EnvironmentError(e) + # Then try modules in main distribution try: - import zipimport - except ImportError: - pass - else: - for aPath in self.toolpath: - try: - importer = zipimport.zipimporter(aPath) - return importer.load_module(self.name) - except ImportError as e: - pass - - finally: - sys.path = oldpythonpath - - # old code - # try: - # try: - # file, path, desc = imp.find_module(self.name, self.toolpath) - # try: - # return imp.load_module(self.name, file, path, desc) - # - # finally: - # if file: - # file.close() - # except ImportError as e: - # if str(e)!="No module named %s"%self.name: - # raise SCons.Errors.EnvironmentError(e) - # try: - # import zipimport - # except ImportError: - # pass - # else: - # for aPath in self.toolpath: - # try: - # importer = zipimport.zipimporter(aPath) - # return importer.load_module(self.name) - # except ImportError as e: - # pass - # finally: - # sys.path = oldpythonpath + return importlib.import_module('SCons.Tool.'+self.name) + except ImportError as e: + if str(e) != "No module named %s" % self.name: + raise SCons.Errors.EnvironmentError(e) + try: + import zipimport + except ImportError: + pass + else: + for aPath in self.toolpath: + try: + importer = zipimport.zipimporter(aPath) + return importer.load_module(self.name) + except ImportError as e: + pass + + finally: + sys.path = oldpythonpath + + full_name = 'SCons.Tool.' + self.name try: -- cgit v0.12 From b387e34357c968d0855c525c7e838657a957ff01 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 23 May 2016 10:35:46 -0700 Subject: Remove debug code to reenable python version specific tool module loading code. --- src/engine/SCons/Tool/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index d75d7ca..45d0aa1 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -116,7 +116,7 @@ class Tool(object): sys.path = self.toolpath + sys.path - if False and sys.version_info[0] < 3: + if sys.version_info[0] < 3: # Py 2 code try: try: -- cgit v0.12 -- cgit v0.12 From e4b799e8dc348159c5f2d70bdf49819c4d8270bc Mon Sep 17 00:00:00 2001 From: Daniel Holth Date: Sun, 5 Jun 2016 20:23:12 -0400 Subject: avoid using __slots__ on Node and Executor (but only on PyPy) --- src/engine/SCons/Executor.py | 6 ++--- src/engine/SCons/Node/__init__.py | 5 +++- src/engine/SCons/compat/__init__.py | 47 +++++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/engine/SCons/Executor.py b/src/engine/SCons/Executor.py index 7107fde..dd5088d 100644 --- a/src/engine/SCons/Executor.py +++ b/src/engine/SCons/Executor.py @@ -35,7 +35,7 @@ import SCons.Debug from SCons.Debug import logInstanceCreation import SCons.Errors import SCons.Memoize - +from SCons.compat import with_metaclass, NoSlotsPyPy class Batch(object): """Remembers exact association between targets @@ -154,7 +154,7 @@ _execute_str_map = {0 : execute_null_str, 1 : execute_actions_str} -class Executor(object): +class Executor(object, with_metaclass(NoSlotsPyPy)): """A class for controlling instances of executing an action. This largely exists to hold a single association of an action, @@ -580,7 +580,7 @@ def get_NullEnvironment(): nullenv = NullEnvironment() return nullenv -class Null(object): +class Null(object, with_metaclass(NoSlotsPyPy)): """A null Executor, with a null build Environment, that does nothing when the rest of the methods call it. diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 1a76b60..e714172 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -57,6 +57,8 @@ import SCons.Util from SCons.Debug import Trace +from SCons.compat import with_metaclass, NoSlotsPyPy + print_duplicate = 0 def classname(obj): @@ -489,7 +491,8 @@ class BuildInfoBase(object): if key not in ('__weakref__',): setattr(self, key, value) -class Node(object): + +class Node(object, with_metaclass(NoSlotsPyPy)): """The base Node class, for entities that we know how to build, or use to build other Nodes. """ diff --git a/src/engine/SCons/compat/__init__.py b/src/engine/SCons/compat/__init__.py index 0ddbdd5..285c4ac 100644 --- a/src/engine/SCons/compat/__init__.py +++ b/src/engine/SCons/compat/__init__.py @@ -63,6 +63,8 @@ import os import sys import imp # Use the "imp" module to protect imports from fixers. +PYPY = hasattr(sys, 'pypy_translation_info') + def import_as(module, name): """ Imports the specified module (from our local directory) as the @@ -135,6 +137,51 @@ except AttributeError: del _UserString +def with_metaclass(meta, *bases): + """ + Function from jinja2/_compat.py. License: BSD. + + Use it like this:: + + class BaseForm(object): + pass + + class FormType(type): + pass + + class Form(with_metaclass(FormType, BaseForm)): + pass + + This requires a bit of explanation: the basic idea is to make a + dummy metaclass for one level of class instantiation that replaces + itself with the actual metaclass. Because of internal type checks + we also need to make sure that we downgrade the custom metaclass + for one level to something closer to type (that's why __call__ and + __init__ comes back from type etc.). + + This has the advantage over six.with_metaclass of not introducing + dummy classes into the final MRO. + """ + class metaclass(meta): + __call__ = type.__call__ + __init__ = type.__init__ + def __new__(cls, name, this_bases, d): + if this_bases is None: + return type.__new__(cls, name, (), d) + return meta(name, bases, d) + return metaclass('temporary_class', None, {}) + + +class NoSlotsPyPy(type): + """ + Workaround for PyPy not working well with __slots__ and __class__ assignment. + """ + def __new__(meta, name, bases, dct): + if PYPY and '__slots__' in dct: + dct['__slats__'] = dct.pop('__slots__') + return super(NoSlotsPyPy, meta).__new__(meta, name, bases, dct) + + # Local Variables: # tab-width:4 # indent-tabs-mode:nil -- cgit v0.12 From 3128ce66f69ee2be54080caea8d86f817885616b Mon Sep 17 00:00:00 2001 From: Daniel Holth Date: Sun, 5 Jun 2016 22:57:26 -0400 Subject: fix some tests for pypy The major category of broken test is that which depends on garbage collection to flush and close an open file. Also, the empty list is apparently not a singleton in pypy. --- QMTest/TestCmd.py | 11 ++++++----- src/engine/SCons/ActionTests.py | 30 ++++++++++++++++++------------ 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/QMTest/TestCmd.py b/QMTest/TestCmd.py index 2fba0a0..b0a456b 100644 --- a/QMTest/TestCmd.py +++ b/QMTest/TestCmd.py @@ -1731,11 +1731,12 @@ class TestCmd(object): file = self.canonicalize(file) if mode[0] != 'w': raise ValueError("mode must begin with 'w'") - try: - open(file, mode).write(content) - except TypeError as e: - # python 3 default strings are not bytes, but unicode - open(file, mode).write(bytes(content,'utf-8')) + with open(file, mode) as f: + try: + f.write(content) + except TypeError as e: + # python 3 default strings are not bytes, but unicode + f.write(bytes(content,'utf-8')) # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py index 3eee4b6..9007183 100644 --- a/src/engine/SCons/ActionTests.py +++ b/src/engine/SCons/ActionTests.py @@ -231,7 +231,7 @@ def test_positional_args(pos_callback, cmd, **kw): """ act = SCons.Action.Action(cmd, **kw) pos_callback(act) - assert act.varlist is (), act.varlist + assert act.varlist == (), act.varlist if not isinstance(act, SCons.Action._ActionAction): # only valid cmdstrfunc is None @@ -316,7 +316,7 @@ class ActionTestCase(unittest.TestCase): """ a1 = SCons.Action.Action(["x", "y", "z", [ "a", "b", "c"]]) assert isinstance(a1, SCons.Action.ListAction), a1 - assert a1.varlist is (), a1.varlist + assert a1.varlist == (), a1.varlist assert isinstance(a1.list[0], SCons.Action.CommandAction), a1.list[0] assert a1.list[0].cmd_list == "x", a1.list[0].cmd_list assert isinstance(a1.list[1], SCons.Action.CommandAction), a1.list[1] @@ -328,7 +328,7 @@ class ActionTestCase(unittest.TestCase): a2 = SCons.Action.Action("x\ny\nz") assert isinstance(a2, SCons.Action.ListAction), a2 - assert a2.varlist is (), a2.varlist + assert a2.varlist == (), a2.varlist assert isinstance(a2.list[0], SCons.Action.CommandAction), a2.list[0] assert a2.list[0].cmd_list == "x", a2.list[0].cmd_list assert isinstance(a2.list[1], SCons.Action.CommandAction), a2.list[1] @@ -341,7 +341,7 @@ class ActionTestCase(unittest.TestCase): a3 = SCons.Action.Action(["x", foo, "z"]) assert isinstance(a3, SCons.Action.ListAction), a3 - assert a3.varlist is (), a3.varlist + assert a3.varlist == (), a3.varlist assert isinstance(a3.list[0], SCons.Action.CommandAction), a3.list[0] assert a3.list[0].cmd_list == "x", a3.list[0].cmd_list assert isinstance(a3.list[1], SCons.Action.FunctionAction), a3.list[1] @@ -351,7 +351,7 @@ class ActionTestCase(unittest.TestCase): a4 = SCons.Action.Action(["x", "y"], strfunction=foo) assert isinstance(a4, SCons.Action.ListAction), a4 - assert a4.varlist is (), a4.varlist + assert a4.varlist == (), a4.varlist assert isinstance(a4.list[0], SCons.Action.CommandAction), a4.list[0] assert a4.list[0].cmd_list == "x", a4.list[0].cmd_list assert a4.list[0].strfunction == foo, a4.list[0].strfunction @@ -361,7 +361,7 @@ class ActionTestCase(unittest.TestCase): a5 = SCons.Action.Action("x\ny", strfunction=foo) assert isinstance(a5, SCons.Action.ListAction), a5 - assert a5.varlist is (), a5.varlist + assert a5.varlist == (), a5.varlist assert isinstance(a5.list[0], SCons.Action.CommandAction), a5.list[0] assert a5.list[0].cmd_list == "x", a5.list[0].cmd_list assert a5.list[0].strfunction == foo, a5.list[0].strfunction @@ -1533,7 +1533,8 @@ class FunctionActionTestCase(unittest.TestCase): global count count = count + 1 for t in target: - open(t, 'w').write("function1\n") + with open(t, 'w') as f: + f.write("function1\n") return 1 act = SCons.Action.FunctionAction(function1, {}) @@ -1548,7 +1549,8 @@ class FunctionActionTestCase(unittest.TestCase): class class1a(object): def __init__(self, target, source, env): - open(env['out'], 'w').write("class1a\n") + with open(env['out'], 'w') as f: + f.write("class1a\n") act = SCons.Action.FunctionAction(class1a, {}) r = act([], [], Environment(out = outfile)) @@ -1558,7 +1560,8 @@ class FunctionActionTestCase(unittest.TestCase): class class1b(object): def __call__(self, target, source, env): - open(env['out'], 'w').write("class1b\n") + with open(env['out'], 'w') as f: + f.write("class1b\n") return 2 act = SCons.Action.FunctionAction(class1b(), {}) @@ -1710,17 +1713,20 @@ class ListActionTestCase(unittest.TestCase): cmd2 = r'%s %s %s syzygy' % (_python_, act_py, outfile) def function2(target, source, env): - open(env['out'], 'a').write("function2\n") + with open(env['out'], 'a') as f: + f.write("function2\n") return 0 class class2a(object): def __call__(self, target, source, env): - open(env['out'], 'a').write("class2a\n") + with open(env['out'], 'a') as f: + f.write("class2a\n") return 0 class class2b(object): def __init__(self, target, source, env): - open(env['out'], 'a').write("class2b\n") + with open(env['out'], 'a') as f: + f.write("class2b\n") act = SCons.Action.ListAction([cmd2, function2, class2a(), class2b]) r = act([], [], Environment(out = outfile)) assert isinstance(r.status, class2b), r.status -- cgit v0.12 From 88958d1f4beae35315b26ec1b32b38eeb41946f8 Mon Sep 17 00:00:00 2001 From: Daniel Holth Date: Mon, 6 Jun 2016 20:05:23 -0400 Subject: just throw away __slots__ on pypy --- src/engine/SCons/compat/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/SCons/compat/__init__.py b/src/engine/SCons/compat/__init__.py index 285c4ac..6f20b73 100644 --- a/src/engine/SCons/compat/__init__.py +++ b/src/engine/SCons/compat/__init__.py @@ -178,7 +178,7 @@ class NoSlotsPyPy(type): """ def __new__(meta, name, bases, dct): if PYPY and '__slots__' in dct: - dct['__slats__'] = dct.pop('__slots__') + dct.pop('__slots__') return super(NoSlotsPyPy, meta).__new__(meta, name, bases, dct) -- cgit v0.12 From f8fbe351d2677bc2e4e3094e905c579825c1582a Mon Sep 17 00:00:00 2001 From: Daniel Holth Date: Wed, 15 Jun 2016 19:46:00 -0400 Subject: wrap several frequently-used open() calls in with statements --- src/engine/SCons/Node/FS.py | 4 ++-- src/engine/SCons/Node/__init__.py | 3 ++- src/engine/SCons/Scanner/C.py | 5 ++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index d19afa9..71511b5 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -1211,9 +1211,9 @@ class FS(LocalFS): def getcwd(self): if hasattr(self, "_cwd"): - return self._cwd + return self._cwd else: - return "" + return "" def chdir(self, dir, change_os_dir=0): """Change the current working directory for lookups. diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index e714172..51762a3 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -214,7 +214,8 @@ def get_contents_file(node): return '' fname = node.rfile().get_abspath() try: - contents = open(fname, "rb").read() + with open(fname, "rb") as fp: + contents = fp.read() except EnvironmentError as e: if not e.filename: e.filename = fname diff --git a/src/engine/SCons/Scanner/C.py b/src/engine/SCons/Scanner/C.py index 3b34b88..c2e50a6 100644 --- a/src/engine/SCons/Scanner/C.py +++ b/src/engine/SCons/Scanner/C.py @@ -58,12 +58,11 @@ class SConsCPPScanner(SCons.cpp.PreProcessor): return result def read_file(self, file): try: - fp = open(str(file.rfile())) + with open(str(file.rfile())) as fp: + return fp.read() except EnvironmentError as e: self.missing.append((file, self.current_file)) return '' - else: - return fp.read() def dictify_CPPDEFINES(env): cppdefines = env.get('CPPDEFINES', {}) -- cgit v0.12 From d31cff4a15d3adf3842826c3af8317a2ba050038 Mon Sep 17 00:00:00 2001 From: Daniel Holth Date: Thu, 16 Jun 2016 22:46:03 -0400 Subject: add __main__.py for 'python -m SCons' --- src/engine/SCons/__main__.py | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/engine/SCons/__main__.py diff --git a/src/engine/SCons/__main__.py b/src/engine/SCons/__main__.py new file mode 100644 index 0000000..5a3aadb --- /dev/null +++ b/src/engine/SCons/__main__.py @@ -0,0 +1,5 @@ +if __name__ == "__main__": + import SCons.Script + # this does all the work, and calls sys.exit + # with the proper exit status when done. + SCons.Script.main() -- cgit v0.12 From 16c3e45d786b939f78cf0169be160fd65c679150 Mon Sep 17 00:00:00 2001 From: Daniel Holth Date: Thu, 16 Jun 2016 22:49:38 -0400 Subject: no need for a __main__ guard in __main__.py --- src/engine/SCons/__main__.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/engine/SCons/__main__.py b/src/engine/SCons/__main__.py index 5a3aadb..0dfbb9d 100644 --- a/src/engine/SCons/__main__.py +++ b/src/engine/SCons/__main__.py @@ -1,5 +1,4 @@ -if __name__ == "__main__": - import SCons.Script - # this does all the work, and calls sys.exit - # with the proper exit status when done. - SCons.Script.main() +import SCons.Script +# this does all the work, and calls sys.exit +# with the proper exit status when done. +SCons.Script.main() -- cgit v0.12 From 707a453c9c9db84449c4d3bf214b9ec65f2807db Mon Sep 17 00:00:00 2001 From: Daniel Holth Date: Sun, 19 Jun 2016 22:48:06 -0400 Subject: update CHANGES.txt --- src/CHANGES.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index aab73b4..db52cf0 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -10,6 +10,11 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Whatever John Doe did. + From Daniel Holth: + - Add basic support for PyPy (by deleting __slots__ from Node with a + metaclass on PyPy); wrap most-used open() calls in 'with' statements to + avoid too many open files. + - Add __main__.py for `python -m SCons` in case it is on PYTHONPATH. From Paweł Tomulik: - Fixed the issue with LDMODULEVERSIONFLAGS reported by Tim Jennes -- cgit v0.12 From 1d93e3871ee6858e3bc362aa4e9822c29aadb1a3 Mon Sep 17 00:00:00 2001 From: Daniel Holth Date: Sun, 19 Jun 2016 22:50:06 -0400 Subject: 'with open' in own SConstruct --- SConstruct | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/SConstruct b/SConstruct index 5eded92..c5734af 100644 --- a/SConstruct +++ b/SConstruct @@ -356,7 +356,8 @@ try: if os.path.isfile(dest) or os.path.islink(dest): os.unlink(dest) if not os.path.isdir(dest): - open(dest, 'wb').write(zf.read(name)) + with open(dest, 'wb') as fp: + fp.write(zf.read(name)) except ImportError: if unzip and zip: @@ -371,7 +372,8 @@ def SCons_revision(target, source, env): """ t = str(target[0]) s = source[0].rstr() - contents = open(s, 'rb').read() + with open(s, 'rb') as fp: + contents = fp.read() # Note: We construct the __*__ substitution strings here # so that they don't get replaced when this file gets # copied into the tree for packaging. -- cgit v0.12