kevin-toolbox-dev 1.2.7__py3-none-any.whl → 1.3.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.
Files changed (30) hide show
  1. kevin_toolbox/__init__.py +2 -2
  2. kevin_toolbox/computer_science/algorithm/registration/registry.py +35 -11
  3. kevin_toolbox/computer_science/algorithm/statistician/__init__.py +1 -0
  4. kevin_toolbox/computer_science/algorithm/statistician/accumulator_base.py +146 -0
  5. kevin_toolbox/computer_science/algorithm/statistician/average_accumulator.py +9 -36
  6. kevin_toolbox/computer_science/algorithm/statistician/exponential_moving_average.py +10 -18
  7. kevin_toolbox/computer_science/algorithm/statistician/init_var/__init__.py +2 -0
  8. kevin_toolbox/computer_science/algorithm/statistician/init_var/init_by_data_format.py +24 -0
  9. kevin_toolbox/computer_science/algorithm/statistician/init_var/init_by_like.py +20 -0
  10. kevin_toolbox/data_flow/file/json_/read_json.py +1 -1
  11. kevin_toolbox/data_flow/file/markdown/generate_table.py +117 -13
  12. kevin_toolbox/nested_dict_list/copy_.py +7 -7
  13. kevin_toolbox/nested_dict_list/serializer/__init__.py +1 -0
  14. kevin_toolbox/nested_dict_list/serializer/enum_variable.py +12 -0
  15. kevin_toolbox/nested_dict_list/serializer/read.py +2 -1
  16. kevin_toolbox/nested_dict_list/serializer/variable.py +0 -12
  17. kevin_toolbox/nested_dict_list/serializer/write.py +2 -1
  18. kevin_toolbox/nested_dict_list/set_value.py +8 -2
  19. kevin_toolbox/patches/for_numpy/__init__.py +1 -0
  20. kevin_toolbox/patches/for_numpy/linalg/softmax.py +40 -4
  21. kevin_toolbox/patches/for_optuna/sample_from_feasible_domain.py +39 -13
  22. kevin_toolbox/patches/for_os/__init__.py +1 -0
  23. kevin_toolbox/patches/for_os/remove.py +4 -2
  24. kevin_toolbox/patches/for_os/walk.py +167 -0
  25. kevin_toolbox_dev-1.3.0.dist-info/METADATA +73 -0
  26. {kevin_toolbox_dev-1.2.7.dist-info → kevin_toolbox_dev-1.3.0.dist-info}/RECORD +28 -23
  27. kevin_toolbox/computer_science/algorithm/statistician/_init_var.py +0 -27
  28. kevin_toolbox_dev-1.2.7.dist-info/METADATA +0 -69
  29. {kevin_toolbox_dev-1.2.7.dist-info → kevin_toolbox_dev-1.3.0.dist-info}/WHEEL +0 -0
  30. {kevin_toolbox_dev-1.2.7.dist-info → kevin_toolbox_dev-1.3.0.dist-info}/top_level.txt +0 -0
@@ -3,7 +3,6 @@ import time
3
3
  from kevin_toolbox.patches import for_os
4
4
  from kevin_toolbox.data_flow.file import json_
5
5
  import kevin_toolbox.nested_dict_list as ndl
6
- from kevin_toolbox.nested_dict_list.serializer.variable import SERIALIZER_BACKEND
7
6
 
8
7
 
9
8
  def read(input_path, **kwargs):
@@ -13,6 +12,8 @@ def read(input_path, **kwargs):
13
12
  参数:
14
13
  input_path: <path> 文件夹或者 .tar 文件,具体结构参考 write()
15
14
  """
15
+ from kevin_toolbox.nested_dict_list.serializer.variable import SERIALIZER_BACKEND
16
+
16
17
  assert os.path.exists(input_path)
17
18
 
18
19
  # 解压
@@ -1,5 +1,4 @@
1
1
  import os
2
- from enum import Enum
3
2
  from kevin_toolbox.computer_science.algorithm.registration import Registry
4
3
 
5
4
  SERIALIZER_BACKEND = Registry(uid="SERIALIZER_BACKEND")
@@ -7,14 +6,3 @@ SERIALIZER_BACKEND = Registry(uid="SERIALIZER_BACKEND")
7
6
  # 从 kevin_toolbox/nested_dict_list/serializer/backends 下收集被注册的 backend
8
7
  SERIALIZER_BACKEND.collect_from_paths(path_ls=[os.path.join(os.path.dirname(__file__), "backends"), ],
9
8
  b_execute_now=False)
10
-
11
-
12
- class Strictness_Level(Enum):
13
- """
14
- 对于正确性与完整性的要求的严格程度
15
- """
16
- COMPLETE = "high" # 所有节点均有一个或者多个匹配上的 backend,且第一个匹配上的 backend 就成功写入。
17
- COMPATIBLE = "normal" # 所有节点均有一个或者多个匹配上的 backend,但是首先匹配到的 backend 写入出错,使用其后再次匹配到的其他 backend 能够成功写入
18
- # (这种情况更多应归咎于 backend 的 writable() 方法无法拒绝所有错误输入或者 backend 本身没有按照预期工作。一般而言这对最终写入内容的正确不会有太大影响。)
19
- # 这个等级是默认等级
20
- IGNORE_FAILURE = "low" # 匹配不完整,或者某些节点尝试过所有匹配到的 backend 之后仍然无法写入
@@ -6,7 +6,7 @@ from kevin_toolbox.data_flow.file import json_
6
6
  from kevin_toolbox.patches import for_os
7
7
  import kevin_toolbox.nested_dict_list as ndl
8
8
  from kevin_toolbox.nested_dict_list.traverse import Traversal_Mode
9
- from kevin_toolbox.nested_dict_list.serializer.variable import SERIALIZER_BACKEND, Strictness_Level
9
+ from .enum_variable import Strictness_Level
10
10
 
11
11
 
12
12
  def write(var, output_dir, settings=None, traversal_mode=Traversal_Mode.BFS, b_pack_into_tar=True,
@@ -83,6 +83,7 @@ def write(var, output_dir, settings=None, traversal_mode=Traversal_Mode.BFS, b_p
83
83
  的 backend 之后仍然无法写入
84
84
  默认是 "normal"
85
85
  """
86
+ from kevin_toolbox.nested_dict_list.serializer.variable import SERIALIZER_BACKEND
86
87
 
87
88
  #
88
89
  traversal_mode = Traversal_Mode(traversal_mode)
@@ -52,11 +52,17 @@ def set_value(var, name, value, b_force=False):
52
52
  raise ValueError(f'The location pointed to by name {name} does not exist in var')
53
53
  else:
54
54
  if method_ls[-1] in "|:":
55
+ # 对于字符串默认使用 dict 构建
55
56
  value = {raw_key: value}
56
57
  else:
58
+ # 对于需要eval的情况
57
59
  key = eval(raw_key)
58
- assert isinstance(key, (int,)) and key >= 0
59
- value = [None] * key + [value]
60
+ if isinstance(key, (int,)) and key >= 0:
61
+ # 只有当 key 为非负整数时,才会使用 list 构建
62
+ value = [None] * key + [value]
63
+ else:
64
+ # 其他,比如当 key 为元组、浮点数等等时,则使用 dict 构建
65
+ value = {key: value}
60
66
  var = set_value(var=var, name=name[:-1 - len(node_ls[-1])], value=value, b_force=b_force)
61
67
 
62
68
  return var
@@ -0,0 +1 @@
1
+ from . import linalg
@@ -1,11 +1,47 @@
1
1
  import numpy as np
2
2
 
3
3
 
4
- def softmax(v, axis=-1):
5
- # 为了数值稳定,减去最大值
6
- v = v - np.max(v)
7
- return np.exp(v) / np.sum(np.exp(v), axis=axis, keepdims=True)
4
+ def softmax(x, axis=-1, temperature=None, b_use_log_over_x=False):
5
+ """
6
+ 一种将多个数值转换为概率分布的函数
7
+ softmax(x)[k] = e^{x_k/t} / sum_{i}( e^{x_i/t} )
8
+
9
+ 参数:
10
+ axis: <int> 要对将哪一个轴转为概率分布(亦即沿着该轴求和将得到1)
11
+ 默认为最后一个轴
12
+ temperature: <float> 温度系数,起到对输入中的相对小/大值的抑制/增强作用。
13
+ 它是一个非负数。
14
+ 它越大,输出的概率分布越平缓。当趋于无穷时,输出退化为均匀分布。
15
+ 它越小,输出的概率分布越尖锐。当趋于0时,输出退化成狄拉克函数。
16
+ b_use_log_over_x: <boolean> 对输入的概率分布首先进行一次 log() 操作。
17
+ 默认为 False
18
+ 当设为 True 开启后,该函数将从 softmax 变为:
19
+ softmax(log(x))[k] = x_k^{1/t} / sum_{i}( x_i^{1/t} )
20
+ """
21
+ x = np.asarray(x)
22
+
23
+ if temperature == 0:
24
+ # quick
25
+ res = np.zeros_like(x)
26
+ res = np.where(x == np.max(x, axis=axis), 1, res)
27
+ elif b_use_log_over_x:
28
+ # softmax(log(x))
29
+ res = x ** (1 / temperature)
30
+ else:
31
+ # softmax(x)
32
+ # 为了数值稳定,减去最大值
33
+ x = x - np.max(x)
34
+ #
35
+ if temperature is not None:
36
+ assert temperature > 0
37
+ x /= temperature
38
+ res = np.exp(x)
39
+ res = res / np.sum(res, axis=axis, keepdims=True)
40
+ return res
8
41
 
9
42
 
10
43
  if __name__ == '__main__':
11
44
  print(softmax(np.asarray([0, 0.1]) * 10))
45
+ print(softmax(np.asarray([0, 0.1]), temperature=0.1))
46
+ print(softmax(np.asarray([[[0], [0.1]]]), temperature=0.00001, axis=1))
47
+ print(softmax(np.asarray([[[0], [0.1]]]), temperature=0, axis=1))
@@ -2,14 +2,14 @@ import optuna
2
2
  import kevin_toolbox.nested_dict_list as ndl
3
3
 
4
4
 
5
- def sample_from_feasible_domain(var, trial: optuna.trial.BaseTrial, pre_name=""):
5
+ def sample_from_feasible_domain(var, trial: optuna.trial.BaseTrial, f_p_name_builder=None, b_use_name_as_idx=True):
6
6
  """
7
7
  使用试验 trial 基于输入中的定义域 feasible_domain 部分进行参数采样和替换。
8
8
  遍历输入中的所有元素,找出符合 <feasible_domain> 格式要求的记录了参数定义域的元素,
9
9
  然后使用输入的试验实例 trial 结合参数定义域采样出对应的参数,最后用采样出来的参数替换掉原来的定义域。
10
10
 
11
11
  参数:
12
- inputs: <list/dict> 当其中的元素满足 <feasible_domain> 格式要求,将进行采样与替换。
12
+ var: <list/dict> 当其中的元素满足 <feasible_domain> 格式要求,将进行采样与替换。
13
13
  <feasible_domain> 格式要求:
14
14
  1. 是一个 dictionary
15
15
  2. 包含 "p_type" 字段
@@ -20,15 +20,26 @@ def sample_from_feasible_domain(var, trial: optuna.trial.BaseTrial, pre_name="")
20
20
  更多参见 https://optuna.readthedocs.io/zh_CN/latest/reference/generated/optuna.trial.Trial.html#optuna.trial.Trial
21
21
  中的 suggest_xxx() 函数。
22
22
  trial: <optuna.trial.BaseTrial> 试验
23
- pre_name: <string> 采样出的参数在试验 trial 中注册的名称的前缀
23
+ f_p_name_builder: <callable> 对于采样出的参数,使用该函数构建其在试验 trial 中注册的名称。
24
+ 函数类型为 def(idx, p_type): ...
25
+ 其中:
26
+ idx 被采样的节点在 var 中的位置
27
+ 当 b_use_name_as_idx=False 时,
28
+ 对于列表是 index,对于字典是 key
29
+ 当为 True 时,传入的是元素在整体结构中的 name 位置,name的格式和含义参考
30
+ name_handler.parse_name() 中的介绍
31
+ p_type 被采样的节点中的 "p_type" 字段
32
+ 默认为:
33
+ lambda idx, p_type: idx
34
+ b_use_name_as_idx: <boolean> 决定传入 f_p_name_builder 中的参数 idx 的形式。
24
35
 
25
36
  返回:
26
- var, name_ls
37
+ var, node_vs_paras_s
27
38
  var 是采样后的结果
28
- name_ls 是被采样的节点名称,注意并不带 pre_name 前缀
39
+ node_vs_paras_s 是一个<dict>,以被采样的节点在 var 中位置的名称作为键,以对应节点在 trial 中注册的参数名为值。
29
40
 
30
41
  实例:
31
- 对于输入 inputs={
42
+ 对于输入 var={
32
43
  "thr":[
33
44
  "interval_thr": {
34
45
  "p_type": "categorical",
@@ -56,19 +67,33 @@ def sample_from_feasible_domain(var, trial: optuna.trial.BaseTrial, pre_name="")
56
67
  ]
57
68
  }
58
69
  可能返回的采样结果是 res={"thr":[{"interval_thr":1000}, {"iou_thr":0.6}, {"connection":lambda x:x} ], }。
59
- pre_name="my" 时,这些参数在 trial 中注册的名称分别是 "my:thr@0:interval_thr","my:thr@1:iou_thr" 和 "my:thr@1:connection"。
70
+ f_p_name_builder=lambda idx, p_type: f'my{idx}' 时,
71
+ 这些参数在 trial 中注册的名称分别是 "my:thr@0:interval_thr","my:thr@1:iou_thr" 和 "my:thr@1:connection"。
60
72
  特别地,
61
73
  - 对于字典形式的 choices,其中保存在 trial 中的取值是其键 key 而非 value。
62
74
  - 对于list形式,但含有非支持类型的 choices,其中保存在 trial 中的取值是元素的 index。
63
75
  这些名称的含义详见 get_value()。
64
76
  """
77
+ if f_p_name_builder is None:
78
+ f_p_name_builder = lambda idx, p_type: idx
79
+ if not b_use_name_as_idx:
80
+ p_name_builder = lambda idx, p_type: f_p_name_builder(ndl.name_handler.parse_name(idx)[-1][-1], p_type)
81
+ else:
82
+ p_name_builder = f_p_name_builder
65
83
 
66
- name_ls=[]
84
+ node_vs_paras_s = dict()
85
+ p_name_set = set()
67
86
 
68
87
  def func(idx, v):
69
- nonlocal name_ls
88
+ nonlocal node_vs_paras_s, p_name_builder
89
+
70
90
  p_type = v.pop("p_type")
91
+ p_name = v.pop("p_name") if "p_name" in v else f'{p_name_builder(idx, p_type)}'
92
+ assert p_name not in p_name_set, \
93
+ f"p_name={p_name} is duplicated!"
94
+ p_name_set.add(p_name)
71
95
  kwargs = v
96
+ #
72
97
  choice_values = None
73
98
  if p_type == "categorical":
74
99
  # optuna 目前的类别元素仅支持 None, bool, int, float 和 str 类型
@@ -83,14 +108,15 @@ def sample_from_feasible_domain(var, trial: optuna.trial.BaseTrial, pre_name="")
83
108
  choice_values = kwargs["choices"]
84
109
  kwargs["choices"] = list(kwargs["choices"].keys())
85
110
 
86
- v = eval(f'trial.suggest_{p_type}(name=name, **kwargs)',
87
- {"trial": trial, "name": f'{pre_name}{idx}', "kwargs": kwargs})
111
+ v = eval(f'trial.suggest_{p_type}(name=name, **kwargs)', {"trial": trial, "name": p_name, "kwargs": kwargs})
88
112
  if choice_values is not None:
89
113
  v = choice_values[v]
90
- name_ls.append(idx)
114
+
115
+ #
116
+ node_vs_paras_s[idx] = p_name
91
117
  return v
92
118
 
93
119
  var = ndl.traverse(var=var, match_cond=lambda _, __, v: isinstance(v, (dict,)) and "p_type" in v,
94
120
  action_mode="replace", converter=func, b_use_name_as_idx=True)
95
121
 
96
- return var, name_ls
122
+ return var, node_vs_paras_s
@@ -1,3 +1,4 @@
1
1
  from .remove import remove
2
2
  from .pack import pack
3
3
  from .unpack import unpack
4
+ from .walk import walk, Path_Ignorer, Ignore_Scope
@@ -4,13 +4,15 @@ import shutil
4
4
 
5
5
  def remove(path, ignore_errors=False):
6
6
  """
7
- 移除文件/文件夹
7
+ 移除文件/文件夹/软连接
8
8
 
9
9
  返回:
10
10
  boolean 是否成功
11
11
  """
12
12
  try:
13
- if os.path.isfile(path): # 移除文件
13
+ if os.path.islink(path): # 移除软连接
14
+ os.unlink(path)
15
+ elif os.path.isfile(path): # 移除文件
14
16
  os.remove(path)
15
17
  elif os.path.isdir(path): # 移除文件夹
16
18
  shutil.rmtree(path=path, ignore_errors=False)
@@ -0,0 +1,167 @@
1
+ import os
2
+ from collections import defaultdict
3
+ from enum import Enum
4
+
5
+
6
+ class Ignore_Scope(Enum):
7
+ ROOT = "root"
8
+ DIRS = "dirs"
9
+ FILES = "files"
10
+
11
+
12
+ class Path_Ignorer:
13
+ def __init__(self, ignore_s=None):
14
+ self.ignore_s = defaultdict(list)
15
+ try:
16
+ if isinstance(ignore_s, (list, tuple)):
17
+ for it in ignore_s:
18
+ for scope in it["scope"]:
19
+ scope = Ignore_Scope(scope)
20
+ self.ignore_s[scope].append(it["func"])
21
+ elif isinstance(ignore_s, (dict,)):
22
+ for k, v in ignore_s.items():
23
+ self.ignore_s[Ignore_Scope(k)].extend(v)
24
+ except:
25
+ raise ValueError(f'invalid ignore_s, got a {ignore_s}')
26
+
27
+ def __call__(self, scope, *args, **kwargs):
28
+ for func in self.ignore_s[scope]:
29
+ if func(*args, **kwargs):
30
+ return True
31
+ return False
32
+
33
+ def __len__(self):
34
+ return len(self.ignore_s)
35
+
36
+
37
+ def walk(top, topdown=True, onerror=None, followlinks=False, ignore_s=None):
38
+ """
39
+ 在 os.walk() 的基础上增加了以下功能
40
+ - 可以通过 ignore_s 参数来排除特定的目录和文件
41
+
42
+ 参数:
43
+ (对于参数 top,topdown,onerror,followlinks,其用法与 os.walk() 完全相同)
44
+ top: <path> 要遍历的目录
45
+ topdown: <boolean> 是否从浅到深遍历
46
+ 默认为 True,优先遍历完浅层目录
47
+ onerror: <callable> 当遇到异常时,会调用该函数
48
+ followlinks: <boolean> 是否遍历软链接目录
49
+ 默认为 False,不对软链接进行进一步遍历
50
+ ignore_s: <list/tuple of dict or dict> 排除规则
51
+ 有两种输入方式:
52
+
53
+ 方式 1 <list/tuple of dict>:
54
+ 列表中每个字典需要具有以下键值对:
55
+ "scope": <list/tuple of str> 该规则的作用范围
56
+ 可选值,及(满足规则时)对应效果:
57
+ "root": 不遍历满足规则的目录
58
+ "dirs": 将返回的三元组中第二个 dirs 部分中满足规则的部分移除
59
+ "files": 将返回的三元组中第三个 files 部分中满足规则的部分移除
60
+ "func": <callable> 排除规则
61
+ 当调用该函数的返回值为 True 时,执行排除。
62
+ 函数类型为 def(b_is_dir, b_is_symlink, path): ...
63
+ 其中:
64
+ b_is_dir 是否是目录
65
+ b_is_symlink 是否是软链接
66
+ path 输入是对于作用范围 "root",输入的直接就是 root,
67
+ 对于作用范围 "dirs",输入是 dirs 中的每个元素和 root 组成的绝对路径,
68
+ 对于作用范围 "files",输入是 files 中的每个元素和 root 组成的绝对路径。
69
+ 注意:
70
+ - 当有多个规则时,只要满足其一即会进行排除。
71
+ - 任何规则都不会对 top 目录进行过滤,亦即对 top 的遍历是必然的。不能通过设定某个 top 满足的规则来停止对 top 的遍历。
72
+ 比如,通过下面的规则就可以实现不对 basename 为 "test" 和 "temp" 的目录进行遍历和输出,
73
+ 同时只保留非软连接的 .png 和 .jpg 文件:
74
+ [
75
+ {
76
+ "func": lambda _, __, path: os.path.basename(path) in ["temp", "test"],
77
+ "scope": ["root", "dirs"]
78
+ },
79
+ {
80
+ "func": lambda _, b_is_symlink, path: b_is_symlink or not path.endswith((".png",".jpg")),
81
+ "scope": ["files", ]
82
+ }
83
+ ]
84
+
85
+ 方式 2 <dict>:
86
+ 一个以 scope 为键,func 为值的字典。
87
+ 延续上面的例子,其另一种等效形式为:
88
+ {
89
+ "root": [
90
+ lambda _, __, path: os.path.basename(path) in ["temp", "test"],
91
+ ],
92
+ "dirs": [
93
+ lambda _, __, path: os.path.basename(path) in ["temp", "test"],
94
+ ],
95
+ "files": [
96
+ lambda _, b_is_symlink, path: b_is_symlink or not path.endswith((".png",".jpg")),
97
+ ]
98
+ }
99
+
100
+ 方式 3 <Path_Ignorer>:
101
+ 根据 ignore_s 构建的 Path_Ignorer
102
+
103
+ """
104
+ # 根据 ignore_s 构建 Path_Ignorer
105
+ path_ignorer = ignore_s if isinstance(ignore_s, (Path_Ignorer,)) else Path_Ignorer(ignore_s=ignore_s)
106
+
107
+ #
108
+ yield from __walk(top, topdown, onerror, followlinks, path_ignorer)
109
+
110
+
111
+ def __walk(top, topdown, onerror, followlinks, path_ignorer):
112
+ #
113
+ top = os.fspath(top)
114
+ dirs, files = [], []
115
+ walk_dirs = []
116
+
117
+ try:
118
+ scandir_it = os.scandir(top)
119
+ except OSError as error:
120
+ if onerror is not None:
121
+ onerror(error)
122
+ return
123
+
124
+ with scandir_it:
125
+ while True:
126
+ try:
127
+ try:
128
+ entry = next(scandir_it)
129
+ except StopIteration:
130
+ break
131
+ except OSError as error:
132
+ if onerror is not None:
133
+ onerror(error)
134
+ return
135
+
136
+ try:
137
+ is_dir = entry.is_dir()
138
+ except OSError:
139
+ is_dir = False
140
+
141
+ if is_dir:
142
+ dirs.append(entry.name)
143
+ walk_dirs.append(os.path.join(top, entry.name))
144
+ else:
145
+ files.append(entry.name)
146
+
147
+ # 过滤
148
+ if len(path_ignorer) > 0:
149
+ for it_ls, scope in zip([walk_dirs, dirs, files], [Ignore_Scope.ROOT, Ignore_Scope.DIRS, Ignore_Scope.FILES]):
150
+ for i in reversed(range(len(it_ls))):
151
+ path = os.path.join(top, it_ls[i]) if scope != Ignore_Scope.ROOT else it_ls[i]
152
+ if path_ignorer(scope, scope != Ignore_Scope.FILES, os.path.islink(path), path):
153
+ it_ls.pop(i)
154
+
155
+ #
156
+ if topdown:
157
+ yield top, dirs, files
158
+ #
159
+ for new_path in walk_dirs:
160
+ if followlinks or not os.path.islink(new_path):
161
+ yield from __walk(new_path, topdown, onerror, followlinks, path_ignorer)
162
+ else:
163
+ for new_path in walk_dirs:
164
+ if followlinks or not os.path.islink(new_path):
165
+ yield from __walk(new_path, topdown, onerror, followlinks, path_ignorer)
166
+ #
167
+ yield top, dirs, files
@@ -0,0 +1,73 @@
1
+ Metadata-Version: 2.1
2
+ Name: kevin-toolbox-dev
3
+ Version: 1.3.0
4
+ Summary: 一个常用的工具代码包集合
5
+ Home-page: https://github.com/cantbeblank96/kevin_toolbox
6
+ Download-URL: https://github.com/username/your-package/archive/refs/tags/v1.0.0.tar.gz
7
+ Author: kevin hsu
8
+ Author-email: xukaiming1996@163.com
9
+ License: MIT
10
+ Keywords: mathematics,pytorch,numpy,machine-learning,algorithm
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Programming Language :: Python :: 3
14
+ Requires-Python: >=3.6
15
+ Description-Content-Type: text/markdown
16
+ Requires-Dist: torch (>=1.2.0)
17
+ Requires-Dist: numpy (>=1.19.0)
18
+ Provides-Extra: plot
19
+ Requires-Dist: matplotlib (>=3.0) ; extra == 'plot'
20
+ Provides-Extra: rest
21
+ Requires-Dist: pytest (>=6.2.5) ; extra == 'rest'
22
+ Requires-Dist: line-profiler (>=3.5) ; extra == 'rest'
23
+
24
+ # kevin_toolbox
25
+
26
+ 一个通用的工具代码包集合
27
+
28
+
29
+
30
+ 环境要求
31
+
32
+ ```shell
33
+ numpy>=1.19
34
+ pytorch>=1.2
35
+ ```
36
+
37
+ 安装方法:
38
+
39
+ ```shell
40
+ pip install kevin-toolbox --no-dependencies
41
+ ```
42
+
43
+
44
+
45
+ [项目地址 Repo](https://github.com/cantbeblank96/kevin_toolbox)
46
+
47
+ [使用指南 User_Guide](./notes/User_Guide.md)
48
+
49
+ [免责声明 Disclaimer](./notes/Disclaimer.md)
50
+
51
+ [版本更新记录](./notes/Release_Record.md):
52
+
53
+ - v 1.3.0 (2023-12-13)【bug fix】【new feature】【incompatible change】
54
+ - nested_dict_list
55
+ - serializer
56
+ - 【bug fix】fix bug in read() and write(),解除这两个函数中出现的 nested_dict_list 和 kevin_toolbox.computer_science.algorithm.registration.Registry 模块之间的交叉引用。
57
+ - 【bug fix】fix bug in set_value(),对于使用method=@,但是node不为正整数的name进行强制写入的情况,未修复前表现为错误地尝试使用list进行构建并报错,现修复为使用 dict 进行构建。在新的策略下,对于强制写入,只有 method=@ 且 node 为非负正整数的情况下才会使用 list 进行构建,其他一律用 dict。
58
+ - 添加了对应的测试用例。
59
+ - patches.for_os
60
+ - 【new feature】add walk(),该方法在 os.walk() 的基础上增加了 ignore_s 参数,用于设定规则排除特定的目录和文件。相较于先使用 os.walk() 递归遍历这个目录,再对内容进行逐个过滤筛选的这种方式,本方法在遍历过程中就可以使用规则进行过滤并决定是否要继续深入遍历,更加高效。
61
+ - 补充了对应的测试用例。
62
+ - 【new feature】add Path_Ignorer,该类用于解释 ignore_s 参数,并进行基于规则的判断。
63
+ - 【new feature】modify remove(),支持对软连接的删除。
64
+ - computer_science.algorithm.registration
65
+ - 【new feature】【incompatible change】modify Registry.collect_from_paths(),将原有的通过目录前缀匹配来排除目录的 path_ls_to_exclude 参数,替换成通过规则匹配待排除目录的 ignore_s 参数,更加自由灵活。ignore_s 参数的设定方式与 for_os.walk() 中的 ignore_s 参数相同。
66
+ - 添加了对应的测试用例。
67
+ - patches.for_optuna
68
+ - 【new feature】【incompatible change】modify sample_from_feasible_domain(),进行了以下改变:
69
+ - 允许在 <feasible_domain> 中通过 "p_name" 字段来强制指定该参数在 trial 中的注册名称。
70
+ - 支持通过 f_p_name_builder 和 b_use_name_as_idx 决定如何从 <feasible_domain> 的位置生成参数的注册名称。
71
+ - 删去了 pre_name 参数,如果要实现原 pre_name 的效果,可以等效使用:
72
+ - `f_p_name_builder =lambda idx, p_type: f'{pre_name}{idx}'`
73
+ - 原来返回 var, node_name_ls 改为返回 var, node_vs_paras_s,其中 node_vs_paras_s 是一个`<dict>`,以被采样的节点在 var 中位置的名称作为键,以对应节点在 trial 中注册的参数名为值。
@@ -1,4 +1,4 @@
1
- kevin_toolbox/__init__.py,sha256=2_ntSVYDatiXtpDCOlmtORdDEtjh7diI0smSuFtn-34,410
1
+ kevin_toolbox/__init__.py,sha256=W_CLt--CjnjEw_hvNoQ6sNjhKqIx6otWbRWTAdprkh0,410
2
2
  kevin_toolbox/computer_science/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  kevin_toolbox/computer_science/algorithm/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
4
4
  kevin_toolbox/computer_science/algorithm/combinatorial_optimization/__init__.py,sha256=fBMX0_WiV8kfHLWZNfVe2uL67gsN_oHfpbuHaHUOiys,142
@@ -25,16 +25,19 @@ kevin_toolbox/computer_science/algorithm/parallel_and_concurrent/multi_thread_ex
25
25
  kevin_toolbox/computer_science/algorithm/pareto_front/__init__.py,sha256=LbeaSzG0hkx8NHAlzvEalrGi2WufaXguVfeBRzaw-MA,57
26
26
  kevin_toolbox/computer_science/algorithm/pareto_front/get_pareto_points_idx.py,sha256=a-8Js-dpkuVu9MsImW9hwHp9OTC278xo9oJP96oX0Io,2712
27
27
  kevin_toolbox/computer_science/algorithm/registration/__init__.py,sha256=teEd9HkrB6baLpwNwae5c4wn0QRwV3KtBv-2V9-Z7cc,49
28
- kevin_toolbox/computer_science/algorithm/registration/registry.py,sha256=_4s3u3hpg0jPmOv9UldzHe2Oa_XGQErjl9xTEwSCTwk,13842
28
+ kevin_toolbox/computer_science/algorithm/registration/registry.py,sha256=rAs7kG_f6P9AL264TuUin_8-jgYnQNo7EB8axgtCxkk,15383
29
29
  kevin_toolbox/computer_science/algorithm/scheduler/__init__.py,sha256=ENzZsNaMu6ISilTxeE3_EP_L0dNi8SI7IYdTdxic2nw,76
30
30
  kevin_toolbox/computer_science/algorithm/scheduler/strategy_manager.py,sha256=yLh2GBEsedJhqvB90zEmAOdZ8IF7nn1r9lSE95BbnEQ,12194
31
31
  kevin_toolbox/computer_science/algorithm/scheduler/trigger.py,sha256=YlqTX2TE44BwcQI0jfvcBCJhouhdAYuhwu2QJhuBWP0,4470
32
32
  kevin_toolbox/computer_science/algorithm/search/__init__.py,sha256=zja7FXLTNd2dSVzzGp1TbBp4i3TDY8S9tcJ9pqc684A,41
33
33
  kevin_toolbox/computer_science/algorithm/search/binary_search.py,sha256=FcOdgxfuNews_AhPF_CoQDr2vBPqpUpifF7Fmgml1p4,1013
34
- kevin_toolbox/computer_science/algorithm/statistician/__init__.py,sha256=zW1zesXYNjh6cAZPz_gsXd2LEEPlvA7SNB0huCb9WCg,120
35
- kevin_toolbox/computer_science/algorithm/statistician/_init_var.py,sha256=-u9RFiiPFlCLwdVfVZslYq9jNyDz4r_A9kRSH05sExw,904
36
- kevin_toolbox/computer_science/algorithm/statistician/average_accumulator.py,sha256=hdgpnMtvBQri-_ZxEAkSwyK6_qy4sJdqEeYauOBgLMI,3101
37
- kevin_toolbox/computer_science/algorithm/statistician/exponential_moving_average.py,sha256=P5E1EL1ioRAz_vlI-Ls9gZFhxVA83eTNjUppb2WqdlM,5571
34
+ kevin_toolbox/computer_science/algorithm/statistician/__init__.py,sha256=_ZAqOf9yUcGzn0ByVYhj9xZMdljzQj1mZNXGfHOFb4k,167
35
+ kevin_toolbox/computer_science/algorithm/statistician/accumulator_base.py,sha256=1JgznVWBLOn4dXkiMJphhyj6HPLFzXIe98jxc_rTzJg,6098
36
+ kevin_toolbox/computer_science/algorithm/statistician/average_accumulator.py,sha256=dxWg8B3APM7Y9qRtFLP2CNbmPivpSzln-VdSVh0xykA,2570
37
+ kevin_toolbox/computer_science/algorithm/statistician/exponential_moving_average.py,sha256=t5MxoCFVRz9qnRncdGQEIDKAKtMTqijv2n6gHaMLeRM,5363
38
+ kevin_toolbox/computer_science/algorithm/statistician/init_var/__init__.py,sha256=LrrLKilP-LqkNeLEqClZN4wMl9TvEaDktgbmw7CN1mY,121
39
+ kevin_toolbox/computer_science/algorithm/statistician/init_var/init_by_data_format.py,sha256=vCLguGS7het-gwPZ5uR2KDxnHV4gPaNbzJflocLbmLQ,769
40
+ kevin_toolbox/computer_science/algorithm/statistician/init_var/init_by_like.py,sha256=8QfvltiNDqZUYiNW6Ebt0UIuYvyqhSpsCYn99T2q70c,572
38
41
  kevin_toolbox/computer_science/algorithm/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
42
  kevin_toolbox/computer_science/data_structure/__init__.py,sha256=_esL73v9Gi40xb5N7UGxslIk8yHM6idQlXbzELR7XhA,31
40
43
  kevin_toolbox/computer_science/data_structure/executor.py,sha256=i-2zQj4lj597BvkarCMT-gYxhoRe8cHyQyO98X7m-9E,6206
@@ -50,7 +53,7 @@ kevin_toolbox/data_flow/core/reader/unified_reader.py,sha256=k1-I4rj5bjPix-_jni7
50
53
  kevin_toolbox/data_flow/core/reader/unified_reader_base.py,sha256=P7uqkjfHwc_KHUpAdOy-sCwCSM8lzF_8ZtDmg6FhiX0,11929
51
54
  kevin_toolbox/data_flow/file/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
52
55
  kevin_toolbox/data_flow/file/json_/__init__.py,sha256=VAt8COS2tO3PJRuhSc43i35fEOlArFM_YahdTmEBaHE,85
53
- kevin_toolbox/data_flow/file/json_/read_json.py,sha256=kjaf9tkROOLTJwICHRHmn_BID9Jyz7wXjR43IIpmtrs,1753
56
+ kevin_toolbox/data_flow/file/json_/read_json.py,sha256=XzygeWCxDeO95Q0Wl2Z8lXgfVUCdEyLMph4NpN-nh44,1784
54
57
  kevin_toolbox/data_flow/file/json_/write_json.py,sha256=F7wkolZkggAh6H8YExcVxmy-109BliYTtNYmr0JI_-E,2355
55
58
  kevin_toolbox/data_flow/file/json_/converter/__init__.py,sha256=jQoEaS57dl33O0XguHBEilkVmn0q-LiStKWSiqXZNLc,369
56
59
  kevin_toolbox/data_flow/file/json_/converter/convert_dict_key_to_number.py,sha256=SuSZj_HCqKZutHAJ5AttABnGBRZplPGQhMxJBt2Wlgc,559
@@ -75,7 +78,7 @@ kevin_toolbox/data_flow/file/kevin_notation/test/test_data/data_all.py,sha256=cv
75
78
  kevin_toolbox/data_flow/file/markdown/__init__.py,sha256=iTZTBvcEUehBdcWxzFQEW4iEcXbAQkdkEmENiGtBjqs,125
76
79
  kevin_toolbox/data_flow/file/markdown/generate_link.py,sha256=9okSyCFIDQW5T35a6-epVyoCkCL1vFH5215P5MRXfYk,304
77
80
  kevin_toolbox/data_flow/file/markdown/generate_list.py,sha256=Gv5BcqWE4M4w8ADN8NX5LyD9DxILXTQtJvcazi_NuyE,1006
78
- kevin_toolbox/data_flow/file/markdown/generate_table.py,sha256=dWtsKVu8wxVJVRLJ1jzeB-OjzAc9I_f_1DVKOHEZkRM,1236
81
+ kevin_toolbox/data_flow/file/markdown/generate_table.py,sha256=Xh9IRqLaeVoXDoFF1u6temMgf4MRng6pawJiUDknEdg,7209
79
82
  kevin_toolbox/developing/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
80
83
  kevin_toolbox/developing/general_matrix_multiplication.py,sha256=Ie9c8mYBYR-Bg7CjU4L1dsOxXsxnx1jz-rA7_ez7vjg,2089
81
84
  kevin_toolbox/developing/test.py,sha256=6Y23SY3FJVrvZmiiXKNPKv84lhVRW-XyjNeecj9lLYA,241
@@ -194,21 +197,22 @@ kevin_toolbox/math/utils/get_function_table_for_array_and_tensor.py,sha256=hZrXb
194
197
  kevin_toolbox/math/utils/set_crop_by_box.py,sha256=NzW7M26Av097RchLUAhaO84ETLV121uxsNot_U6otLw,1775
195
198
  kevin_toolbox/math/utils/spilt_integer_most_evenly.py,sha256=H0H7FixHsYtPVElIfVpuH7s7kaQ0JQI0r0Eu_HCvfwY,345
196
199
  kevin_toolbox/nested_dict_list/__init__.py,sha256=dYhc3G6DqaV-BfHY8JUfXLOIbYsWpR8mgbpgdv4emC4,296
197
- kevin_toolbox/nested_dict_list/copy_.py,sha256=GTO3D55DSlGONAChLHllWGPa2dxM52yzEcmN7xay2Ww,6161
200
+ kevin_toolbox/nested_dict_list/copy_.py,sha256=MvzNRKm8htYpMe7Td1ao2-ZoaYVC_iNTG7O2SBVrJKE,6144
198
201
  kevin_toolbox/nested_dict_list/count_leaf_node_nums.py,sha256=l67u47EvO1inoGinUqH6RZ7cHXwN0VcBQPUvSheqAvA,614
199
202
  kevin_toolbox/nested_dict_list/get_hash.py,sha256=Ygadnn5dnvIeE-9t39p2EwNKNRLzomL37ZsRD5daXxo,1286
200
203
  kevin_toolbox/nested_dict_list/get_nodes.py,sha256=MrWc08K_-hdaoaFRrUP_y2to3afUclf39BCfKnRCOGs,3457
201
204
  kevin_toolbox/nested_dict_list/get_value.py,sha256=isvUhqSQyUNHBXgNuZX6_o2c84UV_SpjNjAYm2M3gd4,2083
202
- kevin_toolbox/nested_dict_list/set_value.py,sha256=PaNQNsfz0_2evJmKHdF4saqIUPOYScAfC8wQJKwe3w4,3122
205
+ kevin_toolbox/nested_dict_list/set_value.py,sha256=pmSWzC0y0jBxk7yritsjKU2Q-PPMar0X3A9bF6uWvoQ,3470
203
206
  kevin_toolbox/nested_dict_list/traverse.py,sha256=5_EirnYVy34JLfXxuTvb-mMjDeO1veyfLOcaVYcuGF8,6846
204
207
  kevin_toolbox/nested_dict_list/name_handler/__init__.py,sha256=P_pWq78oN6NdvWg2h6AduW_sUqbeaaVyoWWbW9kbgmU,107
205
208
  kevin_toolbox/nested_dict_list/name_handler/build_name.py,sha256=Hj8Bz-90DBezfQgbzThR1-C206dqY13KmEguFECQWMY,1020
206
209
  kevin_toolbox/nested_dict_list/name_handler/escape_node.py,sha256=niT9MxmsyrSZYhKXlWzdoKXVYhWRCR-kmQBkZopznpA,1163
207
210
  kevin_toolbox/nested_dict_list/name_handler/parse_name.py,sha256=QpF8y7OuI4G6pS6sH_EXAV2TzJXYRu45bcIGJpVjiZc,2311
208
- kevin_toolbox/nested_dict_list/serializer/__init__.py,sha256=Fn38vJkHXdcvMc83VzCZBqVIyjFblmR7T5d49o7RvC0,48
209
- kevin_toolbox/nested_dict_list/serializer/read.py,sha256=2tT0yn3qq_cXxC5380el-RpY3ONM4QhZ0RrcHcmfcLk,2572
210
- kevin_toolbox/nested_dict_list/serializer/variable.py,sha256=K4xGehjnRoLbb5321-QXQkSH5UnPo9dExrVtPmt6xE4,1239
211
- kevin_toolbox/nested_dict_list/serializer/write.py,sha256=KdMq3QocIoGEKSQcG09GxPuieU4pvRGv0TeQk21mGtw,18115
211
+ kevin_toolbox/nested_dict_list/serializer/__init__.py,sha256=xLDfzSZIDNBssHArUEK84gF6WZFR64qJy0iOpM8LbP8,92
212
+ kevin_toolbox/nested_dict_list/serializer/enum_variable.py,sha256=RWPydtXI4adOJYGo_k5CWHSL0Odzj_bsahb24p1ranY,847
213
+ kevin_toolbox/nested_dict_list/serializer/read.py,sha256=8196AZW3y1eZNguw5fDi5gQmOtpJ0MdqhRNHZ5EWYHI,2577
214
+ kevin_toolbox/nested_dict_list/serializer/variable.py,sha256=ZywG6obipRBCGY1cY42gdvsuWk8GLZXr6eCYcW7ZJ9c,392
215
+ kevin_toolbox/nested_dict_list/serializer/write.py,sha256=sQtryi7NbVWynOMWpKKkqxoTf9dxSGE4yC4ReIAxT8U,18145
212
216
  kevin_toolbox/nested_dict_list/serializer/backends/__init__.py,sha256=8g7y-L3cmctxao616dVkGiot00FJzKNmNl_69V2bSmE,39
213
217
  kevin_toolbox/nested_dict_list/serializer/backends/_json_.py,sha256=oJXIc28yjxsD9ZJuw120pVHTVsTzCdaXEhVUSQeydq4,2145
214
218
  kevin_toolbox/nested_dict_list/serializer/backends/_ndl.py,sha256=QMF4DFAnt1sp35atds6t44nfCYuIOeGgW1-SPfJq6KM,1652
@@ -230,17 +234,18 @@ kevin_toolbox/patches/for_matplotlib/__init__.py,sha256=VNY4dGXSaB87HWek85xDRGOf
230
234
  kevin_toolbox/patches/for_matplotlib/add_trajectory_2d.py,sha256=mKXRUNJiEZBcff3pAkwL_gcKGn55CLRhYCTSd3fj1Go,1837
231
235
  kevin_toolbox/patches/for_matplotlib/add_trajectory_3d.py,sha256=VGlZfVY0xhUBOUzWJVPxZZNHHRvWLR0HZzhADA_cbsU,1696
232
236
  kevin_toolbox/patches/for_matplotlib/arrow3d.py,sha256=JSnNMr1hU2N4FUX526I4MDr04mksDgu4VuegYFDxk1Q,1361
233
- kevin_toolbox/patches/for_numpy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
237
+ kevin_toolbox/patches/for_numpy/__init__.py,sha256=SNjZGxTRBn-uzkyZi6Jcz-9juhhZKT8TI70qH-fhGGc,21
234
238
  kevin_toolbox/patches/for_numpy/linalg/__init__.py,sha256=qRoO08nCQJyodtdH8S-ZRhWZvW4qyVnWQL6Ok7iXpjY,99
235
239
  kevin_toolbox/patches/for_numpy/linalg/cos_similar.py,sha256=bFkfDwrW3maXq5i9ZABidKfg8ZdEdXfFgNzW_uygrM4,423
236
240
  kevin_toolbox/patches/for_numpy/linalg/normalize.py,sha256=7qstt__rwUkk3jRJOQoneBp9YdfhYQtWfh6PZoWbvaA,625
237
- kevin_toolbox/patches/for_numpy/linalg/softmax.py,sha256=Wdyvu7SwtQ7IUuhb_6YJijW3N99JKE6GumuhjZWJ5Rg,253
241
+ kevin_toolbox/patches/for_numpy/linalg/softmax.py,sha256=5ukhay9SvQoOch6czEXuJXqXg47Q1fokrv_zZTDHRjI,2035
238
242
  kevin_toolbox/patches/for_optuna/__init__.py,sha256=w7FuRlbX4rqVlpwOSAGQ2Y3ZhCglW81n2_4usHzIyJU,69
239
- kevin_toolbox/patches/for_optuna/sample_from_feasible_domain.py,sha256=zZcM7v1kAgEQGtN8oXVe0V2GiyGPUV16SujczF7ruxM,5325
240
- kevin_toolbox/patches/for_os/__init__.py,sha256=Gt9psQWmC5zt8DazalHnWk9IAy9CFdCRn9FV0m2dgu4,77
243
+ kevin_toolbox/patches/for_optuna/sample_from_feasible_domain.py,sha256=-Ckwo2N4vhWr08F7ROLfwLWIx4ERwdwn4Q5Ft2JRm7g,7071
244
+ kevin_toolbox/patches/for_os/__init__.py,sha256=Q6GzEPWggV4EovJdrertlL2l__W7k0zUEpuQIQDcA7A,128
241
245
  kevin_toolbox/patches/for_os/pack.py,sha256=A6u4g3dfwXPtlU4gBcThNrktz6dO4DVi2wmQXytqfDI,656
242
- kevin_toolbox/patches/for_os/remove.py,sha256=ji71D3BQA8g-xZr7IMRD9ANXfdsszS9QXDopAfVHfnw,658
246
+ kevin_toolbox/patches/for_os/remove.py,sha256=PmwqzVJbyfdqwXn_T1F9d4Oar8CwQ2YFaqcZQkfnrnI,750
243
247
  kevin_toolbox/patches/for_os/unpack.py,sha256=d_fO7nPmExy1VIg7ADIMayCzjBBeFxvJLhIsulIRlzI,1047
248
+ kevin_toolbox/patches/for_os/walk.py,sha256=LrtEeRUDwzZgu_zGZ-kPsFJd4D-8R8ECHW6WNdEsDSw,8376
244
249
  kevin_toolbox/patches/for_test/__init__.py,sha256=sFr2VZD1zk8Vtjq2_F8uE4xNovJF6yDY8j1YND5XAw0,49
245
250
  kevin_toolbox/patches/for_test/check_consistency.py,sha256=5zwjHc0M3A-RTYcgZpIugm6-L-m2pDSG496dCkg8Q4Q,5038
246
251
  kevin_toolbox/patches/for_torch/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -258,7 +263,7 @@ kevin_toolbox/patches/for_torch/math/get_y_at_x.py,sha256=bfoVcasZ_tMdhR_1Me0Jli
258
263
  kevin_toolbox/patches/for_torch/math/my_around.py,sha256=ptpU3ids50gwf663EpHbw7raj9tNrDGBFZ5t_uMNH14,1378
259
264
  kevin_toolbox/patches/for_torch/nn/__init__.py,sha256=aJs3RMqRzQmd8KKDmQW9FxwCqS5yfPqEdg-m0PwlQro,39
260
265
  kevin_toolbox/patches/for_torch/nn/lambda_layer.py,sha256=KUuLiX_Dr4bvRmpAaCW5QTDWDcnMPRnw0jg4NNXTFhM,223
261
- kevin_toolbox_dev-1.2.7.dist-info/METADATA,sha256=3Uz7Am_zWp3g0DfPQm1wJa55sikzRDML4VxCwIEVkjo,3104
262
- kevin_toolbox_dev-1.2.7.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
263
- kevin_toolbox_dev-1.2.7.dist-info/top_level.txt,sha256=S5TeRGF-PwlhsaUEPTI-f2vWrpLmh3axpyI6v-Fi75o,14
264
- kevin_toolbox_dev-1.2.7.dist-info/RECORD,,
266
+ kevin_toolbox_dev-1.3.0.dist-info/METADATA,sha256=Lv7LGBtCfRboHibUCT2EhwceSzrBneAbK7vwo5IJFss,3843
267
+ kevin_toolbox_dev-1.3.0.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
268
+ kevin_toolbox_dev-1.3.0.dist-info/top_level.txt,sha256=S5TeRGF-PwlhsaUEPTI-f2vWrpLmh3axpyI6v-Fi75o,14
269
+ kevin_toolbox_dev-1.3.0.dist-info/RECORD,,