If isdir and isfile are used on a link whose target doesn't exist, they raise a PermanentError though they should return False, similar to os.path.isdir/isfile.
Example:
>>> conn=ftputil.FTPHost('mirror3.mirror.garr.it','anonymous','p@p.com')
>>> conn.path.islink("/mirrors/zebra")
True
>>> conn.lstat("/mirrors/zebra")._st_target
'../1/zebra'
>>> conn.path.exists("/mirrors/1")
False
>>> conn.path.isdir("/mirrors/zebra")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "ftp_path.py", line 145, in isdir
path, _exception_for_missing_path=False)
File "ftputil.py", line 824, in stat
return self._stat.stat(path, _exception_for_missing_path)
File "ftp_stat.py", line 587, in stat
_exception_for_missing_path)
File "ftp_stat.py", line 543, in __call_with_parser_retry
result = method(*args, **kwargs)
File "ftp_stat.py", line 508, in _real_stat
lstat_result = self._real_lstat(path, _exception_for_missing_path)
File "ftp_stat.py", line 460, in _real_lstat
lines = self._host_dir(dirname)
File "ftp_stat.py", line 390, in _host_dir
return self._host._dir(path)
File "ftputil.py", line 781, in _dir
descend_deeply=True)
File "ftputil.py", line 564, in _robust_ftp_command
self.chdir(path)
File "ftputil.py", line 587, in chdir
ftp_error._try_with_oserror(self._session.cwd, path)
File "ftp_error.py", line 152, in _try_with_oserror
raise PermanentError(*exc.args)
ftp_error.PermanentError: 550 /1: No such file or directory
Debugging info: ftputil 2.4.2b, Python 2.6.2 (linux2)
One might think that FTPHost.path.exists is broken, but Nautilus 2.26.2 (Gnone file manager) also denotes the link as "(broken)".
I've just checked in a test case, changeset 884. This tests the path "dir_with_broken_link/nonexistent" (without a directory change beforehand).
Seemingly the whole thing is even a bit more involved. The bug isn't triggered by a mere broken link but only by special ones. For example, these link targets cause tracebacks:
- nonexistent/nonexistent
- ../nonexistent/nonexistent
- /nonexistent/nonexistent
- ./nonexistent
But these don't:
- nonexistent
- ../nonexistent
- /nonexistent
This issue seems to be a duplicate of that in ticket #66. The traceback looks like it, and the unit test I wrote then for this ticket passes now.