adiumentum 0.1.1__py3-none-any.whl → 0.3.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- adiumentum/__init__.py +35 -14
- adiumentum/dependency_sorting.py +84 -0
- adiumentum/display.py +49 -0
- adiumentum/functional.py +56 -5
- adiumentum/io_utils.py +63 -0
- adiumentum/markers.py +67 -84
- adiumentum/merge.py +113 -0
- adiumentum/paths_manager.py +19 -0
- adiumentum/pydantic_extensions.md +839 -0
- adiumentum/pydantic_extensions.py +410 -0
- adiumentum/{string.py → string_utils.py} +39 -11
- adiumentum/typing_utils.py +115 -2
- adiumentum-0.3.1.dist-info/METADATA +60 -0
- adiumentum-0.3.1.dist-info/RECORD +26 -0
- adiumentum-0.3.1.dist-info/entry_points.txt +3 -0
- adiumentum/io.py +0 -33
- adiumentum-0.1.1.dist-info/METADATA +0 -236
- adiumentum-0.1.1.dist-info/RECORD +0 -19
- {adiumentum-0.1.1.dist-info → adiumentum-0.3.1.dist-info}/WHEEL +0 -0
adiumentum/merge.py
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
from collections.abc import Callable, Hashable, Iterable
|
2
|
+
from functools import reduce
|
3
|
+
from typing import TypeVar
|
4
|
+
|
5
|
+
T = TypeVar("T")
|
6
|
+
H = TypeVar("H", bound=Hashable)
|
7
|
+
TPost = TypeVar("TPost")
|
8
|
+
TPre = TypeVar("TPre")
|
9
|
+
K = TypeVar("K", bound=Hashable)
|
10
|
+
V = TypeVar("V")
|
11
|
+
type Filterer[T] = Callable[[T], bool]
|
12
|
+
|
13
|
+
type IterableVal = list["ValType"] | set[Hashable] | tuple["ValType", ...]
|
14
|
+
type ValType = Hashable | IterableVal | dict[Hashable, "ValType"]
|
15
|
+
type IterReturnType = list[ValType] | set[Hashable] | tuple[ValType]
|
16
|
+
type Mergeable[K, T] = str | object | list[T] | set[T] | tuple[T] | dict[K, "Mergeable"]
|
17
|
+
|
18
|
+
|
19
|
+
def make_hashable(ob: object) -> Hashable:
|
20
|
+
def make_sequence_hashable(ob: list[T] | set[T]) -> tuple[T, ...]:
|
21
|
+
return tuple(ob)
|
22
|
+
|
23
|
+
def make_dict_hashable(ob: dict[K, V]) -> tuple[tuple[K, V], ...]:
|
24
|
+
return tuple(ob.items())
|
25
|
+
|
26
|
+
if isinstance(ob, Hashable):
|
27
|
+
return ob
|
28
|
+
if isinstance(ob, list | set):
|
29
|
+
return make_sequence_hashable(ob)
|
30
|
+
if isinstance(ob, dict):
|
31
|
+
return make_dict_hashable(ob)
|
32
|
+
return str(ob)
|
33
|
+
|
34
|
+
|
35
|
+
def join_as_sequence( # noqa: C901,PLR0911
|
36
|
+
lv: ValType,
|
37
|
+
rv: ValType,
|
38
|
+
default_new_type: type[list] | type[tuple] | type[set] = tuple,
|
39
|
+
add_duplicates: bool = True,
|
40
|
+
) -> IterableVal:
|
41
|
+
def keep_duplicates(a: Iterable, _) -> Iterable:
|
42
|
+
return a
|
43
|
+
|
44
|
+
def remove_duplicates(a: Iterable, b) -> Iterable:
|
45
|
+
compare = set(b) if isinstance(b, list | set | tuple) else {b}
|
46
|
+
return filter(lambda x: x not in compare, a)
|
47
|
+
|
48
|
+
filtr = keep_duplicates if add_duplicates else remove_duplicates
|
49
|
+
|
50
|
+
if isinstance(lv, list):
|
51
|
+
if isinstance(rv, list | set | tuple):
|
52
|
+
return lv + list(filtr(rv, lv))
|
53
|
+
else:
|
54
|
+
return lv if rv in lv else [*lv, rv]
|
55
|
+
if isinstance(lv, tuple):
|
56
|
+
if isinstance(rv, list | set | tuple):
|
57
|
+
return (*lv, *filtr(rv, lv))
|
58
|
+
else:
|
59
|
+
return lv if rv in lv else (*lv, rv)
|
60
|
+
if isinstance(lv, set):
|
61
|
+
if isinstance(rv, list | set | tuple):
|
62
|
+
return {*lv, *filtr(map(make_hashable, rv), lv)}
|
63
|
+
else:
|
64
|
+
return lv if make_hashable(rv) in lv else {*lv, make_hashable(rv)}
|
65
|
+
|
66
|
+
if isinstance(rv, list):
|
67
|
+
return [lv, *filtr(rv, lv)]
|
68
|
+
if isinstance(rv, tuple):
|
69
|
+
return (lv, *filtr(rv, lv))
|
70
|
+
if isinstance(rv, set):
|
71
|
+
return {make_hashable(lv), *filtr(rv, make_hashable(lv))}
|
72
|
+
|
73
|
+
return default_new_type((lv, rv))
|
74
|
+
|
75
|
+
|
76
|
+
def merge_dicts(
|
77
|
+
*dicts: dict[Hashable, ValType],
|
78
|
+
default_new_sequence: type[list] | type[tuple] | type[set] = tuple,
|
79
|
+
add_duplicates: bool = True,
|
80
|
+
) -> dict[Hashable, ValType]:
|
81
|
+
def merge_values(right_val: ValType, left_val: ValType) -> ValType: # noqa: PLR0911
|
82
|
+
if left_val == right_val:
|
83
|
+
return left_val
|
84
|
+
if isinstance(left_val, dict) and isinstance(right_val, dict):
|
85
|
+
return merge_dicts(left_val, right_val, default_new_sequence=default_new_sequence)
|
86
|
+
if left_val is None:
|
87
|
+
return right_val
|
88
|
+
if right_val is None:
|
89
|
+
return left_val
|
90
|
+
if isinstance(left_val, dict):
|
91
|
+
return left_val
|
92
|
+
if isinstance(right_val, dict):
|
93
|
+
return right_val
|
94
|
+
return join_as_sequence(
|
95
|
+
left_val,
|
96
|
+
right_val,
|
97
|
+
default_new_type=default_new_sequence,
|
98
|
+
add_duplicates=add_duplicates,
|
99
|
+
)
|
100
|
+
|
101
|
+
def merge(
|
102
|
+
left: dict[Hashable, ValType], right: dict[Hashable, ValType]
|
103
|
+
) -> dict[Hashable, ValType]:
|
104
|
+
common_keys: set[Hashable] = set(left).intersection(set(right))
|
105
|
+
common: dict[Hashable, ValType] = {}
|
106
|
+
for key in common_keys:
|
107
|
+
lv, rv = left[key], right[key]
|
108
|
+
new_dict: dict[Hashable, ValType] = {key: merge_values(lv, rv)}
|
109
|
+
common.update(new_dict)
|
110
|
+
|
111
|
+
return left | right | common
|
112
|
+
|
113
|
+
return reduce(merge, dicts)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
from abc import abstractmethod
|
2
|
+
from pathlib import Path
|
3
|
+
from typing import Self
|
4
|
+
|
5
|
+
|
6
|
+
class PathsManager:
|
7
|
+
@abstractmethod
|
8
|
+
def setup(self) -> None: ...
|
9
|
+
|
10
|
+
@classmethod
|
11
|
+
@abstractmethod
|
12
|
+
def auto(cls, root_dir: Path): ...
|
13
|
+
|
14
|
+
@classmethod
|
15
|
+
@abstractmethod
|
16
|
+
def read(cls, config_file_path: Path) -> Self: ...
|
17
|
+
|
18
|
+
@abstractmethod
|
19
|
+
def write(self, config_file_path: Path) -> None: ...
|