ezKit 1.7.6__py3-none-any.whl → 1.7.7__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.
- ezKit/token.py +49 -15
- ezKit/utils.py +10 -3
- ezKit/xftp.py +111 -83
- {ezKit-1.7.6.dist-info → ezKit-1.7.7.dist-info}/METADATA +2 -1
- {ezKit-1.7.6.dist-info → ezKit-1.7.7.dist-info}/RECORD +8 -8
- {ezKit-1.7.6.dist-info → ezKit-1.7.7.dist-info}/LICENSE +0 -0
- {ezKit-1.7.6.dist-info → ezKit-1.7.7.dist-info}/WHEEL +0 -0
- {ezKit-1.7.6.dist-info → ezKit-1.7.7.dist-info}/top_level.txt +0 -0
ezKit/token.py
CHANGED
@@ -1,44 +1,78 @@
|
|
1
|
+
"""Token"""
|
1
2
|
import json
|
3
|
+
from typing import Any
|
4
|
+
|
5
|
+
from loguru import logger
|
2
6
|
|
3
7
|
from .cipher import AESCipher
|
4
8
|
from .utils import datetime_now, datetime_offset, datetime_string_to_datetime, datetime_to_string, v_true
|
5
9
|
|
6
10
|
|
7
|
-
def generate_token(key: str = 'Fc0zXCmGKd7tPu6W', timeout: int = 3600, data:
|
11
|
+
def generate_token(key: str = 'Fc0zXCmGKd7tPu6W', timeout: int = 3600, data: Any = None) -> (str | None):
|
8
12
|
try:
|
13
|
+
now = datetime_now()
|
14
|
+
|
15
|
+
if now is None:
|
16
|
+
return None
|
17
|
+
|
18
|
+
offset = datetime_offset(now, seconds=+timeout)
|
19
|
+
|
20
|
+
if offset is None:
|
21
|
+
return None
|
22
|
+
|
9
23
|
source = json.dumps(
|
10
24
|
obj={
|
11
|
-
|
12
|
-
|
25
|
+
"datetime": datetime_to_string(offset),
|
26
|
+
"data": data
|
13
27
|
},
|
14
28
|
default=str
|
15
29
|
)
|
30
|
+
|
16
31
|
cipher = AESCipher(key=key, algorithm='sha256')
|
32
|
+
|
17
33
|
return cipher.encrypt(source)
|
18
|
-
|
34
|
+
|
35
|
+
except Exception as e:
|
36
|
+
logger.exception(e)
|
19
37
|
return None
|
20
38
|
|
21
39
|
|
22
|
-
def parsing_token(token_string: str, key: str = 'Fc0zXCmGKd7tPu6W') ->
|
40
|
+
def parsing_token(token_string: str, key: str = 'Fc0zXCmGKd7tPu6W') -> (dict | None):
|
23
41
|
try:
|
24
|
-
if v_true(token_string, str):
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
42
|
+
if v_true(token_string, str) is False:
|
43
|
+
return None
|
44
|
+
|
45
|
+
cipher = AESCipher(key=key, algorithm='sha256')
|
46
|
+
|
47
|
+
target = cipher.decrypt(token_string)
|
48
|
+
|
49
|
+
if target is None:
|
30
50
|
return None
|
31
|
-
|
51
|
+
|
52
|
+
source: dict = json.loads(target)
|
53
|
+
|
54
|
+
source['datetime'] = datetime_string_to_datetime(source['datetime'])
|
55
|
+
|
56
|
+
return source
|
57
|
+
|
58
|
+
except Exception as e:
|
59
|
+
logger.exception(e)
|
32
60
|
return None
|
33
61
|
|
34
62
|
|
35
63
|
def certify_token(token_string: str, key: str = 'Fc0zXCmGKd7tPu6W') -> bool:
|
36
64
|
try:
|
65
|
+
|
37
66
|
result = parsing_token(token_string, key)
|
38
|
-
|
67
|
+
|
68
|
+
if result is None:
|
39
69
|
return False
|
40
|
-
|
70
|
+
|
71
|
+
if result.get('datetime') < datetime_now(): # type: ignore
|
41
72
|
return False
|
73
|
+
|
42
74
|
return True
|
43
|
-
|
75
|
+
|
76
|
+
except Exception as e:
|
77
|
+
logger.exception(e)
|
44
78
|
return False
|
ezKit/utils.py
CHANGED
@@ -984,7 +984,9 @@ def datetime_now(
|
|
984
984
|
"""获取当前日期和时间"""
|
985
985
|
_utc = kwargs.pop("utc", False)
|
986
986
|
try:
|
987
|
-
|
987
|
+
if _utc is True:
|
988
|
+
return datetime.datetime.now(datetime.timezone.utc)
|
989
|
+
return datetime.datetime.now(**kwargs)
|
988
990
|
except Exception as e:
|
989
991
|
if v_true(debug, bool):
|
990
992
|
logger.exception(e)
|
@@ -992,7 +994,7 @@ def datetime_now(
|
|
992
994
|
|
993
995
|
|
994
996
|
def datetime_offset(
|
995
|
-
datetime_instance: datetime.datetime,
|
997
|
+
datetime_instance: datetime.datetime | None = None,
|
996
998
|
debug: bool = False,
|
997
999
|
**kwargs
|
998
1000
|
) -> datetime.datetime | None:
|
@@ -1005,7 +1007,12 @@ def datetime_offset(
|
|
1005
1007
|
try:
|
1006
1008
|
if isinstance(datetime_instance, datetime.datetime):
|
1007
1009
|
return datetime_instance + datetime.timedelta(**kwargs)
|
1008
|
-
|
1010
|
+
|
1011
|
+
if _utc is True:
|
1012
|
+
return datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(**kwargs)
|
1013
|
+
|
1014
|
+
return datetime.datetime.now() + datetime.timedelta(**kwargs)
|
1015
|
+
|
1009
1016
|
except Exception as e:
|
1010
1017
|
if v_true(debug, bool):
|
1011
1018
|
logger.exception(e)
|
ezKit/xftp.py
CHANGED
@@ -1,15 +1,18 @@
|
|
1
|
-
|
2
|
-
ftplib: https://docs.python.org/3.
|
3
|
-
|
1
|
+
"""
|
2
|
+
ftplib: https://docs.python.org/3.11/library/ftplib.html
|
3
|
+
"""
|
4
4
|
import os
|
5
5
|
from ftplib import FTP
|
6
6
|
from pathlib import Path
|
7
7
|
|
8
|
+
from loguru import logger
|
9
|
+
|
8
10
|
|
9
11
|
class XFTP:
|
12
|
+
"""XFTP"""
|
10
13
|
|
11
|
-
def __init__(self, host=
|
12
|
-
|
14
|
+
def __init__(self, host="127.0.0.1", port=21, username="anonymous", password="", encoding="UTF-8", debuglevel=0):
|
15
|
+
"""Initiation"""
|
13
16
|
self.ftp = FTP()
|
14
17
|
self.ftp.set_debuglevel(debuglevel)
|
15
18
|
self.host = host
|
@@ -19,118 +22,141 @@ class XFTP:
|
|
19
22
|
self.encoding = encoding
|
20
23
|
self.retry = 1
|
21
24
|
|
22
|
-
def connect(self):
|
23
|
-
|
25
|
+
def connect(self) -> bool:
|
26
|
+
"""FTP connect"""
|
24
27
|
try:
|
25
28
|
self.ftp.connect(host=self.host, port=self.port, timeout=10)
|
26
29
|
self.ftp.encoding = self.encoding
|
27
30
|
self.ftp.login(user=self.username, passwd=self.password)
|
28
|
-
|
29
|
-
|
31
|
+
logger.success("FTP connect success")
|
32
|
+
logger.info("-" * 80)
|
30
33
|
return True
|
31
34
|
except Exception as e:
|
32
|
-
print(f
|
33
|
-
if self.retry >= 3:
|
34
|
-
|
35
|
-
|
36
|
-
self.retry += 1
|
37
|
-
self.connect()
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
35
|
+
# print(f"FTP connect error: {e}, retry...")
|
36
|
+
# if self.retry >= 3:
|
37
|
+
# print("FTP connect faild")
|
38
|
+
# return False
|
39
|
+
# self.retry += 1
|
40
|
+
# self.connect()
|
41
|
+
logger.exception(e)
|
42
|
+
return False
|
43
|
+
|
44
|
+
def close(self, info=None) -> bool:
|
45
|
+
"""FTP close"""
|
46
|
+
if info is not None:
|
47
|
+
logger.info(info)
|
42
48
|
try:
|
43
49
|
self.ftp.quit()
|
44
|
-
except:
|
50
|
+
except Exception as e:
|
51
|
+
logger.exception(e)
|
45
52
|
self.ftp.close()
|
46
|
-
|
47
|
-
|
53
|
+
logger.info("-" * 80)
|
54
|
+
logger.success("FTP connect closed")
|
55
|
+
return True
|
48
56
|
|
49
|
-
def get_file_list(self,
|
50
|
-
|
51
|
-
|
52
|
-
|
57
|
+
def get_file_list(self, target='/') -> (list[str] | None):
|
58
|
+
"""Get file list"""
|
59
|
+
try:
|
60
|
+
self.chdir_to_remote(target)
|
61
|
+
return self.ftp.nlst()
|
62
|
+
except Exception as e:
|
63
|
+
logger.exception(e)
|
64
|
+
return None
|
53
65
|
|
54
|
-
def get_file_size(self,
|
55
|
-
|
56
|
-
|
57
|
-
|
66
|
+
def get_file_size(self, file, target="/") -> (int | None):
|
67
|
+
"""Get file size"""
|
68
|
+
try:
|
69
|
+
self.chdir_to_remote(target)
|
70
|
+
return self.ftp.size(file)
|
71
|
+
except Exception as e:
|
72
|
+
logger.exception(e)
|
73
|
+
return None
|
58
74
|
|
59
|
-
def mkdir(self,
|
60
|
-
|
75
|
+
def mkdir(self, target="/") -> bool:
|
76
|
+
"""创建目录 (从 / 目录依次递增创建子目录. 如果目录存在, 创建目录时会报错, 所以这里忽略所有错误.)"""
|
61
77
|
try:
|
62
|
-
dir_list =
|
78
|
+
dir_list = target.split("/")
|
63
79
|
for i, _ in enumerate(dir_list):
|
64
|
-
|
80
|
+
dir_path = "/".join(dir_list[:i + 1])
|
65
81
|
try:
|
66
|
-
self.ftp.mkd(
|
67
|
-
except:
|
68
|
-
|
82
|
+
self.ftp.mkd(dir_path)
|
83
|
+
except Exception as e:
|
84
|
+
logger.exception(e)
|
69
85
|
return True
|
70
|
-
except:
|
86
|
+
except Exception as e:
|
87
|
+
logger.exception(e)
|
71
88
|
return False
|
72
89
|
|
73
|
-
def chdir_to_remote(self,
|
74
|
-
|
90
|
+
def chdir_to_remote(self, target="/") -> bool:
|
91
|
+
"""change to remote directory"""
|
75
92
|
try:
|
76
|
-
self.ftp.cwd(
|
77
|
-
|
78
|
-
|
93
|
+
self.ftp.cwd(target)
|
94
|
+
return True
|
95
|
+
except Exception as e:
|
96
|
+
self.close(f"remote directory error: {target}")
|
97
|
+
logger.exception(e)
|
98
|
+
return False
|
79
99
|
|
80
100
|
def x_exit(self, info=None):
|
81
|
-
|
82
|
-
|
101
|
+
"""Exit"""
|
102
|
+
if info is not None:
|
103
|
+
logger.info(info)
|
83
104
|
# 注意: exit() 并不会退出脚本, 配合 try 使用
|
84
105
|
exit()
|
85
106
|
|
86
|
-
def x_exec(self, local_dir=
|
87
|
-
|
107
|
+
def x_exec(self, local_dir=".", local_file="", remote_dir="/", remote_file="", upload=False):
|
108
|
+
"""Download or Upload"""
|
88
109
|
|
89
110
|
bufsize = 1024
|
90
|
-
local_path = local_dir
|
91
|
-
remote_path = remote_dir
|
92
|
-
|
111
|
+
local_path = f"{local_dir}/{local_file}"
|
112
|
+
remote_path = f"{remote_dir}/{remote_file}"
|
113
|
+
|
114
|
+
info = 'Download'
|
115
|
+
if upload is True:
|
116
|
+
info = 'Upload'
|
93
117
|
|
94
118
|
# 检查参数
|
95
|
-
if upload:
|
96
|
-
if local_file ==
|
119
|
+
if upload is True:
|
120
|
+
if local_file == "":
|
97
121
|
self.close('Argument Miss: local file')
|
98
122
|
# 如果没有设置 远程文件 名称, 则使用 本地文件 名称
|
99
|
-
if remote_file ==
|
123
|
+
if remote_file == "":
|
100
124
|
remote_file = local_file
|
101
|
-
remote_path = remote_dir
|
125
|
+
remote_path = f"{remote_dir}/{remote_file}"
|
102
126
|
else:
|
103
|
-
if remote_file ==
|
104
|
-
self.close(
|
127
|
+
if remote_file == "":
|
128
|
+
self.close("Argument Miss: remote file")
|
105
129
|
# 如果没有设置 本地文件 名称, 则使用 远程文件 名称
|
106
|
-
if local_file ==
|
130
|
+
if local_file == "":
|
107
131
|
local_file = remote_file
|
108
|
-
local_path = local_dir
|
132
|
+
local_path = f"{local_dir}/{local_file}"
|
109
133
|
|
110
134
|
# 进入本地目录
|
111
135
|
try:
|
112
|
-
if upload:
|
136
|
+
if upload is True:
|
113
137
|
# 检查本地目录
|
114
138
|
stat = Path(local_dir)
|
115
|
-
|
139
|
+
if stat.exists() is False:
|
140
|
+
self.close(f"Local directory error: {local_dir}")
|
116
141
|
else:
|
117
142
|
# 创建本地目录
|
118
143
|
Path(local_dir).mkdir(parents=True, exist_ok=True)
|
119
144
|
# 进入本地目录
|
120
145
|
os.chdir(local_dir)
|
121
|
-
except:
|
146
|
+
except Exception as e:
|
147
|
+
logger.exception(e)
|
122
148
|
# 第一层 try 使用 self.x_exit() 无效, 直接使用 self.close()
|
123
|
-
self.close(f
|
149
|
+
self.close(f"Local directory error: {local_dir}")
|
124
150
|
|
125
151
|
# 上传或下载
|
126
152
|
try:
|
127
153
|
|
128
|
-
if upload:
|
154
|
+
if upload is True:
|
129
155
|
|
130
|
-
|
156
|
+
# 上传
|
131
157
|
|
132
158
|
# 创建远程目录
|
133
|
-
if remote_dir !=
|
159
|
+
if remote_dir != "/":
|
134
160
|
self.mkdir(remote_dir)
|
135
161
|
|
136
162
|
# 进入远程目录
|
@@ -139,52 +165,54 @@ class XFTP:
|
|
139
165
|
# 上传文件
|
140
166
|
stat = Path(local_file)
|
141
167
|
if stat.exists() and stat.is_file():
|
142
|
-
with open(local_file,
|
168
|
+
with open(local_file, "rb") as fid:
|
143
169
|
self.ftp.storbinary(f'STOR {remote_file}', fid, bufsize)
|
144
|
-
|
170
|
+
logger.success(f"{info} success: {local_path.replace('//', '/')} -> {remote_path.replace('//', '/')}")
|
145
171
|
return True
|
146
|
-
|
147
|
-
|
172
|
+
|
173
|
+
self.x_exit(f"{info} error: {local_path.replace('//', '/')} is not exist")
|
148
174
|
|
149
175
|
else:
|
150
176
|
|
151
|
-
|
177
|
+
# 下载
|
152
178
|
|
153
179
|
# 进入远程目录
|
154
180
|
self.chdir_to_remote(remote_dir)
|
155
181
|
|
156
182
|
# 下载文件
|
157
183
|
if remote_file in self.ftp.nlst():
|
158
|
-
with open(local_file,
|
184
|
+
with open(local_file, "wb") as fid:
|
159
185
|
self.ftp.retrbinary(f'RETR {remote_file}', fid.write, bufsize)
|
160
|
-
|
186
|
+
logger.success(f"{info} success: {remote_path.replace('//', '/')} -> {local_path.replace('//', '/')}")
|
161
187
|
return True
|
162
|
-
|
163
|
-
|
188
|
+
|
189
|
+
self.x_exit(f"{info} error: {remote_path.replace('//', '/')} is not exist")
|
164
190
|
|
165
191
|
except Exception as e:
|
166
192
|
# 第一层 try 使用 self.x_exit() 无效, 直接使用 self.close()
|
167
193
|
# self.close('{} faild! Please check {} or {}'.format(info, local_path, remote_path))
|
168
|
-
self.close(f
|
194
|
+
self.close(f"{info} error: {e}")
|
169
195
|
return False
|
170
196
|
|
171
|
-
def handle_all(self, local_dir=
|
172
|
-
|
173
|
-
if upload:
|
197
|
+
def handle_all(self, local_dir=".", remote_dir="/", upload=False):
|
198
|
+
"""Handle All"""
|
199
|
+
if upload is True:
|
174
200
|
# 检查本地目录
|
175
201
|
stat = Path(local_dir)
|
176
|
-
|
202
|
+
if stat.exists() is False:
|
203
|
+
self.close(f"Local directory error: {local_dir}")
|
177
204
|
# 获取文件列表
|
178
205
|
local_files = [f for f in os.listdir(local_dir) if os.path.isfile(os.path.join(local_dir, f))]
|
179
206
|
for i in local_files:
|
180
207
|
self.x_exec(local_dir=local_dir, remote_dir=remote_dir, local_file=i, upload=True)
|
181
208
|
else:
|
182
209
|
remote_files = self.get_file_list(remote_dir)
|
183
|
-
|
184
|
-
|
210
|
+
if remote_files is not None:
|
211
|
+
for i in remote_files:
|
212
|
+
self.x_exec(local_dir=local_dir, remote_dir=remote_dir, remote_file=i)
|
185
213
|
|
186
|
-
def retrlines(self, remote_dir=
|
187
|
-
|
214
|
+
def retrlines(self, remote_dir="/", cmd="LIST"):
|
215
|
+
"""Retrlines"""
|
188
216
|
try:
|
189
217
|
self.chdir_to_remote(remote_dir)
|
190
218
|
print(self.ftp.retrlines(cmd))
|
@@ -11,12 +11,12 @@ ezKit/qywx.py,sha256=7eWrlTLrUj6U6cViEGbT6_LQxFGVqkhGAefBSS6T_-0,6531
|
|
11
11
|
ezKit/redis.py,sha256=pY4SPlcgQ7S8IeY2xoDpxy-xCZxzZQrQJNAoWRsC1dI,1773
|
12
12
|
ezKit/reports.py,sha256=dBBggggCCLuk5YD6SjdUPuxTr3wiJojP3lA7dQfg6Pk,8898
|
13
13
|
ezKit/sendemail.py,sha256=AAdxBvEYN_AJVvBkSAvXzhXC5jkbRsD_8P51h2SdTRw,8413
|
14
|
-
ezKit/token.py,sha256=
|
15
|
-
ezKit/utils.py,sha256=
|
16
|
-
ezKit/xftp.py,sha256=
|
14
|
+
ezKit/token.py,sha256=Q7z2ImQWs6NRxMtpsgNo9mhBeSs8nRCHCaWPf4031qg,1797
|
15
|
+
ezKit/utils.py,sha256=UBAeybjLAB0tBLPD2M2QXfpI_smtkmPP4t7dX-Pcsu4,48849
|
16
|
+
ezKit/xftp.py,sha256=BlxDctgJaCNeQNsVMwW6BcP3sL21SMVs-nPMjU_6rVg,7774
|
17
17
|
ezKit/zabbix.py,sha256=soM5UEeYMfm7NczbPOVLirmHm3G20dECQ0aCBttZfhQ,28350
|
18
|
-
ezKit-1.7.
|
19
|
-
ezKit-1.7.
|
20
|
-
ezKit-1.7.
|
21
|
-
ezKit-1.7.
|
22
|
-
ezKit-1.7.
|
18
|
+
ezKit-1.7.7.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
19
|
+
ezKit-1.7.7.dist-info/METADATA,sha256=7DiaRRyo1lystQf8VPWxpqkKHUK60DeKXgT2wmGSXbw,192
|
20
|
+
ezKit-1.7.7.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
21
|
+
ezKit-1.7.7.dist-info/top_level.txt,sha256=aYLB_1WODsqNTsTFWcKP-BN0KCTKcV-HZJ4zlHkCFw8,6
|
22
|
+
ezKit-1.7.7.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|