diff --git a/Doc/lib/libtest.tex b/Doc/lib/libtest.tex index f30b49bcbf8..326c5f0e2ba 100644 --- a/Doc/lib/libtest.tex +++ b/Doc/lib/libtest.tex @@ -285,6 +285,14 @@ originated from. The \module{test.test_support} module defines the following classes: +\begin{classdesc}{TransientResource}{exc\optional{, **kwargs}} +Create a context manager that raises \class{ResourceDenied} if the specified +exception type is raised. Any keyword arguments are treated as name/value +pairs to be compared against any exception raised with the \code{with} +statement. Only if all pairs match is \class{ResourceDenied} raised. +\versionadded{2.6} +\end{classdesc} + \begin{classdesc}{EnvironmentVarGuard}{} Class used to temporarily set or unset environment variables. Instances can be used as a context manager. diff --git a/Lib/test/test_socket_ssl.py b/Lib/test/test_socket_ssl.py index 3c9c9f03c0e..8fb7e4c13e8 100644 --- a/Lib/test/test_socket_ssl.py +++ b/Lib/test/test_socket_ssl.py @@ -27,7 +27,8 @@ def test_basic(): print "didn't raise TypeError" socket.RAND_add("this is a random string", 75.0) - f = urllib.urlopen('https://sf.net') + with test_support.TransientResource(IOError, errno=errno.ETIMEDOUT): + f = urllib.urlopen('https://sf.net') buf = f.read() f.close() diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py index 82fd5f4131b..2e47aedf214 100644 --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -312,6 +312,31 @@ class EnvironmentVarGuard(object): for unset in self._unset: del self._environ[unset] +class TransientResource(object): + + """Raise ResourceDenied if an exception is raised while the context manager + is in effect that matches the specified exception and attributes.""" + + def __init__(self, exc, **kwargs): + self.exc = exc + self.attrs = kwargs + + def __enter__(self): + return self + + def __exit__(self, type_=None, value=None, traceback=None): + """If type_ is a subclass of self.exc and value has attributes matching + self.attrs, raise ResourceDenied. Otherwise let the exception + propagate (if any).""" + if type_ is not None and issubclass(self.exc, type_): + for attr, attr_value in self.attrs.iteritems(): + if not hasattr(value, attr): + break + if getattr(value, attr) != attr_value: + break + else: + raise ResourceDenied("an optional resource is not available") + #======================================================================= # Decorator for running a function in a different locale, correctly resetting diff --git a/Misc/NEWS b/Misc/NEWS index 0ceb078ee17..b80dd323f81 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -516,6 +516,10 @@ Extension Modules Tests ----- +- Added test.test_support.TransientResource which is a context manager to + surround calls to resources that are not guaranteed to work even if + test.test_support.requires says that the resource should exist. + - Added a test for slicing of an exception. - Added test.test_support.EnvironmentVarGuard. It's a class that provides a