persidict 0.34.2__py3-none-any.whl → 0.35.0__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.
Potentially problematic release.
This version of persidict might be problematic. Click here for more details.
- persidict/file_dir_dict.py +259 -53
- persidict/jokers.py +52 -12
- persidict/overlapping_multi_dict.py +99 -36
- persidict/persi_dict.py +293 -105
- persidict/s3_dict.py +167 -38
- persidict/safe_chars.py +22 -3
- persidict/safe_str_tuple.py +142 -34
- persidict/safe_str_tuple_signing.py +140 -36
- persidict/write_once_dict.py +180 -38
- {persidict-0.34.2.dist-info → persidict-0.35.0.dist-info}/METADATA +4 -5
- persidict-0.35.0.dist-info/RECORD +13 -0
- {persidict-0.34.2.dist-info → persidict-0.35.0.dist-info}/WHEEL +1 -1
- persidict/.DS_Store +0 -0
- persidict-0.34.2.dist-info/RECORD +0 -14
|
@@ -1,57 +1,120 @@
|
|
|
1
1
|
from .persi_dict import PersiDict
|
|
2
2
|
|
|
3
3
|
class OverlappingMultiDict:
|
|
4
|
-
"""
|
|
4
|
+
"""Container for multiple PersiDict instances sharing the same base and differing by file_type.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
of the inner PersiDict object.
|
|
6
|
+
This class instantiates several sub-dictionaries (PersiDict subclasses) that
|
|
7
|
+
share common parameters but differ by their file_type. Each sub-dictionary is
|
|
8
|
+
exposed as an attribute whose name equals the file_type (e.g., obj.json, obj.csv).
|
|
9
|
+
All sub-dictionaries typically point to the same underlying base directory or
|
|
10
|
+
bucket and differ only in how items are materialized by file type.
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
Attributes:
|
|
13
|
+
dict_type (type):
|
|
14
|
+
A subclass of PersiDict used to create each sub-dictionary.
|
|
15
|
+
shared_subdicts_params (dict):
|
|
16
|
+
Parameters applied to every created sub-dictionary (e.g., base_dir,
|
|
17
|
+
bucket, immutable_items, digest_len).
|
|
18
|
+
individual_subdicts_params (dict):
|
|
19
|
+
Mapping from file_type (attribute name) to a dict of parameters that
|
|
20
|
+
are specific to that sub-dictionary. These override or extend
|
|
21
|
+
shared_subdicts_params for the given file_type.
|
|
22
|
+
subdicts_names (list[str]):
|
|
23
|
+
The list of file_type names (i.e., attribute names) created.
|
|
16
24
|
|
|
25
|
+
Raises:
|
|
26
|
+
TypeError: If pickling is attempted or item access is used on the
|
|
27
|
+
OverlappingMultiDict itself rather than its sub-dicts.
|
|
17
28
|
"""
|
|
18
29
|
def __init__(self
|
|
19
30
|
, dict_type:type
|
|
20
31
|
, shared_subdicts_params:dict
|
|
21
32
|
, **individual_subdicts_params):
|
|
22
|
-
|
|
23
|
-
|
|
33
|
+
"""Initialize the container and create sub-dictionaries.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
dict_type (type):
|
|
37
|
+
A subclass of PersiDict that will be instantiated for each
|
|
38
|
+
file_type provided via individual_subdicts_params.
|
|
39
|
+
shared_subdicts_params (dict):
|
|
40
|
+
Parameters shared by all sub-dicts (e.g., base_dir, bucket).
|
|
41
|
+
**individual_subdicts_params: Dict[str, dict]
|
|
42
|
+
Keyword arguments where each key is a file_type (also the
|
|
43
|
+
attribute name to be created) and each value is a dict of
|
|
44
|
+
parameters specific to that sub-dict. These are merged with
|
|
45
|
+
shared_subdicts_params when constructing the sub-dict. The
|
|
46
|
+
resulting dict also receives file_type=<key>.
|
|
47
|
+
|
|
48
|
+
Raises:
|
|
49
|
+
TypeError: If dict_type is not a PersiDict subclass, or if
|
|
50
|
+
shared_subdicts_params is not a dict, or if any individual
|
|
51
|
+
parameter set is not a dict.
|
|
52
|
+
"""
|
|
53
|
+
if not issubclass(dict_type, PersiDict):
|
|
54
|
+
raise TypeError("dict_type must be a subclass of PersiDict")
|
|
55
|
+
if not isinstance(shared_subdicts_params, dict):
|
|
56
|
+
raise TypeError("shared_subdicts_params must be a dict")
|
|
24
57
|
self.dict_type = dict_type
|
|
25
58
|
self.shared_subdicts_params = shared_subdicts_params
|
|
26
59
|
self.individual_subdicts_params = individual_subdicts_params
|
|
27
60
|
self.subdicts_names = list(individual_subdicts_params.keys())
|
|
28
61
|
for subdict_name in individual_subdicts_params:
|
|
29
|
-
|
|
62
|
+
if not isinstance(individual_subdicts_params[subdict_name], dict):
|
|
63
|
+
raise TypeError(
|
|
64
|
+
f"Params for subdict {subdict_name!r} must be a dict")
|
|
30
65
|
self.__dict__[subdict_name] = dict_type(
|
|
31
66
|
**{**shared_subdicts_params
|
|
32
67
|
,**individual_subdicts_params[subdict_name]
|
|
33
68
|
,"file_type":subdict_name})
|
|
34
69
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
70
|
+
def __getstate__(self):
|
|
71
|
+
"""Prevent pickling.
|
|
72
|
+
|
|
73
|
+
Raises:
|
|
74
|
+
TypeError: Always raised; this object is not pickleable.
|
|
75
|
+
"""
|
|
76
|
+
raise TypeError("OverlappingMultiDict cannot be pickled.")
|
|
77
|
+
|
|
78
|
+
def __setstate__(self, state):
|
|
79
|
+
"""Prevent unpickling.
|
|
80
|
+
|
|
81
|
+
Raises:
|
|
82
|
+
TypeError: Always raised; this object is not pickleable.
|
|
83
|
+
"""
|
|
84
|
+
raise TypeError("OverlappingMultiDict cannot be pickled.")
|
|
85
|
+
|
|
86
|
+
def __getitem__(self, key):
|
|
87
|
+
"""Disallow item access on the container itself.
|
|
88
|
+
|
|
89
|
+
Suggest accessing items through the sub-dictionaries exposed as
|
|
90
|
+
attributes (e.g., obj.json[key]).
|
|
91
|
+
|
|
92
|
+
Raises:
|
|
93
|
+
TypeError: Always raised to indicate unsupported operation.
|
|
94
|
+
"""
|
|
95
|
+
raise TypeError(
|
|
96
|
+
"OverlappingMultiDict does not support item access by key. "
|
|
97
|
+
"Individual items should be accessed through nested dicts, "
|
|
98
|
+
f"which are available via attributes {self.subdicts_names}")
|
|
99
|
+
|
|
100
|
+
def __setitem__(self, key, value):
|
|
101
|
+
"""Disallow item assignment on the container itself.
|
|
102
|
+
|
|
103
|
+
Raises:
|
|
104
|
+
TypeError: Always raised to indicate unsupported operation.
|
|
105
|
+
"""
|
|
106
|
+
raise TypeError(
|
|
107
|
+
"OverlappingMultiDict does not support item assignment by key. "
|
|
108
|
+
"Individual items should be accessed through nested dicts, "
|
|
109
|
+
f"which are available via attributes {self.subdicts_names}")
|
|
110
|
+
|
|
111
|
+
def __delitem__(self, key):
|
|
112
|
+
"""Disallow item deletion on the container itself.
|
|
113
|
+
|
|
114
|
+
Raises:
|
|
115
|
+
TypeError: Always raised to indicate unsupported operation.
|
|
116
|
+
"""
|
|
117
|
+
raise TypeError(
|
|
118
|
+
"OverlappingMultiDict does not support item deletion by key. "
|
|
119
|
+
"Individual items can be deletedthrough nested dicts, "
|
|
120
|
+
f"which are available via attributes {self.subdicts_names}")
|