pyxllib 0.3.96__py3-none-any.whl → 0.3.200__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 (358) hide show
  1. pyxllib/__init__.py +21 -21
  2. pyxllib/algo/__init__.py +8 -8
  3. pyxllib/algo/disjoint.py +54 -54
  4. pyxllib/algo/geo.py +541 -529
  5. pyxllib/algo/intervals.py +964 -964
  6. pyxllib/algo/matcher.py +389 -311
  7. pyxllib/algo/newbie.py +166 -166
  8. pyxllib/algo/pupil.py +629 -461
  9. pyxllib/algo/shapelylib.py +67 -67
  10. pyxllib/algo/specialist.py +241 -240
  11. pyxllib/algo/stat.py +494 -458
  12. pyxllib/algo/treelib.py +149 -149
  13. pyxllib/algo/unitlib.py +66 -66
  14. {pyxlpr → pyxllib/autogui}/__init__.py +5 -5
  15. pyxllib/autogui/activewin.py +246 -0
  16. pyxllib/autogui/all.py +9 -0
  17. pyxllib/{ext/autogui → autogui}/autogui.py +852 -823
  18. pyxllib/autogui/uiautolib.py +362 -0
  19. pyxllib/{ext/autogui → autogui}/virtualkey.py +102 -102
  20. pyxllib/autogui/wechat.py +827 -0
  21. pyxllib/autogui/wechat_msg.py +421 -0
  22. pyxllib/autogui/wxautolib.py +84 -0
  23. pyxllib/cv/__init__.py +5 -5
  24. pyxllib/cv/expert.py +267 -267
  25. pyxllib/cv/imfile.py +159 -159
  26. pyxllib/cv/imhash.py +39 -39
  27. pyxllib/cv/pupil.py +9 -9
  28. pyxllib/cv/rgbfmt.py +1525 -1525
  29. pyxllib/cv/slidercaptcha.py +137 -0
  30. pyxllib/cv/trackbartools.py +251 -251
  31. pyxllib/cv/xlcvlib.py +1040 -1040
  32. pyxllib/cv/xlpillib.py +423 -423
  33. pyxllib/data/echarts.py +240 -129
  34. pyxllib/data/jsonlib.py +89 -0
  35. pyxllib/data/oss.py +72 -72
  36. pyxllib/data/pglib.py +1127 -643
  37. pyxllib/data/sqlite.py +568 -341
  38. pyxllib/data/sqllib.py +297 -297
  39. pyxllib/ext/JLineViewer.py +505 -492
  40. pyxllib/ext/__init__.py +6 -6
  41. pyxllib/ext/demolib.py +246 -246
  42. pyxllib/ext/drissionlib.py +277 -0
  43. pyxllib/ext/kq5034lib.py +12 -1606
  44. pyxllib/ext/old.py +663 -663
  45. pyxllib/ext/qt.py +449 -449
  46. pyxllib/ext/robustprocfile.py +497 -0
  47. pyxllib/ext/seleniumlib.py +76 -76
  48. pyxllib/ext/tk.py +173 -173
  49. pyxllib/ext/unixlib.py +827 -826
  50. pyxllib/ext/utools.py +351 -338
  51. pyxllib/ext/webhook.py +124 -101
  52. pyxllib/ext/win32lib.py +40 -40
  53. pyxllib/ext/wjxlib.py +88 -0
  54. pyxllib/ext/wpsapi.py +124 -0
  55. pyxllib/ext/xlwork.py +9 -0
  56. pyxllib/ext/yuquelib.py +1105 -173
  57. pyxllib/file/__init__.py +17 -17
  58. pyxllib/file/docxlib.py +761 -761
  59. pyxllib/file/gitlib.py +309 -309
  60. pyxllib/file/libreoffice.py +165 -0
  61. pyxllib/file/movielib.py +148 -139
  62. pyxllib/file/newbie.py +10 -10
  63. pyxllib/file/onenotelib.py +1469 -1469
  64. pyxllib/file/packlib/__init__.py +330 -293
  65. pyxllib/file/packlib/zipfile.py +2441 -2441
  66. pyxllib/file/pdflib.py +426 -426
  67. pyxllib/file/pupil.py +185 -185
  68. pyxllib/file/specialist/__init__.py +685 -685
  69. pyxllib/file/specialist/dirlib.py +799 -799
  70. pyxllib/file/specialist/download.py +193 -186
  71. pyxllib/file/specialist/filelib.py +2829 -2618
  72. pyxllib/file/xlsxlib.py +3131 -2976
  73. pyxllib/file/xlsyncfile.py +341 -0
  74. pyxllib/prog/__init__.py +5 -5
  75. pyxllib/prog/cachetools.py +64 -0
  76. pyxllib/prog/deprecatedlib.py +233 -233
  77. pyxllib/prog/filelock.py +42 -0
  78. pyxllib/prog/ipyexec.py +253 -253
  79. pyxllib/prog/multiprogs.py +940 -0
  80. pyxllib/prog/newbie.py +451 -444
  81. pyxllib/prog/pupil.py +1197 -1128
  82. pyxllib/prog/sitepackages.py +33 -33
  83. pyxllib/prog/specialist/__init__.py +391 -217
  84. pyxllib/prog/specialist/bc.py +203 -200
  85. pyxllib/prog/specialist/browser.py +497 -488
  86. pyxllib/prog/specialist/common.py +347 -347
  87. pyxllib/prog/specialist/datetime.py +199 -131
  88. pyxllib/prog/specialist/tictoc.py +240 -241
  89. pyxllib/prog/specialist/xllog.py +180 -180
  90. pyxllib/prog/xlosenv.py +108 -101
  91. pyxllib/stdlib/__init__.py +17 -17
  92. pyxllib/stdlib/tablepyxl/__init__.py +10 -10
  93. pyxllib/stdlib/tablepyxl/style.py +303 -303
  94. pyxllib/stdlib/tablepyxl/tablepyxl.py +130 -130
  95. pyxllib/text/__init__.py +8 -8
  96. pyxllib/text/ahocorasick.py +39 -39
  97. pyxllib/text/airscript.js +744 -0
  98. pyxllib/text/charclasslib.py +121 -109
  99. pyxllib/text/jiebalib.py +267 -264
  100. pyxllib/text/jinjalib.py +32 -0
  101. pyxllib/text/jsa_ai_prompt.md +271 -0
  102. pyxllib/text/jscode.py +922 -767
  103. pyxllib/text/latex/__init__.py +158 -158
  104. pyxllib/text/levenshtein.py +303 -303
  105. pyxllib/text/nestenv.py +1215 -1215
  106. pyxllib/text/newbie.py +300 -288
  107. pyxllib/text/pupil/__init__.py +8 -8
  108. pyxllib/text/pupil/common.py +1121 -1095
  109. pyxllib/text/pupil/xlalign.py +326 -326
  110. pyxllib/text/pycode.py +47 -47
  111. pyxllib/text/specialist/__init__.py +8 -8
  112. pyxllib/text/specialist/common.py +112 -112
  113. pyxllib/text/specialist/ptag.py +186 -186
  114. pyxllib/text/spellchecker.py +172 -172
  115. pyxllib/text/templates/echart_base.html +11 -0
  116. pyxllib/text/templates/highlight_code.html +17 -0
  117. pyxllib/text/templates/latex_editor.html +103 -0
  118. pyxllib/text/vbacode.py +17 -17
  119. pyxllib/text/xmllib.py +747 -685
  120. pyxllib/xl.py +42 -38
  121. pyxllib/xlcv.py +17 -17
  122. pyxllib-0.3.200.dist-info/METADATA +48 -0
  123. pyxllib-0.3.200.dist-info/RECORD +126 -0
  124. {pyxllib-0.3.96.dist-info → pyxllib-0.3.200.dist-info}/WHEEL +1 -2
  125. {pyxllib-0.3.96.dist-info → pyxllib-0.3.200.dist-info/licenses}/LICENSE +190 -190
  126. pyxllib/ext/autogui/__init__.py +0 -8
  127. pyxllib-0.3.96.dist-info/METADATA +0 -51
  128. pyxllib-0.3.96.dist-info/RECORD +0 -333
  129. pyxllib-0.3.96.dist-info/top_level.txt +0 -2
  130. pyxlpr/ai/__init__.py +0 -5
  131. pyxlpr/ai/clientlib.py +0 -1281
  132. pyxlpr/ai/specialist.py +0 -286
  133. pyxlpr/ai/torch_app.py +0 -172
  134. pyxlpr/ai/xlpaddle.py +0 -655
  135. pyxlpr/ai/xltorch.py +0 -705
  136. pyxlpr/data/__init__.py +0 -11
  137. pyxlpr/data/coco.py +0 -1325
  138. pyxlpr/data/datacls.py +0 -365
  139. pyxlpr/data/datasets.py +0 -200
  140. pyxlpr/data/gptlib.py +0 -1291
  141. pyxlpr/data/icdar/__init__.py +0 -96
  142. pyxlpr/data/icdar/deteval.py +0 -377
  143. pyxlpr/data/icdar/icdar2013.py +0 -341
  144. pyxlpr/data/icdar/iou.py +0 -340
  145. pyxlpr/data/icdar/rrc_evaluation_funcs_1_1.py +0 -463
  146. pyxlpr/data/imtextline.py +0 -473
  147. pyxlpr/data/labelme.py +0 -866
  148. pyxlpr/data/removeline.py +0 -179
  149. pyxlpr/data/specialist.py +0 -57
  150. pyxlpr/eval/__init__.py +0 -85
  151. pyxlpr/paddleocr.py +0 -776
  152. pyxlpr/ppocr/__init__.py +0 -15
  153. pyxlpr/ppocr/configs/rec/multi_language/generate_multi_language_configs.py +0 -226
  154. pyxlpr/ppocr/data/__init__.py +0 -135
  155. pyxlpr/ppocr/data/imaug/ColorJitter.py +0 -26
  156. pyxlpr/ppocr/data/imaug/__init__.py +0 -67
  157. pyxlpr/ppocr/data/imaug/copy_paste.py +0 -170
  158. pyxlpr/ppocr/data/imaug/east_process.py +0 -437
  159. pyxlpr/ppocr/data/imaug/gen_table_mask.py +0 -244
  160. pyxlpr/ppocr/data/imaug/iaa_augment.py +0 -114
  161. pyxlpr/ppocr/data/imaug/label_ops.py +0 -789
  162. pyxlpr/ppocr/data/imaug/make_border_map.py +0 -184
  163. pyxlpr/ppocr/data/imaug/make_pse_gt.py +0 -106
  164. pyxlpr/ppocr/data/imaug/make_shrink_map.py +0 -126
  165. pyxlpr/ppocr/data/imaug/operators.py +0 -433
  166. pyxlpr/ppocr/data/imaug/pg_process.py +0 -906
  167. pyxlpr/ppocr/data/imaug/randaugment.py +0 -143
  168. pyxlpr/ppocr/data/imaug/random_crop_data.py +0 -239
  169. pyxlpr/ppocr/data/imaug/rec_img_aug.py +0 -533
  170. pyxlpr/ppocr/data/imaug/sast_process.py +0 -777
  171. pyxlpr/ppocr/data/imaug/text_image_aug/__init__.py +0 -17
  172. pyxlpr/ppocr/data/imaug/text_image_aug/augment.py +0 -120
  173. pyxlpr/ppocr/data/imaug/text_image_aug/warp_mls.py +0 -168
  174. pyxlpr/ppocr/data/lmdb_dataset.py +0 -115
  175. pyxlpr/ppocr/data/pgnet_dataset.py +0 -104
  176. pyxlpr/ppocr/data/pubtab_dataset.py +0 -107
  177. pyxlpr/ppocr/data/simple_dataset.py +0 -372
  178. pyxlpr/ppocr/losses/__init__.py +0 -61
  179. pyxlpr/ppocr/losses/ace_loss.py +0 -52
  180. pyxlpr/ppocr/losses/basic_loss.py +0 -135
  181. pyxlpr/ppocr/losses/center_loss.py +0 -88
  182. pyxlpr/ppocr/losses/cls_loss.py +0 -30
  183. pyxlpr/ppocr/losses/combined_loss.py +0 -67
  184. pyxlpr/ppocr/losses/det_basic_loss.py +0 -208
  185. pyxlpr/ppocr/losses/det_db_loss.py +0 -80
  186. pyxlpr/ppocr/losses/det_east_loss.py +0 -63
  187. pyxlpr/ppocr/losses/det_pse_loss.py +0 -149
  188. pyxlpr/ppocr/losses/det_sast_loss.py +0 -121
  189. pyxlpr/ppocr/losses/distillation_loss.py +0 -272
  190. pyxlpr/ppocr/losses/e2e_pg_loss.py +0 -140
  191. pyxlpr/ppocr/losses/kie_sdmgr_loss.py +0 -113
  192. pyxlpr/ppocr/losses/rec_aster_loss.py +0 -99
  193. pyxlpr/ppocr/losses/rec_att_loss.py +0 -39
  194. pyxlpr/ppocr/losses/rec_ctc_loss.py +0 -44
  195. pyxlpr/ppocr/losses/rec_enhanced_ctc_loss.py +0 -70
  196. pyxlpr/ppocr/losses/rec_nrtr_loss.py +0 -30
  197. pyxlpr/ppocr/losses/rec_sar_loss.py +0 -28
  198. pyxlpr/ppocr/losses/rec_srn_loss.py +0 -47
  199. pyxlpr/ppocr/losses/table_att_loss.py +0 -109
  200. pyxlpr/ppocr/metrics/__init__.py +0 -44
  201. pyxlpr/ppocr/metrics/cls_metric.py +0 -45
  202. pyxlpr/ppocr/metrics/det_metric.py +0 -82
  203. pyxlpr/ppocr/metrics/distillation_metric.py +0 -73
  204. pyxlpr/ppocr/metrics/e2e_metric.py +0 -86
  205. pyxlpr/ppocr/metrics/eval_det_iou.py +0 -274
  206. pyxlpr/ppocr/metrics/kie_metric.py +0 -70
  207. pyxlpr/ppocr/metrics/rec_metric.py +0 -75
  208. pyxlpr/ppocr/metrics/table_metric.py +0 -50
  209. pyxlpr/ppocr/modeling/architectures/__init__.py +0 -32
  210. pyxlpr/ppocr/modeling/architectures/base_model.py +0 -88
  211. pyxlpr/ppocr/modeling/architectures/distillation_model.py +0 -60
  212. pyxlpr/ppocr/modeling/backbones/__init__.py +0 -54
  213. pyxlpr/ppocr/modeling/backbones/det_mobilenet_v3.py +0 -268
  214. pyxlpr/ppocr/modeling/backbones/det_resnet_vd.py +0 -246
  215. pyxlpr/ppocr/modeling/backbones/det_resnet_vd_sast.py +0 -285
  216. pyxlpr/ppocr/modeling/backbones/e2e_resnet_vd_pg.py +0 -265
  217. pyxlpr/ppocr/modeling/backbones/kie_unet_sdmgr.py +0 -186
  218. pyxlpr/ppocr/modeling/backbones/rec_mobilenet_v3.py +0 -138
  219. pyxlpr/ppocr/modeling/backbones/rec_mv1_enhance.py +0 -258
  220. pyxlpr/ppocr/modeling/backbones/rec_nrtr_mtb.py +0 -48
  221. pyxlpr/ppocr/modeling/backbones/rec_resnet_31.py +0 -210
  222. pyxlpr/ppocr/modeling/backbones/rec_resnet_aster.py +0 -143
  223. pyxlpr/ppocr/modeling/backbones/rec_resnet_fpn.py +0 -307
  224. pyxlpr/ppocr/modeling/backbones/rec_resnet_vd.py +0 -286
  225. pyxlpr/ppocr/modeling/heads/__init__.py +0 -54
  226. pyxlpr/ppocr/modeling/heads/cls_head.py +0 -52
  227. pyxlpr/ppocr/modeling/heads/det_db_head.py +0 -118
  228. pyxlpr/ppocr/modeling/heads/det_east_head.py +0 -121
  229. pyxlpr/ppocr/modeling/heads/det_pse_head.py +0 -37
  230. pyxlpr/ppocr/modeling/heads/det_sast_head.py +0 -128
  231. pyxlpr/ppocr/modeling/heads/e2e_pg_head.py +0 -253
  232. pyxlpr/ppocr/modeling/heads/kie_sdmgr_head.py +0 -206
  233. pyxlpr/ppocr/modeling/heads/multiheadAttention.py +0 -163
  234. pyxlpr/ppocr/modeling/heads/rec_aster_head.py +0 -393
  235. pyxlpr/ppocr/modeling/heads/rec_att_head.py +0 -202
  236. pyxlpr/ppocr/modeling/heads/rec_ctc_head.py +0 -88
  237. pyxlpr/ppocr/modeling/heads/rec_nrtr_head.py +0 -826
  238. pyxlpr/ppocr/modeling/heads/rec_sar_head.py +0 -402
  239. pyxlpr/ppocr/modeling/heads/rec_srn_head.py +0 -280
  240. pyxlpr/ppocr/modeling/heads/self_attention.py +0 -406
  241. pyxlpr/ppocr/modeling/heads/table_att_head.py +0 -246
  242. pyxlpr/ppocr/modeling/necks/__init__.py +0 -32
  243. pyxlpr/ppocr/modeling/necks/db_fpn.py +0 -111
  244. pyxlpr/ppocr/modeling/necks/east_fpn.py +0 -188
  245. pyxlpr/ppocr/modeling/necks/fpn.py +0 -138
  246. pyxlpr/ppocr/modeling/necks/pg_fpn.py +0 -314
  247. pyxlpr/ppocr/modeling/necks/rnn.py +0 -92
  248. pyxlpr/ppocr/modeling/necks/sast_fpn.py +0 -284
  249. pyxlpr/ppocr/modeling/necks/table_fpn.py +0 -110
  250. pyxlpr/ppocr/modeling/transforms/__init__.py +0 -28
  251. pyxlpr/ppocr/modeling/transforms/stn.py +0 -135
  252. pyxlpr/ppocr/modeling/transforms/tps.py +0 -308
  253. pyxlpr/ppocr/modeling/transforms/tps_spatial_transformer.py +0 -156
  254. pyxlpr/ppocr/optimizer/__init__.py +0 -61
  255. pyxlpr/ppocr/optimizer/learning_rate.py +0 -228
  256. pyxlpr/ppocr/optimizer/lr_scheduler.py +0 -49
  257. pyxlpr/ppocr/optimizer/optimizer.py +0 -160
  258. pyxlpr/ppocr/optimizer/regularizer.py +0 -52
  259. pyxlpr/ppocr/postprocess/__init__.py +0 -55
  260. pyxlpr/ppocr/postprocess/cls_postprocess.py +0 -33
  261. pyxlpr/ppocr/postprocess/db_postprocess.py +0 -234
  262. pyxlpr/ppocr/postprocess/east_postprocess.py +0 -143
  263. pyxlpr/ppocr/postprocess/locality_aware_nms.py +0 -200
  264. pyxlpr/ppocr/postprocess/pg_postprocess.py +0 -52
  265. pyxlpr/ppocr/postprocess/pse_postprocess/__init__.py +0 -15
  266. pyxlpr/ppocr/postprocess/pse_postprocess/pse/__init__.py +0 -29
  267. pyxlpr/ppocr/postprocess/pse_postprocess/pse/setup.py +0 -14
  268. pyxlpr/ppocr/postprocess/pse_postprocess/pse_postprocess.py +0 -118
  269. pyxlpr/ppocr/postprocess/rec_postprocess.py +0 -654
  270. pyxlpr/ppocr/postprocess/sast_postprocess.py +0 -355
  271. pyxlpr/ppocr/tools/__init__.py +0 -14
  272. pyxlpr/ppocr/tools/eval.py +0 -83
  273. pyxlpr/ppocr/tools/export_center.py +0 -77
  274. pyxlpr/ppocr/tools/export_model.py +0 -129
  275. pyxlpr/ppocr/tools/infer/predict_cls.py +0 -151
  276. pyxlpr/ppocr/tools/infer/predict_det.py +0 -300
  277. pyxlpr/ppocr/tools/infer/predict_e2e.py +0 -169
  278. pyxlpr/ppocr/tools/infer/predict_rec.py +0 -414
  279. pyxlpr/ppocr/tools/infer/predict_system.py +0 -204
  280. pyxlpr/ppocr/tools/infer/utility.py +0 -629
  281. pyxlpr/ppocr/tools/infer_cls.py +0 -83
  282. pyxlpr/ppocr/tools/infer_det.py +0 -134
  283. pyxlpr/ppocr/tools/infer_e2e.py +0 -122
  284. pyxlpr/ppocr/tools/infer_kie.py +0 -153
  285. pyxlpr/ppocr/tools/infer_rec.py +0 -146
  286. pyxlpr/ppocr/tools/infer_table.py +0 -107
  287. pyxlpr/ppocr/tools/program.py +0 -596
  288. pyxlpr/ppocr/tools/test_hubserving.py +0 -117
  289. pyxlpr/ppocr/tools/train.py +0 -163
  290. pyxlpr/ppocr/tools/xlprog.py +0 -748
  291. pyxlpr/ppocr/utils/EN_symbol_dict.txt +0 -94
  292. pyxlpr/ppocr/utils/__init__.py +0 -24
  293. pyxlpr/ppocr/utils/dict/ar_dict.txt +0 -117
  294. pyxlpr/ppocr/utils/dict/arabic_dict.txt +0 -162
  295. pyxlpr/ppocr/utils/dict/be_dict.txt +0 -145
  296. pyxlpr/ppocr/utils/dict/bg_dict.txt +0 -140
  297. pyxlpr/ppocr/utils/dict/chinese_cht_dict.txt +0 -8421
  298. pyxlpr/ppocr/utils/dict/cyrillic_dict.txt +0 -163
  299. pyxlpr/ppocr/utils/dict/devanagari_dict.txt +0 -167
  300. pyxlpr/ppocr/utils/dict/en_dict.txt +0 -63
  301. pyxlpr/ppocr/utils/dict/fa_dict.txt +0 -136
  302. pyxlpr/ppocr/utils/dict/french_dict.txt +0 -136
  303. pyxlpr/ppocr/utils/dict/german_dict.txt +0 -143
  304. pyxlpr/ppocr/utils/dict/hi_dict.txt +0 -162
  305. pyxlpr/ppocr/utils/dict/it_dict.txt +0 -118
  306. pyxlpr/ppocr/utils/dict/japan_dict.txt +0 -4399
  307. pyxlpr/ppocr/utils/dict/ka_dict.txt +0 -153
  308. pyxlpr/ppocr/utils/dict/korean_dict.txt +0 -3688
  309. pyxlpr/ppocr/utils/dict/latin_dict.txt +0 -185
  310. pyxlpr/ppocr/utils/dict/mr_dict.txt +0 -153
  311. pyxlpr/ppocr/utils/dict/ne_dict.txt +0 -153
  312. pyxlpr/ppocr/utils/dict/oc_dict.txt +0 -96
  313. pyxlpr/ppocr/utils/dict/pu_dict.txt +0 -130
  314. pyxlpr/ppocr/utils/dict/rs_dict.txt +0 -91
  315. pyxlpr/ppocr/utils/dict/rsc_dict.txt +0 -134
  316. pyxlpr/ppocr/utils/dict/ru_dict.txt +0 -125
  317. pyxlpr/ppocr/utils/dict/ta_dict.txt +0 -128
  318. pyxlpr/ppocr/utils/dict/table_dict.txt +0 -277
  319. pyxlpr/ppocr/utils/dict/table_structure_dict.txt +0 -2759
  320. pyxlpr/ppocr/utils/dict/te_dict.txt +0 -151
  321. pyxlpr/ppocr/utils/dict/ug_dict.txt +0 -114
  322. pyxlpr/ppocr/utils/dict/uk_dict.txt +0 -142
  323. pyxlpr/ppocr/utils/dict/ur_dict.txt +0 -137
  324. pyxlpr/ppocr/utils/dict/xi_dict.txt +0 -110
  325. pyxlpr/ppocr/utils/dict90.txt +0 -90
  326. pyxlpr/ppocr/utils/e2e_metric/Deteval.py +0 -574
  327. pyxlpr/ppocr/utils/e2e_metric/polygon_fast.py +0 -83
  328. pyxlpr/ppocr/utils/e2e_utils/extract_batchsize.py +0 -87
  329. pyxlpr/ppocr/utils/e2e_utils/extract_textpoint_fast.py +0 -457
  330. pyxlpr/ppocr/utils/e2e_utils/extract_textpoint_slow.py +0 -592
  331. pyxlpr/ppocr/utils/e2e_utils/pgnet_pp_utils.py +0 -162
  332. pyxlpr/ppocr/utils/e2e_utils/visual.py +0 -162
  333. pyxlpr/ppocr/utils/en_dict.txt +0 -95
  334. pyxlpr/ppocr/utils/gen_label.py +0 -81
  335. pyxlpr/ppocr/utils/ic15_dict.txt +0 -36
  336. pyxlpr/ppocr/utils/iou.py +0 -54
  337. pyxlpr/ppocr/utils/logging.py +0 -69
  338. pyxlpr/ppocr/utils/network.py +0 -84
  339. pyxlpr/ppocr/utils/ppocr_keys_v1.txt +0 -6623
  340. pyxlpr/ppocr/utils/profiler.py +0 -110
  341. pyxlpr/ppocr/utils/save_load.py +0 -150
  342. pyxlpr/ppocr/utils/stats.py +0 -72
  343. pyxlpr/ppocr/utils/utility.py +0 -80
  344. pyxlpr/ppstructure/__init__.py +0 -13
  345. pyxlpr/ppstructure/predict_system.py +0 -187
  346. pyxlpr/ppstructure/table/__init__.py +0 -13
  347. pyxlpr/ppstructure/table/eval_table.py +0 -72
  348. pyxlpr/ppstructure/table/matcher.py +0 -192
  349. pyxlpr/ppstructure/table/predict_structure.py +0 -136
  350. pyxlpr/ppstructure/table/predict_table.py +0 -221
  351. pyxlpr/ppstructure/table/table_metric/__init__.py +0 -16
  352. pyxlpr/ppstructure/table/table_metric/parallel.py +0 -51
  353. pyxlpr/ppstructure/table/table_metric/table_metric.py +0 -247
  354. pyxlpr/ppstructure/table/tablepyxl/__init__.py +0 -13
  355. pyxlpr/ppstructure/table/tablepyxl/style.py +0 -283
  356. pyxlpr/ppstructure/table/tablepyxl/tablepyxl.py +0 -118
  357. pyxlpr/ppstructure/utility.py +0 -71
  358. pyxlpr/xlai.py +0 -10
@@ -1,293 +1,330 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- # @Author : 陈坤泽
4
- # @Email : 877362867@qq.com
5
- # @Date : 2022/02/15 09:51
6
-
7
- import os
8
- import shutil
9
- from tarfile import TarFile
10
- # 这个包里的ZipFile是拷贝后修改过的,不影响标准库zipfile里的功能
11
- import pyxllib.file.packlib.zipfile as zipfile
12
- from pyxllib.file.packlib.zipfile import ZipFile
13
-
14
- from pyxllib.file.specialist import XlPath, reduce_dir_depth
15
- from pyxllib.prog.pupil import inject_members
16
-
17
- """ 问题:py官方的ZipFile解压带中文的文件会乱码
18
-
19
- 解决办法及操作流程
20
- 1、定期将官方的zipfile.py文件更新到pyxllib.file.packlib.zipfile
21
- 2、将代码中两处cp437都替换为gbk
22
- """
23
-
24
-
25
- def unpack_zipfile(filename, extract_dir):
26
- """ 为了修复zipfile底层的中文解压乱码问题,修改了shutil._UNPACK_FORMATS的底层功能
27
- """
28
- from shutil import ReadError
29
-
30
- zip = zipfile.ZipFile(filename)
31
- if not zipfile.is_zipfile(filename):
32
- raise ReadError("%s is not a zip file" % filename)
33
- try:
34
- for info in zip.infolist():
35
- name = info.filename
36
-
37
- # don't extract absolute paths or ones with .. in them
38
- if name.startswith('/') or '..' in name:
39
- continue
40
-
41
- target = os.path.join(extract_dir, *name.split('/'))
42
- if not target:
43
- continue
44
-
45
- os.makedirs(XlPath(target).parent, exist_ok=True)
46
- if not name.endswith('/'):
47
- # file
48
- data = zip.read(info.filename)
49
- f = open(target, 'wb')
50
- try:
51
- f.write(data)
52
- finally:
53
- f.close()
54
- del data
55
- finally:
56
- zip.close()
57
-
58
-
59
- # 解决unzip中文乱码问题
60
- shutil._UNPACK_FORMATS['zip'] = (['.zip'], unpack_zipfile, [], "ZIP file")
61
-
62
-
63
- def _parse_depth(names):
64
- """ 判断有几层目录都只有独立的一个目录
65
-
66
- :param names: 一组相对路径名
67
- :return: 如果直接目录下文件已经不唯一,返回0
68
-
69
- >>> _parse_depth(['a'])
70
- 1
71
- >>> _parse_depth(['a', 'a/1'])
72
- 2
73
- >>> _parse_depth(['a', 'a/b', 'a/b/1', 'a/b/2'])
74
- 2
75
- >>> _parse_depth(['a', 'a/b', 'a/b/1', 'a/c/3'])
76
- 1
77
- """
78
- parents = []
79
- for name in names:
80
- p = XlPath(name)
81
- ps = [x.as_posix() for x in p.parents]
82
- parents.append(ps[-2::-1] + [p.as_posix()])
83
- i = 0
84
- while len({x[i] for x in parents if len(x) > i}) == 1:
85
- i += 1
86
- return i
87
-
88
-
89
- def _unpack_base(packfile, namelist, format=None, extract_dir=None, wrap=0):
90
- """ 解压
91
-
92
- :param packfile: 压缩包本身的文件路径名称,在wrap=1时可能会用到,用来添加一个同名目录
93
- :param namelist: 压缩包里所有文件的相对路径
94
- :param format: 压缩包类型,比如zip、tar,可以不输入,此时直接采用shutil.unpack_archive里的判断机制
95
- :param extract_dir: 解压目标目录,可以不输入,会自动判断
96
- 自动解压规则:压缩包里目录不唯一,则以压缩包本身的名称创建一个目录存放
97
- 否则以压缩包里的目录名为准
98
- :param wrap: 解压时倾向的处理机制
99
- 0,默认,不进行任何处理
100
- 1,如果压缩包里一级目录下不止一个对象,使用压缩包本身的名称再包一层
101
- -1,如果压缩包里一级目录下只有一个目录,则丢弃这个目录,只取里面的内容出来
102
- 同理,可能这一个目录里的文件,还是只有一个目录,此时支持设置-2、-3等解开上限
103
- 也就-1比较常用,-2、-3等很少见了
104
- TODO 还有一种解压机制,只取里面的部分文件,有空可以继续调研扩展下
105
- :return: 无论怎样,最后都是放到一个目录里,返回改目录路径
106
- """
107
-
108
- # 1 默认解压目录是self所在目录,注意这点跟shutil.unpack_archive的当前工作目录不同
109
- p0 = XlPath(packfile)
110
- if extract_dir is None:
111
- extract_dir = p0.parent
112
-
113
- depth = _parse_depth(namelist)
114
-
115
- # 2 是否要加目录层级,或者去掉目录层级
116
- if wrap == 1 and depth == 0:
117
- # 压缩包里直接目录下有多个文件,且指定了wrap,则加一层目录
118
- shutil.unpack_archive(packfile, extract_dir / p0.stem, format)
119
- elif wrap < 0 < depth:
120
- # 压缩包有depth层冗余目录,并且指定wrap要解开这几层目录
121
- # 先正常解压(每种压缩包格式内部处理机制都有点不太一样,所以先解压,然后用目录文件功能处理更合适)
122
- shutil.unpack_archive(packfile, extract_dir, format)
123
- reduce_dir_depth(extract_dir, unwrap=-wrap)
124
- else:
125
- # 正常解压
126
- shutil.unpack_archive(packfile, extract_dir, format)
127
-
128
-
129
- class XlZipFile(ZipFile):
130
-
131
- def infolist2(self, prefix=None, zipinfo=True):
132
- """>> self.infolist2() # getinfo的多文件版本
133
- 1 <ZipInfo filename='[Content_Types].xml' compress_type=deflate file_size=1495 compress_size=383>
134
- 2 <ZipInfo filename='_rels/.rels' compress_type=deflate file_size=590 compress_size=243>
135
- ......
136
- 20 <ZipInfo filename='word/fontTable.xml' compress_type=deflate file_size=1590 compress_size=521>
137
- 21 <ZipInfo filename='docProps/app.xml' compress_type=deflate file_size=720 compress_size=384>
138
-
139
- :param prefix:
140
- 可以筛选文件的前缀,例如“word/”可以筛选出word目录下的
141
- :param zipinfo:
142
- 返回的list每个元素是zipinfo数据类型
143
- """
144
- ls = self.infolist()
145
- if prefix:
146
- ls = list(filter(lambda t: t.filename.startswith(prefix), ls))
147
- if not zipinfo:
148
- ls = list(map(lambda x: x.filename, ls))
149
- return ls
150
-
151
- def unpack(self, extract_dir=None, format='zip', wrap=0):
152
- _unpack_base(self.filename, self.namelist(), format, extract_dir, wrap)
153
-
154
-
155
- class XlTarFile(TarFile):
156
-
157
- def unpack(self, extract_dir=None, format='tar', wrap=0):
158
- _unpack_base(self.name, self.getnames(), format, extract_dir, wrap)
159
-
160
-
161
- inject_members(XlZipFile, ZipFile)
162
- inject_members(XlTarFile, TarFile)
163
-
164
-
165
- def unpack_archive(filename, extract_dir=None, format=None, *, wrap=1):
166
- """ 对shutil.unpack_archive的扩展,增加了一个wrap的接口功能 """
167
- if format is None:
168
- format = shutil._find_unpack_format(str(filename).lower())
169
-
170
- if format.endswith('zip'):
171
- XlZipFile(filename).unpack(extract_dir, format, wrap)
172
- elif format.endswith('tar'):
173
- XlTarFile(filename).unpack(extract_dir, format, wrap)
174
- else:
175
- # 其他还没扩展的格式,不支持wrap功能,但仍然可以使用shutil标准的接口解压
176
- shutil.unpack_archive(filename, extract_dir, format)
177
-
178
-
179
- def compress_to_zip(source_path, target_zip_path=None, wrap=None,
180
- ignore_func=None):
181
- """ 压缩指定的文件或文件夹为ZIP格式。
182
-
183
- :param str source_path: 要压缩的文件或文件夹路径
184
- :param str target_zip_path: 目标ZIP文件路径(可选)
185
- :param str wrap: 在ZIP文件内部创建的目录名,所有内容将被放在这个目录下
186
- :param func ignore_func: 忽略文件的函数,输入目录或文件的路径,返回True表示不取用
187
- """
188
- # 根据输入路径生成默认的目标ZIP文件路径
189
- if target_zip_path is None:
190
- # 获取输入路径的基本名称(文件名或文件夹名)
191
- base_name = os.path.basename(source_path)
192
- # 为基本名称添加'.zip'后缀
193
- target_zip_path = os.path.join(os.path.dirname(source_path), f"{base_name}.zip")
194
-
195
- # 创建一个ZipFile对象来写入压缩文件
196
- with XlZipFile(target_zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
197
- # 如果是文件夹,则遍历文件夹中的所有文件和子文件夹
198
- if os.path.isdir(source_path):
199
- for root, _, files in os.walk(source_path):
200
- if ignore_func and ignore_func(root):
201
- continue
202
-
203
- for file in files:
204
- if ignore_func and ignore_func(file):
205
- continue
206
-
207
- file_path = os.path.join(root, file)
208
- # 计算文件在ZIP中的相对路径
209
- arcname = os.path.relpath(file_path, source_path)
210
- if wrap:
211
- arcname = os.path.join(wrap, arcname)
212
- zipf.write(file_path, arcname)
213
- # 如果是文件,则直接将文件添加到ZIP中
214
- elif os.path.isfile(source_path):
215
- arcname = os.path.basename(source_path)
216
- if wrap:
217
- arcname = os.path.join(wrap, arcname)
218
- zipf.write(source_path, arcname)
219
-
220
- return target_zip_path
221
-
222
-
223
- def smart_compress_zip(root, paths, check_func=None):
224
- """ 智能压缩,比compress_to_zip功能会更强些
225
-
226
- :param root: 要有个根目录,才知道paths里添加到压缩包的时候存储到怎样的相对目录下
227
- :param paths: 所有待添加到压缩包的文件或目录
228
- :param check_func: 规则判断函数,输入文件或目录的路径
229
- return
230
- 0,明确不要
231
- 1,要使用,但要递归内部文件精细检查
232
- 2,全部都要
233
- """
234
-
235
- if check_func is None:
236
- def check_func(path):
237
- p = XlPath(path)
238
-
239
- if set(p.parts) & {'__pycache__', '.git', '.idea', 'dist', 'build', '.pytest_cache'}:
240
- return 0
241
-
242
- if p.parts[-1].endswith('.egg-info'):
243
- return 0
244
-
245
- return 1
246
-
247
- def add_dir(dir):
248
- for subroot, _, names in os.walk(dir):
249
- for name in names:
250
- file = XlPath(subroot) / name
251
- zipf.write(file, file.relpath(root))
252
-
253
- def add_path(path):
254
- tag = check_func(path)
255
-
256
- if path.is_file():
257
- if tag:
258
- zipf.write(path, path.relpath(root))
259
- elif path.is_dir():
260
- if tag == 2:
261
- add_dir(path)
262
- elif tag == 1:
263
- for subroot, _, names in os.walk(path):
264
- tag2 = check_func(subroot)
265
- if tag2 == 2:
266
- add_dir(subroot)
267
- elif tag2 == 1:
268
- for name in names:
269
- file = XlPath(subroot) / name
270
- if check_func(file):
271
- zipf.write(file, file.relpath(root))
272
-
273
- # 工作目录会自动切换的,这里取工作目录名即可
274
- if not isinstance(paths, list):
275
- paths = [paths]
276
-
277
- root = XlPath(root)
278
- num = len(paths)
279
- outfile = None
280
- if num > 1:
281
- outfile = root / XlPath(root.name + '.zip')
282
- elif num == 1:
283
- outfile = root / (XlPath(paths[0]).name + '.zip')
284
- else:
285
- return
286
- zipf = XlZipFile(outfile, 'w', zipfile.ZIP_DEFLATED)
287
-
288
- for subroot in paths:
289
- add_path(XlPath(subroot))
290
-
291
- zipf.close()
292
-
293
- return outfile
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # @Author : 陈坤泽
4
+ # @Email : 877362867@qq.com
5
+ # @Date : 2022/02/15 09:51
6
+
7
+ import os
8
+ import shutil
9
+ from tarfile import TarFile
10
+ # 这个包里的ZipFile是拷贝后修改过的,不影响标准库zipfile里的功能
11
+ # import pyxllib.file.packlib.zipfile as zipfile
12
+ # from pyxllib.file.packlib.zipfile import ZipFile
13
+ import zipfile
14
+ from zipfile import ZipFile
15
+ import tempfile
16
+
17
+ from pyxllib.file.specialist import XlPath, reduce_dir_depth
18
+ from pyxllib.prog.pupil import inject_members
19
+
20
+ """ 问题:py官方的ZipFile解压带中文的文件会乱码
21
+
22
+ 解决办法及操作流程
23
+ 1、定期将官方的zipfile.py文件更新到pyxllib.file.packlib.zipfile
24
+ 2、将代码中两处cp437都替换为gbk
25
+ """
26
+
27
+
28
+ def unpack_zipfile(filename, extract_dir):
29
+ """ 为了修复zipfile底层的中文解压乱码问题,修改了shutil._UNPACK_FORMATS的底层功能
30
+ """
31
+ from shutil import ReadError
32
+
33
+ zip = zipfile.ZipFile(filename)
34
+ if not zipfile.is_zipfile(filename):
35
+ raise ReadError("%s is not a zip file" % filename)
36
+ try:
37
+ for info in zip.infolist():
38
+ name = info.filename
39
+
40
+ # don't extract absolute paths or ones with .. in them
41
+ if name.startswith('/') or '..' in name:
42
+ continue
43
+
44
+ target = os.path.join(extract_dir, *name.split('/'))
45
+ if not target:
46
+ continue
47
+
48
+ os.makedirs(XlPath(target).parent, exist_ok=True)
49
+ if not name.endswith('/'):
50
+ # file
51
+ data = zip.read(info.filename)
52
+ f = open(target, 'wb')
53
+ try:
54
+ f.write(data)
55
+ finally:
56
+ f.close()
57
+ del data
58
+ finally:
59
+ zip.close()
60
+
61
+
62
+ # 解决unzip中文乱码问题
63
+ shutil._UNPACK_FORMATS['zip'] = (['.zip'], unpack_zipfile, [], "ZIP file")
64
+
65
+
66
+ def _parse_depth(names):
67
+ """ 判断有几层目录都只有独立的一个目录
68
+
69
+ :param names: 一组相对路径名
70
+ :return: 如果直接目录下文件已经不唯一,返回0
71
+
72
+ >>> _parse_depth(['a'])
73
+ 1
74
+ >>> _parse_depth(['a', 'a/1'])
75
+ 2
76
+ >>> _parse_depth(['a', 'a/b', 'a/b/1', 'a/b/2'])
77
+ 2
78
+ >>> _parse_depth(['a', 'a/b', 'a/b/1', 'a/c/3'])
79
+ 1
80
+ """
81
+ parents = []
82
+ for name in names:
83
+ p = XlPath(name)
84
+ ps = [x.as_posix() for x in p.parents]
85
+ parents.append(ps[-2::-1] + [p.as_posix()])
86
+ i = 0
87
+ while len({x[i] for x in parents if len(x) > i}) == 1:
88
+ i += 1
89
+ return i
90
+
91
+
92
+ def _unpack_base(packfile, namelist, format=None, extract_dir=None, wrap=0):
93
+ """ 解压
94
+
95
+ :param packfile: 压缩包本身的文件路径名称,在wrap=1时可能会用到,用来添加一个同名目录
96
+ :param namelist: 压缩包里所有文件的相对路径
97
+ :param format: 压缩包类型,比如zip、tar,可以不输入,此时直接采用shutil.unpack_archive里的判断机制
98
+ :param extract_dir: 解压目标目录,可以不输入,会自动判断
99
+ 自动解压规则:压缩包里目录不唯一,则以压缩包本身的名称创建一个目录存放
100
+ 否则以压缩包里的目录名为准
101
+ :param wrap: 解压时倾向的处理机制
102
+ 0,默认,不进行任何处理
103
+ 1,如果压缩包里一级目录下不止一个对象,使用压缩包本身的名称再包一层
104
+ -1,如果压缩包里一级目录下只有一个目录,则丢弃这个目录,只取里面的内容出来
105
+ 同理,可能这一个目录里的文件,还是只有一个目录,此时支持设置-2、-3等解开上限
106
+ 也就-1比较常用,-2、-3等很少见了
107
+ TODO 还有一种解压机制,只取里面的部分文件,有空可以继续调研扩展下
108
+ :return: 无论怎样,最后都是放到一个目录里,返回改目录路径
109
+ """
110
+
111
+ # 1 默认解压目录是self所在目录,注意这点跟shutil.unpack_archive的当前工作目录不同
112
+ p0 = XlPath(packfile)
113
+ if extract_dir is None:
114
+ extract_dir = p0.parent
115
+
116
+ depth = _parse_depth(namelist)
117
+
118
+ # 2 是否要加目录层级,或者去掉目录层级
119
+ if wrap == 1 and depth == 0:
120
+ # 压缩包里直接目录下有多个文件,且指定了wrap,则加一层目录
121
+ shutil.unpack_archive(packfile, extract_dir / p0.stem, format)
122
+ elif wrap < 0 < depth:
123
+ # 压缩包有depth层冗余目录,并且指定wrap要解开这几层目录
124
+ # 先正常解压(每种压缩包格式内部处理机制都有点不太一样,所以先解压,然后用目录文件功能处理更合适)
125
+ shutil.unpack_archive(packfile, extract_dir, format)
126
+ reduce_dir_depth(extract_dir, unwrap=-wrap)
127
+ else:
128
+ # 正常解压
129
+ shutil.unpack_archive(packfile, extract_dir, format)
130
+
131
+
132
+ def zip_filter_rule(path):
133
+ p = XlPath(path)
134
+
135
+ # 排除特定目录或文件
136
+ if set(p.parts) & {'__pycache__', '.git', '.idea', 'dist', 'build', '.pytest_cache', '.venv'}:
137
+ return 0
138
+
139
+ # 排除特定文件扩展名
140
+ if p.suffix in {'.egg-info', '.lock'}:
141
+ return 0
142
+
143
+ # 精细检查内部文件
144
+ if p.is_dir():
145
+ return 1
146
+
147
+ # 全部包含其他情况
148
+ return 2
149
+
150
+
151
+ class XlZipFile(ZipFile):
152
+
153
+ def infolist2(self, prefix=None, zipinfo=True):
154
+ """>> self.infolist2() # getinfo的多文件版本
155
+ 1 <ZipInfo filename='[Content_Types].xml' compress_type=deflate file_size=1495 compress_size=383>
156
+ 2 <ZipInfo filename='_rels/.rels' compress_type=deflate file_size=590 compress_size=243>
157
+ ......
158
+ 20 <ZipInfo filename='word/fontTable.xml' compress_type=deflate file_size=1590 compress_size=521>
159
+ 21 <ZipInfo filename='docProps/app.xml' compress_type=deflate file_size=720 compress_size=384>
160
+
161
+ :param prefix:
162
+ 可以筛选文件的前缀,例如“word/”可以筛选出word目录下的
163
+ :param zipinfo:
164
+ 返回的list每个元素是zipinfo数据类型
165
+ """
166
+ ls = self.infolist()
167
+ if prefix:
168
+ ls = list(filter(lambda t: t.filename.startswith(prefix), ls))
169
+ if not zipinfo:
170
+ ls = list(map(lambda x: x.filename, ls))
171
+ return ls
172
+
173
+ def unpack(self, extract_dir=None, format='zip', wrap=0):
174
+ _unpack_base(self.filename, self.namelist(), format, extract_dir, wrap)
175
+
176
+ def write_dir(self, directory, arcname=None, filter_rule=None):
177
+ """
178
+ 将指定目录(包含子目录)添加到 zip 文件中,并可自定义在 zip 中的存储路径。
179
+
180
+ :param directory: 要压缩的目录路径
181
+ :param arcname: 在 zip 文件中存储的根目录名,
182
+ None, 默认跟ZipFile.write的arcname一样,直接取输入的目录名
183
+ :param filter_rule: 过滤规则函数,用于排除不需要的文件。函数应接受文件路径作为参数,
184
+ 返回0, 1, 2,分别表示排除、递归检查、全部包括。
185
+ """
186
+ if arcname is None:
187
+ arcname = directory
188
+
189
+ if filter_rule is True:
190
+ filter_rule = zip_filter_rule
191
+
192
+ for root, dirs, files in os.walk(directory):
193
+ for file in files:
194
+ file_path = os.path.join(root, file)
195
+
196
+ # 调用过滤函数获取过滤状态
197
+ if filter_rule:
198
+ result = filter_rule(file_path)
199
+ if result == 0: # 明确不要
200
+ continue
201
+ elif result == 1: # 需要递归精细检查
202
+ pass # 继续执行文件写入逻辑
203
+ elif result == 2: # 全部包含
204
+ # 计算文件在 zip 文件中的相对路径
205
+ zip_path = os.path.join(arcname, os.path.relpath(file_path, directory))
206
+ self.write(file_path, zip_path)
207
+ continue
208
+
209
+ # 默认情况下,递归处理
210
+ zip_path = os.path.join(arcname, os.path.relpath(file_path, directory))
211
+ self.write(file_path, zip_path)
212
+
213
+ for dir in dirs[:]:
214
+ dir_path = os.path.join(root, dir)
215
+
216
+ if filter_rule:
217
+ result = filter_rule(dir_path)
218
+ if result == 0: # 明确不要
219
+ dirs.remove(dir) # 排除整个目录
220
+ elif result == 2: # 全部包含
221
+ # 添加整个目录
222
+ for root2, _, files2 in os.walk(dir_path):
223
+ for file2 in files2:
224
+ file_path = os.path.join(root2, file2)
225
+ zip_path = os.path.join(arcname, os.path.relpath(file_path, directory))
226
+ self.write(file_path, zip_path)
227
+ dirs.remove(dir) # 递归中不再处理此目录
228
+
229
+ def write_path(self, path, arcname=None, filter_rule=None):
230
+ """ 封装的同时支持文件或目录的操作 """
231
+ if XlPath(path).is_dir():
232
+ self.write_dir(path, arcname, filter_rule)
233
+ elif XlPath(path).is_file():
234
+ self.write(path, arcname)
235
+ else:
236
+ raise ValueError
237
+
238
+ def xlwrite(self, path, arcname=None, filter_rule=True):
239
+ self.write_path(path, arcname, filter_rule)
240
+
241
+ @classmethod
242
+ def create(cls, name=None):
243
+ """ 在临时目录下新建一个目录,然后放一个压缩包文件 """
244
+ # 如果没有提供 name,则生成一个临时的文件名
245
+ if name is None:
246
+ name = tempfile.mktemp(suffix=".zip").split('/')[-1] # 提取生成的文件名
247
+
248
+ # 创建临时目录(因为可能有并发操作,每个处理都建立一个目录更安全)
249
+ temp_dir = tempfile.mkdtemp()
250
+ temp_zip_path = f"{temp_dir}/{name}"
251
+
252
+ # 创建 ZipFile 对象
253
+ zipf = ZipFile(temp_zip_path, 'w')
254
+ return zipf
255
+
256
+ def fastapi_resp(self):
257
+ """ 返回供fastapi后端使用的文件接口 """
258
+ from fastapi.responses import FileResponse
259
+
260
+ self.close()
261
+ return FileResponse(self.filename, media_type='application/zip',
262
+ filename=XlPath(self.filename).name)
263
+
264
+
265
+ class XlTarFile(TarFile):
266
+
267
+ def unpack(self, extract_dir=None, format='tar', wrap=0):
268
+ _unpack_base(self.name, self.getnames(), format, extract_dir, wrap)
269
+
270
+
271
+ inject_members(XlZipFile, ZipFile)
272
+ inject_members(XlTarFile, TarFile)
273
+
274
+
275
+ def unpack_archive(filename, extract_dir=None, format=None, *, wrap=1):
276
+ """ 对shutil.unpack_archive的扩展,增加了一个wrap的接口功能 """
277
+ if format is None:
278
+ format = shutil._find_unpack_format(str(filename).lower())
279
+
280
+ if format.endswith('zip'):
281
+ XlZipFile(filename).unpack(extract_dir, format, wrap)
282
+ elif format.endswith('tar'):
283
+ XlTarFile(filename).unpack(extract_dir, format, wrap)
284
+ else:
285
+ # 其他还没扩展的格式,不支持wrap功能,但仍然可以使用shutil标准的接口解压
286
+ shutil.unpack_archive(filename, extract_dir, format)
287
+
288
+
289
+ def compress_to_zip(source_path, target_zip_path=None, wrap=None,
290
+ ignore_func=None):
291
+ """ 压缩指定的文件或文件夹为ZIP格式。
292
+
293
+ :param str source_path: 要压缩的文件或文件夹路径
294
+ :param str target_zip_path: 目标ZIP文件路径(可选)
295
+ :param str wrap: 在ZIP文件内部创建的目录名,所有内容将被放在这个目录下
296
+ :param func ignore_func: 忽略文件的函数,输入目录或文件的路径,返回True表示不取用
297
+ """
298
+ # 根据输入路径生成默认的目标ZIP文件路径
299
+ if target_zip_path is None:
300
+ # 获取输入路径的基本名称(文件名或文件夹名)
301
+ base_name = os.path.basename(source_path)
302
+ # 为基本名称添加'.zip'后缀
303
+ target_zip_path = os.path.join(os.path.dirname(source_path), f"{base_name}.zip")
304
+
305
+ # 创建一个ZipFile对象来写入压缩文件
306
+ with XlZipFile(target_zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
307
+ # 如果是文件夹,则遍历文件夹中的所有文件和子文件夹
308
+ if os.path.isdir(source_path):
309
+ for root, _, files in os.walk(source_path):
310
+ if ignore_func and ignore_func(root):
311
+ continue
312
+
313
+ for file in files:
314
+ if ignore_func and ignore_func(file):
315
+ continue
316
+
317
+ file_path = os.path.join(root, file)
318
+ # 计算文件在ZIP中的相对路径
319
+ arcname = os.path.relpath(file_path, source_path)
320
+ if wrap:
321
+ arcname = os.path.join(wrap, arcname)
322
+ zipf.write(file_path, arcname)
323
+ # 如果是文件,则直接将文件添加到ZIP中
324
+ elif os.path.isfile(source_path):
325
+ arcname = os.path.basename(source_path)
326
+ if wrap:
327
+ arcname = os.path.join(wrap, arcname)
328
+ zipf.write(source_path, arcname)
329
+
330
+ return target_zip_path