1"""Exception classes raised by urllib.
2
3The base exception class is URLError, which inherits from IOError.  It
4doesn't define any behavior of its own, but is the base class for all
5exceptions defined in this package.
6
7HTTPError is an exception class that is also a valid HTTP response
8instance.  It behaves this way because HTTP protocol errors are valid
9responses, with a status code, headers, and a body.  In some contexts,
10an application may want to handle an exception like a regular
11response.
12"""
13from __future__ import absolute_import, division, unicode_literals
14from future import standard_library
15
16from future.backports.urllib import response as urllib_response
17
18
19__all__ = ['URLError', 'HTTPError', 'ContentTooShortError']
20
21
22# do these error classes make sense?
23# make sure all of the IOError stuff is overridden.  we just want to be
24# subtypes.
25
26class URLError(IOError):
27    # URLError is a sub-type of IOError, but it doesn't share any of
28    # the implementation.  need to override __init__ and __str__.
29    # It sets self.args for compatibility with other EnvironmentError
30    # subclasses, but args doesn't have the typical format with errno in
31    # slot 0 and strerror in slot 1.  This may be better than nothing.
32    def __init__(self, reason, filename=None):
33        self.args = reason,
34        self.reason = reason
35        if filename is not None:
36            self.filename = filename
37
38    def __str__(self):
39        return '<urlopen error %s>' % self.reason
40
41class HTTPError(URLError, urllib_response.addinfourl):
42    """Raised when HTTP error occurs, but also acts like non-error return"""
43    __super_init = urllib_response.addinfourl.__init__
44
45    def __init__(self, url, code, msg, hdrs, fp):
46        self.code = code
47        self.msg = msg
48        self.hdrs = hdrs
49        self.fp = fp
50        self.filename = url
51        # The addinfourl classes depend on fp being a valid file
52        # object.  In some cases, the HTTPError may not have a valid
53        # file object.  If this happens, the simplest workaround is to
54        # not initialize the base classes.
55        if fp is not None:
56            self.__super_init(fp, hdrs, url, code)
57
58    def __str__(self):
59        return 'HTTP Error %s: %s' % (self.code, self.msg)
60
61    # since URLError specifies a .reason attribute, HTTPError should also
62    #  provide this attribute. See issue13211 for discussion.
63    @property
64    def reason(self):
65        return self.msg
66
67    def info(self):
68        return self.hdrs
69
70
71# exception raised when downloaded size does not match content-length
72class ContentTooShortError(URLError):
73    def __init__(self, message, content):
74        URLError.__init__(self, message)
75        self.content = content
76