mindstudio-probe 1.0.3__py3-none-any.whl → 1.0.4__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 (262) hide show
  1. {mindstudio_probe-1.0.3.dist-info → mindstudio_probe-1.0.4.dist-info}/LICENSE +201 -201
  2. {mindstudio_probe-1.0.3.dist-info → mindstudio_probe-1.0.4.dist-info}/METADATA +36 -34
  3. mindstudio_probe-1.0.4.dist-info/RECORD +276 -0
  4. {mindstudio_probe-1.0.3.dist-info → mindstudio_probe-1.0.4.dist-info}/WHEEL +1 -1
  5. {mindstudio_probe-1.0.3.dist-info → mindstudio_probe-1.0.4.dist-info}/entry_points.txt +1 -0
  6. msprobe/README.md +101 -237
  7. msprobe/{config/config.json → config.json} +49 -49
  8. msprobe/core/advisor/advisor.py +124 -124
  9. msprobe/core/advisor/advisor_const.py +59 -59
  10. msprobe/core/advisor/advisor_result.py +58 -58
  11. msprobe/core/common/const.py +341 -318
  12. msprobe/core/common/exceptions.py +99 -99
  13. msprobe/core/common/{file_check.py → file_utils.py} +478 -283
  14. msprobe/core/common/log.py +76 -69
  15. msprobe/core/common/utils.py +385 -616
  16. msprobe/core/common_config.py +85 -71
  17. msprobe/core/compare/acc_compare.py +299 -298
  18. msprobe/core/compare/check.py +95 -95
  19. msprobe/core/compare/compare_cli.py +49 -49
  20. msprobe/core/compare/highlight.py +223 -222
  21. msprobe/core/compare/multiprocessing_compute.py +149 -149
  22. msprobe/core/compare/npy_compare.py +295 -295
  23. msprobe/core/compare/utils.py +430 -429
  24. msprobe/core/data_dump/data_collector.py +154 -144
  25. msprobe/core/data_dump/data_processor/base.py +314 -293
  26. msprobe/core/data_dump/data_processor/factory.py +59 -59
  27. msprobe/core/data_dump/data_processor/mindspore_processor.py +186 -198
  28. msprobe/core/data_dump/data_processor/pytorch_processor.py +366 -389
  29. msprobe/core/data_dump/json_writer.py +96 -116
  30. msprobe/core/data_dump/scope.py +178 -178
  31. msprobe/core/grad_probe/constant.py +70 -70
  32. msprobe/core/grad_probe/grad_compare.py +171 -175
  33. msprobe/core/grad_probe/utils.py +64 -52
  34. msprobe/docs/01.installation.md +89 -0
  35. msprobe/docs/02.config_introduction.md +165 -0
  36. msprobe/docs/03.config_examples.md +247 -0
  37. msprobe/docs/04.acl_config_examples.md +76 -0
  38. msprobe/docs/05.data_dump_PyTorch.md +198 -0
  39. msprobe/docs/06.data_dump_MindSpore.md +243 -0
  40. msprobe/docs/07.accuracy_checker_PyTorch.md +274 -0
  41. msprobe/docs/08.accuracy_checker_online_PyTorch.md +198 -0
  42. msprobe/docs/09.accuracy_checker_MindSpore.md +68 -0
  43. msprobe/docs/10.accuracy_compare_PyTorch.md +245 -0
  44. msprobe/docs/11.accuracy_compare_MindSpore.md +202 -0
  45. msprobe/docs/12.overflow_check_PyTorch.md +79 -0
  46. msprobe/docs/13.overflow_check_MindSpore.md +31 -0
  47. msprobe/{pytorch/doc/parse_tool.md → docs/14.data_parse_PyTorch.md} +283 -286
  48. msprobe/docs/15.free_benchmarking_PyTorch.md +164 -0
  49. msprobe/{doc/grad_probe/grad_probe.md → docs/17.grad_probe.md} +207 -207
  50. msprobe/docs/FAQ_PyTorch.md +177 -0
  51. msprobe/docs/S02.report_free_benchmarking_validation_performance_baseline.md +146 -0
  52. msprobe/docs/img/free_benchmark_framework.png +0 -0
  53. msprobe/mindspore/__init__.py +1 -1
  54. msprobe/mindspore/api_accuracy_checker/api_accuracy_checker.py +254 -245
  55. msprobe/mindspore/api_accuracy_checker/api_info.py +69 -69
  56. msprobe/mindspore/api_accuracy_checker/api_runner.py +155 -151
  57. msprobe/mindspore/api_accuracy_checker/base_compare_algorithm.py +196 -196
  58. msprobe/mindspore/api_accuracy_checker/cmd_parser.py +6 -0
  59. msprobe/mindspore/api_accuracy_checker/compute_element.py +238 -223
  60. msprobe/mindspore/api_accuracy_checker/main.py +8 -15
  61. msprobe/mindspore/api_accuracy_checker/type_mapping.py +113 -113
  62. msprobe/mindspore/api_accuracy_checker/utils.py +79 -62
  63. msprobe/mindspore/cell_processor.py +34 -34
  64. msprobe/mindspore/common/const.py +106 -87
  65. msprobe/mindspore/common/log.py +37 -37
  66. msprobe/mindspore/common/utils.py +81 -57
  67. msprobe/mindspore/compare/distributed_compare.py +75 -75
  68. msprobe/mindspore/compare/ms_compare.py +219 -117
  69. msprobe/mindspore/compare/ms_graph_compare.py +348 -317
  70. msprobe/mindspore/compare/ms_to_pt_api.yaml +399 -399
  71. msprobe/mindspore/debugger/debugger_config.py +66 -74
  72. msprobe/mindspore/debugger/precision_debugger.py +126 -107
  73. msprobe/mindspore/dump/dump_tool_factory.py +35 -35
  74. msprobe/mindspore/dump/hook_cell/api_registry.py +118 -104
  75. msprobe/mindspore/dump/hook_cell/hook_cell.py +55 -53
  76. msprobe/mindspore/dump/hook_cell/support_wrap_ops.yaml +922 -925
  77. msprobe/mindspore/dump/hook_cell/wrap_api.py +113 -0
  78. msprobe/mindspore/dump/jit_dump.py +72 -56
  79. msprobe/mindspore/dump/kernel_graph_dump.py +59 -60
  80. msprobe/mindspore/dump/kernel_kbyk_dump.py +64 -65
  81. msprobe/mindspore/free_benchmark/api_pynative_self_check.py +116 -116
  82. msprobe/mindspore/free_benchmark/common/config.py +12 -12
  83. msprobe/mindspore/free_benchmark/common/handler_params.py +17 -17
  84. msprobe/mindspore/free_benchmark/common/utils.py +71 -71
  85. msprobe/mindspore/free_benchmark/data/support_wrap_ops.yaml +842 -842
  86. msprobe/mindspore/free_benchmark/decorator/dec_forward.py +43 -42
  87. msprobe/mindspore/free_benchmark/decorator/decorator_factory.py +107 -107
  88. msprobe/mindspore/free_benchmark/handler/base_handler.py +90 -90
  89. msprobe/mindspore/free_benchmark/handler/check_handler.py +41 -41
  90. msprobe/mindspore/free_benchmark/handler/fix_handler.py +36 -36
  91. msprobe/mindspore/free_benchmark/handler/handler_factory.py +21 -21
  92. msprobe/mindspore/free_benchmark/perturbation/add_noise.py +67 -67
  93. msprobe/mindspore/free_benchmark/perturbation/base_perturbation.py +21 -21
  94. msprobe/mindspore/free_benchmark/perturbation/bit_noise.py +63 -63
  95. msprobe/mindspore/free_benchmark/perturbation/exchange_value.py +51 -0
  96. msprobe/mindspore/free_benchmark/perturbation/improve_precision.py +35 -34
  97. msprobe/mindspore/free_benchmark/perturbation/no_change.py +12 -12
  98. msprobe/mindspore/free_benchmark/perturbation/perturbation_factory.py +29 -27
  99. msprobe/mindspore/free_benchmark/self_check_tool_factory.py +33 -33
  100. msprobe/mindspore/grad_probe/global_context.py +90 -91
  101. msprobe/mindspore/grad_probe/grad_analyzer.py +231 -231
  102. msprobe/mindspore/grad_probe/grad_monitor.py +27 -27
  103. msprobe/mindspore/grad_probe/grad_stat_csv.py +131 -131
  104. msprobe/mindspore/grad_probe/hook.py +94 -92
  105. msprobe/mindspore/grad_probe/utils.py +29 -28
  106. msprobe/mindspore/ms_config.py +128 -126
  107. msprobe/mindspore/overflow_check/kernel_graph_overflow_check.py +44 -45
  108. msprobe/mindspore/overflow_check/overflow_check_tool_factory.py +34 -34
  109. msprobe/mindspore/runtime.py +4 -4
  110. msprobe/mindspore/service.py +378 -354
  111. msprobe/mindspore/task_handler_factory.py +24 -24
  112. msprobe/msprobe.py +105 -107
  113. msprobe/pytorch/__init__.py +3 -3
  114. msprobe/pytorch/api_accuracy_checker/common/config.py +53 -55
  115. msprobe/pytorch/api_accuracy_checker/common/utils.py +214 -165
  116. msprobe/pytorch/api_accuracy_checker/compare/algorithm.py +213 -213
  117. msprobe/pytorch/api_accuracy_checker/compare/api_precision_compare.py +606 -581
  118. msprobe/pytorch/api_accuracy_checker/compare/api_precision_standard.yaml +132 -132
  119. msprobe/pytorch/api_accuracy_checker/compare/api_precision_threshold.yaml +390 -390
  120. msprobe/pytorch/api_accuracy_checker/compare/compare.py +386 -381
  121. msprobe/pytorch/api_accuracy_checker/compare/compare_column.py +73 -73
  122. msprobe/pytorch/api_accuracy_checker/compare/compare_utils.py +245 -244
  123. msprobe/pytorch/api_accuracy_checker/config.yaml +10 -10
  124. msprobe/pytorch/api_accuracy_checker/run_ut/data_generate.py +335 -332
  125. msprobe/pytorch/api_accuracy_checker/run_ut/multi_run_ut.py +200 -199
  126. msprobe/pytorch/api_accuracy_checker/run_ut/run_overflow_check.py +133 -134
  127. msprobe/pytorch/api_accuracy_checker/run_ut/run_ut.py +592 -581
  128. msprobe/pytorch/api_accuracy_checker/run_ut/run_ut_utils.py +70 -74
  129. msprobe/pytorch/api_accuracy_checker/run_ut/torch_ut_setting.json +7 -4
  130. msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/attl.py +197 -202
  131. msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/client.py +325 -324
  132. msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/device_dispatch.py +204 -204
  133. msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/server.py +219 -218
  134. msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/ssl_config.py +10 -10
  135. msprobe/pytorch/bench_functions/__init__.py +15 -15
  136. msprobe/pytorch/bench_functions/apply_adam_w.py +28 -28
  137. msprobe/pytorch/bench_functions/confusion_transpose.py +19 -19
  138. msprobe/pytorch/bench_functions/fast_gelu.py +55 -55
  139. msprobe/pytorch/bench_functions/layer_norm_eval.py +6 -6
  140. msprobe/pytorch/bench_functions/linear.py +12 -12
  141. msprobe/pytorch/bench_functions/matmul_backward.py +48 -48
  142. msprobe/pytorch/bench_functions/npu_fusion_attention.py +509 -421
  143. msprobe/pytorch/bench_functions/rms_norm.py +15 -15
  144. msprobe/pytorch/bench_functions/rotary_mul.py +52 -52
  145. msprobe/pytorch/bench_functions/scaled_mask_softmax.py +26 -26
  146. msprobe/pytorch/bench_functions/swiglu.py +55 -55
  147. msprobe/pytorch/common/__init__.py +2 -2
  148. msprobe/pytorch/common/compare_script.template +14 -14
  149. msprobe/pytorch/common/log.py +20 -31
  150. msprobe/pytorch/common/parse_json.py +39 -39
  151. msprobe/pytorch/common/utils.py +305 -300
  152. msprobe/pytorch/compare/distributed_compare.py +66 -66
  153. msprobe/pytorch/compare/mapping.yaml +607 -607
  154. msprobe/pytorch/compare/match.py +34 -33
  155. msprobe/pytorch/compare/pt_compare.py +50 -40
  156. msprobe/pytorch/debugger/debugger_config.py +95 -95
  157. msprobe/pytorch/debugger/precision_debugger.py +125 -125
  158. msprobe/pytorch/free_benchmark/__init__.py +8 -8
  159. msprobe/pytorch/free_benchmark/common/constant.py +70 -70
  160. msprobe/pytorch/free_benchmark/common/counter.py +71 -71
  161. msprobe/pytorch/free_benchmark/common/enums.py +37 -37
  162. msprobe/pytorch/free_benchmark/common/params.py +129 -129
  163. msprobe/pytorch/free_benchmark/common/utils.py +102 -102
  164. msprobe/pytorch/free_benchmark/compare/grad_saver.py +179 -179
  165. msprobe/pytorch/free_benchmark/compare/single_benchmark.py +104 -104
  166. msprobe/pytorch/free_benchmark/main.py +105 -105
  167. msprobe/pytorch/free_benchmark/perturbed_layers/base_layer.py +13 -13
  168. msprobe/pytorch/free_benchmark/perturbed_layers/layer_factory.py +41 -41
  169. msprobe/pytorch/free_benchmark/perturbed_layers/npu/add_noise.py +90 -90
  170. msprobe/pytorch/free_benchmark/perturbed_layers/npu/bit_noise.py +104 -104
  171. msprobe/pytorch/free_benchmark/perturbed_layers/npu/change_value.py +63 -63
  172. msprobe/pytorch/free_benchmark/perturbed_layers/npu/improve_precision.py +68 -68
  173. msprobe/pytorch/free_benchmark/perturbed_layers/npu/no_change.py +28 -28
  174. msprobe/pytorch/free_benchmark/perturbed_layers/npu/npu_base_layser.py +45 -45
  175. msprobe/pytorch/free_benchmark/perturbed_layers/run_cpu.py +19 -19
  176. msprobe/pytorch/free_benchmark/result_handlers/base_handler.py +217 -217
  177. msprobe/pytorch/free_benchmark/result_handlers/check_handler.py +39 -39
  178. msprobe/pytorch/free_benchmark/result_handlers/fix_handler.py +23 -23
  179. msprobe/pytorch/free_benchmark/result_handlers/handler_factory.py +30 -30
  180. msprobe/pytorch/free_benchmark/result_handlers/preheat_handler.py +170 -170
  181. msprobe/pytorch/function_factory.py +76 -75
  182. msprobe/pytorch/functional/dump_module.py +39 -39
  183. msprobe/pytorch/grad_probe/grad_monitor.py +91 -90
  184. msprobe/pytorch/grad_probe/grad_stat_csv.py +128 -128
  185. msprobe/pytorch/hook_module/api_registry.py +161 -161
  186. msprobe/pytorch/hook_module/hook_module.py +120 -120
  187. msprobe/pytorch/hook_module/support_wrap_ops.yaml +1879 -1877
  188. msprobe/pytorch/hook_module/utils.py +30 -29
  189. msprobe/pytorch/hook_module/wrap_aten.py +110 -110
  190. msprobe/pytorch/hook_module/wrap_distributed.py +78 -78
  191. msprobe/pytorch/hook_module/wrap_functional.py +105 -105
  192. msprobe/pytorch/hook_module/wrap_npu_custom.py +93 -84
  193. msprobe/pytorch/hook_module/wrap_tensor.py +71 -71
  194. msprobe/pytorch/hook_module/wrap_torch.py +86 -86
  195. msprobe/pytorch/hook_module/wrap_vf.py +62 -62
  196. msprobe/pytorch/module_processer.py +138 -138
  197. msprobe/pytorch/online_dispatch/__init__.py +20 -20
  198. msprobe/pytorch/online_dispatch/compare.py +236 -236
  199. msprobe/pytorch/online_dispatch/dispatch.py +271 -271
  200. msprobe/pytorch/online_dispatch/dump_compare.py +155 -156
  201. msprobe/pytorch/online_dispatch/single_compare.py +391 -391
  202. msprobe/pytorch/online_dispatch/torch_ops_config.yaml +49 -49
  203. msprobe/pytorch/online_dispatch/utils.py +130 -146
  204. msprobe/pytorch/parse.py +4 -4
  205. msprobe/pytorch/parse_tool/cli.py +32 -32
  206. msprobe/pytorch/parse_tool/lib/compare.py +260 -271
  207. msprobe/pytorch/parse_tool/lib/config.py +52 -52
  208. msprobe/pytorch/parse_tool/lib/file_desc.py +31 -31
  209. msprobe/pytorch/parse_tool/lib/interactive_cli.py +102 -102
  210. msprobe/pytorch/parse_tool/lib/parse_exception.py +54 -54
  211. msprobe/pytorch/parse_tool/lib/parse_tool.py +158 -158
  212. msprobe/pytorch/parse_tool/lib/utils.py +316 -321
  213. msprobe/pytorch/parse_tool/lib/visualization.py +85 -91
  214. msprobe/pytorch/pt_config.py +188 -187
  215. msprobe/pytorch/service.py +246 -252
  216. mindstudio_probe-1.0.3.dist-info/RECORD +0 -272
  217. msprobe/config/README.md +0 -539
  218. msprobe/mindspore/doc/compare.md +0 -58
  219. msprobe/mindspore/doc/dump.md +0 -217
  220. msprobe/mindspore/dump/hook_cell/wrap_functional.py +0 -91
  221. msprobe/mindspore/dump/hook_cell/wrap_tensor.py +0 -63
  222. msprobe/pytorch/doc/FAQ.md +0 -193
  223. msprobe/pytorch/doc/api_accuracy_checker.md +0 -313
  224. msprobe/pytorch/doc/api_accuracy_checker_online.md +0 -187
  225. msprobe/pytorch/doc/dump.md +0 -260
  226. msprobe/pytorch/doc/msprobe/321/207/342/226/223/342/225/233/321/205/342/225/221/320/266/321/205/342/225/226/320/265/321/205/320/225/342/225/226/321/206/320/245/342/226/221/321/206/320/235/320/276dump/321/206/320/260/320/227/321/205/320/227/320/226/321/206/320/220/320/267/321/210/320/223/342/225/234/321/205/320/257/342/225/221/321/207/342/225/221/342/224/220/321/206/320/232/320/265/321/205/320/241/320/232.md +0 -182
  227. msprobe/pytorch/doc/ptdbg_ascend_compare.md +0 -240
  228. msprobe/pytorch/doc/ptdbg_ascend_overview.md +0 -68
  229. msprobe/pytorch/doc/ptdbg_ascend_quickstart.md +0 -381
  230. msprobe/pytorch/doc/run_overflow_check.md +0 -25
  231. msprobe/pytorch/doc//321/205/320/254/320/270/321/207/342/225/221/342/224/220/321/207/342/226/223/342/225/233/321/205/342/225/221/320/266/321/206/320/277/320/244/321/205/320/277/342/225/243.md +0 -90
  232. msprobe/pytorch/doc//321/206/320/247/320/260/321/206/320/260/320/227/321/206/320/255/320/226/321/205/342/225/226/320/265/321/205/320/225/342/225/226/321/205/320/254/342/225/221/321/206/320/251/320/277/321/211/320/272/320/234/321/210/320/277/320/221/321/205/320/242/320/234/321/206/320/220/320/267/321/210/320/223/342/225/234/321/205/320/257/342/225/221/321/207/342/225/221/342/224/220/321/206/320/232/320/265/321/205/320/241/320/232.md +0 -151
  233. {mindstudio_probe-1.0.3.dist-info → mindstudio_probe-1.0.4.dist-info}/top_level.txt +0 -0
  234. /msprobe/{pytorch/doc → docs}/img/BLOOM-7B_1.png +0 -0
  235. /msprobe/{pytorch/doc → docs}/img/BLOOM-7B_2.png +0 -0
  236. /msprobe/{pytorch/doc → docs}/img/BLOOM-7B_3.png +0 -0
  237. /msprobe/{pytorch/doc → docs}/img/BLOOM-7B_4.png +0 -0
  238. /msprobe/{pytorch/doc → docs}/img/GPT-3_1.png +0 -0
  239. /msprobe/{pytorch/doc → docs}/img/GPT-3_2.png +0 -0
  240. /msprobe/{pytorch/doc → docs}/img/GPT-3_3.png +0 -0
  241. /msprobe/{pytorch/doc → docs}/img/GPT-3_4.png +0 -0
  242. /msprobe/{pytorch/doc → docs}/img/GPT-3_5.png +0 -0
  243. /msprobe/{pytorch/doc → docs}/img/GPT-3_6.png +0 -0
  244. /msprobe/{pytorch/doc → docs}/img/GPT-3_7.png +0 -0
  245. /msprobe/{pytorch/doc → docs}/img/GPT-3_8.png +0 -0
  246. /msprobe/{pytorch/doc → docs}/img/YOLOV5S_1.png +0 -0
  247. /msprobe/{pytorch/doc → docs}/img/YOLOV5S_2.png +0 -0
  248. /msprobe/{pytorch/doc → docs}/img/accuracy_checking_details.png +0 -0
  249. /msprobe/{pytorch/doc → docs}/img/accuracy_checking_result.png +0 -0
  250. /msprobe/{pytorch/doc → docs}/img/api_precision_compare_details.png +0 -0
  251. /msprobe/{pytorch/doc → docs}/img/api_precision_compare_result.png +0 -0
  252. /msprobe/{pytorch/doc → docs}/img/auto_analyze_log.png +0 -0
  253. /msprobe/{pytorch/doc → docs}/img/compare_result_pkl.png +0 -0
  254. /msprobe/{pytorch/doc → docs}/img/compare_result_pkl_md5.png.png +0 -0
  255. /msprobe/{pytorch/doc → docs}/img/cpu_info.png +0 -0
  256. /msprobe/{config → docs}/img/free_benchmark.png +0 -0
  257. /msprobe/{doc/grad_probe/img/image-1.png → docs/img/grad_probe_image-1.png} +0 -0
  258. /msprobe/{doc/grad_probe/img/image-2.png → docs/img/grad_probe_image-2.png} +0 -0
  259. /msprobe/{doc/grad_probe/img/image-3.png → docs/img/grad_probe_image-3.png} +0 -0
  260. /msprobe/{doc/grad_probe/img/image-4.png → docs/img/grad_probe_image-4.png} +0 -0
  261. /msprobe/{doc/grad_probe/img/image.png → docs/img/grad_probe_image.png} +0 -0
  262. /msprobe/{pytorch/doc → docs}/img/module_compare.png +0 -0
@@ -1,283 +1,478 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """
4
- # Copyright (C) 2022-2023. Huawei Technologies Co., Ltd. All rights reserved.
5
- # Licensed under the Apache License, Version 2.0 (the "License");
6
- # you may not use this file except in compliance with the License.
7
- # You may obtain a copy of the License at
8
- #
9
- # http://www.apache.org/licenses/LICENSE-2.0
10
- #
11
- # Unless required by applicable law or agreed to in writing, software
12
- # distributed under the License is distributed on an "AS IS" BASIS,
13
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- # See the License for the specific language governing permissions and
15
- # limitations under the License.
16
- """
17
- import os
18
- import re
19
-
20
- from msprobe.core.common.log import logger
21
- from msprobe.core.common.exceptions import FileCheckException
22
- from msprobe.core.common.const import FileCheckConst
23
-
24
-
25
- class FileChecker:
26
- """
27
- The class for check file.
28
-
29
- Attributes:
30
- file_path: The file or dictionary path to be verified.
31
- path_type: file or dictionary
32
- ability(str): FileCheckConst.WRITE_ABLE or FileCheckConst.READ_ABLE to set file has writability or readability
33
- file_type(str): The correct file type for file
34
- """
35
- def __init__(self, file_path, path_type, ability=None, file_type=None, is_script=True):
36
- self.file_path = file_path
37
- self.path_type = self._check_path_type(path_type)
38
- self.ability = ability
39
- self.file_type = file_type
40
- self.is_script = is_script
41
-
42
- @staticmethod
43
- def _check_path_type(path_type):
44
- if path_type not in [FileCheckConst.DIR, FileCheckConst.FILE]:
45
- logger.error(f'The path_type must be {FileCheckConst.DIR} or {FileCheckConst.FILE}.')
46
- raise FileCheckException(FileCheckException.ILLEGAL_PARAM_ERROR)
47
- return path_type
48
-
49
- def common_check(self):
50
- """
51
- 功能:用户校验基本文件权限:软连接、文件长度、是否存在、读写权限、文件属组、文件特殊字符
52
- 注意:文件后缀的合法性,非通用操作,可使用其他独立接口实现
53
- """
54
- check_path_exists(self.file_path)
55
- check_link(self.file_path)
56
- self.file_path = os.path.realpath(self.file_path)
57
- check_path_length(self.file_path)
58
- check_path_type(self.file_path, self.path_type)
59
- self.check_path_ability()
60
- if self.is_script:
61
- check_path_owner_consistent(self.file_path)
62
- check_path_pattern_vaild(self.file_path)
63
- check_common_file_size(self.file_path)
64
- check_file_suffix(self.file_path, self.file_type)
65
- return self.file_path
66
-
67
- def check_path_ability(self):
68
- if self.ability == FileCheckConst.WRITE_ABLE:
69
- check_path_writability(self.file_path)
70
- if self.ability == FileCheckConst.READ_ABLE:
71
- check_path_readability(self.file_path)
72
- if self.ability == FileCheckConst.READ_WRITE_ABLE:
73
- check_path_readability(self.file_path)
74
- check_path_writability(self.file_path)
75
-
76
-
77
- class FileOpen:
78
- """
79
- The class for open file by a safe way.
80
-
81
- Attributes:
82
- file_path: The file or dictionary path to be opened.
83
- mode(str): The file open mode
84
- """
85
- SUPPORT_READ_MODE = ["r", "rb"]
86
- SUPPORT_WRITE_MODE = ["w", "wb", "a", "ab"]
87
- SUPPORT_READ_WRITE_MODE = ["r+", "rb+", "w+", "wb+", "a+", "ab+"]
88
-
89
- def __init__(self, file_path, mode, encoding='utf-8'):
90
- self.file_path = file_path
91
- self.mode = mode
92
- self.encoding = encoding
93
- self._handle = None
94
-
95
- def __enter__(self):
96
- self.check_file_path()
97
- binary_mode = "b"
98
- if binary_mode not in self.mode:
99
- self._handle = open(self.file_path, self.mode, encoding=self.encoding)
100
- else:
101
- self._handle = open(self.file_path, self.mode)
102
- return self._handle
103
-
104
- def __exit__(self, exc_type, exc_val, exc_tb):
105
- if self._handle:
106
- self._handle.close()
107
-
108
- def check_file_path(self):
109
- support_mode = self.SUPPORT_READ_MODE + self.SUPPORT_WRITE_MODE + self.SUPPORT_READ_WRITE_MODE
110
- if self.mode not in support_mode:
111
- logger.error("File open not support %s mode" % self.mode)
112
- raise FileCheckException(FileCheckException.ILLEGAL_PARAM_ERROR)
113
- check_link(self.file_path)
114
- self.file_path = os.path.realpath(self.file_path)
115
- check_path_length(self.file_path)
116
- self.check_ability_and_owner()
117
- check_path_pattern_vaild(self.file_path)
118
- if os.path.exists(self.file_path):
119
- check_common_file_size(self.file_path)
120
-
121
- def check_ability_and_owner(self):
122
- if self.mode in self.SUPPORT_READ_MODE:
123
- check_path_exists(self.file_path)
124
- check_path_readability(self.file_path)
125
- check_path_owner_consistent(self.file_path)
126
- if self.mode in self.SUPPORT_WRITE_MODE and os.path.exists(self.file_path):
127
- check_path_writability(self.file_path)
128
- check_path_owner_consistent(self.file_path)
129
- if self.mode in self.SUPPORT_READ_WRITE_MODE and os.path.exists(self.file_path):
130
- check_path_readability(self.file_path)
131
- check_path_writability(self.file_path)
132
- check_path_owner_consistent(self.file_path)
133
-
134
-
135
- def check_link(path):
136
- abs_path = os.path.abspath(path)
137
- if os.path.islink(abs_path):
138
- logger.error('The file path {} is a soft link.'.format(path))
139
- raise FileCheckException(FileCheckException.SOFT_LINK_ERROR)
140
-
141
-
142
- def check_path_length(path, name_length=None):
143
- file_max_name_length = name_length if name_length else FileCheckConst.FILE_NAME_LENGTH
144
- if len(path) > FileCheckConst.DIRECTORY_LENGTH or \
145
- len(os.path.basename(path)) > file_max_name_length:
146
- logger.error('The file path length exceeds limit.')
147
- raise FileCheckException(FileCheckException.ILLEGAL_PATH_ERROR)
148
-
149
-
150
- def check_path_exists(path):
151
- if not os.path.exists(path):
152
- logger.error('The file path %s does not exist.' % path)
153
- raise FileCheckException(FileCheckException.ILLEGAL_PATH_ERROR)
154
-
155
-
156
- def check_path_readability(path):
157
- if not os.access(path, os.R_OK):
158
- logger.error('The file path %s is not readable.' % path)
159
- raise FileCheckException(FileCheckException.FILE_PERMISSION_ERROR)
160
-
161
-
162
- def check_path_writability(path):
163
- if not os.access(path, os.W_OK):
164
- logger.error('The file path %s is not writable.' % path)
165
- raise FileCheckException(FileCheckException.FILE_PERMISSION_ERROR)
166
-
167
-
168
- def check_path_executable(path):
169
- if not os.access(path, os.X_OK):
170
- logger.error('The file path %s is not executable.' % path)
171
- raise FileCheckException(FileCheckException.FILE_PERMISSION_ERROR)
172
-
173
-
174
- def check_other_user_writable(path):
175
- st = os.stat(path)
176
- if st.st_mode & 0o002:
177
- logger.error('The file path %s may be insecure because other users have write permissions. ' % path)
178
- raise FileCheckException(FileCheckException.FILE_PERMISSION_ERROR)
179
-
180
-
181
- def check_path_owner_consistent(path):
182
- file_owner = os.stat(path).st_uid
183
- if file_owner != os.getuid():
184
- logger.error('The file path %s may be insecure because is does not belong to you.' % path)
185
- raise FileCheckException(FileCheckException.FILE_PERMISSION_ERROR)
186
-
187
-
188
- def check_path_pattern_vaild(path):
189
- if not re.match(FileCheckConst.FILE_VALID_PATTERN, path):
190
- logger.error('The file path %s contains special characters.' %(path))
191
- raise FileCheckException(FileCheckException.ILLEGAL_PATH_ERROR)
192
-
193
-
194
- def check_file_size(file_path, max_size):
195
- file_size = os.path.getsize(file_path)
196
- if file_size >= max_size:
197
- logger.error(f'The size of file path {file_path} exceeds {max_size} bytes.')
198
- raise FileCheckException(FileCheckException.FILE_TOO_LARGE_ERROR)
199
-
200
-
201
- def check_common_file_size(file_path):
202
- if os.path.isfile(file_path):
203
- for suffix, max_size in FileCheckConst.FILE_SIZE_DICT.items():
204
- if file_path.endswith(suffix):
205
- check_file_size(file_path, max_size)
206
- break
207
-
208
-
209
- def check_file_suffix(file_path, file_suffix):
210
- if file_suffix:
211
- if not file_path.endswith(file_suffix):
212
- logger.error(f"The {file_path} should be a {file_suffix} file!")
213
- raise FileCheckException(FileCheckException.INVALID_FILE_ERROR)
214
-
215
-
216
- def check_path_type(file_path, file_type):
217
- if file_type == FileCheckConst.FILE:
218
- if not os.path.isfile(file_path):
219
- logger.error(f"The {file_path} should be a file!")
220
- raise FileCheckException(FileCheckException.INVALID_FILE_ERROR)
221
- if file_type == FileCheckConst.DIR:
222
- if not os.path.isdir(file_path):
223
- logger.error(f"The {file_path} should be a dictionary!")
224
- raise FileCheckException(FileCheckException.INVALID_FILE_ERROR)
225
-
226
-
227
- def create_directory(dir_path):
228
- """
229
- Function Description:
230
- creating a directory with specified permissions
231
- Parameter:
232
- dir_path: directory path
233
- Exception Description:
234
- when invalid data throw exception
235
- """
236
- dir_path = os.path.realpath(dir_path)
237
- try:
238
- os.makedirs(dir_path, mode=FileCheckConst.DATA_DIR_AUTHORITY, exist_ok=True)
239
- except OSError as ex:
240
- raise FileCheckException(FileCheckException.ILLEGAL_PATH_ERROR,
241
- 'Failed to create {}. Please check the path permission or disk space .{}'.format(dir_path, str(ex))) from ex
242
-
243
-
244
- def check_path_before_create(path):
245
- if path_len_exceeds_limit(path):
246
- raise FileCheckException(FileCheckException.ILLEGAL_PATH_ERROR, 'The file path length exceeds limit.')
247
-
248
- if not re.match(FileCheckConst.FILE_PATTERN, os.path.realpath(path)):
249
- raise FileCheckException(FileCheckException.ILLEGAL_PATH_ERROR,
250
- 'The file path {} contains special characters.'.format(path))
251
-
252
-
253
- def change_mode(path, mode):
254
- if not os.path.exists(path) or os.path.islink(path):
255
- return
256
- try:
257
- os.chmod(path, mode)
258
- except PermissionError as ex:
259
- raise FileCheckException(FileCheckException.FILE_PERMISSION_ERROR,
260
- 'Failed to change {} authority. {}'.format(path, str(ex))) from ex
261
-
262
-
263
- def path_len_exceeds_limit(file_path):
264
- return len(os.path.realpath(file_path)) > FileCheckConst.DIRECTORY_LENGTH or \
265
- len(os.path.basename(file_path)) > FileCheckConst.FILE_NAME_LENGTH
266
-
267
-
268
- def check_file_type(path):
269
- """
270
- Function Description:
271
- determine if it is a file or a directory
272
- Parameter:
273
- path: path
274
- Exception Description:
275
- when neither a file nor a directory throw exception
276
- """
277
- if os.path.isdir(path):
278
- return FileCheckConst.DIR
279
- elif os.path.isfile(path):
280
- return FileCheckConst.FILE
281
- else:
282
- logger.error('Neither a file nor a directory.')
283
- raise FileCheckException(FileCheckException.INVALID_FILE_ERROR)
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ # Copyright (C) 2022-2023. Huawei Technologies Co., Ltd. All rights reserved.
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ """
17
+ import csv
18
+ import fcntl
19
+ import os
20
+ import json
21
+ import re
22
+ import shutil
23
+ import yaml
24
+ import numpy as np
25
+
26
+ from msprobe.core.common.log import logger
27
+ from msprobe.core.common.exceptions import FileCheckException
28
+ from msprobe.core.common.const import FileCheckConst
29
+
30
+
31
+ class FileChecker:
32
+ """
33
+ The class for check file.
34
+
35
+ Attributes:
36
+ file_path: The file or dictionary path to be verified.
37
+ path_type: file or dictionary
38
+ ability(str): FileCheckConst.WRITE_ABLE or FileCheckConst.READ_ABLE to set file has writability or readability
39
+ file_type(str): The correct file type for file
40
+ """
41
+
42
+ def __init__(self, file_path, path_type, ability=None, file_type=None, is_script=True):
43
+ self.file_path = file_path
44
+ self.path_type = self._check_path_type(path_type)
45
+ self.ability = ability
46
+ self.file_type = file_type
47
+ self.is_script = is_script
48
+
49
+ @staticmethod
50
+ def _check_path_type(path_type):
51
+ if path_type not in [FileCheckConst.DIR, FileCheckConst.FILE]:
52
+ logger.error(f'The path_type must be {FileCheckConst.DIR} or {FileCheckConst.FILE}.')
53
+ raise FileCheckException(FileCheckException.ILLEGAL_PARAM_ERROR)
54
+ return path_type
55
+
56
+ def common_check(self):
57
+ """
58
+ 功能:用户校验基本文件权限:软连接、文件长度、是否存在、读写权限、文件属组、文件特殊字符
59
+ 注意:文件后缀的合法性,非通用操作,可使用其他独立接口实现
60
+ """
61
+ check_path_exists(self.file_path)
62
+ check_link(self.file_path)
63
+ self.file_path = os.path.realpath(self.file_path)
64
+ check_path_length(self.file_path)
65
+ check_path_type(self.file_path, self.path_type)
66
+ self.check_path_ability()
67
+ if self.is_script:
68
+ check_path_owner_consistent(self.file_path)
69
+ check_path_pattern_vaild(self.file_path)
70
+ check_common_file_size(self.file_path)
71
+ check_file_suffix(self.file_path, self.file_type)
72
+ return self.file_path
73
+
74
+ def check_path_ability(self):
75
+ if self.ability == FileCheckConst.WRITE_ABLE:
76
+ check_path_writability(self.file_path)
77
+ if self.ability == FileCheckConst.READ_ABLE:
78
+ check_path_readability(self.file_path)
79
+ if self.ability == FileCheckConst.READ_WRITE_ABLE:
80
+ check_path_readability(self.file_path)
81
+ check_path_writability(self.file_path)
82
+
83
+
84
+ class FileOpen:
85
+ """
86
+ The class for open file by a safe way.
87
+
88
+ Attributes:
89
+ file_path: The file or dictionary path to be opened.
90
+ mode(str): The file open mode
91
+ """
92
+ SUPPORT_READ_MODE = ["r", "rb"]
93
+ SUPPORT_WRITE_MODE = ["w", "wb", "a", "ab"]
94
+ SUPPORT_READ_WRITE_MODE = ["r+", "rb+", "w+", "wb+", "a+", "ab+"]
95
+
96
+ def __init__(self, file_path, mode, encoding='utf-8'):
97
+ self.file_path = file_path
98
+ self.mode = mode
99
+ self.encoding = encoding
100
+ self._handle = None
101
+
102
+ def __enter__(self):
103
+ self.check_file_path()
104
+ binary_mode = "b"
105
+ if binary_mode not in self.mode:
106
+ self._handle = open(self.file_path, self.mode, encoding=self.encoding)
107
+ else:
108
+ self._handle = open(self.file_path, self.mode)
109
+ return self._handle
110
+
111
+ def __exit__(self, exc_type, exc_val, exc_tb):
112
+ if self._handle:
113
+ self._handle.close()
114
+
115
+ def check_file_path(self):
116
+ support_mode = self.SUPPORT_READ_MODE + self.SUPPORT_WRITE_MODE + self.SUPPORT_READ_WRITE_MODE
117
+ if self.mode not in support_mode:
118
+ logger.error("File open not support %s mode" % self.mode)
119
+ raise FileCheckException(FileCheckException.ILLEGAL_PARAM_ERROR)
120
+ check_link(self.file_path)
121
+ self.file_path = os.path.realpath(self.file_path)
122
+ check_path_length(self.file_path)
123
+ self.check_ability_and_owner()
124
+ check_path_pattern_vaild(self.file_path)
125
+ if os.path.exists(self.file_path):
126
+ check_common_file_size(self.file_path)
127
+
128
+ def check_ability_and_owner(self):
129
+ if self.mode in self.SUPPORT_READ_MODE:
130
+ check_path_exists(self.file_path)
131
+ check_path_readability(self.file_path)
132
+ check_path_owner_consistent(self.file_path)
133
+ if self.mode in self.SUPPORT_WRITE_MODE and os.path.exists(self.file_path):
134
+ check_path_writability(self.file_path)
135
+ check_path_owner_consistent(self.file_path)
136
+ if self.mode in self.SUPPORT_READ_WRITE_MODE and os.path.exists(self.file_path):
137
+ check_path_readability(self.file_path)
138
+ check_path_writability(self.file_path)
139
+ check_path_owner_consistent(self.file_path)
140
+
141
+
142
+ def check_link(path):
143
+ abs_path = os.path.abspath(path)
144
+ if os.path.islink(abs_path):
145
+ logger.error('The file path {} is a soft link.'.format(path))
146
+ raise FileCheckException(FileCheckException.SOFT_LINK_ERROR)
147
+
148
+
149
+ def check_path_length(path, name_length=None):
150
+ file_max_name_length = name_length if name_length else FileCheckConst.FILE_NAME_LENGTH
151
+ if len(path) > FileCheckConst.DIRECTORY_LENGTH or \
152
+ len(os.path.basename(path)) > file_max_name_length:
153
+ logger.error('The file path length exceeds limit.')
154
+ raise FileCheckException(FileCheckException.ILLEGAL_PATH_ERROR)
155
+
156
+
157
+ def check_path_exists(path):
158
+ if not os.path.exists(path):
159
+ logger.error('The file path %s does not exist.' % path)
160
+ raise FileCheckException(FileCheckException.ILLEGAL_PATH_ERROR)
161
+
162
+
163
+ def check_path_readability(path):
164
+ if not os.access(path, os.R_OK):
165
+ logger.error('The file path %s is not readable.' % path)
166
+ raise FileCheckException(FileCheckException.FILE_PERMISSION_ERROR)
167
+
168
+
169
+ def check_path_writability(path):
170
+ if not os.access(path, os.W_OK):
171
+ logger.error('The file path %s is not writable.' % path)
172
+ raise FileCheckException(FileCheckException.FILE_PERMISSION_ERROR)
173
+
174
+
175
+ def check_path_executable(path):
176
+ if not os.access(path, os.X_OK):
177
+ logger.error('The file path %s is not executable.' % path)
178
+ raise FileCheckException(FileCheckException.FILE_PERMISSION_ERROR)
179
+
180
+
181
+ def check_other_user_writable(path):
182
+ st = os.stat(path)
183
+ if st.st_mode & 0o002:
184
+ logger.error('The file path %s may be insecure because other users have write permissions. ' % path)
185
+ raise FileCheckException(FileCheckException.FILE_PERMISSION_ERROR)
186
+
187
+
188
+ def check_path_owner_consistent(path):
189
+ file_owner = os.stat(path).st_uid
190
+ if file_owner != os.getuid():
191
+ logger.error('The file path %s may be insecure because is does not belong to you.' % path)
192
+ raise FileCheckException(FileCheckException.FILE_PERMISSION_ERROR)
193
+
194
+
195
+ def check_path_pattern_vaild(path):
196
+ if not re.match(FileCheckConst.FILE_VALID_PATTERN, path):
197
+ logger.error('The file path %s contains special characters.' % (path))
198
+ raise FileCheckException(FileCheckException.ILLEGAL_PATH_ERROR)
199
+
200
+
201
+ def check_file_size(file_path, max_size):
202
+ try:
203
+ file_size = os.path.getsize(file_path)
204
+ except OSError as os_error:
205
+ logger.error(f'Failed to open "{file_path}". {str(os_error)}')
206
+ raise FileCheckException(FileCheckException.INVALID_FILE_ERROR) from os_error
207
+ if file_size >= max_size:
208
+ logger.error(f'The size ({file_size}) of {file_path} exceeds ({max_size}) bytes, tools not support.')
209
+ raise FileCheckException(FileCheckException.FILE_TOO_LARGE_ERROR)
210
+
211
+
212
+ def check_common_file_size(file_path):
213
+ if os.path.isfile(file_path):
214
+ for suffix, max_size in FileCheckConst.FILE_SIZE_DICT.items():
215
+ if file_path.endswith(suffix):
216
+ check_file_size(file_path, max_size)
217
+ break
218
+
219
+
220
+ def check_file_suffix(file_path, file_suffix):
221
+ if file_suffix:
222
+ if not file_path.endswith(file_suffix):
223
+ logger.error(f"The {file_path} should be a {file_suffix} file!")
224
+ raise FileCheckException(FileCheckException.INVALID_FILE_ERROR)
225
+
226
+
227
+ def check_path_type(file_path, file_type):
228
+ if file_type == FileCheckConst.FILE:
229
+ if not os.path.isfile(file_path):
230
+ logger.error(f"The {file_path} should be a file!")
231
+ raise FileCheckException(FileCheckException.INVALID_FILE_ERROR)
232
+ if file_type == FileCheckConst.DIR:
233
+ if not os.path.isdir(file_path):
234
+ logger.error(f"The {file_path} should be a dictionary!")
235
+ raise FileCheckException(FileCheckException.INVALID_FILE_ERROR)
236
+
237
+
238
+ def make_dir(dir_path):
239
+ dir_path = os.path.realpath(dir_path)
240
+ check_path_before_create(dir_path)
241
+ if os.path.isdir(dir_path):
242
+ return
243
+ try:
244
+ os.makedirs(dir_path, mode=FileCheckConst.DATA_DIR_AUTHORITY, exist_ok=True)
245
+ except OSError as ex:
246
+ raise FileCheckException(FileCheckException.ILLEGAL_PATH_ERROR,
247
+ f"Failed to create {dir_path}. "
248
+ f"Please check the path permission or disk space. {str(ex)}") from ex
249
+ file_check = FileChecker(dir_path, FileCheckConst.DIR)
250
+ file_check.common_check()
251
+
252
+
253
+ def create_directory(dir_path):
254
+ """
255
+ Function Description:
256
+ creating a safe directory with specified permissions
257
+ Parameter:
258
+ dir_path: directory path
259
+ Exception Description:
260
+ when invalid data throw exception
261
+ """
262
+ dir_path = os.path.realpath(dir_path)
263
+ check_path_before_create(dir_path)
264
+ parent_dir = os.path.dirname(dir_path)
265
+ if not os.path.isdir(parent_dir):
266
+ create_directory(parent_dir)
267
+ make_dir(dir_path)
268
+
269
+
270
+ def check_path_before_create(path):
271
+ if path_len_exceeds_limit(path):
272
+ raise FileCheckException(FileCheckException.ILLEGAL_PATH_ERROR, 'The file path length exceeds limit.')
273
+
274
+ if not re.match(FileCheckConst.FILE_PATTERN, os.path.realpath(path)):
275
+ raise FileCheckException(FileCheckException.ILLEGAL_PATH_ERROR,
276
+ 'The file path {} contains special characters.'.format(path))
277
+
278
+
279
+ def check_file_or_directory_path(path, isdir=False):
280
+ """
281
+ Function Description:
282
+ check whether the path is valid
283
+ Parameter:
284
+ path: the path to check
285
+ isdir: the path is dir or file
286
+ Exception Description:
287
+ when invalid data throw exception
288
+ """
289
+ if isdir:
290
+ path_checker = FileChecker(path, FileCheckConst.DIR, FileCheckConst.WRITE_ABLE)
291
+ else:
292
+ path_checker = FileChecker(path, FileCheckConst.FILE, FileCheckConst.READ_ABLE)
293
+ path_checker.common_check()
294
+
295
+
296
+ def change_mode(path, mode):
297
+ if not os.path.exists(path) or os.path.islink(path):
298
+ return
299
+ try:
300
+ os.chmod(path, mode)
301
+ except PermissionError as ex:
302
+ raise FileCheckException(FileCheckException.FILE_PERMISSION_ERROR,
303
+ 'Failed to change {} authority. {}'.format(path, str(ex))) from ex
304
+
305
+
306
+ def path_len_exceeds_limit(file_path):
307
+ return len(os.path.realpath(file_path)) > FileCheckConst.DIRECTORY_LENGTH or \
308
+ len(os.path.basename(file_path)) > FileCheckConst.FILE_NAME_LENGTH
309
+
310
+
311
+ def check_file_type(path):
312
+ """
313
+ Function Description:
314
+ determine if it is a file or a directory
315
+ Parameter:
316
+ path: path
317
+ Exception Description:
318
+ when neither a file nor a directory throw exception
319
+ """
320
+ if os.path.isdir(path):
321
+ return FileCheckConst.DIR
322
+ elif os.path.isfile(path):
323
+ return FileCheckConst.FILE
324
+ else:
325
+ logger.error('Neither a file nor a directory.')
326
+ raise FileCheckException(FileCheckException.INVALID_FILE_ERROR)
327
+
328
+
329
+ def load_yaml(yaml_path):
330
+ path_checker = FileChecker(yaml_path, FileCheckConst.FILE, FileCheckConst.READ_ABLE, FileCheckConst.YAML_SUFFIX)
331
+ checked_path = path_checker.common_check()
332
+ try:
333
+ with FileOpen(checked_path, "r") as f:
334
+ yaml_data = yaml.safe_load(f)
335
+ except Exception as e:
336
+ logger.error(f"The yaml file failed to load. Please check the path: {checked_path}.")
337
+ raise RuntimeError(f"Load yaml file {checked_path} failed.") from e
338
+ return yaml_data
339
+
340
+
341
+ def load_npy(filepath, enable_pickle=False):
342
+ check_file_or_directory_path(filepath)
343
+ try:
344
+ npy = np.load(filepath, allow_pickle=enable_pickle)
345
+ except Exception as e:
346
+ logger.error(f"The numpy file failed to load. Please check the path: {filepath}.")
347
+ raise RuntimeError(f"Load numpy file {filepath} failed.") from e
348
+ return npy
349
+
350
+
351
+ def load_json(json_path):
352
+ try:
353
+ with FileOpen(json_path, "r") as f:
354
+ fcntl.flock(f, fcntl.LOCK_EX)
355
+ data = json.load(f)
356
+ fcntl.flock(f, fcntl.LOCK_UN)
357
+ except Exception as e:
358
+ logger.error(f'load json file "{os.path.basename(json_path)}" failed.')
359
+ raise RuntimeError(f"Load json file {json_path} failed.") from e
360
+ return data
361
+
362
+
363
+ def save_json(json_path, data, indent=None):
364
+ json_path = os.path.realpath(json_path)
365
+ check_path_before_create(json_path)
366
+ try:
367
+ with FileOpen(json_path, 'w') as f:
368
+ fcntl.flock(f, fcntl.LOCK_EX)
369
+ json.dump(data, f, indent=indent)
370
+ fcntl.flock(f, fcntl.LOCK_UN)
371
+ except Exception as e:
372
+ logger.error(f'Save json file "{os.path.basename(json_path)}" failed.')
373
+ raise RuntimeError(f"Save json file {json_path} failed.") from e
374
+ change_mode(json_path, FileCheckConst.DATA_FILE_AUTHORITY)
375
+
376
+
377
+ def move_file(src_path, dst_path):
378
+ check_file_or_directory_path(src_path)
379
+ check_path_before_create(dst_path)
380
+ try:
381
+ shutil.move(src_path, dst_path)
382
+ except Exception as e:
383
+ logger.error(f"move file {src_path} to {dst_path} failed")
384
+ raise RuntimeError(f"move file {src_path} to {dst_path} failed") from e
385
+ change_mode(dst_path, FileCheckConst.DATA_FILE_AUTHORITY)
386
+
387
+
388
+ def save_npy(data, filepath):
389
+ filepath = os.path.realpath(filepath)
390
+ check_path_before_create(filepath)
391
+ try:
392
+ np.save(filepath, data)
393
+ except Exception as e:
394
+ logger.error(f"The numpy file failed to save. Please check the path: {filepath}.")
395
+ raise RuntimeError(f"Save numpy file {filepath} failed.") from e
396
+ change_mode(filepath, FileCheckConst.DATA_FILE_AUTHORITY)
397
+
398
+
399
+ def save_npy_to_txt(self, data, dst_file='', align=0):
400
+ if os.path.exists(dst_file):
401
+ self.log.info("Dst file %s exists, will not save new one.", dst_file)
402
+ return
403
+ shape = data.shape
404
+ data = data.flatten()
405
+ if align == 0:
406
+ align = 1 if len(shape) == 0 else shape[-1]
407
+ elif data.size % align != 0:
408
+ pad_array = np.zeros((align - data.size % align,))
409
+ data = np.append(data, pad_array)
410
+ check_path_before_create(dst_file)
411
+ try:
412
+ np.savetxt(dst_file, data.reshape((-1, align)), delimiter=' ', fmt='%g')
413
+ except Exception as e:
414
+ self.log.error("An unexpected error occurred: %s when savetxt to %s" % (str(e)), dst_file)
415
+ change_mode(dst_file, FileCheckConst.DATA_FILE_AUTHORITY)
416
+
417
+
418
+ def save_workbook(workbook, file_path):
419
+ """
420
+ 保存工作簿到指定的文件路径
421
+ workbook: 要保存的工作簿对象
422
+ file_path: 文件保存路径
423
+ """
424
+ file_path = os.path.realpath(file_path)
425
+ check_path_before_create(file_path)
426
+ try:
427
+ workbook.save(file_path)
428
+ except Exception as e:
429
+ logger.error(f'Save result file "{os.path.basename(file_path)}" failed')
430
+ raise RuntimeError(f"Save result file {file_path} failed.") from e
431
+ change_mode(file_path, FileCheckConst.DATA_FILE_AUTHORITY)
432
+
433
+
434
+ def write_csv(data, filepath, mode="a+"):
435
+ file_path = os.path.realpath(filepath)
436
+ check_path_before_create(filepath)
437
+ try:
438
+ with FileOpen(filepath, mode, encoding='utf-8-sig') as f:
439
+ writer = csv.writer(f)
440
+ writer.writerows(data)
441
+ except Exception as e:
442
+ logger.error(f'Save csv file "{os.path.basename(file_path)}" failed')
443
+ raise RuntimeError(f"Save csv file {file_path} failed.") from e
444
+ change_mode(filepath, FileCheckConst.DATA_FILE_AUTHORITY)
445
+
446
+
447
+ def remove_path(path):
448
+ if not os.path.exists(path):
449
+ return
450
+ try:
451
+ if os.path.islink(path) or os.path.isfile(path):
452
+ os.remove(path)
453
+ else:
454
+ shutil.rmtree(path)
455
+ except PermissionError as err:
456
+ logger.error("Failed to delete {}. Please check the permission.".format(path))
457
+ raise FileCheckException(FileCheckException.ILLEGAL_PATH_ERROR) from err
458
+ except Exception as e:
459
+ logger.error("Failed to delete {}. Please check.".format(path))
460
+ raise RuntimeError(f"Delete {path} failed.") from e
461
+
462
+
463
+ def get_json_contents(file_path):
464
+ ops = get_file_content_bytes(file_path)
465
+ try:
466
+ json_obj = json.loads(ops)
467
+ except ValueError as error:
468
+ logger.error('Failed to load json.')
469
+ raise FileCheckException(FileCheckException.INVALID_FILE_ERROR) from error
470
+ if not isinstance(json_obj, dict):
471
+ logger.error('Json file content is not a dictionary!')
472
+ raise FileCheckException(FileCheckException.INVALID_FILE_ERROR)
473
+ return json_obj
474
+
475
+
476
+ def get_file_content_bytes(file):
477
+ with FileOpen(file, 'rb') as file_handle:
478
+ return file_handle.read()