summaryrefslogtreecommitdiffstats
path: root/Lib/test/support.py
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/test/support.py
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/test/support.py')
-rw-r--r--Lib/test/support.py32
1 files changed, 24 insertions, 8 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__?