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.
- hutool/__init__.py +174 -0
- hutool/cache/__init__.py +7 -0
- hutool/cache/cache_util.py +47 -0
- hutool/cache/fifo_cache.py +87 -0
- hutool/cache/lfu_cache.py +129 -0
- hutool/cache/lru_cache.py +93 -0
- hutool/cache/timed_cache.py +115 -0
- hutool/captcha/__init__.py +3 -0
- hutool/captcha/captcha_util.py +215 -0
- hutool/core/__init__.py +23 -0
- hutool/core/_base.py +61 -0
- hutool/core/bean.py +214 -0
- hutool/core/codec.py +111 -0
- hutool/core/coll.py +635 -0
- hutool/core/date.py +1024 -0
- hutool/core/exceptions.py +66 -0
- hutool/core/io/__init__.py +0 -0
- hutool/core/io/data_size_util.py +79 -0
- hutool/core/io/file_name_util.py +111 -0
- hutool/core/io/file_util.py +650 -0
- hutool/core/io/io_util.py +133 -0
- hutool/core/io/path_util.py +247 -0
- hutool/core/io/resource_util.py +137 -0
- hutool/core/map.py +933 -0
- hutool/core/math_util.py +105 -0
- hutool/core/net.py +288 -0
- hutool/core/text/__init__.py +0 -0
- hutool/core/text/csv_util.py +54 -0
- hutool/core/text/str_builder.py +224 -0
- hutool/core/text/unicode_util.py +58 -0
- hutool/core/tree.py +242 -0
- hutool/core/util/__init__.py +63 -0
- hutool/core/util/array_util.py +503 -0
- hutool/core/util/boolean_util.py +124 -0
- hutool/core/util/charset_util.py +60 -0
- hutool/core/util/class_util.py +136 -0
- hutool/core/util/coordinate_util.py +186 -0
- hutool/core/util/credit_code_util.py +110 -0
- hutool/core/util/desensitized_util.py +194 -0
- hutool/core/util/enum_util.py +94 -0
- hutool/core/util/escape_util.py +97 -0
- hutool/core/util/hash_util.py +243 -0
- hutool/core/util/hex_util.py +140 -0
- hutool/core/util/id_util.py +147 -0
- hutool/core/util/idcard_util.py +300 -0
- hutool/core/util/number_util.py +720 -0
- hutool/core/util/object_util.py +294 -0
- hutool/core/util/page_util.py +61 -0
- hutool/core/util/phone_util.py +140 -0
- hutool/core/util/random_util.py +112 -0
- hutool/core/util/re_util.py +231 -0
- hutool/core/util/reflect_util.py +135 -0
- hutool/core/util/runtime_util.py +89 -0
- hutool/core/util/str_util.py +2320 -0
- hutool/core/util/system_util.py +62 -0
- hutool/core/util/url_util.py +232 -0
- hutool/core/util/version_util.py +41 -0
- hutool/core/util/xml_util.py +158 -0
- hutool/core/util/zip_util.py +126 -0
- hutool/cron/__init__.py +4 -0
- hutool/cron/cron_pattern.py +123 -0
- hutool/cron/cron_util.py +115 -0
- hutool/crypto/__init__.py +5 -0
- hutool/crypto/digest_util.py +167 -0
- hutool/crypto/secure_util.py +311 -0
- hutool/crypto/sign_util.py +74 -0
- hutool/dfa/__init__.py +3 -0
- hutool/dfa/sensitive_util.py +114 -0
- hutool/extra/__init__.py +6 -0
- hutool/extra/emoji_util.py +90 -0
- hutool/extra/pinyin_util.py +44 -0
- hutool/extra/qr_code_util.py +58 -0
- hutool/extra/template_util.py +41 -0
- hutool/http/__init__.py +6 -0
- hutool/http/html_util.py +88 -0
- hutool/http/http_request.py +188 -0
- hutool/http/http_response.py +139 -0
- hutool/http/http_util.py +237 -0
- hutool/json_util.py +251 -0
- hutool/jwt_util.py +57 -0
- hutool/setting/__init__.py +5 -0
- hutool/setting/props_util.py +79 -0
- hutool/setting/setting_util.py +80 -0
- hutool/setting/yaml_util.py +45 -0
- hutool_python-1.0.0.dist-info/LICENSE +127 -0
- hutool_python-1.0.0.dist-info/METADATA +438 -0
- hutool_python-1.0.0.dist-info/RECORD +89 -0
- hutool_python-1.0.0.dist-info/WHEEL +5 -0
- hutool_python-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"""Cron表达式解析与匹配"""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime, timedelta
|
|
4
|
+
from typing import List, Optional, Set
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class CronPattern:
|
|
8
|
+
"""Cron表达式解析与匹配
|
|
9
|
+
|
|
10
|
+
支持标准5位cron: 分 时 日 月 周
|
|
11
|
+
|
|
12
|
+
特殊字符说明:
|
|
13
|
+
|
|
14
|
+
- ``*`` : 匹配任意值
|
|
15
|
+
- ``,`` : 列举多个值 (如 1,3,5)
|
|
16
|
+
- ``-`` : 范围 (如 1-5)
|
|
17
|
+
- ``/`` : 步长 (如 */5 表示每5个单位)
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(self, pattern: str) -> None:
|
|
21
|
+
"""初始化CronPattern
|
|
22
|
+
|
|
23
|
+
:param pattern: cron表达式字符串,格式为 "分 时 日 月 周"
|
|
24
|
+
:raises ValueError: 表达式格式不正确
|
|
25
|
+
"""
|
|
26
|
+
self._pattern: str = pattern
|
|
27
|
+
self._fields: List[str] = pattern.strip().split()
|
|
28
|
+
if len(self._fields) != 5:
|
|
29
|
+
raise ValueError(f"无效的cron表达式 '{pattern}',必须包含5个字段: 分 时 日 月 周")
|
|
30
|
+
|
|
31
|
+
def match(self, dt: datetime) -> bool:
|
|
32
|
+
"""判断给定时间是否匹配
|
|
33
|
+
|
|
34
|
+
:param dt: 待匹配的时间
|
|
35
|
+
:return: 是否匹配cron表达式
|
|
36
|
+
"""
|
|
37
|
+
minute_set = self._parse_field(self._fields[0], 0, 59)
|
|
38
|
+
hour_set = self._parse_field(self._fields[1], 0, 23)
|
|
39
|
+
day_set = self._parse_field(self._fields[2], 1, 31)
|
|
40
|
+
month_set = self._parse_field(self._fields[3], 1, 12)
|
|
41
|
+
weekday_set = self._parse_field(self._fields[4], 0, 6)
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
dt.minute in minute_set
|
|
45
|
+
and dt.hour in hour_set
|
|
46
|
+
and dt.day in day_set
|
|
47
|
+
and dt.month in month_set
|
|
48
|
+
and dt.weekday() % 7 in weekday_set
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
def next_match_time(self, after: Optional[datetime] = None) -> datetime:
|
|
52
|
+
"""获取下一次匹配时间
|
|
53
|
+
|
|
54
|
+
:param after: 基准时间,默认为当前时间
|
|
55
|
+
:return: 下一次匹配的时间
|
|
56
|
+
:raises RuntimeError: 超过搜索上限仍未找到匹配时间
|
|
57
|
+
"""
|
|
58
|
+
if after is None:
|
|
59
|
+
after = datetime.now()
|
|
60
|
+
# 从下一分钟开始搜索
|
|
61
|
+
current = after.replace(second=0, microsecond=0) + timedelta(minutes=1)
|
|
62
|
+
# 最多搜索2年内的匹配
|
|
63
|
+
max_search = 366 * 24 * 60
|
|
64
|
+
for _ in range(max_search):
|
|
65
|
+
if self.match(current):
|
|
66
|
+
return current
|
|
67
|
+
current += timedelta(minutes=1)
|
|
68
|
+
raise RuntimeError(f"在2年内未找到匹配 '{self._pattern}' 的时间")
|
|
69
|
+
|
|
70
|
+
@staticmethod
|
|
71
|
+
def _parse_field(field: str, min_val: int, max_val: int) -> Set[int]:
|
|
72
|
+
"""解析单个cron字段
|
|
73
|
+
|
|
74
|
+
:param field: 字段字符串
|
|
75
|
+
:param min_val: 最小值
|
|
76
|
+
:param max_val: 最大值
|
|
77
|
+
:return: 匹配的值集合
|
|
78
|
+
:raises ValueError: 字段格式不正确
|
|
79
|
+
"""
|
|
80
|
+
values: Set[int] = set()
|
|
81
|
+
|
|
82
|
+
parts = field.split(",")
|
|
83
|
+
for part in parts:
|
|
84
|
+
step: Optional[int] = None
|
|
85
|
+
if "/" in part:
|
|
86
|
+
range_part, step_str = part.split("/", 1)
|
|
87
|
+
step = int(step_str)
|
|
88
|
+
if step <= 0:
|
|
89
|
+
raise ValueError(f"步长必须大于0: {part}")
|
|
90
|
+
else:
|
|
91
|
+
range_part = part
|
|
92
|
+
|
|
93
|
+
if range_part == "*":
|
|
94
|
+
start = min_val
|
|
95
|
+
end = max_val
|
|
96
|
+
elif "-" in range_part:
|
|
97
|
+
start_str, end_str = range_part.split("-", 1)
|
|
98
|
+
start = int(start_str)
|
|
99
|
+
end = int(end_str)
|
|
100
|
+
else:
|
|
101
|
+
val = int(range_part)
|
|
102
|
+
if step is not None:
|
|
103
|
+
start = val
|
|
104
|
+
end = max_val
|
|
105
|
+
else:
|
|
106
|
+
if val < min_val or val > max_val:
|
|
107
|
+
raise ValueError(f"值 {val} 超出范围 [{min_val}, {max_val}]")
|
|
108
|
+
values.add(val)
|
|
109
|
+
continue
|
|
110
|
+
|
|
111
|
+
if step is None:
|
|
112
|
+
step = 1
|
|
113
|
+
|
|
114
|
+
for v in range(start, end + 1, step):
|
|
115
|
+
if v < min_val or v > max_val:
|
|
116
|
+
raise ValueError(f"值 {v} 超出范围 [{min_val}, {max_val}]")
|
|
117
|
+
values.add(v)
|
|
118
|
+
|
|
119
|
+
return values
|
|
120
|
+
|
|
121
|
+
def __str__(self) -> str:
|
|
122
|
+
"""返回cron表达式字符串"""
|
|
123
|
+
return self._pattern
|
hutool/cron/cron_util.py
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""定时任务工具类"""
|
|
2
|
+
|
|
3
|
+
import threading
|
|
4
|
+
import time
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from typing import Callable, List, Optional
|
|
7
|
+
|
|
8
|
+
from .cron_pattern import CronPattern
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class _CronTask:
|
|
12
|
+
"""内部Cron任务"""
|
|
13
|
+
|
|
14
|
+
def __init__(self, pattern: CronPattern, func: Callable) -> None:
|
|
15
|
+
self.pattern = pattern
|
|
16
|
+
self.func = func
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class _FixedRateTask:
|
|
20
|
+
"""内部固定频率任务"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, func: Callable, period_seconds: int) -> None:
|
|
23
|
+
self.func = func
|
|
24
|
+
self.period_seconds = period_seconds
|
|
25
|
+
self.last_run: Optional[float] = None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class CronUtil:
|
|
29
|
+
"""定时任务工具类"""
|
|
30
|
+
|
|
31
|
+
_tasks: List[_CronTask] = []
|
|
32
|
+
_fixed_tasks: List[_FixedRateTask] = []
|
|
33
|
+
_running: bool = False
|
|
34
|
+
_thread: Optional[threading.Thread] = None
|
|
35
|
+
_lock = threading.Lock()
|
|
36
|
+
|
|
37
|
+
@classmethod
|
|
38
|
+
def schedule(cls, cron_pattern: str, func: Callable) -> None:
|
|
39
|
+
"""添加定时任务
|
|
40
|
+
|
|
41
|
+
:param cron_pattern: cron表达式字符串,格式为 "分 时 日 月 周"
|
|
42
|
+
:param func: 定时执行的函数
|
|
43
|
+
"""
|
|
44
|
+
pattern = CronPattern(cron_pattern)
|
|
45
|
+
with cls._lock:
|
|
46
|
+
cls._tasks.append(_CronTask(pattern, func))
|
|
47
|
+
|
|
48
|
+
@classmethod
|
|
49
|
+
def schedule_at_fixed_rate(cls, func: Callable, period_seconds: int) -> None:
|
|
50
|
+
"""添加固定频率任务
|
|
51
|
+
|
|
52
|
+
:param func: 定时执行的函数
|
|
53
|
+
:param period_seconds: 执行间隔(秒)
|
|
54
|
+
"""
|
|
55
|
+
with cls._lock:
|
|
56
|
+
task = _FixedRateTask(func, period_seconds)
|
|
57
|
+
cls._fixed_tasks.append(task)
|
|
58
|
+
|
|
59
|
+
@classmethod
|
|
60
|
+
def start(cls) -> None:
|
|
61
|
+
"""启动调度器
|
|
62
|
+
|
|
63
|
+
调度器在后台线程中运行,每秒检查一次是否有需要执行的任务。
|
|
64
|
+
"""
|
|
65
|
+
if cls._running:
|
|
66
|
+
return
|
|
67
|
+
cls._running = True
|
|
68
|
+
cls._thread = threading.Thread(target=cls._run_loop, daemon=True)
|
|
69
|
+
cls._thread.start()
|
|
70
|
+
|
|
71
|
+
@classmethod
|
|
72
|
+
def stop(cls) -> None:
|
|
73
|
+
"""停止调度器"""
|
|
74
|
+
cls._running = False
|
|
75
|
+
if cls._thread is not None:
|
|
76
|
+
cls._thread.join(timeout=5)
|
|
77
|
+
cls._thread = None
|
|
78
|
+
|
|
79
|
+
@classmethod
|
|
80
|
+
def restart(cls) -> None:
|
|
81
|
+
"""重启调度器"""
|
|
82
|
+
cls.stop()
|
|
83
|
+
cls.start()
|
|
84
|
+
|
|
85
|
+
@classmethod
|
|
86
|
+
def _run_loop(cls) -> None:
|
|
87
|
+
"""调度器主循环"""
|
|
88
|
+
while cls._running:
|
|
89
|
+
now = datetime.now()
|
|
90
|
+
# 检查cron任务
|
|
91
|
+
with cls._lock:
|
|
92
|
+
tasks_snapshot = list(cls._tasks)
|
|
93
|
+
fixed_tasks_snapshot = list(cls._fixed_tasks)
|
|
94
|
+
|
|
95
|
+
for task in tasks_snapshot:
|
|
96
|
+
try:
|
|
97
|
+
if task.pattern.match(now):
|
|
98
|
+
task.func()
|
|
99
|
+
except Exception as e:
|
|
100
|
+
print(f"[CronUtil] 执行cron任务时发生异常: {e}")
|
|
101
|
+
|
|
102
|
+
# 检查固定频率任务
|
|
103
|
+
for task in fixed_tasks_snapshot:
|
|
104
|
+
try:
|
|
105
|
+
current_time = time.time()
|
|
106
|
+
if task.last_run is None or (current_time - task.last_run >= task.period_seconds):
|
|
107
|
+
task.func()
|
|
108
|
+
task.last_run = current_time
|
|
109
|
+
except Exception as e:
|
|
110
|
+
print(f"[CronUtil] 执行固定频率任务时发生异常: {e}")
|
|
111
|
+
|
|
112
|
+
# 休眠到下一个分钟的开始
|
|
113
|
+
now = datetime.now()
|
|
114
|
+
seconds_until_next_minute = 60 - now.second
|
|
115
|
+
time.sleep(max(1, seconds_until_next_minute))
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import hashlib
|
|
2
|
+
import hmac
|
|
3
|
+
from typing import Union
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class DigestUtil:
|
|
7
|
+
"""摘要工具类
|
|
8
|
+
|
|
9
|
+
提供常用的摘要(哈希)算法封装,包括:
|
|
10
|
+
- MD5 / SHA-1 / SHA-256 / SHA-384 / SHA-512
|
|
11
|
+
- HMAC-MD5 / HMAC-SHA1 / HMAC-SHA256
|
|
12
|
+
所有方法同时支持 str 和 bytes 输入。
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
# ------------------------------------------------------------------ #
|
|
16
|
+
# 内部辅助
|
|
17
|
+
# ------------------------------------------------------------------ #
|
|
18
|
+
|
|
19
|
+
@staticmethod
|
|
20
|
+
def _to_bytes(data: Union[str, bytes]) -> bytes:
|
|
21
|
+
"""将输入统一转为 bytes"""
|
|
22
|
+
if isinstance(data, str):
|
|
23
|
+
return data.encode("utf-8")
|
|
24
|
+
return data
|
|
25
|
+
|
|
26
|
+
@staticmethod
|
|
27
|
+
def _digest(data: Union[str, bytes], algorithm: str) -> bytes:
|
|
28
|
+
"""通用摘要计算,返回原始 bytes"""
|
|
29
|
+
return hashlib.new(algorithm, DigestUtil._to_bytes(data)).digest()
|
|
30
|
+
|
|
31
|
+
@staticmethod
|
|
32
|
+
def _hex_digest(data: Union[str, bytes], algorithm: str) -> str:
|
|
33
|
+
"""通用摘要计算,返回十六进制字符串"""
|
|
34
|
+
return hashlib.new(algorithm, DigestUtil._to_bytes(data)).hexdigest()
|
|
35
|
+
|
|
36
|
+
# ------------------------------------------------------------------ #
|
|
37
|
+
# MD5
|
|
38
|
+
# ------------------------------------------------------------------ #
|
|
39
|
+
|
|
40
|
+
@staticmethod
|
|
41
|
+
def md5(data: Union[str, bytes]) -> bytes:
|
|
42
|
+
"""计算MD5摘要,返回原始bytes"""
|
|
43
|
+
return DigestUtil._digest(data, "md5")
|
|
44
|
+
|
|
45
|
+
@staticmethod
|
|
46
|
+
def md5_hex(data: Union[str, bytes]) -> str:
|
|
47
|
+
"""计算MD5摘要,返回32位十六进制字符串"""
|
|
48
|
+
return DigestUtil._hex_digest(data, "md5")
|
|
49
|
+
|
|
50
|
+
@staticmethod
|
|
51
|
+
def md5_hex16(data: Union[str, bytes]) -> str:
|
|
52
|
+
"""计算MD5摘要,返回16位十六进制字符串(取32位结果的中间16位)"""
|
|
53
|
+
return DigestUtil.md5_hex(data)[8:24]
|
|
54
|
+
|
|
55
|
+
# ------------------------------------------------------------------ #
|
|
56
|
+
# SHA-1
|
|
57
|
+
# ------------------------------------------------------------------ #
|
|
58
|
+
|
|
59
|
+
@staticmethod
|
|
60
|
+
def sha1(data: Union[str, bytes]) -> bytes:
|
|
61
|
+
"""计算SHA-1摘要,返回原始bytes"""
|
|
62
|
+
return DigestUtil._digest(data, "sha1")
|
|
63
|
+
|
|
64
|
+
@staticmethod
|
|
65
|
+
def sha1_hex(data: Union[str, bytes]) -> str:
|
|
66
|
+
"""计算SHA-1摘要,返回十六进制字符串"""
|
|
67
|
+
return DigestUtil._hex_digest(data, "sha1")
|
|
68
|
+
|
|
69
|
+
# ------------------------------------------------------------------ #
|
|
70
|
+
# SHA-256
|
|
71
|
+
# ------------------------------------------------------------------ #
|
|
72
|
+
|
|
73
|
+
@staticmethod
|
|
74
|
+
def sha256(data: Union[str, bytes]) -> bytes:
|
|
75
|
+
"""计算SHA-256摘要,返回原始bytes"""
|
|
76
|
+
return DigestUtil._digest(data, "sha256")
|
|
77
|
+
|
|
78
|
+
@staticmethod
|
|
79
|
+
def sha256_hex(data: Union[str, bytes]) -> str:
|
|
80
|
+
"""计算SHA-256摘要,返回十六进制字符串"""
|
|
81
|
+
return DigestUtil._hex_digest(data, "sha256")
|
|
82
|
+
|
|
83
|
+
# ------------------------------------------------------------------ #
|
|
84
|
+
# SHA-384
|
|
85
|
+
# ------------------------------------------------------------------ #
|
|
86
|
+
|
|
87
|
+
@staticmethod
|
|
88
|
+
def sha384(data: Union[str, bytes]) -> bytes:
|
|
89
|
+
"""计算SHA-384摘要,返回原始bytes"""
|
|
90
|
+
return DigestUtil._digest(data, "sha384")
|
|
91
|
+
|
|
92
|
+
@staticmethod
|
|
93
|
+
def sha384_hex(data: Union[str, bytes]) -> str:
|
|
94
|
+
"""计算SHA-384摘要,返回十六进制字符串"""
|
|
95
|
+
return DigestUtil._hex_digest(data, "sha384")
|
|
96
|
+
|
|
97
|
+
# ------------------------------------------------------------------ #
|
|
98
|
+
# SHA-512
|
|
99
|
+
# ------------------------------------------------------------------ #
|
|
100
|
+
|
|
101
|
+
@staticmethod
|
|
102
|
+
def sha512(data: Union[str, bytes]) -> bytes:
|
|
103
|
+
"""计算SHA-512摘要,返回原始bytes"""
|
|
104
|
+
return DigestUtil._digest(data, "sha512")
|
|
105
|
+
|
|
106
|
+
@staticmethod
|
|
107
|
+
def sha512_hex(data: Union[str, bytes]) -> str:
|
|
108
|
+
"""计算SHA-512摘要,返回十六进制字符串"""
|
|
109
|
+
return DigestUtil._hex_digest(data, "sha512")
|
|
110
|
+
|
|
111
|
+
# ------------------------------------------------------------------ #
|
|
112
|
+
# HMAC
|
|
113
|
+
# ------------------------------------------------------------------ #
|
|
114
|
+
|
|
115
|
+
@staticmethod
|
|
116
|
+
def _hmac_digest(data: Union[str, bytes], key: Union[str, bytes], algorithm: str) -> bytes:
|
|
117
|
+
"""通用HMAC计算,返回原始bytes"""
|
|
118
|
+
return hmac.new(
|
|
119
|
+
DigestUtil._to_bytes(key),
|
|
120
|
+
DigestUtil._to_bytes(data),
|
|
121
|
+
algorithm,
|
|
122
|
+
).digest()
|
|
123
|
+
|
|
124
|
+
@staticmethod
|
|
125
|
+
def _hmac_hex_digest(data: Union[str, bytes], key: Union[str, bytes], algorithm: str) -> str:
|
|
126
|
+
"""通用HMAC计算,返回十六进制字符串"""
|
|
127
|
+
return hmac.new(
|
|
128
|
+
DigestUtil._to_bytes(key),
|
|
129
|
+
DigestUtil._to_bytes(data),
|
|
130
|
+
algorithm,
|
|
131
|
+
).hexdigest()
|
|
132
|
+
|
|
133
|
+
# HMAC-MD5
|
|
134
|
+
|
|
135
|
+
@staticmethod
|
|
136
|
+
def hmac_md5(data: Union[str, bytes], key: Union[str, bytes]) -> bytes:
|
|
137
|
+
"""HMAC-MD5计算,返回原始bytes"""
|
|
138
|
+
return DigestUtil._hmac_digest(data, key, "md5")
|
|
139
|
+
|
|
140
|
+
@staticmethod
|
|
141
|
+
def hmac_md5_hex(data: Union[str, bytes], key: Union[str, bytes]) -> str:
|
|
142
|
+
"""HMAC-MD5计算,返回十六进制字符串"""
|
|
143
|
+
return DigestUtil._hmac_hex_digest(data, key, "md5")
|
|
144
|
+
|
|
145
|
+
# HMAC-SHA1
|
|
146
|
+
|
|
147
|
+
@staticmethod
|
|
148
|
+
def hmac_sha1(data: Union[str, bytes], key: Union[str, bytes]) -> bytes:
|
|
149
|
+
"""HMAC-SHA1计算,返回原始bytes"""
|
|
150
|
+
return DigestUtil._hmac_digest(data, key, "sha1")
|
|
151
|
+
|
|
152
|
+
@staticmethod
|
|
153
|
+
def hmac_sha1_hex(data: Union[str, bytes], key: Union[str, bytes]) -> str:
|
|
154
|
+
"""HMAC-SHA1计算,返回十六进制字符串"""
|
|
155
|
+
return DigestUtil._hmac_hex_digest(data, key, "sha1")
|
|
156
|
+
|
|
157
|
+
# HMAC-SHA256
|
|
158
|
+
|
|
159
|
+
@staticmethod
|
|
160
|
+
def hmac_sha256(data: Union[str, bytes], key: Union[str, bytes]) -> bytes:
|
|
161
|
+
"""HMAC-SHA256计算,返回原始bytes"""
|
|
162
|
+
return DigestUtil._hmac_digest(data, key, "sha256")
|
|
163
|
+
|
|
164
|
+
@staticmethod
|
|
165
|
+
def hmac_sha256_hex(data: Union[str, bytes], key: Union[str, bytes]) -> str:
|
|
166
|
+
"""HMAC-SHA256计算,返回十六进制字符串"""
|
|
167
|
+
return DigestUtil._hmac_hex_digest(data, key, "sha256")
|