root/trunk/ftp_error.py

Revision 754, 4.6 kB (checked in by schwa, 3 weeks ago)
Removed confusing part of docstring. After all, commands like
`listdir` raise an `FTPOSError` if they don't find a path. Rather,
`FTPIOError` is used if Python accessing a local filesystem would
raise an `IOError`. For example: `ftp_host.open("nonexistent")`
raises an `FTPIOError`.
  • Property svn:mime-type set to text/x-python
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1 # Copyright (C) 2003-2008, Stefan Schwarzer <sschwarzer@sschwarzer.net>
2 # All rights reserved.
3 #
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are
6 # met:
7 #
8 # - Redistributions of source code must retain the above copyright
9 #   notice, this list of conditions and the following disclaimer.
10 #
11 # - Redistributions in binary form must reproduce the above copyright
12 #   notice, this list of conditions and the following disclaimer in the
13 #   documentation and/or other materials provided with the distribution.
14 #
15 # - Neither the name of the above author nor the names of the
16 #   contributors to the software may be used to endorse or promote
17 #   products derived from this software without specific prior written
18 #   permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
24 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32 """
33 ftp_error.py - exception classes and wrappers
34 """
35
36 # $Id$
37
38 # "Too many ancestors"
39 # pylint: disable-msg = R0901
40
41 import ftplib
42 import sys
43
44 import ftputil_version
45
46
47 class FTPError(Exception):
48     """General error class."""
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
54         try:
55             self.errno = int(self.strerror[:3])
56         except (TypeError, IndexError, ValueError):
57             self.errno = None
58         self.filename = None
59
60     def __str__(self):
61         return "%s\nDebugging info: %s" % \
62                (self.strerror, ftputil_version.version_info)
63
64 # internal errors are those that have more to do with the inner
65 #  workings of ftputil than with errors on the server side
66 class InternalError(FTPError):
67     """Internal error."""
68     pass
69
70 class RootDirError(InternalError):
71     """Raised for generic stat calls on the remote root directory."""
72     pass
73
74 class InaccessibleLoginDirError(InternalError):
75     """May be raised if the login directory isn't accessible."""
76     pass
77
78 class TimeShiftError(InternalError):
79     """Raised for invalid time shift values."""
80     pass
81
82 class ParserError(InternalError):
83     """Raised if a line of a remote directory can't be parsed."""
84     pass
85
86 # currently not used
87 class KeepAliveError(InternalError):
88     """Raised if the keep-alive feature failed."""
89     pass
90
91 class FTPOSError(FTPError, OSError):
92     """Generic FTP error related to `OSError`."""
93     pass
94
95 class TemporaryError(FTPOSError):
96     """Raised for temporary FTP errors (4xx)."""
97     pass
98
99 class PermanentError(FTPOSError):
100     """Raised for permanent FTP errors (5xx)."""
101     pass
102
103 class CommandNotImplementedError(PermanentError):
104     """Raised if the server doesn't implement a certain feature (502)."""
105     pass
106
107 # currently not used
108 class SyncError(PermanentError):
109     """Raised for problems specific to syncing directories."""
110     pass
111
112 #XXX Do you know better names for `_try_with_oserror` and
113 #    `_try_with_ioerror`?
114 def _try_with_oserror(callee, *args, **kwargs):
115     """
116     Try the callee with the given arguments and map resulting
117     exceptions from `ftplib.all_errors` to `FTPOSError` and its
118     derived classes.
119     """
120     try:
121         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)
127         else:
128             raise PermanentError(obj)
129     except ftplib.all_errors:
130         ftp_error = sys.exc_info()[1]
131         raise FTPOSError(ftp_error)
132
133 class FTPIOError(FTPError, IOError):
134     """Generic FTP error related to `IOError`."""
135     pass
136
137 def _try_with_ioerror(callee, *args, **kwargs):
138     """
139     Try the callee with the given arguments and map resulting
140     exceptions from `ftplib.all_errors` to `FTPIOError`.
141     """
142     try:
143         return callee(*args, **kwargs)
144     except ftplib.all_errors:
145         ftp_error = sys.exc_info()[1]
146         raise FTPIOError(ftp_error)
147
Note: See TracBrowser for help on using the browser.