kevin-toolbox-dev 1.3.4__py3-none-any.whl → 1.3.5__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 CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = "1.3.4"
1
+ __version__ = "1.3.5"
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 1727961379 --verbose 0'
15
+ f'--expiration_timestamp 1731518184 --verbose 0'
16
16
  )
@@ -1,15 +1,17 @@
1
1
  import os
2
2
  import json
3
+ from io import BytesIO, StringIO
3
4
  from kevin_toolbox.data_flow.file.json_.converter import integrate, unescape_tuple_and_set, unescape_non_str_dict_key
4
5
  from kevin_toolbox.nested_dict_list import traverse
5
6
 
6
7
 
7
- def read_json(file_path, converters=None, b_use_suggested_converter=False):
8
+ def read_json(file_path=None, file_obj=None, converters=None, b_use_suggested_converter=False):
8
9
  """
9
10
  读取 json file
10
11
 
11
12
  参数:
12
13
  file_path
14
+ file_obj
13
15
  converters: <list of converters> 对读取内容中每个节点的处理方式
14
16
  转换器 converter 应该是一个形如 def(x): ... ; return x 的函数,具体可以参考
15
17
  json_.converter 中已实现的转换器
@@ -19,13 +21,17 @@ def read_json(file_path, converters=None, b_use_suggested_converter=False):
19
21
  默认为 False。
20
22
  注意:当 converters 非 None,此参数失效,以 converters 中的具体设置为准
21
23
  """
22
- assert os.path.isfile(file_path), f'file {file_path} not found'
24
+ assert file_path is not None or file_obj is not None
25
+ if file_path is not None:
26
+ assert os.path.isfile(file_path), f'file {file_path} not found'
27
+ file_obj = open(file_path, 'r')
28
+ elif isinstance(file_obj, (BytesIO,)):
29
+ file_obj = StringIO(file_obj.read().decode('utf-8'))
30
+ content = json.load(file_obj)
31
+
23
32
  if converters is None and b_use_suggested_converter:
24
33
  converters = [unescape_tuple_and_set, unescape_non_str_dict_key]
25
34
 
26
- with open(file_path, 'r') as f:
27
- content = json.load(f)
28
-
29
35
  if converters is not None:
30
36
  converter = integrate(converters)
31
37
  content = traverse(var=[content],
@@ -5,7 +5,7 @@ import warnings
5
5
  from kevin_toolbox.data_flow.file.kevin_notation.converter import Converter, CONVERTER_FOR_WRITER
6
6
  from kevin_toolbox.data_flow.file import kevin_notation
7
7
 
8
- np.warnings.filterwarnings('ignore', category=np.VisibleDeprecationWarning)
8
+ warnings.filterwarnings('ignore', category=np.VisibleDeprecationWarning)
9
9
 
10
10
 
11
11
  class Kevin_Notation_Writer:
@@ -27,7 +27,10 @@ class NDL(Backend_Base):
27
27
  """
28
28
  是否可以写
29
29
  """
30
- return True
30
+ if "name" in kwargs:
31
+ return not os.path.exists(os.path.join(self.paras["folder"], f'{kwargs["name"]}'))
32
+ else:
33
+ return True
31
34
 
32
35
  def readable(self, name, **kwargs):
33
36
  """
@@ -3,6 +3,7 @@ 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
+ import tempfile
6
7
 
7
8
 
8
9
  def read(input_path, **kwargs):
@@ -16,19 +17,26 @@ def read(input_path, **kwargs):
16
17
 
17
18
  assert os.path.exists(input_path)
18
19
 
19
- # 解压
20
- temp_dir = None
21
- if os.path.isfile(input_path) and input_path.endswith(".tar"):
22
- while True:
23
- temp_dir = os.path.join(os.path.dirname(input_path), f'temp{time.time()}')
24
- if not os.path.isdir(temp_dir):
25
- os.makedirs(temp_dir)
26
- break
27
- for_os.unpack(source=input_path, target=temp_dir)
28
- input_path = os.path.join(temp_dir, os.listdir(temp_dir)[0])
20
+ with tempfile.TemporaryDirectory(dir=os.path.dirname(input_path)) as temp_dir:
21
+ if os.path.isfile(input_path) and input_path.endswith(".tar"): # 解压
22
+ for_os.unpack(source=input_path, target=temp_dir)
23
+ input_path = os.path.join(temp_dir, os.listdir(temp_dir)[0])
24
+ var = _read_unpacked_ndl(input_path, **kwargs)
25
+
26
+ return var
27
+
28
+
29
+ def _read_unpacked_ndl(input_path, **kwargs):
30
+ """
31
+ 读取 input_path 中保存的嵌套字典列表
32
+ """
33
+ from kevin_toolbox.nested_dict_list.serializer.variable import SERIALIZER_BACKEND
34
+
35
+ assert os.path.exists(input_path)
29
36
 
30
37
  # 读取 var
31
38
  var = json_.read(file_path=os.path.join(input_path, "var.json"), b_use_suggested_converter=True)
39
+
32
40
  # 读取 record
33
41
  record_s = dict()
34
42
  if os.path.isfile(os.path.join(input_path, "record.json")):
@@ -63,10 +71,6 @@ def read(input_path, **kwargs):
63
71
  from kevin_toolbox.nested_dict_list import value_parser
64
72
  var = value_parser.replace_identical_with_reference(var=var, flag="same", b_reverse=True)
65
73
 
66
- #
67
- if temp_dir is not None:
68
- for_os.remove(path=temp_dir, ignore_errors=True)
69
-
70
74
  return var
71
75
 
72
76
 
@@ -1,6 +1,7 @@
1
1
  import os
2
2
  import time
3
3
  import warnings
4
+ import tempfile
4
5
  import kevin_toolbox
5
6
  from kevin_toolbox.data_flow.file import json_
6
7
  from kevin_toolbox.patches import for_os
@@ -111,7 +112,13 @@ def write(var, output_dir, settings=None, traversal_mode=Traversal_Mode.BFS, b_p
111
112
  # 检查参数
112
113
  traversal_mode = Traversal_Mode(traversal_mode)
113
114
  strictness_level = Strictness_Level(strictness_level)
114
- os.makedirs(output_dir, exist_ok=True)
115
+ #
116
+ assert not os.path.exists(output_dir + ".tar" if b_pack_into_tar else output_dir), f'target already exists'
117
+ os.makedirs(os.path.dirname(output_dir), exist_ok=True)
118
+ temp_dir = tempfile.TemporaryDirectory(dir=os.path.dirname(output_dir))
119
+ temp_output_dir = os.path.join(temp_dir.name, os.path.basename(output_dir))
120
+ os.makedirs(temp_output_dir, exist_ok=True)
121
+ #
115
122
  var = ndl.copy_(var=var, b_deepcopy=False)
116
123
  if b_keep_identical_relations:
117
124
  from kevin_toolbox.nested_dict_list import value_parser
@@ -144,7 +151,7 @@ def write(var, output_dir, settings=None, traversal_mode=Traversal_Mode.BFS, b_p
144
151
  backend_name_ls = setting["backend"] if isinstance(setting["backend"], (list, tuple)) else [setting["backend"]]
145
152
  for i in backend_name_ls:
146
153
  if i not in backend_s:
147
- backend_s[i] = SERIALIZER_BACKEND.get(name=i)(folder=os.path.join(output_dir, "nodes"))
154
+ backend_s[i] = SERIALIZER_BACKEND.get(name=i)(folder=os.path.join(temp_output_dir, "nodes"))
148
155
  #
149
156
  t_mode = Traversal_Mode(setting.get("traversal_mode", traversal_mode))
150
157
  # _process and paras
@@ -189,17 +196,19 @@ def write(var, output_dir, settings=None, traversal_mode=Traversal_Mode.BFS, b_p
189
196
  f'please check settings to make sure all nodes have been covered and can be deal with backend'
190
197
 
191
198
  # 保存 var 的结构
192
- json_.write(content=var, file_path=os.path.join(output_dir, "var.json"), b_use_suggested_converter=True)
199
+ json_.write(content=var, file_path=os.path.join(temp_output_dir, "var.json"), b_use_suggested_converter=True)
193
200
  # 保存处理结果(非必要)
194
201
  json_.write(content=dict(processed=processed_s, raw_structure=processed_s_bak, timestamp=time.time(),
195
202
  kt_version=kevin_toolbox.__version__,
196
203
  b_keep_identical_relations=b_keep_identical_relations),
197
- file_path=os.path.join(output_dir, "record.json"), b_use_suggested_converter=True)
204
+ file_path=os.path.join(temp_output_dir, "record.json"), b_use_suggested_converter=True)
198
205
 
199
206
  # 打包成 .tar 文件
200
207
  if b_pack_into_tar:
201
- for_os.pack(source=output_dir)
202
- for_os.remove(path=output_dir, ignore_errors=True)
208
+ for_os.pack(source=temp_output_dir)
209
+ os.rename(temp_output_dir + ".tar", output_dir + ".tar")
210
+ else:
211
+ os.rename(temp_output_dir, output_dir)
203
212
 
204
213
 
205
214
  def _judge_processed_or_not(processed_s, name):
@@ -1,4 +1,5 @@
1
1
  from .remove import remove
2
+ from .copy import copy
2
3
  from .pack import pack
3
4
  from .unpack import unpack
4
5
  from .walk import walk, Path_Ignorer, Ignore_Scope
@@ -0,0 +1,33 @@
1
+ import os
2
+ import shutil
3
+ from kevin_toolbox.patches.for_os import remove
4
+
5
+
6
+ def copy(src, dst, follow_symlinks=True, remove_dst_if_exists=False):
7
+ """
8
+ 复制文件/文件夹/软连接
9
+
10
+ 参数:
11
+ follow_symlinks: <boolean> 是否跟随符号链接
12
+ 对于 src 是软连接或者 src 指向的目录下具有软连接的情况,
13
+ 当设置为 True 时,会复制所有链接指向的实际文件或目录内容。
14
+ 当设置为 False 时,则仅仅软连接本身,而不是指向的内容
15
+ 默认为 True
16
+ remove_dst_if_exists: <boolean> 当目标存在时,是否尝试进行移除
17
+ """
18
+ assert os.path.exists(src), f'failed to copy, src not exists: {src}'
19
+ if remove_dst_if_exists:
20
+ remove(path=dst, ignore_errors=True)
21
+ assert not os.path.exists(dst), f'failed to copy, dst exists: {dst}'
22
+
23
+ os.makedirs(os.path.dirname(dst), exist_ok=True)
24
+ if os.path.isdir(src):
25
+ if not follow_symlinks and os.path.islink(src):
26
+ # 如果是符号链接,并且我们跟随符号链接,则复制链接本身
27
+ os.symlink(os.readlink(src), dst)
28
+ else:
29
+ # 否则,递归复制目录
30
+ shutil.copytree(src, dst, symlinks=not follow_symlinks)
31
+ else:
32
+ # 复制文件
33
+ shutil.copy2(src, dst, follow_symlinks=follow_symlinks)
@@ -7,7 +7,8 @@ import kevin_toolbox.nested_dict_list as ndl
7
7
  def check_consistency(*args, tolerance=1e-7, require_same_shape=True):
8
8
  """
9
9
  检查 args 中多个变量之间是否一致
10
- 变量支持python的所有内置类型,以及复杂的 nested_dict_list 结构, array 等
10
+ 变量支持 python 的所有内置类型,以及复杂的 nested_dict_list 结构, array 等
11
+ 对于 array,不区分 numpy 的 array,torch 的 tensor,还是 tuple of number,只要其中的值相等,即视为相同。
11
12
 
12
13
  参数:
13
14
  tolerance: <float> 判断 <np.number/np.bool_> 之间是否一致时,的容许误差。
@@ -28,13 +29,13 @@ def check_consistency(*args, tolerance=1e-7, require_same_shape=True):
28
29
  try:
29
30
  _check_item(*names_ls, tolerance=tolerance, require_same_shape=True)
30
31
  except AssertionError as e:
31
- assert False, f'inputs <nested_dict_list> has different structure\nthe nodes that differ are:\n{e}'
32
+ raise AssertionError(f'inputs <nested_dict_list> has different structure\nthe nodes that differ are:\n{e}')
32
33
  for its in zip(names_ls[0], *values_ls):
33
34
  try:
34
35
  _check_item(*its[1:], tolerance=tolerance, require_same_shape=require_same_shape)
35
36
  except AssertionError as e:
36
- assert False, \
37
- f'value of nodes {its[0]} in inputs <nested_dict_list> are inconsistent\nthe difference is:\n{e}'
37
+ raise AssertionError(
38
+ f'value of nodes {its[0]} in inputs <nested_dict_list> are inconsistent\nthe difference is:\n{e}')
38
39
  # 简单结构
39
40
  else:
40
41
  _check_item(*args, tolerance=tolerance, require_same_shape=require_same_shape)
@@ -45,44 +46,111 @@ def _check_item(*args, tolerance, require_same_shape):
45
46
  检查 args 中多个 array 之间是否一致
46
47
 
47
48
  工作流程:
48
- 本函数会首先将输入的 args 中的所有变量转换为 np.array;
49
- 然后使用 issubclass() 判断转换后得到的变量属于以下哪几种基本类型:
50
- - 当所有变量都属于 np.number 数值(包含int、float等)或者 np.bool_ 布尔值时,
51
- 将对变量两两求差,当差值小于给定的容许误差 tolerance 时,视为一致。
52
- - 当所有变量都属于 np.flexible 可变长度类型(包含string等)或者 np.object 时,
53
- 将使用==进行比较,当返回值都为 True 时,视为一致。
54
- - 当变量的基本类型不一致(比如同时有np.number和np.flexible)时,
55
- 直接判断为不一致。
56
- numpy 中基本类型之间的继承关系参见: https://numpy.org.cn/reference/arrays/scalars.html
49
+ 1. 对于 args 都是 tuple/list 且每个 tuple/list 的长度都一致的情况,将会拆分为对应各个元素递归进行比较。
50
+ 2. args 中的 tuple 和 tensor 分别转换为 list 和 numpy。
51
+ 3. 检查 args 中是否有 np.array 或者 tensor,若有则根据 require_same_shape 判断其形状是否一致。
52
+ 4. 先将输入的 args 中的所有变量转换为 np.array;
53
+ 然后使用 issubclass() 判断转换后得到的变量属于以下哪几种基本类型:
54
+ - 当所有变量都属于 np.number 数值(包含int、float等)或者 np.bool_ 布尔值时,
55
+ 将对变量两两求差,当差值小于给定的容许误差 tolerance 时,视为一致。
56
+ 注意:在比较过程中,若变量中存在 np.nan 值,将会首先比较有 np.nan 值的位置是否相等,然后再比较非 np.nan 值部分。
57
+ 亦即在相同位置上都具有 np.nan 视为相同。
58
+ 比如 [np.nan, np.nan, 3] 和 [np.nan, np.nan, 3] 会视为相等,
59
+ [np.nan, np.nan] 和 np.nan 在 require_same_shape=False 时会被视为相等。
60
+ - 当所有变量都属于 np.flexible 可变长度类型(包含string等)或者 np.object 时,
61
+ 将使用==进行比较,当返回值都为 True 时,视为一致。
62
+ - 当变量的基本类型不一致(比如同时有np.number和np.flexible)时,
63
+ 直接判断为不一致。
64
+ numpy 中基本类型之间的继承关系参见: https://numpy.org.cn/reference/arrays/scalars.html
57
65
 
58
66
  参数:
59
67
  tolerance: <float> 判断 <np.number/np.bool_> 之间是否一致时,的容许误差。
60
68
  require_same_shape: <boolean> 是否强制要求变量的形状一致。
61
- 当设置为 False 时,不同形状的变量可能因为 numpy broadcast 机制而在比较前自动 reshape 为相同维度,进而可能通过比较。
69
+ 注意:仅在原始 args 中含有 np.array 或者 tensor 的情况会采取 broadcast,亦即此时该参数才会起效。
70
+ 当设置为 False 时,不同形状的变量可能因为 broadcast 机制而在比较前自动 reshape 为相同维度,进而通过比较。
62
71
  """
63
- np.warnings.filterwarnings('ignore', category=np.VisibleDeprecationWarning)
72
+ warnings.filterwarnings('ignore', category=np.VisibleDeprecationWarning)
64
73
  warnings.filterwarnings("ignore", category=DeprecationWarning)
65
74
 
66
75
  assert len(args) >= 2
67
- assert isinstance(tolerance, (int, float,))
76
+ assert isinstance(tolerance, (int, float,)) and tolerance >= 0
77
+ raw_args = args
78
+
79
+ # 当 args 都是 tuple/list 且每个 tuple 的长度都一致时,将会拆分为对应各个元素进行比较
80
+ if all([isinstance(i, (tuple, list)) for i in args]) and all([len(i) == len(args[0]) for i in args[1:]]):
81
+ for i, it_ls in enumerate(zip(*args)):
82
+ try:
83
+ _check_item(*it_ls, tolerance=tolerance, require_same_shape=require_same_shape)
84
+ except AssertionError as e:
85
+ raise AssertionError(f'elements {i} are inconsistent\nthe difference is:\n{e}')
86
+ return
87
+
88
+ #
89
+ args = ndl.traverse(var=list(args), match_cond=lambda _, __, v: isinstance(v, (tuple,)), action_mode="replace",
90
+ converter=lambda _, v: list(v), b_traverse_matched_element=True)
91
+ args = ndl.traverse(var=list(args), match_cond=lambda _, __, v: torch.is_tensor(v), action_mode="replace",
92
+ converter=lambda _, v: v.detach().cpu().numpy(), b_traverse_matched_element=False)
93
+ b_has_raw_array = any([isinstance(i, np.ndarray) for i in args])
68
94
 
69
- args = [v.detach().cpu() if torch.is_tensor(v) else v for v in args]
70
- args = [np.asarray(v) for v in args]
95
+ try:
96
+ args = [np.asarray(v) for v in args] # if b_has_raw_array else [np.array(v, dtype=object) for v in args]
97
+ except Exception as e:
98
+ raise RuntimeError(f'{raw_args} cannot be converted to np.array, \n'
99
+ f'because {e}')
71
100
 
72
- for v in args[1:]:
101
+ # 比较形状
102
+ if b_has_raw_array:
73
103
  if require_same_shape:
74
- assert args[0].shape == v.shape, \
75
- f"{args[0]}, {v}, different shape: {args[0].shape}, {v.shape}"
76
- if issubclass(args[0].dtype.type, (np.number, np.bool_,)):
77
- # 数字类型
104
+ # 要求形状一致
105
+ for v in args[1:]:
106
+ assert args[0].shape == v.shape, \
107
+ f"{args[0]}, {v}, different shape: {args[0].shape}, {v.shape}"
108
+ else:
109
+ # 否则要求至少能够进行 broadcast
110
+ for v in args[1:]:
111
+ try:
112
+ np.broadcast_arrays(args[0], v)
113
+ except:
114
+ raise AssertionError(f'{args[0]}, {v}, failed to broadcast')
115
+ # 如果都是空的 array,直接视为相等
116
+ if all([i.size == 0 for i in args]):
117
+ return
118
+ b_allow_broadcast = b_has_raw_array and not require_same_shape
119
+
120
+ # 比较值
121
+ if issubclass(args[0].dtype.type, (np.number, np.bool_,)):
122
+ # 数字类型
123
+ for v in args[1:]:
78
124
  assert issubclass(v.dtype.type, (np.number, np.bool_,))
79
- if args[0].size > 0:
80
- assert np.max(np.abs(args[0] - v.astype(dtype=float))) < tolerance, \
81
- f"{args[0]}, {v}, deviation: {np.max(np.abs(args[0] - v))}"
82
- elif issubclass(args[0].dtype.type, (np.flexible, object,)):
83
- # 可变长度类型
125
+ v_0, v_1 = args[0].astype(dtype=float), v.astype(dtype=float)
126
+ v_0, v_1 = np.broadcast_arrays(v_0, v_1) if b_allow_broadcast else (v_0, v_1)
127
+ assert v_0.shape == v_1.shape, \
128
+ f'{v_0}, {v_1}, different shape: {v_0.shape}, {v_1.shape}'
129
+ #
130
+ if v_0.size > 0:
131
+ try:
132
+ if np.any(np.isnan(v)):
133
+ assert np.all(np.isnan(v_0) == np.isnan(v_1))
134
+ v_0 = np.nan_to_num(v_0, nan=1e10)
135
+ v_1 = np.nan_to_num(v_1, nan=1e10)
136
+ assert np.max(np.abs(v_0 - v_1)) < tolerance
137
+ except AssertionError:
138
+ raise AssertionError(f"{args[0]}, {v}, deviation: {np.max(np.abs(args[0] - v))}")
139
+ elif issubclass(args[0].dtype.type, (np.flexible, object,)):
140
+ # 可变长度类型
141
+ for v in args[1:]:
84
142
  assert issubclass(v.dtype.type, (np.flexible, object,))
85
- for i, j in zip(args[0].reshape(-1), v.reshape(-1)):
143
+ v_0, v_1 = np.broadcast_arrays(args[0], v) if b_allow_broadcast else (args[0], v)
144
+ assert v_0.shape == v_1.shape, \
145
+ f'{v_0}, {v_1}, different shape: {v_0.shape}, {v_1.shape}\n' + (
146
+ '' if require_same_shape else
147
+ f'\tMore details: \n'
148
+ f'\t\tAlthough require_same_shape=False has been setted, broadcast failed because the variable at \n'
149
+ f'\t\tthis position does not contain elements of type np.array and tensor.')
150
+ #
151
+ for i, j in zip(v_0.reshape(-1), v_1.reshape(-1)):
152
+ if i is j:
153
+ continue
86
154
  temp = i == j
87
155
  if isinstance(temp, (bool,)):
88
156
  assert temp, \
@@ -90,14 +158,17 @@ def _check_item(*args, tolerance, require_same_shape):
90
158
  else:
91
159
  assert temp.all(), \
92
160
  f"{args[0]}, {v}, diff: {temp}"
93
- else:
94
- raise ValueError
161
+ else:
162
+ raise ValueError
95
163
 
96
164
 
97
165
  if __name__ == '__main__':
98
166
  a = np.array([[1, 2, 3]])
99
167
  b = np.array([[1, 2, 3]])
100
168
  c = {'d': 3, 'c': 4}
101
- check_consistency([c, a], [c, b])
102
169
 
103
- check_consistency(True, True)
170
+ # var = ((1, 2), (4))
171
+ #
172
+ # var = ndl.traverse(var=[var], match_cond=lambda _, __, v: isinstance(v, (tuple,)), action_mode="replace",
173
+ # converter=lambda _, v: list(v), b_traverse_matched_element=True)[0]
174
+ # print(var)
@@ -0,0 +1,74 @@
1
+ Metadata-Version: 2.1
2
+ Name: kevin-toolbox-dev
3
+ Version: 1.3.5
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
+ Platform: UNKNOWN
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python
14
+ Classifier: Programming Language :: Python :: 3
15
+ Requires-Python: >=3.6
16
+ Description-Content-Type: text/markdown
17
+ Requires-Dist: torch (>=1.2.0)
18
+ Requires-Dist: numpy (>=1.19.0)
19
+ Provides-Extra: plot
20
+ Requires-Dist: matplotlib (>=3.0) ; extra == 'plot'
21
+ Provides-Extra: rest
22
+ Requires-Dist: pytest (>=6.2.5) ; extra == 'rest'
23
+ Requires-Dist: line-profiler (>=3.5) ; extra == 'rest'
24
+
25
+ # kevin_toolbox
26
+
27
+ 一个通用的工具代码包集合
28
+
29
+
30
+
31
+ 环境要求
32
+
33
+ ```shell
34
+ numpy>=1.19
35
+ pytorch>=1.2
36
+ ```
37
+
38
+ 安装方法:
39
+
40
+ ```shell
41
+ pip install kevin-toolbox --no-dependencies
42
+ ```
43
+
44
+
45
+
46
+ [项目地址 Repo](https://github.com/cantbeblank96/kevin_toolbox)
47
+
48
+ [使用指南 User_Guide](./notes/User_Guide.md)
49
+
50
+ [免责声明 Disclaimer](./notes/Disclaimer.md)
51
+
52
+ [版本更新记录](./notes/Release_Record.md):
53
+
54
+ - v 1.3.5 (2024-05-18)【bug fix】【new feature】
55
+ - patches
56
+ - for_os
57
+ - 【new feature】add copy(),无论是文件/目录/软连接都可以使用该函数进行复制。
58
+ - 同时支持follow_symlinks参数用于决定是否跟随符号链接复制其指向的内容,支持remove_dst_if_exists用于决定当目标存在时是否尝试进行移除。
59
+ - for_test
60
+ - 【bug fix】fix bug in check_consistency(),解决了以下问题:
61
+ - 对于含有 np.nan 值的array错误地一律都判断为不相等,修改后将相同位置的 np.nan 值视为相等。
62
+ - require_same_shape=False 时无法正常为不对齐的 可变长度类型 报错。
63
+ - 对于包含 requires_grad=True 的 tensor 的复杂 tuple 异常报错。
64
+ - 添加了对应的测试用例。
65
+ - nested_dict_list
66
+ - 【bug fix】modify temporary file management in write() and read(),加强对写入和读取时创建的临时文件的管理,保证异常退出时能够自动清理临时文件夹。
67
+ - data_flow.file
68
+ - json_
69
+ - 【new feature】modify read(),新增了 file_obj 参数,支持直接从 BytesIO 和 StringIO 中读取json文件。
70
+ - 添加了对应的测试用例。
71
+ - 在更高版本的numpy中已经没有 np.warnings 了,因此将所有 np.warnings 替换为 warnings。
72
+
73
+
74
+
@@ -1,4 +1,4 @@
1
- kevin_toolbox/__init__.py,sha256=ryG5DAc-XozLnxNQjuTKTRynJFnwdQHKBZ2vaN1upx4,410
1
+ kevin_toolbox/__init__.py,sha256=JzwJXkcT4vV0qixg5n7pd24pB0WTgH5FVJcfB3f6ZCQ,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/cache_manager/__init__.py,sha256=p2hddkZ1HfYF9-m2Hx-o9IotwQHd4QwDCePy2ADpTDA,41
@@ -71,7 +71,7 @@ kevin_toolbox/data_flow/core/reader/unified_reader.py,sha256=l6JxPoDUOdx2ZIPX2WL
71
71
  kevin_toolbox/data_flow/core/reader/unified_reader_base.py,sha256=4gIADdV8UKpt2yD8dZjQsXFcF75nJ83ooIae3D7bw2s,11783
72
72
  kevin_toolbox/data_flow/file/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
73
73
  kevin_toolbox/data_flow/file/json_/__init__.py,sha256=VAt8COS2tO3PJRuhSc43i35fEOlArFM_YahdTmEBaHE,85
74
- kevin_toolbox/data_flow/file/json_/read_json.py,sha256=S-rlY-spIAJVyB-zPQOmKUDdtNAgedSmXHjkY_TNGUE,1808
74
+ kevin_toolbox/data_flow/file/json_/read_json.py,sha256=BhAUCcagwPsSMaMeCJyyxDW3h9SGf1Dfvb0nXi6B_T8,2084
75
75
  kevin_toolbox/data_flow/file/json_/write_json.py,sha256=mWaxePr_QzfyeCb0hAy4xTKOGX7q0eFjep0jDqOqIgw,2379
76
76
  kevin_toolbox/data_flow/file/json_/converter/__init__.py,sha256=oQMgAgzELLq_f4LIIfz5E6l_E7g4lFsXqfmnJ3tPZTY,401
77
77
  kevin_toolbox/data_flow/file/json_/converter/convert_dict_key_to_number.py,sha256=SuSZj_HCqKZutHAJ5AttABnGBRZplPGQhMxJBt2Wlgc,559
@@ -84,7 +84,7 @@ kevin_toolbox/data_flow/file/json_/converter/unescape_tuple_and_set.py,sha256=3v
84
84
  kevin_toolbox/data_flow/file/kevin_notation/__init__.py,sha256=g9UUF9nJrOMc0ndCwVROQLsux4Or2yVMJMdhK5P9nRc,259
85
85
  kevin_toolbox/data_flow/file/kevin_notation/converter.py,sha256=5k_Yxw-fBKEkxFG0bnl1fRsz06MlUS-4f3gZ--bmDs8,3621
86
86
  kevin_toolbox/data_flow/file/kevin_notation/kevin_notation_reader.py,sha256=iN6nV8mMbifTbECNmjc-G2pzpxivhks5kCXGVdvS9fQ,8297
87
- kevin_toolbox/data_flow/file/kevin_notation/kevin_notation_writer.py,sha256=dyzkufi_SM-uU7cyI3yLFd8U4GnyRR5pyS88op6mhRY,16331
87
+ kevin_toolbox/data_flow/file/kevin_notation/kevin_notation_writer.py,sha256=Py8kyyi9RgxCSpuGebNkaxc9g4S8TdtiNJNDrJyP2UA,16328
88
88
  kevin_toolbox/data_flow/file/kevin_notation/read.py,sha256=w0RE0WwTmWycEozJVshAiE0gMBxproBRwBEMLS6tB6c,544
89
89
  kevin_toolbox/data_flow/file/kevin_notation/write.py,sha256=gPabz_h2mtXqCTyBVzip_QSb6L4tsrNSqibFzuqsIv8,556
90
90
  kevin_toolbox/data_flow/file/kevin_notation/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -229,13 +229,13 @@ kevin_toolbox/nested_dict_list/name_handler/escape_node.py,sha256=niT9MxmsyrSZYh
229
229
  kevin_toolbox/nested_dict_list/name_handler/parse_name.py,sha256=vUlAXPocpVSxtb3EnRi7U5K40Tz9plFG-_sbwLfYiy4,2280
230
230
  kevin_toolbox/nested_dict_list/serializer/__init__.py,sha256=79dd9l-mNz0bycFKjNm7YsfWPR-JsVx9NoG_Ofqy-HQ,153
231
231
  kevin_toolbox/nested_dict_list/serializer/enum_variable.py,sha256=RWPydtXI4adOJYGo_k5CWHSL0Odzj_bsahb24p1ranY,847
232
- kevin_toolbox/nested_dict_list/serializer/read.py,sha256=yessvu7msmP2kV3ZhOTVmI2ENI-R1-TdhVgZdS8eWDk,2843
232
+ kevin_toolbox/nested_dict_list/serializer/read.py,sha256=Ms86R8jRvuvbIWiyL8WUYXvU9APRXe72w9q_YcOKUWM,2944
233
233
  kevin_toolbox/nested_dict_list/serializer/saved_node_name_builder.py,sha256=qsD-rmDmVaKZP4owN3Wm3QY2Ksi71XlYETqw4VmIsSU,1011
234
234
  kevin_toolbox/nested_dict_list/serializer/variable.py,sha256=ZywG6obipRBCGY1cY42gdvsuWk8GLZXr6eCYcW7ZJ9c,392
235
- kevin_toolbox/nested_dict_list/serializer/write.py,sha256=kP_sM-NtI3vJT7KwBZsz_ReZprfVefzUFplW7Kh0zVQ,21024
235
+ kevin_toolbox/nested_dict_list/serializer/write.py,sha256=VMwD579NBl0QZeHh9P4WuFzA3CdtuRaqLLu5S5NGt5E,21468
236
236
  kevin_toolbox/nested_dict_list/serializer/backends/__init__.py,sha256=8g7y-L3cmctxao616dVkGiot00FJzKNmNl_69V2bSmE,39
237
237
  kevin_toolbox/nested_dict_list/serializer/backends/_json_.py,sha256=oJXIc28yjxsD9ZJuw120pVHTVsTzCdaXEhVUSQeydq4,2145
238
- kevin_toolbox/nested_dict_list/serializer/backends/_ndl.py,sha256=QMF4DFAnt1sp35atds6t44nfCYuIOeGgW1-SPfJq6KM,1652
238
+ kevin_toolbox/nested_dict_list/serializer/backends/_ndl.py,sha256=3YkAq_Bqzehnw0kGxqxwtF6uUz0EV37tLI-1ROHjixY,1794
239
239
  kevin_toolbox/nested_dict_list/serializer/backends/_numpy_bin.py,sha256=xiPFmPUTjy0X0R1E0N8mrByENhNb69QalHnbYQXFvTo,1470
240
240
  kevin_toolbox/nested_dict_list/serializer/backends/_numpy_npy.py,sha256=CF6R7ie68zA0TqAXBdxUgHKVDYtEPHfVXR9rMFBbsdw,1384
241
241
  kevin_toolbox/nested_dict_list/serializer/backends/_pickle_.py,sha256=yCe4BXwSU55fbBX-HbTWI5ReT9Hhd7knu5zqvgUw5t4,1282
@@ -282,13 +282,14 @@ kevin_toolbox/patches/for_optuna/serialize/for_study/load.py,sha256=DwnDheJx5IJp
282
282
  kevin_toolbox/patches/for_optuna/serialize/for_trial/__init__.py,sha256=YSROCv89O84gzzRP2NfVl0Xhd4_RsdoqU3Nnr-vhWhk,46
283
283
  kevin_toolbox/patches/for_optuna/serialize/for_trial/dump.py,sha256=FT-Z1rzCNUYz5St1Yc0bfDWAV10WaV41rlbWIS72Jp0,982
284
284
  kevin_toolbox/patches/for_optuna/serialize/for_trial/load.py,sha256=2fpeeHPKA9bT7CjQ6DVRXOarF6IAA6_f2pXbB1rXcvE,796
285
- kevin_toolbox/patches/for_os/__init__.py,sha256=Q6GzEPWggV4EovJdrertlL2l__W7k0zUEpuQIQDcA7A,128
285
+ kevin_toolbox/patches/for_os/__init__.py,sha256=jx4UCTxEW2QhLfgfPhxcgUrftvs_2420IAQJso82DeQ,151
286
+ kevin_toolbox/patches/for_os/copy.py,sha256=PWFLu15DpIA4JZxatvphHANNn2H3nC93qTbLLxDl5NU,1509
286
287
  kevin_toolbox/patches/for_os/pack.py,sha256=A6u4g3dfwXPtlU4gBcThNrktz6dO4DVi2wmQXytqfDI,656
287
288
  kevin_toolbox/patches/for_os/remove.py,sha256=PmwqzVJbyfdqwXn_T1F9d4Oar8CwQ2YFaqcZQkfnrnI,750
288
289
  kevin_toolbox/patches/for_os/unpack.py,sha256=d_fO7nPmExy1VIg7ADIMayCzjBBeFxvJLhIsulIRlzI,1047
289
290
  kevin_toolbox/patches/for_os/walk.py,sha256=LrtEeRUDwzZgu_zGZ-kPsFJd4D-8R8ECHW6WNdEsDSw,8376
290
291
  kevin_toolbox/patches/for_test/__init__.py,sha256=sFr2VZD1zk8Vtjq2_F8uE4xNovJF6yDY8j1YND5XAw0,49
291
- kevin_toolbox/patches/for_test/check_consistency.py,sha256=5zwjHc0M3A-RTYcgZpIugm6-L-m2pDSG496dCkg8Q4Q,5038
292
+ kevin_toolbox/patches/for_test/check_consistency.py,sha256=cerf4NywkvWYMvuJUjimfRRVU7D9vL30jTAX0NxxRoM,9422
292
293
  kevin_toolbox/patches/for_torch/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
293
294
  kevin_toolbox/patches/for_torch/compatible/__init__.py,sha256=7l4FPTILBR8EmStJNHIsbwfFkZpe4xkJZtrlyC8riL8,75
294
295
  kevin_toolbox/patches/for_torch/compatible/concat.py,sha256=vFJn9B437gxDOa5Ze_gXxZewiClqoiIkWeAktDEcJK4,393
@@ -304,7 +305,7 @@ kevin_toolbox/patches/for_torch/math/get_y_at_x.py,sha256=bfoVcasZ_tMdhR_1Me0Jli
304
305
  kevin_toolbox/patches/for_torch/math/my_around.py,sha256=ptpU3ids50gwf663EpHbw7raj9tNrDGBFZ5t_uMNH14,1378
305
306
  kevin_toolbox/patches/for_torch/nn/__init__.py,sha256=aJs3RMqRzQmd8KKDmQW9FxwCqS5yfPqEdg-m0PwlQro,39
306
307
  kevin_toolbox/patches/for_torch/nn/lambda_layer.py,sha256=KUuLiX_Dr4bvRmpAaCW5QTDWDcnMPRnw0jg4NNXTFhM,223
307
- kevin_toolbox_dev-1.3.4.dist-info/METADATA,sha256=NANoXo3yczTlDCHbDo38F_QLlPf0LBYWIwMS4fRHipY,2710
308
- kevin_toolbox_dev-1.3.4.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
309
- kevin_toolbox_dev-1.3.4.dist-info/top_level.txt,sha256=S5TeRGF-PwlhsaUEPTI-f2vWrpLmh3axpyI6v-Fi75o,14
310
- kevin_toolbox_dev-1.3.4.dist-info/RECORD,,
308
+ kevin_toolbox_dev-1.3.5.dist-info/METADATA,sha256=ftmjWCBMUjdd756VCDmVAXgSXT1hIBWpZpvzngyAWCQ,2636
309
+ kevin_toolbox_dev-1.3.5.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
310
+ kevin_toolbox_dev-1.3.5.dist-info/top_level.txt,sha256=S5TeRGF-PwlhsaUEPTI-f2vWrpLmh3axpyI6v-Fi75o,14
311
+ kevin_toolbox_dev-1.3.5.dist-info/RECORD,,
@@ -1,67 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: kevin-toolbox-dev
3
- Version: 1.3.4
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
- Platform: UNKNOWN
12
- Classifier: License :: OSI Approved :: MIT License
13
- Classifier: Programming Language :: Python
14
- Classifier: Programming Language :: Python :: 3
15
- Requires-Python: >=3.6
16
- Description-Content-Type: text/markdown
17
- Requires-Dist: torch (>=1.2.0)
18
- Requires-Dist: numpy (>=1.19.0)
19
- Provides-Extra: plot
20
- Requires-Dist: matplotlib (>=3.0) ; extra == 'plot'
21
- Provides-Extra: rest
22
- Requires-Dist: pytest (>=6.2.5) ; extra == 'rest'
23
- Requires-Dist: line-profiler (>=3.5) ; extra == 'rest'
24
-
25
- # kevin_toolbox
26
-
27
- 一个通用的工具代码包集合
28
-
29
-
30
-
31
- 环境要求
32
-
33
- ```shell
34
- numpy>=1.19
35
- pytorch>=1.2
36
- ```
37
-
38
- 安装方法:
39
-
40
- ```shell
41
- pip install kevin-toolbox --no-dependencies
42
- ```
43
-
44
-
45
-
46
- [项目地址 Repo](https://github.com/cantbeblank96/kevin_toolbox)
47
-
48
- [使用指南 User_Guide](./notes/User_Guide.md)
49
-
50
- [免责声明 Disclaimer](./notes/Disclaimer.md)
51
-
52
- [版本更新记录](./notes/Release_Record.md):
53
-
54
- - v 1.3.4 (2024-04-06)【bug fix】【new feature】
55
- - nested_dict_list
56
- - 【new feature】add replace_identical_with_reference() to value_parser,新增该函数用于将具有相同 id 的多个节点,替换为单个节点和其多个引用的形式。一般用于去除冗余部分,压缩 ndl 的结构。
57
- - 【bug fix】【new feature】fix bug in write(),添加了 saved_node_name_format 参数控制 nodes 下文件名的生成。
58
- - bug:在 v1.3.3 前直接使用原始的 node_name 来作为 nodes/ 目录下的文件名,这导致当 node_name 中带有特殊字符时,比如 "/"(在linux下) 和 ":"(在windows下),将会导致保存失败。
59
- - fix:使用 saved_node_name_format 指定生成文件名的方式,默认方式 '{count}_{hash_name}' 可以避免出现特殊字符。
60
- - 【bug fix】fix bug in write()
61
- - bug:在 v1.3.3 前 processed_s 通过 ndl.set_value() 来逐个节点构建,但是由于根据节点名创建的结果可能和原结构存在差异(详见 ndl.set_value() 中b_force参数的介绍),因此导致 processed_s 和 var 结构不一致,导致出错。
62
- - fix:使用 ndl.copy_() 来创建结构与 var 一致的 processed_s。
63
- - 【new feature】add b_keep_identical_relations to write(),增加该参数用于决定是否保留不同节点之间的 id 相等关系。
64
- - 添加了对应的测试用例。
65
-
66
-
67
-