diff options
Diffstat (limited to 'lib/subunit/python/testtools/matchers.py')
-rw-r--r-- | lib/subunit/python/testtools/matchers.py | 282 |
1 files changed, 0 insertions, 282 deletions
diff --git a/lib/subunit/python/testtools/matchers.py b/lib/subunit/python/testtools/matchers.py deleted file mode 100644 index 039c84b7c7..0000000000 --- a/lib/subunit/python/testtools/matchers.py +++ /dev/null @@ -1,282 +0,0 @@ -# Copyright (c) 2009 Jonathan M. Lange. See LICENSE for details. - -"""Matchers, a way to express complex assertions outside the testcase. - -Inspired by 'hamcrest'. - -Matcher provides the abstract API that all matchers need to implement. - -Bundled matchers are listed in __all__: a list can be obtained by running -$ python -c 'import testtools.matchers; print testtools.matchers.__all__' -""" - -__metaclass__ = type -__all__ = [ - 'Annotate', - 'DocTestMatches', - 'Equals', - 'MatchesAll', - 'MatchesAny', - 'NotEquals', - 'Not', - ] - -import doctest - - -class Matcher: - """A pattern matcher. - - A Matcher must implement match and __str__ to be used by - testtools.TestCase.assertThat. Matcher.match(thing) returns None when - thing is completely matched, and a Mismatch object otherwise. - - Matchers can be useful outside of test cases, as they are simply a - pattern matching language expressed as objects. - - testtools.matchers is inspired by hamcrest, but is pythonic rather than - a Java transcription. - """ - - def match(self, something): - """Return None if this matcher matches something, a Mismatch otherwise. - """ - raise NotImplementedError(self.match) - - def __str__(self): - """Get a sensible human representation of the matcher. - - This should include the parameters given to the matcher and any - state that would affect the matches operation. - """ - raise NotImplementedError(self.__str__) - - -class Mismatch: - """An object describing a mismatch detected by a Matcher.""" - - def describe(self): - """Describe the mismatch. - - This should be either a human-readable string or castable to a string. - """ - raise NotImplementedError(self.describe_difference) - - -class DocTestMatches: - """See if a string matches a doctest example.""" - - def __init__(self, example, flags=0): - """Create a DocTestMatches to match example. - - :param example: The example to match e.g. 'foo bar baz' - :param flags: doctest comparison flags to match on. e.g. - doctest.ELLIPSIS. - """ - if not example.endswith('\n'): - example += '\n' - self.want = example # required variable name by doctest. - self.flags = flags - self._checker = doctest.OutputChecker() - - def __str__(self): - if self.flags: - flagstr = ", flags=%d" % self.flags - else: - flagstr = "" - return 'DocTestMatches(%r%s)' % (self.want, flagstr) - - def _with_nl(self, actual): - result = str(actual) - if not result.endswith('\n'): - result += '\n' - return result - - def match(self, actual): - with_nl = self._with_nl(actual) - if self._checker.check_output(self.want, with_nl, self.flags): - return None - return DocTestMismatch(self, with_nl) - - def _describe_difference(self, with_nl): - return self._checker.output_difference(self, with_nl, self.flags) - - -class DocTestMismatch: - """Mismatch object for DocTestMatches.""" - - def __init__(self, matcher, with_nl): - self.matcher = matcher - self.with_nl = with_nl - - def describe(self): - return self.matcher._describe_difference(self.with_nl) - - -class Equals: - """Matches if the items are equal.""" - - def __init__(self, expected): - self.expected = expected - - def match(self, other): - if self.expected == other: - return None - return EqualsMismatch(self.expected, other) - - def __str__(self): - return "Equals(%r)" % self.expected - - -class EqualsMismatch: - """Two things differed.""" - - def __init__(self, expected, other): - self.expected = expected - self.other = other - - def describe(self): - return "%r != %r" % (self.expected, self.other) - - -class NotEquals: - """Matches if the items are not equal. - - In most cases, this is equivalent to `Not(Equals(foo))`. The difference - only matters when testing `__ne__` implementations. - """ - - def __init__(self, expected): - self.expected = expected - - def __str__(self): - return 'NotEquals(%r)' % (self.expected,) - - def match(self, other): - if self.expected != other: - return None - return NotEqualsMismatch(self.expected, other) - - -class NotEqualsMismatch: - """Two things are the same.""" - - def __init__(self, expected, other): - self.expected = expected - self.other = other - - def describe(self): - return '%r == %r' % (self.expected, self.other) - - -class MatchesAny: - """Matches if any of the matchers it is created with match.""" - - def __init__(self, *matchers): - self.matchers = matchers - - def match(self, matchee): - results = [] - for matcher in self.matchers: - mismatch = matcher.match(matchee) - if mismatch is None: - return None - results.append(mismatch) - return MismatchesAll(results) - - def __str__(self): - return "MatchesAny(%s)" % ', '.join([ - str(matcher) for matcher in self.matchers]) - - -class MatchesAll: - """Matches if all of the matchers it is created with match.""" - - def __init__(self, *matchers): - self.matchers = matchers - - def __str__(self): - return 'MatchesAll(%s)' % ', '.join(map(str, self.matchers)) - - def match(self, matchee): - results = [] - for matcher in self.matchers: - mismatch = matcher.match(matchee) - if mismatch is not None: - results.append(mismatch) - if results: - return MismatchesAll(results) - else: - return None - - -class MismatchesAll: - """A mismatch with many child mismatches.""" - - def __init__(self, mismatches): - self.mismatches = mismatches - - def describe(self): - descriptions = ["Differences: ["] - for mismatch in self.mismatches: - descriptions.append(mismatch.describe()) - descriptions.append("]\n") - return '\n'.join(descriptions) - - -class Not: - """Inverts a matcher.""" - - def __init__(self, matcher): - self.matcher = matcher - - def __str__(self): - return 'Not(%s)' % (self.matcher,) - - def match(self, other): - mismatch = self.matcher.match(other) - if mismatch is None: - return MatchedUnexpectedly(self.matcher, other) - else: - return None - - -class MatchedUnexpectedly: - """A thing matched when it wasn't supposed to.""" - - def __init__(self, matcher, other): - self.matcher = matcher - self.other = other - - def describe(self): - return "%r matches %s" % (self.other, self.matcher) - - -class Annotate: - """Annotates a matcher with a descriptive string. - - Mismatches are then described as '<mismatch>: <annotation>'. - """ - - def __init__(self, annotation, matcher): - self.annotation = annotation - self.matcher = matcher - - def __str__(self): - return 'Annotate(%r, %s)' % (self.annotation, self.matcher) - - def match(self, other): - mismatch = self.matcher.match(other) - if mismatch is not None: - return AnnotatedMismatch(self.annotation, mismatch) - - -class AnnotatedMismatch: - """A mismatch annotated with a descriptive string.""" - - def __init__(self, annotation, mismatch): - self.annotation = annotation - self.mismatch = mismatch - - def describe(self): - return '%s: %s' % (self.mismatch.describe(), self.annotation) |