File size: 2,838 Bytes
5caedb4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
from collections import defaultdict
from typing import DefaultDict, List, Set, Union

from pydantic.dataclasses import dataclass


@dataclass
class Dependency:
    """
    Represents a dependency with a key, value, and set condition.

    Attributes:
        key (str): The key of the dependency (parent).
        value (Union[str, bool, int, None]): The value of the dependency to look for. \
            None for empty condition (dependency only needs to exist).
        is_set (bool): Whether the value of the dependency should be set (True) or not \
            set (False).
    """

    key: str
    value: Union[str, bool, int, None]
    is_set: bool

    def check(self, dependency_values: List[str]) -> bool:
        """
        Check if dependency is satisfied

        Args:
            dependency_values (List[str]): List of dependency values to check against.

        Returns:
            bool: True if the dependency is satisfied, False otherwise.
        """

        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 type `Dependency`.

    This class maps dependencies of keys requiring any number dependencies of \
        type `Dependency`. It is primarily useful for specifying nested dependencies \
        of UI elements shown in Wave.

    Attributes:
        dependencies (DefaultDict[str, List[Dependency]]): A dictionary mapping keys \
            to their dependencies of type `Dependency`.
        triggers (Set[str]): A set of all dependency keys that can trigger changes.
    """

    def __init__(self) -> None:
        self.dependencies: DefaultDict[str, List[Dependency]] = defaultdict(list)
        self.triggers: Set[str] = set()

    def add(self, keys: List[str], dependencies: List[Dependency]) -> None:
        """
        Append dependencies of type `Dependency` for given keys.

        Args:
            keys (List[str]): Keys to add dependencies for.
            dependencies (List[Dependency]): The Dependencys to depend on.

        Raises:
            ValueError: If the input keys are not unique.
        """

        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)