summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2010-09-07 21:09:09 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2010-09-07 21:09:09 (GMT)
commit8bc09039ed7a2aa9d878e82419baf3402c48600d (patch)
treea7684250e1ec70d80b90d9b6a500bee22c5ed29c /Lib
parent4b92b5fad3baaa22a3ab198556e1adf5a2df7d9c (diff)
downloadcpython-8bc09039ed7a2aa9d878e82419baf3402c48600d.zip
cpython-8bc09039ed7a2aa9d878e82419baf3402c48600d.tar.gz
cpython-8bc09039ed7a2aa9d878e82419baf3402c48600d.tar.bz2
Improve transient_internet() again to detect more network errors,
and use it in test_robotparser. Fixes #8574.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/test/support.py32
-rw-r--r--Lib/test/test_robotparser.py29
2 files changed, 39 insertions, 22 deletions
diff --git a/Lib/test/support.py b/Lib/test/support.py
index 64c9a86..6ce5ebf 100644
--- a/Lib/test/support.py
+++ b/Lib/test/support.py
@@ -787,8 +787,18 @@ ioerror_peer_reset = TransientResource(IOError, errno=errno.ECONNRESET)
def transient_internet(resource_name, *, timeout=30.0, errnos=()):
"""Return a context manager that raises ResourceDenied when various issues
with the Internet connection manifest themselves as exceptions."""
+ default_errnos = [
+ ('ECONNREFUSED', 111),
+ ('ECONNRESET', 104),
+ ('ENETUNREACH', 101),
+ ('ETIMEDOUT', 110),
+ ]
+
denied = ResourceDenied("Resource '%s' is not available" % resource_name)
- captured_errnos = errnos or (errno.ETIMEDOUT, errno.ECONNRESET)
+ captured_errnos = errnos
+ if not captured_errnos:
+ captured_errnos = [getattr(errno, name, num)
+ for (name, num) in default_errnos]
def filter_error(err):
if (isinstance(err, socket.timeout) or
@@ -803,14 +813,20 @@ def transient_internet(resource_name, *, timeout=30.0, errnos=()):
socket.setdefaulttimeout(timeout)
yield
except IOError as err:
- # socket.error inherits IOError
+ # urllib can wrap original socket errors multiple times (!), we must
+ # unwrap to get at the original error.
+ while True:
+ a = err.args
+ if len(a) >= 1 and isinstance(a[0], IOError):
+ err = a[0]
+ # The error can also be wrapped as args[1]:
+ # except socket.error as msg:
+ # raise IOError('socket error', msg).with_traceback(sys.exc_info()[2])
+ elif len(a) >= 2 and isinstance(a[1], IOError):
+ err = a[1]
+ else:
+ break
filter_error(err)
- # urllib.request wraps the original socket.error with IOerror:
- #
- # except socket.error as msg:
- # raise IOError('socket error', msg).with_traceback(sys.exc_info()[2])
- if len(err.args) >= 2 and isinstance(err.args[1], socket.error):
- filter_error(err.args[1])
raise
# XXX should we catch generic exceptions and look for their
# __cause__ or __context__?
diff --git a/Lib/test/test_robotparser.py b/Lib/test/test_robotparser.py
index fd00706..2a6d047 100644
--- a/Lib/test/test_robotparser.py
+++ b/Lib/test/test_robotparser.py
@@ -235,23 +235,24 @@ class NetworkTestCase(unittest.TestCase):
def testPasswordProtectedSite(self):
support.requires('network')
- # XXX it depends on an external resource which could be unavailable
- url = 'http://mueblesmoraleda.com'
- parser = urllib.robotparser.RobotFileParser()
- parser.set_url(url)
- try:
- parser.read()
- except URLError:
- self.skipTest('%s is unavailable' % url)
- self.assertEqual(parser.can_fetch("*", url+"/robots.txt"), False)
+ with support.transient_internet('mueblesmoraleda.com'):
+ url = 'http://mueblesmoraleda.com'
+ parser = urllib.robotparser.RobotFileParser()
+ parser.set_url(url)
+ try:
+ parser.read()
+ except URLError:
+ self.skipTest('%s is unavailable' % url)
+ self.assertEqual(parser.can_fetch("*", url+"/robots.txt"), False)
def testPythonOrg(self):
support.requires('network')
- parser = urllib.robotparser.RobotFileParser(
- "http://www.python.org/robots.txt")
- parser.read()
- self.assertTrue(parser.can_fetch("*",
- "http://www.python.org/robots.txt"))
+ with support.transient_internet('www.python.org'):
+ parser = urllib.robotparser.RobotFileParser(
+ "http://www.python.org/robots.txt")
+ parser.read()
+ self.assertTrue(
+ parser.can_fetch("*", "http://www.python.org/robots.txt"))
def test_main():
support.run_unittest(NetworkTestCase)