Skip to content

Commit

Permalink
Python BaseUniqueSortedEnum
Browse files Browse the repository at this point in the history
  • Loading branch information
ego committed Feb 22, 2024
1 parent eecd900 commit 93f8c04
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 0 deletions.
79 changes: 79 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2145,6 +2145,85 @@ and [Helping Modular Humanize AI Through Brand](https://www.metalab.com/blog/hel
* [Apache TVM](https://tvm.apache.org)


## Python hints

Python problem with PostgreSQL Enum type.
We need names and values as strings, and we need to maintain their order.

```Python
import enum
from functools import total_ordering


@total_ordering
@enum.unique
class BaseUniqueSortedEnum(enum.Enum):
"""Base unique enum class with ordering."""

def __new__(cls, *args, **kwargs):
obj = object.__new__(cls)
obj.index = len(cls.__members__) + 1
return obj

def __hash__(self) -> int:
return hash(
f"{self.__module__}_{self.__class__.__name__}_{self.name}_{self.value}"
)

def __eq__(self, other) -> bool:
self._check_type(other)
return super().__eq__(other)

def __lt__(self, other) -> bool:
self._check_type(other)
return self.index < other.index

def _check_type(self, other) -> None:
if type(self) != type(other):
raise TypeError(f"Different types of Enum: {self} != {other}")


class Dog(BaseUniqueSortedEnum):
BLOODHOUND = "BLOODHOUND"
WEIMARANER = "WEIMARANER"
SAME = "SAME"


class Cat(BaseUniqueSortedEnum):
BRITISH = "BRITISH"
SCOTTISH = "SCOTTISH"
SAME = "SAME"


assert Dog.BLOODHOUND < Dog.WEIMARANER
assert Dog.BLOODHOUND <= Dog.WEIMARANER
assert Dog.BLOODHOUND != Dog.WEIMARANER
assert Dog.BLOODHOUND == Dog.BLOODHOUND
assert Dog.WEIMARANER == Dog.WEIMARANER
assert Dog.WEIMARANER > Dog.BLOODHOUND
assert Dog.WEIMARANER >= Dog.BLOODHOUND

assert Cat.BRITISH < Cat.SCOTTISH
assert Cat.BRITISH <= Cat.SCOTTISH
assert Cat.BRITISH != Cat.SCOTTISH
assert Cat.BRITISH == Cat.BRITISH
assert Cat.SCOTTISH == Cat.SCOTTISH
assert Cat.SCOTTISH > Cat.BRITISH
assert Cat.SCOTTISH >= Cat.BRITISH

assert hash(Dog.BLOODHOUND) == hash(Dog.BLOODHOUND)
assert hash(Dog.WEIMARANER) == hash(Dog.WEIMARANER)
assert hash(Dog.BLOODHOUND) != hash(Dog.WEIMARANER)
assert hash(Dog.SAME) != hash(Cat.SAME)

# raise TypeError
Dog.SAME <= Cat.SAME
Dog.SAME < Cat.SAME
Dog.SAME > Cat.SAME
Dog.SAME >= Cat.SAME
Dog.SAME != Cat.SAME
```

# Contributing

* Your contributions are always welcome!
Expand Down
71 changes: 71 additions & 0 deletions python/enums.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import enum
from functools import total_ordering


@total_ordering
@enum.unique
class BaseUniqueSortedEnum(enum.Enum):
"""Base unique enum class with ordering."""

def __new__(cls, *args, **kwargs):
obj = object.__new__(cls)
obj.index = len(cls.__members__) + 1
return obj

def __hash__(self) -> int:
return hash(
f"{self.__module__}_{self.__class__.__name__}_{self.name}_{self.value}"
)

def __eq__(self, other) -> bool:
self._check_type(other)
return super().__eq__(other)

def __lt__(self, other) -> bool:
self._check_type(other)
return self.index < other.index

def _check_type(self, other) -> None:
if type(self) != type(other):
raise TypeError(f"Different types of Enum: {self} != {other}")


class Dog(BaseUniqueSortedEnum):
BLOODHOUND = "BLOODHOUND"
WEIMARANER = "WEIMARANER"
SAME = "SAME"


class Cat(BaseUniqueSortedEnum):
BRITISH = "BRITISH"
SCOTTISH = "SCOTTISH"
SAME = "SAME"


assert Dog.BLOODHOUND < Dog.WEIMARANER
assert Dog.BLOODHOUND <= Dog.WEIMARANER
assert Dog.BLOODHOUND != Dog.WEIMARANER
assert Dog.BLOODHOUND == Dog.BLOODHOUND
assert Dog.WEIMARANER == Dog.WEIMARANER
assert Dog.WEIMARANER > Dog.BLOODHOUND
assert Dog.WEIMARANER >= Dog.BLOODHOUND

assert Cat.BRITISH < Cat.SCOTTISH
assert Cat.BRITISH <= Cat.SCOTTISH
assert Cat.BRITISH != Cat.SCOTTISH
assert Cat.BRITISH == Cat.BRITISH
assert Cat.SCOTTISH == Cat.SCOTTISH
assert Cat.SCOTTISH > Cat.BRITISH
assert Cat.SCOTTISH >= Cat.BRITISH

assert hash(Dog.BLOODHOUND) == hash(Dog.BLOODHOUND)
assert hash(Dog.WEIMARANER) == hash(Dog.WEIMARANER)
assert hash(Dog.BLOODHOUND) != hash(Dog.WEIMARANER)
assert hash(Dog.SAME) != hash(Cat.SAME)

# raise TypeError
Dog.SAME <= Cat.SAME
Dog.SAME < Cat.SAME
Dog.SAME > Cat.SAME
Dog.SAME >= Cat.SAME
Dog.SAME != Cat.SAME

0 comments on commit 93f8c04

Please sign in to comment.