mirror of https://github.com/python/cpython
#1178141: add addinfourl.code to get http status code from urllib.
This commit is contained in:
parent
dcd6b52206
commit
9b0d46db11
|
@ -27,16 +27,17 @@ High-level interface
|
||||||
a server somewhere on the network. If the connection cannot be made the
|
a server somewhere on the network. If the connection cannot be made the
|
||||||
:exc:`IOError` exception is raised. If all went well, a file-like object is
|
:exc:`IOError` exception is raised. If all went well, a file-like object is
|
||||||
returned. This supports the following methods: :meth:`read`, :meth:`readline`,
|
returned. This supports the following methods: :meth:`read`, :meth:`readline`,
|
||||||
:meth:`readlines`, :meth:`fileno`, :meth:`close`, :meth:`info` and
|
:meth:`readlines`, :meth:`fileno`, :meth:`close`, :meth:`info`, :meth:`getcode` and
|
||||||
:meth:`geturl`. It also has proper support for the :term:`iterator` protocol. One
|
:meth:`geturl`. It also has proper support for the :term:`iterator` protocol. One
|
||||||
caveat: the :meth:`read` method, if the size argument is omitted or negative,
|
caveat: the :meth:`read` method, if the size argument is omitted or negative,
|
||||||
may not read until the end of the data stream; there is no good way to determine
|
may not read until the end of the data stream; there is no good way to determine
|
||||||
that the entire stream from a socket has been read in the general case.
|
that the entire stream from a socket has been read in the general case.
|
||||||
|
|
||||||
Except for the :meth:`info` and :meth:`geturl` methods, these methods have the
|
Except for the :meth:`info`, :meth:`getcode` and :meth:`geturl` methods,
|
||||||
same interface as for file objects --- see section :ref:`bltin-file-objects` in
|
these methods have the same interface as for file objects --- see section
|
||||||
this manual. (It is not a built-in file object, however, so it can't be used at
|
:ref:`bltin-file-objects` in this manual. (It is not a built-in file object,
|
||||||
those few places where a true built-in file object is required.)
|
however, so it can't be used at those few places where a true built-in file
|
||||||
|
object is required.)
|
||||||
|
|
||||||
.. index:: module: mimetools
|
.. index:: module: mimetools
|
||||||
|
|
||||||
|
@ -58,6 +59,9 @@ High-level interface
|
||||||
the client was redirected to. The :meth:`geturl` method can be used to get at
|
the client was redirected to. The :meth:`geturl` method can be used to get at
|
||||||
this redirected URL.
|
this redirected URL.
|
||||||
|
|
||||||
|
The :meth:`getcode` method returns the HTTP status code that was sent with the
|
||||||
|
response, or ``None`` if the URL is no HTTP URL.
|
||||||
|
|
||||||
If the *url* uses the :file:`http:` scheme identifier, the optional *data*
|
If the *url* uses the :file:`http:` scheme identifier, the optional *data*
|
||||||
argument may be given to specify a ``POST`` request (normally the request type
|
argument may be given to specify a ``POST`` request (normally the request type
|
||||||
is ``GET``). The *data* argument must be in standard
|
is ``GET``). The *data* argument must be in standard
|
||||||
|
|
|
@ -47,7 +47,7 @@ class urlopen_FileTests(unittest.TestCase):
|
||||||
def test_interface(self):
|
def test_interface(self):
|
||||||
# Make sure object returned by urlopen() has the specified methods
|
# Make sure object returned by urlopen() has the specified methods
|
||||||
for attr in ("read", "readline", "readlines", "fileno",
|
for attr in ("read", "readline", "readlines", "fileno",
|
||||||
"close", "info", "geturl", "__iter__"):
|
"close", "info", "geturl", "getcode", "__iter__"):
|
||||||
self.assert_(hasattr(self.returned_obj, attr),
|
self.assert_(hasattr(self.returned_obj, attr),
|
||||||
"object returned by urlopen() lacks %s attribute" %
|
"object returned by urlopen() lacks %s attribute" %
|
||||||
attr)
|
attr)
|
||||||
|
@ -87,6 +87,9 @@ class urlopen_FileTests(unittest.TestCase):
|
||||||
def test_geturl(self):
|
def test_geturl(self):
|
||||||
self.assertEqual(self.returned_obj.geturl(), self.pathname)
|
self.assertEqual(self.returned_obj.geturl(), self.pathname)
|
||||||
|
|
||||||
|
def test_getcode(self):
|
||||||
|
self.assertEqual(self.returned_obj.getcode(), None)
|
||||||
|
|
||||||
def test_iter(self):
|
def test_iter(self):
|
||||||
# Test iterator
|
# Test iterator
|
||||||
# Don't need to count number of iterations since test would fail the
|
# Don't need to count number of iterations since test would fail the
|
||||||
|
@ -123,6 +126,8 @@ class urlopen_HttpTests(unittest.TestCase):
|
||||||
fp = urllib.urlopen("http://python.org/")
|
fp = urllib.urlopen("http://python.org/")
|
||||||
self.assertEqual(fp.readline(), 'Hello!')
|
self.assertEqual(fp.readline(), 'Hello!')
|
||||||
self.assertEqual(fp.readline(), '')
|
self.assertEqual(fp.readline(), '')
|
||||||
|
self.assertEqual(fp.geturl(), 'http://python.org/')
|
||||||
|
self.assertEqual(fp.getcode(), 200)
|
||||||
finally:
|
finally:
|
||||||
self.unfakehttp()
|
self.unfakehttp()
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,16 @@ class urlopenNetworkTests(unittest.TestCase):
|
||||||
open_url.close()
|
open_url.close()
|
||||||
self.assertEqual(gotten_url, URL)
|
self.assertEqual(gotten_url, URL)
|
||||||
|
|
||||||
|
def test_getcode(self):
|
||||||
|
# test getcode() with the fancy opener to get 404 error codes
|
||||||
|
URL = "http://www.python.org/XXXinvalidXXX"
|
||||||
|
open_url = urllib.FancyURLopener().open(URL)
|
||||||
|
try:
|
||||||
|
code = open_url.getcode()
|
||||||
|
finally:
|
||||||
|
open_url.close()
|
||||||
|
self.assertEqual(code, 404)
|
||||||
|
|
||||||
def test_fileno(self):
|
def test_fileno(self):
|
||||||
if (sys.platform in ('win32',) or
|
if (sys.platform in ('win32',) or
|
||||||
not hasattr(os, 'fdopen')):
|
not hasattr(os, 'fdopen')):
|
||||||
|
|
|
@ -343,7 +343,7 @@ class URLopener:
|
||||||
# According to RFC 2616, "2xx" code indicates that the client's
|
# According to RFC 2616, "2xx" code indicates that the client's
|
||||||
# request was successfully received, understood, and accepted.
|
# request was successfully received, understood, and accepted.
|
||||||
if (200 <= errcode < 300):
|
if (200 <= errcode < 300):
|
||||||
return addinfourl(fp, headers, "http:" + url)
|
return addinfourl(fp, headers, "http:" + url, errcode)
|
||||||
else:
|
else:
|
||||||
if data is None:
|
if data is None:
|
||||||
return self.http_error(url, fp, errcode, errmsg, headers)
|
return self.http_error(url, fp, errcode, errmsg, headers)
|
||||||
|
@ -438,7 +438,7 @@ class URLopener:
|
||||||
# According to RFC 2616, "2xx" code indicates that the client's
|
# According to RFC 2616, "2xx" code indicates that the client's
|
||||||
# request was successfully received, understood, and accepted.
|
# request was successfully received, understood, and accepted.
|
||||||
if (200 <= errcode < 300):
|
if (200 <= errcode < 300):
|
||||||
return addinfourl(fp, headers, "https:" + url)
|
return addinfourl(fp, headers, "https:" + url, errcode)
|
||||||
else:
|
else:
|
||||||
if data is None:
|
if data is None:
|
||||||
return self.http_error(url, fp, errcode, errmsg, headers)
|
return self.http_error(url, fp, errcode, errmsg, headers)
|
||||||
|
@ -610,7 +610,7 @@ class FancyURLopener(URLopener):
|
||||||
|
|
||||||
def http_error_default(self, url, fp, errcode, errmsg, headers):
|
def http_error_default(self, url, fp, errcode, errmsg, headers):
|
||||||
"""Default error handling -- don't raise an exception."""
|
"""Default error handling -- don't raise an exception."""
|
||||||
return addinfourl(fp, headers, "http:" + url)
|
return addinfourl(fp, headers, "http:" + url, errcode)
|
||||||
|
|
||||||
def http_error_302(self, url, fp, errcode, errmsg, headers, data=None):
|
def http_error_302(self, url, fp, errcode, errmsg, headers, data=None):
|
||||||
"""Error 302 -- relocated (temporarily)."""
|
"""Error 302 -- relocated (temporarily)."""
|
||||||
|
@ -953,14 +953,18 @@ class addinfo(addbase):
|
||||||
class addinfourl(addbase):
|
class addinfourl(addbase):
|
||||||
"""class to add info() and geturl() methods to an open file."""
|
"""class to add info() and geturl() methods to an open file."""
|
||||||
|
|
||||||
def __init__(self, fp, headers, url):
|
def __init__(self, fp, headers, url, code=None):
|
||||||
addbase.__init__(self, fp)
|
addbase.__init__(self, fp)
|
||||||
self.headers = headers
|
self.headers = headers
|
||||||
self.url = url
|
self.url = url
|
||||||
|
self.code = code
|
||||||
|
|
||||||
def info(self):
|
def info(self):
|
||||||
return self.headers
|
return self.headers
|
||||||
|
|
||||||
|
def getcode(self):
|
||||||
|
return self.code
|
||||||
|
|
||||||
def geturl(self):
|
def geturl(self):
|
||||||
return self.url
|
return self.url
|
||||||
|
|
||||||
|
|
|
@ -369,6 +369,9 @@ Core and builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- #1178141: add a getcode() method to the addinfourls that urllib.open()
|
||||||
|
returns so that you can retrieve the HTTP status code.
|
||||||
|
|
||||||
- Issue #1003: Fix zipfile decryption check, it would fail zip files
|
- Issue #1003: Fix zipfile decryption check, it would fail zip files
|
||||||
with extended local headers.
|
with extended local headers.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue