Ftputil is broken with links that start with ./
An example is ftp.heanet.ie
>>> conn.path.islink('/pub/apache')
True
>>> conn.listdir('/pub/apache')
['/pub/apache']
/pub/apache is a link to ./www.apache.org
lrwxrwxrwx 1 ftp ftp 16 Jul 1 2008 /pub/apache -> ./www.apache.org
The content is the following:
ftp> ls pub/apache/
200 PORT command successful
150 Opening ASCII mode data connection for file list
-rw-rw-r-- 1 ftp ftp 1069 Oct 10 2001 404.html
drwxrwxr-x 5 ftp ftp 231 Dec 24 2006 ads
drwxrwxr-x 3 ftp ftp 1459 Mar 20 2006 ca
drwxrwxr-x 9 ftp ftp 1773 Dec 22 2006 dev
drwxrwxr-x 70 ftp ftp 1806 Apr 28 18:19 dist
drwxrwxr-x 4 ftp ftp 104 Dec 11 2006 dyn
drwxrwxr-x 3 ftp ftp 48 Dec 11 2006 errors
-rw-rw-r-- 1 ftp ftp 3638 Feb 14 2005 favicon-a.ico
-rw-rw-r-- 1 ftp ftp 3638 Feb 13 2005 favicon-c.ico
-rw-rw-r-- 1 ftp ftp 766 Sep 24 2001 favicon-old.ico
-rw-rw-r-- 1 ftp ftp 3638 Aug 19 2005 favicon.ico
drwxrwxr-x 8 ftp ftp 971 Dec 21 2006 foundation
drwxrwxr-x 3 ftp ftp 109 Dec 11 2006 history
drwxrwxr-x 3 ftp ftp 1112 Jun 22 2006 images
drwxrwxr-x 3 ftp ftp 935 Sep 24 2001 images-old
-rw-rw-r-- 1 ftp ftp 14489 Dec 21 2006 index.html
-rw-rw-r-- 1 ftp ftp 14633 Jul 9 2006 index.html.save
drwxrwxr-x 3 ftp ftp 226 Dec 24 2006 info
drwxrwxr-x 3 ftp ftp 81 Dec 11 2006 jcp
drwxrwxr-x 3 ftp ftp 143 Dec 11 2006 legal
drwxrwxr-x 5 ftp ftp 578 Dec 11 2006 licenses
lrwxrwxrwx 1 ftp ftp 39 May 25 2008 mail -> /home/apmail/public-arch/www.apache.org
drwxrwxr-x 4 ftp ftp 250 Dec 28 2006 mirrors
-rw-rw-r-- 1 ftp ftp 92186 Apr 17 2003 mlists.html
-rw-rw-r-- 1 ftp ftp 784 Dec 19 2004 phf_abuse_log.cgi
-rw-rw-r-- 1 ftp ftp 47 May 16 2006 robots.txt
drwxrwxr-x 3 ftp ftp 49 Jan 25 2005 style
226 Transfer complete
ftputil should detect all the kinds of valid links and list the dir contents,
regards Nicola
It seems this bug is implicitly fixed by the change which already fixed bug #33. :-)
Link to link are not yet correctly managed :-)
conn=ftputil.FTPHost('mirror3.mirror.garr.it','anonymous','p@p.com') conn.path.isdir('/mirrors/zebra/') --------------------------------------------------------------------------- PermanentError Traceback (most recent call last) /home/nicola/workspace/FtpManager/<ipython console> /home/nicola/workspace/FtpManager/extlib/ftputil/ftp_path.pyc in isdir(self, path) 142 return True 143 try: --> 144 stat_result = self._host.stat( 145 path, _exception_for_missing_path=False) 146 if stat_result is None: /home/nicola/workspace/FtpManager/extlib/ftputil/ftputil.pyc in stat(self, path, _exception_for_missing_path) 822 _not_ intended for use by ftputil clients.) 823 """ --> 824 return self._stat.stat(path, _exception_for_missing_path) 825 826 def walk(self, top, topdown=True, onerror=None): /home/nicola/workspace/FtpManager/extlib/ftputil/ftp_stat.pyc in stat(self, path, _exception_for_missing_path) 584 the server (e. g. timeout). 585 """ 586 return self.__call_with_parser_retry(self._real_stat, path, --> 587 _exception_for_missing_path) 588 /home/nicola/workspace/FtpManager/extlib/ftputil/ftp_stat.pyc in __call_with_parser_retry(self, method, *args, **kwargs) 541 # parser - which is wrong. 542 try: --> 543 result = method(*args, **kwargs) 544 # if a `listdir` call didn't find anything, we can't 545 # say anything about the usefulness of the parser /home/nicola/workspace/FtpManager/extlib/ftputil/ftp_stat.pyc in _real_stat(self, path, _exception_for_missing_path) 506 while True: 507 # stat the link if it is one, else the file/directory --> 508 lstat_result = self._real_lstat(path, _exception_for_missing_path) 509 if lstat_result is None: 510 return None /home/nicola/workspace/FtpManager/extlib/ftputil/ftp_stat.pyc in _real_lstat(self, path, _exception_for_missing_path) 458 # we want to collect as many stat results in the cache as 459 # possible --> 460 lines = self._host_dir(dirname) 461 for line in lines: 462 if self._parser.ignores_line(line): /home/nicola/workspace/FtpManager/extlib/ftputil/ftp_stat.pyc in _host_dir(self, path) 388 when applied to `path`. 389 """ --> 390 return self._host._dir(path) 391 392 def _real_listdir(self, path): /home/nicola/workspace/FtpManager/extlib/ftputil/ftputil.pyc in _dir(self, path) 779 return lines 780 lines = self._robust_ftp_command(_FTPHost_dir_command, path, --> 781 descend_deeply=True) 782 return lines 783 /home/nicola/workspace/FtpManager/extlib/ftputil/ftputil.pyc in _robust_ftp_command(self, command, path, descend_deeply) 562 if descend_deeply: 563 # invoke the command in (not: on) the deepest directory --> 564 self.chdir(path) 565 # workaround for some servers that give recursive 566 # listings when called with a dot as path; see issue <a href="/~sschwarzer/ftputil/33" title="~sschwarzer/ftputil#33: FTPHost.listdir fails for some servers if the path contains slashes">#33</a>, /home/nicola/workspace/FtpManager/extlib/ftputil/ftputil.pyc in chdir(self, path) 585 def chdir(self, path): 586 """Change the directory on the host.""" --> 587 ftp_error._try_with_oserror(self._session.cwd, path) 588 self._current_dir = self.path.normpath(self.path.join( 589 # use "old" current dir /home/nicola/workspace/FtpManager/extlib/ftputil/ftp_error.pyc in _try_with_oserror(callee, *args, **kwargs) 150 raise CommandNotImplementedError(*exc.args) 151 else: --> 152 raise PermanentError(*exc.args) 153 except ftplib.all_errors: 154 exc = sys.exc_info()[1] PermanentError: 550 /mirrors/1: No such file or directory Debugging info: ftputil 2.4.2b, Python 2.4.3 (linux2)
regards Nicola
Hi Nicola,
I can reproduce the traceback. However, its background is different from the original description. The target of the link /mirrors/zebra doesn't exist at all, so isdir should return False instead of causing a traceback. The behavior of FTPHost.listdir to cause a PermanentError on the other hand would be correct. In contrast, the example in the original description shows a traceback even upon a listdir call on an existing target.
I've added another ticket, #39, which is more specific and "reclose" this bug for now. :-)
Stefan