issequence_containinginorder.py 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. __author__ = "Jon Reid"
  2. __copyright__ = "Copyright 2011 hamcrest.org"
  3. __license__ = "BSD, see License.txt"
  4. from hamcrest.core.base_matcher import BaseMatcher
  5. from hamcrest.core.helpers.hasmethod import hasmethod
  6. from hamcrest.core.helpers.wrap_matcher import wrap_matcher
  7. class MatchingInOrder(object):
  8. def __init__(self, matchers, mismatch_description):
  9. self.matchers = matchers
  10. self.mismatch_description = mismatch_description
  11. self.next_match_index = 0
  12. def matches(self, item):
  13. return self.isnotsurplus(item) and self.ismatched(item)
  14. def isfinished(self):
  15. if self.next_match_index < len(self.matchers):
  16. if self.mismatch_description:
  17. self.mismatch_description.append_text('No item matched: ') \
  18. .append_description_of(self.matchers[self.next_match_index])
  19. return False
  20. return True
  21. def ismatched(self, item):
  22. matcher = self.matchers[self.next_match_index]
  23. if not matcher.matches(item):
  24. if self.mismatch_description:
  25. self.mismatch_description.append_text('item ' + str(self.next_match_index) + ': ')
  26. matcher.describe_mismatch(item, self.mismatch_description)
  27. return False
  28. self.next_match_index += 1
  29. return True
  30. def isnotsurplus(self, item):
  31. if len(self.matchers) <= self.next_match_index:
  32. if self.mismatch_description:
  33. self.mismatch_description.append_text('Not matched: ') \
  34. .append_description_of(item)
  35. return False
  36. return True
  37. class IsSequenceContainingInOrder(BaseMatcher):
  38. def __init__(self, matchers):
  39. self.matchers = matchers
  40. def matches(self, sequence, mismatch_description=None):
  41. try:
  42. matchsequence = MatchingInOrder(self.matchers, mismatch_description)
  43. for item in sequence:
  44. if not matchsequence.matches(item):
  45. return False
  46. return matchsequence.isfinished()
  47. except TypeError:
  48. if mismatch_description:
  49. super(IsSequenceContainingInOrder, self) \
  50. .describe_mismatch(sequence, mismatch_description)
  51. return False
  52. def describe_mismatch(self, item, mismatch_description):
  53. self.matches(item, mismatch_description)
  54. def describe_to(self, description):
  55. description.append_text('a sequence containing ') \
  56. .append_list('[', ', ', ']', self.matchers)
  57. def contains(*items):
  58. """Matches if sequence's elements satisfy a given list of matchers, in order.
  59. :param match1,...: A comma-separated list of matchers.
  60. This matcher iterates the evaluated sequence and a given list of matchers,
  61. seeing if each element satisfies its corresponding matcher.
  62. Any argument that is not a matcher is implicitly wrapped in an
  63. :py:func:`~hamcrest.core.core.isequal.equal_to` matcher to check for
  64. equality.
  65. """
  66. matchers = []
  67. for item in items:
  68. matchers.append(wrap_matcher(item))
  69. return IsSequenceContainingInOrder(matchers)