diff options
author | Mats Wichmann <mats@linux.com> | 2022-05-30 18:37:44 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-30 18:37:44 (GMT) |
commit | b94c8b09050f9927d0793b56f10b756f21cbfc91 (patch) | |
tree | 2c2f94467d05dcd4e75f3672eca0f8cbb1bcaad2 /SCons/Scanner | |
parent | 150197f2273fa639aa4815a68f9bcd38d3068a8d (diff) | |
parent | 27a7837979f4ae5939e212c74a6f7a242df58de4 (diff) | |
download | SCons-b94c8b09050f9927d0793b56f10b756f21cbfc91.zip SCons-b94c8b09050f9927d0793b56f10b756f21cbfc91.tar.gz SCons-b94c8b09050f9927d0793b56f10b756f21cbfc91.tar.bz2 |
Merge branch 'master' into 4162-python-311-unittests
Diffstat (limited to 'SCons/Scanner')
-rw-r--r-- | SCons/Scanner/Java.py | 99 | ||||
-rw-r--r-- | SCons/Scanner/JavaTests.py | 160 |
2 files changed, 259 insertions, 0 deletions
diff --git a/SCons/Scanner/Java.py b/SCons/Scanner/Java.py new file mode 100644 index 0000000..ab1f4e6 --- /dev/null +++ b/SCons/Scanner/Java.py @@ -0,0 +1,99 @@ +# 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 +# "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 os + +import SCons.Node +import SCons.Node.FS +import SCons.Scanner +import SCons.Util + + +def _subst_libs(env, libs): + """ + Substitute environment variables and split into list. + """ + if SCons.Util.is_String(libs): + libs = env.subst(libs) + if SCons.Util.is_String(libs): + libs = libs.split() + elif SCons.Util.is_Sequence(libs): + _libs = [] + for lib in libs: + _libs += _subst_libs(env, lib) + libs = _libs + else: + # libs is an object (Node, for example) + libs = [libs] + return libs + + +def _collect_classes(list, dirname, files): + for fname in files: + if os.path.splitext(fname)[1] == ".class": + list.append(os.path.join(str(dirname), fname)) + + +def scan(node, env, libpath=()): + """Scan for files on the JAVACLASSPATH. + + The classpath can contain: + - Explicit paths to JAR/Zip files + - Wildcards (*) + - Directories which contain classes in an unnamed package + - Parent directories of the root package for classes in a named package + + Class path entries that are neither directories nor archives (.zip or JAR files) nor the asterisk (*) wildcard character are ignored. + """ + classpath = env.get('JAVACLASSPATH', []) + classpath = _subst_libs(env, classpath) + + result = [] + for path in classpath: + if SCons.Util.is_String(path) and "*" in path: + libs = env.Glob(path) + else: + libs = [path] + + for lib in libs: + if os.path.isdir(str(lib)): + # grab the in-memory nodes + env.Dir(lib).walk(_collect_classes, result) + # now the on-disk ones + for root, dirs, files in os.walk(str(lib)): + _collect_classes(result, root, files) + else: + result.append(lib) + + return list(filter(lambda x: os.path.splitext(str(x))[1] in [".class", ".zip", ".jar"], result)) + + +def JavaScanner(): + return SCons.Scanner.Base(scan, 'JavaScanner', + skeys=['.java']) + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/SCons/Scanner/JavaTests.py b/SCons/Scanner/JavaTests.py new file mode 100644 index 0000000..9fb39ce --- /dev/null +++ b/SCons/Scanner/JavaTests.py @@ -0,0 +1,160 @@ +# 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 +# "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 +import collections +import os + +import TestCmd + +import SCons.Scanner.Java +import SCons.Node.FS +import SCons.Warnings + + +test = TestCmd.TestCmd(workdir = '') +test.subdir('com') + +files = [ + 'bootclasspath.jar', + 'classpath.jar', + 'Test.class', + 'com/Test.class' +] + +for fname in files: + test.write(fname, "\n") + + +class DummyEnvironment(collections.UserDict): + def __init__(self,**kw): + collections.UserDict.__init__(self) + self.data.update(kw) + self.fs = SCons.Node.FS.FS(test.workpath('')) + self['ENV'] = {} + + def Dictionary(self, *args): + return self.data + + def subst(self, strSubst, target=None, source=None, conv=None): + if strSubst[0] == '$': + return self.data[strSubst[1:]] + return strSubst + + def subst_path(self, path, target=None, source=None, conv=None): + if not isinstance(path, list): + path = [path] + return list(map(self.subst, path)) + + def has_key(self, key): + return key in self.Dictionary() + + def get_calculator(self): + return None + + def get_factory(self, factory): + return factory or self.fs.File + + def Dir(self, filename): + return self.fs.Dir(filename) + + def File(self, filename): + return self.fs.File(filename) + + def Glob(self, path): + return self.fs.Glob(path) + + +class DummyNode: + def __init__(self, name): + self.name = name + + def rexists(self): + return 1 + + def __str__(self): + return self.name + + +global my_normpath +my_normpath = os.path.normpath + +if os.path.normcase('foo') == os.path.normcase('FOO'): + my_normpath = os.path.normcase + +def deps_match(self, deps, headers): + scanned = sorted(map(my_normpath, list(map(str, deps)))) + expect = sorted(map(my_normpath, headers)) + self.assertTrue(scanned == expect, "expect %s != scanned %s" % (expect, scanned)) + + +class JavaScannerEmptyClasspath(unittest.TestCase): + def runTest(self): + path = [] + env = DummyEnvironment(JAVASUFFIXES=['.java'], + JAVACLASSPATH=path) + s = SCons.Scanner.Java.JavaScanner() + deps = s(DummyNode('dummy'), env) + expected = [] + deps_match(self, deps, expected) + + +class JavaScannerClasspath(unittest.TestCase): + def runTest(self): + env = DummyEnvironment(JAVASUFFIXES=['.java'], + JAVACLASSPATH=[test.workpath('classpath.jar')]) + s = SCons.Scanner.Java.JavaScanner() + deps = s(DummyNode('dummy'), env) + expected = ['classpath.jar'] + deps_match(self, deps, expected) + + +class JavaScannerWildcardClasspath(unittest.TestCase): + def runTest(self): + env = DummyEnvironment(JAVASUFFIXES=['.java'], + JAVACLASSPATH=[test.workpath('*')]) + s = SCons.Scanner.Java.JavaScanner() + deps = s(DummyNode('dummy'), env) + expected = ['bootclasspath.jar', 'classpath.jar', 'Test.class'] + deps_match(self, deps, expected) + + +class JavaScannerDirClasspath(unittest.TestCase): + def runTest(self): + env = DummyEnvironment(JAVASUFFIXES=['.java'], + JAVACLASSPATH=[test.workpath()]) + s = SCons.Scanner.Java.JavaScanner() + deps = s(DummyNode('dummy'), env) + expected = ['Test.class', 'com/Test.class'] + deps_match(self, deps, expected) + + + +if __name__ == "__main__": + unittest.main() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: |