Merge pull request #1062 from Carreau/allow-broken-symlink-on-path

Don't crash if broken symlink on path.
This commit is contained in:
Morten Enemark Lund 2016-06-03 20:51:18 +02:00
commit dc838fdaf0
2 changed files with 42 additions and 23 deletions

View file

@ -591,29 +591,37 @@ def test_partial_string():
def test_executables_in():
expected = set()
types = ('none', 'file', 'file', 'directory')
executables = (True, True, False)
types = ('file', 'directory', 'brokensymlink')
executables = (True, False)
with TemporaryDirectory() as test_path:
for i in range(64):
_type = types[i%len(types)]
if _type == 'none':
continue
executable = executables[i%len(executables)]
if _type == 'file' and executable:
ext = '.exe' if ON_WINDOWS else ''
expected.add(str(i) + ext)
else:
ext = ''
path = os.path.join(test_path, str(i) + ext)
if _type == 'file':
with open(path, 'w') as f:
f.write(str(i))
elif _type == 'directory':
os.mkdir(path)
if executable:
os.chmod(path, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR)
result = set(executables_in(test_path))
for _type in types:
for executable in executables:
fname = '%s_%s' % (_type, executable)
if _type == 'none':
continue
if _type == 'file' and executable:
ext = '.exe' if ON_WINDOWS else ''
expected.add(fname + ext)
else:
ext = ''
path = os.path.join(test_path, fname + ext)
if _type == 'file':
with open(path, 'w') as f:
f.write(fname)
elif _type == 'directory':
os.mkdir(path)
elif _type == 'brokensymlink':
tmp_path = os.path.join(test_path, 'i_wont_exist')
with open(tmp_path,'w') as f:
f.write('deleteme')
os.symlink(tmp_path, path)
os.remove(tmp_path)
if executable and not _type == 'brokensymlink' :
os.chmod(path, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR)
result = set(executables_in(test_path))
assert_equal(expected, result)

View file

@ -312,6 +312,18 @@ class redirect_stderr(_RedirectStream):
_stream = "stderr"
def _yield_accessible_unix_file_names(path):
"yield file names of executablel files in `path`"
for file_ in scandir(path):
try:
if file_.is_file() and os.access(file_.path, os.X_OK):
yield file_.name
except NotADirectoryError:
# broken Symlink are neither dir not files
pass
def _executables_in_posix(path):
if PYTHON_VERSION_INFO < (3, 5, 0):
for fname in os.listdir(path):
@ -320,8 +332,7 @@ def _executables_in_posix(path):
(not os.path.isdir(fpath))):
yield fname
else:
yield from (x.name for x in scandir(path)
if x.is_file() and os.access(x.path, os.X_OK))
yield from _yield_accessible_unix_file_names(path)
def _executables_in_windows(path):