mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
bpo-35755: shutil.which() uses os.confstr("CS_PATH") (GH-12858)
shutil.which() and distutils.spawn.find_executable() now use os.confstr("CS_PATH") if available instead of os.defpath, if the PATH environment variable is not set. Don't use os.confstr("CS_PATH") nor os.defpath if the PATH environment variable is set to an empty string to mimick Unix 'which' command behavior. Changes: * find_executable() now starts by checking for the executable in the current working directly case. Add an explicit "if not path: return None". * Add tests for PATH='' (empty string), PATH=':' and for PATHEXT.
This commit is contained in:
parent
71ce03df9c
commit
228a3c99bd
5 changed files with 155 additions and 18 deletions
|
@ -1619,6 +1619,57 @@ class TestWhich(unittest.TestCase):
|
|||
rv = shutil.which(self.file)
|
||||
self.assertEqual(rv, self.temp_file.name)
|
||||
|
||||
def test_environ_path_empty(self):
|
||||
# PATH='': no match
|
||||
with support.EnvironmentVarGuard() as env:
|
||||
env['PATH'] = ''
|
||||
with unittest.mock.patch('os.confstr', return_value=self.dir, \
|
||||
create=True), \
|
||||
support.swap_attr(os, 'defpath', self.dir), \
|
||||
support.change_cwd(self.dir):
|
||||
rv = shutil.which(self.file)
|
||||
self.assertIsNone(rv)
|
||||
|
||||
def test_environ_path_cwd(self):
|
||||
expected_cwd = os.path.basename(self.temp_file.name)
|
||||
if sys.platform == "win32":
|
||||
curdir = os.curdir
|
||||
if isinstance(expected_cwd, bytes):
|
||||
curdir = os.fsencode(curdir)
|
||||
expected_cwd = os.path.join(curdir, expected_cwd)
|
||||
|
||||
# PATH=':': explicitly looks in the current directory
|
||||
with support.EnvironmentVarGuard() as env:
|
||||
env['PATH'] = os.pathsep
|
||||
with unittest.mock.patch('os.confstr', return_value=self.dir, \
|
||||
create=True), \
|
||||
support.swap_attr(os, 'defpath', self.dir):
|
||||
rv = shutil.which(self.file)
|
||||
self.assertIsNone(rv)
|
||||
|
||||
# look in current directory
|
||||
with support.change_cwd(self.dir):
|
||||
rv = shutil.which(self.file)
|
||||
self.assertEqual(rv, expected_cwd)
|
||||
|
||||
def test_environ_path_missing(self):
|
||||
with support.EnvironmentVarGuard() as env:
|
||||
env.pop('PATH', None)
|
||||
|
||||
# without confstr
|
||||
with unittest.mock.patch('os.confstr', side_effect=ValueError, \
|
||||
create=True), \
|
||||
support.swap_attr(os, 'defpath', self.dir):
|
||||
rv = shutil.which(self.file)
|
||||
self.assertEqual(rv, self.temp_file.name)
|
||||
|
||||
# with confstr
|
||||
with unittest.mock.patch('os.confstr', return_value=self.dir, \
|
||||
create=True), \
|
||||
support.swap_attr(os, 'defpath', ''):
|
||||
rv = shutil.which(self.file)
|
||||
self.assertEqual(rv, self.temp_file.name)
|
||||
|
||||
def test_empty_path(self):
|
||||
base_dir = os.path.dirname(self.dir)
|
||||
with support.change_cwd(path=self.dir), \
|
||||
|
@ -1633,6 +1684,23 @@ class TestWhich(unittest.TestCase):
|
|||
rv = shutil.which(self.file)
|
||||
self.assertIsNone(rv)
|
||||
|
||||
@unittest.skipUnless(sys.platform == "win32", 'test specific to Windows')
|
||||
def test_pathext(self):
|
||||
ext = ".xyz"
|
||||
temp_filexyz = tempfile.NamedTemporaryFile(dir=self.temp_dir,
|
||||
prefix="Tmp2", suffix=ext)
|
||||
os.chmod(temp_filexyz.name, stat.S_IXUSR)
|
||||
self.addCleanup(temp_filexyz.close)
|
||||
|
||||
# strip path and extension
|
||||
program = os.path.basename(temp_filexyz.name)
|
||||
program = os.path.splitext(program)[0]
|
||||
|
||||
with support.EnvironmentVarGuard() as env:
|
||||
env['PATHEXT'] = ext
|
||||
rv = shutil.which(program, path=self.temp_dir)
|
||||
self.assertEqual(rv, temp_filexyz.name)
|
||||
|
||||
|
||||
class TestWhichBytes(TestWhich):
|
||||
def setUp(self):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue