UtilityLibAPI 1.2510.22__tar.gz → 1.2510.23__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.
- {utilitylibapi-1.2510.22 → utilitylibapi-1.2510.23}/PKG-INFO +5 -1
- {utilitylibapi-1.2510.22 → utilitylibapi-1.2510.23}/README.md +4 -0
- {utilitylibapi-1.2510.22 → utilitylibapi-1.2510.23}/pyproject.toml +1 -1
- utilitylibapi-1.2510.23/src/UtilityLibAPI/ExtWrapper7zLib.py +166 -0
- utilitylibapi-1.2510.23/src/UtilityLibAPI/__init__.py +10 -0
- {utilitylibapi-1.2510.22 → utilitylibapi-1.2510.23}/src/UtilityLibAPI.egg-info/PKG-INFO +5 -1
- {utilitylibapi-1.2510.22 → utilitylibapi-1.2510.23}/src/UtilityLibAPI.egg-info/SOURCES.txt +1 -0
- utilitylibapi-1.2510.22/src/UtilityLibAPI/__init__.py +0 -8
- {utilitylibapi-1.2510.22 → utilitylibapi-1.2510.23}/LICENSE +0 -0
- {utilitylibapi-1.2510.22 → utilitylibapi-1.2510.23}/setup.cfg +0 -0
- {utilitylibapi-1.2510.22 → utilitylibapi-1.2510.23}/src/UtilityLibAPI/EnDeCodeLib.py +0 -0
- {utilitylibapi-1.2510.22 → utilitylibapi-1.2510.23}/src/UtilityLibAPI/MailSenderLib.py +0 -0
- {utilitylibapi-1.2510.22 → utilitylibapi-1.2510.23}/src/UtilityLibAPI/SessionVARLib.py +0 -0
- {utilitylibapi-1.2510.22 → utilitylibapi-1.2510.23}/src/UtilityLibAPI.egg-info/dependency_links.txt +0 -0
- {utilitylibapi-1.2510.22 → utilitylibapi-1.2510.23}/src/UtilityLibAPI.egg-info/requires.txt +0 -0
- {utilitylibapi-1.2510.22 → utilitylibapi-1.2510.23}/src/UtilityLibAPI.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: UtilityLibAPI
|
|
3
|
-
Version: 1.2510.
|
|
3
|
+
Version: 1.2510.23
|
|
4
4
|
Summary: UtilityLibAPI Python package
|
|
5
5
|
Author-email: James Lin <tylin123@ms27.hinet.net>
|
|
6
6
|
License: Copyright (c) 2025 James Lin **UtilityLibAPI**
|
|
@@ -33,6 +33,10 @@ Dynamic: license-file
|
|
|
33
33
|
#UtilityLibAPI Classes
|
|
34
34
|
|
|
35
35
|
## History of version
|
|
36
|
+
Version 1.2510.22: 2025/10/21<BR>
|
|
37
|
+
Add ExtWrapper7zLib --> 7z Archive tools library
|
|
38
|
+
|
|
39
|
+
|
|
36
40
|
Version 1.2510.22: 2025/10/21<BR>
|
|
37
41
|
Add MailSenderLib --> CLASS_MailSender library
|
|
38
42
|
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import threading
|
|
3
|
+
import subprocess
|
|
4
|
+
import time
|
|
5
|
+
from typing import Callable, Dict, Optional
|
|
6
|
+
|
|
7
|
+
class CLASS_ExtWrapper7z:
|
|
8
|
+
def __init__(self, Pms_7z_path: Optional[str] = None):
|
|
9
|
+
self.Pms_7z_path = Pms_7z_path or self.CUF_Find7zPath()
|
|
10
|
+
self.tasks: Dict[int, Dict] = {}
|
|
11
|
+
self.task_counter = 0
|
|
12
|
+
self.lock = threading.Lock()
|
|
13
|
+
|
|
14
|
+
# 🔍 自動搜尋 7z.exe
|
|
15
|
+
def CUF_Find7zPath(self) -> Optional[str]:
|
|
16
|
+
common_paths = [
|
|
17
|
+
r"C:\\Program Files\\7-Zip\\7z.exe",
|
|
18
|
+
r"C:\\Program Files (x86)\\7-Zip\\7z.exe",
|
|
19
|
+
]
|
|
20
|
+
for path in common_paths:
|
|
21
|
+
if os.path.exists(path):
|
|
22
|
+
return path
|
|
23
|
+
|
|
24
|
+
for root, dirs, files in os.walk("C:\\"):
|
|
25
|
+
if "7z.exe" in files:
|
|
26
|
+
return os.path.join(root, "7z.exe")
|
|
27
|
+
return None
|
|
28
|
+
|
|
29
|
+
# 📦 建立壓縮或解壓縮任務
|
|
30
|
+
def CUF_AddTask(
|
|
31
|
+
self,
|
|
32
|
+
Pms_Mode: str, # "compress" 或 "extract"
|
|
33
|
+
Pms_InputPath: str,
|
|
34
|
+
Pms_OutputPath: str,
|
|
35
|
+
Pmi_VolumeSizeMB: int = 0,
|
|
36
|
+
Pms_Password: str = "",
|
|
37
|
+
Pmf_Callback: Optional[Callable[[int, float, str], None]] = None,
|
|
38
|
+
) -> int:
|
|
39
|
+
with self.lock:
|
|
40
|
+
self.task_counter += 1
|
|
41
|
+
mi_TaskID = self.task_counter
|
|
42
|
+
self.tasks[mi_TaskID] = {
|
|
43
|
+
"thread": None,
|
|
44
|
+
"progress": 0.0,
|
|
45
|
+
"status": "queued",
|
|
46
|
+
"cancel": False,
|
|
47
|
+
"mode": Pms_Mode,
|
|
48
|
+
"input": Pms_InputPath,
|
|
49
|
+
"output": Pms_OutputPath,
|
|
50
|
+
"callback": Pmf_Callback,
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
thread = threading.Thread(
|
|
54
|
+
target=self._CUF_RunTask,
|
|
55
|
+
args=(mi_TaskID, Pms_Mode, Pms_InputPath, Pms_OutputPath, Pmi_VolumeSizeMB, Pms_Password),
|
|
56
|
+
daemon=True,
|
|
57
|
+
)
|
|
58
|
+
self.tasks[mi_TaskID]["thread"] = thread
|
|
59
|
+
thread.start()
|
|
60
|
+
return mi_TaskID
|
|
61
|
+
|
|
62
|
+
# 🧩 執行壓縮/解壓縮
|
|
63
|
+
def _CUF_RunTask(self, TaskID, Mode, InputPath, OutputPath, VolumeSizeMB, Password):
|
|
64
|
+
task = self.tasks[TaskID]
|
|
65
|
+
task["status"] = "running"
|
|
66
|
+
Pms_7z_path = self.Pms_7z_path
|
|
67
|
+
if not Pms_7z_path or not os.path.exists(Pms_7z_path):
|
|
68
|
+
task["status"] = "error"
|
|
69
|
+
if task["callback"]:
|
|
70
|
+
task["callback"](TaskID, 0, "7z.exe not found")
|
|
71
|
+
return
|
|
72
|
+
|
|
73
|
+
if Mode == "compress":
|
|
74
|
+
cmd = [Pms_7z_path, "a", OutputPath, "-y"]
|
|
75
|
+
# 🔹 支援多個檔案/資料夾;以 ; 分隔
|
|
76
|
+
paths = [p.strip() for p in InputPath.split(";") if p.strip()]
|
|
77
|
+
cmd.extend(paths)
|
|
78
|
+
if Password:
|
|
79
|
+
cmd.append(f"-p{Password}")
|
|
80
|
+
if VolumeSizeMB > 0:
|
|
81
|
+
cmd.append(f"-v{VolumeSizeMB}m")
|
|
82
|
+
|
|
83
|
+
elif Mode == "extract":
|
|
84
|
+
cmd = [Pms_7z_path, "x", InputPath, f"-o{OutputPath}", "-y"]
|
|
85
|
+
if Password:
|
|
86
|
+
cmd.append(f"-p{Password}")
|
|
87
|
+
else:
|
|
88
|
+
task["status"] = "error"
|
|
89
|
+
if task["callback"]:
|
|
90
|
+
task["callback"](TaskID, 0, "Invalid mode")
|
|
91
|
+
return
|
|
92
|
+
|
|
93
|
+
proc = subprocess.Popen(
|
|
94
|
+
cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
for line in proc.stdout:
|
|
98
|
+
if task["cancel"]:
|
|
99
|
+
proc.terminate()
|
|
100
|
+
task["status"] = "cancelled"
|
|
101
|
+
if task["callback"]:
|
|
102
|
+
task["callback"](TaskID, task["progress"], "Cancelled")
|
|
103
|
+
return
|
|
104
|
+
|
|
105
|
+
if "%" in line:
|
|
106
|
+
try:
|
|
107
|
+
percent = float(line.strip().split("%")[0].split()[-1])
|
|
108
|
+
task["progress"] = percent
|
|
109
|
+
if task["callback"]:
|
|
110
|
+
task["callback"](TaskID, percent, "running")
|
|
111
|
+
except:
|
|
112
|
+
pass
|
|
113
|
+
|
|
114
|
+
proc.wait()
|
|
115
|
+
if proc.returncode == 0 and not task["cancel"]:
|
|
116
|
+
task["status"] = "done"
|
|
117
|
+
task["progress"] = 100.0
|
|
118
|
+
if task["callback"]:
|
|
119
|
+
task["callback"](TaskID, 100.0, "done")
|
|
120
|
+
elif not task["cancel"]:
|
|
121
|
+
task["status"] = "error"
|
|
122
|
+
if task["callback"]:
|
|
123
|
+
task["callback"](TaskID, task["progress"], "error")
|
|
124
|
+
|
|
125
|
+
# ❌ 取消任務
|
|
126
|
+
def CUF_CancelTask(self, Pmi_TaskID: int):
|
|
127
|
+
if Pmi_TaskID in self.tasks:
|
|
128
|
+
self.tasks[Pmi_TaskID]["cancel"] = True
|
|
129
|
+
|
|
130
|
+
# 📊 查詢所有任務總進度
|
|
131
|
+
def CUF_GetTotalProgress(self) -> float:
|
|
132
|
+
with self.lock:
|
|
133
|
+
if not self.tasks:
|
|
134
|
+
return 0.0
|
|
135
|
+
total = sum(task["progress"] for task in self.tasks.values())
|
|
136
|
+
return total / len(self.tasks)
|
|
137
|
+
|
|
138
|
+
# 🔍 查詢任務狀態
|
|
139
|
+
def CUF_GetTaskStatus(self, Pmi_TaskID: int) -> str:
|
|
140
|
+
return self.tasks.get(Pmi_TaskID, {}).get("status", "unknown")
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
# ================================================================================
|
|
146
|
+
# === 測試範例 ===
|
|
147
|
+
if(__name__ == "__main__"):
|
|
148
|
+
def my_callback(TaskID, progress, status):
|
|
149
|
+
print(f"[Task {TaskID}] {status} - {progress:.1f}%")
|
|
150
|
+
|
|
151
|
+
wrapper = CLASS_ExtWrapper7z()
|
|
152
|
+
print("7z 路徑:", wrapper.Pms_7z_path)
|
|
153
|
+
|
|
154
|
+
# 壓縮多個檔案 (同時支援萬用字元與多個資料夾)
|
|
155
|
+
task1 = wrapper.CUF_AddTask(
|
|
156
|
+
"compress",
|
|
157
|
+
Pms_InputPath=r"C:\\Temp\\Rubber\b1*.bmp;C:\\boost\\more",
|
|
158
|
+
Pms_OutputPath=r"C:\\TEMP\\OKOKO_GOOD.7z",
|
|
159
|
+
Pmi_VolumeSizeMB=50,
|
|
160
|
+
Pmf_Callback=my_callback,
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
while True:
|
|
164
|
+
total_progress = wrapper.CUF_GetTotalProgress()
|
|
165
|
+
print(f"總進度: {total_progress:.2f}%")
|
|
166
|
+
time.sleep(2)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from .EnDeCodeLib import CLASS_EnDeCodeLib
|
|
2
|
+
from .SessionVARLib import CLASS_SessionVAR
|
|
3
|
+
from .MailSenderLib import CLASS_MailSender
|
|
4
|
+
from .ExtWrapper7zLib import CLASS_ExtWrapper7z
|
|
5
|
+
|
|
6
|
+
__all__ = ["CLASS_EnDeCodeLib",
|
|
7
|
+
"CLASS_SessionVAR",
|
|
8
|
+
"CLASS_MailSender",
|
|
9
|
+
"CLASS_ExtWrapper7z"
|
|
10
|
+
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: UtilityLibAPI
|
|
3
|
-
Version: 1.2510.
|
|
3
|
+
Version: 1.2510.23
|
|
4
4
|
Summary: UtilityLibAPI Python package
|
|
5
5
|
Author-email: James Lin <tylin123@ms27.hinet.net>
|
|
6
6
|
License: Copyright (c) 2025 James Lin **UtilityLibAPI**
|
|
@@ -33,6 +33,10 @@ Dynamic: license-file
|
|
|
33
33
|
#UtilityLibAPI Classes
|
|
34
34
|
|
|
35
35
|
## History of version
|
|
36
|
+
Version 1.2510.22: 2025/10/21<BR>
|
|
37
|
+
Add ExtWrapper7zLib --> 7z Archive tools library
|
|
38
|
+
|
|
39
|
+
|
|
36
40
|
Version 1.2510.22: 2025/10/21<BR>
|
|
37
41
|
Add MailSenderLib --> CLASS_MailSender library
|
|
38
42
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{utilitylibapi-1.2510.22 → utilitylibapi-1.2510.23}/src/UtilityLibAPI.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
{utilitylibapi-1.2510.22 → utilitylibapi-1.2510.23}/src/UtilityLibAPI.egg-info/top_level.txt
RENAMED
|
File without changes
|