kevin-toolbox-dev 1.4.9__py3-none-any.whl → 1.4.11__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.
- kevin_toolbox/__init__.py +2 -2
- kevin_toolbox/computer_science/algorithm/cache_manager/__init__.py +1 -0
- kevin_toolbox/computer_science/algorithm/cache_manager/cache/cache_base.py +10 -0
- kevin_toolbox/computer_science/algorithm/cache_manager/cache/memo_cache.py +17 -0
- kevin_toolbox/computer_science/algorithm/cache_manager/cache_manager.py +24 -74
- kevin_toolbox/computer_science/algorithm/cache_manager/cache_manager_wto_strategy.py +157 -0
- kevin_toolbox/computer_science/algorithm/for_seq/__init__.py +1 -0
- kevin_toolbox/computer_science/algorithm/for_seq/sample_subset_most_evenly.py +52 -0
- kevin_toolbox/computer_science/algorithm/redirector/__init__.py +1 -0
- kevin_toolbox/computer_science/algorithm/redirector/redirectable_sequence_fetcher.py +258 -0
- kevin_toolbox/computer_science/algorithm/sampler/__init__.py +1 -0
- kevin_toolbox/computer_science/algorithm/sampler/reservoir_sampler.py +116 -0
- kevin_toolbox/computer_science/algorithm/statistician/accumulator_base.py +1 -1
- kevin_toolbox/data_flow/file/kevin_notation/kevin_notation_reader.py +18 -7
- kevin_toolbox/data_flow/file/kevin_notation/kevin_notation_writer.py +8 -1
- kevin_toolbox/data_flow/file/kevin_notation/test/test_data/data_0.py +2 -1
- kevin_toolbox/data_flow/file/kevin_notation/test/test_kevin_notation.py +1 -4
- kevin_toolbox/data_flow/file/kevin_notation/test/test_kevin_notation_debug.py +16 -4
- kevin_toolbox/data_flow/file/markdown/table/get_format.py +3 -0
- kevin_toolbox/nested_dict_list/get_nodes.py +9 -0
- kevin_toolbox/nested_dict_list/value_parser/replace_identical_with_reference.py +2 -4
- kevin_toolbox/patches/for_logging/build_logger.py +3 -1
- kevin_toolbox_dev-1.4.11.dist-info/METADATA +67 -0
- {kevin_toolbox_dev-1.4.9.dist-info → kevin_toolbox_dev-1.4.11.dist-info}/RECORD +26 -20
- kevin_toolbox_dev-1.4.9.dist-info/METADATA +0 -75
- {kevin_toolbox_dev-1.4.9.dist-info → kevin_toolbox_dev-1.4.11.dist-info}/WHEEL +0 -0
- {kevin_toolbox_dev-1.4.9.dist-info → kevin_toolbox_dev-1.4.11.dist-info}/top_level.txt +0 -0
kevin_toolbox/__init__.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
__version__ = "1.4.
|
1
|
+
__version__ = "1.4.11"
|
2
2
|
|
3
3
|
|
4
4
|
import os
|
@@ -12,5 +12,5 @@ os.system(
|
|
12
12
|
os.system(
|
13
13
|
f'python {os.path.split(__file__)[0]}/env_info/check_validity_and_uninstall.py '
|
14
14
|
f'--package_name kevin-toolbox-dev '
|
15
|
-
f'--expiration_timestamp
|
15
|
+
f'--expiration_timestamp 1760340881 --verbose 0'
|
16
16
|
)
|
@@ -12,6 +12,7 @@ class Cache_Base(ABC):
|
|
12
12
|
- 判断是否命中 has()
|
13
13
|
- 获取缓存已占空间 len()
|
14
14
|
- 清空所有内容 clear()
|
15
|
+
- 加载和保存状态 load_state_dict(), state_dict()
|
15
16
|
等方法。
|
16
17
|
|
17
18
|
对外提供:
|
@@ -21,6 +22,7 @@ class Cache_Base(ABC):
|
|
21
22
|
- 判断是否命中 has()
|
22
23
|
- 获取缓存已占空间 len()
|
23
24
|
- 清空所有内容 clear()
|
25
|
+
- 加载和保存状态 load_state_dict(), state_dict()
|
24
26
|
等接口。
|
25
27
|
"""
|
26
28
|
|
@@ -69,6 +71,14 @@ class Cache_Base(ABC):
|
|
69
71
|
def clear(self):
|
70
72
|
pass
|
71
73
|
|
74
|
+
@abstractmethod
|
75
|
+
def load_state_dict(self, state_dict):
|
76
|
+
pass
|
77
|
+
|
78
|
+
@abstractmethod
|
79
|
+
def state_dict(self, b_deepcopy=True):
|
80
|
+
pass
|
81
|
+
|
72
82
|
def __getitem__(self, key):
|
73
83
|
# self[key]
|
74
84
|
return self.read(key=key)
|
@@ -30,6 +30,23 @@ class Memo_Cache(Cache_Base):
|
|
30
30
|
def clear(self):
|
31
31
|
self.cache_s.clear()
|
32
32
|
|
33
|
+
def load_state_dict(self, state_dict):
|
34
|
+
"""
|
35
|
+
加载状态
|
36
|
+
"""
|
37
|
+
self.clear()
|
38
|
+
self.cache_s.update(state_dict["cache_s"])
|
39
|
+
|
40
|
+
def state_dict(self, b_deepcopy=True):
|
41
|
+
"""
|
42
|
+
获取状态
|
43
|
+
"""
|
44
|
+
temp = {"cache_s": self.cache_s}
|
45
|
+
if b_deepcopy:
|
46
|
+
import kevin_toolbox.nested_dict_list as ndl
|
47
|
+
temp = ndl.copy_(var=temp, b_deepcopy=True, b_keep_internal_references=True)
|
48
|
+
return temp
|
49
|
+
|
33
50
|
|
34
51
|
# 添加其他别名
|
35
52
|
for name in [":in_memory:Memo", ":in_memory:MC", ":in_memory:memory"]:
|
@@ -2,9 +2,10 @@ import time
|
|
2
2
|
from .strategy import Strategy_Base
|
3
3
|
from .cache import Cache_Base
|
4
4
|
from .variable import CACHE_STRATEGY_REGISTRY, CACHE_BUILDER_REGISTRY
|
5
|
+
from .cache_manager_wto_strategy import Cache_Manager_wto_Strategy
|
5
6
|
|
6
7
|
|
7
|
-
class Cache_Manager:
|
8
|
+
class Cache_Manager(Cache_Manager_wto_Strategy):
|
8
9
|
"""
|
9
10
|
缓存管理器
|
10
11
|
|
@@ -14,6 +15,7 @@ class Cache_Manager:
|
|
14
15
|
- 删除并返回条目 pop(key)
|
15
16
|
- 判断是否有该条目 has()
|
16
17
|
- 清空所有内容 clear()
|
18
|
+
- 加载和保存状态 load_state_dict(), state_dict()
|
17
19
|
|
18
20
|
并支持以下用法:
|
19
21
|
通过 len(.) 获取缓存大小,通过 in 操作符判断是否有某个条目
|
@@ -95,29 +97,7 @@ class Cache_Manager:
|
|
95
97
|
self.cache = cache # type:Cache_Base
|
96
98
|
self.metadata_s = dict() # 保存条目的相关信息
|
97
99
|
|
98
|
-
def
|
99
|
-
"""
|
100
|
-
以 key 为查询键,将 value 添加到缓存中
|
101
|
-
|
102
|
-
参数:
|
103
|
-
key:
|
104
|
-
value:
|
105
|
-
b_allow_overwrite: <boolean> 是否允许覆写缓存中已有的条目
|
106
|
-
默认为 True
|
107
|
-
"""
|
108
|
-
# 判断是否需要进行覆写
|
109
|
-
if self.cache.has(key=key):
|
110
|
-
if id(value) != id(self.cache.read(key=key)):
|
111
|
-
if b_allow_overwrite:
|
112
|
-
self.__remove_of_cache(key=key)
|
113
|
-
else:
|
114
|
-
raise KeyError(f'key: {key} already exists, modification of existing entries is prohibited')
|
115
|
-
else:
|
116
|
-
return
|
117
|
-
# 记录到缓存
|
118
|
-
self.__write_of_cache(key=key, value=value)
|
119
|
-
|
120
|
-
def __write_of_cache(self, key, value):
|
100
|
+
def _write_of_cache(self, key, value):
|
121
101
|
"""
|
122
102
|
向缓存中新增不存在的条目
|
123
103
|
"""
|
@@ -143,9 +123,9 @@ class Cache_Manager:
|
|
143
123
|
assert len(suggest_keys) == len(self.cache) - self.paras["refactor_size"], \
|
144
124
|
f'expect {len(self.cache) - self.paras["refactor_size"]} deletion suggestions, but got {len(suggest_keys)}'
|
145
125
|
for key in suggest_keys:
|
146
|
-
self.
|
126
|
+
self._remove_of_cache(key=key)
|
147
127
|
|
148
|
-
def
|
128
|
+
def _remove_of_cache(self, key):
|
149
129
|
"""
|
150
130
|
从缓存中删除存在的条目
|
151
131
|
"""
|
@@ -154,43 +134,7 @@ class Cache_Manager:
|
|
154
134
|
# 通知策略管理器
|
155
135
|
self.strategy.notified_by_remove_of_cache(key=key, metadata=metadata)
|
156
136
|
|
157
|
-
def
|
158
|
-
"""
|
159
|
-
获取 key 对应的值
|
160
|
-
|
161
|
-
参数:
|
162
|
-
key: <hashable>
|
163
|
-
default: 默认值
|
164
|
-
当 key 在缓存中不存在时返回
|
165
|
-
default_factory: <callable> 用于产生默认值的函数
|
166
|
-
当 key 在缓存中不存在时返回该函数的结果
|
167
|
-
使用该参数相对于 default 能延迟默认值的产生(如果不需要用到默认值就不生成),提高效率
|
168
|
-
注意!!上面两个参数同时指定时,将以前者为准。
|
169
|
-
b_add_if_not_found: <boolean> 当 key 在缓存中不存在时,是否添加到缓存中
|
170
|
-
默认为 False
|
171
|
-
"""
|
172
|
-
if self.cache.has(key=key):
|
173
|
-
value = self.__read_of_cache(key=key)
|
174
|
-
elif "default" in kwargs or callable(default_factory):
|
175
|
-
value = kwargs["default"] if "default" in kwargs else default_factory()
|
176
|
-
if b_add_if_not_found:
|
177
|
-
self.__write_of_cache(key=key, value=value)
|
178
|
-
else:
|
179
|
-
raise KeyError(key)
|
180
|
-
return value
|
181
|
-
|
182
|
-
def pop(self, key):
|
183
|
-
"""
|
184
|
-
从缓存中删除 key 对应的条目,并返回该条目的值
|
185
|
-
"""
|
186
|
-
if self.cache.has(key=key):
|
187
|
-
value = self.__read_of_cache(key=key)
|
188
|
-
self.__remove_of_cache(key=key)
|
189
|
-
else:
|
190
|
-
raise KeyError(key)
|
191
|
-
return value
|
192
|
-
|
193
|
-
def __read_of_cache(self, key):
|
137
|
+
def _read_of_cache(self, key):
|
194
138
|
"""
|
195
139
|
读取缓存中 已经存在的 条目
|
196
140
|
"""
|
@@ -205,20 +149,26 @@ class Cache_Manager:
|
|
205
149
|
|
206
150
|
return value
|
207
151
|
|
208
|
-
def has(self, key):
|
209
|
-
"""
|
210
|
-
判断 key 是否在缓存中
|
211
|
-
注意!!不会更新 metadata
|
212
|
-
"""
|
213
|
-
return self.cache.has(key=key)
|
214
|
-
|
215
152
|
def clear(self):
|
216
153
|
self.cache.clear()
|
217
154
|
self.metadata_s.clear()
|
218
155
|
self.strategy.notified_by_clear_of_cache()
|
219
156
|
|
220
|
-
|
221
|
-
|
157
|
+
# ---------------------- 用于保存和加载状态 ---------------------- #
|
158
|
+
def load_state_dict(self, state_dict):
|
159
|
+
"""
|
160
|
+
加载状态
|
161
|
+
"""
|
162
|
+
self.clear()
|
163
|
+
self.cache.load_state_dict(state_dict=state_dict["cache"])
|
164
|
+
self.metadata_s.update(state_dict["metadata_s"])
|
222
165
|
|
223
|
-
def
|
224
|
-
|
166
|
+
def state_dict(self, b_deepcopy=True):
|
167
|
+
"""
|
168
|
+
获取状态
|
169
|
+
"""
|
170
|
+
temp = {"cache": self.cache.state_dict(b_deepcopy=False), "metadata_s": self.metadata_s}
|
171
|
+
if b_deepcopy:
|
172
|
+
import kevin_toolbox.nested_dict_list as ndl
|
173
|
+
temp = ndl.copy_(var=temp, b_deepcopy=True, b_keep_internal_references=True)
|
174
|
+
return temp
|
@@ -0,0 +1,157 @@
|
|
1
|
+
from .cache import Cache_Base
|
2
|
+
from .variable import CACHE_BUILDER_REGISTRY
|
3
|
+
|
4
|
+
|
5
|
+
class Cache_Manager_wto_Strategy:
|
6
|
+
"""
|
7
|
+
不绑定任何策略的缓存管理器
|
8
|
+
|
9
|
+
提供以下接口:
|
10
|
+
- 添加条目 add(key, value, b_allow_overwrite)
|
11
|
+
- 获取条目 get(key, b_add_if_not_found, default_factory, default)
|
12
|
+
- 删除并返回条目 pop(key)
|
13
|
+
- 判断是否有该条目 has()
|
14
|
+
- 清空所有内容 clear()
|
15
|
+
- 加载和保存状态 load_state_dict(), state_dict()
|
16
|
+
|
17
|
+
并支持以下用法:
|
18
|
+
通过 len(.) 获取缓存大小,通过 in 操作符判断是否有某个条目
|
19
|
+
"""
|
20
|
+
|
21
|
+
def __init__(self, **kwargs):
|
22
|
+
"""
|
23
|
+
参数:
|
24
|
+
cache: <str/dict/Cache_Base> 缓存种类
|
25
|
+
"""
|
26
|
+
# 默认参数
|
27
|
+
paras = {
|
28
|
+
"cache": ":in_memory:Memo",
|
29
|
+
}
|
30
|
+
|
31
|
+
# 获取参数
|
32
|
+
paras.update(kwargs)
|
33
|
+
|
34
|
+
# 校验参数
|
35
|
+
# cache
|
36
|
+
assert isinstance(paras["cache"], (str, dict, Cache_Base)), \
|
37
|
+
"cache must be a string, dict of paras or a Cache_Base object"
|
38
|
+
if isinstance(paras["cache"], str):
|
39
|
+
cache = CACHE_BUILDER_REGISTRY.get(name=paras["cache"])()
|
40
|
+
elif isinstance(paras["cache"], dict):
|
41
|
+
cache = CACHE_BUILDER_REGISTRY.get(name=paras["cache"]["name"])(**paras["cache"].get("paras", dict()))
|
42
|
+
else:
|
43
|
+
cache = paras["cache"]
|
44
|
+
|
45
|
+
self.paras = paras
|
46
|
+
self.cache = cache # type:Cache_Base
|
47
|
+
|
48
|
+
def _write_of_cache(self, key, value):
|
49
|
+
"""
|
50
|
+
向缓存中新增不存在的条目
|
51
|
+
"""
|
52
|
+
#
|
53
|
+
self.cache.write(key=key, value=value)
|
54
|
+
|
55
|
+
def _remove_of_cache(self, key):
|
56
|
+
"""
|
57
|
+
从缓存中删除存在的条目
|
58
|
+
"""
|
59
|
+
self.cache.remove(key=key)
|
60
|
+
|
61
|
+
def _read_of_cache(self, key):
|
62
|
+
"""
|
63
|
+
读取缓存中 已经存在的 条目
|
64
|
+
"""
|
65
|
+
return self.cache.read(key=key)
|
66
|
+
|
67
|
+
def add(self, key, value, b_allow_overwrite=True):
|
68
|
+
"""
|
69
|
+
以 key 为查询键,将 value 添加到缓存中
|
70
|
+
|
71
|
+
参数:
|
72
|
+
key:
|
73
|
+
value:
|
74
|
+
b_allow_overwrite: <boolean> 是否允许覆写缓存中已有的条目
|
75
|
+
默认为 True
|
76
|
+
"""
|
77
|
+
# 判断是否需要进行覆写
|
78
|
+
if self.cache.has(key=key):
|
79
|
+
if id(value) != id(self.cache.read(key=key)):
|
80
|
+
if b_allow_overwrite:
|
81
|
+
self._remove_of_cache(key=key)
|
82
|
+
else:
|
83
|
+
raise KeyError(f'key: {key} already exists, modification of existing entries is prohibited')
|
84
|
+
else:
|
85
|
+
return
|
86
|
+
# 记录到缓存
|
87
|
+
self._write_of_cache(key=key, value=value)
|
88
|
+
|
89
|
+
def get(self, key, b_add_if_not_found=False, default_factory=None, **kwargs):
|
90
|
+
"""
|
91
|
+
获取 key 对应的值
|
92
|
+
|
93
|
+
参数:
|
94
|
+
key: <hashable>
|
95
|
+
default: 默认值
|
96
|
+
当 key 在缓存中不存在时返回
|
97
|
+
default_factory: <callable> 用于产生默认值的函数
|
98
|
+
当 key 在缓存中不存在时返回该函数的结果
|
99
|
+
使用该参数相对于 default 能延迟默认值的产生(如果不需要用到默认值就不生成),提高效率
|
100
|
+
注意!!上面两个参数同时指定时,将以前者为准。
|
101
|
+
b_add_if_not_found: <boolean> 当 key 在缓存中不存在时,是否添加到缓存中
|
102
|
+
默认为 False
|
103
|
+
"""
|
104
|
+
if self.cache.has(key=key):
|
105
|
+
value = self._read_of_cache(key=key)
|
106
|
+
elif "default" in kwargs or callable(default_factory):
|
107
|
+
value = kwargs["default"] if "default" in kwargs else default_factory()
|
108
|
+
if b_add_if_not_found:
|
109
|
+
self._write_of_cache(key=key, value=value)
|
110
|
+
else:
|
111
|
+
raise KeyError(key)
|
112
|
+
return value
|
113
|
+
|
114
|
+
def pop(self, key):
|
115
|
+
"""
|
116
|
+
从缓存中删除 key 对应的条目,并返回该条目的值
|
117
|
+
"""
|
118
|
+
if self.cache.has(key=key):
|
119
|
+
value = self._read_of_cache(key=key)
|
120
|
+
self._remove_of_cache(key=key)
|
121
|
+
else:
|
122
|
+
raise KeyError(key)
|
123
|
+
return value
|
124
|
+
|
125
|
+
def has(self, key):
|
126
|
+
"""
|
127
|
+
判断 key 是否在缓存中
|
128
|
+
注意!!不会更新 metadata
|
129
|
+
"""
|
130
|
+
return self.cache.has(key=key)
|
131
|
+
|
132
|
+
def clear(self):
|
133
|
+
self.cache.clear()
|
134
|
+
|
135
|
+
# ---------------------- 用于保存和加载状态 ---------------------- #
|
136
|
+
def load_state_dict(self, state_dict):
|
137
|
+
"""
|
138
|
+
加载状态
|
139
|
+
"""
|
140
|
+
self.clear()
|
141
|
+
self.cache.load_state_dict(state_dict=state_dict["cache"])
|
142
|
+
|
143
|
+
def state_dict(self, b_deepcopy=True):
|
144
|
+
"""
|
145
|
+
获取状态
|
146
|
+
"""
|
147
|
+
temp = {"cache": self.cache.state_dict(b_deepcopy=False)}
|
148
|
+
if b_deepcopy:
|
149
|
+
import kevin_toolbox.nested_dict_list as ndl
|
150
|
+
temp = ndl.copy_(var=temp, b_deepcopy=True, b_keep_internal_references=True)
|
151
|
+
return temp
|
152
|
+
|
153
|
+
def __len__(self):
|
154
|
+
return len(self.cache)
|
155
|
+
|
156
|
+
def __contains__(self, key):
|
157
|
+
return self.has(key)
|
@@ -0,0 +1,52 @@
|
|
1
|
+
import math
|
2
|
+
from kevin_toolbox.patches.for_numpy.random import get_rng
|
3
|
+
|
4
|
+
|
5
|
+
def sample_subset_most_evenly(inputs, ratio=None, nums=None, seed=None, rng=None, b_shuffle_the_tail=True):
|
6
|
+
"""
|
7
|
+
对列表按给定比例or数量进行采样,并返回一个新的列表,并保证列表中每个元素在新列表中的占比尽量相近
|
8
|
+
说明:
|
9
|
+
根据 ratio/nums 的值,将输入列表重复复制并可能随机打乱尾部元素以保证每个元素都有等概率被选取,
|
10
|
+
生成一个新列表,其长度约为 len(inputs) * ratio nums。
|
11
|
+
以 ratio 为例:
|
12
|
+
- 当 ratio 为整数时,返回原列表重复多次的结果;
|
13
|
+
- 当 ratio 为非整数时,除了重复复制整数倍部分外,
|
14
|
+
还会从打乱后的列表中随机选取部分元素以达到目标长度。
|
15
|
+
|
16
|
+
参数:
|
17
|
+
inputs: <iterable> 输入列表或其他可迭代对象
|
18
|
+
ratio: <float> 采样比例,
|
19
|
+
采样后新列表长度约为 len(inputs) * ratio
|
20
|
+
nums: <int> 采样数量。
|
21
|
+
b_shuffle_the_tail: <boolean> 是否对尾部进行随机打乱
|
22
|
+
默认为 True
|
23
|
+
seed: <int, optional> 随机种子,用于生成确定性随机数
|
24
|
+
默认为 None
|
25
|
+
rng: <Random, optional> 随机数生成器实例
|
26
|
+
仅在b_shuffle_the_tail=True时,以上两个参数起效,且仅需指定一个即可。
|
27
|
+
|
28
|
+
"""
|
29
|
+
if nums is None:
|
30
|
+
assert ratio is not None
|
31
|
+
nums = math.ceil(len(inputs) * ratio)
|
32
|
+
assert nums >= 0
|
33
|
+
if len(inputs) == 0 or nums == 0:
|
34
|
+
return []
|
35
|
+
|
36
|
+
inputs = list(inputs)
|
37
|
+
temp = inputs.copy()
|
38
|
+
if b_shuffle_the_tail:
|
39
|
+
rng = get_rng(seed=seed, rng=rng)
|
40
|
+
rng.shuffle(temp)
|
41
|
+
|
42
|
+
outputs = [] + inputs * math.floor(nums / len(inputs)) + temp[:nums % len(inputs)]
|
43
|
+
return outputs
|
44
|
+
|
45
|
+
|
46
|
+
if __name__ == '__main__':
|
47
|
+
print(sample_subset_most_evenly(range(5), ratio=8 / 5, seed=114, b_shuffle_the_tail=False))
|
48
|
+
print(sample_subset_most_evenly(range(5), ratio=8 / 5, seed=114, b_shuffle_the_tail=True))
|
49
|
+
|
50
|
+
#
|
51
|
+
print(sample_subset_most_evenly(range(5), nums=8, seed=114, b_shuffle_the_tail=False))
|
52
|
+
print(sample_subset_most_evenly(range(5), nums=8, seed=114, b_shuffle_the_tail=True))
|
@@ -0,0 +1 @@
|
|
1
|
+
from .redirectable_sequence_fetcher import Redirectable_Sequence_Fetcher
|