import inspect, io, traceback
from . import module
_all = module.All(globals())
[docs]class MessageMixin(Exception):
message = None
[docs] def __init__(self, message=None, **kwargs):
if message is not None:
self.message = message
self.__dict__.update(kwargs)
Exception.__init__(self)
def __str__(self):
attributes = inspect.getmembers(self, lambda a: not inspect.isroutine(a))
return self.message.format(**{a: v for a, v in attributes if a[0] != '_'})
[docs]class BadHTTPResponseCodeError(MessageMixin, Exception):
message = 'Download request {url} code {r_code} expected {code}.'
[docs]class CorruptedFileError(MessageMixin, Exception):
message = 'File {path} is corrupted checksum {file_hash} expected {expected_hash}.'
[docs]class ForbiddenError(Exception):
"""A forbidden error."""
[docs]class InvalidBrandError(MessageMixin, Exception):
message = 'Brand {brand} not in {brands}.'
[docs]class InvalidIPSocketError(MessageMixin, Exception):
message = '{socket} is not a valid IP socket.'
[docs]class MultipleSignalHandlersError(MessageMixin, Exception):
message = 'Signal {signum} already handled by {handlers}.'
[docs]class UndefinedPathError(Exception):
pass
[docs]def assert_raises_item(exception_cls, something, index, value=None, delete=False):
"""
**Example usage**
>>> x = {0: 3.14, 1: 2.54}
Assert that __getitem__ will fail:
>>> assert_raises_item(KeyError, x, 2)
>>> assert_raises_item(ValueError, x, 3)
Traceback (most recent call last):
...
ValueError: Exception KeyError is not an instance of ValueError.
>>> assert_raises_item(Exception, x, 0)
Traceback (most recent call last):
...
AssertionError: Exception Exception not raised.
Assert that __setitem__ will fail:
>>> assert_raises_item(TypeError, x, [10], value=3.1415)
>>> assert_raises_item(TypeError, x, 0, value=3.1415)
Traceback (most recent call last):
...
AssertionError: Exception TypeError not raised.
Assert that __delitem__ will fail:
>>> assert_raises_item(KeyError, x, 2, delete=True)
>>> assert_raises_item(KeyError, x, 1, delete=True)
Traceback (most recent call last):
...
AssertionError: Exception KeyError not raised.
>>> x == {0: 3.1415}
True
"""
try:
if delete:
del something[index]
elif value is None:
something[index] # pylint:disable=pointless-statement
else:
something[index] = value
except Exception as ex: # pylint:disable=broad-except
if not isinstance(ex, exception_cls):
raise ValueError(
f'Exception {ex.__class__.__name__} is not '
f'an instance of {exception_cls.__name__}.') from ex
return
raise AssertionError(f'Exception {exception_cls.__name__} not raised.')
[docs]def get_exception_with_traceback(exception):
"""
Return a string with the exception traceback.
**Example usage**
If the exception was not raised then there are no traceback:
>>> get_exception_with_traceback(ValueError('yé'))
'ValueError: yé\\n'
If the exception was raised then there is a traceback:
>>> try:
... raise RuntimeError('yé')
... except Exception as ex:
... trace = get_exception_with_traceback(ex)
>>> 'Traceback' in trace
True
>>> "raise RuntimeError('yé')" in trace
True
"""
buf = io.StringIO()
traceback.print_exception(type(exception), exception, exception.__traceback__, file=buf)
return buf.getvalue()
__all__ = _all.diff(globals())