source: ftp_error.py @ 719:f3f570705fe7

Last change on this file since 719:f3f570705fe7 was 719:f3f570705fe7, checked in by Stefan Schwarzer <sschwarzer@…>, 13 years 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`.
File size: 4.6 KB
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"""
33ftp_error.py - exception classes and wrappers
34"""
35
36# $Id$
37
38# "Too many ancestors"
39# pylint: disable-msg = R0901
40
41import ftplib
42import sys
43
44import ftputil_version
45
46
47class 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
66class InternalError(FTPError):
67    """Internal error."""
68    pass
69
70class RootDirError(InternalError):
71    """Raised for generic stat calls on the remote root directory."""
72    pass
73
74class InaccessibleLoginDirError(InternalError):
75    """May be raised if the login directory isn't accessible."""
76    pass
77
78class TimeShiftError(InternalError):
79    """Raised for invalid time shift values."""
80    pass
81
82class ParserError(InternalError):
83    """Raised if a line of a remote directory can't be parsed."""
84    pass
85
86# currently not used
87class KeepAliveError(InternalError):
88    """Raised if the keep-alive feature failed."""
89    pass
90
91class FTPOSError(FTPError, OSError):
92    """Generic FTP error related to `OSError`."""
93    pass
94
95class TemporaryError(FTPOSError):
96    """Raised for temporary FTP errors (4xx)."""
97    pass
98
99class PermanentError(FTPOSError):
100    """Raised for permanent FTP errors (5xx)."""
101    pass
102
103class CommandNotImplementedError(PermanentError):
104    """Raised if the server doesn't implement a certain feature (502)."""
105    pass
106
107# currently not used
108class 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`?
114def _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
133class FTPIOError(FTPError, IOError):
134    """Generic FTP error related to `IOError`."""
135    pass
136
137def _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 repository browser.