Changeset 772:2166f443d615

Show
Ignore:
Timestamp:
2009-04-05 16:28:42 (17 months ago)
Author:
Stefan Schwarzer <sschwarzer@…>
Branch:
default
convert_revision:
svn:778c30c8-61e0-0310-89d4-fe2f97a467b2/trunk@809
Message:
Make the `ftp_error` module more robust with respect to `ftplib`
exceptions containing bytestrings or unicode strings or no strings
at all. Normally, `ftplib` exceptions will only contain bytestrings
but that may not be true for subclasses of `ftplib` exception
classes in third-party modules.
Files:
1 added
2 modified

Legend:

Unmodified
Added
Removed
  • MANIFEST

    r768 r772  
    2020setup.py 
    2121_test_base.py 
     22_test_ftp_error.py 
    2223_test_ftp_file.py 
    2324_test_ftp_path.py 
  • ftp_error.py

    r719 r772  
    1 # Copyright (C) 2003-2008, Stefan Schwarzer <sschwarzer@sschwarzer.net> 
     1# Copyright (C) 2003-2009, Stefan Schwarzer <sschwarzer@sschwarzer.net> 
    22# All rights reserved. 
    33# 
     
    4141import ftplib 
    4242import sys 
     43import warnings 
    4344 
    4445import ftputil_version 
     
    4849    """General error class.""" 
    4950 
    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 
     51    def __init__(self, *args): 
     52        # contrary to what `ftplib`'s documentation says, `all_errors` 
     53        #  does _not_ contain the subclasses, so I explicitly add them 
     54        if args and args[0].__class__ in ftplib.all_errors + \ 
     55                                         tuple(ftplib.Error.__subclasses__()): 
     56            warnings.warn(("Passing exception objects into the FTPError " 
     57              "constructor is deprecated and will be disabled in ftputil 2.6"), 
     58              DeprecationWarning, stacklevel=2) 
     59        super(FTPError, self).__init__(*args) 
     60        # don't use `args[0]` because `args` may be empty 
     61        if args: 
     62            self.strerror = self.args[0] 
     63        else: 
     64            self.strerror = "" 
    5465        try: 
    5566            self.errno = int(self.strerror[:3]) 
     
    110121    pass 
    111122 
     123 
    112124#XXX Do you know better names for `_try_with_oserror` and 
    113125#    `_try_with_ioerror`? 
     
    118130    derived classes. 
    119131    """ 
     132    # use `*exc.args` instead of `str(args)` because args might be 
     133    #  a unicode string with non-ascii characters 
    120134    try: 
    121135        return callee(*args, **kwargs) 
    122     except ftplib.error_temp, obj: 
    123         raise TemporaryError(obj) 
    124     except ftplib.error_perm, obj: 
    125         if str(obj).startswith("502"): 
    126             raise CommandNotImplementedError(obj) 
     136    except ftplib.error_temp, exc: 
     137        raise TemporaryError(*exc.args) 
     138    except ftplib.error_perm, exc: 
     139        # if `exc.args` is present, assume it's a byte or unicode string 
     140        if exc.args and exc.args[0].startswith("502"): 
     141            raise CommandNotImplementedError(*exc.args) 
    127142        else: 
    128             raise PermanentError(obj) 
     143            raise PermanentError(*exc.args) 
    129144    except ftplib.all_errors: 
    130         ftp_error = sys.exc_info()[1] 
    131         raise FTPOSError(ftp_error) 
     145        exc = sys.exc_info()[1] 
     146        raise FTPOSError(*exc.args) 
    132147 
    133148class FTPIOError(FTPError, IOError): 
    134149    """Generic FTP error related to `IOError`.""" 
    135150    pass 
     151 
    136152 
    137153def _try_with_ioerror(callee, *args, **kwargs): 
     
    143159        return callee(*args, **kwargs) 
    144160    except ftplib.all_errors: 
    145         ftp_error = sys.exc_info()[1] 
    146         raise FTPIOError(ftp_error) 
     161        exc = sys.exc_info()[1] 
     162        # use `*exc.args` instead of `str(args)` because args might be 
     163        #  a unicode string with non-ascii characters 
     164        raise FTPIOError(*exc.args) 
    147165