74 lines
1.7 KiB
Python
74 lines
1.7 KiB
Python
from __future__ import annotations
|
|
|
|
import dataclasses
|
|
import enum
|
|
from abc import abstractmethod
|
|
from typing import Generic, Protocol, TypeVar
|
|
|
|
|
|
class Comparable(Protocol):
|
|
@abstractmethod
|
|
def __gt__(self: T, other: T, /) -> bool:
|
|
pass
|
|
|
|
@abstractmethod
|
|
def __ge__(self: T, other: T, /) -> bool:
|
|
pass
|
|
|
|
@abstractmethod
|
|
def __lt__(self: T, other: T, /) -> bool:
|
|
pass
|
|
|
|
@abstractmethod
|
|
def __le__(self: T, other: T, /) -> bool:
|
|
pass
|
|
|
|
|
|
T = TypeVar("T", bound=Comparable)
|
|
|
|
|
|
@dataclasses.dataclass
|
|
class Range(Generic[T]):
|
|
gt: T | None = None
|
|
gte: T | None = None
|
|
lt: T | None = None
|
|
lte: T | None = None
|
|
|
|
def lower_bound(self) -> tuple[T, bool] | None:
|
|
if self.gt is None and self.gte is None:
|
|
return None
|
|
elif self.gt is not None and self.gte is not None:
|
|
lb = self.gt if (self.gt > self.gte) else self.gte
|
|
eq = self.gt < self.gte
|
|
return lb, eq
|
|
elif self.gt is not None:
|
|
return self.gt, False
|
|
elif self.gte is not None:
|
|
return self.gte, True
|
|
|
|
def upper_bound(self) -> tuple[T, bool] | None:
|
|
if self.lt is None and self.lte is None:
|
|
return None
|
|
elif self.lt is not None and self.lte is not None:
|
|
ub = self.lt if (self.lt < self.lte) else self.lte
|
|
eq = self.lt > self.lte
|
|
return ub, eq
|
|
elif self.lt is not None:
|
|
return self.lt, False
|
|
elif self.lte is not None:
|
|
return self.lte, True
|
|
|
|
|
|
class Order(enum.Enum):
|
|
ASCENDING = 'ASC'
|
|
DESCENDING = 'DESC'
|
|
|
|
|
|
ColT = TypeVar("ColT")
|
|
|
|
|
|
@dataclasses.dataclass
|
|
class OrderCol(Generic[ColT]):
|
|
column: ColT
|
|
order: Order
|