UtilityLibAPI 1.2512.801__tar.gz → 1.2512.1001__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 (37) hide show
  1. utilitylibapi-1.2512.1001/MANIFEST.in +3 -0
  2. {utilitylibapi-1.2512.801/src/UtilityLibAPI.egg-info → utilitylibapi-1.2512.1001}/PKG-INFO +6 -2
  3. {utilitylibapi-1.2512.801 → utilitylibapi-1.2512.1001}/README.md +5 -1
  4. {utilitylibapi-1.2512.801 → utilitylibapi-1.2512.1001}/pyproject.toml +1 -1
  5. utilitylibapi-1.2512.1001/src/UtilityLibAPI/Archive7zLib.cp310-win_amd64.pyd +0 -0
  6. utilitylibapi-1.2512.1001/src/UtilityLibAPI/Archive7zLib.pyi +12 -0
  7. utilitylibapi-1.2512.1001/src/UtilityLibAPI/EnDeCodeCppPyLib.cp310-win_amd64.pyd +0 -0
  8. utilitylibapi-1.2512.1001/src/UtilityLibAPI/EnDeCodeCppPyLib.pyi +9 -0
  9. utilitylibapi-1.2512.1001/src/UtilityLibAPI/EnDeCodeLib.cp310-win_amd64.pyd +0 -0
  10. utilitylibapi-1.2512.1001/src/UtilityLibAPI/EnDeCodeLib.pyi +12 -0
  11. utilitylibapi-1.2512.1001/src/UtilityLibAPI/ExtWrapper7zLib.cp310-win_amd64.pyd +0 -0
  12. utilitylibapi-1.2512.1001/src/UtilityLibAPI/ExtWrapper7zLib.pyi +14 -0
  13. utilitylibapi-1.2512.1001/src/UtilityLibAPI/MailSenderLib.cp310-win_amd64.pyd +0 -0
  14. utilitylibapi-1.2512.1001/src/UtilityLibAPI/MailSenderLib.pyi +24 -0
  15. utilitylibapi-1.2512.1001/src/UtilityLibAPI/SessionVARLib.cp310-win_amd64.pyd +0 -0
  16. utilitylibapi-1.2512.1001/src/UtilityLibAPI/SessionVARLib.pyi +13 -0
  17. utilitylibapi-1.2512.1001/src/UtilityLibAPI/__init__.py +14 -0
  18. utilitylibapi-1.2512.1001/src/UtilityLibAPI/out/UtilityLibAPI/Archive7zLib.pyi +12 -0
  19. utilitylibapi-1.2512.1001/src/UtilityLibAPI/out/UtilityLibAPI/EnDeCodeCppPyLib.pyi +9 -0
  20. utilitylibapi-1.2512.1001/src/UtilityLibAPI/out/UtilityLibAPI/EnDeCodeLib.pyi +12 -0
  21. utilitylibapi-1.2512.1001/src/UtilityLibAPI/out/UtilityLibAPI/ExtWrapper7zLib.pyi +14 -0
  22. utilitylibapi-1.2512.1001/src/UtilityLibAPI/out/UtilityLibAPI/MailSenderLib.pyi +24 -0
  23. utilitylibapi-1.2512.1001/src/UtilityLibAPI/out/UtilityLibAPI/SessionVARLib.pyi +13 -0
  24. {utilitylibapi-1.2512.801 → utilitylibapi-1.2512.1001/src/UtilityLibAPI.egg-info}/PKG-INFO +6 -2
  25. utilitylibapi-1.2512.1001/src/UtilityLibAPI.egg-info/SOURCES.txt +29 -0
  26. utilitylibapi-1.2512.801/src/UtilityLibAPI/Archive7zLib.py +0 -335
  27. utilitylibapi-1.2512.801/src/UtilityLibAPI/EnDeCodeLib.py +0 -198
  28. utilitylibapi-1.2512.801/src/UtilityLibAPI/ExtWrapper7zLib.py +0 -166
  29. utilitylibapi-1.2512.801/src/UtilityLibAPI/MailSenderLib.py +0 -304
  30. utilitylibapi-1.2512.801/src/UtilityLibAPI/SessionVARLib.py +0 -143
  31. utilitylibapi-1.2512.801/src/UtilityLibAPI/__init__.py +0 -12
  32. utilitylibapi-1.2512.801/src/UtilityLibAPI.egg-info/SOURCES.txt +0 -15
  33. {utilitylibapi-1.2512.801 → utilitylibapi-1.2512.1001}/LICENSE +0 -0
  34. {utilitylibapi-1.2512.801 → utilitylibapi-1.2512.1001}/setup.cfg +0 -0
  35. {utilitylibapi-1.2512.801 → utilitylibapi-1.2512.1001}/src/UtilityLibAPI.egg-info/dependency_links.txt +0 -0
  36. {utilitylibapi-1.2512.801 → utilitylibapi-1.2512.1001}/src/UtilityLibAPI.egg-info/requires.txt +0 -0
  37. {utilitylibapi-1.2512.801 → utilitylibapi-1.2512.1001}/src/UtilityLibAPI.egg-info/top_level.txt +0 -0
@@ -0,0 +1,3 @@
1
+ recursive-exclude src *.py
2
+ recursive-include src *__init__.py
3
+ recursive-include src *.pyd
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: UtilityLibAPI
3
- Version: 1.2512.801
3
+ Version: 1.2512.1001
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,10 +33,14 @@ Dynamic: license-file
33
33
  #UtilityLibAPI Classes
34
34
 
35
35
  ## History of version
36
+ Version 1.2512.1001: 2025/12/10<BR>
37
+ 1) Improve performace and speed for windows environment.<BR>
38
+ 2) Add CLASS_EnDeCodeCppPy class<BR>
39
+ 3) Remove CLASS_EnDeCode::CUF_CROSS_EncodeBase64(), CLASS_EnDeCode::CUF_CROSS_DecodeBase64()<BR>
40
+
36
41
  Version 1.2512.0801: 2025/12/08<BR>
37
42
  Modify CUF_Open() function for multi user accounts.
38
43
 
39
-
40
44
  Version 1.2512.0501: 2025/12/05<BR>
41
45
  Fixed break down when smtp server not auth or response time out.
42
46
 
@@ -1,10 +1,14 @@
1
1
  #UtilityLibAPI Classes
2
2
 
3
3
  ## History of version
4
+ Version 1.2512.1001: 2025/12/10<BR>
5
+ 1) Improve performace and speed for windows environment.<BR>
6
+ 2) Add CLASS_EnDeCodeCppPy class<BR>
7
+ 3) Remove CLASS_EnDeCode::CUF_CROSS_EncodeBase64(), CLASS_EnDeCode::CUF_CROSS_DecodeBase64()<BR>
8
+
4
9
  Version 1.2512.0801: 2025/12/08<BR>
5
10
  Modify CUF_Open() function for multi user accounts.
6
11
 
7
-
8
12
  Version 1.2512.0501: 2025/12/05<BR>
9
13
  Fixed break down when smtp server not auth or response time out.
10
14
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "UtilityLibAPI"
7
- version = "1.2512.0801"
7
+ version = "1.2512.1001"
8
8
  description = "UtilityLibAPI Python package"
9
9
  authors = [
10
10
  { name="James Lin", email="tylin123@ms27.hinet.net" }
@@ -0,0 +1,12 @@
1
+ from _typeshed import Incomplete
2
+
3
+ class CLASS_Archive7z:
4
+ on_progress: Incomplete
5
+ seven_zip_path: Incomplete
6
+ def __init__(self) -> None: ...
7
+ def CUF_SET_ProgressEvent(self, func_progress) -> None: ...
8
+ def CUF_CompressFolder(self, Pms_FolderName: str, Pms_File7z: str, Pms_Password: str = None, Pmi_SplitSize_K: int = -1): ...
9
+ def CUF_CompressFile(self, Pms_FileSource: str, Pms_File7z: str, Pms_Password: str = None, Pmi_SplitSize_K: int = -1): ...
10
+ def CUF_Decompress(self, Pms_ArchiveFile, Pms_OutputDir, Pms_Password=None): ...
11
+
12
+ def GE_ProgressEvent(Pmf_Percent) -> None: ...
@@ -0,0 +1,9 @@
1
+ from _typeshed import Incomplete
2
+
3
+ class CLASS_EnDeCodeCppPy:
4
+ CVmba_CppPyKeys: Incomplete
5
+ def __init__(self, Pmsa_CppPyKeys) -> None: ...
6
+ def CVF_ADV_Encrypt(self, Pms_b64: str) -> str: ...
7
+ def CVF_ADV_Decrypt(self, Pms_Merged: str) -> str: ...
8
+ def CUF_ENCRYPT_B64(self, Pms_Text: str) -> str: ...
9
+ def CUF_DECRYPT_B64(self, Pms_ENC_Text: str) -> str: ...
@@ -0,0 +1,12 @@
1
+ from _typeshed import Incomplete
2
+
3
+ class CLASS_EnDeCodeLib:
4
+ CVmba_CROSS_KEY: Incomplete
5
+ CVms_CROSS_ASC: str
6
+ CVms_CROSS_MAP: str
7
+ def __init__(self) -> None: ...
8
+ def CVF_CROSS_XOR(self, Pmc_SRC_CH): ...
9
+ def CUF_CROSS_SetKey(self, Rmca_KeyCode) -> None: ...
10
+ def CUF_CROSS_GetKey(self): ...
11
+ def CUF_CROSS_EnCode(self, Pms_SRC_Text): ...
12
+ def CUF_CROSS_DeCode(self, Pms_ENC_Text): ...
@@ -0,0 +1,14 @@
1
+ from _typeshed import Incomplete
2
+ from typing import Callable
3
+
4
+ class CLASS_ExtWrapper7z:
5
+ Pms_7z_path: Incomplete
6
+ tasks: dict[int, dict]
7
+ task_counter: int
8
+ lock: Incomplete
9
+ def __init__(self, Pms_7z_path: str | None = None) -> None: ...
10
+ def CUF_Find7zPath(self) -> str | None: ...
11
+ def CUF_AddTask(self, Pms_Mode: str, Pms_InputPath: str, Pms_OutputPath: str, Pmi_VolumeSizeMB: int = 0, Pms_Password: str = '', Pmf_Callback: Callable[[int, float, str], None] | None = None) -> int: ...
12
+ def CUF_CancelTask(self, Pmi_TaskID: int): ...
13
+ def CUF_GetTotalProgress(self) -> float: ...
14
+ def CUF_GetTaskStatus(self, Pmi_TaskID: int) -> str: ...
@@ -0,0 +1,24 @@
1
+ import smtplib
2
+ from _typeshed import Incomplete
3
+ from email import encoders as encoders
4
+ from email.mime.base import MIMEBase as MIMEBase
5
+ from email.mime.multipart import MIMEMultipart
6
+
7
+ class CLASS_MailSender:
8
+ CVms_SMTP_Server: Incomplete
9
+ CVmi_Port: Incomplete
10
+ CVms_Account: Incomplete
11
+ CVms_Password: Incomplete
12
+ CVmb_UseSSL: Incomplete
13
+ OnAfterSendSuccess: Callable[[str], None] | None
14
+ OnAfterSendFailure: Callable[[str], None] | None
15
+ CVobj_Server: smtplib.SMTP | None
16
+ def __init__(self, Pms_SMTP_Server: str, Pmi_Port: int, Pms_Account: str, Pms_Password: str, Pmb_UseSSL: bool = True) -> None: ...
17
+ def CUF_Open(self, Pms_Account: str, Pms_PassWD: str) -> bool: ...
18
+ def CUF_Close(self) -> None: ...
19
+ def CUF_Reconnect(self) -> bool: ...
20
+ def CUF_CreateMessage(self, Pms_Subject: str, Pms_BodyText: str, Pms_BodyHTML: str | None = None, Pms_From: str | None = None, Pobj_To: list[str] | None = None, Pobj_Cc: list[str] | None = None, Pobj_Bcc: list[str] | None = None, Pobj_Attachments: list[str] | None = None) -> MIMEMultipart: ...
21
+ def CUF_SendMail(self, Pms_Subject: str, Pms_BodyText: str, Pms_BodyHTML: str | None, Pobj_To: list[str], Pms_From: str | None = None, Pobj_Cc: list[str] | None = None, Pobj_Bcc: list[str] | None = None, Pobj_Attachments: list[str] | None = None) -> bool: ...
22
+
23
+ def GE_OnSendSuccess(Pms_Subject: str): ...
24
+ def GE_OnSendFailure(Pms_ErrMsg: str): ...
@@ -0,0 +1,13 @@
1
+ from _typeshed import Incomplete
2
+
3
+ class CLASS_SessionVAR:
4
+ conn: Incomplete
5
+ cursor: Incomplete
6
+ table_name: str
7
+ def __init__(self) -> None: ...
8
+ def CUF_New_SessionID(self): ...
9
+ def CUF_Create(self, Pms_host: str, Pmi_port: int, Pms_user: str, Pms_password: str, Pms_db: str, Pms_SessionID: str = None, Pms_table_name: str = '_session_table'): ...
10
+ def CUF_SET(self, Pms_SessionID, Pms_VarName, Pms_VarValue) -> None: ...
11
+ def CUF_GET(self, Pms_SessionID, Pms_VarName): ...
12
+ def CUF_Release(self, Pms_param) -> None: ...
13
+ def CUF_Close(self) -> None: ...
@@ -0,0 +1,14 @@
1
+ from .EnDeCodeLib import CLASS_EnDeCodeLib
2
+ from .EnDeCodeCppPyLib import CLASS_EnDeCodeCppPy
3
+ from .SessionVARLib import CLASS_SessionVAR
4
+ from .MailSenderLib import CLASS_MailSender
5
+ from .Archive7zLib import CLASS_Archive7z
6
+ from .ExtWrapper7zLib import CLASS_ExtWrapper7z
7
+
8
+ __all__ = ["CLASS_EnDeCodeLib",
9
+ "CLASS_EnDeCodeCppPy",
10
+ "CLASS_SessionVAR",
11
+ "CLASS_MailSender",
12
+ "CLASS_ExtWrapper7z",
13
+ "CLASS_Archive7z"
14
+ ]
@@ -0,0 +1,12 @@
1
+ from _typeshed import Incomplete
2
+
3
+ class CLASS_Archive7z:
4
+ on_progress: Incomplete
5
+ seven_zip_path: Incomplete
6
+ def __init__(self) -> None: ...
7
+ def CUF_SET_ProgressEvent(self, func_progress) -> None: ...
8
+ def CUF_CompressFolder(self, Pms_FolderName: str, Pms_File7z: str, Pms_Password: str = None, Pmi_SplitSize_K: int = -1): ...
9
+ def CUF_CompressFile(self, Pms_FileSource: str, Pms_File7z: str, Pms_Password: str = None, Pmi_SplitSize_K: int = -1): ...
10
+ def CUF_Decompress(self, Pms_ArchiveFile, Pms_OutputDir, Pms_Password=None): ...
11
+
12
+ def GE_ProgressEvent(Pmf_Percent) -> None: ...
@@ -0,0 +1,9 @@
1
+ from _typeshed import Incomplete
2
+
3
+ class CLASS_EnDeCodeCppPy:
4
+ CVmba_CppPyKeys: Incomplete
5
+ def __init__(self, Pmsa_CppPyKeys) -> None: ...
6
+ def CVF_ADV_Encrypt(self, Pms_b64: str) -> str: ...
7
+ def CVF_ADV_Decrypt(self, Pms_Merged: str) -> str: ...
8
+ def CUF_ENCRYPT_B64(self, Pms_Text: str) -> str: ...
9
+ def CUF_DECRYPT_B64(self, Pms_ENC_Text: str) -> str: ...
@@ -0,0 +1,12 @@
1
+ from _typeshed import Incomplete
2
+
3
+ class CLASS_EnDeCodeLib:
4
+ CVmba_CROSS_KEY: Incomplete
5
+ CVms_CROSS_ASC: str
6
+ CVms_CROSS_MAP: str
7
+ def __init__(self) -> None: ...
8
+ def CVF_CROSS_XOR(self, Pmc_SRC_CH): ...
9
+ def CUF_CROSS_SetKey(self, Rmca_KeyCode) -> None: ...
10
+ def CUF_CROSS_GetKey(self): ...
11
+ def CUF_CROSS_EnCode(self, Pms_SRC_Text): ...
12
+ def CUF_CROSS_DeCode(self, Pms_ENC_Text): ...
@@ -0,0 +1,14 @@
1
+ from _typeshed import Incomplete
2
+ from typing import Callable
3
+
4
+ class CLASS_ExtWrapper7z:
5
+ Pms_7z_path: Incomplete
6
+ tasks: dict[int, dict]
7
+ task_counter: int
8
+ lock: Incomplete
9
+ def __init__(self, Pms_7z_path: str | None = None) -> None: ...
10
+ def CUF_Find7zPath(self) -> str | None: ...
11
+ def CUF_AddTask(self, Pms_Mode: str, Pms_InputPath: str, Pms_OutputPath: str, Pmi_VolumeSizeMB: int = 0, Pms_Password: str = '', Pmf_Callback: Callable[[int, float, str], None] | None = None) -> int: ...
12
+ def CUF_CancelTask(self, Pmi_TaskID: int): ...
13
+ def CUF_GetTotalProgress(self) -> float: ...
14
+ def CUF_GetTaskStatus(self, Pmi_TaskID: int) -> str: ...
@@ -0,0 +1,24 @@
1
+ import smtplib
2
+ from _typeshed import Incomplete
3
+ from email import encoders as encoders
4
+ from email.mime.base import MIMEBase as MIMEBase
5
+ from email.mime.multipart import MIMEMultipart
6
+
7
+ class CLASS_MailSender:
8
+ CVms_SMTP_Server: Incomplete
9
+ CVmi_Port: Incomplete
10
+ CVms_Account: Incomplete
11
+ CVms_Password: Incomplete
12
+ CVmb_UseSSL: Incomplete
13
+ OnAfterSendSuccess: Callable[[str], None] | None
14
+ OnAfterSendFailure: Callable[[str], None] | None
15
+ CVobj_Server: smtplib.SMTP | None
16
+ def __init__(self, Pms_SMTP_Server: str, Pmi_Port: int, Pms_Account: str, Pms_Password: str, Pmb_UseSSL: bool = True) -> None: ...
17
+ def CUF_Open(self, Pms_Account: str, Pms_PassWD: str) -> bool: ...
18
+ def CUF_Close(self) -> None: ...
19
+ def CUF_Reconnect(self) -> bool: ...
20
+ def CUF_CreateMessage(self, Pms_Subject: str, Pms_BodyText: str, Pms_BodyHTML: str | None = None, Pms_From: str | None = None, Pobj_To: list[str] | None = None, Pobj_Cc: list[str] | None = None, Pobj_Bcc: list[str] | None = None, Pobj_Attachments: list[str] | None = None) -> MIMEMultipart: ...
21
+ def CUF_SendMail(self, Pms_Subject: str, Pms_BodyText: str, Pms_BodyHTML: str | None, Pobj_To: list[str], Pms_From: str | None = None, Pobj_Cc: list[str] | None = None, Pobj_Bcc: list[str] | None = None, Pobj_Attachments: list[str] | None = None) -> bool: ...
22
+
23
+ def GE_OnSendSuccess(Pms_Subject: str): ...
24
+ def GE_OnSendFailure(Pms_ErrMsg: str): ...
@@ -0,0 +1,13 @@
1
+ from _typeshed import Incomplete
2
+
3
+ class CLASS_SessionVAR:
4
+ conn: Incomplete
5
+ cursor: Incomplete
6
+ table_name: str
7
+ def __init__(self) -> None: ...
8
+ def CUF_New_SessionID(self): ...
9
+ def CUF_Create(self, Pms_host: str, Pmi_port: int, Pms_user: str, Pms_password: str, Pms_db: str, Pms_SessionID: str = None, Pms_table_name: str = '_session_table'): ...
10
+ def CUF_SET(self, Pms_SessionID, Pms_VarName, Pms_VarValue) -> None: ...
11
+ def CUF_GET(self, Pms_SessionID, Pms_VarName): ...
12
+ def CUF_Release(self, Pms_param) -> None: ...
13
+ def CUF_Close(self) -> None: ...
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: UtilityLibAPI
3
- Version: 1.2512.801
3
+ Version: 1.2512.1001
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,10 +33,14 @@ Dynamic: license-file
33
33
  #UtilityLibAPI Classes
34
34
 
35
35
  ## History of version
36
+ Version 1.2512.1001: 2025/12/10<BR>
37
+ 1) Improve performace and speed for windows environment.<BR>
38
+ 2) Add CLASS_EnDeCodeCppPy class<BR>
39
+ 3) Remove CLASS_EnDeCode::CUF_CROSS_EncodeBase64(), CLASS_EnDeCode::CUF_CROSS_DecodeBase64()<BR>
40
+
36
41
  Version 1.2512.0801: 2025/12/08<BR>
37
42
  Modify CUF_Open() function for multi user accounts.
38
43
 
39
-
40
44
  Version 1.2512.0501: 2025/12/05<BR>
41
45
  Fixed break down when smtp server not auth or response time out.
42
46
 
@@ -0,0 +1,29 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ pyproject.toml
5
+ setup.cfg
6
+ src/UtilityLibAPI/Archive7zLib.cp310-win_amd64.pyd
7
+ src/UtilityLibAPI/Archive7zLib.pyi
8
+ src/UtilityLibAPI/EnDeCodeCppPyLib.cp310-win_amd64.pyd
9
+ src/UtilityLibAPI/EnDeCodeCppPyLib.pyi
10
+ src/UtilityLibAPI/EnDeCodeLib.cp310-win_amd64.pyd
11
+ src/UtilityLibAPI/EnDeCodeLib.pyi
12
+ src/UtilityLibAPI/ExtWrapper7zLib.cp310-win_amd64.pyd
13
+ src/UtilityLibAPI/ExtWrapper7zLib.pyi
14
+ src/UtilityLibAPI/MailSenderLib.cp310-win_amd64.pyd
15
+ src/UtilityLibAPI/MailSenderLib.pyi
16
+ src/UtilityLibAPI/SessionVARLib.cp310-win_amd64.pyd
17
+ src/UtilityLibAPI/SessionVARLib.pyi
18
+ src/UtilityLibAPI/__init__.py
19
+ src/UtilityLibAPI.egg-info/PKG-INFO
20
+ src/UtilityLibAPI.egg-info/SOURCES.txt
21
+ src/UtilityLibAPI.egg-info/dependency_links.txt
22
+ src/UtilityLibAPI.egg-info/requires.txt
23
+ src/UtilityLibAPI.egg-info/top_level.txt
24
+ src/UtilityLibAPI/out/UtilityLibAPI/Archive7zLib.pyi
25
+ src/UtilityLibAPI/out/UtilityLibAPI/EnDeCodeCppPyLib.pyi
26
+ src/UtilityLibAPI/out/UtilityLibAPI/EnDeCodeLib.pyi
27
+ src/UtilityLibAPI/out/UtilityLibAPI/ExtWrapper7zLib.pyi
28
+ src/UtilityLibAPI/out/UtilityLibAPI/MailSenderLib.pyi
29
+ src/UtilityLibAPI/out/UtilityLibAPI/SessionVARLib.pyi
@@ -1,335 +0,0 @@
1
- import os
2
- import sys
3
- import shutil
4
- import subprocess
5
- import re
6
- import glob
7
-
8
- class CLASS_Archive7z:
9
- def __init__(self):
10
- self.on_progress = None
11
- self.seven_zip_path = self._find_7z_exe()
12
-
13
- # -------------------------------------------------------------
14
- # 自動搜尋 7z.exe
15
- # -------------------------------------------------------------
16
- def _find_7z_exe(self):
17
- candidate_paths = [
18
- r"C:\Program Files\7-Zip\7z.exe",
19
- r"C:\Program Files (x86)\7-Zip\7z.exe"
20
- ]
21
- # 1. 先找常用路徑
22
- for p in candidate_paths:
23
- if os.path.exists(p):
24
- return p
25
- # 2. 從 PATH 搜尋
26
- p = shutil.which("7z")
27
- if p:
28
- return p
29
-
30
- # 3. 找不到 → 拋錯
31
- raise FileNotFoundError("找不到 7z.exe,請確認是否已安裝 7-Zip")
32
-
33
-
34
- # -------------------------------------------------------------
35
- # 設定進度事件
36
- # -------------------------------------------------------------
37
- def CUF_SET_ProgressEvent(self, func_progress):
38
- self.on_progress = func_progress
39
-
40
-
41
- def _find_7z_exe(self):
42
- """
43
- 依照優先順序尋找 7za.exe → 7z.exe
44
- 並支援掃描所有磁碟(C, D, E, F...)
45
- """
46
- # ---------------------------
47
- # 1. PATH 中找 7za / 7z
48
- # ---------------------------
49
- p = shutil.which("7za")
50
- if p:
51
- return p
52
- p = shutil.which("7z")
53
- if p:
54
- return p
55
- # ---------------------------
56
- # 2. 常見安裝路徑
57
- # ---------------------------
58
- common_paths = [
59
- r"C:\Program Files\7-Zip\7za.exe",
60
- r"C:\Program Files (x86)\7-Zip\7za.exe",
61
- r"C:\Program Files\7-Zip\7z.exe",
62
- r"C:\Program Files (x86)\7-Zip\7z.exe",
63
- ]
64
- for p in common_paths:
65
- if os.path.exists(p):
66
- return p
67
- # ---------------------------
68
- # 3. 掃描所有磁碟(C, D, E, F...)
69
- # 搜尋特定資料夾名稱避免太慢
70
- # ---------------------------
71
- search_dirs = [
72
- "7-Zip",
73
- "7Zip",
74
- "7zip",
75
- "7zip\\bin",
76
- "Program Files\\7-Zip",
77
- "Program Files (x86)\\7-Zip",
78
- ]
79
- drives = []
80
- for letter in "CDEFGHIJKLMNOPQRSTUVWXYZ":
81
- d = f"{letter}:\\"
82
- if os.path.exists(d):
83
- drives.append(d)
84
-
85
- for drive in drives:
86
- for folder in search_dirs:
87
- base = os.path.join(drive, folder)
88
-
89
- # 若資料夾不存在跳過
90
- if not os.path.isdir(base):
91
- continue
92
-
93
- # 檢查底下是否有 7za.exe 或 7z.exe
94
- exe_7za = os.path.join(base, "7za.exe")
95
- exe_7z = os.path.join(base, "7z.exe")
96
-
97
- if os.path.exists(exe_7za):
98
- return exe_7za
99
- if os.path.exists(exe_7z):
100
- return exe_7z
101
-
102
- # 若還沒找到 → 試著遞迴搜尋
103
- try:
104
- for root, dirs, files in os.walk(base):
105
- if "7za.exe" in files:
106
- return os.path.join(root, "7za.exe")
107
- if "7z.exe" in files:
108
- return os.path.join(root, "7z.exe")
109
- except PermissionError:
110
- pass # 跳過無權限的資料夾
111
-
112
- # ---------------------------
113
- # 全部找不到 → 拋錯
114
- # ---------------------------
115
- raise FileNotFoundError("找不到 7za.exe 或 7z.exe,請確認是否已安裝 7-Zip")
116
-
117
- # -------------------------------------------------------------
118
- # 封裝執行 7z.exe,並解析 stdout 進度 (%)
119
- # -------------------------------------------------------------
120
- def _run_7z(self, args_list):
121
- """
122
- 同時支援:
123
- ✔ 有 % → 觸發 int 進度
124
- ✔ 沒 % → 逐行觸發文字行
125
- """
126
- cmd = [self.seven_zip_path] + args_list
127
-
128
- process = subprocess.Popen(
129
- cmd,
130
- stdout=subprocess.PIPE,
131
- stderr=subprocess.STDOUT,
132
- universal_newlines=True,
133
- encoding="utf-8",
134
- errors="ignore"
135
- )
136
-
137
- progress_pattern = re.compile(r"(\d+)%")
138
-
139
- for line in process.stdout:
140
- line = line.strip()
141
-
142
- # 嘗試找百分比
143
- match = progress_pattern.search(line)
144
- if match:
145
- pct = int(match.group(1))
146
- if self.on_progress:
147
- try:
148
- self.on_progress(pct)
149
- except:
150
- pass
151
- else:
152
- # 沒有百分比 → 仍然要回報文字行(使用者可自訂怎麼處理)
153
- if self.on_progress and line:
154
- try:
155
- self.on_progress(line) # 回傳文字行
156
- except:
157
- pass
158
- process.wait()
159
-
160
-
161
- # -------------------------------------------------------------
162
- # 壓縮資料夾
163
- # -------------------------------------------------------------
164
- def CUF_CompressFolder(self, Pms_FolderName:str, Pms_File7z:str,
165
- Pms_Password:str=None,
166
- Pmi_SplitSize_K:int=-1):
167
-
168
- if not os.path.exists(Pms_FolderName):
169
- raise ValueError("Pms_FolderName 必須是資料夾")
170
-
171
- # -------------------------------------------------------
172
- # 取出 Pms_File7z 的路徑並建立
173
- # -------------------------------------------------------
174
- out_dir = os.path.dirname(Pms_File7z)
175
- if out_dir.strip() == "":
176
- out_dir = os.getcwd()
177
-
178
- os.makedirs(out_dir, exist_ok=True)
179
-
180
- file_name_only = os.path.basename(Pms_File7z) # Orange.7z
181
-
182
- # -------------------------------------------------------
183
- # 組合 7z 參數
184
- # -------------------------------------------------------
185
- args = ["a"]
186
-
187
- if Pms_Password:
188
- args.append(f"-p{Pms_Password}")
189
-
190
- if Pmi_SplitSize_K != -1:
191
- args.append(f"-v{Pmi_SplitSize_K}k")
192
-
193
- # 7z 輸出檔名(不能帶路徑)
194
- args.append(file_name_only)
195
-
196
- # 加入來源資料夾
197
- args.append(Pms_FolderName)
198
-
199
- # -------------------------------------------------------
200
- # 執行壓縮 (7z 產生在目前工作目錄)
201
- # -------------------------------------------------------
202
- self._run_7z(args)
203
-
204
- # -------------------------------------------------------
205
- # ▒▒▒ 壓縮後 → 將檔案移到 Pms_File7z 指定路徑 ▒▒▒
206
- # -------------------------------------------------------
207
- self._move_output_files(file_name_only, out_dir)
208
-
209
-
210
- # -------------------------------------------------------------
211
- # 壓縮檔案(支援萬用字元 *.txt, apple*.*)
212
- # -------------------------------------------------------------
213
- def CUF_CompressFile(self, Pms_FileSource:str, Pms_File7z:str,
214
- Pms_Password:str=None,
215
- Pmi_SplitSize_K:int=-1):
216
- file_list = glob.glob(Pms_FileSource)
217
- if not file_list:
218
- raise FileNotFoundError(f"找不到符合的檔案: {Pms_FileSource}")
219
-
220
- # -------------------------------------------------------
221
- # 取出 Pms_File7z 的路徑並建立
222
- # -------------------------------------------------------
223
- out_dir = os.path.dirname(Pms_File7z)
224
- if out_dir.strip() == "":
225
- out_dir = os.getcwd()
226
-
227
- os.makedirs(out_dir, exist_ok=True)
228
-
229
- file_name_only = os.path.basename(Pms_File7z)
230
-
231
- # -------------------------------------------------------
232
- # 組合 7z 參數
233
- # -------------------------------------------------------
234
- args = ["a"]
235
-
236
- if Pms_Password:
237
- args.append(f"-p{Pms_Password}")
238
-
239
- if Pmi_SplitSize_K not in (None, -1):
240
- args.append(f"-v{Pmi_SplitSize_K}k")
241
-
242
- args.append(file_name_only)
243
-
244
- for f in file_list:
245
- args.append(f)
246
-
247
- # -------------------------------------------------------
248
- # 執行壓縮
249
- # -------------------------------------------------------
250
- self._run_7z(args)
251
-
252
- # -------------------------------------------------------
253
- # ▒▒▒ 壓縮後 → 移動所有分割檔 / 單一檔 ▒▒▒
254
- # -------------------------------------------------------
255
- self._move_output_files(file_name_only, out_dir)
256
-
257
-
258
- # -------------------------------------------------------------
259
- # 共用:移動壓縮結果到指定目錄
260
- # -------------------------------------------------------------
261
- def _move_output_files(self, base_file_name:str, out_dir:str):
262
- """
263
- base_file_name = "Orange.7z"
264
- 最後尋找:
265
- Orange.7z
266
- Orange.7z.001
267
- Orange.7z.002
268
- ...
269
- """
270
- for f in os.listdir("."):
271
- if f == base_file_name or f.startswith(base_file_name + "."):
272
- shutil.move(f, os.path.join(out_dir, f))
273
-
274
-
275
- def CUF_Decompress(self, Pms_ArchiveFile, Pms_OutputDir, Pms_Password=None):
276
- """
277
- 解壓縮通用函式(最終穩定版本)
278
- -------------------------------------
279
- Pms_ArchiveFile : 壓縮檔完整路徑
280
- Pms_OutputDir : 要解壓到哪裡
281
- Pms_Password : 解壓密碼(可省略)
282
- -------------------------------------
283
- 支援格式:
284
- 7z, zip, rar, tar, tar.gz, tar.bz2, tar.xz
285
- """
286
- # ---------- 路徑檢查 ----------
287
- if not os.path.exists(Pms_ArchiveFile):
288
- return False, f"Compress file not found: {Pms_ArchiveFile}"
289
-
290
- os.makedirs(Pms_OutputDir, exist_ok=True)
291
-
292
- Pms_7zExe = self.seven_zip_path
293
-
294
- args = ["x"]
295
-
296
- if Pms_Password:
297
- args.append(f"-p{Pms_Password}")
298
-
299
- args.append(Pms_ArchiveFile)
300
- args.append(f"-o{Pms_OutputDir}")
301
- args.append("-y")
302
-
303
- # ★★★ 使用會有進度事件的版本 ★★★
304
- try:
305
- self._run_7z(args)
306
- return True, "Decompress successful."
307
- except Exception as e:
308
- return False, f"Decompress failure:\n{str(e)}"
309
-
310
-
311
- # ================================================================================
312
- # [使用範例]
313
- def GE_ProgressEvent(Pmf_Percent):
314
- print(str(Pmf_Percent));
315
-
316
- if(__name__=="__main__"):
317
- ms_Path_7z: str;
318
-
319
- obj_7z = CLASS_Archive7z();
320
-
321
- obj_7z.CUF_SET_ProgressEvent(GE_ProgressEvent);
322
-
323
- obj_7z.CUF_CompressFolder(Pms_FolderName="X:\\TEMP\\BOOK\\MUSIC",
324
- Pms_File7z="X:\\temp\\book\\PPPK\\GOOD_FILE",
325
- Pms_Password="Gotech123",
326
- Pmi_SplitSize_K=640);
327
-
328
- obj_7z.CUF_CompressFile(Pms_FileSource="X:\\temp\\book\\*.png",
329
- Pms_File7z="X:\\temp\\book\\abcde\\pqrst\\PPPK-2\\我的PNG圖檔",
330
- Pms_Password="OKOKGOOD",
331
- Pmi_SplitSize_K=100);
332
-
333
- obj_7z.CUF_Decompress(Pms_ArchiveFile="X:\\TEMP\\BOOK\\abcde\\pqrst\\PPPK-2\\我的PNG圖檔.7z.001",
334
- Pms_OutputDir="X:\\temp\\OK了",
335
- Pms_Password="OKOKGOOD")