mindstudio-probe 1.0.3__py3-none-any.whl → 1.1.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 (278) hide show
  1. {mindstudio_probe-1.0.3.dist-info → mindstudio_probe-1.1.0.dist-info}/LICENSE +201 -201
  2. {mindstudio_probe-1.0.3.dist-info → mindstudio_probe-1.1.0.dist-info}/METADATA +36 -34
  3. mindstudio_probe-1.1.0.dist-info/RECORD +287 -0
  4. {mindstudio_probe-1.0.3.dist-info → mindstudio_probe-1.1.0.dist-info}/WHEEL +1 -1
  5. {mindstudio_probe-1.0.3.dist-info → mindstudio_probe-1.1.0.dist-info}/entry_points.txt +1 -0
  6. msprobe/README.md +131 -237
  7. msprobe/__init__.py +16 -1
  8. msprobe/{config/config.json → config.json} +47 -49
  9. msprobe/core/advisor/advisor.py +124 -124
  10. msprobe/core/advisor/advisor_const.py +58 -59
  11. msprobe/core/advisor/advisor_result.py +58 -58
  12. msprobe/core/common/const.py +402 -318
  13. msprobe/core/common/exceptions.py +99 -99
  14. msprobe/core/common/{file_check.py → file_utils.py} +523 -283
  15. msprobe/core/common/inplace_op_checker.py +38 -0
  16. msprobe/core/common/inplace_ops.yaml +251 -0
  17. msprobe/core/common/log.py +86 -69
  18. msprobe/core/common/utils.py +371 -616
  19. msprobe/core/common_config.py +78 -71
  20. msprobe/core/compare/acc_compare.py +472 -298
  21. msprobe/core/compare/check.py +180 -95
  22. msprobe/core/compare/compare_cli.py +69 -49
  23. msprobe/core/compare/highlight.py +259 -222
  24. msprobe/core/compare/multiprocessing_compute.py +174 -149
  25. msprobe/core/compare/npy_compare.py +310 -295
  26. msprobe/core/compare/utils.py +464 -429
  27. msprobe/core/data_dump/data_collector.py +153 -144
  28. msprobe/core/data_dump/data_processor/base.py +337 -293
  29. msprobe/core/data_dump/data_processor/factory.py +76 -59
  30. msprobe/core/data_dump/data_processor/mindspore_processor.py +192 -198
  31. msprobe/core/data_dump/data_processor/pytorch_processor.py +383 -389
  32. msprobe/core/data_dump/json_writer.py +117 -116
  33. msprobe/core/data_dump/scope.py +194 -178
  34. msprobe/core/grad_probe/constant.py +74 -70
  35. msprobe/core/grad_probe/grad_compare.py +170 -175
  36. msprobe/core/grad_probe/utils.py +77 -52
  37. msprobe/docs/01.installation.md +99 -0
  38. msprobe/docs/02.config_introduction.md +137 -0
  39. msprobe/docs/03.config_examples.md +237 -0
  40. msprobe/docs/04.acl_config_examples.md +78 -0
  41. msprobe/docs/05.data_dump_PyTorch.md +326 -0
  42. msprobe/docs/06.data_dump_MindSpore.md +285 -0
  43. msprobe/docs/07.accuracy_checker_PyTorch.md +297 -0
  44. msprobe/docs/08.accuracy_checker_online_PyTorch.md +238 -0
  45. msprobe/docs/09.accuracy_checker_MindSpore.md +68 -0
  46. msprobe/docs/10.accuracy_compare_PyTorch.md +327 -0
  47. msprobe/docs/11.accuracy_compare_MindSpore.md +333 -0
  48. msprobe/docs/12.overflow_check_PyTorch.md +79 -0
  49. msprobe/docs/13.overflow_check_MindSpore.md +31 -0
  50. msprobe/{pytorch/doc/parse_tool.md → docs/14.data_parse_PyTorch.md} +283 -286
  51. msprobe/docs/15.free_benchmarking_PyTorch.md +170 -0
  52. msprobe/docs/16.free_benchmarking_MindSpore.md +140 -0
  53. msprobe/{doc/grad_probe/grad_probe.md → docs/17.grad_probe.md} +205 -207
  54. 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 → docs/18.online_dispatch.md} +89 -90
  55. msprobe/docs/FAQ.md +189 -0
  56. msprobe/docs/S02.report_free_benchmarking_validation_performance_baseline.md +146 -0
  57. msprobe/docs/img/free_benchmark_framework.png +0 -0
  58. msprobe/docs/img/ms_dump.png +0 -0
  59. msprobe/docs/img/ms_layer.png +0 -0
  60. msprobe/docs/img/pt_dump.png +0 -0
  61. msprobe/mindspore/__init__.py +2 -1
  62. msprobe/mindspore/api_accuracy_checker/api_accuracy_checker.py +278 -245
  63. msprobe/mindspore/api_accuracy_checker/api_info.py +76 -69
  64. msprobe/mindspore/api_accuracy_checker/api_runner.py +155 -151
  65. msprobe/mindspore/api_accuracy_checker/base_compare_algorithm.py +196 -196
  66. msprobe/mindspore/api_accuracy_checker/cmd_parser.py +6 -0
  67. msprobe/mindspore/api_accuracy_checker/compute_element.py +238 -223
  68. msprobe/mindspore/api_accuracy_checker/main.py +8 -15
  69. msprobe/mindspore/api_accuracy_checker/type_mapping.py +113 -113
  70. msprobe/mindspore/api_accuracy_checker/utils.py +79 -62
  71. msprobe/mindspore/cell_processor.py +58 -34
  72. msprobe/mindspore/common/const.py +108 -87
  73. msprobe/mindspore/common/log.py +37 -37
  74. msprobe/mindspore/common/utils.py +97 -57
  75. msprobe/mindspore/compare/distributed_compare.py +62 -75
  76. msprobe/mindspore/compare/layer_mapping.py +146 -0
  77. msprobe/mindspore/compare/modify_mapping.py +107 -0
  78. msprobe/mindspore/compare/ms_compare.py +357 -117
  79. msprobe/mindspore/compare/ms_graph_compare.py +364 -317
  80. msprobe/mindspore/compare/ms_to_pt_api.yaml +399 -399
  81. msprobe/mindspore/debugger/debugger_config.py +69 -74
  82. msprobe/mindspore/debugger/precision_debugger.py +150 -107
  83. msprobe/mindspore/dump/dump_tool_factory.py +50 -35
  84. msprobe/mindspore/dump/hook_cell/api_registry.py +128 -104
  85. msprobe/mindspore/dump/hook_cell/hook_cell.py +55 -53
  86. msprobe/mindspore/dump/hook_cell/primitive_hooks.py +206 -0
  87. msprobe/mindspore/dump/hook_cell/support_wrap_ops.yaml +994 -925
  88. msprobe/mindspore/dump/hook_cell/wrap_api.py +121 -0
  89. msprobe/mindspore/dump/jit_dump.py +96 -56
  90. msprobe/mindspore/dump/kernel_graph_dump.py +75 -60
  91. msprobe/mindspore/dump/kernel_kbyk_dump.py +79 -65
  92. msprobe/mindspore/free_benchmark/api_pynative_self_check.py +131 -116
  93. msprobe/mindspore/free_benchmark/common/config.py +27 -12
  94. msprobe/mindspore/free_benchmark/common/handler_params.py +32 -17
  95. msprobe/mindspore/free_benchmark/common/utils.py +85 -71
  96. msprobe/mindspore/free_benchmark/data/support_wrap_ops.yaml +842 -842
  97. msprobe/mindspore/free_benchmark/decorator/dec_forward.py +57 -42
  98. msprobe/mindspore/free_benchmark/decorator/decorator_factory.py +122 -107
  99. msprobe/mindspore/free_benchmark/handler/base_handler.py +105 -90
  100. msprobe/mindspore/free_benchmark/handler/check_handler.py +56 -41
  101. msprobe/mindspore/free_benchmark/handler/fix_handler.py +51 -36
  102. msprobe/mindspore/free_benchmark/handler/handler_factory.py +36 -21
  103. msprobe/mindspore/free_benchmark/perturbation/add_noise.py +82 -67
  104. msprobe/mindspore/free_benchmark/perturbation/base_perturbation.py +36 -21
  105. msprobe/mindspore/free_benchmark/perturbation/bit_noise.py +78 -63
  106. msprobe/mindspore/free_benchmark/perturbation/exchange_value.py +77 -0
  107. msprobe/mindspore/free_benchmark/perturbation/improve_precision.py +49 -34
  108. msprobe/mindspore/free_benchmark/perturbation/no_change.py +27 -12
  109. msprobe/mindspore/free_benchmark/perturbation/perturbation_factory.py +44 -27
  110. msprobe/mindspore/free_benchmark/self_check_tool_factory.py +48 -33
  111. msprobe/mindspore/grad_probe/global_context.py +100 -91
  112. msprobe/mindspore/grad_probe/grad_analyzer.py +231 -231
  113. msprobe/mindspore/grad_probe/grad_monitor.py +27 -27
  114. msprobe/mindspore/grad_probe/grad_stat_csv.py +131 -131
  115. msprobe/mindspore/grad_probe/hook.py +94 -92
  116. msprobe/mindspore/grad_probe/utils.py +29 -28
  117. msprobe/mindspore/ms_config.py +128 -126
  118. msprobe/mindspore/overflow_check/kernel_graph_overflow_check.py +60 -45
  119. msprobe/mindspore/overflow_check/overflow_check_tool_factory.py +49 -34
  120. msprobe/mindspore/runtime.py +4 -4
  121. msprobe/mindspore/service.py +297 -354
  122. msprobe/mindspore/task_handler_factory.py +24 -24
  123. msprobe/msprobe.py +105 -107
  124. msprobe/pytorch/__init__.py +23 -4
  125. msprobe/pytorch/api_accuracy_checker/common/config.py +70 -55
  126. msprobe/pytorch/api_accuracy_checker/common/utils.py +246 -165
  127. msprobe/pytorch/api_accuracy_checker/compare/algorithm.py +230 -213
  128. msprobe/pytorch/api_accuracy_checker/compare/api_precision_compare.py +632 -581
  129. msprobe/pytorch/api_accuracy_checker/compare/api_precision_standard.yaml +132 -132
  130. msprobe/pytorch/api_accuracy_checker/compare/api_precision_threshold.yaml +390 -390
  131. msprobe/pytorch/api_accuracy_checker/compare/compare.py +416 -381
  132. msprobe/pytorch/api_accuracy_checker/compare/compare_column.py +90 -73
  133. msprobe/pytorch/api_accuracy_checker/compare/compare_utils.py +265 -244
  134. msprobe/pytorch/api_accuracy_checker/config.yaml +10 -10
  135. msprobe/pytorch/api_accuracy_checker/run_ut/data_generate.py +370 -332
  136. msprobe/pytorch/api_accuracy_checker/run_ut/multi_run_ut.py +221 -199
  137. msprobe/pytorch/api_accuracy_checker/run_ut/run_overflow_check.py +150 -134
  138. msprobe/pytorch/api_accuracy_checker/run_ut/run_ut.py +518 -581
  139. msprobe/pytorch/api_accuracy_checker/run_ut/run_ut_utils.py +213 -74
  140. msprobe/pytorch/api_accuracy_checker/run_ut/torch_ut_setting.json +7 -4
  141. msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/attl.py +218 -202
  142. msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/client.py +370 -324
  143. msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/device_dispatch.py +227 -204
  144. msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/dump_dispatch.py +110 -0
  145. msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/server.py +244 -218
  146. msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/torch_ops_config.yaml +63 -0
  147. msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/utils.py +44 -0
  148. msprobe/pytorch/bench_functions/__init__.py +30 -15
  149. msprobe/pytorch/bench_functions/apply_adam_w.py +43 -28
  150. msprobe/pytorch/bench_functions/confusion_transpose.py +34 -19
  151. msprobe/pytorch/bench_functions/fast_gelu.py +70 -55
  152. msprobe/pytorch/bench_functions/layer_norm_eval.py +21 -6
  153. msprobe/pytorch/bench_functions/linear.py +27 -12
  154. msprobe/pytorch/bench_functions/matmul_backward.py +63 -48
  155. msprobe/pytorch/bench_functions/npu_fusion_attention.py +538 -421
  156. msprobe/pytorch/bench_functions/rms_norm.py +30 -15
  157. msprobe/pytorch/bench_functions/rotary_mul.py +71 -52
  158. msprobe/pytorch/bench_functions/scaled_mask_softmax.py +41 -26
  159. msprobe/pytorch/bench_functions/swiglu.py +70 -55
  160. msprobe/pytorch/common/__init__.py +17 -2
  161. msprobe/pytorch/common/compare_script.template +14 -14
  162. msprobe/pytorch/common/log.py +33 -32
  163. msprobe/pytorch/common/parse_json.py +54 -39
  164. msprobe/pytorch/common/utils.py +310 -300
  165. msprobe/pytorch/compare/distributed_compare.py +66 -66
  166. msprobe/pytorch/compare/mapping.yaml +607 -607
  167. msprobe/pytorch/compare/match.py +49 -33
  168. msprobe/pytorch/compare/pt_compare.py +82 -40
  169. msprobe/pytorch/debugger/debugger_config.py +108 -95
  170. msprobe/pytorch/debugger/precision_debugger.py +173 -125
  171. msprobe/pytorch/free_benchmark/__init__.py +23 -8
  172. msprobe/pytorch/free_benchmark/common/constant.py +70 -70
  173. msprobe/pytorch/free_benchmark/common/counter.py +71 -71
  174. msprobe/pytorch/free_benchmark/common/enums.py +65 -37
  175. msprobe/pytorch/free_benchmark/common/params.py +144 -129
  176. msprobe/pytorch/free_benchmark/common/utils.py +118 -102
  177. msprobe/pytorch/free_benchmark/compare/grad_saver.py +200 -179
  178. msprobe/pytorch/free_benchmark/compare/single_benchmark.py +119 -104
  179. msprobe/pytorch/free_benchmark/main.py +120 -105
  180. msprobe/pytorch/free_benchmark/perturbed_layers/base_layer.py +28 -13
  181. msprobe/pytorch/free_benchmark/perturbed_layers/layer_factory.py +56 -41
  182. msprobe/pytorch/free_benchmark/perturbed_layers/npu/add_noise.py +105 -90
  183. msprobe/pytorch/free_benchmark/perturbed_layers/npu/bit_noise.py +119 -104
  184. msprobe/pytorch/free_benchmark/perturbed_layers/npu/change_value.py +87 -63
  185. msprobe/pytorch/free_benchmark/perturbed_layers/npu/improve_precision.py +83 -68
  186. msprobe/pytorch/free_benchmark/perturbed_layers/npu/no_change.py +43 -28
  187. msprobe/pytorch/free_benchmark/perturbed_layers/npu/npu_base_layser.py +60 -45
  188. msprobe/pytorch/free_benchmark/perturbed_layers/run_cpu.py +34 -19
  189. msprobe/pytorch/free_benchmark/result_handlers/base_handler.py +256 -217
  190. msprobe/pytorch/free_benchmark/result_handlers/check_handler.py +54 -39
  191. msprobe/pytorch/free_benchmark/result_handlers/fix_handler.py +38 -23
  192. msprobe/pytorch/free_benchmark/result_handlers/handler_factory.py +45 -30
  193. msprobe/pytorch/free_benchmark/result_handlers/preheat_handler.py +185 -170
  194. msprobe/pytorch/function_factory.py +91 -75
  195. msprobe/pytorch/functional/module_dump.py +84 -0
  196. msprobe/pytorch/grad_probe/grad_monitor.py +91 -90
  197. msprobe/pytorch/grad_probe/grad_stat_csv.py +128 -128
  198. msprobe/pytorch/hook_module/__init__.py +16 -1
  199. msprobe/pytorch/hook_module/api_registry.py +166 -161
  200. msprobe/pytorch/hook_module/hook_module.py +118 -120
  201. msprobe/pytorch/hook_module/support_wrap_ops.yaml +1879 -1877
  202. msprobe/pytorch/hook_module/utils.py +28 -29
  203. msprobe/pytorch/hook_module/wrap_aten.py +111 -110
  204. msprobe/pytorch/hook_module/wrap_distributed.py +77 -78
  205. msprobe/pytorch/hook_module/wrap_functional.py +104 -105
  206. msprobe/pytorch/hook_module/wrap_npu_custom.py +85 -84
  207. msprobe/pytorch/hook_module/wrap_tensor.py +69 -71
  208. msprobe/pytorch/hook_module/wrap_torch.py +84 -86
  209. msprobe/pytorch/hook_module/wrap_vf.py +60 -62
  210. msprobe/pytorch/module_processer.py +153 -138
  211. msprobe/pytorch/online_dispatch/__init__.py +20 -20
  212. msprobe/pytorch/online_dispatch/compare.py +235 -236
  213. msprobe/pytorch/online_dispatch/dispatch.py +271 -271
  214. msprobe/pytorch/online_dispatch/dump_compare.py +155 -156
  215. msprobe/pytorch/online_dispatch/single_compare.py +391 -391
  216. msprobe/pytorch/online_dispatch/torch_ops_config.yaml +57 -49
  217. msprobe/pytorch/online_dispatch/utils.py +127 -146
  218. msprobe/pytorch/parse.py +19 -4
  219. msprobe/pytorch/parse_tool/cli.py +31 -32
  220. msprobe/pytorch/parse_tool/lib/compare.py +259 -271
  221. msprobe/pytorch/parse_tool/lib/config.py +52 -52
  222. msprobe/pytorch/parse_tool/lib/file_desc.py +31 -31
  223. msprobe/pytorch/parse_tool/lib/interactive_cli.py +102 -102
  224. msprobe/pytorch/parse_tool/lib/parse_exception.py +54 -54
  225. msprobe/pytorch/parse_tool/lib/parse_tool.py +161 -158
  226. msprobe/pytorch/parse_tool/lib/utils.py +320 -321
  227. msprobe/pytorch/parse_tool/lib/visualization.py +85 -91
  228. msprobe/pytorch/pt_config.py +317 -187
  229. msprobe/pytorch/service.py +311 -252
  230. mindstudio_probe-1.0.3.dist-info/RECORD +0 -272
  231. msprobe/config/README.md +0 -539
  232. msprobe/mindspore/doc/compare.md +0 -58
  233. msprobe/mindspore/doc/dump.md +0 -217
  234. msprobe/mindspore/dump/hook_cell/wrap_functional.py +0 -91
  235. msprobe/mindspore/dump/hook_cell/wrap_tensor.py +0 -63
  236. msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/ssl_config.py +0 -10
  237. msprobe/pytorch/doc/FAQ.md +0 -193
  238. msprobe/pytorch/doc/api_accuracy_checker.md +0 -313
  239. msprobe/pytorch/doc/api_accuracy_checker_online.md +0 -187
  240. msprobe/pytorch/doc/dump.md +0 -260
  241. 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
  242. msprobe/pytorch/doc/ptdbg_ascend_compare.md +0 -240
  243. msprobe/pytorch/doc/ptdbg_ascend_overview.md +0 -68
  244. msprobe/pytorch/doc/ptdbg_ascend_quickstart.md +0 -381
  245. msprobe/pytorch/doc/run_overflow_check.md +0 -25
  246. 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
  247. msprobe/pytorch/functional/data_processor.py +0 -0
  248. msprobe/pytorch/functional/dump_module.py +0 -39
  249. {mindstudio_probe-1.0.3.dist-info → mindstudio_probe-1.1.0.dist-info}/top_level.txt +0 -0
  250. /msprobe/{pytorch/doc → docs}/img/BLOOM-7B_1.png +0 -0
  251. /msprobe/{pytorch/doc → docs}/img/BLOOM-7B_2.png +0 -0
  252. /msprobe/{pytorch/doc → docs}/img/BLOOM-7B_3.png +0 -0
  253. /msprobe/{pytorch/doc → docs}/img/BLOOM-7B_4.png +0 -0
  254. /msprobe/{pytorch/doc → docs}/img/GPT-3_1.png +0 -0
  255. /msprobe/{pytorch/doc → docs}/img/GPT-3_2.png +0 -0
  256. /msprobe/{pytorch/doc → docs}/img/GPT-3_3.png +0 -0
  257. /msprobe/{pytorch/doc → docs}/img/GPT-3_4.png +0 -0
  258. /msprobe/{pytorch/doc → docs}/img/GPT-3_5.png +0 -0
  259. /msprobe/{pytorch/doc → docs}/img/GPT-3_6.png +0 -0
  260. /msprobe/{pytorch/doc → docs}/img/GPT-3_7.png +0 -0
  261. /msprobe/{pytorch/doc → docs}/img/GPT-3_8.png +0 -0
  262. /msprobe/{pytorch/doc → docs}/img/YOLOV5S_1.png +0 -0
  263. /msprobe/{pytorch/doc → docs}/img/YOLOV5S_2.png +0 -0
  264. /msprobe/{pytorch/doc → docs}/img/accuracy_checking_details.png +0 -0
  265. /msprobe/{pytorch/doc → docs}/img/accuracy_checking_result.png +0 -0
  266. /msprobe/{pytorch/doc → docs}/img/api_precision_compare_details.png +0 -0
  267. /msprobe/{pytorch/doc → docs}/img/api_precision_compare_result.png +0 -0
  268. /msprobe/{pytorch/doc → docs}/img/auto_analyze_log.png +0 -0
  269. /msprobe/{pytorch/doc → docs}/img/compare_result_pkl.png +0 -0
  270. /msprobe/{pytorch/doc → docs}/img/compare_result_pkl_md5.png.png +0 -0
  271. /msprobe/{pytorch/doc → docs}/img/cpu_info.png +0 -0
  272. /msprobe/{config → docs}/img/free_benchmark.png +0 -0
  273. /msprobe/{doc/grad_probe/img/image-1.png → docs/img/grad_probe_image-1.png} +0 -0
  274. /msprobe/{doc/grad_probe/img/image-2.png → docs/img/grad_probe_image-2.png} +0 -0
  275. /msprobe/{doc/grad_probe/img/image-3.png → docs/img/grad_probe_image-3.png} +0 -0
  276. /msprobe/{doc/grad_probe/img/image-4.png → docs/img/grad_probe_image-4.png} +0 -0
  277. /msprobe/{doc/grad_probe/img/image.png → docs/img/grad_probe_image.png} +0 -0
  278. /msprobe/{pytorch/doc → docs}/img/module_compare.png +0 -0
@@ -1,321 +1,320 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """
4
- # Copyright (C) 2022-2024. 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 logging
18
- import os
19
- import io
20
- import re
21
- import sys
22
- import subprocess
23
- import hashlib
24
- import csv
25
- import time
26
- import numpy as np
27
- from collections import namedtuple
28
- from msprobe.pytorch.parse_tool.lib.config import Const
29
- from msprobe.pytorch.parse_tool.lib.file_desc import DumpDecodeFileDesc, FileDesc
30
- from msprobe.pytorch.parse_tool.lib.parse_exception import ParseException
31
- from msprobe.core.common.file_check import change_mode, check_other_user_writable,\
32
- check_path_executable, check_path_owner_consistent
33
- from msprobe.core.common.const import FileCheckConst
34
- from msprobe.core.common.file_check import FileOpen, FileChecker
35
- from msprobe.core.common.utils import check_file_or_directory_path
36
- from msprobe.pytorch.common.log import logger
37
-
38
-
39
- try:
40
- from rich.traceback import install
41
- from rich.panel import Panel
42
- from rich.table import Table
43
- from rich import print as rich_print
44
- from rich.columns import Columns
45
-
46
- install()
47
- except ImportError as err:
48
- install = None
49
- Panel = None
50
- Table = None
51
- Columns = None
52
- rich_print = None
53
- logger.warning(
54
- "Failed to import rich, Some features may not be available. Please run 'pip install rich' to fix it.")
55
-
56
-
57
- class Util:
58
- def __init__(self):
59
- self.ms_accu_cmp = None
60
- self.log = logger
61
- self.python = sys.executable
62
-
63
- @staticmethod
64
- def print(content):
65
- rich_print(content)
66
-
67
- @staticmethod
68
- def path_strip(path):
69
- return path.strip("'").strip('"')
70
-
71
- @staticmethod
72
- def check_executable_file(path):
73
- check_path_owner_consistent(path)
74
- check_other_user_writable(path)
75
- check_path_executable(path)
76
-
77
- @staticmethod
78
- def get_subdir_count(self, directory):
79
- subdir_count = 0
80
- path_checker = FileChecker(directory)
81
- path_checker.common_check()
82
- for _, dirs, _ in os.walk(directory):
83
- subdir_count += len(dirs)
84
- break
85
- return subdir_count
86
-
87
- @staticmethod
88
- def get_subfiles_count(self, directory):
89
- file_count = 0
90
- for root, _, files in os.walk(directory, topdown=True):
91
- path_checker = FileChecker(root)
92
- path_checker.common_check()
93
- file_count += len(files)
94
- path_depth = root.count(os.sep)
95
- if path_depth <= Const.MAX_TRAVERSAL_DEPTH:
96
- yield root, _, files
97
- else:
98
- _[:] = []
99
- return file_count
100
-
101
- @staticmethod
102
- def get_sorted_subdirectories_names(self, directory):
103
- subdirectories = []
104
- for item in os.listdir(directory):
105
- item_path = os.path.join(directory, item)
106
- if os.path.isdir(item_path):
107
- subdirectories.append(item)
108
- return sorted(subdirectories)
109
-
110
- @staticmethod
111
- def get_sorted_files_names(self, directory):
112
- files = []
113
- for item in os.listdir(directory):
114
- item_path = os.path.join(directory, item)
115
- if os.path.isfile(item_path):
116
- files.append(item)
117
- return sorted(files)
118
-
119
- @staticmethod
120
- def check_npy_files_valid_in_dir(self, dir_path):
121
- for file_name in os.listdir(dir_path):
122
- file_path = os.path.join(dir_path, file_name)
123
- check_file_or_directory_path(file_path)
124
- _, file_extension = os.path.splitext(file_path)
125
- if not file_extension == '.npy':
126
- return False
127
- return True
128
-
129
- @staticmethod
130
- def get_md5_for_numpy(self, obj):
131
- np_bytes = obj.tobytes()
132
- md5_hash = hashlib.md5(np_bytes)
133
- return md5_hash.hexdigest()
134
-
135
- @staticmethod
136
- def deal_with_dir_or_file_inconsistency(self, output_path):
137
- if os.path.exists(output_path):
138
- os.remove(output_path)
139
- raise ParseException("Inconsistent directory structure or file.")
140
-
141
- @staticmethod
142
- def deal_with_value_if_has_zero(self, data):
143
- if data.dtype in Const.FLOAT_TYPE:
144
- zero_mask = (data == 0)
145
- # 给0的地方加上eps防止除0
146
- data[zero_mask] += np.finfo(data.dtype).eps
147
- else:
148
- # int type + float eps 会报错,所以这里要强转
149
- data = data.astype(float)
150
- zero_mask = (data == 0)
151
- data[zero_mask] += np.finfo(float).eps
152
- return data
153
-
154
- @staticmethod
155
- def dir_contains_only(self, path, endfix):
156
- for root, _, files in os.walk(path, topdown=True):
157
- path_checker = FileChecker(root)
158
- path_checker.common_check()
159
- for file in files:
160
- if not file.endswith(endfix):
161
- return False
162
- path_depth = root.count(os.sep)
163
- if path_depth <= Const.MAX_TRAVERSAL_DEPTH:
164
- yield root, _, files
165
- else:
166
- _[:] = []
167
- return True
168
-
169
- @staticmethod
170
- def localtime_str(self):
171
- return time.strftime("%Y%m%d%H%M%S", time.localtime())
172
-
173
- @staticmethod
174
- def change_filemode_safe(self, path):
175
- change_mode(path, FileCheckConst.DATA_FILE_AUTHORITY)
176
-
177
- @staticmethod
178
- def _gen_npu_dump_convert_file_info(name, match, dir_path):
179
- return DumpDecodeFileDesc(name, dir_path, int(match.groups()[-4]), op_name=match.group(2),
180
- op_type=match.group(1), task_id=int(match.group(3)), anchor_type=match.groups()[-3],
181
- anchor_idx=int(match.groups()[-2]))
182
-
183
- @staticmethod
184
- def _gen_numpy_file_info(name, math, dir_path):
185
- return FileDesc(name, dir_path)
186
-
187
- def execute_command(self, cmd):
188
- if not cmd:
189
- self.log.error("Commond is None")
190
- return -1
191
- self.log.info("[RUN CMD]: %s", cmd)
192
- cmd = cmd.split(" ")
193
- complete_process = subprocess.run(cmd, shell=False)
194
- return complete_process.returncode
195
-
196
- def print_panel(self, content, title='', fit=True):
197
- if not Panel:
198
- self.print(content)
199
- return
200
- if fit:
201
- self.print(Panel.fit(content, title=title))
202
- else:
203
- self.print(Panel(content, title=title))
204
-
205
- def check_msaccucmp(self, target_file):
206
- if os.path.split(target_file)[-1] != Const.MS_ACCU_CMP_FILE_NAME:
207
- self.log.error(
208
- "Check msaccucmp failed in dir %s. This is not a correct msaccucmp file" % target_file)
209
- raise ParseException(ParseException.PARSE_MSACCUCMP_ERROR)
210
- result = subprocess.run(
211
- [self.python, target_file, "--help"], stdout=subprocess.PIPE, shell=False)
212
- if result.returncode == 0:
213
- self.log.info("Check [%s] success.", target_file)
214
- else:
215
- self.log.error("Check msaccucmp failed in dir %s" % target_file)
216
- self.log.error("Please specify a valid msaccucmp.py path or install the cann package")
217
- raise ParseException(ParseException.PARSE_MSACCUCMP_ERROR)
218
- return target_file
219
-
220
- def gen_npy_info_txt(self, source_data):
221
- (shape, dtype, max_data, min_data, mean) = \
222
- self.npy_info(source_data)
223
- return \
224
- '[Shape: %s] [Dtype: %s] [Max: %s] [Min: %s] [Mean: %s]' % (shape, dtype, max_data, min_data, mean)
225
-
226
- def list_convert_files(self, path, external_pattern=""):
227
- return self.list_file_with_pattern(
228
- path, Const.OFFLINE_DUMP_CONVERT_PATTERN, external_pattern, self._gen_npu_dump_convert_file_info
229
- )
230
-
231
- def list_numpy_files(self, path, extern_pattern=''):
232
- return self.list_file_with_pattern(path, Const.NUMPY_PATTERN, extern_pattern,
233
- self._gen_numpy_file_info)
234
-
235
- def create_columns(self, content):
236
- if not Columns:
237
- self.log.error("No module named rich, please install it")
238
- raise ParseException(ParseException.PARSE_NO_MODULE_ERROR)
239
- return Columns(content)
240
-
241
- def create_table(self, title, columns):
242
- if not Table:
243
- self.log.error("No module named rich, please install it and restart parse tool")
244
- raise ParseException(ParseException.PARSE_NO_MODULE_ERROR)
245
- table = Table(title=title)
246
- for column_name in columns:
247
- table.add_column(column_name, overflow='fold')
248
- return table
249
-
250
- def check_path_valid(self, path):
251
- path = self.path_strip(path)
252
- path_checker = FileChecker(path)
253
- path_checker.common_check()
254
- return True
255
-
256
- def check_files_in_path(self, path):
257
- if os.path.isdir(path) and len(os.listdir(path)) == 0:
258
- self.log.error("No files in %s." % path)
259
- raise ParseException(ParseException.PARSE_INVALID_PATH_ERROR)
260
-
261
- def npy_info(self, source_data):
262
- if isinstance(source_data, np.ndarray):
263
- data = source_data
264
- else:
265
- self.log.error("Invalid data, data is not ndarray")
266
- raise ParseException(ParseException.PARSE_INVALID_DATA_ERROR)
267
- if data.dtype == 'object':
268
- self.log.error("Invalid data, data is object.")
269
- raise ParseException(ParseException.PARSE_INVALID_DATA_ERROR)
270
- if np.size(data) == 0:
271
- self.log.error("Invalid data, data is empty")
272
- raise ParseException(ParseException.PARSE_INVALID_DATA_ERROR)
273
- npu_info_result = namedtuple('npu_info_result', ['shape', 'dtype', 'max', 'min', 'mean'])
274
- res = npu_info_result(data.shape, data.dtype, data.max(), data.min(), data.mean())
275
- return res
276
-
277
- def list_file_with_pattern(self, path, pattern, extern_pattern, gen_info_func):
278
- self.check_path_valid(path)
279
- file_list = {}
280
- re_pattern = re.compile(pattern)
281
- for dir_path, _, file_names in os.walk(path, topdown=True):
282
- path_checker = FileChecker(dir)
283
- path_checker.common_check()
284
- for name in file_names:
285
- match = re_pattern.match(name)
286
- if not match:
287
- continue
288
- if extern_pattern != '' and re_pattern.match(extern_pattern) and not re.match(extern_pattern, name):
289
- continue
290
- file_list[name] = gen_info_func(name, match, dir_path)
291
- path_depth = dir_path.count(os.sep)
292
- if path_depth <= Const.MAX_TRAVERSAL_DEPTH:
293
- yield dir_path, _, file_names
294
- else:
295
- _[:] = []
296
- return file_list
297
-
298
- def check_file_path_format(self, path, suffix):
299
- if os.path.isfile(path):
300
- if not path.endswith(suffix):
301
- self.log.error("%s is not a %s file." % (path, suffix))
302
- raise ParseException(ParseException.PARSE_INVALID_FILE_FORMAT_ERROR)
303
- elif os.path.isdir(path):
304
- self.log.error("Please specify a single file path")
305
- raise ParseException(ParseException.PARSE_INVALID_PATH_ERROR)
306
- else:
307
- self.log.error("The file path %s is invalid" % path)
308
- raise ParseException(ParseException.PARSE_INVALID_PATH_ERROR)
309
-
310
- def check_str_param(self, param):
311
- if len(param) > Const.FILE_NAME_LENGTH:
312
- self.log.error('The parameter length exceeds limit')
313
- raise ParseException(ParseException.PARSE_INVALID_PARAM_ERROR)
314
- if not re.match(Const.FILE_PATTERN, param):
315
- self.log.error('The parameter {} contains special characters.'.format(param))
316
- raise ParseException(ParseException.PARSE_INVALID_PARAM_ERROR)
317
-
318
- def is_subdir_count_equal(self, dir1, dir2):
319
- dir1_count = self.get_subdir_count(dir1)
320
- dir2_count = self.get_subdir_count(dir2)
321
- return dir1_count == dir2_count
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ # Copyright (C) 2022-2024. 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
+ import sys
20
+ import subprocess
21
+ import hashlib
22
+ import time
23
+ import numpy as np
24
+ from collections import namedtuple
25
+ from msprobe.pytorch.parse_tool.lib.config import Const
26
+ from msprobe.pytorch.parse_tool.lib.file_desc import DumpDecodeFileDesc, FileDesc
27
+ from msprobe.pytorch.parse_tool.lib.parse_exception import ParseException
28
+ from msprobe.core.common.file_utils import change_mode, check_other_user_writable,\
29
+ check_path_executable, check_path_owner_consistent
30
+ from msprobe.core.common.const import FileCheckConst
31
+ from msprobe.core.common.file_utils import check_file_or_directory_path, remove_path, check_file_type
32
+ from msprobe.pytorch.common.log import logger
33
+
34
+
35
+ try:
36
+ from rich.traceback import install
37
+ from rich.panel import Panel
38
+ from rich.table import Table
39
+ from rich import print as rich_print
40
+ from rich.columns import Columns
41
+
42
+ install()
43
+ except ImportError as err:
44
+ install = None
45
+ Panel = None
46
+ Table = None
47
+ Columns = None
48
+ rich_print = None
49
+ logger.warning(
50
+ "Failed to import rich, Some features may not be available. Please run 'pip install rich' to fix it.")
51
+
52
+
53
+ class Util:
54
+ def __init__(self):
55
+ self.ms_accu_cmp = None
56
+ self.log = logger
57
+ self.python = sys.executable
58
+
59
+ @staticmethod
60
+ def print(content):
61
+ rich_print(content)
62
+
63
+ @staticmethod
64
+ def path_strip(path):
65
+ return path.strip("'").strip('"')
66
+
67
+ @staticmethod
68
+ def check_executable_file(path):
69
+ check_path_owner_consistent(path)
70
+ check_other_user_writable(path)
71
+ check_path_executable(path)
72
+
73
+ @staticmethod
74
+ def get_subdir_count(directory):
75
+ subdir_count = 0
76
+ check_file_or_directory_path(directory, isdir=True)
77
+ for _, dirs, _ in os.walk(directory):
78
+ subdir_count += len(dirs)
79
+ break
80
+ return subdir_count
81
+
82
+ @staticmethod
83
+ def get_subfiles_count(directory):
84
+ file_count = 0
85
+ for root, _, files in os.walk(directory, topdown=True):
86
+ check_file_or_directory_path(root, isdir=True)
87
+ file_count += len(files)
88
+ path_depth = root.count(os.sep)
89
+ if path_depth <= Const.MAX_TRAVERSAL_DEPTH:
90
+ yield root, _, files
91
+ else:
92
+ _[:] = []
93
+ return file_count
94
+
95
+ @staticmethod
96
+ def get_sorted_subdirectories_names(directory):
97
+ subdirectories = []
98
+ for item in os.listdir(directory):
99
+ item_path = os.path.join(directory, item)
100
+ if os.path.isdir(item_path):
101
+ subdirectories.append(item)
102
+ return sorted(subdirectories)
103
+
104
+ @staticmethod
105
+ def get_sorted_files_names(directory):
106
+ files = []
107
+ for item in os.listdir(directory):
108
+ item_path = os.path.join(directory, item)
109
+ if os.path.isfile(item_path):
110
+ files.append(item)
111
+ return sorted(files)
112
+
113
+ @staticmethod
114
+ def check_npy_files_valid_in_dir(dir_path):
115
+ for file_name in os.listdir(dir_path):
116
+ file_path = os.path.join(dir_path, file_name)
117
+ check_file_or_directory_path(file_path)
118
+ _, file_extension = os.path.splitext(file_path)
119
+ if not file_extension == '.npy':
120
+ return False
121
+ return True
122
+
123
+ @staticmethod
124
+ def get_md5_for_numpy(obj):
125
+ np_bytes = obj.tobytes()
126
+ md5_hash = hashlib.md5(np_bytes)
127
+ return md5_hash.hexdigest()
128
+
129
+ @staticmethod
130
+ def deal_with_dir_or_file_inconsistency(output_path):
131
+ remove_path(output_path)
132
+ raise ParseException("Inconsistent directory structure or file.")
133
+
134
+ @staticmethod
135
+ def deal_with_value_if_has_zero(data):
136
+ if data.dtype in Const.FLOAT_TYPE:
137
+ zero_mask = (data == 0)
138
+ # 给0的地方加上eps防止除0
139
+ data[zero_mask] += np.finfo(data.dtype).eps
140
+ else:
141
+ # int type + float eps 会报错,所以这里要强转
142
+ data = data.astype(float)
143
+ zero_mask = (data == 0)
144
+ data[zero_mask] += np.finfo(float).eps
145
+ return data
146
+
147
+ @staticmethod
148
+ def dir_contains_only(path, endfix):
149
+ for root, _, files in os.walk(path, topdown=True):
150
+ check_file_or_directory_path(root, isdir=True)
151
+ for file in files:
152
+ if not file.endswith(endfix):
153
+ return False
154
+ path_depth = root.count(os.sep)
155
+ if path_depth <= Const.MAX_TRAVERSAL_DEPTH:
156
+ yield root, _, files
157
+ else:
158
+ _[:] = []
159
+ return True
160
+
161
+ @staticmethod
162
+ def localtime_str():
163
+ return time.strftime("%Y%m%d%H%M%S", time.localtime())
164
+
165
+ @staticmethod
166
+ def change_filemode_safe(path):
167
+ change_mode(path, FileCheckConst.DATA_FILE_AUTHORITY)
168
+
169
+ @staticmethod
170
+ def _gen_npu_dump_convert_file_info(name, match, dir_path):
171
+ return DumpDecodeFileDesc(name, dir_path, int(match.groups()[-4]), op_name=match.group(2),
172
+ op_type=match.group(1), task_id=int(match.group(3)), anchor_type=match.groups()[-3],
173
+ anchor_idx=int(match.groups()[-2]))
174
+
175
+ @staticmethod
176
+ def _gen_numpy_file_info(name, math, dir_path):
177
+ return FileDesc(name, dir_path)
178
+
179
+ def execute_command(self, cmd):
180
+ if not cmd:
181
+ self.log.error("Commond is None")
182
+ return -1
183
+ self.log.info("[RUN CMD]: %s" % cmd)
184
+ cmd = cmd.split(" ")
185
+ complete_process = subprocess.run(cmd, shell=False)
186
+ return complete_process.returncode
187
+
188
+ def print_panel(self, content, title='', fit=True):
189
+ if not Panel:
190
+ self.print(content)
191
+ return
192
+ if fit:
193
+ self.print(Panel.fit(content, title=title))
194
+ else:
195
+ self.print(Panel(content, title=title))
196
+
197
+ def check_msaccucmp(self, target_file):
198
+ if os.path.split(target_file)[-1] != Const.MS_ACCU_CMP_FILE_NAME:
199
+ self.log.error(
200
+ "Check msaccucmp failed in dir %s. This is not a correct msaccucmp file" % target_file)
201
+ raise ParseException(ParseException.PARSE_MSACCUCMP_ERROR)
202
+ result = subprocess.run(
203
+ [self.python, target_file, "--help"], stdout=subprocess.PIPE, shell=False)
204
+ if result.returncode == 0:
205
+ self.log.info("Check [%s] success." % (target_file))
206
+ else:
207
+ self.log.error("Check msaccucmp failed in dir %s" % target_file)
208
+ self.log.error("Please specify a valid msaccucmp.py path or install the cann package")
209
+ raise ParseException(ParseException.PARSE_MSACCUCMP_ERROR)
210
+ return target_file
211
+
212
+ def gen_npy_info_txt(self, source_data):
213
+ (shape, dtype, max_data, min_data, mean) = \
214
+ self.npy_info(source_data)
215
+ return \
216
+ '[Shape: %s] [Dtype: %s] [Max: %s] [Min: %s] [Mean: %s]' % (shape, dtype, max_data, min_data, mean)
217
+
218
+ def list_convert_files(self, path, external_pattern=""):
219
+ return self.list_file_with_pattern(
220
+ path, Const.OFFLINE_DUMP_CONVERT_PATTERN, external_pattern, self._gen_npu_dump_convert_file_info
221
+ )
222
+
223
+ def list_numpy_files(self, path, extern_pattern=''):
224
+ return self.list_file_with_pattern(path, Const.NUMPY_PATTERN, extern_pattern,
225
+ self._gen_numpy_file_info)
226
+
227
+ def create_columns(self, content):
228
+ if not Columns:
229
+ self.log.error("No module named rich, please install it")
230
+ raise ParseException(ParseException.PARSE_NO_MODULE_ERROR)
231
+ return Columns(content)
232
+
233
+ def create_table(self, title, columns):
234
+ if not Table:
235
+ self.log.error("No module named rich, please install it and restart parse tool")
236
+ raise ParseException(ParseException.PARSE_NO_MODULE_ERROR)
237
+ table = Table(title=title)
238
+ for column_name in columns:
239
+ table.add_column(column_name, overflow='fold')
240
+ return table
241
+
242
+ def check_path_valid(self, path):
243
+ path = self.path_strip(path)
244
+ if not path or not os.path.exists(path):
245
+ self.log.error("The path %s does not exist." % path)
246
+ raise ParseException(ParseException.PARSE_INVALID_PATH_ERROR)
247
+ isdir = check_file_type(path) == FileCheckConst.DIR
248
+ check_file_or_directory_path(path, isdir=isdir)
249
+ return True
250
+
251
+ def check_files_in_path(self, path):
252
+ if os.path.isdir(path) and len(os.listdir(path)) == 0:
253
+ self.log.error("No files in %s." % path)
254
+ raise ParseException(ParseException.PARSE_INVALID_PATH_ERROR)
255
+
256
+ def npy_info(self, source_data):
257
+ if isinstance(source_data, np.ndarray):
258
+ data = source_data
259
+ else:
260
+ self.log.error("Invalid data, data is not ndarray")
261
+ raise ParseException(ParseException.PARSE_INVALID_DATA_ERROR)
262
+ if data.dtype == 'object':
263
+ self.log.error("Invalid data, data is object.")
264
+ raise ParseException(ParseException.PARSE_INVALID_DATA_ERROR)
265
+ if np.size(data) == 0:
266
+ self.log.error("Invalid data, data is empty")
267
+ raise ParseException(ParseException.PARSE_INVALID_DATA_ERROR)
268
+ npu_info_result = namedtuple('npu_info_result', ['shape', 'dtype', 'max', 'min', 'mean'])
269
+ res = npu_info_result(data.shape, data.dtype, data.max(), data.min(), data.mean())
270
+ return res
271
+
272
+ def list_file_with_pattern(self, path, pattern, extern_pattern, gen_info_func):
273
+ self.check_path_valid(path)
274
+ file_list = {}
275
+ re_pattern = re.compile(pattern)
276
+ for dir_path, _, file_names in os.walk(path, topdown=True):
277
+ check_file_or_directory_path(dir_path, isdir=True)
278
+ for name in file_names:
279
+ match = re_pattern.match(name)
280
+ if not match:
281
+ continue
282
+ if extern_pattern != '' and re_pattern.match(extern_pattern) and not re.match(extern_pattern, name):
283
+ continue
284
+ file_list[name] = gen_info_func(name, match, dir_path)
285
+ path_depth = dir_path.count(os.sep)
286
+ if path_depth <= Const.MAX_TRAVERSAL_DEPTH:
287
+ yield dir_path, _, file_names
288
+ else:
289
+ _[:] = []
290
+ return file_list
291
+
292
+ def check_file_path_format(self, path, suffix):
293
+ if os.path.isfile(path):
294
+ if not path.endswith(suffix):
295
+ self.log.error("%s is not a %s file." % (path, suffix))
296
+ raise ParseException(ParseException.PARSE_INVALID_FILE_FORMAT_ERROR)
297
+ elif os.path.isdir(path):
298
+ self.log.error("Please specify a single file path")
299
+ raise ParseException(ParseException.PARSE_INVALID_PATH_ERROR)
300
+ else:
301
+ self.log.error("The file path %s is invalid" % path)
302
+ raise ParseException(ParseException.PARSE_INVALID_PATH_ERROR)
303
+
304
+ def check_str_param(self, param):
305
+ if len(param) > Const.FILE_NAME_LENGTH:
306
+ self.log.error('The parameter length exceeds limit')
307
+ raise ParseException(ParseException.PARSE_INVALID_PARAM_ERROR)
308
+ if not re.match(Const.FILE_PATTERN, param):
309
+ self.log.error('The parameter {} contains special characters.'.format(param))
310
+ raise ParseException(ParseException.PARSE_INVALID_PARAM_ERROR)
311
+
312
+ def is_subdir_count_equal(self, dir1, dir2):
313
+ dir1_count = self.get_subdir_count(dir1)
314
+ dir2_count = self.get_subdir_count(dir2)
315
+ return dir1_count == dir2_count
316
+
317
+ def check_positive(self, value):
318
+ if value <= 0.0:
319
+ self.log.error("Invalid value. It must be greater than 0.")
320
+ raise ParseException(ParseException.PARSE_INVALID_DATA_ERROR)