summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMats Wichmann <mats@linux.com>2022-07-17 14:38:07 (GMT)
committerMats Wichmann <mats@linux.com>2022-07-17 17:15:34 (GMT)
commit56d95dcd2af886e04abe1f94a8cb582cd5b9a28a (patch)
tree6dac127968aae5a00a5df57a841424c0a262bf83
parent767abe618f636e2e00b614f0510f2eaa208fb28e (diff)
downloadSCons-56d95dcd2af886e04abe1f94a8cb582cd5b9a28a.zip
SCons-56d95dcd2af886e04abe1f94a8cb582cd5b9a28a.tar.gz
SCons-56d95dcd2af886e04abe1f94a8cb582cd5b9a28a.tar.bz2
Stop using deprecated load_module
importlib.load_module is deprecated since 3.10 and scheduled for removal in the 2023 Python release (3.12) - this makes the tests somewhat noisy. The zip import code was reworked, to use exec_module. A test was added in the Platform code - there's now a dummy platform module inside a zip file that the PlatformTests unittest uses. The tool import code finally dropped the fallback to Python2-style importing, and the zip import section matches the (now tested) Platform version. Not sure this is needed at all: the regular import machinery ought to find a zipfile without extra steps, since here it uses sys.path (the platform code does *not* use sys.path). sconsign now just uses import_module, the "my_import" function is no longer needed but was left in for now. sconsign actually used the "imp" module, which is deprecated since 3.4. A little cleaup in the three scripts/ files. Fixes #4162 Signed-off-by: Mats Wichmann <mats@linux.com>
-rw-r--r--SCons/Platform/PlatformTests.py11
-rw-r--r--SCons/Platform/__init__.py47
-rw-r--r--SCons/Platform/testzip.zipbin0 -> 1142 bytes
-rw-r--r--SCons/Tool/__init__.py67
-rw-r--r--SCons/Utilities/sconsign.py71
-rw-r--r--scripts/scons-configure-cache.py8
-rwxr-xr-xscripts/scons.py3
-rw-r--r--scripts/sconsign.py6
8 files changed, 110 insertions, 103 deletions
diff --git a/SCons/Platform/PlatformTests.py b/SCons/Platform/PlatformTests.py
index bdb8996..195243a 100644
--- a/SCons/Platform/PlatformTests.py
+++ b/SCons/Platform/PlatformTests.py
@@ -112,6 +112,13 @@ class PlatformTestCase(unittest.TestCase):
assert env['HOST_OS'] == 'hpux', env
assert env['HOST_ARCH'] != '', env
+ p = SCons.Platform.Platform('testzip')
+ assert str(p) == 'testzip', p
+ env = Environment()
+ p(env)
+ assert env['HOST_OS'] == 'zippy', env
+ assert env['TESTDUMMY'] == 1866, env
+
p = SCons.Platform.Platform('win32')
assert str(p) == 'win32', p
env = Environment()
@@ -159,10 +166,6 @@ class PlatformTestCase(unittest.TestCase):
assert p.synonyms != '', 'SCons.Platform.win32.get_architecture() not setting synonyms'
-
-
-
-
class TempFileMungeTestCase(unittest.TestCase):
def test_MAXLINELENGTH(self):
""" Test different values for MAXLINELENGTH with the same
diff --git a/SCons/Platform/__init__.py b/SCons/Platform/__init__.py
index 93c5cd3..e3da6ed 100644
--- a/SCons/Platform/__init__.py
+++ b/SCons/Platform/__init__.py
@@ -83,7 +83,7 @@ def platform_default():
return sys.platform
-def platform_module(name = platform_default()):
+def platform_module(name=platform_default()):
"""Return the imported module for the platform.
This looks for a module name that matches the specified argument.
@@ -91,27 +91,34 @@ def platform_module(name = platform_default()):
our execution environment.
"""
full_name = 'SCons.Platform.' + name
- if full_name not in sys.modules:
- if os.name == 'java':
- eval(full_name)
- else:
+ try:
+ return sys.modules[full_name]
+ except KeyError:
+ try:
+ # the specific platform module is a relative import
+ mod = importlib.import_module("." + name, __name__)
+ except ModuleNotFoundError:
try:
- # the specific platform module is a relative import
- mod = importlib.import_module("." + name, __name__)
- except ImportError:
- try:
- import zipimport
- importer = zipimport.zipimporter( sys.modules['SCons.Platform'].__path__[0] )
- mod = importer.load_module(full_name)
- except ImportError:
- raise SCons.Errors.UserError("No platform named '%s'" % name)
- setattr(SCons.Platform, name, mod)
- return sys.modules[full_name]
+ # because we don't do this import using sys.path,
+ # need to try zipimport explicitly.
+ import zipimport
+
+ parent = sys.modules['SCons.Platform'].__path__[0]
+ tryname = os.path.join(parent, name + '.zip')
+ importer = zipimport.zipimporter(tryname)
+ spec = importer.find_spec(full_name)
+ mod = importlib.util.module_from_spec(spec)
+ sys.modules[full_name] = mod
+ importer.exec_module(mod)
+ except zipimport.ZipImportError:
+ raise SCons.Errors.UserError("No platform named '%s'" % name)
+
+ setattr(SCons.Platform, name, mod)
+ return mod
def DefaultToolList(platform, env):
- """Select a default tool list for the specified platform.
- """
+ """Select a default tool list for the specified platform."""
return SCons.Tool.tool_list(platform, env)
@@ -328,8 +335,8 @@ class TempFileMunge:
def Platform(name = platform_default()):
- """Select a canned Platform specification.
- """
+ """Select a canned Platform specification."""
+
module = platform_module(name)
spec = PlatformSpec(name, module.generate)
return spec
diff --git a/SCons/Platform/testzip.zip b/SCons/Platform/testzip.zip
new file mode 100644
index 0000000..05d1b1c
--- /dev/null
+++ b/SCons/Platform/testzip.zip
Binary files differ
diff --git a/SCons/Tool/__init__.py b/SCons/Tool/__init__.py
index 8e4a22d..b618b22 100644
--- a/SCons/Tool/__init__.py
+++ b/SCons/Tool/__init__.py
@@ -120,32 +120,16 @@ class Tool:
if hasattr(module, 'options'):
self.options = module.options
- def _load_dotted_module_py2(self, short_name, full_name, searchpaths=None):
- import imp
-
- splitname = short_name.split('.')
- index = 0
- srchpths = searchpaths
- for item in splitname:
- file, path, desc = imp.find_module(item, srchpths)
- mod = imp.load_module(full_name, file, path, desc)
- srchpths = [path]
- return mod, file
-
def _tool_module(self):
+ """Try to load a tool module.
+
+ This will hunt in the toolpath for both a Python file (toolname.py)
+ and a Python module (toolname directory), then try the regular
+ import machinery, then fallback to try a zipfile.
+ """
oldpythonpath = sys.path
sys.path = self.toolpath + sys.path
- # sys.stderr.write("Tool:%s\nPATH:%s\n"%(self.name,sys.path))
-
- # From: http://stackoverflow.com/questions/67631/how-to-import-a-module-given-the-full-path/67692#67692
- # import importlib.util
- # spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")
- # foo = importlib.util.module_from_spec(spec)
- # spec.loader.exec_module(foo)
- # foo.MyClass()
- # Py 3 code
-
-
+ # sys.stderr.write("Tool:%s\nPATH:%s\n" % (self.name,sys.path))
# sys.stderr.write("toolpath:%s\n" % self.toolpath)
# sys.stderr.write("SCONS.TOOL path:%s\n" % sys.modules['SCons.Tool'].__path__)
debug = False
@@ -203,19 +187,19 @@ class Tool:
# Not sure what to do in the case that there already
# exists sys.modules[self.name] but the source file is
# different.. ?
- module = spec.loader.load_module(spec.name)
-
sys.modules[found_name] = module
+ spec.loader.exec_module(module)
if add_to_scons_tools_namespace:
# If we found it in SCons.Tool, then add it to the module
setattr(SCons.Tool, self.name, module)
-
found_module = module
if found_module is not None:
sys.path = oldpythonpath
return found_module
+ # we didn't find the module, go back and try some other things
+ # was this name previously imported? Is there a zipfile?
sys.path = oldpythonpath
full_name = 'SCons.Tool.' + self.name
@@ -223,26 +207,17 @@ class Tool:
return sys.modules[full_name]
except KeyError:
try:
- smpath = sys.modules['SCons.Tool'].__path__
- try:
- module, file = self._load_dotted_module_py2(self.name, full_name, smpath)
- setattr(SCons.Tool, self.name, module)
- if file:
- file.close()
- return module
- except ImportError as e:
- if str(e) != "No module named %s" % self.name:
- raise SCons.Errors.SConsEnvironmentError(e)
- try:
- import zipimport
- importer = zipimport.zipimporter(sys.modules['SCons.Tool'].__path__[0])
- module = importer.load_module(full_name)
- setattr(SCons.Tool, self.name, module)
- return module
- except ImportError as e:
- m = "No tool named '%s': %s" % (self.name, e)
- raise SCons.Errors.SConsEnvironmentError(m)
- except ImportError as e:
+ import zipimport
+ parent = sys.modules['SCons.Tool'].__path__[0]
+ tryname = os.path.join(parent, name + '.zip')
+ importer = zipimport.zipimporter(tryname)
+ spec = importer.find_spec(full_name)
+ module = importlib.util.module_from_spec(spec)
+ sys.modules[full_name] = module
+ importer.exec_module(module)
+ setattr(SCons.Tool, self.name, module)
+ return module
+ except zipimporter.ZipImportError as e:
m = "No tool named '%s': %s" % (self.name, e)
raise SCons.Errors.SConsEnvironmentError(m)
diff --git a/SCons/Utilities/sconsign.py b/SCons/Utilities/sconsign.py
index e595b2d..4cb598d 100644
--- a/SCons/Utilities/sconsign.py
+++ b/SCons/Utilities/sconsign.py
@@ -51,13 +51,18 @@ def my_whichdb(filename):
def my_import(mname):
+ """Import database module.
+
+ This was used if the module was *not* SCons.dblite, to allow
+ for programmatic importing. It is no longer used, in favor of
+ importlib.import_module, and will be removed eventually.
+ """
import imp
if '.' in mname:
i = mname.rfind('.')
parent = my_import(mname[:i])
- fp, pathname, description = imp.find_module(mname[i+1:],
- parent.__path__)
+ fp, pathname, description = imp.find_module(mname[i+1:], parent.__path__)
else:
fp, pathname, description = imp.find_module(mname)
return imp.load_module(mname, fp, pathname, description)
@@ -371,36 +376,50 @@ def Do_SConsignDir(name):
##############################################################################
def main():
- global Do_Call
+ global Do_Call
global nodeinfo_string
global args
global Verbose
global Readable
helpstr = """\
- Usage: sconsign [OPTIONS] [FILE ...]
- Options:
- -a, --act, --action Print build action information.
- -c, --csig Print content signature information.
- -d DIR, --dir=DIR Print only info about DIR.
- -e ENTRY, --entry=ENTRY Print only info about ENTRY.
- -f FORMAT, --format=FORMAT FILE is in the specified FORMAT.
- -h, --help Print this message and exit.
- -i, --implicit Print implicit dependency information.
- -r, --readable Print timestamps in human-readable form.
- --raw Print raw Python object representations.
- -s, --size Print file sizes.
- -t, --timestamp Print timestamp information.
- -v, --verbose Verbose, describe each field.
- """
+Usage: sconsign [OPTIONS] [FILE ...]
+
+Options:
+ -a, --act, --action Print build action information.
+ -c, --csig Print content signature information.
+ -d DIR, --dir=DIR Print only info about DIR.
+ -e ENTRY, --entry=ENTRY Print only info about ENTRY.
+ -f FORMAT, --format=FORMAT FILE is in the specified FORMAT.
+ -h, --help Print this message and exit.
+ -i, --implicit Print implicit dependency information.
+ -r, --readable Print timestamps in human-readable form.
+ --raw Print raw Python object representations.
+ -s, --size Print file sizes.
+ -t, --timestamp Print timestamp information.
+ -v, --verbose Verbose, describe each field.
+"""
try:
- opts, args = getopt.getopt(sys.argv[1:], "acd:e:f:hirstv",
- ['act', 'action',
- 'csig', 'dir=', 'entry=',
- 'format=', 'help', 'implicit',
- 'raw', 'readable',
- 'size', 'timestamp', 'verbose'])
+ opts, args = getopt.getopt(
+ sys.argv[1:],
+ 'acd:e:f:hirstv',
+ [
+ 'act',
+ 'action',
+ 'csig',
+ 'dir=',
+ 'entry=',
+ 'format=',
+ 'help',
+ 'implicit',
+ 'raw',
+ 'readable',
+ 'size',
+ 'timestamp',
+ 'verbose',
+ ],
+ )
except getopt.GetoptError as err:
sys.stderr.write(str(err) + '\n')
print(helpstr)
@@ -423,7 +442,7 @@ def main():
if dbm_name:
try:
if dbm_name != "SCons.dblite":
- dbm = my_import(dbm_name)
+ dbm = importlib.import_module(dbm_name)
else:
import SCons.dblite
@@ -466,7 +485,7 @@ def main():
if dbm_name:
Map_Module = {'SCons.dblite': 'dblite'}
if dbm_name != "SCons.dblite":
- dbm = my_import(dbm_name)
+ dbm = importlib.import_module(dbm_name)
else:
import SCons.dblite
diff --git a/scripts/scons-configure-cache.py b/scripts/scons-configure-cache.py
index da0e848..8f81d8a 100644
--- a/scripts/scons-configure-cache.py
+++ b/scripts/scons-configure-cache.py
@@ -2,7 +2,9 @@
#
# SCons - a Software Constructor
#
-# __COPYRIGHT__
+# MIT License
+#
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -47,7 +49,7 @@ import os
import sys
# python compatibility check
-if sys.version_info < (3, 5, 0):
+if sys.version_info < (3, 6, 0):
msg = "scons: *** SCons version %s does not run under Python version %s.\n\
Python >= 3.5 is required.\n"
sys.stderr.write(msg % (__version__, sys.version.split()[0]))
@@ -92,4 +94,4 @@ sys.path = libs + sys.path
from SCons.Utilities.ConfigureCache import main
if __name__ == "__main__":
- main() \ No newline at end of file
+ main()
diff --git a/scripts/scons.py b/scripts/scons.py
index 86a6bf6..6a36ef7 100755
--- a/scripts/scons.py
+++ b/scripts/scons.py
@@ -41,9 +41,8 @@ __developer__ = "__DEVELOPER__"
import os
import sys
-
# Python compatibility check
-if sys.version_info < (3, 5, 0):
+if sys.version_info < (3, 6, 0):
msg = "scons: *** SCons version %s does not run under Python version %s.\n\
Python >= 3.5 is required.\n"
sys.stderr.write(msg % (__version__, sys.version.split()[0]))
diff --git a/scripts/sconsign.py b/scripts/sconsign.py
index 0edd05c..19e0c82 100644
--- a/scripts/sconsign.py
+++ b/scripts/sconsign.py
@@ -2,7 +2,9 @@
#
# SCons - a Software Constructor
#
-# __COPYRIGHT__
+# MIT License
+#
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -39,7 +41,7 @@ import os
import sys
# python compatibility check
-if sys.version_info < (3, 5, 0):
+if sys.version_info < (3, 6, 0):
msg = "scons: *** SCons version %s does not run under Python version %s.\n\
Python >= 3.5 is required.\n"
sys.stderr.write(msg % (__version__, sys.version.split()[0]))