pyxllib 0.3.96__py3-none-any.whl → 0.3.197__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.
- pyxllib/algo/geo.py +12 -0
- pyxllib/algo/intervals.py +1 -1
- pyxllib/algo/matcher.py +78 -0
- pyxllib/algo/pupil.py +187 -19
- pyxllib/algo/specialist.py +2 -1
- pyxllib/algo/stat.py +38 -2
- {pyxlpr → pyxllib/autogui}/__init__.py +1 -1
- pyxllib/autogui/activewin.py +246 -0
- pyxllib/autogui/all.py +9 -0
- pyxllib/{ext/autogui → autogui}/autogui.py +40 -11
- pyxllib/autogui/uiautolib.py +362 -0
- pyxllib/autogui/wechat.py +827 -0
- pyxllib/autogui/wechat_msg.py +421 -0
- pyxllib/autogui/wxautolib.py +84 -0
- pyxllib/cv/slidercaptcha.py +137 -0
- pyxllib/data/echarts.py +123 -12
- pyxllib/data/jsonlib.py +89 -0
- pyxllib/data/pglib.py +514 -30
- pyxllib/data/sqlite.py +231 -4
- pyxllib/ext/JLineViewer.py +14 -1
- pyxllib/ext/drissionlib.py +277 -0
- pyxllib/ext/kq5034lib.py +0 -1594
- pyxllib/ext/robustprocfile.py +497 -0
- pyxllib/ext/unixlib.py +6 -5
- pyxllib/ext/utools.py +108 -95
- pyxllib/ext/webhook.py +32 -14
- pyxllib/ext/wjxlib.py +88 -0
- pyxllib/ext/wpsapi.py +124 -0
- pyxllib/ext/xlwork.py +9 -0
- pyxllib/ext/yuquelib.py +1003 -71
- pyxllib/file/docxlib.py +1 -1
- pyxllib/file/libreoffice.py +165 -0
- pyxllib/file/movielib.py +9 -0
- pyxllib/file/packlib/__init__.py +112 -75
- pyxllib/file/pdflib.py +1 -1
- pyxllib/file/pupil.py +1 -1
- pyxllib/file/specialist/dirlib.py +1 -1
- pyxllib/file/specialist/download.py +10 -3
- pyxllib/file/specialist/filelib.py +266 -55
- pyxllib/file/xlsxlib.py +205 -50
- pyxllib/file/xlsyncfile.py +341 -0
- pyxllib/prog/cachetools.py +64 -0
- pyxllib/prog/filelock.py +42 -0
- pyxllib/prog/multiprogs.py +940 -0
- pyxllib/prog/newbie.py +9 -2
- pyxllib/prog/pupil.py +129 -60
- pyxllib/prog/specialist/__init__.py +176 -2
- pyxllib/prog/specialist/bc.py +5 -2
- pyxllib/prog/specialist/browser.py +11 -2
- pyxllib/prog/specialist/datetime.py +68 -0
- pyxllib/prog/specialist/tictoc.py +12 -13
- pyxllib/prog/specialist/xllog.py +5 -5
- pyxllib/prog/xlosenv.py +7 -0
- pyxllib/text/airscript.js +744 -0
- pyxllib/text/charclasslib.py +17 -5
- pyxllib/text/jiebalib.py +6 -3
- pyxllib/text/jinjalib.py +32 -0
- pyxllib/text/jsa_ai_prompt.md +271 -0
- pyxllib/text/jscode.py +159 -4
- pyxllib/text/nestenv.py +1 -1
- pyxllib/text/newbie.py +12 -0
- pyxllib/text/pupil/common.py +26 -0
- pyxllib/text/specialist/ptag.py +2 -2
- pyxllib/text/templates/echart_base.html +11 -0
- pyxllib/text/templates/highlight_code.html +17 -0
- pyxllib/text/templates/latex_editor.html +103 -0
- pyxllib/text/xmllib.py +76 -14
- pyxllib/xl.py +2 -1
- pyxllib-0.3.197.dist-info/METADATA +48 -0
- pyxllib-0.3.197.dist-info/RECORD +126 -0
- {pyxllib-0.3.96.dist-info → pyxllib-0.3.197.dist-info}/WHEEL +1 -2
- pyxllib/ext/autogui/__init__.py +0 -8
- pyxllib-0.3.96.dist-info/METADATA +0 -51
- pyxllib-0.3.96.dist-info/RECORD +0 -333
- pyxllib-0.3.96.dist-info/top_level.txt +0 -2
- pyxlpr/ai/__init__.py +0 -5
- pyxlpr/ai/clientlib.py +0 -1281
- pyxlpr/ai/specialist.py +0 -286
- pyxlpr/ai/torch_app.py +0 -172
- pyxlpr/ai/xlpaddle.py +0 -655
- pyxlpr/ai/xltorch.py +0 -705
- pyxlpr/data/__init__.py +0 -11
- pyxlpr/data/coco.py +0 -1325
- pyxlpr/data/datacls.py +0 -365
- pyxlpr/data/datasets.py +0 -200
- pyxlpr/data/gptlib.py +0 -1291
- pyxlpr/data/icdar/__init__.py +0 -96
- pyxlpr/data/icdar/deteval.py +0 -377
- pyxlpr/data/icdar/icdar2013.py +0 -341
- pyxlpr/data/icdar/iou.py +0 -340
- pyxlpr/data/icdar/rrc_evaluation_funcs_1_1.py +0 -463
- pyxlpr/data/imtextline.py +0 -473
- pyxlpr/data/labelme.py +0 -866
- pyxlpr/data/removeline.py +0 -179
- pyxlpr/data/specialist.py +0 -57
- pyxlpr/eval/__init__.py +0 -85
- pyxlpr/paddleocr.py +0 -776
- pyxlpr/ppocr/__init__.py +0 -15
- pyxlpr/ppocr/configs/rec/multi_language/generate_multi_language_configs.py +0 -226
- pyxlpr/ppocr/data/__init__.py +0 -135
- pyxlpr/ppocr/data/imaug/ColorJitter.py +0 -26
- pyxlpr/ppocr/data/imaug/__init__.py +0 -67
- pyxlpr/ppocr/data/imaug/copy_paste.py +0 -170
- pyxlpr/ppocr/data/imaug/east_process.py +0 -437
- pyxlpr/ppocr/data/imaug/gen_table_mask.py +0 -244
- pyxlpr/ppocr/data/imaug/iaa_augment.py +0 -114
- pyxlpr/ppocr/data/imaug/label_ops.py +0 -789
- pyxlpr/ppocr/data/imaug/make_border_map.py +0 -184
- pyxlpr/ppocr/data/imaug/make_pse_gt.py +0 -106
- pyxlpr/ppocr/data/imaug/make_shrink_map.py +0 -126
- pyxlpr/ppocr/data/imaug/operators.py +0 -433
- pyxlpr/ppocr/data/imaug/pg_process.py +0 -906
- pyxlpr/ppocr/data/imaug/randaugment.py +0 -143
- pyxlpr/ppocr/data/imaug/random_crop_data.py +0 -239
- pyxlpr/ppocr/data/imaug/rec_img_aug.py +0 -533
- pyxlpr/ppocr/data/imaug/sast_process.py +0 -777
- pyxlpr/ppocr/data/imaug/text_image_aug/__init__.py +0 -17
- pyxlpr/ppocr/data/imaug/text_image_aug/augment.py +0 -120
- pyxlpr/ppocr/data/imaug/text_image_aug/warp_mls.py +0 -168
- pyxlpr/ppocr/data/lmdb_dataset.py +0 -115
- pyxlpr/ppocr/data/pgnet_dataset.py +0 -104
- pyxlpr/ppocr/data/pubtab_dataset.py +0 -107
- pyxlpr/ppocr/data/simple_dataset.py +0 -372
- pyxlpr/ppocr/losses/__init__.py +0 -61
- pyxlpr/ppocr/losses/ace_loss.py +0 -52
- pyxlpr/ppocr/losses/basic_loss.py +0 -135
- pyxlpr/ppocr/losses/center_loss.py +0 -88
- pyxlpr/ppocr/losses/cls_loss.py +0 -30
- pyxlpr/ppocr/losses/combined_loss.py +0 -67
- pyxlpr/ppocr/losses/det_basic_loss.py +0 -208
- pyxlpr/ppocr/losses/det_db_loss.py +0 -80
- pyxlpr/ppocr/losses/det_east_loss.py +0 -63
- pyxlpr/ppocr/losses/det_pse_loss.py +0 -149
- pyxlpr/ppocr/losses/det_sast_loss.py +0 -121
- pyxlpr/ppocr/losses/distillation_loss.py +0 -272
- pyxlpr/ppocr/losses/e2e_pg_loss.py +0 -140
- pyxlpr/ppocr/losses/kie_sdmgr_loss.py +0 -113
- pyxlpr/ppocr/losses/rec_aster_loss.py +0 -99
- pyxlpr/ppocr/losses/rec_att_loss.py +0 -39
- pyxlpr/ppocr/losses/rec_ctc_loss.py +0 -44
- pyxlpr/ppocr/losses/rec_enhanced_ctc_loss.py +0 -70
- pyxlpr/ppocr/losses/rec_nrtr_loss.py +0 -30
- pyxlpr/ppocr/losses/rec_sar_loss.py +0 -28
- pyxlpr/ppocr/losses/rec_srn_loss.py +0 -47
- pyxlpr/ppocr/losses/table_att_loss.py +0 -109
- pyxlpr/ppocr/metrics/__init__.py +0 -44
- pyxlpr/ppocr/metrics/cls_metric.py +0 -45
- pyxlpr/ppocr/metrics/det_metric.py +0 -82
- pyxlpr/ppocr/metrics/distillation_metric.py +0 -73
- pyxlpr/ppocr/metrics/e2e_metric.py +0 -86
- pyxlpr/ppocr/metrics/eval_det_iou.py +0 -274
- pyxlpr/ppocr/metrics/kie_metric.py +0 -70
- pyxlpr/ppocr/metrics/rec_metric.py +0 -75
- pyxlpr/ppocr/metrics/table_metric.py +0 -50
- pyxlpr/ppocr/modeling/architectures/__init__.py +0 -32
- pyxlpr/ppocr/modeling/architectures/base_model.py +0 -88
- pyxlpr/ppocr/modeling/architectures/distillation_model.py +0 -60
- pyxlpr/ppocr/modeling/backbones/__init__.py +0 -54
- pyxlpr/ppocr/modeling/backbones/det_mobilenet_v3.py +0 -268
- pyxlpr/ppocr/modeling/backbones/det_resnet_vd.py +0 -246
- pyxlpr/ppocr/modeling/backbones/det_resnet_vd_sast.py +0 -285
- pyxlpr/ppocr/modeling/backbones/e2e_resnet_vd_pg.py +0 -265
- pyxlpr/ppocr/modeling/backbones/kie_unet_sdmgr.py +0 -186
- pyxlpr/ppocr/modeling/backbones/rec_mobilenet_v3.py +0 -138
- pyxlpr/ppocr/modeling/backbones/rec_mv1_enhance.py +0 -258
- pyxlpr/ppocr/modeling/backbones/rec_nrtr_mtb.py +0 -48
- pyxlpr/ppocr/modeling/backbones/rec_resnet_31.py +0 -210
- pyxlpr/ppocr/modeling/backbones/rec_resnet_aster.py +0 -143
- pyxlpr/ppocr/modeling/backbones/rec_resnet_fpn.py +0 -307
- pyxlpr/ppocr/modeling/backbones/rec_resnet_vd.py +0 -286
- pyxlpr/ppocr/modeling/heads/__init__.py +0 -54
- pyxlpr/ppocr/modeling/heads/cls_head.py +0 -52
- pyxlpr/ppocr/modeling/heads/det_db_head.py +0 -118
- pyxlpr/ppocr/modeling/heads/det_east_head.py +0 -121
- pyxlpr/ppocr/modeling/heads/det_pse_head.py +0 -37
- pyxlpr/ppocr/modeling/heads/det_sast_head.py +0 -128
- pyxlpr/ppocr/modeling/heads/e2e_pg_head.py +0 -253
- pyxlpr/ppocr/modeling/heads/kie_sdmgr_head.py +0 -206
- pyxlpr/ppocr/modeling/heads/multiheadAttention.py +0 -163
- pyxlpr/ppocr/modeling/heads/rec_aster_head.py +0 -393
- pyxlpr/ppocr/modeling/heads/rec_att_head.py +0 -202
- pyxlpr/ppocr/modeling/heads/rec_ctc_head.py +0 -88
- pyxlpr/ppocr/modeling/heads/rec_nrtr_head.py +0 -826
- pyxlpr/ppocr/modeling/heads/rec_sar_head.py +0 -402
- pyxlpr/ppocr/modeling/heads/rec_srn_head.py +0 -280
- pyxlpr/ppocr/modeling/heads/self_attention.py +0 -406
- pyxlpr/ppocr/modeling/heads/table_att_head.py +0 -246
- pyxlpr/ppocr/modeling/necks/__init__.py +0 -32
- pyxlpr/ppocr/modeling/necks/db_fpn.py +0 -111
- pyxlpr/ppocr/modeling/necks/east_fpn.py +0 -188
- pyxlpr/ppocr/modeling/necks/fpn.py +0 -138
- pyxlpr/ppocr/modeling/necks/pg_fpn.py +0 -314
- pyxlpr/ppocr/modeling/necks/rnn.py +0 -92
- pyxlpr/ppocr/modeling/necks/sast_fpn.py +0 -284
- pyxlpr/ppocr/modeling/necks/table_fpn.py +0 -110
- pyxlpr/ppocr/modeling/transforms/__init__.py +0 -28
- pyxlpr/ppocr/modeling/transforms/stn.py +0 -135
- pyxlpr/ppocr/modeling/transforms/tps.py +0 -308
- pyxlpr/ppocr/modeling/transforms/tps_spatial_transformer.py +0 -156
- pyxlpr/ppocr/optimizer/__init__.py +0 -61
- pyxlpr/ppocr/optimizer/learning_rate.py +0 -228
- pyxlpr/ppocr/optimizer/lr_scheduler.py +0 -49
- pyxlpr/ppocr/optimizer/optimizer.py +0 -160
- pyxlpr/ppocr/optimizer/regularizer.py +0 -52
- pyxlpr/ppocr/postprocess/__init__.py +0 -55
- pyxlpr/ppocr/postprocess/cls_postprocess.py +0 -33
- pyxlpr/ppocr/postprocess/db_postprocess.py +0 -234
- pyxlpr/ppocr/postprocess/east_postprocess.py +0 -143
- pyxlpr/ppocr/postprocess/locality_aware_nms.py +0 -200
- pyxlpr/ppocr/postprocess/pg_postprocess.py +0 -52
- pyxlpr/ppocr/postprocess/pse_postprocess/__init__.py +0 -15
- pyxlpr/ppocr/postprocess/pse_postprocess/pse/__init__.py +0 -29
- pyxlpr/ppocr/postprocess/pse_postprocess/pse/setup.py +0 -14
- pyxlpr/ppocr/postprocess/pse_postprocess/pse_postprocess.py +0 -118
- pyxlpr/ppocr/postprocess/rec_postprocess.py +0 -654
- pyxlpr/ppocr/postprocess/sast_postprocess.py +0 -355
- pyxlpr/ppocr/tools/__init__.py +0 -14
- pyxlpr/ppocr/tools/eval.py +0 -83
- pyxlpr/ppocr/tools/export_center.py +0 -77
- pyxlpr/ppocr/tools/export_model.py +0 -129
- pyxlpr/ppocr/tools/infer/predict_cls.py +0 -151
- pyxlpr/ppocr/tools/infer/predict_det.py +0 -300
- pyxlpr/ppocr/tools/infer/predict_e2e.py +0 -169
- pyxlpr/ppocr/tools/infer/predict_rec.py +0 -414
- pyxlpr/ppocr/tools/infer/predict_system.py +0 -204
- pyxlpr/ppocr/tools/infer/utility.py +0 -629
- pyxlpr/ppocr/tools/infer_cls.py +0 -83
- pyxlpr/ppocr/tools/infer_det.py +0 -134
- pyxlpr/ppocr/tools/infer_e2e.py +0 -122
- pyxlpr/ppocr/tools/infer_kie.py +0 -153
- pyxlpr/ppocr/tools/infer_rec.py +0 -146
- pyxlpr/ppocr/tools/infer_table.py +0 -107
- pyxlpr/ppocr/tools/program.py +0 -596
- pyxlpr/ppocr/tools/test_hubserving.py +0 -117
- pyxlpr/ppocr/tools/train.py +0 -163
- pyxlpr/ppocr/tools/xlprog.py +0 -748
- pyxlpr/ppocr/utils/EN_symbol_dict.txt +0 -94
- pyxlpr/ppocr/utils/__init__.py +0 -24
- pyxlpr/ppocr/utils/dict/ar_dict.txt +0 -117
- pyxlpr/ppocr/utils/dict/arabic_dict.txt +0 -162
- pyxlpr/ppocr/utils/dict/be_dict.txt +0 -145
- pyxlpr/ppocr/utils/dict/bg_dict.txt +0 -140
- pyxlpr/ppocr/utils/dict/chinese_cht_dict.txt +0 -8421
- pyxlpr/ppocr/utils/dict/cyrillic_dict.txt +0 -163
- pyxlpr/ppocr/utils/dict/devanagari_dict.txt +0 -167
- pyxlpr/ppocr/utils/dict/en_dict.txt +0 -63
- pyxlpr/ppocr/utils/dict/fa_dict.txt +0 -136
- pyxlpr/ppocr/utils/dict/french_dict.txt +0 -136
- pyxlpr/ppocr/utils/dict/german_dict.txt +0 -143
- pyxlpr/ppocr/utils/dict/hi_dict.txt +0 -162
- pyxlpr/ppocr/utils/dict/it_dict.txt +0 -118
- pyxlpr/ppocr/utils/dict/japan_dict.txt +0 -4399
- pyxlpr/ppocr/utils/dict/ka_dict.txt +0 -153
- pyxlpr/ppocr/utils/dict/korean_dict.txt +0 -3688
- pyxlpr/ppocr/utils/dict/latin_dict.txt +0 -185
- pyxlpr/ppocr/utils/dict/mr_dict.txt +0 -153
- pyxlpr/ppocr/utils/dict/ne_dict.txt +0 -153
- pyxlpr/ppocr/utils/dict/oc_dict.txt +0 -96
- pyxlpr/ppocr/utils/dict/pu_dict.txt +0 -130
- pyxlpr/ppocr/utils/dict/rs_dict.txt +0 -91
- pyxlpr/ppocr/utils/dict/rsc_dict.txt +0 -134
- pyxlpr/ppocr/utils/dict/ru_dict.txt +0 -125
- pyxlpr/ppocr/utils/dict/ta_dict.txt +0 -128
- pyxlpr/ppocr/utils/dict/table_dict.txt +0 -277
- pyxlpr/ppocr/utils/dict/table_structure_dict.txt +0 -2759
- pyxlpr/ppocr/utils/dict/te_dict.txt +0 -151
- pyxlpr/ppocr/utils/dict/ug_dict.txt +0 -114
- pyxlpr/ppocr/utils/dict/uk_dict.txt +0 -142
- pyxlpr/ppocr/utils/dict/ur_dict.txt +0 -137
- pyxlpr/ppocr/utils/dict/xi_dict.txt +0 -110
- pyxlpr/ppocr/utils/dict90.txt +0 -90
- pyxlpr/ppocr/utils/e2e_metric/Deteval.py +0 -574
- pyxlpr/ppocr/utils/e2e_metric/polygon_fast.py +0 -83
- pyxlpr/ppocr/utils/e2e_utils/extract_batchsize.py +0 -87
- pyxlpr/ppocr/utils/e2e_utils/extract_textpoint_fast.py +0 -457
- pyxlpr/ppocr/utils/e2e_utils/extract_textpoint_slow.py +0 -592
- pyxlpr/ppocr/utils/e2e_utils/pgnet_pp_utils.py +0 -162
- pyxlpr/ppocr/utils/e2e_utils/visual.py +0 -162
- pyxlpr/ppocr/utils/en_dict.txt +0 -95
- pyxlpr/ppocr/utils/gen_label.py +0 -81
- pyxlpr/ppocr/utils/ic15_dict.txt +0 -36
- pyxlpr/ppocr/utils/iou.py +0 -54
- pyxlpr/ppocr/utils/logging.py +0 -69
- pyxlpr/ppocr/utils/network.py +0 -84
- pyxlpr/ppocr/utils/ppocr_keys_v1.txt +0 -6623
- pyxlpr/ppocr/utils/profiler.py +0 -110
- pyxlpr/ppocr/utils/save_load.py +0 -150
- pyxlpr/ppocr/utils/stats.py +0 -72
- pyxlpr/ppocr/utils/utility.py +0 -80
- pyxlpr/ppstructure/__init__.py +0 -13
- pyxlpr/ppstructure/predict_system.py +0 -187
- pyxlpr/ppstructure/table/__init__.py +0 -13
- pyxlpr/ppstructure/table/eval_table.py +0 -72
- pyxlpr/ppstructure/table/matcher.py +0 -192
- pyxlpr/ppstructure/table/predict_structure.py +0 -136
- pyxlpr/ppstructure/table/predict_table.py +0 -221
- pyxlpr/ppstructure/table/table_metric/__init__.py +0 -16
- pyxlpr/ppstructure/table/table_metric/parallel.py +0 -51
- pyxlpr/ppstructure/table/table_metric/table_metric.py +0 -247
- pyxlpr/ppstructure/table/tablepyxl/__init__.py +0 -13
- pyxlpr/ppstructure/table/tablepyxl/style.py +0 -283
- pyxlpr/ppstructure/table/tablepyxl/tablepyxl.py +0 -118
- pyxlpr/ppstructure/utility.py +0 -71
- pyxlpr/xlai.py +0 -10
- /pyxllib/{ext/autogui → autogui}/virtualkey.py +0 -0
- {pyxllib-0.3.96.dist-info → pyxllib-0.3.197.dist-info/licenses}/LICENSE +0 -0
pyxllib/file/docxlib.py
CHANGED
@@ -0,0 +1,165 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# @Author : 陈坤泽
|
4
|
+
# @Email : 877362867@qq.com
|
5
|
+
# @Date : 2024/04/27
|
6
|
+
|
7
|
+
"""
|
8
|
+
libreoffice这个软件相关的功能
|
9
|
+
|
10
|
+
官网:https://www.libreoffice.org/download/download-libreoffice/
|
11
|
+
|
12
|
+
linux的安装:
|
13
|
+
sudo apt-get update
|
14
|
+
sudo apt-get install libreoffice -y
|
15
|
+
"""
|
16
|
+
|
17
|
+
import os
|
18
|
+
from pathlib import Path
|
19
|
+
import subprocess
|
20
|
+
import sys
|
21
|
+
import tempfile
|
22
|
+
from datetime import datetime
|
23
|
+
|
24
|
+
|
25
|
+
def check_libreoffice():
|
26
|
+
""" 检查LibreOffice是否安装 """
|
27
|
+
executor = get_libreoffice_executor()
|
28
|
+
try:
|
29
|
+
subprocess.run([executor, '--version'], check=True)
|
30
|
+
except FileNotFoundError:
|
31
|
+
return False
|
32
|
+
except subprocess.CalledProcessError:
|
33
|
+
return False
|
34
|
+
return True
|
35
|
+
|
36
|
+
|
37
|
+
def get_libreoffice_executor():
|
38
|
+
""" 获得可执行文件的名称 """
|
39
|
+
# 根据所在系统区分
|
40
|
+
if sys.platform == 'win32':
|
41
|
+
return 'soffice.exe'
|
42
|
+
else:
|
43
|
+
return 'libreoffice'
|
44
|
+
|
45
|
+
|
46
|
+
def infer_file_format(file_path):
|
47
|
+
""" 推断文件所属办公文档的'主类' """
|
48
|
+
ext = Path(file_path).suffix.lower()
|
49
|
+
if ext in ['.doc', '.docx']:
|
50
|
+
fmt = 'docx'
|
51
|
+
elif ext in ['.ppt', '.pptx']:
|
52
|
+
fmt = 'pptx'
|
53
|
+
elif ext in ['.xls', '.xlsx']:
|
54
|
+
# todo 其实excel还有xlsm的可能,但是用libreoffice可能没有微软365那样可以判断出宏的情况保存为xlsm
|
55
|
+
fmt = 'xlsx'
|
56
|
+
else:
|
57
|
+
raise ValueError("不支持的文件格式")
|
58
|
+
return fmt
|
59
|
+
|
60
|
+
|
61
|
+
class UpgradeOfficeFile:
|
62
|
+
@classmethod
|
63
|
+
def to_dir(cls, file_path, out_dir=None, fmt=None, timeout=10):
|
64
|
+
""" 将doc文件转换为docx文件
|
65
|
+
|
66
|
+
:param file_path: 待升级的文件路径
|
67
|
+
:param out_dir: 输出文件目录
|
68
|
+
官方接口默认只能设置导出目录,不能设置导出文件名,文件名是跟原始文件一样的
|
69
|
+
:param fmt: 输出文件格式
|
70
|
+
docx, xlsx, pptx
|
71
|
+
"""
|
72
|
+
if isinstance(file_path, Path):
|
73
|
+
file_path = file_path.as_posix()
|
74
|
+
|
75
|
+
# 获取LibreOffice可执行文件的名称
|
76
|
+
executor = get_libreoffice_executor()
|
77
|
+
|
78
|
+
# 如果未指定输出路径,则默认在输入文件的同目录下生成同名的DOCX文件
|
79
|
+
if out_dir is None:
|
80
|
+
out_dir = os.path.dirname(file_path)
|
81
|
+
|
82
|
+
if fmt is None:
|
83
|
+
fmt = infer_file_format(file_path)
|
84
|
+
|
85
|
+
# 构建转换命令
|
86
|
+
command = [
|
87
|
+
executor,
|
88
|
+
'--headless', # 无界面模式
|
89
|
+
'--convert-to', fmt, # 转换为docx格式
|
90
|
+
'--outdir', str(out_dir), # 输出目录
|
91
|
+
file_path # 输入文件路径
|
92
|
+
]
|
93
|
+
|
94
|
+
subprocess.run(command, timeout=timeout, check=True)
|
95
|
+
|
96
|
+
# 返回转换后的文件路径
|
97
|
+
base_name = os.path.basename(file_path)
|
98
|
+
name, _ = os.path.splitext(base_name)
|
99
|
+
new_file_path = os.path.join(out_dir, f"{name}.{fmt}")
|
100
|
+
|
101
|
+
# todo 以目标文件是否存在判断转换是否成功也是有一定bug的,可能目标文件本来就存在
|
102
|
+
# 但如果严谨判断,就要分析subprocess.run的输出结果了,那个太麻烦,先用简便方法处理
|
103
|
+
if not Path(new_file_path).exists():
|
104
|
+
raise ValueError(f"升级文档失败")
|
105
|
+
|
106
|
+
return new_file_path
|
107
|
+
|
108
|
+
@classmethod
|
109
|
+
def to_file(cls, in_file, out_file=None, fmt=None, timeout=10):
|
110
|
+
""" 可以指定转换出的文件名的版本
|
111
|
+
|
112
|
+
:param in_file: 待转换的文件路径
|
113
|
+
:param out_file: 输出文件路径
|
114
|
+
若未指定,默认与原文件同名,在原文件所在目录生成
|
115
|
+
:param fmt: 输出文件格式
|
116
|
+
docx, xlsx, pptx
|
117
|
+
若未指定,则根据in_file的后缀名自动判断
|
118
|
+
"""
|
119
|
+
# 将in_file转换为Path对象
|
120
|
+
in_file = Path(in_file)
|
121
|
+
|
122
|
+
# 如果fmt为None,则根据in_file推断
|
123
|
+
if fmt is None:
|
124
|
+
fmt = infer_file_format(in_file)
|
125
|
+
|
126
|
+
# 如果out_file为None,则默认在原文件目录生成同名的新格式文件
|
127
|
+
if out_file is None:
|
128
|
+
out_file = in_file.with_suffix(f'.{fmt}')
|
129
|
+
else:
|
130
|
+
out_file = Path(out_file)
|
131
|
+
|
132
|
+
# 确保out_file的父目录存在,不存在则创建
|
133
|
+
out_file.parent.mkdir(parents=True, exist_ok=True)
|
134
|
+
|
135
|
+
# 调用upgrade_office_file函数进行转换
|
136
|
+
temp_file = cls.to_dir(in_file, out_dir=out_file.parent, fmt=fmt, timeout=timeout)
|
137
|
+
|
138
|
+
# 将生成的临时文件重命名为out_file
|
139
|
+
os.rename(temp_file, out_file)
|
140
|
+
|
141
|
+
return out_file
|
142
|
+
|
143
|
+
@classmethod
|
144
|
+
def to_tempfile(cls, in_file, fmt=None, *, timestamp_stem=False, create_subdir=False, timeout=10):
|
145
|
+
""" 将文件转换为临时文件
|
146
|
+
|
147
|
+
:param timestamp_stem: 时间戳文件名
|
148
|
+
:param create_subdir: 是否在临时目录中创建新的子目录
|
149
|
+
"""
|
150
|
+
if fmt is None:
|
151
|
+
fmt = infer_file_format(in_file)
|
152
|
+
|
153
|
+
root = Path(tempfile.gettempdir())
|
154
|
+
if create_subdir:
|
155
|
+
root2 = root / datetime.now().strftime('%Y%m%d.%H%M%S.%f')
|
156
|
+
root2.mkdir(parents=True, exist_ok=True)
|
157
|
+
root = root2
|
158
|
+
|
159
|
+
if timestamp_stem:
|
160
|
+
stem = datetime.now().strftime('%Y%m%d.%H%M%S.%f')
|
161
|
+
out_file = cls.to_file(in_file, out_file=root / f"{stem}.{fmt}", fmt=fmt, timeout=timeout)
|
162
|
+
else:
|
163
|
+
out_file = cls.to_dir(in_file, out_dir=root, fmt=fmt, timeout=timeout)
|
164
|
+
|
165
|
+
return out_file
|
pyxllib/file/movielib.py
CHANGED
@@ -10,6 +10,7 @@ check_install_package('moviepy')
|
|
10
10
|
|
11
11
|
import cv2
|
12
12
|
from moviepy.editor import VideoFileClip
|
13
|
+
from moviepy.editor import cvsecs
|
13
14
|
import numpy as np
|
14
15
|
from tqdm import tqdm
|
15
16
|
|
@@ -137,3 +138,11 @@ class XlVideoFileClip(VideoFileClip):
|
|
137
138
|
|
138
139
|
|
139
140
|
inject_members(XlVideoFileClip, VideoFileClip)
|
141
|
+
|
142
|
+
|
143
|
+
def clip_video(input_file, output_file, start_time, end_time):
|
144
|
+
start_time = cvsecs(start_time)
|
145
|
+
end_time = cvsecs(end_time)
|
146
|
+
clip = VideoFileClip(input_file).subclip(start_time, end_time)
|
147
|
+
clip.write_videofile(output_file)
|
148
|
+
clip.reader.close()
|
pyxllib/file/packlib/__init__.py
CHANGED
@@ -8,8 +8,11 @@ import os
|
|
8
8
|
import shutil
|
9
9
|
from tarfile import TarFile
|
10
10
|
# 这个包里的ZipFile是拷贝后修改过的,不影响标准库zipfile里的功能
|
11
|
-
import pyxllib.file.packlib.zipfile as zipfile
|
12
|
-
from pyxllib.file.packlib.zipfile import 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
|
13
16
|
|
14
17
|
from pyxllib.file.specialist import XlPath, reduce_dir_depth
|
15
18
|
from pyxllib.prog.pupil import inject_members
|
@@ -126,6 +129,25 @@ def _unpack_base(packfile, namelist, format=None, extract_dir=None, wrap=0):
|
|
126
129
|
shutil.unpack_archive(packfile, extract_dir, format)
|
127
130
|
|
128
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
|
+
|
129
151
|
class XlZipFile(ZipFile):
|
130
152
|
|
131
153
|
def infolist2(self, prefix=None, zipinfo=True):
|
@@ -151,6 +173,94 @@ class XlZipFile(ZipFile):
|
|
151
173
|
def unpack(self, extract_dir=None, format='zip', wrap=0):
|
152
174
|
_unpack_base(self.filename, self.namelist(), format, extract_dir, wrap)
|
153
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
|
+
|
154
264
|
|
155
265
|
class XlTarFile(TarFile):
|
156
266
|
|
@@ -218,76 +328,3 @@ def compress_to_zip(source_path, target_zip_path=None, wrap=None,
|
|
218
328
|
zipf.write(source_path, arcname)
|
219
329
|
|
220
330
|
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
|
pyxllib/file/pdflib.py
CHANGED
@@ -19,7 +19,7 @@ from pyxllib.prog.newbie import round_int, decode_bitflags
|
|
19
19
|
from pyxllib.prog.pupil import DictTool, inject_members, dprint
|
20
20
|
from pyxllib.prog.specialist import browser
|
21
21
|
from pyxllib.algo.newbie import round_unit
|
22
|
-
from pyxllib.
|
22
|
+
from pyxllib.prog.pupil import get_number_width
|
23
23
|
from pyxllib.file.specialist import XlPath, writefile, get_etag
|
24
24
|
from pyxllib.cv.expert import xlcv, xlpil
|
25
25
|
from pyxlpr.data.labelme import LabelmeDict
|
pyxllib/file/pupil.py
CHANGED
@@ -38,7 +38,7 @@ class Dir(PathBase):
|
|
38
38
|
|
39
39
|
# 零、常用的目录类
|
40
40
|
TEMP = pathlib.Path(tempfile.gettempdir())
|
41
|
-
if os.
|
41
|
+
if os.getenv('Desktop', None): # 如果修改了win10默认的桌面路径,需要在环境变量添加一个正确的Desktop路径值
|
42
42
|
DESKTOP = os.environ['Desktop']
|
43
43
|
else:
|
44
44
|
DESKTOP = os.path.join(str(pathlib.Path.home()), 'Desktop') # 这个不一定准,桌面是有可能被移到D盘等的
|
@@ -13,19 +13,26 @@ from urllib import request
|
|
13
13
|
import requests
|
14
14
|
from bs4 import BeautifulSoup
|
15
15
|
|
16
|
-
from pyxllib.file.specialist import File, Dir
|
16
|
+
from pyxllib.file.specialist import File, Dir, refinepath
|
17
17
|
|
18
18
|
|
19
19
|
def download_file(url, fn=None, *, encoding=None, if_exists=None, ext=None, temp=False):
|
20
|
-
""" 类似writefile,只是源数据是从url里下载
|
20
|
+
r""" 类似writefile,只是源数据是从url里下载
|
21
21
|
|
22
22
|
:param url: 数据下载链接
|
23
23
|
:param fn: 保存位置,会从url智能提取文件名
|
24
24
|
:param if_exists: 详见 File.write 参数解释
|
25
25
|
:para temp: 将文件写到临时文件夹
|
26
26
|
:return:
|
27
|
+
|
28
|
+
>> download_file(image_url) # 保存在当前工作目录下
|
29
|
+
D:/home/chenkunze/slns/xlproject/xlsln/ckz2024/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg
|
30
|
+
>> download_file(image_url, fn=r"D:/home/chenkunze/slns/xlproject/xlsln/ckz2024/a.png") # 指定路径
|
31
|
+
D:/home/chenkunze/slns/xlproject/xlsln/ckz2024/a.png
|
32
|
+
>> download_file(image_url, fn=r"D:/home/chenkunze/slns/xlproject/xlsln/ckz2024") # 暂不支持目录
|
33
|
+
ValueError: 不能用目录初始化一个File对象 D:\home\chenkunze\slns\xlproject\xlsln\ckz2023
|
27
34
|
"""
|
28
|
-
if not fn: fn = url.split('/')[-1]
|
35
|
+
if not fn: fn = refinepath(url.split('/')[-1])[-80:] # 这里故意截断文件名最长80个字符
|
29
36
|
root = Dir.TEMP if temp else None
|
30
37
|
fn = File(fn, root, suffix=ext).write(requests.get(url).content,
|
31
38
|
encoding=encoding, if_exists=if_exists, etag=(not fn))
|