Mercurial > p > roundup > code
view roundup/anypy/cmp_.py @ 7800:2d4684e4702d
fix: enhancement to history command output and % template fix.
Rather than using the key field, use the label field for descriptions.
Call cls.labelprop(default_to_id=True) so it returns id rather than
the first sorted property name.
If labelprop() returns 'id' or 'title', we return nothing. 'id' means
there is no label set and no properties named 'name' or 'title'. So
have the caller do whatever it wants (prepend classname for example)
when there is no human readable name. This prevents %(name)s%(key)s
from producing: 23(23).
Also don't accept the 'title' property. Titles can be too
long. Arguably we could: '%(name)20s' to limit the title
length. However without ellipses or something truncating the title
might be confusing. So again pretend there is no human readable name.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Tue, 12 Mar 2024 11:52:17 -0400 |
| parents | dec7de56f253 |
| children |
line wrap: on
line source
try: # will raise TypeError under python 3 None < 0 # noqa: PLR0133, B015 def NoneAndDictComparable(v): return v except TypeError: # comparator to allow comparisons against None and dict # comparisons (these were allowed in Python 2, but aren't allowed # in Python 3 any more) class NoneAndDictComparable(object): # noqa: PLW1641 def __init__(self, value): self.value = value def __cmp__(self, other): # noqa: PLW3201, PLR0911 if not isinstance(other, self.__class__): raise TypeError('not comparable') if self.value == other.value: return 0 elif self.value is None: return -1 elif other.value is None: return 1 elif type(self.value) is tuple and type(other.value) is tuple: for lhs, rhs in zip(self.value, other.value): lhsCmp = NoneAndDictComparable(lhs) rhsCmp = NoneAndDictComparable(rhs) result = lhsCmp.__cmp__(rhsCmp) if result != 0: return result return len(self.value) - len(other.value) elif type(self.value) is dict and type(other.value) is dict: diff = len(self.value) - len(other.value) if diff == 0: lhsItems = tuple(sorted(self.value.items(), key=NoneAndDictComparable)) rhsItems = tuple(sorted(other.value.items(), key=NoneAndDictComparable)) return -1 if NoneAndDictComparable(lhsItems) < NoneAndDictComparable(rhsItems) else 1 else: return diff elif self.value < other.value: return -1 else: return 1 def __eq__(self, other): return self.__cmp__(other) == 0 def __ne__(self, other): return self.__cmp__(other) != 0 def __lt__(self, other): return self.__cmp__(other) < 0 def __le__(self, other): return self.__cmp__(other) <= 0 def __ge__(self, other): return self.__cmp__(other) >= 0 def __gt__(self, other): return self.__cmp__(other) > 0 def _test(): # ruff: noqa: S101, B011, PLC0415, PLR2004 import sys _py3 = sys.version_info[0] > 2 Comp = NoneAndDictComparable assert Comp(None) < Comp(0) assert Comp(None) < Comp('') assert Comp(None) < Comp({}) assert Comp((0, None)) < Comp((0, 0)) assert not Comp(0) < Comp(None) assert not Comp('') < Comp(None) assert not Comp({}) < Comp(None) assert not Comp((0, 0)) < Comp((0, None)) try: not Comp("") < Comp((0, None)) if _py3: assert False, "Incompatible types are reporting comparable." except TypeError: pass assert Comp((0, 0)) < Comp((0, 0, None)) assert Comp((0, None, None)) < Comp((0, 0, 0)) assert Comp(0) < Comp(1) assert Comp(1) > Comp(0) assert not Comp(1) < Comp(0) assert not Comp(0) > Comp(0) assert Comp(0) <= Comp(1) assert Comp(1) >= Comp(0) assert not Comp(1) <= Comp(0) assert Comp(0) >= Comp(0) assert Comp({0: None}) < Comp({0: 0}) assert Comp({0: 0}) < Comp({0: 1}) assert Comp({0: 0}) == Comp({0: 0}) assert Comp({0: 0}) != Comp({0: 1}) assert Comp({0: 0, 1: 1}) > Comp({0: 1}) assert Comp({0: 0, 1: 1}) < Comp({0: 0, 2: 2}) if __name__ == '__main__': _test()
