annotate corebio/utils/_which.py @ 0:c55bdc2fb9fa

Uploaded
author davidmurphy
date Thu, 27 Oct 2011 12:09:09 -0400
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
1 #!/usr/bin/env python
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
2 # Copyright (c) 2002-2005 ActiveState Corp.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
3 # See LICENSE.txt for license details.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
4 # Author:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
5 # Trent Mick (TrentM@ActiveState.com)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
6 # Home:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
7 # http://trentm.com/projects/which/
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
8
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
9 r"""Find the full path to commands.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
10
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
11 which(command, path=None, verbose=0, exts=None)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
12 Return the full path to the first match of the given command on the
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
13 path.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
14
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
15 whichall(command, path=None, verbose=0, exts=None)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
16 Return a list of full paths to all matches of the given command on
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
17 the path.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
18
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
19 whichgen(command, path=None, verbose=0, exts=None)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
20 Return a generator which will yield full paths to all matches of the
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
21 given command on the path.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
22
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
23 By default the PATH environment variable is searched (as well as, on
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
24 Windows, the AppPaths key in the registry), but a specific 'path' list
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
25 to search may be specified as well. On Windows, the PATHEXT environment
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
26 variable is applied as appropriate.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
27
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
28 If "verbose" is true then a tuple of the form
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
29 (<fullpath>, <matched-where-description>)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
30 is returned for each match. The latter element is a textual description
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
31 of where the match was found. For example:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
32 from PATH element 0
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
33 from HKLM\SOFTWARE\...\perl.exe
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
34 """
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
35
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
36 _cmdlnUsage = """
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
37 Show the full path of commands.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
38
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
39 Usage:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
40 which [<options>...] [<command-name>...]
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
41
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
42 Options:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
43 -h, --help Print this help and exit.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
44 -V, --version Print the version info and exit.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
45
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
46 -a, --all Print *all* matching paths.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
47 -v, --verbose Print out how matches were located and
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
48 show near misses on stderr.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
49 -q, --quiet Just print out matches. I.e., do not print out
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
50 near misses.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
51
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
52 -p <altpath>, --path=<altpath>
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
53 An alternative path (list of directories) may
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
54 be specified for searching.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
55 -e <exts>, --exts=<exts>
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
56 Specify a list of extensions to consider instead
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
57 of the usual list (';'-separate list, Windows
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
58 only).
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
59
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
60 Show the full path to the program that would be run for each given
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
61 command name, if any. Which, like GNU's which, returns the number of
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
62 failed arguments, or -1 when no <command-name> was given.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
63
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
64 Near misses include duplicates, non-regular files and (on Un*x)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
65 files without executable access.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
66 """
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
67
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
68 __revision__ = "$Id: which.py 430 2005-08-20 03:11:58Z trentm $"
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
69 __version_info__ = (1, 1, 0)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
70 __version__ = '.'.join(map(str, __version_info__))
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
71
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
72 import os
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
73 import sys
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
74 import getopt
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
75 import stat
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
76
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
77
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
78 #---- exceptions
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
79
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
80 class WhichError(Exception):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
81 pass
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
82
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
83
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
84
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
85 #---- internal support stuff
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
86
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
87 def _getRegisteredExecutable(exeName):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
88 """Windows allow application paths to be registered in the registry."""
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
89 registered = None
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
90 if sys.platform.startswith('win'):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
91 if os.path.splitext(exeName)[1].lower() != '.exe':
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
92 exeName += '.exe'
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
93 import _winreg
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
94 try:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
95 key = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\" +\
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
96 exeName
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
97 value = _winreg.QueryValue(_winreg.HKEY_LOCAL_MACHINE, key)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
98 registered = (value, "from HKLM\\"+key)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
99 except _winreg.error:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
100 pass
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
101 if registered and not os.path.exists(registered[0]):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
102 registered = None
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
103 return registered
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
104
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
105 def _samefile(fname1, fname2):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
106 if sys.platform.startswith('win'):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
107 return ( os.path.normpath(os.path.normcase(fname1)) ==\
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
108 os.path.normpath(os.path.normcase(fname2)) )
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
109 else:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
110 return os.path.samefile(fname1, fname2)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
111
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
112 def _cull(potential, matches, verbose=0):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
113 """Cull inappropriate matches. Possible reasons:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
114 - a duplicate of a previous match
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
115 - not a disk file
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
116 - not executable (non-Windows)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
117 If 'potential' is approved it is returned and added to 'matches'.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
118 Otherwise, None is returned.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
119 """
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
120 for match in matches: # don't yield duplicates
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
121 if _samefile(potential[0], match[0]):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
122 if verbose:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
123 sys.stderr.write("duplicate: %s (%s)\n" % potential)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
124 return None
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
125 else:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
126 if not stat.S_ISREG(os.stat(potential[0]).st_mode):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
127 if verbose:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
128 sys.stderr.write("not a regular file: %s (%s)\n" % potential)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
129 elif not os.access(potential[0], os.X_OK):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
130 if verbose:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
131 sys.stderr.write("no executable access: %s (%s)\n"\
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
132 % potential)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
133 else:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
134 matches.append(potential)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
135 return potential
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
136
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
137
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
138 #---- module API
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
139
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
140 def whichgen(command, path=None, verbose=0, exts=None):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
141 """Return a generator of full paths to the given command.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
142
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
143 "command" is a the name of the executable to search for.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
144 "path" is an optional alternate path list to search. The default it
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
145 to use the PATH environment variable.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
146 "verbose", if true, will cause a 2-tuple to be returned for each
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
147 match. The second element is a textual description of where the
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
148 match was found.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
149 "exts" optionally allows one to specify a list of extensions to use
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
150 instead of the standard list for this system. This can
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
151 effectively be used as an optimization to, for example, avoid
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
152 stat's of "foo.vbs" when searching for "foo" and you know it is
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
153 not a VisualBasic script but ".vbs" is on PATHEXT. This option
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
154 is only supported on Windows.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
155
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
156 This method returns a generator which yields either full paths to
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
157 the given command or, if verbose, tuples of the form (<path to
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
158 command>, <where path found>).
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
159 """
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
160 matches = []
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
161 if path is None:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
162 usingGivenPath = 0
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
163 path = os.environ.get("PATH", "").split(os.pathsep)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
164 if sys.platform.startswith("win"):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
165 path.insert(0, os.curdir) # implied by Windows shell
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
166 else:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
167 usingGivenPath = 1
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
168
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
169 # Windows has the concept of a list of extensions (PATHEXT env var).
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
170 if sys.platform.startswith("win"):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
171 if exts is None:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
172 exts = os.environ.get("PATHEXT", "").split(os.pathsep)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
173 # If '.exe' is not in exts then obviously this is Win9x and
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
174 # or a bogus PATHEXT, then use a reasonable default.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
175 for ext in exts:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
176 if ext.lower() == ".exe":
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
177 break
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
178 else:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
179 exts = ['.COM', '.EXE', '.BAT']
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
180 elif not isinstance(exts, list):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
181 raise TypeError("'exts' argument must be a list or None")
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
182 else:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
183 if exts is not None:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
184 raise WhichError("'exts' argument is not supported on "\
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
185 "platform '%s'" % sys.platform)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
186 exts = []
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
187
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
188 # File name cannot have path separators because PATH lookup does not
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
189 # work that way.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
190 if os.sep in command or os.altsep and os.altsep in command:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
191 pass
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
192 else:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
193 for i in range(len(path)):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
194 dirName = path[i]
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
195 # On windows the dirName *could* be quoted, drop the quotes
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
196 if sys.platform.startswith("win") and len(dirName) >= 2\
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
197 and dirName[0] == '"' and dirName[-1] == '"':
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
198 dirName = dirName[1:-1]
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
199 for ext in ['']+exts:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
200 absName = os.path.abspath(
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
201 os.path.normpath(os.path.join(dirName, command+ext)))
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
202 if os.path.isfile(absName):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
203 if usingGivenPath:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
204 fromWhere = "from given path element %d" % i
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
205 elif not sys.platform.startswith("win"):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
206 fromWhere = "from PATH element %d" % i
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
207 elif i == 0:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
208 fromWhere = "from current directory"
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
209 else:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
210 fromWhere = "from PATH element %d" % (i-1)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
211 match = _cull((absName, fromWhere), matches, verbose)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
212 if match:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
213 if verbose:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
214 yield match
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
215 else:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
216 yield match[0]
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
217 match = _getRegisteredExecutable(command)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
218 if match is not None:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
219 match = _cull(match, matches, verbose)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
220 if match:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
221 if verbose:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
222 yield match
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
223 else:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
224 yield match[0]
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
225
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
226
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
227 def which(command, path=None, verbose=0, exts=None):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
228 """Return the full path to the first match of the given command on
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
229 the path.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
230
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
231 "command" is a the name of the executable to search for.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
232 "path" is an optional alternate path list to search. The default it
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
233 to use the PATH environment variable.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
234 "verbose", if true, will cause a 2-tuple to be returned. The second
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
235 element is a textual description of where the match was found.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
236 "exts" optionally allows one to specify a list of extensions to use
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
237 instead of the standard list for this system. This can
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
238 effectively be used as an optimization to, for example, avoid
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
239 stat's of "foo.vbs" when searching for "foo" and you know it is
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
240 not a VisualBasic script but ".vbs" is on PATHEXT. This option
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
241 is only supported on Windows.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
242
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
243 If no match is found for the command, a WhichError is raised.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
244 """
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
245 try:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
246 match = whichgen(command, path, verbose, exts).next()
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
247 except StopIteration:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
248 raise WhichError("Could not find '%s' on the path." % command)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
249 return match
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
250
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
251
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
252 def whichall(command, path=None, verbose=0, exts=None):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
253 """Return a list of full paths to all matches of the given command
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
254 on the path.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
255
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
256 "command" is a the name of the executable to search for.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
257 "path" is an optional alternate path list to search. The default it
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
258 to use the PATH environment variable.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
259 "verbose", if true, will cause a 2-tuple to be returned for each
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
260 match. The second element is a textual description of where the
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
261 match was found.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
262 "exts" optionally allows one to specify a list of extensions to use
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
263 instead of the standard list for this system. This can
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
264 effectively be used as an optimization to, for example, avoid
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
265 stat's of "foo.vbs" when searching for "foo" and you know it is
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
266 not a VisualBasic script but ".vbs" is on PATHEXT. This option
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
267 is only supported on Windows.
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
268 """
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
269 return list( whichgen(command, path, verbose, exts) )
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
270
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
271
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
272
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
273 #---- mainline
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
274
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
275 def main(argv):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
276 all = 0
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
277 verbose = 0
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
278 altpath = None
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
279 exts = None
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
280 try:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
281 optlist, args = getopt.getopt(argv[1:], 'haVvqp:e:',
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
282 ['help', 'all', 'version', 'verbose', 'quiet', 'path=', 'exts='])
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
283 except getopt.GetoptError, msg:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
284 sys.stderr.write("which: error: %s. Your invocation was: %s\n"\
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
285 % (msg, argv))
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
286 sys.stderr.write("Try 'which --help'.\n")
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
287 return 1
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
288 for opt, optarg in optlist:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
289 if opt in ('-h', '--help'):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
290 print _cmdlnUsage
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
291 return 0
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
292 elif opt in ('-V', '--version'):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
293 print "which %s" % __version__
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
294 return 0
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
295 elif opt in ('-a', '--all'):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
296 all = 1
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
297 elif opt in ('-v', '--verbose'):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
298 verbose = 1
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
299 elif opt in ('-q', '--quiet'):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
300 verbose = 0
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
301 elif opt in ('-p', '--path'):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
302 if optarg:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
303 altpath = optarg.split(os.pathsep)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
304 else:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
305 altpath = []
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
306 elif opt in ('-e', '--exts'):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
307 if optarg:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
308 exts = optarg.split(os.pathsep)
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
309 else:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
310 exts = []
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
311
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
312 if len(args) == 0:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
313 return -1
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
314
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
315 failures = 0
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
316 for arg in args:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
317 #print "debug: search for %r" % arg
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
318 nmatches = 0
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
319 for match in whichgen(arg, path=altpath, verbose=verbose, exts=exts):
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
320 if verbose:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
321 print "%s (%s)" % match
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
322 else:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
323 print match
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
324 nmatches += 1
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
325 if not all:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
326 break
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
327 if not nmatches:
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
328 failures += 1
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
329 return failures
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
330
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
331
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
332 if __name__ == "__main__":
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
333 sys.exit( main(sys.argv) )
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
334
c55bdc2fb9fa Uploaded
davidmurphy
parents:
diff changeset
335