[IMP] tools: find_in_path: use which (file found on python bug tracker)
bzr revid: chs@openerp.com-20100531093913-mn98pno6srb74v27
This commit is contained in:
parent
74cf00b2fd
commit
c11f53d695
|
@ -3,6 +3,7 @@
|
||||||
#
|
#
|
||||||
# OpenERP, Open Source Management Solution
|
# OpenERP, Open Source Management Solution
|
||||||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
|
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
|
||||||
|
# Copyright (C) 2010 OpenERP s.a. (<http://openerp.com>).
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU Affero General Public License as
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
@ -34,6 +35,7 @@ import socket
|
||||||
import re
|
import re
|
||||||
from itertools import islice
|
from itertools import islice
|
||||||
import threading
|
import threading
|
||||||
|
from which import which
|
||||||
|
|
||||||
|
|
||||||
if sys.version_info[:2] < (2, 4):
|
if sys.version_info[:2] < (2, 4):
|
||||||
|
@ -112,23 +114,19 @@ def init_db(cr):
|
||||||
cr.commit()
|
cr.commit()
|
||||||
|
|
||||||
def find_in_path(name):
|
def find_in_path(name):
|
||||||
if os.name == "nt":
|
try:
|
||||||
sep = ';'
|
return which(name)
|
||||||
else:
|
except IOError:
|
||||||
sep = ':'
|
return None
|
||||||
path = [dir for dir in os.environ['PATH'].split(sep)
|
|
||||||
if os.path.isdir(dir)]
|
|
||||||
for dir in path:
|
|
||||||
val = os.path.join(dir, name)
|
|
||||||
if os.path.isfile(val) or os.path.islink(val):
|
|
||||||
return val
|
|
||||||
return None
|
|
||||||
|
|
||||||
def find_pg_tool(name):
|
def find_pg_tool(name):
|
||||||
|
path = None
|
||||||
if config['pg_path'] and config['pg_path'] != 'None':
|
if config['pg_path'] and config['pg_path'] != 'None':
|
||||||
return os.path.join(config['pg_path'], name)
|
path = config['pg_path']
|
||||||
else:
|
try:
|
||||||
return find_in_path(name)
|
return which(name, path=path)
|
||||||
|
except IOError:
|
||||||
|
return None
|
||||||
|
|
||||||
def exec_pg_command(name, *args):
|
def exec_pg_command(name, *args):
|
||||||
prog = find_pg_tool(name)
|
prog = find_pg_tool(name)
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
""" Which - locate a command
|
||||||
|
|
||||||
|
* adapted from Brian Curtin's http://bugs.python.org/file15381/shutil_which.patch
|
||||||
|
* see http://bugs.python.org/issue444582
|
||||||
|
* uses ``PATHEXT`` on Windows
|
||||||
|
* searches current directory before ``PATH`` on Windows,
|
||||||
|
but not before an explicitly passed path
|
||||||
|
* accepts both string or iterable for an explicitly passed path, or pathext
|
||||||
|
* accepts an explicitly passed empty path, or pathext (either '' or [])
|
||||||
|
* does not search ``PATH`` for files that have a path specified in their name already
|
||||||
|
* moved defpath and defpathext lists initialization to module level,
|
||||||
|
instead of initializing them on each function call
|
||||||
|
* changed interface: which_files() returns generator, which() returns first match,
|
||||||
|
or raises IOError(errno.ENOENT)
|
||||||
|
|
||||||
|
.. function:: which_files(file [, mode=os.F_OK | os.X_OK[, path=None[, pathext=None]]])
|
||||||
|
|
||||||
|
Return a generator which yields full paths in which the *file* name exists
|
||||||
|
in a directory that is part of the file name, or on *path*,
|
||||||
|
and has the given *mode*.
|
||||||
|
By default, *mode* matches an inclusive OR of os.F_OK and os.X_OK
|
||||||
|
- an existing executable file.
|
||||||
|
The *path* is, by default, the ``PATH`` variable on the platform,
|
||||||
|
or the string/iterable passed in as *path*.
|
||||||
|
In the event that a ``PATH`` variable is not found, :const:`os.defpath` is used.
|
||||||
|
On Windows, a current directory is searched before using the ``PATH`` variable,
|
||||||
|
but not before an explicitly passed *path*.
|
||||||
|
The *pathext* is only used on Windows to match files with given extensions appended as well.
|
||||||
|
It defaults to the ``PATHEXT`` variable, or the string/iterable passed in as *pathext*.
|
||||||
|
In the event that a ``PATHEXT`` variable is not found,
|
||||||
|
default value for Windows XP/Vista is used.
|
||||||
|
The command is always searched without extension first,
|
||||||
|
even when *pathext* is explicitly passed.
|
||||||
|
|
||||||
|
.. function:: which(file [, mode=os.F_OK | os.X_OK[, path=None[, pathext=None]]])
|
||||||
|
Return first match generated by which_files(file, mode, path, pathext),
|
||||||
|
or raise IOError(errno.ENOENT).
|
||||||
|
|
||||||
|
"""
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
__all__ = 'which which_files pathsep defpath defpathext F_OK R_OK W_OK X_OK'.split()
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from os import access, defpath, pathsep, environ, F_OK, R_OK, W_OK, X_OK
|
||||||
|
from os.path import exists, dirname, split, join
|
||||||
|
|
||||||
|
windows = sys.platform.startswith('win')
|
||||||
|
|
||||||
|
defpath = environ.get('PATH', defpath).split(pathsep)
|
||||||
|
|
||||||
|
if windows:
|
||||||
|
defpath.insert(0, '.') # can insert without checking, when duplicates are removed
|
||||||
|
# given the quite usual mess in PATH on Windows, let's rather remove duplicates
|
||||||
|
seen = set()
|
||||||
|
defpath = [dir for dir in defpath if dir.lower() not in seen and not seen.add(dir.lower())]
|
||||||
|
del seen
|
||||||
|
|
||||||
|
defpathext = [''] + environ.get('PATHEXT',
|
||||||
|
'.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC').lower().split(pathsep)
|
||||||
|
else:
|
||||||
|
defpathext = ['']
|
||||||
|
|
||||||
|
def which_files(file, mode=F_OK | X_OK, path=None, pathext=None):
|
||||||
|
""" Locate a file in a path supplied as a part of the file name,
|
||||||
|
or the user's path, or a supplied path.
|
||||||
|
The function yields full paths (not necessarily absolute paths),
|
||||||
|
in which the given file name matches an existing file in a directory on the path.
|
||||||
|
|
||||||
|
>>> def test_which(expected, *args, **argd):
|
||||||
|
... result = list(which_files(*args, **argd))
|
||||||
|
... assert result == expected, 'which_files: %s != %s' % (result, expected)
|
||||||
|
...
|
||||||
|
... try:
|
||||||
|
... result = [ which(*args, **argd) ]
|
||||||
|
... except IOError:
|
||||||
|
... result = []
|
||||||
|
... assert result[:1] == expected[:1], 'which: %s != %s' % (result[:1], expected[:1])
|
||||||
|
|
||||||
|
>>> if windows: cmd = environ['COMSPEC']
|
||||||
|
>>> if windows: test_which([cmd], 'cmd')
|
||||||
|
>>> if windows: test_which([cmd], 'cmd.exe')
|
||||||
|
>>> if windows: test_which([cmd], 'cmd', path=dirname(cmd))
|
||||||
|
>>> if windows: test_which([cmd], 'cmd', pathext='.exe')
|
||||||
|
>>> if windows: test_which([cmd], cmd)
|
||||||
|
>>> if windows: test_which([cmd], cmd, path='<nonexistent>')
|
||||||
|
>>> if windows: test_which([cmd], cmd, pathext='<nonexistent>')
|
||||||
|
>>> if windows: test_which([cmd], cmd[:-4])
|
||||||
|
>>> if windows: test_which([cmd], cmd[:-4], path='<nonexistent>')
|
||||||
|
|
||||||
|
>>> if windows: test_which([], 'cmd', path='<nonexistent>')
|
||||||
|
>>> if windows: test_which([], 'cmd', pathext='<nonexistent>')
|
||||||
|
>>> if windows: test_which([], '<nonexistent>/cmd')
|
||||||
|
>>> if windows: test_which([], cmd[:-4], pathext='<nonexistent>')
|
||||||
|
|
||||||
|
>>> if not windows: sh = '/bin/sh'
|
||||||
|
>>> if not windows: test_which([sh], 'sh')
|
||||||
|
>>> if not windows: test_which([sh], 'sh', path=dirname(sh))
|
||||||
|
>>> if not windows: test_which([sh], 'sh', pathext='<nonexistent>')
|
||||||
|
>>> if not windows: test_which([sh], sh)
|
||||||
|
>>> if not windows: test_which([sh], sh, path='<nonexistent>')
|
||||||
|
>>> if not windows: test_which([sh], sh, pathext='<nonexistent>')
|
||||||
|
|
||||||
|
>>> if not windows: test_which([], 'sh', mode=W_OK) # not running as root, are you?
|
||||||
|
>>> if not windows: test_which([], 'sh', path='<nonexistent>')
|
||||||
|
>>> if not windows: test_which([], '<nonexistent>/sh')
|
||||||
|
"""
|
||||||
|
filepath, file = split(file)
|
||||||
|
|
||||||
|
if filepath:
|
||||||
|
path = (filepath,)
|
||||||
|
elif path is None:
|
||||||
|
path = defpath
|
||||||
|
elif isinstance(path, str):
|
||||||
|
path = path.split(pathsep)
|
||||||
|
|
||||||
|
if pathext is None:
|
||||||
|
pathext = defpathext
|
||||||
|
elif isinstance(pathext, str):
|
||||||
|
pathext = pathext.split(pathsep)
|
||||||
|
|
||||||
|
if not '' in pathext:
|
||||||
|
pathext.insert(0, '') # always check command without extension, even for custom pathext
|
||||||
|
|
||||||
|
for dir in path:
|
||||||
|
basepath = join(dir, file)
|
||||||
|
for ext in pathext:
|
||||||
|
fullpath = basepath + ext
|
||||||
|
if exists(fullpath) and access(fullpath, mode):
|
||||||
|
yield fullpath
|
||||||
|
|
||||||
|
def which(file, mode=F_OK | X_OK, path=None, pathext=None):
|
||||||
|
""" Locate a file in a path supplied as a part of the file name,
|
||||||
|
or the user's path, or a supplied path.
|
||||||
|
The function returns full path (not necessarily absolute path),
|
||||||
|
in which the given file name matches an existing file in a directory on the path,
|
||||||
|
or raises IOError(errno.ENOENT).
|
||||||
|
|
||||||
|
>>> # for doctest see which_files()
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return iter(which_files(file, mode, path, pathext)).next()
|
||||||
|
except StopIteration:
|
||||||
|
try:
|
||||||
|
from errno import ENOENT
|
||||||
|
except ImportError:
|
||||||
|
ENOENT = 2
|
||||||
|
raise IOError(ENOENT, '%s not found' % (mode & X_OK and 'command' or 'file'), file)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import doctest
|
||||||
|
doctest.testmod()
|
Loading…
Reference in New Issue