17.12
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
from __future__ import absolute_import
|
||||
from hamcrest.core import *
|
||||
from hamcrest.library import *
|
||||
|
||||
__version__ = "1.9.0"
|
||||
__author__ = "Chris Rose"
|
||||
__copyright__ = "Copyright 2015 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
@@ -0,0 +1,19 @@
|
||||
__author__ = "Per Fagrell"
|
||||
__copyright__ = "Copyright 2013 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
|
||||
__all__ = ['is_callable']
|
||||
|
||||
import sys
|
||||
|
||||
# callable was not part of py3k until 3.2, so we create this
|
||||
# generic is_callable to use callable if possible, otherwise
|
||||
# we use generic homebrew.
|
||||
if sys.version_info[0] == 3 and sys.version_info[1] < 2:
|
||||
def is_callable(function):
|
||||
"""Return whether the object is callable (i.e., some kind of function)."""
|
||||
if function is None:
|
||||
return False
|
||||
return any("__call__" in klass.__dict__ for klass in type(function).__mro__)
|
||||
else:
|
||||
is_callable = callable
|
||||
@@ -0,0 +1,18 @@
|
||||
from __future__ import absolute_import
|
||||
"""Fundamental matchers of objects and values, and composite matchers."""
|
||||
|
||||
from hamcrest.core.core.allof import all_of
|
||||
from hamcrest.core.core.anyof import any_of
|
||||
from hamcrest.core.core.described_as import described_as
|
||||
from hamcrest.core.core.is_ import is_
|
||||
from hamcrest.core.core.isanything import anything
|
||||
from hamcrest.core.core.isequal import equal_to
|
||||
from hamcrest.core.core.isinstanceof import instance_of
|
||||
from hamcrest.core.core.isnone import none, not_none
|
||||
from hamcrest.core.core.isnot import is_not, not_
|
||||
from hamcrest.core.core.issame import same_instance
|
||||
from hamcrest.core.core.raises import calling, raises
|
||||
|
||||
__author__ = "Jon Reid"
|
||||
__copyright__ = "Copyright 2011 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
@@ -0,0 +1,37 @@
|
||||
from hamcrest.core.base_matcher import BaseMatcher
|
||||
from hamcrest.core.helpers.wrap_matcher import wrap_matcher
|
||||
|
||||
__author__ = "Jon Reid"
|
||||
__copyright__ = "Copyright 2011 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
|
||||
|
||||
class AnyOf(BaseMatcher):
|
||||
|
||||
def __init__(self, *matchers):
|
||||
self.matchers = matchers
|
||||
|
||||
def _matches(self, item):
|
||||
for matcher in self.matchers:
|
||||
if matcher.matches(item):
|
||||
return True
|
||||
return False
|
||||
|
||||
def describe_to(self, description):
|
||||
description.append_list('(', ' or ', ')', self.matchers)
|
||||
|
||||
|
||||
def any_of(*items):
|
||||
"""Matches if any of the given matchers evaluate to ``True``.
|
||||
|
||||
:param matcher1,...: A comma-separated list of matchers.
|
||||
|
||||
The matchers are evaluated from left to right using short-circuit
|
||||
evaluation, so evaluation stops as soon as a matcher returns ``True``.
|
||||
|
||||
Any argument that is not a matcher is implicitly wrapped in an
|
||||
:py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
|
||||
equality.
|
||||
|
||||
"""
|
||||
return AnyOf(*[wrap_matcher(item) for item in items])
|
||||
@@ -0,0 +1,31 @@
|
||||
from hamcrest.core.base_matcher import BaseMatcher
|
||||
|
||||
__author__ = "Jon Reid"
|
||||
__copyright__ = "Copyright 2011 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
|
||||
|
||||
class IsAnything(BaseMatcher):
|
||||
|
||||
def __init__(self, description):
|
||||
self.description = description
|
||||
if not description:
|
||||
self.description = 'ANYTHING'
|
||||
|
||||
def _matches(self, item):
|
||||
return True
|
||||
|
||||
def describe_to(self, description):
|
||||
description.append_text(self.description)
|
||||
|
||||
|
||||
def anything(description=None):
|
||||
"""Matches anything.
|
||||
|
||||
:param description: Optional string used to describe this matcher.
|
||||
|
||||
This matcher always evaluates to ``True``. Specify this in composite
|
||||
matchers when the value of a particular element is unimportant.
|
||||
|
||||
"""
|
||||
return IsAnything(description)
|
||||
@@ -0,0 +1,32 @@
|
||||
__author__ = "Jon Reid"
|
||||
__copyright__ = "Copyright 2011 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
|
||||
from hamcrest.core.base_matcher import BaseMatcher
|
||||
from hamcrest.core.matcher import Matcher
|
||||
|
||||
|
||||
class IsEqual(BaseMatcher):
|
||||
|
||||
def __init__(self, equals):
|
||||
self.object = equals
|
||||
|
||||
def _matches(self, item):
|
||||
return item == self.object
|
||||
|
||||
def describe_to(self, description):
|
||||
nested_matcher = isinstance(self.object, Matcher)
|
||||
if nested_matcher:
|
||||
description.append_text('<')
|
||||
description.append_description_of(self.object)
|
||||
if nested_matcher:
|
||||
description.append_text('>')
|
||||
|
||||
|
||||
def equal_to(obj):
|
||||
"""Matches if object is equal to a given object.
|
||||
|
||||
:param obj: The object to compare against as the expected value.
|
||||
|
||||
This matcher compares the evaluated object to ``obj`` for equality."""
|
||||
return IsEqual(obj)
|
||||
@@ -0,0 +1,43 @@
|
||||
from hamcrest.core.base_matcher import BaseMatcher
|
||||
from hamcrest.core.helpers.wrap_matcher import is_matchable_type
|
||||
|
||||
__author__ = "Jon Reid"
|
||||
__copyright__ = "Copyright 2011 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
|
||||
import types
|
||||
|
||||
class IsInstanceOf(BaseMatcher):
|
||||
|
||||
def __init__(self, expected_type):
|
||||
if not is_matchable_type(expected_type):
|
||||
raise TypeError('IsInstanceOf requires type or a tuple of classes and types')
|
||||
self.expected_type = expected_type
|
||||
|
||||
def _matches(self, item):
|
||||
return isinstance(item, self.expected_type)
|
||||
|
||||
def describe_to(self, description):
|
||||
try:
|
||||
type_description = self.expected_type.__name__
|
||||
except AttributeError:
|
||||
type_description = "one of %s" % ",".join(str(e) for e in self.expected_type)
|
||||
description.append_text('an instance of ') \
|
||||
.append_text(type_description)
|
||||
|
||||
|
||||
def instance_of(atype):
|
||||
"""Matches if object is an instance of, or inherits from, a given type.
|
||||
|
||||
:param atype: The type to compare against as the expected type or a tuple
|
||||
of types.
|
||||
|
||||
This matcher checks whether the evaluated object is an instance of
|
||||
``atype`` or an instance of any class that inherits from ``atype``.
|
||||
|
||||
Example::
|
||||
|
||||
instance_of(str)
|
||||
|
||||
"""
|
||||
return IsInstanceOf(atype)
|
||||
@@ -0,0 +1,26 @@
|
||||
from __future__ import absolute_import
|
||||
__author__ = "Jon Reid"
|
||||
__copyright__ = "Copyright 2011 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
|
||||
from hamcrest.core.base_matcher import BaseMatcher
|
||||
from .isnot import is_not
|
||||
|
||||
|
||||
class IsNone(BaseMatcher):
|
||||
|
||||
def _matches(self, item):
|
||||
return item is None
|
||||
|
||||
def describe_to(self, description):
|
||||
description.append_text('None')
|
||||
|
||||
|
||||
def none():
|
||||
"""Matches if object is ``None``."""
|
||||
return IsNone()
|
||||
|
||||
|
||||
def not_none():
|
||||
"""Matches if object is not ``None``."""
|
||||
return is_not(none())
|
||||
@@ -0,0 +1,57 @@
|
||||
from __future__ import absolute_import
|
||||
__author__ = "Jon Reid"
|
||||
__copyright__ = "Copyright 2011 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
|
||||
from hamcrest.core.base_matcher import BaseMatcher, Matcher
|
||||
from hamcrest.core.helpers.wrap_matcher import wrap_matcher, is_matchable_type
|
||||
from .isequal import equal_to
|
||||
from .isinstanceof import instance_of
|
||||
|
||||
|
||||
class IsNot(BaseMatcher):
|
||||
|
||||
def __init__(self, matcher):
|
||||
self.matcher = matcher
|
||||
|
||||
def _matches(self, item):
|
||||
return not self.matcher.matches(item)
|
||||
|
||||
def describe_to(self, description):
|
||||
description.append_text('not ').append_description_of(self.matcher)
|
||||
|
||||
|
||||
def wrap_value_or_type(x):
|
||||
if is_matchable_type(x):
|
||||
return instance_of(x)
|
||||
else:
|
||||
return wrap_matcher(x)
|
||||
|
||||
|
||||
def is_not(match):
|
||||
"""Inverts the given matcher to its logical negation.
|
||||
|
||||
:param match: The matcher to negate.
|
||||
|
||||
This matcher compares the evaluated object to the negation of the given
|
||||
matcher. If the ``match`` argument is not a matcher, it is implicitly
|
||||
wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to
|
||||
check for equality, and thus matches for inequality.
|
||||
|
||||
Examples::
|
||||
|
||||
assert_that(cheese, is_not(equal_to(smelly)))
|
||||
assert_that(cheese, is_not(smelly))
|
||||
|
||||
"""
|
||||
return IsNot(wrap_value_or_type(match))
|
||||
|
||||
def not_(match):
|
||||
"""Alias of :py:func:`is_not` for better readability of negations.
|
||||
|
||||
Examples::
|
||||
|
||||
assert_that(alist, not_(has_item(item)))
|
||||
|
||||
"""
|
||||
return is_not(match)
|
||||
@@ -0,0 +1,5 @@
|
||||
"""Utilities for writing Matchers."""
|
||||
|
||||
__author__ = "Jon Reid"
|
||||
__copyright__ = "Copyright 2011 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
@@ -0,0 +1,44 @@
|
||||
from __future__ import absolute_import
|
||||
"""Library of Matcher implementations."""
|
||||
|
||||
from hamcrest.core import *
|
||||
from hamcrest.library.collection import *
|
||||
from hamcrest.library.integration import *
|
||||
from hamcrest.library.number import *
|
||||
from hamcrest.library.object import *
|
||||
from hamcrest.library.text import *
|
||||
|
||||
__author__ = "Jon Reid"
|
||||
__copyright__ = "Copyright 2011 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
|
||||
__all__ = [
|
||||
'has_entry',
|
||||
'has_entries',
|
||||
'has_key',
|
||||
'has_value',
|
||||
'is_in',
|
||||
'empty',
|
||||
'has_item',
|
||||
'has_items',
|
||||
'contains_inanyorder',
|
||||
'contains',
|
||||
'only_contains',
|
||||
'match_equality',
|
||||
'matches_regexp',
|
||||
'close_to',
|
||||
'greater_than',
|
||||
'greater_than_or_equal_to',
|
||||
'less_than',
|
||||
'less_than_or_equal_to',
|
||||
'has_length',
|
||||
'has_property',
|
||||
'has_properties',
|
||||
'has_string',
|
||||
'equal_to_ignoring_case',
|
||||
'equal_to_ignoring_whitespace',
|
||||
'contains_string',
|
||||
'ends_with',
|
||||
'starts_with',
|
||||
'string_contains_in_order',
|
||||
]
|
||||
@@ -0,0 +1,16 @@
|
||||
"""Matchers of collections."""
|
||||
from __future__ import absolute_import
|
||||
from .isdict_containing import has_entry
|
||||
from .isdict_containingentries import has_entries
|
||||
from .isdict_containingkey import has_key
|
||||
from .isdict_containingvalue import has_value
|
||||
from .isin import is_in
|
||||
from .issequence_containing import has_item, has_items
|
||||
from .issequence_containinginanyorder import contains_inanyorder
|
||||
from .issequence_containinginorder import contains
|
||||
from .issequence_onlycontaining import only_contains
|
||||
from .is_empty import empty
|
||||
|
||||
__author__ = "Chris Rose"
|
||||
__copyright__ = "Copyright 2013 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
@@ -0,0 +1,48 @@
|
||||
from hamcrest.core.base_matcher import BaseMatcher
|
||||
from hamcrest.core.helpers.hasmethod import hasmethod
|
||||
from hamcrest.core.helpers.wrap_matcher import wrap_matcher
|
||||
|
||||
__author__ = "Jon Reid"
|
||||
__copyright__ = "Copyright 2011 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
|
||||
|
||||
class IsDictContainingKey(BaseMatcher):
|
||||
|
||||
def __init__(self, key_matcher):
|
||||
self.key_matcher = key_matcher
|
||||
|
||||
def _matches(self, dictionary):
|
||||
if hasmethod(dictionary, 'keys'):
|
||||
for key in dictionary.keys():
|
||||
if self.key_matcher.matches(key):
|
||||
return True
|
||||
return False
|
||||
|
||||
def describe_to(self, description):
|
||||
description.append_text('a dictionary containing key ') \
|
||||
.append_description_of(self.key_matcher)
|
||||
|
||||
|
||||
def has_key(key_match):
|
||||
"""Matches if dictionary contains an entry whose key satisfies a given
|
||||
matcher.
|
||||
|
||||
:param key_match: The matcher to satisfy for the key, or an expected value
|
||||
for :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
|
||||
|
||||
This matcher iterates the evaluated dictionary, searching for any key-value
|
||||
entry whose key satisfies the given matcher. If a matching entry is found,
|
||||
``has_key`` is satisfied.
|
||||
|
||||
Any argument that is not a matcher is implicitly wrapped in an
|
||||
:py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
|
||||
equality.
|
||||
|
||||
Examples::
|
||||
|
||||
has_key(equal_to('foo'))
|
||||
has_key('foo')
|
||||
|
||||
"""
|
||||
return IsDictContainingKey(wrap_matcher(key_match))
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
from hamcrest.core.base_matcher import BaseMatcher
|
||||
from hamcrest.core.helpers.hasmethod import hasmethod
|
||||
from hamcrest.core.helpers.wrap_matcher import wrap_matcher
|
||||
|
||||
__author__ = "Jon Reid"
|
||||
__copyright__ = "Copyright 2011 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
|
||||
|
||||
class IsDictContainingValue(BaseMatcher):
|
||||
|
||||
def __init__(self, value_matcher):
|
||||
self.value_matcher = value_matcher
|
||||
|
||||
def _matches(self, dictionary):
|
||||
if hasmethod(dictionary, 'values'):
|
||||
for value in dictionary.values():
|
||||
if self.value_matcher.matches(value):
|
||||
return True
|
||||
return False
|
||||
|
||||
def describe_to(self, description):
|
||||
description.append_text('a dictionary containing value ') \
|
||||
.append_description_of(self.value_matcher)
|
||||
|
||||
|
||||
def has_value(value):
|
||||
"""Matches if dictionary contains an entry whose value satisfies a given
|
||||
matcher.
|
||||
|
||||
:param value_match: The matcher to satisfy for the value, or an expected
|
||||
value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
|
||||
|
||||
This matcher iterates the evaluated dictionary, searching for any key-value
|
||||
entry whose value satisfies the given matcher. If a matching entry is
|
||||
found, ``has_value`` is satisfied.
|
||||
|
||||
Any argument that is not a matcher is implicitly wrapped in an
|
||||
:py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
|
||||
equality.
|
||||
|
||||
Examples::
|
||||
|
||||
has_value(equal_to('bar'))
|
||||
has_value('bar')
|
||||
|
||||
"""
|
||||
return IsDictContainingValue(wrap_matcher(value))
|
||||
@@ -0,0 +1,89 @@
|
||||
__author__ = "Jon Reid"
|
||||
__copyright__ = "Copyright 2011 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
|
||||
from hamcrest.core.base_matcher import BaseMatcher
|
||||
from hamcrest.core.core.allof import all_of
|
||||
from hamcrest.core.helpers.hasmethod import hasmethod
|
||||
from hamcrest.core.helpers.wrap_matcher import wrap_matcher
|
||||
|
||||
|
||||
class IsSequenceContaining(BaseMatcher):
|
||||
|
||||
def __init__(self, element_matcher):
|
||||
self.element_matcher = element_matcher
|
||||
|
||||
def _matches(self, sequence):
|
||||
try:
|
||||
for item in sequence:
|
||||
if self.element_matcher.matches(item):
|
||||
return True
|
||||
except TypeError: # not a sequence
|
||||
return False
|
||||
|
||||
def describe_to(self, description):
|
||||
description.append_text('a sequence containing ') \
|
||||
.append_description_of(self.element_matcher)
|
||||
|
||||
|
||||
# It'd be great to make use of all_of, but we can't be sure we won't
|
||||
# be seeing a one-time sequence here (like a generator); see issue #20
|
||||
# Instead, we wrap it inside a class that will convert the sequence into
|
||||
# a concrete list and then hand it off to the all_of matcher.
|
||||
class IsSequenceContainingEvery(BaseMatcher):
|
||||
|
||||
def __init__(self, *element_matchers):
|
||||
delegates = [has_item(e) for e in element_matchers]
|
||||
self.matcher = all_of(*delegates)
|
||||
|
||||
def _matches(self, sequence):
|
||||
try:
|
||||
return self.matcher.matches(list(sequence))
|
||||
except TypeError:
|
||||
return False
|
||||
|
||||
def describe_mismatch(self, item, mismatch_description):
|
||||
self.matcher.describe_mismatch(item, mismatch_description)
|
||||
|
||||
def describe_to(self, description):
|
||||
self.matcher.describe_to(description)
|
||||
|
||||
|
||||
|
||||
def has_item(match):
|
||||
"""Matches if any element of sequence satisfies a given matcher.
|
||||
|
||||
:param match: The matcher to satisfy, or an expected value for
|
||||
:py:func:`~hamcrest.core.core.isequal.equal_to` matching.
|
||||
|
||||
This matcher iterates the evaluated sequence, searching for any element
|
||||
that satisfies a given matcher. If a matching element is found,
|
||||
``has_item`` is satisfied.
|
||||
|
||||
If the ``match`` argument is not a matcher, it is implicitly wrapped in an
|
||||
:py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
|
||||
equality.
|
||||
|
||||
"""
|
||||
return IsSequenceContaining(wrap_matcher(match))
|
||||
|
||||
|
||||
def has_items(*items):
|
||||
"""Matches if all of the given matchers are satisfied by any elements of
|
||||
the sequence.
|
||||
|
||||
:param match1,...: A comma-separated list of matchers.
|
||||
|
||||
This matcher iterates the given matchers, searching for any elements in the
|
||||
evaluated sequence that satisfy them. If each matcher is satisfied, then
|
||||
``has_items`` is satisfied.
|
||||
|
||||
Any argument that is not a matcher is implicitly wrapped in an
|
||||
:py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
|
||||
equality.
|
||||
|
||||
"""
|
||||
matchers = []
|
||||
for item in items:
|
||||
matchers.append(wrap_matcher(item))
|
||||
return IsSequenceContainingEvery(*matchers)
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
from hamcrest.core.base_matcher import BaseMatcher
|
||||
from hamcrest.core.helpers.hasmethod import hasmethod
|
||||
from hamcrest.core.helpers.wrap_matcher import wrap_matcher
|
||||
|
||||
__author__ = "Jon Reid"
|
||||
__copyright__ = "Copyright 2011 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
|
||||
|
||||
class MatchInAnyOrder(object):
|
||||
def __init__(self, matchers, mismatch_description):
|
||||
self.matchers = matchers[:]
|
||||
self.mismatch_description = mismatch_description
|
||||
|
||||
def matches(self, item):
|
||||
return self.isnotsurplus(item) and self.ismatched(item)
|
||||
|
||||
def isfinished(self, sequence):
|
||||
if not self.matchers:
|
||||
return True
|
||||
if self.mismatch_description:
|
||||
self.mismatch_description.append_text('no item matches: ') \
|
||||
.append_list('', ', ', '', self.matchers) \
|
||||
.append_text(' in ') \
|
||||
.append_list('[', ', ', ']', sequence)
|
||||
return False
|
||||
|
||||
def isnotsurplus(self, item):
|
||||
if not self.matchers:
|
||||
if self.mismatch_description:
|
||||
self.mismatch_description.append_text('not matched: ') \
|
||||
.append_description_of(item)
|
||||
return False
|
||||
return True
|
||||
|
||||
def ismatched(self, item):
|
||||
for index, matcher in enumerate(self.matchers):
|
||||
if matcher.matches(item):
|
||||
del self.matchers[index]
|
||||
return True
|
||||
|
||||
if self.mismatch_description:
|
||||
self.mismatch_description.append_text('not matched: ') \
|
||||
.append_description_of(item)
|
||||
return False
|
||||
|
||||
|
||||
class IsSequenceContainingInAnyOrder(BaseMatcher):
|
||||
|
||||
def __init__(self, matchers):
|
||||
self.matchers = matchers
|
||||
|
||||
def matches(self, sequence, mismatch_description=None):
|
||||
try:
|
||||
sequence = list(sequence)
|
||||
matchsequence = MatchInAnyOrder(self.matchers, mismatch_description)
|
||||
for item in sequence:
|
||||
if not matchsequence.matches(item):
|
||||
return False
|
||||
return matchsequence.isfinished(sequence)
|
||||
except TypeError:
|
||||
if mismatch_description:
|
||||
super(IsSequenceContainingInAnyOrder, self) \
|
||||
.describe_mismatch(sequence, mismatch_description)
|
||||
return False
|
||||
|
||||
def describe_mismatch(self, item, mismatch_description):
|
||||
self.matches(item, mismatch_description)
|
||||
|
||||
def describe_to(self, description):
|
||||
description.append_text('a sequence over ') \
|
||||
.append_list('[', ', ', ']', self.matchers) \
|
||||
.append_text(' in any order')
|
||||
|
||||
|
||||
def contains_inanyorder(*items):
|
||||
"""Matches if sequences's elements, in any order, satisfy a given list of
|
||||
matchers.
|
||||
|
||||
:param match1,...: A comma-separated list of matchers.
|
||||
|
||||
This matcher iterates the evaluated sequence, seeing if each element
|
||||
satisfies any of the given matchers. The matchers are tried from left to
|
||||
right, and when a satisfied matcher is found, it is no longer a candidate
|
||||
for the remaining elements. If a one-to-one correspondence is established
|
||||
between elements and matchers, ``contains_inanyorder`` is satisfied.
|
||||
|
||||
Any argument that is not a matcher is implicitly wrapped in an
|
||||
:py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
|
||||
equality.
|
||||
|
||||
"""
|
||||
|
||||
matchers = []
|
||||
for item in items:
|
||||
matchers.append(wrap_matcher(item))
|
||||
return IsSequenceContainingInAnyOrder(matchers)
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
from hamcrest.core.base_matcher import BaseMatcher
|
||||
from hamcrest.core.core.anyof import any_of
|
||||
from hamcrest.core.helpers.hasmethod import hasmethod
|
||||
from hamcrest.core.helpers.wrap_matcher import wrap_matcher
|
||||
|
||||
__author__ = "Jon Reid"
|
||||
__copyright__ = "Copyright 2011 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
|
||||
|
||||
class IsSequenceOnlyContaining(BaseMatcher):
|
||||
|
||||
def __init__(self, matcher):
|
||||
self.matcher = matcher
|
||||
|
||||
def _matches(self, sequence):
|
||||
try:
|
||||
sequence = list(sequence)
|
||||
if len(sequence) == 0:
|
||||
return False
|
||||
for item in sequence:
|
||||
if not self.matcher.matches(item):
|
||||
return False
|
||||
return True
|
||||
except TypeError:
|
||||
return False
|
||||
|
||||
def describe_to(self, description):
|
||||
description.append_text('a sequence containing items matching ') \
|
||||
.append_description_of(self.matcher)
|
||||
|
||||
|
||||
def only_contains(*items):
|
||||
"""Matches if each element of sequence satisfies any of the given matchers.
|
||||
|
||||
:param match1,...: A comma-separated list of matchers.
|
||||
|
||||
This matcher iterates the evaluated sequence, confirming whether each
|
||||
element satisfies any of the given matchers.
|
||||
|
||||
Example::
|
||||
|
||||
only_contains(less_than(4))
|
||||
|
||||
will match ``[3,1,2]``.
|
||||
|
||||
Any argument that is not a matcher is implicitly wrapped in an
|
||||
:py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
|
||||
equality.
|
||||
|
||||
"""
|
||||
matchers = []
|
||||
for item in items:
|
||||
matchers.append(wrap_matcher(item))
|
||||
return IsSequenceOnlyContaining(any_of(*matchers))
|
||||
@@ -0,0 +1,8 @@
|
||||
from __future__ import absolute_import
|
||||
"""Utilities for integrating Hamcrest with other libraries."""
|
||||
|
||||
from .match_equality import match_equality
|
||||
|
||||
__author__ = "Jon Reid"
|
||||
__copyright__ = "Copyright 2011 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
@@ -0,0 +1,42 @@
|
||||
from hamcrest.core.string_description import tostring
|
||||
from hamcrest.core.helpers.wrap_matcher import wrap_matcher
|
||||
|
||||
__author__ = "Chris Rose"
|
||||
__copyright__ = "Copyright 2011 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
__unittest = True
|
||||
|
||||
|
||||
class EqualityWrapper(object):
|
||||
|
||||
def __init__(self, matcher):
|
||||
self.matcher = matcher
|
||||
|
||||
def __eq__(self, object):
|
||||
return self.matcher.matches(object)
|
||||
|
||||
def __str__(self):
|
||||
return repr(self)
|
||||
|
||||
def __repr__(self):
|
||||
return tostring(self.matcher)
|
||||
|
||||
|
||||
def match_equality(matcher):
|
||||
"""Wraps a matcher to define equality in terms of satisfying the matcher.
|
||||
|
||||
``match_equality`` allows Hamcrest matchers to be used in libraries that
|
||||
are not Hamcrest-aware. They might use the equality operator::
|
||||
|
||||
assert match_equality(matcher) == object
|
||||
|
||||
Or they might provide a method that uses equality for its test::
|
||||
|
||||
library.method_that_tests_eq(match_equality(matcher))
|
||||
|
||||
One concrete example is integrating with the ``assert_called_with`` methods
|
||||
in Michael Foord's `mock <http://www.voidspace.org.uk/python/mock/>`_
|
||||
library.
|
||||
|
||||
"""
|
||||
return EqualityWrapper(wrap_matcher(matcher))
|
||||
@@ -0,0 +1,50 @@
|
||||
from hamcrest.core.base_matcher import BaseMatcher
|
||||
from hamcrest.core.helpers.hasmethod import hasmethod
|
||||
from hamcrest.core.helpers.wrap_matcher import wrap_matcher
|
||||
|
||||
__author__ = "Jon Reid"
|
||||
__copyright__ = "Copyright 2011 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
|
||||
|
||||
class HasLength(BaseMatcher):
|
||||
|
||||
def __init__(self, len_matcher):
|
||||
self.len_matcher = len_matcher
|
||||
|
||||
def _matches(self, item):
|
||||
if not hasmethod(item, '__len__'):
|
||||
return False
|
||||
return self.len_matcher.matches(len(item))
|
||||
|
||||
def describe_mismatch(self, item, mismatch_description):
|
||||
super(HasLength, self).describe_mismatch(item, mismatch_description)
|
||||
if hasmethod(item, '__len__'):
|
||||
mismatch_description.append_text(' with length of ') \
|
||||
.append_description_of(len(item))
|
||||
|
||||
def describe_to(self, description):
|
||||
description.append_text('an object with length of ') \
|
||||
.append_description_of(self.len_matcher)
|
||||
|
||||
|
||||
def has_length(match):
|
||||
"""Matches if ``len(item)`` satisfies a given matcher.
|
||||
|
||||
:param match: The matcher to satisfy, or an expected value for
|
||||
:py:func:`~hamcrest.core.core.isequal.equal_to` matching.
|
||||
|
||||
This matcher invokes the :py:func:`len` function on the evaluated object to
|
||||
get its length, passing the result to a given matcher for evaluation.
|
||||
|
||||
If the ``match`` argument is not a matcher, it is implicitly wrapped in an
|
||||
:py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
|
||||
:equality.
|
||||
|
||||
Examples::
|
||||
|
||||
has_length(greater_than(6))
|
||||
has_length(5)
|
||||
|
||||
"""
|
||||
return HasLength(wrap_matcher(match))
|
||||
@@ -0,0 +1,154 @@
|
||||
from hamcrest.core.base_matcher import BaseMatcher
|
||||
from hamcrest.core import anything
|
||||
from hamcrest.core.core.allof import all_of
|
||||
from hamcrest.core.string_description import StringDescription
|
||||
from hamcrest.core.helpers.hasmethod import hasmethod
|
||||
from hamcrest.core.helpers.wrap_matcher import wrap_matcher as wrap_shortcut
|
||||
|
||||
__author__ = "Chris Rose"
|
||||
__copyright__ = "Copyright 2011 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
|
||||
|
||||
class IsObjectWithProperty(BaseMatcher):
|
||||
|
||||
def __init__(self, property_name, value_matcher):
|
||||
self.property_name = property_name
|
||||
self.value_matcher = value_matcher
|
||||
|
||||
def _matches(self, o):
|
||||
if o is None:
|
||||
return False
|
||||
|
||||
if not hasattr(o, self.property_name):
|
||||
return False
|
||||
|
||||
value = getattr(o, self.property_name)
|
||||
return self.value_matcher.matches(value)
|
||||
|
||||
def describe_to(self, description):
|
||||
description.append_text("an object with a property '") \
|
||||
.append_text(self.property_name) \
|
||||
.append_text("' matching ") \
|
||||
.append_description_of(self.value_matcher)
|
||||
|
||||
def describe_mismatch(self, item, mismatch_description):
|
||||
if item is None:
|
||||
mismatch_description.append_text('was None')
|
||||
return
|
||||
|
||||
if not hasattr(item, self.property_name):
|
||||
mismatch_description.append_value(item) \
|
||||
.append_text(' did not have the ') \
|
||||
.append_value(self.property_name) \
|
||||
.append_text(' property')
|
||||
return
|
||||
|
||||
mismatch_description.append_text('property ').append_value(self.property_name).append_text(' ')
|
||||
value = getattr(item, self.property_name)
|
||||
self.value_matcher.describe_mismatch(value, mismatch_description)
|
||||
|
||||
def __str__(self):
|
||||
d = StringDescription()
|
||||
self.describe_to(d)
|
||||
return str(d)
|
||||
|
||||
|
||||
def has_property(name, match=None):
|
||||
"""Matches if object has a property with a given name whose value satisfies
|
||||
a given matcher.
|
||||
|
||||
:param name: The name of the property.
|
||||
:param match: Optional matcher to satisfy.
|
||||
|
||||
This matcher determines if the evaluated object has a property with a given
|
||||
name. If no such property is found, ``has_property`` is not satisfied.
|
||||
|
||||
If the property is found, its value is passed to a given matcher for
|
||||
evaluation. If the ``match`` argument is not a matcher, it is implicitly
|
||||
wrapped in an :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to
|
||||
check for equality.
|
||||
|
||||
If the ``match`` argument is not provided, the
|
||||
:py:func:`~hamcrest.core.core.isanything.anything` matcher is used so that
|
||||
``has_property`` is satisfied if a matching property is found.
|
||||
|
||||
Examples::
|
||||
|
||||
has_property('name', starts_with('J'))
|
||||
has_property('name', 'Jon')
|
||||
has_property('name')
|
||||
|
||||
"""
|
||||
|
||||
if match is None:
|
||||
match = anything()
|
||||
|
||||
return IsObjectWithProperty(name, wrap_shortcut(match))
|
||||
|
||||
|
||||
def has_properties(*keys_valuematchers, **kv_args):
|
||||
"""Matches if an object has properties satisfying all of a dictionary
|
||||
of string property names and corresponding value matchers.
|
||||
|
||||
:param matcher_dict: A dictionary mapping keys to associated value matchers,
|
||||
or to expected values for
|
||||
:py:func:`~hamcrest.core.core.isequal.equal_to` matching.
|
||||
|
||||
Note that the keys must be actual keys, not matchers. Any value argument
|
||||
that is not a matcher is implicitly wrapped in an
|
||||
:py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
|
||||
equality.
|
||||
|
||||
Examples::
|
||||
|
||||
has_properties({'foo':equal_to(1), 'bar':equal_to(2)})
|
||||
has_properties({'foo':1, 'bar':2})
|
||||
|
||||
``has_properties`` also accepts a list of keyword arguments:
|
||||
|
||||
.. function:: has_properties(keyword1=value_matcher1[, keyword2=value_matcher2[, ...]])
|
||||
|
||||
:param keyword1: A keyword to look up.
|
||||
:param valueMatcher1: The matcher to satisfy for the value, or an expected
|
||||
value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
|
||||
|
||||
Examples::
|
||||
|
||||
has_properties(foo=equal_to(1), bar=equal_to(2))
|
||||
has_properties(foo=1, bar=2)
|
||||
|
||||
Finally, ``has_properties`` also accepts a list of alternating keys and their
|
||||
value matchers:
|
||||
|
||||
.. function:: has_properties(key1, value_matcher1[, ...])
|
||||
|
||||
:param key1: A key (not a matcher) to look up.
|
||||
:param valueMatcher1: The matcher to satisfy for the value, or an expected
|
||||
value for :py:func:`~hamcrest.core.core.isequal.equal_to` matching.
|
||||
|
||||
Examples::
|
||||
|
||||
has_properties('foo', equal_to(1), 'bar', equal_to(2))
|
||||
has_properties('foo', 1, 'bar', 2)
|
||||
|
||||
"""
|
||||
if len(keys_valuematchers) == 1:
|
||||
try:
|
||||
base_dict = keys_valuematchers[0].copy()
|
||||
for key in base_dict:
|
||||
base_dict[key] = wrap_shortcut(base_dict[key])
|
||||
except AttributeError:
|
||||
raise ValueError('single-argument calls to has_properties must pass a dict as the argument')
|
||||
else:
|
||||
if len(keys_valuematchers) % 2:
|
||||
raise ValueError('has_properties requires key-value pairs')
|
||||
base_dict = {}
|
||||
for index in range(int(len(keys_valuematchers) / 2)):
|
||||
base_dict[keys_valuematchers[2 * index]] = wrap_shortcut(keys_valuematchers[2 * index + 1])
|
||||
|
||||
for key, value in kv_args.items():
|
||||
base_dict[key] = wrap_shortcut(value)
|
||||
|
||||
return all_of(*[has_property(property_name, property_value_matcher) for \
|
||||
property_name, property_value_matcher in base_dict.items()])
|
||||
@@ -0,0 +1,43 @@
|
||||
__author__ = "Jon Reid"
|
||||
__copyright__ = "Copyright 2011 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
|
||||
from hamcrest.core.base_matcher import BaseMatcher
|
||||
|
||||
import six
|
||||
|
||||
class IsEqualIgnoringCase(BaseMatcher):
|
||||
|
||||
def __init__(self, string):
|
||||
if not isinstance(string, six.string_types):
|
||||
raise TypeError('IsEqualIgnoringCase requires string')
|
||||
self.original_string = string
|
||||
self.lowered_string = string.lower()
|
||||
|
||||
def _matches(self, item):
|
||||
if not isinstance(item, six.string_types):
|
||||
return False
|
||||
return self.lowered_string == item.lower()
|
||||
|
||||
def describe_to(self, description):
|
||||
description.append_description_of(self.original_string) \
|
||||
.append_text(' ignoring case')
|
||||
|
||||
|
||||
def equal_to_ignoring_case(string):
|
||||
"""Matches if object is a string equal to a given string, ignoring case
|
||||
differences.
|
||||
|
||||
:param string: The string to compare against as the expected value.
|
||||
|
||||
This matcher first checks whether the evaluated object is a string. If so,
|
||||
it compares it with ``string``, ignoring differences of case.
|
||||
|
||||
Example::
|
||||
|
||||
equal_to_ignoring_case("hello world")
|
||||
|
||||
will match "heLLo WorlD".
|
||||
|
||||
"""
|
||||
return IsEqualIgnoringCase(string)
|
||||
@@ -0,0 +1,57 @@
|
||||
__author__ = "Jon Reid"
|
||||
__copyright__ = "Copyright 2011 hamcrest.org"
|
||||
__license__ = "BSD, see License.txt"
|
||||
|
||||
from hamcrest.core.base_matcher import BaseMatcher
|
||||
|
||||
import six
|
||||
|
||||
def stripspace(string):
|
||||
result = ''
|
||||
last_was_space = True
|
||||
for character in string:
|
||||
if character.isspace():
|
||||
if not last_was_space:
|
||||
result += ' '
|
||||
last_was_space = True
|
||||
else:
|
||||
result += character
|
||||
last_was_space = False
|
||||
return result.strip()
|
||||
|
||||
|
||||
class IsEqualIgnoringWhiteSpace(BaseMatcher):
|
||||
|
||||
def __init__(self, string):
|
||||
if not isinstance(string, six.string_types):
|
||||
raise TypeError('IsEqualIgnoringWhiteSpace requires string')
|
||||
self.original_string = string
|
||||
self.stripped_string = stripspace(string)
|
||||
|
||||
def _matches(self, item):
|
||||
if not isinstance(item, six.string_types):
|
||||
return False
|
||||
return self.stripped_string == stripspace(item)
|
||||
|
||||
def describe_to(self, description):
|
||||
description.append_description_of(self.original_string) \
|
||||
.append_text(' ignoring whitespace')
|
||||
|
||||
|
||||
def equal_to_ignoring_whitespace(string):
|
||||
"""Matches if object is a string equal to a given string, ignoring
|
||||
differences in whitespace.
|
||||
|
||||
:param string: The string to compare against as the expected value.
|
||||
|
||||
This matcher first checks whether the evaluated object is a string. If so,
|
||||
it compares it with ``string``, ignoring differences in runs of whitespace.
|
||||
|
||||
Example::
|
||||
|
||||
equal_to_ignoring_whitespace("hello world")
|
||||
|
||||
will match ``"hello world"``.
|
||||
|
||||
"""
|
||||
return IsEqualIgnoringWhiteSpace(string)
|
||||
Reference in New Issue
Block a user