/usr/lib/python2.7/dist-packages/testtools/matchers/_exception.py is in python-testtools 1.8.1-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | # Copyright (c) 2009-2012 testtools developers. See LICENSE for details.
__all__ = [
'MatchesException',
'Raises',
'raises',
]
import sys
from testtools.compat import (
classtypes,
istext,
)
from ._basic import MatchesRegex
from ._higherorder import AfterPreproccessing
from ._impl import (
Matcher,
Mismatch,
)
_error_repr = BaseException.__repr__
def _is_exception(exc):
return isinstance(exc, BaseException)
def _is_user_exception(exc):
return isinstance(exc, Exception)
class MatchesException(Matcher):
"""Match an exc_info tuple against an exception instance or type."""
def __init__(self, exception, value_re=None):
"""Create a MatchesException that will match exc_info's for exception.
:param exception: Either an exception instance or type.
If an instance is given, the type and arguments of the exception
are checked. If a type is given only the type of the exception is
checked. If a tuple is given, then as with isinstance, any of the
types in the tuple matching is sufficient to match.
:param value_re: If 'exception' is a type, and the matchee exception
is of the right type, then match against this. If value_re is a
string, then assume value_re is a regular expression and match
the str() of the exception against it. Otherwise, assume value_re
is a matcher, and match the exception against it.
"""
Matcher.__init__(self)
self.expected = exception
if istext(value_re):
value_re = AfterPreproccessing(str, MatchesRegex(value_re), False)
self.value_re = value_re
expected_type = type(self.expected)
self._is_instance = not any(issubclass(expected_type, class_type)
for class_type in classtypes() + (tuple,))
def match(self, other):
if type(other) != tuple:
return Mismatch('%r is not an exc_info tuple' % other)
expected_class = self.expected
if self._is_instance:
expected_class = expected_class.__class__
if not issubclass(other[0], expected_class):
return Mismatch('%r is not a %r' % (other[0], expected_class))
if self._is_instance:
if other[1].args != self.expected.args:
return Mismatch('%s has different arguments to %s.' % (
_error_repr(other[1]), _error_repr(self.expected)))
elif self.value_re is not None:
return self.value_re.match(other[1])
def __str__(self):
if self._is_instance:
return "MatchesException(%s)" % _error_repr(self.expected)
return "MatchesException(%s)" % repr(self.expected)
class Raises(Matcher):
"""Match if the matchee raises an exception when called.
Exceptions which are not subclasses of Exception propogate out of the
Raises.match call unless they are explicitly matched.
"""
def __init__(self, exception_matcher=None):
"""Create a Raises matcher.
:param exception_matcher: Optional validator for the exception raised
by matchee. If supplied the exc_info tuple for the exception raised
is passed into that matcher. If no exception_matcher is supplied
then the simple fact of raising an exception is considered enough
to match on.
"""
self.exception_matcher = exception_matcher
def match(self, matchee):
try:
result = matchee()
return Mismatch('%r returned %r' % (matchee, result))
# Catch all exceptions: Raises() should be able to match a
# KeyboardInterrupt or SystemExit.
except:
exc_info = sys.exc_info()
if self.exception_matcher:
mismatch = self.exception_matcher.match(exc_info)
if not mismatch:
del exc_info
return
else:
mismatch = None
# The exception did not match, or no explicit matching logic was
# performed. If the exception is a non-user exception then
# propagate it.
exception = exc_info[1]
if _is_exception(exception) and not _is_user_exception(exception):
del exc_info
raise
return mismatch
def __str__(self):
return 'Raises()'
def raises(exception):
"""Make a matcher that checks that a callable raises an exception.
This is a convenience function, exactly equivalent to::
return Raises(MatchesException(exception))
See `Raises` and `MatchesException` for more information.
"""
return Raises(MatchesException(exception))
|