Add WhereIs() functionality.
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Wed, 27 Mar 2002 02:49:41 +0000 (02:49 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Wed, 27 Mar 2002 02:49:41 +0000 (02:49 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@306 fdb21ef1-2011-0410-befe-b5e4ea1792b1

doc/man/scons.1
src/CHANGES.txt
src/engine/SCons/Defaults.py
src/engine/SCons/Script/SConscript.py
src/engine/SCons/Util.py
src/engine/SCons/UtilTests.py
test/WhereIs.py [new file with mode: 0644]

index e49008f5b63fdb8d543658bbf110d305c1959ae8..51ee464fe5f425dfe814d9bcab6a207856028037 100644 (file)
@@ -1230,6 +1230,27 @@ is that arguments to the command.
 is a dictionary of the environment variables
 in which the command should be executed.
 
+.TP
+.RI WhereIs( program ", [" path  ", [" pathext ]])
+
+Searches for the specified executable
+.I program,
+returning the full path name to the program
+if it is found,
+and returning None if not.
+Searches the specified
+.I path,
+or the user's current PATH
+(os.environ['PATH'])
+by default.
+On Win32 systems, searches for executable
+programs with any of the file extensions
+listed in the specified
+.I pathext,
+or the user's current PATHEXT
+(os.environ['PATHEXT'])
+by default.
+
 .SH EXTENDING SCONS
 .SS Builder Objects
 .B scons
index 1ffca34d92d2801b0da3fdcdde55b4e8d210b15a..9225510ba6e2627dede8eab72ad974ac07067585 100644 (file)
@@ -57,6 +57,8 @@ RELEASE 0.06 -
 
   - Add support for Aliases (phony targets).
 
+  - Add a WhereIs() method for searching for path names to executables.
+
   From Steve Leblanc:
 
   - Add support for the -U option.
index 36a6aa1db7f0859ec756edd5e7dd0fa8c0dbc8cd..6dedb523272c849eedf64b7bb916acc0cc612ed3 100644 (file)
@@ -52,20 +52,6 @@ import SCons.Util
 
 
 
-def whereis(file):
-    for dir in string.split(os.environ['PATH'], os.pathsep):
-        f = os.path.join(dir, file)
-        if os.path.isfile(f):
-            try:
-                st = os.stat(f)
-            except:
-                continue
-            if stat.S_IMODE(st[stat.ST_MODE]) & 0111:
-                return f
-    return None
-
-
-
 CFile = SCons.Builder.Builder(name = 'CFile',
                               action = { '.l'    : '$LEXCOM',
                                          '.y'    : '$YACCCOM',
@@ -295,7 +281,7 @@ if os.name == 'posix':
 
     arcom = '$AR $ARFLAGS $TARGET $SOURCES'
     ranlib = 'ranlib'
-    if whereis(ranlib):
+    if SCons.Util.WhereIs(ranlib):
         arcom = arcom + '\n$RANLIB $RANLIBFLAGS $TARGET'
 
     ConstructionEnvironment = {
index 2cfc64bd5902523dfff9dbb19f27e6cea7bc0e8f..55520150d81bf5139830fe4629ee5246f8097502 100644 (file)
@@ -179,6 +179,7 @@ def BuildDefaultGlobals():
     globals['Export']            = Export
     globals['File']              = SCons.Node.FS.default_fs.File
     globals['GetBuildPath']      = GetBuildPath
+    globals['GetCommandHandler'] = SCons.Action.GetCommandHandler
     globals['Help']              = Help
     globals['Import']            = Import
     globals['Library']           = SCons.Defaults.Library
@@ -188,5 +189,5 @@ def BuildDefaultGlobals():
     globals['Scanner']           = SCons.Scanner.Base
     globals['SConscript']        = SConscript
     globals['SetCommandHandler'] = SCons.Action.SetCommandHandler
-    globals['GetCommandHandler'] = SCons.Action.GetCommandHandler
+    globals['WhereIs']           = SCons.Util.WhereIs
     return globals
index f60e9815647387482b04a6c68ea735551f3ef0a9..ef998a94bc502e209e050f127b5def003fbe4e4d 100644 (file)
@@ -31,9 +31,12 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
 
 import copy
+import os
 import os.path
 import re
+import stat
 import string
+import sys
 import types
 import UserDict
 import UserList
@@ -279,3 +282,45 @@ if can_read_reg:
     HKEY_LOCAL_MACHINE = hkey_mod.HKEY_LOCAL_MACHINE
     HKEY_CURRENT_USER = hkey_mod.HKEY_CURRENT_USER
     HKEY_USERS = hkey_mod.HKEY_USERS
+
+
+if sys.platform == 'win32':
+
+    def WhereIs(file, path=None, pathext=None):
+        if path is None:
+            path = os.environ['PATH']
+        if is_String(path):
+            path = string.split(path, os.pathsep)
+        if pathext is None:
+            pathext = os.environ['PATHEXT']
+        if is_String(pathext):
+            pathext = string.split(pathext, os.pathsep)
+        for ext in pathext:
+            if string.lower(ext) == string.lower(file[-len(ext):]):
+                pathext = ['']
+                break
+        for dir in path:
+            f = os.path.join(dir, file)
+            for ext in pathext:
+                fext = f + ext
+                if os.path.isfile(fext):
+                    return fext
+        return None
+
+else:
+
+    def WhereIs(file, path=None, pathext=None):
+        if path is None:
+            path = os.environ['PATH']
+        if is_String(path):
+            path = string.split(path, os.pathsep)
+        for dir in path:
+            f = os.path.join(dir, file)
+            if os.path.isfile(f):
+                try:
+                    st = os.stat(f)
+                except:
+                    continue
+                if stat.S_IMODE(st[stat.ST_MODE]) & 0111:
+                    return f
+        return None
index 67bdbb42090bfa1895755ed780bc1722a3cee6cd..d230a08da06451dbc0e6dfea2f75f9fa0604d1f2 100644 (file)
@@ -221,6 +221,67 @@ class UtilTestCase(unittest.TestCase):
         assert not is_String({})
         assert not is_String([])
 
+    def test_WhereIs(self):
+        test = TestCmd.TestCmd(workdir = '')
+
+        sub1_xxx_exe = test.workpath('sub1', 'xxx.exe')
+        sub2_xxx_exe = test.workpath('sub2', 'xxx.exe')
+        sub3_xxx_exe = test.workpath('sub3', 'xxx.exe')
+        sub4_xxx_exe = test.workpath('sub4', 'xxx.exe')
+
+        test.subdir('subdir', 'sub1', 'sub2', 'sub3', 'sub4')
+
+        if sys.platform != 'win32':
+            test.write(sub1_xxx_exe, "\n")
+
+        os.mkdir(sub2_xxx_exe)
+
+        test.write(sub3_xxx_exe, "\n")
+        os.chmod(sub3_xxx_exe, 0777)
+
+        test.write(sub4_xxx_exe, "\n")
+        os.chmod(sub4_xxx_exe, 0777)
+
+        env_path = os.environ['PATH']
+
+        pathdirs_1234 = [ test.workpath('sub1'),
+                          test.workpath('sub2'),
+                          test.workpath('sub3'),
+                          test.workpath('sub4'),
+                        ] + string.split(env_path, os.pathsep)
+
+        pathdirs_1243 = [ test.workpath('sub1'),
+                          test.workpath('sub2'),
+                          test.workpath('sub4'),
+                          test.workpath('sub3'),
+                        ] + string.split(env_path, os.pathsep)
+
+        os.environ['PATH'] = string.join(pathdirs_1234, os.pathsep)
+        wi = WhereIs('xxx.exe')
+        assert wi == test.workpath(sub3_xxx_exe), wi
+        wi = WhereIs('xxx.exe', pathdirs_1243)
+        assert wi == test.workpath(sub4_xxx_exe), wi
+        wi = WhereIs('xxx.exe', string.join(pathdirs_1243, os.pathsep))
+        assert wi == test.workpath(sub4_xxx_exe), wi
+
+        os.environ['PATH'] = string.join(pathdirs_1243, os.pathsep)
+        wi = WhereIs('xxx.exe')
+        assert wi == test.workpath(sub4_xxx_exe), wi
+        wi = WhereIs('xxx.exe', pathdirs_1234)
+        assert wi == test.workpath(sub3_xxx_exe), wi
+        wi = WhereIs('xxx.exe', string.join(pathdirs_1234, os.pathsep))
+        assert wi == test.workpath(sub3_xxx_exe), wi
+
+       if sys.platform == 'win32':
+           wi = WhereIs('xxx', pathext = '')
+           assert wi is None, wi
+
+           wi = WhereIs('xxx', pathext = '.exe')
+           assert wi == test.workpath(sub4_xxx_exe), wi
+
+           wi = WhereIs('xxx', path = pathdirs_1234, pathext = '.BAT;.EXE')
+           assert string.lower(wi) == string.lower(test.workpath(sub3_xxx_exe)), wi
+
 if __name__ == "__main__":
     suite = unittest.makeSuite(UtilTestCase, 'test_')
     if not unittest.TextTestRunner().run(suite).wasSuccessful():
diff --git a/test/WhereIs.py b/test/WhereIs.py
new file mode 100644 (file)
index 0000000..515be14
--- /dev/null
@@ -0,0 +1,126 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2001, 2002 Steven Knight
+#
+# 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 string
+import sys
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+subdir_SConscript = os.path.join('subdir', 'SConscript')
+sub1_xxx_exe = test.workpath('sub1', 'xxx.exe')
+sub2_xxx_exe = test.workpath('sub2', 'xxx.exe')
+sub3_xxx_exe = test.workpath('sub3', 'xxx.exe')
+sub4_xxx_exe = test.workpath('sub4', 'xxx.exe')
+
+test.subdir('subdir', 'sub1', 'sub2', 'sub3', 'sub4')
+
+if sys.platform != 'win32':
+    test.write(sub1_xxx_exe, "\n")
+
+os.mkdir(sub2_xxx_exe)
+
+test.write(sub3_xxx_exe, "\n")
+os.chmod(sub3_xxx_exe, 0777)
+
+test.write(sub4_xxx_exe, "\n")
+os.chmod(sub4_xxx_exe, 0777)
+
+env_path = os.environ['PATH']
+
+pathdirs_1234 = [ test.workpath('sub1'),
+                  test.workpath('sub2'),
+                  test.workpath('sub3'),
+                  test.workpath('sub4'),
+                ] + string.split(env_path, os.pathsep)
+
+pathdirs_1243 = [ test.workpath('sub1'),
+                  test.workpath('sub2'),
+                  test.workpath('sub4'),
+                  test.workpath('sub3'),
+                ] + string.split(env_path, os.pathsep)
+
+test.write('SConstruct', """
+SConscript('%s')
+print WhereIs('xxx.exe')
+print WhereIs('xxx.exe', %s)
+print WhereIs('xxx.exe', %s)
+print WhereIs('xxx.exe', %s)
+print WhereIs('xxx.exe', %s)
+""" % (subdir_SConscript,
+       repr(string.join(pathdirs_1234, os.pathsep)),
+       repr(string.join(pathdirs_1243, os.pathsep)),
+       repr(pathdirs_1234),
+       repr(pathdirs_1243),
+      ))
+
+test.write(subdir_SConscript, """
+print WhereIs('xxx.exe')
+print WhereIs('xxx.exe', %s)
+print WhereIs('xxx.exe', %s)
+print WhereIs('xxx.exe', %s)
+print WhereIs('xxx.exe', %s)
+""" % (repr(string.join(pathdirs_1234, os.pathsep)),
+       repr(string.join(pathdirs_1243, os.pathsep)),
+       repr(pathdirs_1234),
+       repr(pathdirs_1243),
+      ))
+
+os.environ['PATH'] = string.join(pathdirs_1234, os.pathsep)
+
+expect = [ test.workpath(sub3_xxx_exe),
+           test.workpath(sub3_xxx_exe),
+           test.workpath(sub4_xxx_exe),
+           test.workpath(sub3_xxx_exe),
+           test.workpath(sub4_xxx_exe),
+           test.workpath(sub3_xxx_exe),
+           test.workpath(sub3_xxx_exe),
+           test.workpath(sub4_xxx_exe),
+           test.workpath(sub3_xxx_exe),
+           test.workpath(sub4_xxx_exe),
+        ]
+
+test.run(stdout = string.join(expect, "\n") + "\n")
+
+os.environ['PATH'] = string.join(pathdirs_1243, os.pathsep)
+
+expect = [ test.workpath(sub4_xxx_exe),
+           test.workpath(sub3_xxx_exe),
+           test.workpath(sub4_xxx_exe),
+           test.workpath(sub3_xxx_exe),
+           test.workpath(sub4_xxx_exe),
+           test.workpath(sub4_xxx_exe),
+           test.workpath(sub3_xxx_exe),
+           test.workpath(sub4_xxx_exe),
+           test.workpath(sub3_xxx_exe),
+           test.workpath(sub4_xxx_exe),
+        ]
+
+test.run(stdout = string.join(expect, "\n") + "\n")
+
+test.pass_test()