| 1 | |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | """ |
|---|
| 5 | ftp_error.py - exception classes and wrappers |
|---|
| 6 | """ |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | |
|---|
| 10 | |
|---|
| 11 | import ftplib |
|---|
| 12 | import sys |
|---|
| 13 | import warnings |
|---|
| 14 | |
|---|
| 15 | import ftputil_version |
|---|
| 16 | |
|---|
| 17 | |
|---|
| 18 | class FTPError(Exception): |
|---|
| 19 | """General error class.""" |
|---|
| 20 | |
|---|
| 21 | def __init__(self, *args): |
|---|
| 22 | |
|---|
| 23 | |
|---|
| 24 | |
|---|
| 25 | |
|---|
| 26 | |
|---|
| 27 | |
|---|
| 28 | if args and (args[0].__class__ in ftplib.all_errors or |
|---|
| 29 | issubclass(args[0].__class__, ftplib.Error)): |
|---|
| 30 | warnings.warn(("Passing exception objects into the FTPError " |
|---|
| 31 | "constructor is deprecated and will be disabled in ftputil 2.6"), |
|---|
| 32 | DeprecationWarning, stacklevel=2) |
|---|
| 33 | try: |
|---|
| 34 | |
|---|
| 35 | super(FTPError, self).__init__(*args) |
|---|
| 36 | except TypeError: |
|---|
| 37 | |
|---|
| 38 | Exception.__init__(self, *args) |
|---|
| 39 | |
|---|
| 40 | if args: |
|---|
| 41 | self.strerror = self.args[0] |
|---|
| 42 | else: |
|---|
| 43 | self.strerror = "" |
|---|
| 44 | try: |
|---|
| 45 | self.errno = int(self.strerror[:3]) |
|---|
| 46 | except (TypeError, IndexError, ValueError): |
|---|
| 47 | self.errno = None |
|---|
| 48 | self.filename = None |
|---|
| 49 | |
|---|
| 50 | def __str__(self): |
|---|
| 51 | return "%s\nDebugging info: %s" % \ |
|---|
| 52 | (self.strerror, ftputil_version.version_info) |
|---|
| 53 | |
|---|
| 54 | |
|---|
| 55 | |
|---|
| 56 | class InternalError(FTPError): |
|---|
| 57 | """Internal error.""" |
|---|
| 58 | pass |
|---|
| 59 | |
|---|
| 60 | class RootDirError(InternalError): |
|---|
| 61 | """Raised for generic stat calls on the remote root directory.""" |
|---|
| 62 | pass |
|---|
| 63 | |
|---|
| 64 | class InaccessibleLoginDirError(InternalError): |
|---|
| 65 | """May be raised if the login directory isn't accessible.""" |
|---|
| 66 | pass |
|---|
| 67 | |
|---|
| 68 | class TimeShiftError(InternalError): |
|---|
| 69 | """Raised for invalid time shift values.""" |
|---|
| 70 | pass |
|---|
| 71 | |
|---|
| 72 | class ParserError(InternalError): |
|---|
| 73 | """Raised if a line of a remote directory can't be parsed.""" |
|---|
| 74 | pass |
|---|
| 75 | |
|---|
| 76 | |
|---|
| 77 | class KeepAliveError(InternalError): |
|---|
| 78 | """Raised if the keep-alive feature failed.""" |
|---|
| 79 | pass |
|---|
| 80 | |
|---|
| 81 | class FTPOSError(FTPError, OSError): |
|---|
| 82 | """Generic FTP error related to `OSError`.""" |
|---|
| 83 | pass |
|---|
| 84 | |
|---|
| 85 | class TemporaryError(FTPOSError): |
|---|
| 86 | """Raised for temporary FTP errors (4xx).""" |
|---|
| 87 | pass |
|---|
| 88 | |
|---|
| 89 | class PermanentError(FTPOSError): |
|---|
| 90 | """Raised for permanent FTP errors (5xx).""" |
|---|
| 91 | pass |
|---|
| 92 | |
|---|
| 93 | class CommandNotImplementedError(PermanentError): |
|---|
| 94 | """Raised if the server doesn't implement a certain feature (502).""" |
|---|
| 95 | pass |
|---|
| 96 | |
|---|
| 97 | |
|---|
| 98 | class SyncError(PermanentError): |
|---|
| 99 | """Raised for problems specific to syncing directories.""" |
|---|
| 100 | pass |
|---|
| 101 | |
|---|
| 102 | |
|---|
| 103 | |
|---|
| 104 | |
|---|
| 105 | def _try_with_oserror(callee, *args, **kwargs): |
|---|
| 106 | """ |
|---|
| 107 | Try the callee with the given arguments and map resulting |
|---|
| 108 | exceptions from `ftplib.all_errors` to `FTPOSError` and its |
|---|
| 109 | derived classes. |
|---|
| 110 | """ |
|---|
| 111 | |
|---|
| 112 | |
|---|
| 113 | try: |
|---|
| 114 | return callee(*args, **kwargs) |
|---|
| 115 | except ftplib.error_temp, exc: |
|---|
| 116 | raise TemporaryError(*exc.args) |
|---|
| 117 | except ftplib.error_perm, exc: |
|---|
| 118 | |
|---|
| 119 | if exc.args and exc.args[0].startswith("502"): |
|---|
| 120 | raise CommandNotImplementedError(*exc.args) |
|---|
| 121 | else: |
|---|
| 122 | raise PermanentError(*exc.args) |
|---|
| 123 | except ftplib.all_errors: |
|---|
| 124 | exc = sys.exc_info()[1] |
|---|
| 125 | raise FTPOSError(*exc.args) |
|---|
| 126 | |
|---|
| 127 | class FTPIOError(FTPError, IOError): |
|---|
| 128 | """Generic FTP error related to `IOError`.""" |
|---|
| 129 | pass |
|---|
| 130 | |
|---|
| 131 | |
|---|
| 132 | def _try_with_ioerror(callee, *args, **kwargs): |
|---|
| 133 | """ |
|---|
| 134 | Try the callee with the given arguments and map resulting |
|---|
| 135 | exceptions from `ftplib.all_errors` to `FTPIOError`. |
|---|
| 136 | """ |
|---|
| 137 | try: |
|---|
| 138 | return callee(*args, **kwargs) |
|---|
| 139 | except ftplib.all_errors: |
|---|
| 140 | exc = sys.exc_info()[1] |
|---|
| 141 | |
|---|
| 142 | |
|---|
| 143 | raise FTPIOError(*exc.args) |
|---|