[docs]classMatcher(tp.Generic[T],ABC):"""Abstract base class for all other matchers. Defines the core requirements for any matcher: - Must be `comparable for equality`_ with anything. - Must have a sensible `representation`_. As ``__eq__`` and ``__repr__`` are defined in :py:class:`~joythief.core.Matcher` itself, to provide core matcher behaviour, this abstract base class defines two equivalent abstract methods: :py:meth:`~joythief.core.Matcher.compare` and :py:meth:`~joythief.core.Matcher.represent`. You can write custom matchers by implementing these methods: .. code-block:: python import typing as tp from joythief.core import Matcher class IsWelcoming(Matcher[str]): def compare(self, other: tp.Any) -> bool: return other == "hello, world" def represent(self) -> str: return super().represent() # 'IsWelcoming()' .. _comparable for equality: https://docs.python.org/3/reference/datamodel.html#object.__eq__ .. _representation: https://docs.python.org/3/reference/datamodel.html#object.__repr__ """__PLACEHOLDER=object()_equal_to:tp.Any_state:_MatcherStatedef__init__(self)->None:self._equal_to=self.__PLACEHOLDERself._state=_MatcherState.UNCOMPAREDdef__eq__(self,other:tp.Any)->bool:result=self.compare(other)ifresultisNotImplemented:returnresultifself._state==_MatcherState.UNCOMPAREDandresult:self._state=_MatcherState.EQUAL_ONCEself._equal_to=otherelifotherisnotself._equal_to:self._equal_to=self.__PLACEHOLDERself._state=_MatcherState.OTHERreturnresultdef__repr__(self)->str:ifself._state==_MatcherState.EQUAL_ONCE:returnrepr(self._equal_to)returnself.represent()@abstractmethoddefcompare(self,other:tp.Any)->bool:"""Equivalent to `__eq__`__. .. __: https://docs.python.org/3/reference/datamodel.html#object.__eq__ """raiseNotImplementedError@abstractmethoddefrepresent(self)->str:"""Equivalent to `__repr__`__. .. __: https://docs.python.org/3/reference/datamodel.html#object.__repr__ """returnf"{type(self).__name__}()"
MaybeMatcher:TypeAlias=tp.Union[T,Matcher[T]]"""Either ``T`` or a matcher of ``T``."""