Launchpad automatic translations update.
[odoo/odoo.git] / bin / tools / which.py
1 #!/usr/bin/env python
2 """ Which - locate a command
3
4     * adapted from Brian Curtin's http://bugs.python.org/file15381/shutil_which.patch
5     * see http://bugs.python.org/issue444582
6     * uses ``PATHEXT`` on Windows
7     * searches current directory before ``PATH`` on Windows,
8       but not before an explicitly passed path
9     * accepts both string or iterable for an explicitly passed path, or pathext
10     * accepts an explicitly passed empty path, or pathext (either '' or [])
11     * does not search ``PATH`` for files that have a path specified in their name already
12     * moved defpath and defpathext lists initialization to module level,
13       instead of initializing them on each function call
14     * changed interface: which_files() returns generator, which() returns first match,
15       or raises IOError(errno.ENOENT)
16
17     .. function:: which_files(file [, mode=os.F_OK | os.X_OK[, path=None[, pathext=None]]])
18
19        Return a generator which yields full paths in which the *file* name exists
20        in a directory that is part of the file name, or on *path*,
21        and has the given *mode*.
22        By default, *mode* matches an inclusive OR of os.F_OK and os.X_OK
23         - an existing executable file.
24        The *path* is, by default, the ``PATH`` variable on the platform,
25        or the string/iterable passed in as *path*.
26        In the event that a ``PATH`` variable is not found, :const:`os.defpath` is used.
27        On Windows, a current directory is searched before using the ``PATH`` variable,
28        but not before an explicitly passed *path*.
29        The *pathext* is only used on Windows to match files with given extensions appended as well.
30        It defaults to the ``PATHEXT`` variable, or the string/iterable passed in as *pathext*.
31        In the event that a ``PATHEXT`` variable is not found,
32        default value for Windows XP/Vista is used.
33        The command is always searched without extension first,
34        even when *pathext* is explicitly passed.
35
36     .. function:: which(file [, mode=os.F_OK | os.X_OK[, path=None[, pathext=None]]])
37        Return first match generated by which_files(file, mode, path, pathext),
38        or raise IOError(errno.ENOENT).
39
40 """
41 __docformat__ = 'restructuredtext en'
42 __all__ = 'which which_files pathsep defpath defpathext F_OK R_OK W_OK X_OK'.split()
43
44 import sys
45 from os import access, defpath, pathsep, environ, F_OK, R_OK, W_OK, X_OK
46 from os.path import exists, dirname, split, join
47
48 windows = sys.platform.startswith('win')
49
50 defpath = environ.get('PATH', defpath).split(pathsep)
51
52 if windows:
53     defpath.insert(0, '.') # can insert without checking, when duplicates are removed
54     # given the quite usual mess in PATH on Windows, let's rather remove duplicates
55     seen = set()
56     defpath = [dir for dir in defpath if dir.lower() not in seen and not seen.add(dir.lower())]
57     del seen
58
59     defpathext = [''] + environ.get('PATHEXT',
60         '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC').lower().split(pathsep)
61 else:
62     defpathext = ['']
63
64 def which_files(file, mode=F_OK | X_OK, path=None, pathext=None):
65     """ Locate a file in a path supplied as a part of the file name,
66         or the user's path, or a supplied path.
67         The function yields full paths (not necessarily absolute paths),
68         in which the given file name matches an existing file in a directory on the path.
69
70         >>> def test_which(expected, *args, **argd):
71         ...     result = list(which_files(*args, **argd))
72         ...     assert result == expected, 'which_files: %s != %s' % (result, expected)
73         ...
74         ...     try:
75         ...         result = [ which(*args, **argd) ]
76         ...     except IOError:
77         ...         result = []
78         ...     assert result[:1] == expected[:1], 'which: %s != %s' % (result[:1], expected[:1])
79
80         >>> if windows: cmd = environ['COMSPEC']
81         >>> if windows: test_which([cmd], 'cmd')
82         >>> if windows: test_which([cmd], 'cmd.exe')
83         >>> if windows: test_which([cmd], 'cmd', path=dirname(cmd))
84         >>> if windows: test_which([cmd], 'cmd', pathext='.exe')
85         >>> if windows: test_which([cmd], cmd)
86         >>> if windows: test_which([cmd], cmd, path='<nonexistent>')
87         >>> if windows: test_which([cmd], cmd, pathext='<nonexistent>')
88         >>> if windows: test_which([cmd], cmd[:-4])
89         >>> if windows: test_which([cmd], cmd[:-4], path='<nonexistent>')
90
91         >>> if windows: test_which([], 'cmd', path='<nonexistent>')
92         >>> if windows: test_which([], 'cmd', pathext='<nonexistent>')
93         >>> if windows: test_which([], '<nonexistent>/cmd')
94         >>> if windows: test_which([], cmd[:-4], pathext='<nonexistent>')
95
96         >>> if not windows: sh = '/bin/sh'
97         >>> if not windows: test_which([sh], 'sh')
98         >>> if not windows: test_which([sh], 'sh', path=dirname(sh))
99         >>> if not windows: test_which([sh], 'sh', pathext='<nonexistent>')
100         >>> if not windows: test_which([sh], sh)
101         >>> if not windows: test_which([sh], sh, path='<nonexistent>')
102         >>> if not windows: test_which([sh], sh, pathext='<nonexistent>')
103
104         >>> if not windows: test_which([], 'sh', mode=W_OK)  # not running as root, are you?
105         >>> if not windows: test_which([], 'sh', path='<nonexistent>')
106         >>> if not windows: test_which([], '<nonexistent>/sh')
107     """
108     filepath, file = split(file)
109
110     if filepath:
111         path = (filepath,)
112     elif path is None:
113         path = defpath
114     elif isinstance(path, str):
115         path = path.split(pathsep)
116
117     if pathext is None:
118         pathext = defpathext
119     elif isinstance(pathext, str):
120         pathext = pathext.split(pathsep)
121
122     if not '' in pathext:
123         pathext.insert(0, '') # always check command without extension, even for custom pathext
124
125     for dir in path:
126         basepath = join(dir, file)
127         for ext in pathext:
128             fullpath = basepath + ext
129             if exists(fullpath) and access(fullpath, mode):
130                 yield fullpath
131
132 def which(file, mode=F_OK | X_OK, path=None, pathext=None):
133     """ Locate a file in a path supplied as a part of the file name,
134         or the user's path, or a supplied path.
135         The function returns full path (not necessarily absolute path),
136         in which the given file name matches an existing file in a directory on the path,
137         or raises IOError(errno.ENOENT).
138
139         >>> # for doctest see which_files()
140     """
141     try:
142         return iter(which_files(file, mode, path, pathext)).next()
143     except StopIteration:
144         try:
145             from errno import ENOENT
146         except ImportError:
147             ENOENT = 2
148         raise IOError(ENOENT, '%s not found' % (mode & X_OK and 'command' or 'file'), file)
149
150
151 if __name__ == '__main__':
152     import doctest
153     doctest.testmod()