Source code for cake.core.comparity

from __future__ import annotations
from enum import Enum
from typing import TypeVar, Generic
import cake

L = TypeVar('L')
R = TypeVar('R')


def pairwise(supports_len) -> list:
    while len(supports_len) > 2:
        yield (supports_len[0], supports_len[1], supports_len[2])
        supports_len = supports_len[2:]


## Got to explain each symbol in docstring
[docs]class ComparitySymbol(str, Enum): ''' Represents the comparison being made between 2 objects. .. rubric:: EQUAL_TO * Represents the ``==`` operator .. rubric:: NOT_EQUAL_TO * Represents the ``!=`` operator .. rubric:: GREATER_THAN * Represents the ``>`` operator .. rubric:: GREATER_OR_EQUAL_TO * Represents the ``>=`` operator .. rubric:: LESS_THAN * Represents the ``<`` operator .. rubric:: LESS_OR_EQUAL_TO * Represents the ``<=`` operator ''' EQUAL_TO: str = '==' NOT_EQUAL_TO: str = '!=' GREATER_THAN: str = '>' GREATER_OR_EQUAL_TO: str = '>=' LESS_THAN: str = '<' LESS_OR_EQUAL_TO: str = '<=' def __repr__(self) -> str: return f'ComparitySymbol.{self._name_}' @staticmethod def _eq(l, r): return l == r @staticmethod def _neq(l, r): return l != r @staticmethod def _gt(l, r): return l > r @staticmethod def _ge(l, r): return l >= r @staticmethod def _lt(l, r): return l < r @staticmethod def _le(l, r): return l <= r
_mthds = { '==': ComparitySymbol._eq, '!=': ComparitySymbol._neq, '>': ComparitySymbol._gt, '>=': ComparitySymbol._ge, '<': ComparitySymbol._lt, '<=': ComparitySymbol._le, }
[docs]class Comparity(Generic[L, R]): ''' Generic class for representing a comparison between 2 values, Values can be chained. .. code-block:: py >>> (5 < x) Comparity(x > 5) >>> (5 < x) < y Comparity(y > x > 5) >>> ((x < 5) > y) < z Comparity(z > y < x < 5) ''' def __init__(self, left: L, right: R, symbol: ComparitySymbol) -> None: self.left = left self.right = right self.symbol = ComparitySymbol(symbol) def __str__(self, *, repr_: bool = False) -> str: f = str if not repr_ else repr return f'{f(self.left)} {self.symbol.value} {f(self.right)}' def __repr__(self) -> str: return f'Comparity(left={repr(self.left)}, right={repr(self.right)}, symbol={repr(self.symbol)})' def _gather(self) -> list: r = [] if isinstance(self.left, Comparity): r.extend(self.left._gather()) else: r.extend((self.left, self.symbol)) if isinstance(self.right, Comparity): r.extend(self.right._gather()) else: r.append(self.right) return r
[docs] def fits(self, **kwds) -> bool: ''' Checks whether given values fit inside of the comparitive expression, for chained expressions each pair is worked out, any pairs returning Comparity are assumed False. .. note:: Any variables must be passed as a **kwarg**! .. code-block:: py >>> c = x > 5 >>> c Comparity(x > 5) >>> c.fits(x=6) True >>> c.fits(x=1) False ''' nodes = self._gather() pairs = tuple(pairwise(nodes)) results = [] for pair in pairs: l, s, r = pair l = cake.utils.solve_if_possible(l, **kwds) r = cake.utils.solve_if_possible(r, **kwds) if isinstance(r := _mthds[s.value](l, r), bool): results.append(r) else: results.append(False) return all(results)