from dataclasses import dataclass, field from typing import Generic, Iterable, List, Protocol, Union, cast, overload, override from modules.constrains.static import VTaskConstraintStatic from modules.constrains.static.must_be_any import MustBeAnyConstraint from modules.constrains.static.must_include_all_tags import MustIncludeAllTagsConstraint from modules.constrains.static.must_include_any_tag import MustIncludeAnyTagConstraint from modules.constrains.static.must_not import MustNotStatic from modules.constrains.types import QTaskOrFactory from modules.tags import Tag, Tags from utils.types import A, C, Q, V @dataclass class VTaskConstraintsAbstract(Generic[C, V, Q, A]): static_constraints: List[VTaskConstraintStatic[C, V, Q, A]] = field( default_factory=list ) dynamic_constraints: None = None def add_constraint( self, constraint: VTaskConstraintStatic[C, V, Q, A] ) -> "VTaskConstraints[C, V, Q, A]": self.static_constraints.append(constraint) # unsafe, but needed to avoid typing the same thing for two times... return cast("VTaskConstraints[C, V, Q, A]", self) def __call__( self, constraint: VTaskConstraintStatic[C, V, Q, A] ) -> "VTaskConstraints[C, V, Q, A]": return self.add_constraint(constraint) @overload def be_any( self, item: Iterable[QTaskOrFactory[C, V, Q, A]] ) -> "VTaskConstraints[C, V, Q, A]": ... @overload def be_any( self, item: QTaskOrFactory[C, V, Q, A], **kwargs: QTaskOrFactory[C, V, Q, A] ) -> "VTaskConstraints[C, V, Q, A]": ... def be_any( self, item: Union[Iterable[QTaskOrFactory[C, V, Q, A]], QTaskOrFactory[C, V, Q, A]], **kwargs: QTaskOrFabric[C, V, Q, A], ) -> "VTaskConstraints[C, V, Q, A]": return self.add_constraint(MustBeAnyConstraint(item, **kwargs)) @overload def include_any_tag(self, tag: Tags[C, V]) -> "VTaskConstraints[C, V, Q, A]": ... @overload def include_any_tag( self, tag: Iterable[Tag[C, V]] ) -> "VTaskConstraints[C, V, Q, A]": ... @overload def include_any_tag( self, tag: Tag[C, V], **kwargs: Tag[C, V] ) -> "VTaskConstraints[C, V, Q, A]": ... def include_any_tag( self, tag: Union[Tags[C, V], Tag[C, V], Iterable[Tag[C, V]]], **kwargs: Tag[C, V], ) -> "VTaskConstraints[C, V, Q, A]": return self.add_constraint(MustIncludeAnyTagConstraint(tag, **kwargs)) @overload def include_all_tags(self, tag: Tags[C, V]) -> "VTaskConstraints[C, V, Q, A]": ... @overload def include_all_tags( self, tag: Iterable[Tag[C, V]] ) -> "VTaskConstraints[C, V, Q, A]": ... @overload def include_all_tags( self, tag: Tag[C, V], **kwargs: Tag[C, V] ) -> "VTaskConstraints[C, V, Q, A]": ... def include_all_tags( self, tag: Union[Tags[C, V], Tag[C, V], Iterable[Tag[C, V]]], **kwargs: Tag[C, V], ): return self.add_constraint(MustIncludeAllTagsConstraint(tag, **kwargs)) class VTaskConstraintsNegator(VTaskConstraintsAbstract[C, V, Q, A]): def __init__(self, v_task_constraints: "VTaskConstraints[C, V, Q, A]"): self.v_task_constraints = v_task_constraints def add_constraint( self, constraint: VTaskConstraintStatic[C, V, Q, A] ) -> "VTaskConstraints[C, V, Q, A]": return self.v_task_constraints.add_constraint(MustNotStatic(constraint)) @dataclass class VTaskConstraints(VTaskConstraintsAbstract[C, V, Q, A]): nt: VTaskConstraintsNegator[C, V, Q, A] = field(init=False) def __post_init__(self): self.nt = VTaskConstraintsNegator(self)