|
from collections import defaultdict |
|
from dataclasses import dataclass |
|
from typing import DefaultDict, List, Optional, Set, Union |
|
|
|
|
|
@dataclass |
|
class Dependency: |
|
"""Dependency class. |
|
|
|
Args: |
|
key: key of the dependency |
|
value: required value of the dependency, None for empty condition |
|
is_set: whether the dependency should be set, or not set |
|
""" |
|
|
|
key: str |
|
value: Union[str, bool, int, None] = True |
|
is_set: bool = True |
|
|
|
def check(self, dependency_values: Optional[List[str]]) -> bool: |
|
""" |
|
Check if dependency is satisfied |
|
|
|
Args: |
|
dependency_values: list of dependency values |
|
|
|
Returns: |
|
True if the dependency is satisfied, False otherwise |
|
""" |
|
|
|
if dependency_values is None: |
|
dependency_values = [] |
|
|
|
if self.value is None and self.is_set and len(dependency_values): |
|
return False |
|
elif self.value is None and not self.is_set and not len(dependency_values): |
|
return False |
|
elif self.is_set and self.value not in dependency_values: |
|
return False |
|
elif ( |
|
not self.is_set |
|
and len([v for v in dependency_values if v != self.value]) == 0 |
|
): |
|
return False |
|
return True |
|
|
|
|
|
class Nesting: |
|
""" |
|
A tree-like structure to specify nested dependencies of key-value pairs |
|
In detail it maps dependencies of key requiring any number of key:value pairs |
|
|
|
Primarily useful for specifying nested dependencies of UI elements shown in Wave. |
|
""" |
|
|
|
def __init__(self): |
|
self.dependencies: DefaultDict[str, List[Dependency]] = defaultdict(list) |
|
self.triggers: Set[str] = set() |
|
|
|
def add(self, keys: List[str], dependencies: List[Dependency]): |
|
""" |
|
Append dependencies (key:value) for a given key |
|
|
|
Args: |
|
keys: keys to add dependencies for |
|
dependencies: key:value pairs to depend on |
|
""" |
|
|
|
if len(set(keys)) != len(keys): |
|
raise ValueError("Nesting keys must be unique.") |
|
|
|
for dependency in dependencies: |
|
self.triggers.add(dependency.key) |
|
for key in set(keys): |
|
self.dependencies[key].append(dependency) |
|
|