tretool 0.2.1__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.
- tretool-0.2.1/LICENSE +19 -0
- tretool-0.2.1/PKG-INFO +28 -0
- tretool-0.2.1/README.md +13 -0
- tretool-0.2.1/pyproject.toml +28 -0
- tretool-0.2.1/setup.cfg +4 -0
- tretool-0.2.1/src/tretool/__init__.py +27 -0
- tretool-0.2.1/src/tretool/config.py +262 -0
- tretool-0.2.1/src/tretool/encoding.py +92 -0
- tretool-0.2.1/src/tretool/jsonlib.py +299 -0
- tretool-0.2.1/src/tretool/markfunc.py +152 -0
- tretool-0.2.1/src/tretool/mathlib.py +620 -0
- tretool-0.2.1/src/tretool/memorizeTools.py +24 -0
- tretool-0.2.1/src/tretool/path.py +1139 -0
- tretool-0.2.1/src/tretool/platformlib.py +332 -0
- tretool-0.2.1/src/tretool/plugin/plu.py +0 -0
- tretool-0.2.1/src/tretool/plugin.py +348 -0
- tretool-0.2.1/src/tretool/timelib.py +518 -0
- tretool-0.2.1/src/tretool/transform/__init__.py +1 -0
- tretool-0.2.1/src/tretool/transform/pdf.py +396 -0
- tretool-0.2.1/src/tretool/writeLog.py +69 -0
- tretool-0.2.1/src/tretool.egg-info/PKG-INFO +28 -0
- tretool-0.2.1/src/tretool.egg-info/SOURCES.txt +23 -0
- tretool-0.2.1/src/tretool.egg-info/dependency_links.txt +1 -0
- tretool-0.2.1/src/tretool.egg-info/top_level.txt +1 -0
- tretool-0.2.1/tests/tests.py +0 -0
tretool-0.2.1/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2018 The Python Packaging Authority
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
SOFTWARE.
|
tretool-0.2.1/PKG-INFO
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: tretool
|
3
|
+
Version: 0.2.1
|
4
|
+
Summary: 一个有着许多功能的Python工具库
|
5
|
+
Author-email: Jemy <sh_ljr_2013@163.com>
|
6
|
+
License-Expression: MIT
|
7
|
+
Project-URL: Homepage, https://github.com/pypa/sampleproject
|
8
|
+
Project-URL: Issues, https://github.com/pypa/sampleproject/issues
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
10
|
+
Classifier: Operating System :: OS Independent
|
11
|
+
Requires-Python: >=3.10
|
12
|
+
Description-Content-Type: text/markdown
|
13
|
+
License-File: LICENSE
|
14
|
+
Dynamic: license-file
|
15
|
+
|
16
|
+
# tretool
|
17
|
+
|
18
|
+
## tretool - Python多功能工具库
|
19
|
+
|
20
|
+
[](https://www.python.org/)
|
21
|
+
|
22
|
+
**tretool** 是一个集成常用功能的Python工具库。
|
23
|
+
|
24
|
+
## 📦 安装
|
25
|
+
|
26
|
+
### 使用pip
|
27
|
+
bash
|
28
|
+
```pip install tretool
|
tretool-0.2.1/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
[build-system]
|
2
|
+
requires = [
|
3
|
+
"chardet",
|
4
|
+
"packaging",
|
5
|
+
"rich",
|
6
|
+
"setuptools >= 77.0.3"
|
7
|
+
]
|
8
|
+
build-backend = "setuptools.build_meta"
|
9
|
+
|
10
|
+
[project]
|
11
|
+
name = "tretool"
|
12
|
+
version = "0.2.1"
|
13
|
+
authors = [
|
14
|
+
{ name="Jemy", email="sh_ljr_2013@163.com" },
|
15
|
+
]
|
16
|
+
description = "一个有着许多功能的Python工具库"
|
17
|
+
readme = "README.md"
|
18
|
+
requires-python = ">=3.10"
|
19
|
+
classifiers = [
|
20
|
+
"Programming Language :: Python :: 3",
|
21
|
+
"Operating System :: OS Independent",
|
22
|
+
]
|
23
|
+
license = "MIT"
|
24
|
+
license-files = ["LICEN[CS]E*"]
|
25
|
+
|
26
|
+
[project.urls]
|
27
|
+
Homepage = "https://github.com/pypa/sampleproject"
|
28
|
+
Issues = "https://github.com/pypa/sampleproject/issues"
|
tretool-0.2.1/setup.cfg
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
"""
|
2
|
+
# tretool
|
3
|
+
|
4
|
+
## tretool - Python多功能工具库
|
5
|
+
|
6
|
+
[](https://www.python.org/)
|
7
|
+
|
8
|
+
**tretool** 是一个集成常用功能的Python工具库。
|
9
|
+
"""
|
10
|
+
|
11
|
+
from . import config
|
12
|
+
|
13
|
+
from . import encoding
|
14
|
+
|
15
|
+
from . import jsonlib
|
16
|
+
|
17
|
+
from . import markfunc
|
18
|
+
from . import memorizeTools
|
19
|
+
|
20
|
+
from . import path
|
21
|
+
from . import platformlib
|
22
|
+
from . import plugin
|
23
|
+
|
24
|
+
from . import timelib
|
25
|
+
from . import transform
|
26
|
+
|
27
|
+
from . import writeLog
|
@@ -0,0 +1,262 @@
|
|
1
|
+
"""
|
2
|
+
### 配置管理库,提供安全的键值对存储和访问机制
|
3
|
+
|
4
|
+
特性:
|
5
|
+
- 类型安全的设置和获取
|
6
|
+
- 默认值支持
|
7
|
+
- 批量操作支持
|
8
|
+
- 配置项存在性检查
|
9
|
+
- 防止意外覆盖
|
10
|
+
- 配置文件持久化
|
11
|
+
- 配置变更回调
|
12
|
+
"""
|
13
|
+
|
14
|
+
import json
|
15
|
+
import os
|
16
|
+
from typing import Any, Callable, Dict, Optional
|
17
|
+
|
18
|
+
class Config:
|
19
|
+
"""
|
20
|
+
配置管理类,提供安全的键值对存储和访问机制
|
21
|
+
|
22
|
+
特性:
|
23
|
+
- 类型安全的设置和获取
|
24
|
+
- 默认值支持
|
25
|
+
- 批量操作支持
|
26
|
+
- 配置项存在性检查
|
27
|
+
- 防止意外覆盖
|
28
|
+
- 配置变更通知
|
29
|
+
|
30
|
+
使用示例:
|
31
|
+
```
|
32
|
+
config = Config({"theme": "dark"})
|
33
|
+
config.set_config("font_size", 14)
|
34
|
+
theme = config.get_config("theme", default="light")
|
35
|
+
|
36
|
+
# 添加配置变更监听
|
37
|
+
def on_config_change(key, old_value, new_value):
|
38
|
+
print(f"配置变更: {key} 从 {old_value} 改为 {new_value}")
|
39
|
+
|
40
|
+
config.add_change_listener(on_config_change)
|
41
|
+
|
42
|
+
# 保存和加载配置
|
43
|
+
config.save_to_file("settings.json")
|
44
|
+
new_config = Config.load_from_file("settings.json")
|
45
|
+
```
|
46
|
+
"""
|
47
|
+
|
48
|
+
def __init__(self, initial_config: Optional[Dict[str, Any]] = None):
|
49
|
+
"""
|
50
|
+
初始化配置存储
|
51
|
+
|
52
|
+
参数:
|
53
|
+
initial_config: 初始配置字典 (可选)
|
54
|
+
"""
|
55
|
+
self.config_dict = initial_config.copy() if initial_config else {}
|
56
|
+
self._lock = False # 防止意外修改的锁
|
57
|
+
self._change_listeners = [] # 配置变更监听器列表
|
58
|
+
|
59
|
+
def __str__(self) -> str:
|
60
|
+
"""返回配置的可读字符串表示"""
|
61
|
+
return json.dumps(self.config_dict, indent=2, ensure_ascii=False)
|
62
|
+
|
63
|
+
def __repr__(self) -> str:
|
64
|
+
"""返回配置的正式表示"""
|
65
|
+
return f"Config({self.config_dict})"
|
66
|
+
|
67
|
+
def __contains__(self, item: str) -> bool:
|
68
|
+
"""检查配置项是否存在"""
|
69
|
+
return item in self.config_dict
|
70
|
+
|
71
|
+
def __len__(self) -> int:
|
72
|
+
"""返回配置项的数量"""
|
73
|
+
return len(self.config_dict)
|
74
|
+
|
75
|
+
def add_change_listener(self, listener: Callable[[str, Any, Any], None]):
|
76
|
+
"""
|
77
|
+
添加配置变更监听器
|
78
|
+
|
79
|
+
参数:
|
80
|
+
listener: 回调函数,格式为 func(key, old_value, new_value)
|
81
|
+
"""
|
82
|
+
if listener not in self._change_listeners:
|
83
|
+
self._change_listeners.append(listener)
|
84
|
+
|
85
|
+
def remove_change_listener(self, listener: Callable[[str, Any, Any], None]):
|
86
|
+
"""移除配置变更监听器"""
|
87
|
+
if listener in self._change_listeners:
|
88
|
+
self._change_listeners.remove(listener)
|
89
|
+
|
90
|
+
def _notify_change(self, key: str, old_value: Any, new_value: Any):
|
91
|
+
"""通知所有监听器配置变更"""
|
92
|
+
for listener in self._change_listeners:
|
93
|
+
try:
|
94
|
+
listener(key, old_value, new_value)
|
95
|
+
except Exception as e:
|
96
|
+
print(f"配置变更通知错误: {e}")
|
97
|
+
|
98
|
+
def get_config(self, item: str, default: Any = None) -> Any:
|
99
|
+
"""
|
100
|
+
安全获取配置项
|
101
|
+
|
102
|
+
参数:
|
103
|
+
item: 配置键名
|
104
|
+
default: 当键不存在时返回的默认值
|
105
|
+
|
106
|
+
返回:
|
107
|
+
配置值或默认值
|
108
|
+
"""
|
109
|
+
return self.config_dict.get(item, default)
|
110
|
+
|
111
|
+
def set_config(self, item: str, value: Any) -> bool:
|
112
|
+
"""
|
113
|
+
设置配置项
|
114
|
+
|
115
|
+
参数:
|
116
|
+
item: 配置键名
|
117
|
+
value: 配置值
|
118
|
+
|
119
|
+
返回:
|
120
|
+
True 设置成功, False 设置失败
|
121
|
+
"""
|
122
|
+
if self._lock:
|
123
|
+
print(f"警告: 配置系统已锁定,无法修改 '{item}'")
|
124
|
+
return False
|
125
|
+
|
126
|
+
old_value = self.config_dict.get(item)
|
127
|
+
self.config_dict[item] = value
|
128
|
+
|
129
|
+
# 通知变更
|
130
|
+
self._notify_change(item, old_value, value)
|
131
|
+
return True
|
132
|
+
|
133
|
+
def delete_config(self, item: str) -> bool:
|
134
|
+
"""
|
135
|
+
删除配置项
|
136
|
+
|
137
|
+
参数:
|
138
|
+
item: 要删除的配置键名
|
139
|
+
|
140
|
+
返回:
|
141
|
+
True 删除成功, False 键不存在
|
142
|
+
"""
|
143
|
+
if item in self.config_dict:
|
144
|
+
old_value = self.config_dict[item]
|
145
|
+
del self.config_dict[item]
|
146
|
+
|
147
|
+
# 通知变更 (值为 None 表示删除)
|
148
|
+
self._notify_change(item, old_value, None)
|
149
|
+
return True
|
150
|
+
return False
|
151
|
+
|
152
|
+
def save_to_file(self, filename: str) -> bool:
|
153
|
+
"""
|
154
|
+
保存配置到文件
|
155
|
+
|
156
|
+
参数:
|
157
|
+
filename: 文件名
|
158
|
+
|
159
|
+
返回:
|
160
|
+
True 保存成功, False 保存失败
|
161
|
+
"""
|
162
|
+
try:
|
163
|
+
with open(filename, 'w', encoding='utf-8') as f:
|
164
|
+
json.dump(self.get_all_configs(), f, indent=2, ensure_ascii=False)
|
165
|
+
return True
|
166
|
+
except (IOError, TypeError) as e:
|
167
|
+
print(f"保存配置失败: {e}")
|
168
|
+
return False
|
169
|
+
|
170
|
+
@classmethod
|
171
|
+
def load_from_file(cls, filename: str) -> Optional['Config']:
|
172
|
+
"""
|
173
|
+
从文件加载配置
|
174
|
+
|
175
|
+
参数:
|
176
|
+
filename: 文件名
|
177
|
+
|
178
|
+
返回:
|
179
|
+
加载成功的 Config 实例,失败返回 None
|
180
|
+
"""
|
181
|
+
if not os.path.exists(filename):
|
182
|
+
print(f"配置文件不存在: {filename}")
|
183
|
+
return None
|
184
|
+
|
185
|
+
try:
|
186
|
+
with open(filename, 'r', encoding='utf-8') as f:
|
187
|
+
config_data = json.load(f)
|
188
|
+
return cls(config_data)
|
189
|
+
except (IOError, json.JSONDecodeError) as e:
|
190
|
+
print(f"加载配置失败: {e}")
|
191
|
+
return None
|
192
|
+
|
193
|
+
def has_config(self, item: str) -> bool:
|
194
|
+
"""检查配置项是否存在"""
|
195
|
+
return item in self.config_dict
|
196
|
+
|
197
|
+
def lock_config(self):
|
198
|
+
"""锁定配置防止修改"""
|
199
|
+
self._lock = True
|
200
|
+
|
201
|
+
def unlock_config(self):
|
202
|
+
"""解锁配置允许修改"""
|
203
|
+
self._lock = False
|
204
|
+
|
205
|
+
def is_locked(self) -> bool:
|
206
|
+
"""检查配置是否已锁定"""
|
207
|
+
return self._lock
|
208
|
+
|
209
|
+
def bulk_update(self, update_dict: Dict[str, Any]) -> bool:
|
210
|
+
"""
|
211
|
+
批量更新配置
|
212
|
+
|
213
|
+
参数:
|
214
|
+
update_dict: 包含多个键值对的字典
|
215
|
+
|
216
|
+
返回:
|
217
|
+
True 更新成功, False 更新失败
|
218
|
+
"""
|
219
|
+
if self._lock:
|
220
|
+
print("警告: 配置系统已锁定,批量更新被拒绝")
|
221
|
+
return False
|
222
|
+
|
223
|
+
# 记录变更
|
224
|
+
changes = {}
|
225
|
+
for key, value in update_dict.items():
|
226
|
+
old_value = self.config_dict.get(key)
|
227
|
+
self.config_dict[key] = value
|
228
|
+
changes[key] = (old_value, value)
|
229
|
+
|
230
|
+
# 批量通知变更
|
231
|
+
for key, (old_value, new_value) in changes.items():
|
232
|
+
self._notify_change(key, old_value, new_value)
|
233
|
+
|
234
|
+
return True
|
235
|
+
|
236
|
+
def get_all_configs(self) -> Dict[str, Any]:
|
237
|
+
"""获取所有配置的副本"""
|
238
|
+
return self.config_dict.copy()
|
239
|
+
|
240
|
+
def reset_config(self, new_config: Optional[Dict[str, Any]] = None) -> None:
|
241
|
+
"""
|
242
|
+
重置所有配置
|
243
|
+
|
244
|
+
参数:
|
245
|
+
new_config: 新的配置字典 (可选,默认清空)
|
246
|
+
"""
|
247
|
+
if self._lock:
|
248
|
+
print("警告: 配置系统已锁定,无法重置")
|
249
|
+
return
|
250
|
+
|
251
|
+
# 记录所有变更(删除)
|
252
|
+
for key in list(self.config_dict.keys()):
|
253
|
+
old_value = self.config_dict[key]
|
254
|
+
self._notify_change(key, old_value, None)
|
255
|
+
|
256
|
+
# 重置配置
|
257
|
+
self.config_dict = new_config.copy() if new_config else {}
|
258
|
+
|
259
|
+
# 通知所有新配置项
|
260
|
+
for key, value in self.config_dict.items():
|
261
|
+
self._notify_change(key, None, value)
|
262
|
+
|
@@ -0,0 +1,92 @@
|
|
1
|
+
import chardet
|
2
|
+
|
3
|
+
from typing import Union, BinaryIO
|
4
|
+
|
5
|
+
def detect_encoding(
|
6
|
+
input_data: Union[bytes, str, BinaryIO],
|
7
|
+
sample_size: int = 1024,
|
8
|
+
fallback_encoding: str = 'utf-8'
|
9
|
+
) -> str:
|
10
|
+
"""
|
11
|
+
自动检测文本数据的字符编码
|
12
|
+
|
13
|
+
参数:
|
14
|
+
input_data: 可以是以下类型之一:
|
15
|
+
- bytes: 原始字节数据
|
16
|
+
- str: 字符串(将尝试重新编码检测)
|
17
|
+
- BinaryIO: 文件对象(将读取前sample_size字节)
|
18
|
+
sample_size: 从文件/大数据中采样的字节数(默认1024)
|
19
|
+
fallback_encoding: 无法检测时使用的回退编码(默认'utf-8')
|
20
|
+
|
21
|
+
返回:
|
22
|
+
检测到的编码名称字符串
|
23
|
+
|
24
|
+
示例:
|
25
|
+
# 检测字节数据编码
|
26
|
+
detect_encoding(b'\xc3\xa9chantillon')
|
27
|
+
|
28
|
+
# 检测文件编码
|
29
|
+
with open('file.txt', 'rb') as f:
|
30
|
+
encoding = detect_encoding(f)
|
31
|
+
"""
|
32
|
+
raw_data = _get_sample_data(input_data, sample_size)
|
33
|
+
|
34
|
+
if not raw_data:
|
35
|
+
return fallback_encoding
|
36
|
+
|
37
|
+
try:
|
38
|
+
# 使用chardet进行编码检测
|
39
|
+
result = chardet.detect(raw_data)
|
40
|
+
confidence = result['confidence']
|
41
|
+
encoding = result['encoding'].lower()
|
42
|
+
|
43
|
+
# 验证检测结果
|
44
|
+
if confidence > 0.9:
|
45
|
+
return encoding
|
46
|
+
if confidence > 0.7 and validate_encoding(raw_data, encoding):
|
47
|
+
return encoding
|
48
|
+
|
49
|
+
# 尝试常见编码验证
|
50
|
+
for enc in ['utf-8', 'latin-1', 'gbk', 'gb2312', 'big5']:
|
51
|
+
if validate_encoding(raw_data, enc):
|
52
|
+
return enc
|
53
|
+
|
54
|
+
except Exception:
|
55
|
+
pass
|
56
|
+
|
57
|
+
return fallback_encoding
|
58
|
+
|
59
|
+
|
60
|
+
def _get_sample_data(
|
61
|
+
input_data: Union[bytes, str, BinaryIO],
|
62
|
+
sample_size: int
|
63
|
+
) -> bytes:
|
64
|
+
"""获取用于检测的样本数据"""
|
65
|
+
if isinstance(input_data, bytes):
|
66
|
+
return input_data[:sample_size]
|
67
|
+
|
68
|
+
if isinstance(input_data, str):
|
69
|
+
try:
|
70
|
+
return input_data.encode('latin-1', errors='ignore')[:sample_size]
|
71
|
+
except:
|
72
|
+
return b''
|
73
|
+
|
74
|
+
if hasattr(input_data, 'read'):
|
75
|
+
try:
|
76
|
+
pos = input_data.tell()
|
77
|
+
data = input_data.read(sample_size)
|
78
|
+
input_data.seek(pos) # 重置文件指针
|
79
|
+
return data if isinstance(data, bytes) else b''
|
80
|
+
except:
|
81
|
+
return b''
|
82
|
+
|
83
|
+
return b''
|
84
|
+
|
85
|
+
|
86
|
+
def validate_encoding(data: bytes, encoding: str) -> bool:
|
87
|
+
"""验证编码是否有效"""
|
88
|
+
try:
|
89
|
+
data.decode(encoding, errors='strict')
|
90
|
+
return True
|
91
|
+
except:
|
92
|
+
return False
|