mirror of
https://github.com/python/cpython.git
synced 2026-04-13 23:31:02 +00:00
118 lines
2.6 KiB
Python
118 lines
2.6 KiB
Python
from __future__ import annotations
|
|
|
|
import functools
|
|
import operator
|
|
|
|
|
|
# from jaraco.context 6.1
|
|
class ExceptionTrap:
|
|
"""
|
|
A context manager that will catch certain exceptions and provide an
|
|
indication they occurred.
|
|
|
|
>>> with ExceptionTrap() as trap:
|
|
... raise Exception()
|
|
>>> bool(trap)
|
|
True
|
|
|
|
>>> with ExceptionTrap() as trap:
|
|
... pass
|
|
>>> bool(trap)
|
|
False
|
|
|
|
>>> with ExceptionTrap(ValueError) as trap:
|
|
... raise ValueError("1 + 1 is not 3")
|
|
>>> bool(trap)
|
|
True
|
|
>>> trap.value
|
|
ValueError('1 + 1 is not 3')
|
|
>>> trap.tb
|
|
<traceback object at ...>
|
|
|
|
>>> with ExceptionTrap(ValueError) as trap:
|
|
... raise Exception()
|
|
Traceback (most recent call last):
|
|
...
|
|
Exception
|
|
|
|
>>> bool(trap)
|
|
False
|
|
"""
|
|
|
|
exc_info = None, None, None
|
|
|
|
def __init__(self, exceptions=(Exception,)):
|
|
self.exceptions = exceptions
|
|
|
|
def __enter__(self):
|
|
return self
|
|
|
|
@property
|
|
def type(self):
|
|
return self.exc_info[0]
|
|
|
|
@property
|
|
def value(self):
|
|
return self.exc_info[1]
|
|
|
|
@property
|
|
def tb(self):
|
|
return self.exc_info[2]
|
|
|
|
def __exit__(self, *exc_info):
|
|
type = exc_info[0]
|
|
matches = type and issubclass(type, self.exceptions)
|
|
if matches:
|
|
self.exc_info = exc_info
|
|
return matches
|
|
|
|
def __bool__(self):
|
|
return bool(self.type)
|
|
|
|
def raises(self, func, *, _test=bool):
|
|
"""
|
|
Wrap func and replace the result with the truth
|
|
value of the trap (True if an exception occurred).
|
|
|
|
First, give the decorator an alias to support Python 3.8
|
|
Syntax.
|
|
|
|
>>> raises = ExceptionTrap(ValueError).raises
|
|
|
|
Now decorate a function that always fails.
|
|
|
|
>>> @raises
|
|
... def fail():
|
|
... raise ValueError('failed')
|
|
>>> fail()
|
|
True
|
|
"""
|
|
|
|
@functools.wraps(func)
|
|
def wrapper(*args, **kwargs):
|
|
with ExceptionTrap(self.exceptions) as trap:
|
|
func(*args, **kwargs)
|
|
return _test(trap)
|
|
|
|
return wrapper
|
|
|
|
def passes(self, func):
|
|
"""
|
|
Wrap func and replace the result with the truth
|
|
value of the trap (True if no exception).
|
|
|
|
First, give the decorator an alias to support Python 3.8
|
|
Syntax.
|
|
|
|
>>> passes = ExceptionTrap(ValueError).passes
|
|
|
|
Now decorate a function that always fails.
|
|
|
|
>>> @passes
|
|
... def fail():
|
|
... raise ValueError('failed')
|
|
|
|
>>> fail()
|
|
False
|
|
"""
|
|
return self.raises(func, _test=operator.not_)
|