pyxllib 0.3.108__tar.gz → 0.3.110__tar.gz

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 (346) hide show
  1. {pyxllib-0.3.108/pyxllib.egg-info → pyxllib-0.3.110}/PKG-INFO +1 -1
  2. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/pupil.py +100 -22
  3. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/data/pglib.py +68 -35
  4. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/data/sqlite.py +117 -0
  5. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/kq5034lib.py +1 -1
  6. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/libreoffice.py +1 -0
  7. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/specialist/filelib.py +44 -13
  8. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/newbie.py +3 -0
  9. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/specialist/bc.py +5 -2
  10. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/specialist/browser.py +8 -2
  11. {pyxllib-0.3.108 → pyxllib-0.3.110/pyxllib.egg-info}/PKG-INFO +1 -1
  12. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib.egg-info/SOURCES.txt +1 -0
  13. pyxllib-0.3.110/pyxlpr/data/tiktokenlib.py +43 -0
  14. {pyxllib-0.3.108 → pyxllib-0.3.110}/setup.py +1 -1
  15. {pyxllib-0.3.108 → pyxllib-0.3.110}/LICENSE +0 -0
  16. {pyxllib-0.3.108 → pyxllib-0.3.110}/MANIFEST.in +0 -0
  17. {pyxllib-0.3.108 → pyxllib-0.3.110}/README.md +0 -0
  18. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/__init__.py +0 -0
  19. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/__init__.py +0 -0
  20. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/disjoint.py +0 -0
  21. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/geo.py +0 -0
  22. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/intervals.py +0 -0
  23. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/matcher.py +0 -0
  24. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/newbie.py +0 -0
  25. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/shapelylib.py +0 -0
  26. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/specialist.py +0 -0
  27. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/stat.py +0 -0
  28. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/treelib.py +0 -0
  29. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/unitlib.py +0 -0
  30. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/cv/__init__.py +0 -0
  31. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/cv/expert.py +0 -0
  32. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/cv/imfile.py +0 -0
  33. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/cv/imhash.py +0 -0
  34. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/cv/pupil.py +0 -0
  35. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/cv/rgbfmt.py +0 -0
  36. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/cv/trackbartools.py +0 -0
  37. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/cv/xlcvlib.py +0 -0
  38. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/cv/xlpillib.py +0 -0
  39. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/data/__init__.py +0 -0
  40. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/data/echarts.py +0 -0
  41. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/data/jsonlib.py +0 -0
  42. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/data/oss.py +0 -0
  43. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/data/sqllib.py +0 -0
  44. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/JLineViewer.py +0 -0
  45. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/__init__.py +0 -0
  46. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/autogui/__init__.py +0 -0
  47. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/autogui/autogui.py +0 -0
  48. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/autogui/virtualkey.py +0 -0
  49. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/demolib.py +0 -0
  50. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/drissionlib.py +0 -0
  51. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/old.py +0 -0
  52. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/qt.py +0 -0
  53. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/robustprocfile.py +0 -0
  54. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/seleniumlib.py +0 -0
  55. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/tk.py +0 -0
  56. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/unixlib.py +0 -0
  57. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/utools.py +0 -0
  58. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/webhook.py +0 -0
  59. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/win32lib.py +0 -0
  60. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/yuquelib.py +0 -0
  61. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/__init__.py +0 -0
  62. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/docxlib.py +0 -0
  63. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/gitlib.py +0 -0
  64. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/movielib.py +0 -0
  65. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/newbie.py +0 -0
  66. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/onenotelib.py +0 -0
  67. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/packlib/__init__.py +0 -0
  68. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/packlib/zipfile.py +0 -0
  69. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/pdflib.py +0 -0
  70. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/pupil.py +0 -0
  71. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/specialist/__init__.py +0 -0
  72. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/specialist/dirlib.py +0 -0
  73. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/specialist/download.py +0 -0
  74. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/xlsxlib.py +0 -0
  75. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/__init__.py +0 -0
  76. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/deprecatedlib.py +0 -0
  77. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/ipyexec.py +0 -0
  78. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/multiprocs.py +0 -0
  79. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/pupil.py +0 -0
  80. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/sitepackages.py +0 -0
  81. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/specialist/__init__.py +0 -0
  82. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/specialist/common.py +0 -0
  83. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/specialist/datetime.py +0 -0
  84. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/specialist/tictoc.py +0 -0
  85. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/specialist/xllog.py +0 -0
  86. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/xlosenv.py +0 -0
  87. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/stdlib/__init__.py +0 -0
  88. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/stdlib/tablepyxl/__init__.py +0 -0
  89. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/stdlib/tablepyxl/style.py +0 -0
  90. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/stdlib/tablepyxl/tablepyxl.py +0 -0
  91. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/__init__.py +0 -0
  92. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/ahocorasick.py +0 -0
  93. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/charclasslib.py +0 -0
  94. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/jiebalib.py +0 -0
  95. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/jscode.py +0 -0
  96. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/latex/__init__.py +0 -0
  97. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/levenshtein.py +0 -0
  98. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/nestenv.py +0 -0
  99. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/newbie.py +0 -0
  100. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/pupil/__init__.py +0 -0
  101. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/pupil/common.py +0 -0
  102. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/pupil/xlalign.py +0 -0
  103. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/pycode.py +0 -0
  104. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/specialist/__init__.py +0 -0
  105. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/specialist/common.py +0 -0
  106. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/specialist/ptag.py +0 -0
  107. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/spellchecker.py +0 -0
  108. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/vbacode.py +0 -0
  109. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/xmllib.py +0 -0
  110. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/xl.py +0 -0
  111. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/xlcv.py +0 -0
  112. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib.egg-info/dependency_links.txt +0 -0
  113. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib.egg-info/requires.txt +2 -2
  114. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib.egg-info/top_level.txt +0 -0
  115. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/__init__.py +0 -0
  116. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ai/__init__.py +0 -0
  117. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ai/clientlib.py +0 -0
  118. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ai/specialist.py +0 -0
  119. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ai/torch_app.py +0 -0
  120. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ai/xlpaddle.py +0 -0
  121. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ai/xltorch.py +0 -0
  122. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/__init__.py +0 -0
  123. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/coco.py +0 -0
  124. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/datacls.py +0 -0
  125. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/datasets.py +0 -0
  126. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/gptlib.py +0 -0
  127. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/icdar/__init__.py +0 -0
  128. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/icdar/deteval.py +0 -0
  129. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/icdar/icdar2013.py +0 -0
  130. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/icdar/iou.py +0 -0
  131. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/icdar/rrc_evaluation_funcs_1_1.py +0 -0
  132. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/imtextline.py +0 -0
  133. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/labelme.py +0 -0
  134. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/removeline.py +0 -0
  135. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/specialist.py +0 -0
  136. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/eval/__init__.py +0 -0
  137. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/paddleocr.py +0 -0
  138. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/__init__.py +0 -0
  139. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/configs/rec/multi_language/generate_multi_language_configs.py +0 -0
  140. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/__init__.py +0 -0
  141. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/ColorJitter.py +0 -0
  142. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/__init__.py +0 -0
  143. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/copy_paste.py +0 -0
  144. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/east_process.py +0 -0
  145. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/gen_table_mask.py +0 -0
  146. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/iaa_augment.py +0 -0
  147. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/label_ops.py +0 -0
  148. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/make_border_map.py +0 -0
  149. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/make_pse_gt.py +0 -0
  150. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/make_shrink_map.py +0 -0
  151. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/operators.py +0 -0
  152. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/pg_process.py +0 -0
  153. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/randaugment.py +0 -0
  154. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/random_crop_data.py +0 -0
  155. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/rec_img_aug.py +0 -0
  156. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/sast_process.py +0 -0
  157. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/text_image_aug/__init__.py +0 -0
  158. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/text_image_aug/augment.py +0 -0
  159. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/text_image_aug/warp_mls.py +0 -0
  160. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/lmdb_dataset.py +0 -0
  161. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/pgnet_dataset.py +0 -0
  162. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/pubtab_dataset.py +0 -0
  163. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/simple_dataset.py +0 -0
  164. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/__init__.py +0 -0
  165. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/ace_loss.py +0 -0
  166. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/basic_loss.py +0 -0
  167. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/center_loss.py +0 -0
  168. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/cls_loss.py +0 -0
  169. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/combined_loss.py +0 -0
  170. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/det_basic_loss.py +0 -0
  171. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/det_db_loss.py +0 -0
  172. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/det_east_loss.py +0 -0
  173. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/det_pse_loss.py +0 -0
  174. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/det_sast_loss.py +0 -0
  175. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/distillation_loss.py +0 -0
  176. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/e2e_pg_loss.py +0 -0
  177. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/kie_sdmgr_loss.py +0 -0
  178. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/rec_aster_loss.py +0 -0
  179. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/rec_att_loss.py +0 -0
  180. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/rec_ctc_loss.py +0 -0
  181. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/rec_enhanced_ctc_loss.py +0 -0
  182. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/rec_nrtr_loss.py +0 -0
  183. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/rec_sar_loss.py +0 -0
  184. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/rec_srn_loss.py +0 -0
  185. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/table_att_loss.py +0 -0
  186. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/metrics/__init__.py +0 -0
  187. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/metrics/cls_metric.py +0 -0
  188. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/metrics/det_metric.py +0 -0
  189. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/metrics/distillation_metric.py +0 -0
  190. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/metrics/e2e_metric.py +0 -0
  191. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/metrics/eval_det_iou.py +0 -0
  192. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/metrics/kie_metric.py +0 -0
  193. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/metrics/rec_metric.py +0 -0
  194. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/metrics/table_metric.py +0 -0
  195. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/architectures/__init__.py +0 -0
  196. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/architectures/base_model.py +0 -0
  197. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/architectures/distillation_model.py +0 -0
  198. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/__init__.py +0 -0
  199. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/det_mobilenet_v3.py +0 -0
  200. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/det_resnet_vd.py +0 -0
  201. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/det_resnet_vd_sast.py +0 -0
  202. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/e2e_resnet_vd_pg.py +0 -0
  203. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/kie_unet_sdmgr.py +0 -0
  204. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/rec_mobilenet_v3.py +0 -0
  205. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/rec_mv1_enhance.py +0 -0
  206. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/rec_nrtr_mtb.py +0 -0
  207. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/rec_resnet_31.py +0 -0
  208. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/rec_resnet_aster.py +0 -0
  209. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/rec_resnet_fpn.py +0 -0
  210. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/rec_resnet_vd.py +0 -0
  211. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/__init__.py +0 -0
  212. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/cls_head.py +0 -0
  213. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/det_db_head.py +0 -0
  214. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/det_east_head.py +0 -0
  215. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/det_pse_head.py +0 -0
  216. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/det_sast_head.py +0 -0
  217. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/e2e_pg_head.py +0 -0
  218. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/kie_sdmgr_head.py +0 -0
  219. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/multiheadAttention.py +0 -0
  220. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/rec_aster_head.py +0 -0
  221. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/rec_att_head.py +0 -0
  222. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/rec_ctc_head.py +0 -0
  223. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/rec_nrtr_head.py +0 -0
  224. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/rec_sar_head.py +0 -0
  225. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/rec_srn_head.py +0 -0
  226. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/self_attention.py +0 -0
  227. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/table_att_head.py +0 -0
  228. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/necks/__init__.py +0 -0
  229. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/necks/db_fpn.py +0 -0
  230. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/necks/east_fpn.py +0 -0
  231. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/necks/fpn.py +0 -0
  232. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/necks/pg_fpn.py +0 -0
  233. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/necks/rnn.py +0 -0
  234. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/necks/sast_fpn.py +0 -0
  235. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/necks/table_fpn.py +0 -0
  236. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/transforms/__init__.py +0 -0
  237. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/transforms/stn.py +0 -0
  238. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/transforms/tps.py +0 -0
  239. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/transforms/tps_spatial_transformer.py +0 -0
  240. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/optimizer/__init__.py +0 -0
  241. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/optimizer/learning_rate.py +0 -0
  242. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/optimizer/lr_scheduler.py +0 -0
  243. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/optimizer/optimizer.py +0 -0
  244. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/optimizer/regularizer.py +0 -0
  245. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/__init__.py +0 -0
  246. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/cls_postprocess.py +0 -0
  247. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/db_postprocess.py +0 -0
  248. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/east_postprocess.py +0 -0
  249. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/locality_aware_nms.py +0 -0
  250. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/pg_postprocess.py +0 -0
  251. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/pse_postprocess/__init__.py +0 -0
  252. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/pse_postprocess/pse/__init__.py +0 -0
  253. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/pse_postprocess/pse/setup.py +0 -0
  254. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/pse_postprocess/pse_postprocess.py +0 -0
  255. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/rec_postprocess.py +0 -0
  256. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/sast_postprocess.py +0 -0
  257. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/__init__.py +0 -0
  258. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/eval.py +0 -0
  259. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/export_center.py +0 -0
  260. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/export_model.py +0 -0
  261. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer/predict_cls.py +0 -0
  262. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer/predict_det.py +0 -0
  263. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer/predict_e2e.py +0 -0
  264. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer/predict_rec.py +0 -0
  265. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer/predict_system.py +0 -0
  266. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer/utility.py +0 -0
  267. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer_cls.py +0 -0
  268. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer_det.py +0 -0
  269. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer_e2e.py +0 -0
  270. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer_kie.py +0 -0
  271. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer_rec.py +0 -0
  272. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer_table.py +0 -0
  273. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/program.py +0 -0
  274. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/test_hubserving.py +0 -0
  275. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/train.py +0 -0
  276. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/xlprog.py +0 -0
  277. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/EN_symbol_dict.txt +0 -0
  278. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/__init__.py +0 -0
  279. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/ar_dict.txt +0 -0
  280. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/arabic_dict.txt +0 -0
  281. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/be_dict.txt +0 -0
  282. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/bg_dict.txt +0 -0
  283. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/chinese_cht_dict.txt +0 -0
  284. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/cyrillic_dict.txt +0 -0
  285. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/devanagari_dict.txt +0 -0
  286. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/en_dict.txt +0 -0
  287. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/fa_dict.txt +0 -0
  288. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/french_dict.txt +0 -0
  289. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/german_dict.txt +0 -0
  290. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/hi_dict.txt +0 -0
  291. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/it_dict.txt +0 -0
  292. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/japan_dict.txt +0 -0
  293. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/ka_dict.txt +0 -0
  294. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/korean_dict.txt +0 -0
  295. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/latin_dict.txt +0 -0
  296. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/mr_dict.txt +0 -0
  297. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/ne_dict.txt +0 -0
  298. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/oc_dict.txt +0 -0
  299. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/pu_dict.txt +0 -0
  300. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/rs_dict.txt +0 -0
  301. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/rsc_dict.txt +0 -0
  302. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/ru_dict.txt +0 -0
  303. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/ta_dict.txt +0 -0
  304. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/table_dict.txt +0 -0
  305. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/table_structure_dict.txt +0 -0
  306. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/te_dict.txt +0 -0
  307. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/ug_dict.txt +0 -0
  308. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/uk_dict.txt +0 -0
  309. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/ur_dict.txt +0 -0
  310. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/xi_dict.txt +0 -0
  311. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict90.txt +0 -0
  312. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/e2e_metric/Deteval.py +0 -0
  313. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/e2e_metric/polygon_fast.py +0 -0
  314. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/e2e_utils/extract_batchsize.py +0 -0
  315. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/e2e_utils/extract_textpoint_fast.py +0 -0
  316. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/e2e_utils/extract_textpoint_slow.py +0 -0
  317. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/e2e_utils/pgnet_pp_utils.py +0 -0
  318. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/e2e_utils/visual.py +0 -0
  319. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/en_dict.txt +0 -0
  320. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/gen_label.py +0 -0
  321. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/ic15_dict.txt +0 -0
  322. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/iou.py +0 -0
  323. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/logging.py +0 -0
  324. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/network.py +0 -0
  325. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/ppocr_keys_v1.txt +0 -0
  326. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/profiler.py +0 -0
  327. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/save_load.py +0 -0
  328. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/stats.py +0 -0
  329. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/utility.py +0 -0
  330. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/__init__.py +0 -0
  331. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/predict_system.py +0 -0
  332. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/table/__init__.py +0 -0
  333. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/table/eval_table.py +0 -0
  334. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/table/matcher.py +0 -0
  335. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/table/predict_structure.py +0 -0
  336. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/table/predict_table.py +0 -0
  337. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/table/table_metric/__init__.py +0 -0
  338. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/table/table_metric/parallel.py +0 -0
  339. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/table/table_metric/table_metric.py +0 -0
  340. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/table/tablepyxl/__init__.py +0 -0
  341. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/table/tablepyxl/style.py +0 -0
  342. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/table/tablepyxl/tablepyxl.py +0 -0
  343. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/utility.py +0 -0
  344. {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/xlai.py +0 -0
  345. {pyxllib-0.3.108 → pyxllib-0.3.110}/requirements.txt +0 -0
  346. {pyxllib-0.3.108 → pyxllib-0.3.110}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyxllib
3
- Version: 0.3.108
3
+ Version: 0.3.110
4
4
  Summary: 厦门理工模式识别团队通用python代码工具库
5
5
  Home-page: https://github.com/XLPRUtils/pyxllib
6
6
  Author: code4101
@@ -4,11 +4,14 @@
4
4
  # @Email : 877362867@qq.com
5
5
  # @Date : 2021/06/03 14:22
6
6
 
7
- import textwrap
7
+ from bisect import bisect_right
8
8
  from collections import defaultdict, Counter
9
+ import datetime
9
10
  import math
10
11
  import re
12
+ from statistics import quantiles
11
13
  import sys
14
+ import textwrap
12
15
 
13
16
  from pyxllib.prog.newbie import typename, human_readable_number
14
17
  from pyxllib.text.pupil import listalign, int2myalphaenum
@@ -156,13 +159,17 @@ class ValuesStat2:
156
159
  """ 240509周四17:33,第2代统计器
157
160
  """
158
161
 
159
- def __init__(self, values=None, raw_values=None):
162
+ def __init__(self, values=None, raw_values=None, data_type=None):
160
163
  from statistics import pstdev, mean
161
164
 
162
165
  # 支持输入可能带有非数值类型的raw_values
163
166
  if raw_values:
164
- values = [x for x in raw_values if isinstance(x, (int, float))] # todo 可能需要更泛用的判断数值的方法
167
+ if 'timestamp' in data_type:
168
+ values = [x.timestamp() for x in raw_values if hasattr(x, 'timestamp')]
169
+ else:
170
+ values = [x for x in raw_values if isinstance(x, (int, float))] # todo 可能需要更泛用的判断数值的方法
165
171
 
172
+ self.date_type = data_type
166
173
  self.raw_values = raw_values
167
174
  values = values or []
168
175
  self.values = sorted(values)
@@ -171,57 +178,128 @@ class ValuesStat2:
171
178
  else:
172
179
  self.raw_n = 0
173
180
  self.n = len(values)
174
- self.sum = sum(values)
181
+
182
+ if 'timestamp' in data_type:
183
+ self.sum = None
184
+ else:
185
+ self.sum = sum(values)
186
+
175
187
  if self.n:
176
188
  self.mean = mean(self.values)
177
189
  self.std = pstdev(self.values)
178
190
  self.min, self.max = self.values[0], self.values[-1]
179
191
  else:
180
- self.mean = self.std = self.min = self.max = float('nan')
192
+ self.mean = self.std = self.min = self.max = None
181
193
 
182
- self.dist = []
194
+ self.dist = None
183
195
 
184
196
  def __len__(self):
185
197
  return self.n
186
198
 
187
- def summary(self, unit='万', precision=4, percentile=5):
199
+ def _summary(self, unit=None, precision=4, percentile_count=5):
200
+ """ 返回字典结构的总结 """
188
201
  """ 文本汇总性的报告
189
202
 
190
- :param percentile: 包括两个极值端点的切分点数,
203
+ :param percentile_count: 包括两个极值端点的切分点数,
191
204
  设置2,就是不设置分位数,就是只展示最小、最大值
192
205
  如果设置了3,就表示"中位数、二分位数",在展示的时候,会显示50%位置的分位数值
193
206
  如果设置了5,就相当于"四分位数",会显示25%、50%、75%位置的分位数值
194
207
  :param unit: 展示数值时使用的单位
195
208
  :param precision: 展示数值时的精度
196
209
  """
197
- from statistics import quantiles
198
210
 
211
+ # 1 各种细分的格式化方法
199
212
  def fmt0(v):
213
+ # 数量类整数的格式
200
214
  return human_readable_number(v, '万')
201
215
 
202
- def fmt(v):
203
- return human_readable_number(v, unit, precision)
216
+ def fmt1(v):
217
+ if isinstance(v, str):
218
+ return v
219
+ return human_readable_number(v, unit or 'K', precision)
204
220
 
205
- desc = []
221
+ def fmt2(v):
222
+ # 日期类数据的格式化
223
+ # todo 这个应该数据的具体格式来设置的,但是这个现在有点难写,先写死
224
+ if isinstance(v, str):
225
+ return v
226
+ elif isinstance(v, (int, float)):
227
+ v = datetime.datetime.fromtimestamp(v)
228
+
229
+ return v.strftime(unit or '%Y-%m-%d %H:%M:%S')
230
+
231
+ def fmt2b(v):
232
+ # 时间长度类数据的格式化
233
+ return human_readable_number(v, '秒')
234
+
235
+ if 'timestamp' in self.date_type:
236
+ fmt = fmt2
237
+ fmtb = fmt2b
238
+ else:
239
+ fmt = fmtb = fmt1
240
+
241
+ # 2 生成统计报告
242
+ desc = {}
206
243
  if self.raw_n and self.raw_n > self.n:
207
- desc.append(f"非数值数量:{fmt0(self.raw_n - self.n)}")
244
+ desc["总数"] = f"{fmt0(self.n)}/{fmt0(self.raw_n)}≈{self.n / self.raw_n:.2%}"
245
+ else:
246
+ desc["总数"] = f"{fmt0(self.n)}"
208
247
 
209
- desc.append(f"总数:{fmt0(self.n)}")
210
- desc.append(f"总和:{fmt(self.sum)}")
211
- desc.append(f'均值±标准差:{fmt(self.mean)}±{fmt(self.std)}')
248
+ if self.sum is not None:
249
+ desc["总和"] = f"{fmt(self.sum)}"
250
+ if self.mean is not None and self.std is not None:
251
+ desc["均值±标准差"] = f"{fmt(self.mean)}±{fmtb(self.std)}"
252
+ elif self.mean is not None:
253
+ desc["均值"] = f"{fmt(self.mean)}"
254
+ elif self.std is not None:
255
+ desc["标准差"] = f"{fmtb(self.std)}"
212
256
 
213
257
  if self.values:
214
258
  dist = [self.values[0]]
215
- if percentile > 2:
216
- quartiles = quantiles(self.values, n=percentile - 1)
259
+ if percentile_count > 2:
260
+ quartiles = quantiles(self.values, n=percentile_count - 1)
217
261
  dist += quartiles
218
262
  dist.append(self.values[-1])
219
263
 
220
- desc.append(f"分布:{'/'.join([fmt(v) for v in dist])}")
221
- elif self.dist: # 此时当前函数的percentile设置失效,以dist中存储的情况为准
222
- desc.append(f"分布:{'/'.join([fmt(v) for v in self.dist])}")
264
+ desc["分布"] = '/'.join([fmt(v) for v in dist])
265
+ elif self.dist:
266
+ desc["分布"] = '/'.join([fmt(v) for v in self.dist])
267
+
268
+ return desc
269
+
270
+ def summary(self, unit=None, precision=4, percentile_count=5):
271
+ """ 文本汇总性的报告
272
+
273
+ :param percentile_count: 包括两个极值端点的切分点数,
274
+ 设置2,就是不设置分位数,就是只展示最小、最大值
275
+ 如果设置了3,就表示"中位数、二分位数",在展示的时候,会显示50%位置的分位数值
276
+ 如果设置了5,就相当于"四分位数",会显示25%、50%、75%位置的分位数值
277
+ :param unit: 展示数值时使用的单位
278
+ :param precision: 展示数值时的精度
279
+ """
280
+ desc = self._summary(unit, precision, percentile_count)
281
+ return '\t'.join([f"{key}: {value}" for key, value in desc.items()])
282
+
283
+ def calculate_ratios(self, x_values, fmt=False):
284
+ """ 计算并返回一个字典,其中包含每个 x_values 中的值与其小于等于该值的元素的比例
285
+
286
+ :param x_values: 一个数值列表,用来计算每个数值小于等于它的元素的比例
287
+ :param fmt: 直接将值格式化好
288
+ :return: 一个字典,键为输入的数值,值为对应的比例(百分比)
289
+ """
290
+ ratio_dict = {}
291
+ for x in x_values:
292
+ position = bisect_right(self.values, x)
293
+ if self.n > 0:
294
+ ratio = (position / self.n)
295
+ else:
296
+ ratio = 0
297
+ ratio_dict[x] = ratio
298
+
299
+ if fmt:
300
+ ratio_dict = {x: f'{ratio:.2%}' for x, ratio in ratio_dict.items()}
223
301
 
224
- return '\t'.join(desc)
302
+ return ratio_dict
225
303
 
226
304
 
227
305
  class Groups:
@@ -46,7 +46,7 @@ from pyxllib.prog.pupil import utc_now, utc_timestamp
46
46
  from pyxllib.prog.specialist import XlOsEnv
47
47
  from pyxllib.algo.pupil import ValuesStat2
48
48
  from pyxllib.file.specialist import get_etag
49
- from pyxllib.data.sqlite import SqlBase
49
+ from pyxllib.data.sqlite import SqlBase, SqlBuilder
50
50
 
51
51
 
52
52
  class Connection(psycopg.Connection, SqlBase):
@@ -147,6 +147,28 @@ WHERE {table_name}.{item_id_name} = cte.{item_id_name}"""
147
147
  # cur.close()
148
148
  return data
149
149
 
150
+ def exec2dict_batch(self, sql, batch_size=1000, **kwargs):
151
+ """ 分批返回数据的版本
152
+
153
+ :return:
154
+ 第1个值,是一个迭代器,看起来仍然能一条一条返回,实际后台是按照batch_size打包获取的
155
+ 第2个值,是数据总数
156
+ """
157
+ if not isinstance(sql, SqlBuilder):
158
+ raise ValueError('暂时只能搭配SQLBuilder使用')
159
+
160
+ num = self.exec2one(sql.build_count())
161
+ cur = self.exec2dict(sql.build_select(), **kwargs)
162
+
163
+ def yield_row():
164
+ while True:
165
+ rows = cur.fetchmany(batch_size)
166
+ if not rows:
167
+ break
168
+ yield from rows
169
+
170
+ return yield_row(), num
171
+
150
172
  exec_dict = exec2dict
151
173
 
152
174
  def __4_数据类型(self):
@@ -234,72 +256,83 @@ WHERE {table_name}.{item_id_name} = cte.{item_id_name}"""
234
256
  def __6_高级统计(self):
235
257
  pass
236
258
 
237
- def get_field_valuesstat(self, table_name, field_name, percentile_count=5,
238
- cvt_numeric=True, by_data=False):
259
+ def get_column_valuesstat(self, table_name, column, percentile_count=5,
260
+ filter_condition=None, by_data=False):
239
261
  """ 获得指定表格的某个字段的统计特征ValuesStat2对象
240
262
 
241
263
  :param table_name: 表名
242
- :param field_name: 用于计算统计数据的字段名
264
+ :param column: 用于计算统计数据的字段名
243
265
  :param percentile_count: 分位数的数量,例如 3 表示只计算中位数
244
266
  :param by_data: 是否获得原始数据
245
267
  默认只获得统计特征,不获得原始数据
246
268
  """
247
269
 
248
270
  def init_from_db_data():
249
- values = self.exec2col(f'SELECT {field_name} FROM {table_name}')
250
- if cvt_numeric: # 这个是numeric格式字段,是"字符串",要做个转换
271
+ sql = SqlBuilder(table_name)
272
+ if filter_condition:
273
+ sql.where(filter_condition)
274
+ values = self.exec2col(sql.build_select(column))
275
+ if data_type == 'numeric':
251
276
  values = [x and float(x) for x in values]
252
-
253
- return ValuesStat2(raw_values=values)
277
+ return ValuesStat2(raw_values=values, data_type=data_type)
254
278
 
255
279
  def init_from_db():
256
- # 构建基础的 SQL 查询
257
- sql_query = f"""
258
- SELECT
259
- COUNT(*) AS total_count,
260
- COUNT({field_name}) AS non_null_count,
261
- SUM({field_name}) AS total_sum,
262
- AVG({field_name}) AS average,
263
- STDDEV({field_name}) AS standard_deviation,
264
- MIN({field_name}) AS min_value,
265
- MAX({field_name}) AS max_value
266
- """
280
+ # 1 构建基础的 SQL 查询
281
+ sql = SqlBuilder(table_name)
282
+ sql.select("COUNT(*) AS total_count")
283
+ sql.select(f"COUNT({column}) AS non_null_count")
284
+ sql.select(f"MIN({column}) AS min_value")
285
+ sql.select(f"MAX({column}) AS max_value")
286
+ if data_type and 'timestamp' in data_type:
287
+ percentile_type = 'PERCENTILE_DISC'
288
+ # todo 其实时间类也可以"泛化"一种平均值、标准差算法的,这需要获取全量数据,然后自己计算
289
+ elif data_type == 'text':
290
+ percentile_type = 'PERCENTILE_DISC'
291
+ else: # 默认是正常的数值类型
292
+ sql.select(f"SUM({column}) AS total_sum")
293
+ sql.select(f"AVG({column}) AS average")
294
+ sql.select(f"STDDEV({column}) AS standard_deviation")
295
+ percentile_type = 'PERCENTILE_CONT'
267
296
 
268
297
  percentiles = []
269
298
  # 根据分位点的数量动态添加分位数计算
270
299
  if percentile_count > 2:
271
300
  step = 1 / (percentile_count - 1)
272
301
  percentiles = [(i * step) for i in range(1, percentile_count - 1)]
273
- percentiles_query = ", ".join(
274
- f"PERCENTILE_CONT({p:.2f}) WITHIN GROUP (ORDER BY {field_name}) AS percentile_{int(p * 100)}"
275
- for p in percentiles
276
- )
277
- sql_query += ", " + percentiles_query
302
+ for p in percentiles:
303
+ sql.select(f"{percentile_type}({p:.2f}) WITHIN GROUP (ORDER BY {column}) "
304
+ f"AS percentile_{int(p * 100)}")
278
305
 
279
- sql_query += f" FROM {table_name};"
306
+ if filter_condition:
307
+ sql.where(filter_condition)
280
308
 
281
- # 执行 SQL 查询
282
- row = self.exec2dict(sql_query).fetchone()
309
+ row = self.exec2dict(sql.build_select()).fetchone()
283
310
 
284
- # 创建一个新实例并将从数据库获得的数据填充到相应的属性
285
- x = ValuesStat2()
311
+ # 2 统计展示
312
+ x = ValuesStat2(data_type=data_type)
286
313
  x.raw_n = row['total_count']
287
314
  x.n = row['non_null_count']
288
- x.sum = row['total_sum']
289
- x.mean = row['average']
290
- x.std = row['standard_deviation']
315
+ if not x.n:
316
+ return x
317
+
318
+ x.sum = row.get('total_sum', None)
319
+ x.mean = row.get('average', None)
320
+ x.std = row.get('standard_deviation', None)
291
321
 
292
322
  # 如果计算了分位数,填充相应属性
293
323
  x.dist = [row['min_value']] + [row[f"percentile_{int(p * 100)}"] for p in percentiles] + [row['max_value']]
294
- if cvt_numeric:
324
+ if data_type == 'numeric':
295
325
  x.dist = [float(x) for x in x.dist]
296
326
 
297
327
  return x
298
328
 
329
+ data_type = self.get_column_data_type(table_name, column)
299
330
  if by_data:
300
- return init_from_db_data()
331
+ vs = init_from_db_data()
301
332
  else:
302
- return init_from_db()
333
+ vs = init_from_db()
334
+
335
+ return vs
303
336
 
304
337
 
305
338
  """
@@ -4,6 +4,7 @@
4
4
  # @Email : 877362867@qq.com
5
5
  # @Date : 2022/04/12 08:59
6
6
 
7
+ import copy
7
8
  import json
8
9
  import re
9
10
  import sqlite3
@@ -18,6 +19,118 @@ warnings.filterwarnings('ignore', message="pandas only support SQLAlchemy connec
18
19
  warnings.filterwarnings('ignore', message="pandas only supports SQLAlchemy connectable")
19
20
 
20
21
 
22
+ class SqlBuilder:
23
+ def __init__(self, table=''):
24
+ self.table = table
25
+ self._select = []
26
+ self._set = []
27
+ self._where = []
28
+ self._order_by = []
29
+ self._group_by = []
30
+ self._limit = None # 限制最多读多少条数据
31
+ self._offset = None # 从第几条数据开始读
32
+
33
+ def copy(self):
34
+ # 拷贝一个当前状态的副本sql
35
+ return copy.deepcopy(self)
36
+
37
+ def __1_组件(self):
38
+ pass
39
+
40
+ def from_table(self, table):
41
+ self.table = table
42
+ return self
43
+
44
+ def select(self, *columns):
45
+ self._select.extend(columns)
46
+ return self
47
+
48
+ def set(self, *columns):
49
+ self._set.extend(columns)
50
+ return self
51
+
52
+ def where(self, condition):
53
+ self._where.append(condition)
54
+ return self
55
+
56
+ def where_in(self, column, values):
57
+ if values is None:
58
+ return self
59
+
60
+ if isinstance(values, str):
61
+ values = [values]
62
+ values_str = ', '.join(f"'{str(value)}'" for value in values)
63
+ if len(values) == 1:
64
+ self._where.append(f"{column} = {values_str[0]}")
65
+ else:
66
+ self._where.append(f"{column} IN ({values_str})")
67
+ return self
68
+
69
+ def where_or(self, *conditions):
70
+ """ 输入的这一批条件,作为OR组合后成为一个整体条件
71
+ """
72
+ self._where.append(f"({' OR '.join(conditions)})")
73
+ return self
74
+
75
+ def group_by(self, *columns):
76
+ self._group_by.extend(columns)
77
+ return self
78
+
79
+ def order_by(self, *columns):
80
+ self._order_by.extend(columns)
81
+ return self
82
+
83
+ def limit(self, limit, offset=None):
84
+ self._limit = limit
85
+ self._offset = offset
86
+ return self
87
+
88
+ def __2_build_命令(self):
89
+ pass
90
+
91
+ def build_select(self, *columns):
92
+ if columns:
93
+ columns = self._select + list(columns)
94
+ else:
95
+ columns = self._select
96
+
97
+ sql = [f"SELECT {', '.join(columns) or '*'}", f"FROM {self.table}"]
98
+ if self._where:
99
+ sql.append(f"WHERE {' AND '.join(self._where)}")
100
+ if self._group_by:
101
+ sql.append(f"GROUP BY {', '.join(self._group_by)}")
102
+ if self._order_by:
103
+ sql.append(f"ORDER BY {', '.join(self._order_by)}")
104
+ if self._limit is not None:
105
+ limit_clause = f"LIMIT {self._limit}"
106
+ if self._offset is not None:
107
+ limit_clause += f" OFFSET {self._offset}"
108
+ sql.append(limit_clause)
109
+ return '\n'.join(sql)
110
+
111
+ def build_count(self):
112
+ sql = [f"SELECT COUNT(*)", f"FROM {self.table}"]
113
+ if self._where:
114
+ sql.append(f"WHERE {' AND '.join(self._where)}")
115
+ if self._group_by:
116
+ sql.append(f"GROUP BY {', '.join(self._group_by)}")
117
+ return '\n'.join(sql)
118
+
119
+ def build_update(self):
120
+ sql = [f"UPDATE {self.table}"]
121
+ if self._set:
122
+ sql.append(f"SET {', '.join(self._set)}")
123
+ if self._where:
124
+ sql.append(f"WHERE {' AND '.join(self._where)}")
125
+ return '\n'.join(sql)
126
+
127
+ def build_check_data_type(self, column):
128
+ sql = SqlBuilder('information_schema.columns')
129
+ sql.select(f"data_type")
130
+ sql.where(f"table_name='{self.table}' AND column_name='{column}'")
131
+ return sql.build_select()
132
+
133
+
21
134
  class SqlBase:
22
135
  """ Sql语法通用的功能 """
23
136
 
@@ -285,6 +398,10 @@ class SqlBase:
285
398
  print("No 'FROM' keyword found in the data query.")
286
399
  return 0
287
400
 
401
+ def get_column_data_type(self, table_name, col_name):
402
+ """ 获取表格中某一列的数据类型 """
403
+ return self.exec2one(SqlBuilder(table_name).build_check_data_type(col_name))
404
+
288
405
 
289
406
  class Connection(sqlite3.Connection, SqlBase):
290
407
  """
@@ -28,7 +28,7 @@ import fire
28
28
  import pandas as pd
29
29
  from tqdm import tqdm
30
30
  import requests
31
- import requests_cache
31
+ # import requests_cache
32
32
 
33
33
  from pyxllib.text.pupil import chinese2digits, grp_chinese_char
34
34
  from pyxllib.file.xlsxlib import openpyxl
@@ -51,6 +51,7 @@ def infer_file_format(file_path):
51
51
  elif ext in ['.ppt', '.pptx']:
52
52
  fmt = 'pptx'
53
53
  elif ext in ['.xls', '.xlsx']:
54
+ # todo 其实excel还有xlsm的可能,但是用libreoffice可能没有微软365那样可以判断出宏的情况保存为xlsm
54
55
  fmt = 'xlsx'
55
56
  else:
56
57
  raise ValueError("不支持的文件格式")
@@ -1437,9 +1437,9 @@ class XlPath(type(pathlib.Path())):
1437
1437
  dst = XlPath(dst)
1438
1438
  if dst.exist_preprcs(if_exists):
1439
1439
  if self.is_file():
1440
- shutil.copy2(self, dst)
1440
+ return shutil.copy2(self, dst)
1441
1441
  else:
1442
- shutil.copytree(self, dst)
1442
+ return shutil.copytree(self, dst)
1443
1443
 
1444
1444
  def move(self, dst, if_exists=None):
1445
1445
  if not self.exists():
@@ -1465,7 +1465,9 @@ class XlPath(type(pathlib.Path())):
1465
1465
  if not self.exists():
1466
1466
  return self
1467
1467
 
1468
- if '/' in new_name:
1468
+ if not isinstance(new_name, str):
1469
+ raise ValueError(f'rename2只能做重命名操作,目标路径必须是一个str')
1470
+ elif '/' in new_name:
1469
1471
  raise ValueError(f'rename2只能做重命名操作,目标路径中不能包含"/"')
1470
1472
  elif '\\' in new_name:
1471
1473
  raise ValueError(f'rename2只能做重命名操作,目标路径中不能包含"\\"')
@@ -1485,6 +1487,14 @@ class XlPath(type(pathlib.Path())):
1485
1487
  self.rename(dst)
1486
1488
  return dst
1487
1489
 
1490
+ def rename_stem(self, stem, if_exists=None):
1491
+ """ 重命名文件的stem """
1492
+ return self.rename2(stem + self.suffix, if_exists)
1493
+
1494
+ def rename_suffix(self, suffix, if_exists=None):
1495
+ """ 重命名文件的suffix """
1496
+ return self.rename2(self.stem + suffix, if_exists)
1497
+
1488
1498
  def delete(self):
1489
1499
  if self.is_file():
1490
1500
  os.remove(self)
@@ -2504,34 +2514,55 @@ class DirsFileFinder:
2504
2514
  for d in dirs:
2505
2515
  self.add_dir(d)
2506
2516
 
2507
- def add_dir(self, p):
2517
+ def add_dir(self, p, cvt_name_func=None):
2508
2518
  """ 添加备用检索目录
2509
2519
  当前面的目录找不到匹配项的时候,会使用备用目录的文件
2510
2520
  备用目录可以一直添加,有多个,优先级逐渐降低
2521
+
2522
+ :param cvt_name_func: 对名称做个转换再匹配
2511
2523
  """
2512
2524
  files = list(XlPath(p).rglob_files())
2513
- for f in files:
2514
- self.names[f.name].append(f)
2515
- self.stems[f.stem].append(f)
2525
+ if cvt_name_func:
2526
+ for f in files:
2527
+ self.names[cvt_name_func(f.name)].append(f)
2528
+ self.stems[cvt_name_func(f.stem)].append(f)
2529
+ else:
2530
+ for f in files:
2531
+ self.names[f.name].append(f)
2532
+ self.stems[f.stem].append(f)
2516
2533
 
2517
2534
  def find_name(self, name):
2518
2535
  """ 返回第一个匹配的结果 """
2519
- names = self.find_names(name)
2520
- if names:
2521
- return names[0]
2536
+ files = self.find_names(name)
2537
+ if files:
2538
+ return files[0]
2522
2539
 
2523
2540
  def find_names(self, name):
2524
2541
  """ 返回所有匹配的结果 """
2525
2542
  return self.names[name]
2526
2543
 
2527
2544
  def find_stem(self, stem):
2528
- stems = self.find_stems(stem)
2529
- if stems:
2530
- return stems[0]
2545
+ files = self.find_stems(stem)
2546
+ if files:
2547
+ return files[0]
2531
2548
 
2532
2549
  def find_stems(self, stem):
2533
2550
  return self.stems[stem]
2534
2551
 
2552
+ def find_prefix_name(self, prefix_name, suffix=None):
2553
+ files = self.find_prefix_names(prefix_name, suffix=suffix)
2554
+ if files:
2555
+ return files[0]
2556
+
2557
+ def find_prefix_names(self, prefix_name, suffix=None):
2558
+ """ name中前缀为prefix_name """
2559
+ filess = [files for name, files in self.names.items() if name.startswith(prefix_name)]
2560
+ # 将嵌套的list展平
2561
+ files = [file for files in filess for file in files]
2562
+ if suffix:
2563
+ files = [file for file in files if file.suffix == suffix]
2564
+ return files
2565
+
2535
2566
 
2536
2567
  class TwinDirs:
2537
2568
  def __init__(self, src_dir, dst_dir):
@@ -259,6 +259,9 @@ def human_readable_number(value, base_type='K', precision=4):
259
259
  :param str base_type: 进制类型,'K'为1000进制, 'KB'为1024进制(KiB同理), '万'为中文万进制
260
260
  :return: 美化后的字符串
261
261
  """
262
+ if value is None:
263
+ return ''
264
+
262
265
  if abs(value) < 1:
263
266
  return f'{value:.{precision}g}'
264
267
 
@@ -16,7 +16,10 @@ from pyxllib.file.specialist import File, Dir, filesmatch, get_encoding, XlPath
16
16
  # BCompare.exe, bcompare函数要用
17
17
 
18
18
  class BCompare(Explorer):
19
- def __init__(self, app='BCompare', shell=False):
19
+ def __init__(self, app='bcomp', shell=False):
20
+ """
21
+ 240512周日20:06,本来写的是BCompare,但是友鑫mac电脑上发现似乎有问题,所以改成bcomp,这种在windows上也能用
22
+ """
20
23
  super().__init__(app, shell)
21
24
 
22
25
  @classmethod
@@ -48,7 +51,7 @@ class BCompare(Explorer):
48
51
  default_suffix = None
49
52
  for i, arg in enumerate(args):
50
53
  f = XlPath.safe_init(arg)
51
- if f.is_file(): # 是文件对象,且存在
54
+ if f is not None and f.is_file(): # 是文件对象,且存在
52
55
  new_args.append(f)
53
56
  if not default_suffix:
54
57
  default_suffix = f.suffix