Skip to content

matchers#

BaseMatcher#

Bases: ABC

Base Matcher class.

If type is supplied and is not None, checks that matched object is an instance of type.

All subclasses should implement the match method.

Source code in tests/utils/matchers.py
class BaseMatcher(ABC):
    """Base Matcher class.

    If type is supplied and is not None, checks that matched object is an instance of type.

    All subclasses should implement the match method.
    """

    def __init__(self, type=None) -> None:
        self.type = type

    def __eq__(self, other: object) -> bool:
        if self.type is None or isinstance(other, self.type):
            return self.match(other)
        return False

    def __repr__(self) -> str:
        """Print class name and matcher arguments."""
        parts = [self.__class__.__name__]
        items = self.__dict__.items()
        if attributes := ",".join([f"{key}={value}" for key, value in items]):
            parts.append(attributes)
        return f"<{' '.join(parts)}>"

    @abstractmethod
    def match(self, other: object):
        """Return true if object is a match."""

__repr__() #

Print class name and matcher arguments.

Source code in tests/utils/matchers.py
def __repr__(self) -> str:
    """Print class name and matcher arguments."""
    parts = [self.__class__.__name__]
    items = self.__dict__.items()
    if attributes := ",".join([f"{key}={value}" for key, value in items]):
        parts.append(attributes)
    return f"<{' '.join(parts)}>"

match(other) abstractmethod #

Return true if object is a match.

Source code in tests/utils/matchers.py
@abstractmethod
def match(self, other: object):
    """Return true if object is a match."""

AnyMatcher#

Bases: BaseMatcher

Match any object.

Source code in tests/utils/matchers.py
class AnyMatcher(BaseMatcher):
    """Match any object."""

    def match(self, other: object) -> bool:
        return True

LengthMatcher#

Bases: BaseMatcher

Match any object with len(obj) matching specified length.

Source code in tests/utils/matchers.py
class LengthMatcher(BaseMatcher):
    """Match any object with len(obj) matching specified length."""

    def __init__(self, length, type=None) -> None:
        super().__init__(type)
        self.length = length

    def match(self, other: object) -> bool:
        return len(other) == self.length

ListMatcher#

Bases: LengthMatcher

Source code in tests/utils/matchers.py
class ListMatcher(LengthMatcher):
    def __init__(self, length) -> None:
        super().__init__(length, type=list)

BaseValidatorMatcher#

Bases: BaseMatcher

Validator that checks matches using a Django validator.

Source code in tests/utils/matchers.py
class BaseValidatorMatcher(BaseMatcher):
    """Validator that checks matches using a Django validator."""

    validator: Callable

    @abstractmethod
    def __init__(self, type=None) -> None:
        """Subclasses should assign self.validator in __init__."""
        super().__init__(type)

    def match(self, other: object) -> bool:
        try:
            self.validator(other)
            return True
        except exceptions.ValidationError:
            return False

__init__(type=None) abstractmethod #

Subclasses should assign self.validator in init.

Source code in tests/utils/matchers.py
@abstractmethod
def __init__(self, type=None) -> None:
    """Subclasses should assign self.validator in __init__."""
    super().__init__(type)

RegexMatcher#

Bases: BaseValidatorMatcher

Match regex.

Source code in tests/utils/matchers.py
class RegexMatcher(BaseValidatorMatcher):
    """Match regex."""

    def __init__(self, regex, **kwargs) -> None:
        super().__init__(type=str)
        self.validator = validators.RegexValidator(regex, **kwargs)

URLMatcher#

Bases: BaseValidatorMatcher

Match URLs using Django URLValidator.

Note that the validator requires URL to have a domain, so e.g. "https://host/path" will not match.

Source code in tests/utils/matchers.py
class URLMatcher(BaseValidatorMatcher):
    """Match URLs using Django URLValidator.

    Note that the validator requires URL to have a domain,
    so e.g. "https://host/path" will not match.
    """

    def __init__(self, **kwargs) -> None:
        super().__init__(type=str)
        self.validator = validators.URLValidator(**kwargs)

DateTimeMatcher#

Bases: BaseMatcher

Match datetime string values.

Source code in tests/utils/matchers.py
class DateTimeMatcher(BaseMatcher):
    """Match datetime string values."""

    def match(self, other: object) -> bool:
        try:
            if dateparse.parse_datetime(other):
                return True
        except:
            pass
        return False

DictContainingMatcher#

Bases: BaseMatcher

Match dicts that contain all keys and values from partial_dict.

Source code in tests/utils/matchers.py
class DictContainingMatcher(BaseMatcher):
    """Match dicts that contain all keys and values from partial_dict."""

    def __init__(self, partial_dict) -> None:
        self.partial_dict = partial_dict
        super().__init__(type=dict)

    def _match(self, this: dict, other: dict):
        for key, value in this.items():
            if key not in other:
                return False
            other_value = other[key]
            if isinstance(value, dict):
                if not (isinstance(other_value, dict) and self._match(value, other_value)):
                    return False
            if other_value != value:
                return False
        return True

    def match(self, other: dict):
        return self._match(self.partial_dict, other)

Matchers#

Source code in tests/utils/matchers.py
class Matchers:
    Any = AnyMatcher
    DateTime = DateTimeMatcher
    Length = LengthMatcher
    List = ListMatcher
    URL = URLMatcher
    DictContaining = DictContainingMatcher