Skip to content

Commit a88c83c

Browse files
committed
Issue #8574: better implementation of test.support.transient_internet().
Original patch by Victor.
1 parent f015b3f commit a88c83c

2 files changed

Lines changed: 35 additions & 11 deletions

File tree

Lib/test/support.py

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"check_warnings", "CleanImport", "EnvironmentVarGuard",
3636
"TransientResource", "captured_output", "captured_stdout",
3737
"time_out", "socket_peer_reset", "ioerror_peer_reset",
38-
"run_with_locale", 'temp_umask',
38+
"run_with_locale", 'temp_umask', "transient_internet",
3939
"set_memlimit", "bigmemtest", "bigaddrspacetest", "BasicTestRunner",
4040
"run_unittest", "run_doctest", "threading_setup", "threading_cleanup",
4141
"reap_children", "cpython_only", "check_impl_detail", "get_attribute",
@@ -775,23 +775,47 @@ def __exit__(self, type_=None, value=None, traceback=None):
775775
else:
776776
raise ResourceDenied("an optional resource is not available")
777777

778-
779778
# Context managers that raise ResourceDenied when various issues
780779
# with the Internet connection manifest themselves as exceptions.
780+
# XXX deprecate these and use transient_internet() instead
781781
time_out = TransientResource(IOError, errno=errno.ETIMEDOUT)
782782
socket_peer_reset = TransientResource(socket.error, errno=errno.ECONNRESET)
783783
ioerror_peer_reset = TransientResource(IOError, errno=errno.ECONNRESET)
784784

785785

786786
@contextlib.contextmanager
787-
def transient_internet():
787+
def transient_internet(resource_name, *, timeout=30.0, errnos=()):
788788
"""Return a context manager that raises ResourceDenied when various issues
789789
with the Internet connection manifest themselves as exceptions."""
790-
time_out = TransientResource(IOError, errno=errno.ETIMEDOUT)
791-
socket_peer_reset = TransientResource(socket.error, errno=errno.ECONNRESET)
792-
ioerror_peer_reset = TransientResource(IOError, errno=errno.ECONNRESET)
793-
with time_out, socket_peer_reset, ioerror_peer_reset:
790+
denied = ResourceDenied("Resource '%s' is not available" % resource_name)
791+
captured_errnos = errnos or (errno.ETIMEDOUT, errno.ECONNRESET)
792+
793+
def filter_error(err):
794+
if (isinstance(err, socket.timeout) or
795+
getattr(err, 'errno', None) in captured_errnos):
796+
if not verbose:
797+
sys.stderr.write(denied.args[0] + "\n")
798+
raise denied from err
799+
800+
old_timeout = socket.getdefaulttimeout()
801+
try:
802+
if timeout is not None:
803+
socket.setdefaulttimeout(timeout)
794804
yield
805+
except IOError as err:
806+
# socket.error inherits IOError
807+
filter_error(err)
808+
# urllib.request wraps the original socket.error with IOerror:
809+
#
810+
# except socket.error as msg:
811+
# raise IOError('socket error', msg).with_traceback(sys.exc_info()[2])
812+
if len(err.args) >= 2 and isinstance(err.args[1], socket.error):
813+
filter_error(err.args[1])
814+
raise
815+
# XXX should we catch generic exceptions and look for their
816+
# __cause__ or __context__?
817+
finally:
818+
socket.setdefaulttimeout(old_timeout)
795819

796820

797821
@contextlib.contextmanager

Lib/test/test_ssl.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -477,10 +477,10 @@ def test_algorithms(self):
477477
# NOTE: https://sha256.tbs-internet.com is another possible test host
478478
remote = ("sha2.hboeck.de", 443)
479479
sha256_cert = os.path.join(os.path.dirname(__file__), "sha256.pem")
480-
s = ssl.wrap_socket(socket.socket(socket.AF_INET),
481-
cert_reqs=ssl.CERT_REQUIRED,
482-
ca_certs=sha256_cert,)
483-
with support.transient_internet():
480+
with support.transient_internet("sha2.hboeck.de"):
481+
s = ssl.wrap_socket(socket.socket(socket.AF_INET),
482+
cert_reqs=ssl.CERT_REQUIRED,
483+
ca_certs=sha256_cert,)
484484
try:
485485
s.connect(remote)
486486
if support.verbose:

0 commit comments

Comments
 (0)