| [772] | 1 | |
|---|
| [869] | 2 | |
|---|
| [214] | 3 | |
|---|
| 4 | """ |
|---|
| 5 | ftp_error.py - exception classes and wrappers |
|---|
| 6 | """ |
|---|
| 7 | |
|---|
| [714] | 8 | |
|---|
| 9 | |
|---|
| 10 | |
|---|
| [214] | 11 | import ftplib |
|---|
| 12 | import sys |
|---|
| [772] | 13 | import warnings |
|---|
| [214] | 14 | |
|---|
| [499] | 15 | import ftputil_version |
|---|
| 16 | |
|---|
| [214] | 17 | |
|---|
| [618] | 18 | class FTPError(Exception): |
|---|
| [214] | 19 | """General error class.""" |
|---|
| [714] | 20 | |
|---|
| [772] | 21 | def __init__(self, *args): |
|---|
| [778] | 22 | |
|---|
| 23 | |
|---|
| 24 | |
|---|
| 25 | |
|---|
| [772] | 26 | |
|---|
| 27 | |
|---|
| [791] | 28 | if args and (args[0].__class__ in ftplib.all_errors or |
|---|
| 29 | issubclass(args[0].__class__, ftplib.Error)): |
|---|
| [772] | 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) |
|---|
| [791] | 33 | try: |
|---|
| 34 | |
|---|
| 35 | super(FTPError, self).__init__(*args) |
|---|
| 36 | except TypeError: |
|---|
| 37 | |
|---|
| 38 | Exception.__init__(self, *args) |
|---|
| [772] | 39 | |
|---|
| 40 | if args: |
|---|
| 41 | self.strerror = self.args[0] |
|---|
| 42 | else: |
|---|
| 43 | self.strerror = "" |
|---|
| [214] | 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): |
|---|
| [499] | 51 | return "%s\nDebugging info: %s" % \ |
|---|
| 52 | (self.strerror, ftputil_version.version_info) |
|---|
| [214] | 53 | |
|---|
| [464] | 54 | |
|---|
| 55 | |
|---|
| [714] | 56 | class InternalError(FTPError): |
|---|
| 57 | """Internal error.""" |
|---|
| 58 | pass |
|---|
| [214] | 59 | |
|---|
| [714] | 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 |
|---|
| [214] | 101 | |
|---|
| [772] | 102 | |
|---|
| [214] | 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 | """ |
|---|
| [772] | 111 | |
|---|
| 112 | |
|---|
| [214] | 113 | try: |
|---|
| 114 | return callee(*args, **kwargs) |
|---|
| [772] | 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) |
|---|
| [705] | 121 | else: |
|---|
| [772] | 122 | raise PermanentError(*exc.args) |
|---|
| [214] | 123 | except ftplib.all_errors: |
|---|
| [772] | 124 | exc = sys.exc_info()[1] |
|---|
| 125 | raise FTPOSError(*exc.args) |
|---|
| [214] | 126 | |
|---|
| [714] | 127 | class FTPIOError(FTPError, IOError): |
|---|
| [719] | 128 | """Generic FTP error related to `IOError`.""" |
|---|
| [714] | 129 | pass |
|---|
| [214] | 130 | |
|---|
| [772] | 131 | |
|---|
| [214] | 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: |
|---|
| [772] | 140 | exc = sys.exc_info()[1] |
|---|
| 141 | |
|---|
| 142 | |
|---|
| 143 | raise FTPIOError(*exc.args) |
|---|