Module taulu.split
A module that provides a Split class to handle data with left and right variants.
The Split class allows for easy management and manipulation of paired data, such as images or templates, by providing properties and methods to access and modify the left and right components. It also supports applying functions to both components simultaneously and accessing attributes of the contained objects.
Classes
class Split (left: ~T | None = None, right: ~T | None = None)-
Expand source code
class Split(Generic[T]): """Wrapper for data that has both a left and a right variant""" def __init__(self, left: T | None = None, right: T | None = None): self._left = left self._right = right @property def left(self) -> T: assert self._left is not None return self._left @left.setter def left(self, value: T): self._left = value @property def right(self) -> T: assert self._right is not None return self._right @right.setter def right(self, value: T): self._right = value def append(self, value: T): if self._left is None: self._left = value else: self._right = value def __repr__(self) -> str: return f"left: {self._left}, right: {self._right}" def __iter__(self): assert self._left is not None assert self._right is not None return iter((self._left, self._right)) def __getitem__(self, index: bool) -> T: assert self._left is not None assert self._right is not None if int(index) == 0: return self._left else: return self._right def apply( self, funcs: "Split[Callable[[T, *Any], V]] | Callable[[T, *Any], V]", *args, **kwargs, ) -> "Split[V]": if not isinstance(funcs, Split): funcs = Split(funcs, funcs) def get_arg(side: str, arg): if isinstance(arg, Split): return getattr(arg, side) return arg def call(side: str): func = getattr(funcs, side) target = getattr(self, side) side_args = [get_arg(side, arg) for arg in args] side_kwargs = {k: get_arg(side, v) for k, v in kwargs.items()} return func(target, *side_args, **side_kwargs) return Split(call("left"), call("right")) def __getattr__(self, attr_name: str): if attr_name in self.__dict__: return getattr(self, attr_name) def wrapper(*args, **kwargs): return self.apply( Split( getattr(self.left.__class__, attr_name), getattr(self.right.__class__, attr_name), ), *args, **kwargs, ) return wrapperWrapper for data that has both a left and a right variant
Ancestors
- typing.Generic
Instance variables
prop left : ~T-
Expand source code
@property def left(self) -> T: assert self._left is not None return self._left prop right : ~T-
Expand source code
@property def right(self) -> T: assert self._right is not None return self._right
Methods
def append(self, value: ~T)-
Expand source code
def append(self, value: T): if self._left is None: self._left = value else: self._right = value def apply(self,
funcs: Split[Callable[[T, *Any], V]] | Callable[[T, *Any], V],
*args,
**kwargs) ‑> Split[V]-
Expand source code
def apply( self, funcs: "Split[Callable[[T, *Any], V]] | Callable[[T, *Any], V]", *args, **kwargs, ) -> "Split[V]": if not isinstance(funcs, Split): funcs = Split(funcs, funcs) def get_arg(side: str, arg): if isinstance(arg, Split): return getattr(arg, side) return arg def call(side: str): func = getattr(funcs, side) target = getattr(self, side) side_args = [get_arg(side, arg) for arg in args] side_kwargs = {k: get_arg(side, v) for k, v in kwargs.items()} return func(target, *side_args, **side_kwargs) return Split(call("left"), call("right"))