diff --git a/src/azul/indexer/__init__.py b/src/azul/indexer/__init__.py index dc4172c5d..6e673d9ec 100644 --- a/src/azul/indexer/__init__.py +++ b/src/azul/indexer/__init__.py @@ -2,6 +2,9 @@ ABCMeta, abstractmethod, ) +from functools import ( + total_ordering, +) from itertools import ( product, ) @@ -46,8 +49,12 @@ BundleVersion = str +# PyCharm can't handle mixing `attrs` with `total_ordering` and falsely claims +# that comparison operators besides `__lt__` are not defined. +# noinspection PyDataclass @attrs.frozen(kw_only=True, eq=False) -class BundleFQID(SupportsLessAndGreaterThan): +@total_ordering +class BundleFQID: """ A fully qualified bundle identifier. The attributes defined in this class must always be sufficient to decide whether two instances of this class or @@ -67,7 +74,8 @@ def _nucleus(self) -> tuple[str, str]: # their inheritance relationships or how their attributes are annotated # (e.g. specifying `eq=False` has no effect). We want instances of # all subclasses to compare equal as long as `uuid` and `version` are - # equal. + # equal. For the same reason, we can't use `typing.Self` in the signature + # because it would constrain the RHS to instances of subclasses of the LHS. @final def __eq__(self, other: 'BundleFQID') -> bool: """ @@ -131,21 +139,26 @@ def __init_subclass__(cls, **kwargs): # attrs doesn't allow `order=True` when `eq=False` def __lt__(self, other: 'BundleFQID') -> bool: """ - >>> list(sorted([ - ... BundleFQID(uuid='d', version='e'), - ... BundleFQID(uuid='a', version='c'), - ... BundleFQID(uuid='a', version='b'), - ... ])) - ... # doctest: +NORMALIZE_WHITESPACE - [BundleFQID(uuid='a', version='b'), - BundleFQID(uuid='a', version='c'), - BundleFQID(uuid='d', version='e')] + >>> aa = BundleFQID(uuid='a', version='a') + >>> ab = BundleFQID(uuid='a', version='b') + >>> ba = BundleFQID(uuid='b', version='a') + >>> aa < ab < ba + True + + >>> ba > ab > aa + True + + >>> aa <= ab <= ba + True + + >>> ba >= ab >= aa + True + + >>> aa != ab != ba + True """ return self._nucleus() < other._nucleus() - def __gt__(self, other: 'BundleFQID'): - return self._nucleus() > other._nucleus() - def to_json(self) -> MutableJSON: return attrs.asdict(self, recurse=False)