diff -r 3ab32f7add6e Lib/contextlib.py --- a/Lib/contextlib.py Fri Aug 19 18:59:15 2016 +0200 +++ b/Lib/contextlib.py Sat Aug 20 14:10:43 2016 +0200 @@ -234,10 +234,36 @@ with suppress(FileNotFoundError): os.remove(somefile) # Execution still resumes here if the file was already removed + + A whitelist of exceptions that will not suppressed can also be specified + as one exception or a tuple of exceptions to the 'unless' keyword + argument. + Such whitelisted exceptions should normally be subclasses of at least one + of the suppressed exceptions for this operation to make sense. But that + is not enforced. + + try: + with suppress(OSError, unless = PermissionError): + os.remove(somefile) + # Execution still resumes here for any OSError, + # except for PermissionError. + except PermissionError: + # Execution resumes here for PermissionError. + pass + + try: + with suppress(OSError, unless = (PermissionError, FileNotFoundError)): + os.remove(somefile) + # Execution still resumes here for any OSError, + # except for PermissionError and FileNotFoundError. + except PermissionError: + # Execution resumes here for PermissionError and FileNotFoundError. + pass """ - def __init__(self, *exceptions): + def __init__(self, *exceptions, unless = None): self._exceptions = exceptions + self._unless = unless or () def __enter__(self): pass @@ -252,7 +278,9 @@ # exactly reproduce the limitations of the CPython interpreter. # # See http://bugs.python.org/issue12029 for more details - return exctype is not None and issubclass(exctype, self._exceptions) + return exctype is not None and \ + issubclass(exctype, self._exceptions) and \ + not issubclass(exctype, self._unless) # Inspired by discussions on http://bugs.python.org/issue13585 diff -r 3ab32f7add6e Lib/test/test_contextlib.py --- a/Lib/test/test_contextlib.py Fri Aug 19 18:59:15 2016 +0200 +++ b/Lib/test/test_contextlib.py Sat Aug 20 14:10:43 2016 +0200 @@ -953,5 +953,30 @@ 1/0 self.assertTrue(outer_continued) + def test_unless(self): + with self.assertRaises(ZeroDivisionError): + with suppress(Exception, unless = ZeroDivisionError): + 1/0 + with suppress(Exception, unless = ZeroDivisionError): + len(5) + with self.assertRaises(ZeroDivisionError): + with suppress(ArithmeticError, TypeError, unless = ZeroDivisionError): + 1/0 + with suppress(ArithmeticError, TypeError, unless = TypeError): + 1/0 + + def test_multiple_unless(self): + with self.assertRaises(ZeroDivisionError): + with suppress(Exception, unless = (ArithmeticError, TypeError)): + 1/0 + with self.assertRaises(TypeError): + with suppress(Exception, unless = (ArithmeticError, TypeError)): + len(5) + with suppress(Exception, unless = (IndexError, OSError)): + 1/0 + with suppress(Exception, unless = (IndexError, OSError)): + len(5) + + if __name__ == "__main__": unittest.main()

AltStyle によって変換されたページ (->オリジナル) /