Opened 10 years ago

Closed 10 years ago

Last modified 10 years ago

#36 closed defect (fixed)

ftputil's exceptions use super, this won't work with Python <2.5

Reported by: ftputiluser Owned by: schwa
Priority: major Milestone: 2.4.1
Component: Library Version: 2.4
Keywords: Exception, classic class, new-style class Cc:

Description

Seems there is a bug with python 2.4 and ftputil 2.4, look at this:

In [2]: host=ftputil.FTPHost('ftp.microsoft.com','anonymous','test@test.com')

In [3]: host.listdir('/')
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

/home/nicola/workspace/FtpManager/<ipython console> 

/home/nicola/workspace/FtpManager/ftputil/ftputil.py in listdir(self, path)
    800         any of the available parsers raise a `ParserError`.        
    801         """                                                        
--> 802         return self._stat.listdir(path)                            
    803                                                                    
    804     def lstat(self, path, _exception_for_missing_path=True):       

/home/nicola/workspace/FtpManager/ftputil/ftp_stat.py in listdir(self, path)
    560         the server (e. g. timeout).                                 
    561         """                                                         
--> 562         return self.__call_with_parser_retry(self._real_listdir, path)
    563                                                                       
    564     def lstat(self, path, _exception_for_missing_path=True):          

/home/nicola/workspace/FtpManager/ftputil/ftp_stat.py in __call_with_parser_retry(self, method, *args, **kwargs)                                                                                            
    538         #  parser - which is wrong.                                                           
    539         try:                                                                                  
--> 540             result = method(*args, **kwargs)                                                  
    541             # if a `listdir` call didn't find anything, we can't                              
    542             #  say anything about the usefulness of the parser                                

/home/nicola/workspace/FtpManager/ftputil/ftp_stat.py in _real_listdir(self, path)
    415             #  correct timestamp values in the cache
    416             stat_result = self._parser.parse_line(line,
--> 417                                                   self._host.time_shift())
    418             loop_path = self._path.join(path, stat_result._st_name)
    419             self._lstat_cache[loop_path] = stat_result

/home/nicola/workspace/FtpManager/ftputil/ftp_stat.py in parse_line(self, line, time_shift)
    278         If the line can't be parsed, raise a `ParserError`.
    279         """
--> 280         mode_string, nlink, user, group, size, month, day, \
    281           year_or_time, name = self._split_line(line)
    282         # st_mode

/home/nicola/workspace/FtpManager/ftputil/ftp_stat.py in _split_line(self, line)
    268         else:
    269             # no known Unix-style format
--> 270             raise ftp_error.ParserError("line '%s' can't be parsed" % line)
    271
    272     def parse_line(self, line, time_shift=0.0):

/home/nicola/workspace/FtpManager/ftputil/ftp_error.py in __init__(self, ftp_exception)
     49
     50     def __init__(self, ftp_exception):
---> 51         super(FTPError, self).__init__(ftp_exception)
     52         # `message` is set by the base class
     53         self.strerror = self.message

TypeError: super() argument 1 must be type, not classobj

I can repeat this error on centos5/redhat5 (python 2.4.3) and debian etch (python 2.4.4) with ftputil 2.4. If I downgrade to ftputil 2.3 or 2.2.4 all works fine on both etch and centos. The same ftp host with python 2.6 and ftputil 2.4 works just fine. I actually don't have python 2.5.

regards Nicola

Change History (3)

comment:1 Changed 10 years ago by schwa

  • Keywords Exception classic class new-style class added
  • Status changed from new to assigned
  • Summary changed from ftputil 2.4 listdir and python < 2.6 to ftputil's exceptions use super, this won't work with Python <2.5
  • Version set to 2.4

I can confirm this bug.

On Python 2.4:

$ python2.4
Python 2.4.5 (#2, Aug  1 2008, 02:20:59) 
[GCC 4.3.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import ftputil
>>> host=ftputil.FTPHost('ftp.microsoft.com','anonymous','test@test.com')
>>> host.listdir('/')
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "ftputil.py", line 801, in listdir
    return self._stat.listdir(path)
  File "ftp_stat.py", line 562, in listdir
    return self.__call_with_parser_retry(self._real_listdir, path)
  File "ftp_stat.py", line 540, in __call_with_parser_retry
    result = method(*args, **kwargs)
  File "ftp_stat.py", line 417, in _real_listdir
    self._host.time_shift())
  File "ftp_stat.py", line 280, in parse_line
    mode_string, nlink, user, group, size, month, day, \
  File "ftp_stat.py", line 270, in _split_line
    raise ftp_error.ParserError("line '%s' can't be parsed" % line)
  File "ftp_error.py", line 51, in __init__
    super(FTPError, self).__init__(ftp_exception)
TypeError: super() argument 1 must be type, not classobj

By contrast, on Python 2.5:

$ python2.5
Python 2.5.2 (r252:60911, Oct  5 2008, 19:24:49) 
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import ftputil
>>> host=ftputil.FTPHost('ftp.microsoft.com','anonymous','test@test.com')
>>> host.listdir('/')
['bussys', 'deskapps', 'developr', 'KBHelp', 'MISC', 'MISC1', 'peropsys', 'Products', 'PSS', 'ResKit', 'Services', 'Softlib']

The reason is not that something's wrong with the parser but that Python 2.5's Exception, which is the base class of the ftputil exceptions, is a new-style class, whereas in Python 2.4 it's a classic class. And classic classes can't be used together with super in them like I've done.

I already have a fix on my mind, so there's no need for you to hand one in. :-)

comment:2 Changed 10 years ago by schwa

  • Resolution set to fixed
  • Status changed from assigned to closed

Fixed in changeset 859.

I had thought that it would be enough to make FTPOSError a new-style class. However, Python 2.4 refuses classes to be raised which aren't classic classes or their instances.

comment:3 Changed 10 years ago by schwa

  • Milestone set to 2.4.1
Note: See TracTickets for help on using tickets.