summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMats Wichmann <mats@linux.com>2021-11-26 10:25:50 -0700
committerMats Wichmann <mats@linux.com>2021-11-26 11:16:59 -0700
commit9649d0fd2326d607ee545625cea45cf72aab87a6 (patch)
treef1dfbf812ca0624b9836a583d7da6c14af14d450
parentc335e187fb9b2c79fe03489c13cb7859969ed25c (diff)
downloadscons-git-9649d0fd2326d607ee545625cea45cf72aab87a6.tar.gz
Fix tests to not hang on Windows with bad .py assoc
For systems where the association for .py files is not to an actual Python interpreter, those few cases where we need to run a Python script directly as a program don't work. This could be because the association was never set up, or because some other program (e.g. Visual Studio Code) has taken it over. In some cases may appear to "hang" because the alternate program is waiting for user interaction runtest.py now has a mechanism to check (thanks to Brett Cannon for providing this incantation). It isn't super precise (looks for the substring "py" in the queried association), but should work out. It sets an environment variable which the test framework can read and as a result set a flag which individual tests can read. Two tests in scons-time which had previously been set to skip-if-win32 now look at this flag instead. Three tests in sconsign now also look at this flag. This allows a clean run on my dev box with VS Code having taken over the .py association. Various things can break if the environment used to fire off Windows processes doesn't contain %UserProfile%. Added this to the short list of passthrough env vars. Apparently an environment without this value is now considered invalid (it blew up the erroneously launched VS Code, but we've apparently been lucky it hasn't blown up more things - believe there was also a report of a problem with the Visual Studio setup scripts). A little extra cleanup: - a couple of Py2-isms were cleaned out (Script/Main.py and in the test framework) - The paths to look for site-scons were rewritten (part of this was another Py2-ism), and the system path changed a bit - the old path is still checked, and the manpage updated to reflect this. - runtest.py dropped the unused whereis functions. - the three sconsign tests now use f-string formatting, mostly as an experiment to see how easy it is to convert. Fixes #4053 Signed-off-by: Mats Wichmann <mats@linux.com>
-rw-r--r--SCons/Platform/win32.py2
-rw-r--r--SCons/Script/Main.py11
-rw-r--r--doc/man/scons.xml39
-rwxr-xr-xruntest.py72
-rw-r--r--test/scons-time/run/config/python.py10
-rw-r--r--test/scons-time/run/option/python.py11
-rw-r--r--test/sconsign/script/SConsignFile.py44
-rw-r--r--test/sconsign/script/Signatures.py43
-rw-r--r--test/sconsign/script/no-SConsignFile.py72
-rw-r--r--testing/framework/TestCmd.py4
-rw-r--r--testing/framework/TestSCons.py2
-rw-r--r--testing/framework/TestSConsMSVS.py8
12 files changed, 183 insertions, 135 deletions
diff --git a/SCons/Platform/win32.py b/SCons/Platform/win32.py
index eeb2abff4..990794f96 100644
--- a/SCons/Platform/win32.py
+++ b/SCons/Platform/win32.py
@@ -381,7 +381,7 @@ def generate(env):
# for SystemDrive because it's related.
#
# Weigh the impact carefully before adding other variables to this list.
- import_env = ['SystemDrive', 'SystemRoot', 'TEMP', 'TMP' ]
+ import_env = ['SystemDrive', 'SystemRoot', 'TEMP', 'TMP', 'USERPROFILE']
for var in import_env:
v = os.environ.get(var)
if v:
diff --git a/SCons/Script/Main.py b/SCons/Script/Main.py
index c09ebb81d..b873bc2d4 100644
--- a/SCons/Script/Main.py
+++ b/SCons/Script/Main.py
@@ -788,13 +788,12 @@ def _load_all_site_scons_dirs(topdir, verbose=False):
return os.path.expanduser('~/'+d)
if platform == 'win32' or platform == 'cygwin':
- # Note we use $ here instead of %...% because older
- # pythons (prior to 2.6?) didn't expand %...% on Windows.
- # This set of dirs should work on XP, Vista, 7 and later.
sysdirs=[
- os.path.expandvars('$ALLUSERSPROFILE\\Application Data\\scons'),
- os.path.expandvars('$USERPROFILE\\Local Settings\\Application Data\\scons')]
- appdatadir = os.path.expandvars('$APPDATA\\scons')
+ os.path.expandvars('%AllUsersProfile%\\scons'),
+ # TODO older path, kept for compat
+ os.path.expandvars('%AllUsersProfile%\\Application Data\\scons'),
+ os.path.expandvars('%LocalAppData%\\scons')]
+ appdatadir = os.path.expandvars('%AppData%\\scons')
if appdatadir not in sysdirs:
sysdirs.append(appdatadir)
sysdirs.append(homedir('.scons'))
diff --git a/doc/man/scons.xml b/doc/man/scons.xml
index c96d14255..130e1a9a6 100644
--- a/doc/man/scons.xml
+++ b/doc/man/scons.xml
@@ -1729,27 +1729,28 @@ Also suppresses SCons status messages.</para>
</varlistentry>
<varlistentry id="opt-site-dir">
- <term><option>--site-dir=<replaceable>dir</replaceable></option></term>
+ <term><option>--site-dir=<replaceable>path</replaceable></option></term>
<listitem>
-<para>Uses the named <replaceable>dir</replaceable> as the site directory
-rather than the default
-<filename>site_scons</filename>
-directories. This directory will be prepended to
+<para>Use a specific <replaceable>path</replaceable> as the site directory
+rather than searching the list of default site directories.
+This directory will be prepended to
<varname>sys.path</varname>,
the module
-<filename><replaceable>dir</replaceable>/site_init.py</filename>
+<filename><replaceable>path</replaceable>/site_init.py</filename>
will be loaded if it exists, and
-<filename><replaceable>dir</replaceable>/site_tools</filename>
+<filename><replaceable>path</replaceable>/site_tools</filename>
will be added to the default toolpath.</para>
-<para>The default set of
-<filename>site_scons</filename>
-directories used when
+<para>The default set of site directories searched when
<option>--site-dir</option>
is not specified depends on the system platform, as follows.
+Users or system administrators can tune site-specific or
+project-specific &SCons; behavior by setting up a
+site directory in one or more of these locations.
Directories are examined in the order given, from most
-generic to most specific, so the last-executed <filename>site_init.py</filename> file is
-the most specific one (which gives it the chance to override
+generic ("system" directories) to most specific (in the current project),
+so the last-executed <filename>site_init.py</filename> file is
+the most specific one, giving it the chance to override
everything else), and the directories are prepended to the paths, again so
the last directory examined comes first in the resulting path.</para>
@@ -1758,12 +1759,20 @@ the last directory examined comes first in the resulting path.</para>
<term>Windows:</term>
<listitem>
<literallayout class="monospaced">
-%ALLUSERSPROFILE/Application Data/scons/site_scons
-%USERPROFILE%/Local Settings/Application Data/scons/site_scons
+%ALLUSERSPROFILE%/scons/site_scons
+%LOCALAPPDATA%/scons/site_scons
%APPDATA%/scons/site_scons
-%HOME%/.scons/site_scons
+%USERPROFILE%/.scons/site_scons
./site_scons
</literallayout>
+<para>
+Note earlier versions of the documentation listed a different
+path for the "system" site directory, this path is still checked
+but its use is discouraged:
+</para>
+<literallayout class="monospaced">
+%ALLUSERSPROFILE%/Application Data/scons/site_scons
+</literallayout>
</listitem>
</varlistentry>
diff --git a/runtest.py b/runtest.py
index 8d8e10245..54640a10e 100755
--- a/runtest.py
+++ b/runtest.py
@@ -258,31 +258,42 @@ if args.output:
sys.stderr = Tee(logfile, sys.stderr)
# --- define helpers ----
-if sys.platform in ('win32', 'cygwin'):
-
- def whereis(file):
- pathext = [''] + os.environ['PATHEXT'].split(os.pathsep)
- for d in os.environ['PATH'].split(os.pathsep):
- f = os.path.join(d, file)
- for ext in pathext:
- fext = f + ext
- if os.path.isfile(fext):
- return fext
- return None
-
-else:
+if sys.platform == 'win32':
+ # thanks to Bret Cannon for this recipe
+ import ctypes
+
+ shlwapi = ctypes.OleDLL('shlwapi')
+ shlwapi.AssocQueryStringW.argtypes = (
+ ctypes.c_ulong, # flags
+ ctypes.c_ulong, # str
+ ctypes.c_wchar_p, # pszAssoc
+ ctypes.c_wchar_p, # pszExtra
+ ctypes.c_wchar_p, # pszOut
+ ctypes.POINTER(ctypes.c_ulong), # pcchOut
+ )
- def whereis(file):
- for d in os.environ['PATH'].split(os.pathsep):
- f = os.path.join(d, file)
- if os.path.isfile(f):
- try:
- st = os.stat(f)
- except OSError:
- continue
- if stat.S_IMODE(st[stat.ST_MODE]) & 0o111:
- return f
- return None
+ ASSOCF_NOTRUNCATE = 0x00000020
+ ASSOCF_INIT_IGNOREUNKNOWN = 0x00000400
+ ASSOCSTR_COMMAND = 1
+ ASSOCSTR_EXECUTABLE = 2
+ E_POINTER = ctypes.c_long(0x80004003).value
+
+ def get_template_command(filetype, verb=None):
+ flags = ASSOCF_INIT_IGNOREUNKNOWN | ASSOCF_NOTRUNCATE
+ assoc_str = ASSOCSTR_COMMAND
+ cch = ctypes.c_ulong(260)
+ while True:
+ buf = (ctypes.c_wchar * cch.value)()
+ try:
+ shlwapi.AssocQueryStringW(
+ flags, assoc_str, filetype, verb, buf, ctypes.byref(cch)
+ )
+ except OSError as e:
+ if e.winerror != E_POINTER:
+ raise
+ continue
+ break
+ return buf.value
_ws = re.compile(r'\s')
@@ -528,6 +539,19 @@ pythonpath = os.environ.get('PYTHONPATH')
if pythonpath:
testenv['PYTHONPATH'] = testenv['PYTHONPATH'] + os.pathsep + pythonpath
+if sys.platform == 'win32':
+ # Windows doesn't support "shebang" lines directly (the Python launcher
+ # and Windows Store version do, but you have to get them launched first)
+ # so to directly launch a script we depend on an assoc for .py to work.
+ # Some systems may have none, and in some cases IDE programs take over
+ # the assoc. Detect this so the small number of tests affected can skip.
+ try:
+ python_assoc = get_template_command('.py')
+ except OSError:
+ python_assoc = None
+ if not python_assoc or "py" not in python_assoc:
+ testenv['SCONS_NO_DIRECT_SCRIPT'] = '1'
+
os.environ.update(testenv)
# Clear _JAVA_OPTIONS which java tools output to stderr when run breaking tests
diff --git a/test/scons-time/run/config/python.py b/test/scons-time/run/config/python.py
index ac6d1e39d..f1b8fb2e5 100644
--- a/test/scons-time/run/config/python.py
+++ b/test/scons-time/run/config/python.py
@@ -30,14 +30,14 @@ Verify specifying an alternate Python executable in a config file.
import os
import TestSCons_time
-from TestCmd import IS_WINDOWS
-_python_ = TestSCons_time._python_
+from TestCmd import NEED_HELPER
+from TestSCons_time import _python_
test = TestSCons_time.TestSCons_time()
-if IS_WINDOWS:
- # tests expect Windows file assoc to run my_python, not in our control.
- test.skip_test("Skipping test on win32 due to launch problems.")
+
+if NEED_HELPER:
+ test.skip_test("Test host cannot directly execute scripts, skipping test\n")
test.write_sample_project('foo.tar.gz')
diff --git a/test/scons-time/run/option/python.py b/test/scons-time/run/option/python.py
index d117f2c51..d10267ac6 100644
--- a/test/scons-time/run/option/python.py
+++ b/test/scons-time/run/option/python.py
@@ -30,14 +30,15 @@ Verify the run --python option to specify an alternatie Python executable.
import os
import TestSCons_time
-from TestCmd import IS_WINDOWS
-_python_ = TestSCons_time._python_
+from TestCmd import NEED_HELPER
+from TestCmd import IS_WINDOWS
+from TestSCons_time import _python_
test = TestSCons_time.TestSCons_time()
-if IS_WINDOWS:
- # tests expect Windows file assoc to run my_python, not in our control.
- test.skip_test("Skipping test on win32 due to launch problems.")
+
+if NEED_HELPER:
+ test.skip_test("Test host cannot directly execute scripts, skipping test\n")
test.write_sample_project('foo.tar.gz')
diff --git a/test/sconsign/script/SConsignFile.py b/test/sconsign/script/SConsignFile.py
index 4e29ef067..569e5e689 100644
--- a/test/sconsign/script/SConsignFile.py
+++ b/test/sconsign/script/SConsignFile.py
@@ -31,15 +31,20 @@ using the signatures in an SConsignFile().
import TestSCons
import TestSConsign
-_python_ = TestSCons._python_
+from TestSCons import _python_
+from TestCmd import NEED_HELPER
test = TestSConsign.TestSConsign(match = TestSConsign.match_re)
+
+if NEED_HELPER:
+ test.skip_test("Test host cannot directly execute scripts, skipping test\n")
+
test.subdir('sub1', 'sub2')
fake_cc_py = test.workpath('fake_cc.py')
fake_link_py = test.workpath('fake_link.py')
-test.write(fake_cc_py, r"""#!%(_python_)s
+test.write(fake_cc_py, fr"""#!{_python_}
import os
import re
import sys
@@ -66,21 +71,23 @@ def process(infp, outfp):
outfp.write(line)
with open(sys.argv[2], 'w') as outf, open(sys.argv[3], 'r') as ifp:
- outf.write('fake_cc.py: %%s\n' %% sys.argv)
+ outf.write('fake_cc.py: %s\n' % sys.argv)
process(ifp, outf)
sys.exit(0)
-""" % locals())
+"""
+)
-test.write(fake_link_py, r"""#!%(_python_)s
+test.write(fake_link_py, fr"""#!{_python_}
import sys
with open(sys.argv[1], 'w') as outf, open(sys.argv[2], 'r') as ifp:
- outf.write('fake_link.py: %%s\n' %% sys.argv)
+ outf.write('fake_link.py: %s\n' % sys.argv)
outf.write(ifp.read())
sys.exit(0)
-""" % locals())
+"""
+)
test.chmod(fake_cc_py, 0o755)
test.chmod(fake_link_py, 0o755)
@@ -96,24 +103,27 @@ sub2_hello_obj = 'sub2/hello.obj'
sub2_inc1_h = 'sub2/inc1.h'
sub2_inc2_h = 'sub2/inc2.h'
-test.write(['SConstruct'], """\
+test.write(['SConstruct'], f"""\
SConsignFile()
env1 = Environment(
PROGSUFFIX='.exe',
OBJSUFFIX='.obj',
- CCCOM=[[r'%(fake_cc_py)s', 'sub2', '$TARGET', '$SOURCE']],
- LINKCOM=[[r'%(fake_link_py)s', '$TARGET', '$SOURCE']],
+ CCCOM=[[r'{fake_cc_py}', 'sub2', '$TARGET', '$SOURCE']],
+ LINKCOM=[[r'{fake_link_py}', '$TARGET', '$SOURCE']],
)
env1.PrependENVPath('PATHEXT', '.PY')
env1.Program('sub1/hello.c')
env2 = env1.Clone(CPPPATH=['sub2'])
env2.Program('sub2/hello.c')
-""" % locals())
+"""
+)
# TODO in the above, we would normally want to run a python program
-# using "our python" as in:
-# CCCOM=[[r'%(_python_)s', r'%(fake_cc_py)s', 'sub2', '$TARGET', '$SOURCE']],
-# LINKCOM=[[r'%(_python_)s', r'%(fake_link_py)s', '$TARGET', '$SOURCE']],
-# however we're looking at dependencies with sconsign, so that breaks things
+# using "our python" like this:
+# CCCOM=[[r'{_python_}', r'{fake_cc_py}', 'sub2', '$TARGET', '$SOURCE']],
+# LINKCOM=[[r'{_python_}', r'{fake_link_py}', '$TARGET', '$SOURCE']],
+# however we're looking at dependencies with sconsign, so that breaks things.
+# It still breaks things on Windows if something else is registered as the
+# handler for .py files, as Visual Studio Code installs itself.
test.write(['sub1', 'hello.c'], r"""
sub1/hello.c
@@ -131,11 +141,11 @@ main(int argc, char *argv[])
}
""")
-test.write(['sub2', 'inc1.h'], r"""\
+test.write(['sub2', 'inc1.h'], r"""
#define STRING1 "inc1.h"
""")
-test.write(['sub2', 'inc2.h'], r"""\
+test.write(['sub2', 'inc2.h'], r"""
#define STRING2 "inc2.h"
""")
diff --git a/test/sconsign/script/Signatures.py b/test/sconsign/script/Signatures.py
index ced5b44f3..b5db3f94e 100644
--- a/test/sconsign/script/Signatures.py
+++ b/test/sconsign/script/Signatures.py
@@ -32,10 +32,14 @@ value of Decider('timestamp-newer').
import TestSCons
import TestSConsign
-_python_ = TestSCons._python_
+from TestSCons import _python_
+from TestCmd import NEED_HELPER
test = TestSConsign.TestSConsign(match = TestSConsign.match_re)
+if NEED_HELPER:
+ test.skip_test("Test host cannot directly execute scripts, skipping test\n")
+
# Note: We don't use os.path.join() representations of the file names
# in the expected output because paths in the .sconsign files are
# canonicalized to use / as the separator.
@@ -58,7 +62,7 @@ test.subdir('sub1', 'sub2')
fake_cc_py = test.workpath('fake_cc.py')
fake_link_py = test.workpath('fake_link.py')
-test.write(fake_cc_py, r"""#!%(_python_)s
+test.write(fake_cc_py, fr"""#!{_python_}
import os
import re
import sys
@@ -85,26 +89,28 @@ def process(infp, outfp):
outfp.write(line)
with open(sys.argv[2], 'w') as outf, open(sys.argv[3], 'r') as ifp:
- outf.write('fake_cc.py: %%s\n' %% sys.argv)
+ outf.write('fake_cc.py: %s\n' % sys.argv)
process(ifp, outf)
sys.exit(0)
-""" % locals())
+"""
+)
-test.write(fake_link_py, r"""#!%(_python_)s
+test.write(fake_link_py, fr"""#!{_python_}
import sys
with open(sys.argv[1], 'w') as outf, open(sys.argv[2], 'r') as ifp:
- outf.write('fake_link.py: %%s\n' %% sys.argv)
+ outf.write('fake_link.py: %s\n' % sys.argv)
outf.write(ifp.read())
sys.exit(0)
-""" % locals())
+"""
+)
test.chmod(fake_cc_py, 0o755)
test.chmod(fake_link_py, 0o755)
-test.write('SConstruct', """
+test.write('SConstruct', f"""
SConsignFile(None)
Decider('timestamp-newer')
env1 = Environment(
@@ -113,19 +119,22 @@ env1 = Environment(
# Specify the command lines with lists-of-lists so
# finding the implicit dependencies works even with
# spaces in the fake_*_py path names.
- CCCOM=[[r'%(fake_cc_py)s', 'sub2', '$TARGET', '$SOURCE']],
- LINKCOM=[[r'%(fake_link_py)s', '$TARGET', '$SOURCE']],
+ CCCOM=[[r'{fake_cc_py}', 'sub2', '$TARGET', '$SOURCE']],
+ LINKCOM=[[r'{fake_link_py}', '$TARGET', '$SOURCE']],
)
env1.PrependENVPath('PATHEXT', '.PY')
env1.Program('sub1/hello.c')
env2 = env1.Clone(CPPPATH=['sub2'])
env2.Program('sub2/hello.c')
-""" % locals())
+"""
+)
# TODO in the above, we would normally want to run a python program
-# using "our python" as in:
-# CCCOM=[[r'%(_python_)s', r'%(fake_cc_py)s', 'sub2', '$TARGET', '$SOURCE']],
-# LINKCOM=[[r'%(_python_)s', r'%(fake_link_py)s', '$TARGET', '$SOURCE']],
-# however we're looking at dependencies with sconsign, so that breaks things
+# using "our python" like this:
+# CCCOM=[[r'{_python_}', r'{fake_cc_py}', 'sub2', '$TARGET', '$SOURCE']],
+# LINKCOM=[[r'{_python_}', r'{fake_link_py}', '$TARGET', '$SOURCE']],
+# however we're looking at dependencies with sconsign, so that breaks things.
+# It still breaks things on Windows if something else is registered as the
+# handler for .py files, as Visual Studio Code installs itself.
test.write(['sub1', 'hello.c'], r"""\
sub1/hello.c
@@ -154,7 +163,7 @@ date_re = r'\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d'
database_name = test.get_sconsignname()
-test.run_sconsign(arguments = "-e hello.exe -e hello.obj sub1/{}".format(database_name),
+test.run_sconsign(arguments = f"-e hello.exe -e hello.obj sub1/{database_name}",
stdout = r"""hello.exe: %(sig_re)s \d+ \d+
%(sub1_hello_obj)s: %(sig_re)s \d+ \d+
fake_link\.py: None \d+ \d+
@@ -165,7 +174,7 @@ hello.obj: %(sig_re)s \d+ \d+
%(sig_re)s \[.*\]
""" % locals())
-test.run_sconsign(arguments = "-e hello.exe -e hello.obj -r sub1/{}".format(database_name),
+test.run_sconsign(arguments = f"-e hello.exe -e hello.obj -r sub1/{database_name}",
stdout = r"""hello.exe: %(sig_re)s '%(date_re)s' \d+
%(sub1_hello_obj)s: %(sig_re)s '%(date_re)s' \d+
fake_link\.py: None '%(date_re)s' \d+
diff --git a/test/sconsign/script/no-SConsignFile.py b/test/sconsign/script/no-SConsignFile.py
index bdd878bcc..f06a2d074 100644
--- a/test/sconsign/script/no-SConsignFile.py
+++ b/test/sconsign/script/no-SConsignFile.py
@@ -22,9 +22,6 @@
# 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 the sconsign script works when using an individual
@@ -34,10 +31,14 @@ Verify that the sconsign script works when using an individual
import TestSCons
import TestSConsign
-_python_ = TestSCons._python_
+from TestSCons import _python_
+from TestCmd import NEED_HELPER
test = TestSConsign.TestSConsign(match = TestSConsign.match_re)
+if NEED_HELPER:
+ test.skip_test("Test host cannot directly execute scripts, skipping test\n")
+
test.subdir('sub1', 'sub2')
database_name = test.get_sconsignname()
@@ -55,7 +56,7 @@ database_name = test.get_sconsignname()
fake_cc_py = test.workpath('fake_cc.py')
fake_link_py = test.workpath('fake_link.py')
-test.write(fake_cc_py, r"""#!%(_python_)s
+test.write(fake_cc_py, fr"""#!{_python_}
import os
import re
import sys
@@ -82,21 +83,23 @@ def process(infp, outfp):
outfp.write(line)
with open(sys.argv[2], 'w') as outf, open(sys.argv[3], 'r') as ifp:
- outf.write('fake_cc.py: %%s\n' %% sys.argv)
+ outf.write('fake_cc.py: %s\n' % sys.argv)
process(ifp, outf)
sys.exit(0)
-""" % locals())
+"""
+)
-test.write(fake_link_py, r"""#!%(_python_)s
+test.write(fake_link_py, fr"""#!{_python_}
import sys
with open(sys.argv[1], 'w') as outf, open(sys.argv[2], 'r') as ifp:
- outf.write('fake_link.py: %%s\n' %% sys.argv)
+ outf.write('fake_link.py: %s\n' % sys.argv)
outf.write(ifp.read())
sys.exit(0)
-""" % locals())
+"""
+)
test.chmod(fake_cc_py, 0o755)
test.chmod(fake_link_py, 0o755)
@@ -112,7 +115,7 @@ sub2_hello_obj = 'sub2/hello.obj'
sub2_inc1_h = 'sub2/inc1.h'
sub2_inc2_h = 'sub2/inc2.h'
-test.write(['SConstruct'], """
+test.write(['SConstruct'], f"""
SConsignFile(None)
env1 = Environment(
PROGSUFFIX='.exe',
@@ -120,35 +123,38 @@ env1 = Environment(
# Specify the command lines with lists-of-lists so
# finding the implicit dependencies works even with
# spaces in the fake_*_py path names.
- CCCOM=[[r'%(fake_cc_py)s', 'sub2', '$TARGET', '$SOURCE']],
- LINKCOM=[[r'%(fake_link_py)s', '$TARGET', '$SOURCE']],
+ CCCOM=[[r'{fake_cc_py}', 'sub2', '$TARGET', '$SOURCE']],
+ LINKCOM=[[r'{fake_link_py}', '$TARGET', '$SOURCE']],
)
env1.PrependENVPath('PATHEXT', '.PY')
env1.Program('sub1/hello.c')
env2 = env1.Clone(CPPPATH=['sub2'])
env2.Program('sub2/hello.c')
-""" % locals())
+"""
+)
# TODO in the above, we would normally want to run a python program
-# using "our python" as in:
-# CCCOM=[[r'%(_python_)s', r'%(fake_cc_py)s', 'sub2', '$TARGET', '$SOURCE']],
-# LINKCOM=[[r'%(_python_)s', r'%(fake_link_py)s', '$TARGET', '$SOURCE']],
-# however we're looking at dependencies with sconsign, so that breaks things
-
-test.write(['sub1', 'hello.c'], r"""\
+# using "our python" like this:
+# CCCOM=[[r'{_python_}', r'{fake_cc_py}', 'sub2', '$TARGET', '$SOURCE']],
+# LINKCOM=[[r'{_python_}', r'{fake_link_py}', '$TARGET', '$SOURCE']],
+# however we're looking at dependencies with sconsign, so that breaks things.
+# It still breaks things on Windows if something else is registered as the
+# handler for .py files, as Visual Studio Code installs itself.
+
+test.write(['sub1', 'hello.c'], r"""
sub1/hello.c
""")
-test.write(['sub2', 'hello.c'], r"""\
+test.write(['sub2', 'hello.c'], r"""
#include <inc1.h>
#include <inc2.h>
sub2/hello.c
""")
-test.write(['sub2', 'inc1.h'], r"""\
+test.write(['sub2', 'inc1.h'], r"""
#define STRING1 "inc1.h"
""")
-test.write(['sub2', 'inc2.h'], r"""\
+test.write(['sub2', 'inc2.h'], r"""
#define STRING2 "inc2.h"
""")
@@ -167,9 +173,9 @@ hello.obj: %(sig_re)s \d+ \d+
%(sig_re)s \[.*\]
""" % locals()
-test.run_sconsign(arguments = "sub1/{}".format(database_name), stdout=expect)
+test.run_sconsign(arguments = f"sub1/{database_name}", stdout=expect)
-test.run_sconsign(arguments = "--raw sub1/{}".format(database_name),
+test.run_sconsign(arguments = f"--raw sub1/{database_name}",
stdout = r"""hello.c: {'csig': '%(sig_re)s', 'timestamp': \d+L?, 'size': \d+L?, '_version_id': 2}
hello.exe: {'csig': '%(sig_re)s', 'timestamp': \d+L?, 'size': \d+L?, '_version_id': 2}
%(sub1_hello_obj)s: {'csig': '%(sig_re)s', 'timestamp': \d+L?, 'size': \d+L?, '_version_id': 2}
@@ -181,7 +187,7 @@ hello.obj: {'csig': '%(sig_re)s', 'timestamp': \d+L?, 'size': \d+L?, '_version_i
%(sig_re)s \[.*\]
""" % locals())
-test.run_sconsign(arguments = "-v sub1/{}".format(database_name),
+test.run_sconsign(arguments = f"-v sub1/{database_name}",
stdout = r"""hello.c:
csig: %(sig_re)s
timestamp: \d+
@@ -216,7 +222,7 @@ hello.obj:
action: %(sig_re)s \[.*\]
""" % locals())
-test.run_sconsign(arguments = "-c -v sub1/{}".format(database_name),
+test.run_sconsign(arguments = f"-c -v sub1/{database_name}",
stdout = r"""hello.c:
csig: %(sig_re)s
hello.exe:
@@ -225,7 +231,7 @@ hello.obj:
csig: %(sig_re)s
""" % locals())
-test.run_sconsign(arguments = "-s -v sub1/{}".format(database_name),
+test.run_sconsign(arguments = f"-s -v sub1/{database_name}",
stdout = r"""hello.c:
size: \d+
hello.exe:
@@ -234,7 +240,7 @@ hello.obj:
size: \d+
""" % locals())
-test.run_sconsign(arguments = "-t -v sub1/{}".format(database_name),
+test.run_sconsign(arguments = f"-t -v sub1/{database_name}",
stdout = r"""hello.c:
timestamp: \d+
hello.exe:
@@ -243,14 +249,14 @@ hello.obj:
timestamp: \d+
""" % locals())
-test.run_sconsign(arguments = "-e hello.obj sub1/{}".format(database_name),
+test.run_sconsign(arguments = f"-e hello.obj sub1/{database_name}",
stdout = r"""hello.obj: %(sig_re)s \d+ \d+
%(sub1_hello_c)s: %(sig_re)s \d+ \d+
fake_cc\.py: %(sig_re)s \d+ \d+
%(sig_re)s \[.*\]
""" % locals())
-test.run_sconsign(arguments = "-e hello.obj -e hello.exe -e hello.obj sub1/{}".format(database_name),
+test.run_sconsign(arguments = f"-e hello.obj -e hello.exe -e hello.obj sub1/{database_name}",
stdout = r"""hello.obj: %(sig_re)s \d+ \d+
%(sub1_hello_c)s: %(sig_re)s \d+ \d+
fake_cc\.py: %(sig_re)s \d+ \d+
@@ -265,7 +271,7 @@ hello.obj: %(sig_re)s \d+ \d+
%(sig_re)s \[.*\]
""" % locals())
-test.run_sconsign(arguments = "sub2/{}".format(database_name),
+test.run_sconsign(arguments = f"sub2/{database_name}",
stdout = r"""hello.c: %(sig_re)s \d+ \d+
hello.exe: %(sig_re)s \d+ \d+
%(sub2_hello_obj)s: %(sig_re)s \d+ \d+
@@ -293,7 +299,7 @@ inc2.h: %(sig_re)s \d+ \d+
# inc2.h: %(sig_re)s \d+ \d+
#""" % locals())
-test.run_sconsign(arguments = "-e hello.obj sub2/{} sub1/{}".format(database_name, database_name),
+test.run_sconsign(arguments = f"-e hello.obj sub2/{database_name} sub1/{database_name}",
stdout = r"""hello.obj: %(sig_re)s \d+ \d+
%(sub2_hello_c)s: %(sig_re)s \d+ \d+
%(sub2_inc1_h)s: %(sig_re)s \d+ \d+
diff --git a/testing/framework/TestCmd.py b/testing/framework/TestCmd.py
index 903bee693..79b16f561 100644
--- a/testing/framework/TestCmd.py
+++ b/testing/framework/TestCmd.py
@@ -312,17 +312,15 @@ import traceback
from collections import UserList, UserString
from subprocess import PIPE, STDOUT
-
IS_WINDOWS = sys.platform == 'win32'
IS_MACOS = sys.platform == 'darwin'
IS_64_BIT = sys.maxsize > 2**32
IS_PYPY = hasattr(sys, 'pypy_translation_info')
-
+NEED_HELPER = os.environ.get('SCONS_NO_DIRECT_SCRIPT')
# sentinel for cases where None won't do
_Null = object()
-
__all__ = [
'diff_re',
'fail_test',
diff --git a/testing/framework/TestSCons.py b/testing/framework/TestSCons.py
index 99764c577..b6b969441 100644
--- a/testing/framework/TestSCons.py
+++ b/testing/framework/TestSCons.py
@@ -307,8 +307,6 @@ class TestSCons(TestCommon):
kw['program'] = os.path.join(self.orig_cwd, kw['program'])
if 'interpreter' not in kw and not os.environ.get('SCONS_EXEC'):
kw['interpreter'] = [python, ]
- if sys.version_info[0] < 3:
- kw['interpreter'].append('-tt')
if 'match' not in kw:
kw['match'] = match_exact
if 'workdir' not in kw:
diff --git a/testing/framework/TestSConsMSVS.py b/testing/framework/TestSConsMSVS.py
index fc0a411b1..6e5e01bca 100644
--- a/testing/framework/TestSConsMSVS.py
+++ b/testing/framework/TestSConsMSVS.py
@@ -763,8 +763,7 @@ print("self._msvs_versions =%%s"%%str(SCons.Tool.MSCommon.query_versions()))
return result
def get_vs_host_arch(self):
- """ Get an MSVS, SDK , and/or MSVS acceptable platform arch
- """
+ """ Returns an MSVS, SDK , and/or MSVS acceptable platform arch. """
# Dict to 'canonalize' the arch
_ARCH_TO_CANONICAL = {
@@ -778,11 +777,6 @@ print("self._msvs_versions =%%s"%%str(SCons.Tool.MSCommon.query_versions()))
}
host_platform = platform.machine()
- # TODO(2.5): the native Python platform.machine() function returns
- # '' on all Python versions before 2.6, after which it also uses
- # PROCESSOR_ARCHITECTURE.
- if not host_platform:
- host_platform = os.environ.get('PROCESSOR_ARCHITECTURE', '')
try:
host = _ARCH_TO_CANONICAL[host_platform]