h2o-llmstudio
118 строк · 3.3 Кб
1from typing import Iterable, List, Optional
2
3
4class Order:
5"""
6A list-like structure to specify the order of items in a dictionary.
7The main characteristics are:
8- Append and insert only. Cannot remove elements. This is not strictly required
9by the use-case but probably good practice.
10- Elements must be unique. Inserting an element which is already in the list
11will throw an error.
12
13Primarily useful for specifying the order in which UI elements
14should be shown in Wave.
15"""
16
17def __init__(self, keys: Optional[List[str]] = None):
18if keys is not None:
19self._list = list(keys)
20else:
21self._list = list()
22
23def _unique_guard(self, *keys: str):
24for key in keys:
25if key in self._list:
26raise ValueError(f"`{key}` is already in the list!")
27
28def append(self, key: str):
29"""
30Append a key at the end of the list:
31
32Args:
33key: String to append.
34
35Raises:
36- `ValueError` if the key is already in the list.
37"""
38
39self._unique_guard(key)
40
41self._list.append(key)
42
43def extend(self, keys: Iterable[str]):
44"""
45Extend the list by multiple keys.
46
47Args:
48keys: Iterable of keys.
49
50Raises:
51- `ValueError` if one or more key is already in the list.
52"""
53
54self._unique_guard(*keys)
55
56self._list.extend(keys)
57
58def insert(
59self, *keys: str, before: Optional[str] = None, after: Optional[str] = None
60):
61"""
62Insert one or more keys. Either `before` or `after`, but not both, must be set
63to determine position.
64
65Args:
66keys: One more keys to insert.
67after: A key immediately after which the `keys` will be inserted.
68before: A key immediately before which the `keys` are inserted.
69
70Raises:
71- `ValueError` if one or more key is already in the list.
72- `ValueError` if `before` / `after` does not exist in the list.
73- `ValueError` if an invalid combination of arguments is set.
74"""
75
76self._unique_guard(*keys)
77
78if before is not None:
79for key in keys[::-1]:
80self._list.insert(self._list.index(before), key)
81
82if after is not None:
83raise ValueError("`after` must be None if `before` is set.")
84
85if after is not None:
86for key in keys[::-1]:
87self._list.insert(self._list.index(after) + 1, key)
88
89if before is not None:
90raise ValueError("`before` must be None if `after` is set.")
91
92if before is None and after is None:
93raise ValueError("Either `before` or `after` must be set.")
94
95def __getitem__(self, idx):
96return self._list[idx]
97
98def __len__(self):
99return len(self._list)
100
101def __iter__(self):
102return iter(self._list)
103
104
105def test_order():
106order = Order(["dataset", "training", "validation", "logging"])
107
108order.insert("architecture", before="training")
109order.insert("environment", after="validation")
110
111assert [item for item in order] == [
112"dataset",
113"architecture",
114"training",
115"validation",
116"environment",
117"logging",
118]
119