hutool-python 1.0.0__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.
Files changed (89) hide show
  1. hutool/__init__.py +174 -0
  2. hutool/cache/__init__.py +7 -0
  3. hutool/cache/cache_util.py +47 -0
  4. hutool/cache/fifo_cache.py +87 -0
  5. hutool/cache/lfu_cache.py +129 -0
  6. hutool/cache/lru_cache.py +93 -0
  7. hutool/cache/timed_cache.py +115 -0
  8. hutool/captcha/__init__.py +3 -0
  9. hutool/captcha/captcha_util.py +215 -0
  10. hutool/core/__init__.py +23 -0
  11. hutool/core/_base.py +61 -0
  12. hutool/core/bean.py +214 -0
  13. hutool/core/codec.py +111 -0
  14. hutool/core/coll.py +635 -0
  15. hutool/core/date.py +1024 -0
  16. hutool/core/exceptions.py +66 -0
  17. hutool/core/io/__init__.py +0 -0
  18. hutool/core/io/data_size_util.py +79 -0
  19. hutool/core/io/file_name_util.py +111 -0
  20. hutool/core/io/file_util.py +650 -0
  21. hutool/core/io/io_util.py +133 -0
  22. hutool/core/io/path_util.py +247 -0
  23. hutool/core/io/resource_util.py +137 -0
  24. hutool/core/map.py +933 -0
  25. hutool/core/math_util.py +105 -0
  26. hutool/core/net.py +288 -0
  27. hutool/core/text/__init__.py +0 -0
  28. hutool/core/text/csv_util.py +54 -0
  29. hutool/core/text/str_builder.py +224 -0
  30. hutool/core/text/unicode_util.py +58 -0
  31. hutool/core/tree.py +242 -0
  32. hutool/core/util/__init__.py +63 -0
  33. hutool/core/util/array_util.py +503 -0
  34. hutool/core/util/boolean_util.py +124 -0
  35. hutool/core/util/charset_util.py +60 -0
  36. hutool/core/util/class_util.py +136 -0
  37. hutool/core/util/coordinate_util.py +186 -0
  38. hutool/core/util/credit_code_util.py +110 -0
  39. hutool/core/util/desensitized_util.py +194 -0
  40. hutool/core/util/enum_util.py +94 -0
  41. hutool/core/util/escape_util.py +97 -0
  42. hutool/core/util/hash_util.py +243 -0
  43. hutool/core/util/hex_util.py +140 -0
  44. hutool/core/util/id_util.py +147 -0
  45. hutool/core/util/idcard_util.py +300 -0
  46. hutool/core/util/number_util.py +720 -0
  47. hutool/core/util/object_util.py +294 -0
  48. hutool/core/util/page_util.py +61 -0
  49. hutool/core/util/phone_util.py +140 -0
  50. hutool/core/util/random_util.py +112 -0
  51. hutool/core/util/re_util.py +231 -0
  52. hutool/core/util/reflect_util.py +135 -0
  53. hutool/core/util/runtime_util.py +89 -0
  54. hutool/core/util/str_util.py +2320 -0
  55. hutool/core/util/system_util.py +62 -0
  56. hutool/core/util/url_util.py +232 -0
  57. hutool/core/util/version_util.py +41 -0
  58. hutool/core/util/xml_util.py +158 -0
  59. hutool/core/util/zip_util.py +126 -0
  60. hutool/cron/__init__.py +4 -0
  61. hutool/cron/cron_pattern.py +123 -0
  62. hutool/cron/cron_util.py +115 -0
  63. hutool/crypto/__init__.py +5 -0
  64. hutool/crypto/digest_util.py +167 -0
  65. hutool/crypto/secure_util.py +311 -0
  66. hutool/crypto/sign_util.py +74 -0
  67. hutool/dfa/__init__.py +3 -0
  68. hutool/dfa/sensitive_util.py +114 -0
  69. hutool/extra/__init__.py +6 -0
  70. hutool/extra/emoji_util.py +90 -0
  71. hutool/extra/pinyin_util.py +44 -0
  72. hutool/extra/qr_code_util.py +58 -0
  73. hutool/extra/template_util.py +41 -0
  74. hutool/http/__init__.py +6 -0
  75. hutool/http/html_util.py +88 -0
  76. hutool/http/http_request.py +188 -0
  77. hutool/http/http_response.py +139 -0
  78. hutool/http/http_util.py +237 -0
  79. hutool/json_util.py +251 -0
  80. hutool/jwt_util.py +57 -0
  81. hutool/setting/__init__.py +5 -0
  82. hutool/setting/props_util.py +79 -0
  83. hutool/setting/setting_util.py +80 -0
  84. hutool/setting/yaml_util.py +45 -0
  85. hutool_python-1.0.0.dist-info/LICENSE +127 -0
  86. hutool_python-1.0.0.dist-info/METADATA +438 -0
  87. hutool_python-1.0.0.dist-info/RECORD +89 -0
  88. hutool_python-1.0.0.dist-info/WHEEL +5 -0
  89. hutool_python-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,58 @@
1
+ import re
2
+ from typing import List
3
+
4
+
5
+ class UnicodeUtil:
6
+ """Unicode工具类"""
7
+
8
+ @staticmethod
9
+ def to_unicode(string: str) -> str:
10
+ """字符串转Unicode,如 "中文" -> "\\u4e2d\\u6587"
11
+
12
+ :param string: 原始字符串
13
+ :return: Unicode转义后的字符串
14
+ """
15
+ return string.encode("unicode_escape").decode("ascii")
16
+
17
+ @staticmethod
18
+ def from_unicode(unicode_str: str) -> str:
19
+ """Unicode转字符串,如 "\\u4e2d\\u6587" -> "中文"
20
+
21
+ :param unicode_str: Unicode转义字符串
22
+ :return: 解码后的原始字符串
23
+ """
24
+ return unicode_str.encode("ascii").decode("unicode_escape")
25
+
26
+ @staticmethod
27
+ def escape(content: str) -> str:
28
+ """转义非ASCII字符为Unicode
29
+
30
+ 将字符串中所有非ASCII字符转换为 \\uXXXX 格式的Unicode转义序列,
31
+ ASCII字符保持不变。
32
+
33
+ :param content: 原始字符串
34
+ :return: 转义后的字符串
35
+ """
36
+ result: List[str] = []
37
+ for ch in content:
38
+ if ord(ch) > 127:
39
+ result.append(f"\\u{ord(ch):04x}")
40
+ else:
41
+ result.append(ch)
42
+ return "".join(result)
43
+
44
+ @staticmethod
45
+ def unescape(content: str) -> str:
46
+ """反转义Unicode字符
47
+
48
+ 将字符串中的 \\uXXXX 格式的Unicode转义序列还原为实际字符,
49
+ 同时支持 \\uXXXXX 等五位及以上的Unicode码点。
50
+
51
+ :param content: 包含Unicode转义序列的字符串
52
+ :return: 还原后的原始字符串
53
+ """
54
+
55
+ def _replace(match: re.Match) -> str:
56
+ return chr(int(match.group(1), 16))
57
+
58
+ return re.sub(r"\\u([0-9a-fA-F]{4,})", _replace, content)
hutool/core/tree.py ADDED
@@ -0,0 +1,242 @@
1
+ from collections import deque
2
+ from typing import Any, Callable, Dict, List, Optional
3
+
4
+
5
+ class TreeNode:
6
+ """树节点
7
+
8
+ 用于表示树结构中的单个节点,包含节点标识、父节点标识、
9
+ 名称、权重、子节点列表以及扩展属性。
10
+ """
11
+
12
+ def __init__(
13
+ self,
14
+ id: Any = None,
15
+ parent_id: Any = None,
16
+ name: str = "",
17
+ weight: int = 0,
18
+ ):
19
+ """初始化树节点
20
+
21
+ :param id: 节点唯一标识
22
+ :param parent_id: 父节点标识,根节点通常为 None 或特定根标识
23
+ :param name: 节点名称
24
+ :param weight: 节点权重,用于排序
25
+ """
26
+ self.id = id
27
+ self.parent_id = parent_id
28
+ self.name = name
29
+ self.weight = weight
30
+ self.children: List[TreeNode] = []
31
+ self.extra: Dict[str, Any] = {}
32
+
33
+ def __repr__(self) -> str:
34
+ return (
35
+ f"TreeNode(id={self.id!r}, parent_id={self.parent_id!r}, "
36
+ f"name={self.name!r}, weight={self.weight}, "
37
+ f"children_count={len(self.children)})"
38
+ )
39
+
40
+ def to_dict(self) -> dict:
41
+ """将节点及其子树转为字典
42
+
43
+ :return: 包含节点信息和子节点列表的字典
44
+ """
45
+ result = {
46
+ "id": self.id,
47
+ "parentId": self.parent_id,
48
+ "name": self.name,
49
+ "weight": self.weight,
50
+ "children": [child.to_dict() for child in self.children],
51
+ }
52
+ if self.extra:
53
+ result.update(self.extra)
54
+ return result
55
+
56
+
57
+ class TreeUtil:
58
+ """树工具类
59
+
60
+ 提供从平铺列表构建树、遍历、查找、统计等常用操作。
61
+ """
62
+
63
+ @staticmethod
64
+ def build(
65
+ list_data: List[dict],
66
+ root_id: Any = None,
67
+ id_field: str = "id",
68
+ parent_field: str = "parentId",
69
+ children_field: str = "children",
70
+ name_field: str = "name",
71
+ weight_field: str = "weight",
72
+ ) -> List[TreeNode]:
73
+ """从平铺列表构建树
74
+
75
+ 将包含 id 和 parentId 的平铺字典列表转换为树形结构。
76
+
77
+ :param list_data: 平铺的字典列表
78
+ :param root_id: 根节点的 parent_id 值,默认为 None
79
+ :param id_field: 节点ID字段名,默认 "id"
80
+ :param parent_field: 父节点ID字段名,默认 "parentId"
81
+ :param children_field: 子节点列表字段名,默认 "children"
82
+ :param name_field: 节点名称字段名,默认 "name"
83
+ :param weight_field: 权重字段名,默认 "weight"
84
+ :return: 根节点列表(可能有多个顶级节点)
85
+ """
86
+ # 构建 id -> TreeNode 的映射
87
+ node_map: Dict[Any, TreeNode] = {}
88
+ for item in list_data:
89
+ node_id = item.get(id_field)
90
+ node = TreeNode(
91
+ id=node_id,
92
+ parent_id=item.get(parent_field),
93
+ name=str(item.get(name_field, "")),
94
+ weight=int(item.get(weight_field, 0)),
95
+ )
96
+ # 将未识别的字段存入 extra
97
+ known_fields = {id_field, parent_field, children_field, name_field, weight_field}
98
+ for key, value in item.items():
99
+ if key not in known_fields:
100
+ node.extra[key] = value
101
+ node_map[node_id] = node
102
+
103
+ # 组装父子关系
104
+ roots: List[TreeNode] = []
105
+ for item in list_data:
106
+ node_id = item.get(id_field)
107
+ parent_id = item.get(parent_field)
108
+ node = node_map[node_id]
109
+ if parent_id == root_id or parent_id not in node_map:
110
+ roots.append(node)
111
+ else:
112
+ parent = node_map.get(parent_id)
113
+ if parent is not None:
114
+ parent.children.append(node)
115
+
116
+ # 按权重排序子节点
117
+ def _sort_children(nodes: List[TreeNode]) -> None:
118
+ nodes.sort(key=lambda n: n.weight)
119
+ for child in nodes:
120
+ _sort_children(child.children)
121
+
122
+ _sort_children(roots)
123
+ return roots
124
+
125
+ @staticmethod
126
+ def get_node_id(tree_nodes: List[TreeNode], node_id: Any) -> Optional[TreeNode]:
127
+ """根据ID查找节点
128
+
129
+ :param tree_nodes: 树节点列表
130
+ :param node_id: 要查找的节点ID
131
+ :return: 匹配的节点,未找到返回 None
132
+ """
133
+ queue = deque(tree_nodes)
134
+ while queue:
135
+ node = queue.popleft()
136
+ if node.id == node_id:
137
+ return node
138
+ queue.extend(node.children)
139
+ return None
140
+
141
+ @staticmethod
142
+ def to_list(tree_nodes: List[TreeNode]) -> List[dict]:
143
+ """树转平铺列表
144
+
145
+ 将树形结构展平为字典列表,广度优先遍历。
146
+
147
+ :param tree_nodes: 根节点列表
148
+ :return: 平铺的字典列表
149
+ """
150
+ result: List[dict] = []
151
+ queue = deque(tree_nodes)
152
+ while queue:
153
+ node = queue.popleft()
154
+ result.append(node.to_dict())
155
+ queue.extend(node.children)
156
+ return result
157
+
158
+ @staticmethod
159
+ def foreach(
160
+ tree_nodes: List[TreeNode],
161
+ consumer: Callable[[TreeNode], None],
162
+ ) -> None:
163
+ """广度优先遍历(BFS)
164
+
165
+ 对树中每个节点执行 consumer 回调。
166
+
167
+ :param tree_nodes: 根节点列表
168
+ :param consumer: 遍历回调函数
169
+ """
170
+ queue = deque(tree_nodes)
171
+ while queue:
172
+ node = queue.popleft()
173
+ consumer(node)
174
+ queue.extend(node.children)
175
+
176
+ @staticmethod
177
+ def foreach_df(
178
+ tree_nodes: List[TreeNode],
179
+ consumer: Callable[[TreeNode], None],
180
+ ) -> None:
181
+ """深度优先遍历(DFS)
182
+
183
+ 对树中每个节点执行 consumer 回调,使用栈实现非递归遍历。
184
+
185
+ :param tree_nodes: 根节点列表
186
+ :param consumer: 遍历回调函数
187
+ """
188
+ stack = list(reversed(tree_nodes))
189
+ while stack:
190
+ node = stack.pop()
191
+ consumer(node)
192
+ # 反向压栈以保证从左到右的遍历顺序
193
+ stack.extend(reversed(node.children))
194
+
195
+ @staticmethod
196
+ def to_map(tree_nodes: List[TreeNode]) -> Dict[Any, TreeNode]:
197
+ """树转ID到节点的映射
198
+
199
+ :param tree_nodes: 根节点列表
200
+ :return: 以节点ID为键、节点对象为值的字典
201
+ """
202
+ result: Dict[Any, TreeNode] = {}
203
+ queue = deque(tree_nodes)
204
+ while queue:
205
+ node = queue.popleft()
206
+ result[node.id] = node
207
+ queue.extend(node.children)
208
+ return result
209
+
210
+ @staticmethod
211
+ def count(tree_nodes: List[TreeNode]) -> int:
212
+ """统计节点总数
213
+
214
+ :param tree_nodes: 根节点列表
215
+ :return: 树中所有节点的数量
216
+ """
217
+ total = 0
218
+ queue = deque(tree_nodes)
219
+ while queue:
220
+ node = queue.popleft()
221
+ total += 1
222
+ queue.extend(node.children)
223
+ return total
224
+
225
+ @staticmethod
226
+ def get_leaf_nodes(tree_nodes: List[TreeNode]) -> List[TreeNode]:
227
+ """获取所有叶子节点
228
+
229
+ 叶子节点是指没有子节点的节点。
230
+
231
+ :param tree_nodes: 根节点列表
232
+ :return: 叶子节点列表
233
+ """
234
+ leaves: List[TreeNode] = []
235
+ queue = deque(tree_nodes)
236
+ while queue:
237
+ node = queue.popleft()
238
+ if not node.children:
239
+ leaves.append(node)
240
+ else:
241
+ queue.extend(node.children)
242
+ return leaves
@@ -0,0 +1,63 @@
1
+ """Core util 工具类导出。"""
2
+
3
+ from .array_util import ArrayUtil
4
+ from .boolean_util import BooleanUtil
5
+ from .charset_util import CharsetUtil
6
+ from .class_util import ClassUtil
7
+ from .coordinate_util import CoordinateUtil
8
+ from .credit_code_util import CreditCodeUtil
9
+ from .desensitized_util import DesensitizedUtil
10
+ from .enum_util import EnumUtil
11
+ from .escape_util import EscapeUtil
12
+ from .hash_util import HashUtil
13
+ from .hex_util import HexUtil
14
+ from .id_util import IdUtil
15
+ from .idcard_util import IdcardUtil
16
+ from .number_util import NumberUtil
17
+ from .object_util import ObjectUtil
18
+ from .page_util import PageUtil
19
+ from .phone_util import PhoneUtil
20
+ from .random_util import RandomUtil
21
+ from .re_util import ReUtil
22
+ from .reflect_util import ReflectUtil
23
+ from .runtime_util import RuntimeUtil
24
+ from .str_util import CharPool, CharSequenceUtil, CharUtil, StrPool, StrUtil
25
+ from .system_util import SystemUtil
26
+ from .url_util import URLUtil
27
+ from .version_util import VersionUtil
28
+ from .xml_util import XmlUtil
29
+ from .zip_util import ZipUtil
30
+
31
+ __all__ = [
32
+ "ArrayUtil",
33
+ "BooleanUtil",
34
+ "CharPool",
35
+ "CharSequenceUtil",
36
+ "CharUtil",
37
+ "CharsetUtil",
38
+ "ClassUtil",
39
+ "CoordinateUtil",
40
+ "CreditCodeUtil",
41
+ "DesensitizedUtil",
42
+ "EnumUtil",
43
+ "EscapeUtil",
44
+ "HashUtil",
45
+ "HexUtil",
46
+ "IdUtil",
47
+ "IdcardUtil",
48
+ "NumberUtil",
49
+ "ObjectUtil",
50
+ "PageUtil",
51
+ "PhoneUtil",
52
+ "RandomUtil",
53
+ "ReUtil",
54
+ "ReflectUtil",
55
+ "RuntimeUtil",
56
+ "StrPool",
57
+ "StrUtil",
58
+ "SystemUtil",
59
+ "URLUtil",
60
+ "VersionUtil",
61
+ "XmlUtil",
62
+ "ZipUtil",
63
+ ]