absfuyu 3.1.1__py3-none-any.whl → 3.3.3__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.
Potentially problematic release.
This version of absfuyu might be problematic. Click here for more details.
- absfuyu/__init__.py +3 -10
- absfuyu/__main__.py +5 -250
- absfuyu/cli/__init__.py +51 -0
- absfuyu/cli/color.py +24 -0
- absfuyu/cli/config_group.py +56 -0
- absfuyu/cli/do_group.py +76 -0
- absfuyu/cli/game_group.py +109 -0
- absfuyu/config/__init__.py +117 -100
- absfuyu/config/config.json +0 -7
- absfuyu/core.py +5 -66
- absfuyu/everything.py +7 -9
- absfuyu/extensions/beautiful.py +30 -23
- absfuyu/extensions/dev/__init__.py +11 -8
- absfuyu/extensions/dev/password_hash.py +4 -2
- absfuyu/extensions/dev/passwordlib.py +7 -5
- absfuyu/extensions/dev/project_starter.py +4 -2
- absfuyu/extensions/dev/shutdownizer.py +148 -0
- absfuyu/extensions/extra/__init__.py +1 -2
- absfuyu/extensions/extra/data_analysis.py +182 -107
- absfuyu/fun/WGS.py +50 -26
- absfuyu/fun/__init__.py +6 -7
- absfuyu/fun/tarot.py +1 -1
- absfuyu/game/__init__.py +75 -81
- absfuyu/game/game_stat.py +36 -0
- absfuyu/game/sudoku.py +41 -48
- absfuyu/game/tictactoe.py +303 -548
- absfuyu/game/wordle.py +56 -47
- absfuyu/general/__init__.py +17 -7
- absfuyu/general/content.py +16 -15
- absfuyu/general/data_extension.py +282 -90
- absfuyu/general/generator.py +67 -67
- absfuyu/general/human.py +74 -78
- absfuyu/logger.py +94 -68
- absfuyu/pkg_data/__init__.py +29 -25
- absfuyu/py.typed +0 -0
- absfuyu/sort.py +61 -47
- absfuyu/tools/__init__.py +0 -1
- absfuyu/tools/converter.py +80 -62
- absfuyu/tools/keygen.py +62 -67
- absfuyu/tools/obfuscator.py +57 -53
- absfuyu/tools/stats.py +24 -24
- absfuyu/tools/web.py +10 -9
- absfuyu/util/__init__.py +71 -33
- absfuyu/util/api.py +53 -43
- absfuyu/util/json_method.py +25 -27
- absfuyu/util/lunar.py +20 -24
- absfuyu/util/path.py +362 -241
- absfuyu/util/performance.py +217 -135
- absfuyu/util/pkl.py +8 -8
- absfuyu/util/zipped.py +17 -19
- absfuyu/version.py +160 -147
- absfuyu-3.3.3.dist-info/METADATA +124 -0
- absfuyu-3.3.3.dist-info/RECORD +59 -0
- {absfuyu-3.1.1.dist-info → absfuyu-3.3.3.dist-info}/WHEEL +1 -2
- {absfuyu-3.1.1.dist-info → absfuyu-3.3.3.dist-info}/entry_points.txt +1 -0
- {absfuyu-3.1.1.dist-info → absfuyu-3.3.3.dist-info/licenses}/LICENSE +1 -1
- absfuyu/extensions/dev/pkglib.py +0 -98
- absfuyu/game/tictactoe2.py +0 -318
- absfuyu-3.1.1.dist-info/METADATA +0 -215
- absfuyu-3.1.1.dist-info/RECORD +0 -55
- absfuyu-3.1.1.dist-info/top_level.txt +0 -1
absfuyu/logger.py
CHANGED
|
@@ -3,8 +3,8 @@ Absfuyu: Logger
|
|
|
3
3
|
---------------
|
|
4
4
|
Custom Logger Module
|
|
5
5
|
|
|
6
|
-
Version: 1.3.
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 1.3.2
|
|
7
|
+
Date updated: 05/04/2024 (mm/dd/yyyy)
|
|
8
8
|
|
|
9
9
|
Usage:
|
|
10
10
|
------
|
|
@@ -13,28 +13,25 @@ Usage:
|
|
|
13
13
|
>>> logger.debug("This logs!")
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
|
-
|
|
17
16
|
# Module level
|
|
18
17
|
###########################################################################
|
|
19
18
|
__all__ = [
|
|
20
19
|
# logger
|
|
21
|
-
"logger",
|
|
20
|
+
"logger",
|
|
21
|
+
"compress_for_log",
|
|
22
22
|
# log level
|
|
23
|
-
"LogLevel"
|
|
23
|
+
"LogLevel",
|
|
24
24
|
]
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
# Library
|
|
28
28
|
###########################################################################
|
|
29
|
-
# from itertools import chain
|
|
30
29
|
import logging
|
|
31
|
-
from logging.handlers import (
|
|
32
|
-
TimedRotatingFileHandler as _TRFH,
|
|
33
|
-
RotatingFileHandler as _RFH
|
|
34
|
-
)
|
|
35
30
|
import math
|
|
31
|
+
from logging.handlers import RotatingFileHandler as _RFH
|
|
32
|
+
from logging.handlers import TimedRotatingFileHandler as _TRFH
|
|
36
33
|
from pathlib import Path
|
|
37
|
-
from typing import Optional, Union
|
|
34
|
+
from typing import Any, Optional, Union
|
|
38
35
|
|
|
39
36
|
|
|
40
37
|
# Setup
|
|
@@ -43,6 +40,7 @@ class LogLevel:
|
|
|
43
40
|
"""
|
|
44
41
|
``logging``'s log level wrapper + custom log level
|
|
45
42
|
"""
|
|
43
|
+
|
|
46
44
|
TRACE: int = logging.DEBUG - 5
|
|
47
45
|
DEBUG: int = logging.DEBUG
|
|
48
46
|
INFO: int = logging.INFO
|
|
@@ -51,12 +49,15 @@ class LogLevel:
|
|
|
51
49
|
CRITICAL: int = logging.CRITICAL
|
|
52
50
|
EXTREME: int = logging.CRITICAL + 10
|
|
53
51
|
|
|
52
|
+
|
|
54
53
|
class _LogFormat:
|
|
55
54
|
"""Some log format styles"""
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
|
|
56
|
+
FULL = "[%(asctime)s] [%(process)-d] [%(module)s] [%(name)s] [%(funcName)s] [%(levelname)-s] %(message)s" # Time|ProcessID|Module|Name|Function|LogType|Message
|
|
57
|
+
SHORT = "[%(module)s] [%(name)s] [%(funcName)s] [%(levelname)-s] %(message)s" # Module|Name|Function|LogType|Message
|
|
58
|
+
CONSOLE = "%(asctime)s [%(levelname)5s] %(funcName)s:%(lineno)3d: %(message)s" # Time|LogType|Function|LineNumber|Message
|
|
59
|
+
FILE = "%(asctime)s [%(levelname)5s] %(filename)s:%(funcName)s:%(lineno)3d: %(message)s" # Time|LogType|FileName|Function|LineNumber|Message
|
|
60
|
+
|
|
60
61
|
|
|
61
62
|
# Create a custom logger
|
|
62
63
|
logger = logging.getLogger(__name__)
|
|
@@ -65,8 +66,10 @@ logger.setLevel(logging.WARNING)
|
|
|
65
66
|
# Create handlers
|
|
66
67
|
## Console log handler
|
|
67
68
|
console_handler = logging.StreamHandler()
|
|
68
|
-
console_handler.setLevel(LogLevel.TRACE)
|
|
69
|
-
console_handler.setFormatter(
|
|
69
|
+
console_handler.setLevel(LogLevel.TRACE) # Minimum log level
|
|
70
|
+
console_handler.setFormatter(
|
|
71
|
+
logging.Formatter(_LogFormat.CONSOLE, datefmt="%Y-%m-%d %H:%M:%S")
|
|
72
|
+
)
|
|
70
73
|
logger.addHandler(console_handler)
|
|
71
74
|
|
|
72
75
|
|
|
@@ -75,32 +78,33 @@ logger.addHandler(console_handler)
|
|
|
75
78
|
def _compress_list_for_print(iterable: list, max_visible: Optional[int] = 5) -> str:
|
|
76
79
|
"""
|
|
77
80
|
Compress the list to be more log-readable
|
|
78
|
-
|
|
81
|
+
|
|
79
82
|
iterable: list
|
|
80
83
|
max_visible: Maximum items can be printed on screen (Minimum: 3)
|
|
81
84
|
"""
|
|
82
85
|
|
|
83
86
|
if max_visible is None or max_visible <= 2:
|
|
84
87
|
max_visible = 5
|
|
85
|
-
|
|
88
|
+
|
|
86
89
|
if len(iterable) <= max_visible:
|
|
87
90
|
return str(iterable)
|
|
88
|
-
else:
|
|
91
|
+
else:
|
|
89
92
|
# logger.debug(f"Max vis: {max_visible}")
|
|
90
93
|
if max_visible % 2 == 0:
|
|
91
|
-
cut_idx_1 = math.floor(max_visible/2) - 1
|
|
92
|
-
cut_idx_2 = math.floor(max_visible/2)
|
|
94
|
+
cut_idx_1 = math.floor(max_visible / 2) - 1
|
|
95
|
+
cut_idx_2 = math.floor(max_visible / 2)
|
|
93
96
|
else:
|
|
94
|
-
cut_idx_1 = cut_idx_2 = math.floor(max_visible/2)
|
|
95
|
-
|
|
97
|
+
cut_idx_1 = cut_idx_2 = math.floor(max_visible / 2)
|
|
98
|
+
|
|
96
99
|
# logger.debug(f"Cut pos: {(cut_idx_1, cut_idx_2)}")
|
|
97
100
|
# temp = [iterable[:cut_idx_1], ["..."], iterable[len(iterable)-cut_idx_2:]]
|
|
98
101
|
# out = list(chain.from_iterable(temp))
|
|
99
102
|
# out = [*iterable[:cut_idx_1], "...", *iterable[len(iterable)-cut_idx_2:]] # Version 2
|
|
100
|
-
out = f"{str(iterable[:cut_idx_1])[:-1]}, ...,{str(iterable[len(iterable)-cut_idx_2:])[1:]}"
|
|
103
|
+
out = f"{str(iterable[:cut_idx_1])[:-1]}, ...,{str(iterable[len(iterable)-cut_idx_2:])[1:]}" # Version 3
|
|
101
104
|
# logger.debug(out)
|
|
102
105
|
return f"{out} [Len: {len(iterable)}]"
|
|
103
106
|
|
|
107
|
+
|
|
104
108
|
def _compress_string_for_print(text: str, max_visible: Optional[int] = 120) -> str:
|
|
105
109
|
"""
|
|
106
110
|
Compress the string to be more log-readable
|
|
@@ -108,13 +112,13 @@ def _compress_string_for_print(text: str, max_visible: Optional[int] = 120) -> s
|
|
|
108
112
|
text: str
|
|
109
113
|
max_visible: Maximum text can be printed on screen (Minimum: 5)
|
|
110
114
|
"""
|
|
111
|
-
|
|
115
|
+
|
|
112
116
|
if max_visible is None or max_visible <= 5:
|
|
113
117
|
max_visible = 120
|
|
114
|
-
|
|
115
|
-
text = text.replace("\n", " ")
|
|
118
|
+
|
|
119
|
+
text = text.replace("\n", " ") # Remove new line
|
|
116
120
|
# logger.debug(text)
|
|
117
|
-
|
|
121
|
+
|
|
118
122
|
if len(text) <= max_visible:
|
|
119
123
|
return str(text)
|
|
120
124
|
else:
|
|
@@ -122,7 +126,8 @@ def _compress_string_for_print(text: str, max_visible: Optional[int] = 120) -> s
|
|
|
122
126
|
temp = f"{text[:cut_idx]}...{text[len(text)-cut_idx:]}"
|
|
123
127
|
return f"{temp} [Len: {len(text)}]"
|
|
124
128
|
|
|
125
|
-
|
|
129
|
+
|
|
130
|
+
def compress_for_log(object_: Any, max_visible: Optional[int] = None) -> str:
|
|
126
131
|
"""
|
|
127
132
|
Compress the object to be more log-readable
|
|
128
133
|
|
|
@@ -131,25 +136,25 @@ def compress_for_log(object_, max_visible: Optional[int] = None) -> str:
|
|
|
131
136
|
:returns: Compressed log output
|
|
132
137
|
:rtype: str
|
|
133
138
|
"""
|
|
134
|
-
|
|
139
|
+
|
|
135
140
|
if isinstance(object_, list):
|
|
136
141
|
return _compress_list_for_print(object_, max_visible)
|
|
137
|
-
|
|
138
|
-
elif isinstance(object_, set
|
|
142
|
+
|
|
143
|
+
elif isinstance(object_, (set, tuple)):
|
|
139
144
|
return _compress_list_for_print(list(object_), max_visible)
|
|
140
|
-
|
|
145
|
+
|
|
141
146
|
elif isinstance(object_, dict):
|
|
142
147
|
temp = [{k: v} for k, v in object_.items()]
|
|
143
148
|
return _compress_list_for_print(temp, max_visible)
|
|
144
|
-
|
|
149
|
+
|
|
145
150
|
elif isinstance(object_, str):
|
|
146
151
|
return _compress_string_for_print(object_, max_visible)
|
|
147
|
-
|
|
152
|
+
|
|
148
153
|
else:
|
|
149
154
|
try:
|
|
150
155
|
return _compress_string_for_print(str(object_), max_visible)
|
|
151
|
-
except:
|
|
152
|
-
return object_
|
|
156
|
+
except Exception:
|
|
157
|
+
return object_ # type: ignore
|
|
153
158
|
|
|
154
159
|
|
|
155
160
|
# Class
|
|
@@ -157,22 +162,23 @@ def compress_for_log(object_, max_visible: Optional[int] = None) -> str:
|
|
|
157
162
|
class _CustomLogger:
|
|
158
163
|
"""
|
|
159
164
|
Custom logger [W.I.P]
|
|
160
|
-
|
|
161
|
-
Create a custom logger
|
|
165
|
+
|
|
166
|
+
Create a custom logger
|
|
162
167
|
*Useable but maybe unstable*
|
|
163
168
|
"""
|
|
169
|
+
|
|
164
170
|
def __init__(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
171
|
+
self,
|
|
172
|
+
name: str,
|
|
173
|
+
cwd: Union[str, Path] = ".",
|
|
174
|
+
log_format: Optional[str] = None,
|
|
175
|
+
*,
|
|
176
|
+
save_log_file: bool = False,
|
|
177
|
+
separated_error_file: bool = False,
|
|
178
|
+
timed_log: bool = False,
|
|
179
|
+
date_log_format: Optional[str] = None,
|
|
180
|
+
error_log_size: int = 1_000_000, # 1 MB
|
|
181
|
+
) -> None:
|
|
176
182
|
"""
|
|
177
183
|
:param name: Custom logger name
|
|
178
184
|
:param cwd: Current working directory
|
|
@@ -185,17 +191,19 @@ class _CustomLogger:
|
|
|
185
191
|
"""
|
|
186
192
|
self._cwd = Path(cwd)
|
|
187
193
|
self.log_folder = self._cwd.joinpath("logs")
|
|
188
|
-
self.log_folder.mkdir(
|
|
194
|
+
self.log_folder.mkdir(
|
|
195
|
+
exist_ok=True, parents=True
|
|
196
|
+
) # Does not throw exception when folder existed
|
|
189
197
|
self.name = name
|
|
190
198
|
self.log_file = self.log_folder.joinpath(f"{name}.log")
|
|
191
199
|
|
|
192
200
|
# Create a custom logger
|
|
193
201
|
try:
|
|
194
202
|
self.logger = logging.getLogger(self.name)
|
|
195
|
-
except:
|
|
203
|
+
except Exception:
|
|
196
204
|
try:
|
|
197
205
|
self.logger = logging.getLogger(__name__)
|
|
198
|
-
except:
|
|
206
|
+
except Exception:
|
|
199
207
|
self.logger = logging.getLogger()
|
|
200
208
|
self.logger.setLevel(logging.DEBUG)
|
|
201
209
|
|
|
@@ -207,16 +215,20 @@ class _CustomLogger:
|
|
|
207
215
|
## Console log handler
|
|
208
216
|
if log_format is None:
|
|
209
217
|
# Time|LogType|Function|LineNumber|Message
|
|
210
|
-
_log_format =
|
|
218
|
+
_log_format = (
|
|
219
|
+
"%(asctime)s [%(levelname)5s] %(funcName)s:%(lineno)3d: %(message)s"
|
|
220
|
+
)
|
|
211
221
|
else:
|
|
212
222
|
_log_format = log_format
|
|
213
223
|
console_handler = logging.StreamHandler()
|
|
214
|
-
console_handler.setLevel(logging.DEBUG)
|
|
215
|
-
_console_log_format = _log_format
|
|
216
|
-
_console_formatter = logging.Formatter(
|
|
224
|
+
console_handler.setLevel(logging.DEBUG) # Minimum log level
|
|
225
|
+
_console_log_format = _log_format # Create formatters and add it to handlers
|
|
226
|
+
_console_formatter = logging.Formatter(
|
|
227
|
+
_console_log_format, datefmt=_date_format
|
|
228
|
+
)
|
|
217
229
|
console_handler.setFormatter(_console_formatter)
|
|
218
230
|
self._console_handler = console_handler
|
|
219
|
-
self.logger.addHandler(self._console_handler)
|
|
231
|
+
self.logger.addHandler(self._console_handler) # Add handlers to the logger
|
|
220
232
|
|
|
221
233
|
## Log file handler
|
|
222
234
|
if save_log_file:
|
|
@@ -225,18 +237,24 @@ class _CustomLogger:
|
|
|
225
237
|
_log_format = "%(asctime)s [%(levelname)5s] %(filename)s:%(funcName)s:%(lineno)3d: %(message)s"
|
|
226
238
|
else:
|
|
227
239
|
_log_format = log_format
|
|
228
|
-
file_handler = logging.FileHandler(
|
|
240
|
+
file_handler = logging.FileHandler(
|
|
241
|
+
self.log_file, mode="a", encoding="utf-8"
|
|
242
|
+
)
|
|
229
243
|
file_handler.setLevel(logging.DEBUG)
|
|
230
244
|
_file_log_format = _log_format
|
|
231
245
|
_file_formatter = logging.Formatter(_file_log_format, datefmt=_date_format)
|
|
232
246
|
file_handler.setFormatter(_file_formatter)
|
|
233
247
|
self._file_handler = file_handler
|
|
234
248
|
self.logger.addHandler(self._file_handler)
|
|
235
|
-
|
|
249
|
+
|
|
236
250
|
if timed_log:
|
|
237
251
|
## Time handler (split log every day)
|
|
238
|
-
time_handler = _TRFH(
|
|
239
|
-
|
|
252
|
+
time_handler = _TRFH(
|
|
253
|
+
self.log_folder.joinpath(f"{self.name}_timed.log"),
|
|
254
|
+
when="midnight",
|
|
255
|
+
interval=1,
|
|
256
|
+
encoding="utf-8",
|
|
257
|
+
)
|
|
240
258
|
time_handler.setLevel(logging.DEBUG)
|
|
241
259
|
time_handler.setFormatter(_file_formatter)
|
|
242
260
|
self._time_handler = time_handler
|
|
@@ -257,20 +275,27 @@ class _CustomLogger:
|
|
|
257
275
|
_log_format = "%(asctime)s [%(levelname)5s] %(filename)s:%(funcName)s:%(lineno)3d: %(message)s"
|
|
258
276
|
else:
|
|
259
277
|
_log_format = log_format
|
|
260
|
-
error_handler = _RFH(
|
|
261
|
-
|
|
278
|
+
error_handler = _RFH(
|
|
279
|
+
self.log_folder.joinpath(f"{self.name}_error.log"),
|
|
280
|
+
maxBytes=error_log_size,
|
|
281
|
+
backupCount=1,
|
|
282
|
+
encoding="utf-8",
|
|
283
|
+
)
|
|
262
284
|
error_handler.setLevel(logging.ERROR)
|
|
263
|
-
error_handler.setFormatter(_log_format)
|
|
285
|
+
error_handler.setFormatter(_log_format) # type: ignore
|
|
264
286
|
self._error_handler = error_handler
|
|
265
287
|
self.logger.addHandler(self._error_handler)
|
|
266
288
|
|
|
267
289
|
def __str__(self) -> str:
|
|
268
290
|
return f"{self.__class__.__name__}({self.name})"
|
|
291
|
+
|
|
269
292
|
def __repr__(self) -> str:
|
|
270
293
|
return self.__str__()
|
|
271
294
|
|
|
272
295
|
@staticmethod
|
|
273
|
-
def _add_logging_level(
|
|
296
|
+
def _add_logging_level(
|
|
297
|
+
level_name: str, level_num: int, method_name: Optional[str] = None
|
|
298
|
+
):
|
|
274
299
|
"""
|
|
275
300
|
Comprehensively adds a new logging level to the `logging` module and the
|
|
276
301
|
currently configured logging class.
|
|
@@ -302,6 +327,7 @@ class _CustomLogger:
|
|
|
302
327
|
def logForLevel(self, message, *args, **kwargs):
|
|
303
328
|
if self.isEnabledFor(level_num):
|
|
304
329
|
self._log(level_num, message, args, **kwargs)
|
|
330
|
+
|
|
305
331
|
def logToRoot(message, *args, **kwargs):
|
|
306
332
|
logging.log(level_num, message, *args, **kwargs)
|
|
307
333
|
|
|
@@ -311,7 +337,7 @@ class _CustomLogger:
|
|
|
311
337
|
setattr(logging, method_name, logToRoot)
|
|
312
338
|
|
|
313
339
|
def add_log_level(self, level_name: str, level_num: int):
|
|
314
|
-
__class__._add_logging_level(level_name, level_num)
|
|
340
|
+
__class__._add_logging_level(level_name, level_num) # type: ignore
|
|
315
341
|
if level_num < logging.DEBUG:
|
|
316
342
|
self._console_handler.setLevel(level_num)
|
|
317
343
|
self.logger.setLevel(level_num)
|
absfuyu/pkg_data/__init__.py
CHANGED
|
@@ -7,35 +7,31 @@ Version: 2.2.2
|
|
|
7
7
|
Date updated: 30/11/2023 (dd/mm/yyyy)
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
|
-
|
|
11
10
|
# Module level
|
|
12
11
|
###########################################################################
|
|
13
|
-
__all__ = [
|
|
14
|
-
"PkgData"
|
|
15
|
-
]
|
|
12
|
+
__all__ = ["PkgData"]
|
|
16
13
|
|
|
17
14
|
|
|
18
15
|
# Library
|
|
19
16
|
###########################################################################
|
|
17
|
+
import zlib
|
|
20
18
|
from ast import literal_eval
|
|
21
19
|
from importlib.resources import read_binary
|
|
22
20
|
from pathlib import Path
|
|
21
|
+
from sys import version_info as _python_version
|
|
23
22
|
from typing import List, Union
|
|
24
|
-
import zlib
|
|
25
|
-
import sys
|
|
26
23
|
|
|
27
|
-
if
|
|
24
|
+
if _python_version.minor >= 10:
|
|
28
25
|
from importlib.resources import files
|
|
29
26
|
else:
|
|
30
27
|
try:
|
|
31
|
-
from importlib_resources import files
|
|
32
|
-
except:
|
|
33
|
-
raise ImportError("Please install importlib-resources")
|
|
28
|
+
from importlib_resources import files # type: ignore
|
|
29
|
+
except Exception:
|
|
30
|
+
raise ImportError("Please install importlib-resources") # noqa: B904
|
|
34
31
|
|
|
35
32
|
from absfuyu.core import DATA_PATH
|
|
36
33
|
from absfuyu.logger import logger
|
|
37
34
|
|
|
38
|
-
|
|
39
35
|
# External Data
|
|
40
36
|
###########################################################################
|
|
41
37
|
_EXTERNAL_DATA = {
|
|
@@ -55,14 +51,16 @@ class DataList:
|
|
|
55
51
|
|
|
56
52
|
class PkgData:
|
|
57
53
|
"""Package data maker/loader"""
|
|
54
|
+
|
|
58
55
|
def __init__(self, data_name: str) -> None:
|
|
59
56
|
self.name = data_name
|
|
60
|
-
|
|
57
|
+
|
|
61
58
|
def __str__(self) -> str:
|
|
62
59
|
return f"{self.__class__.__name__}({self.name})"
|
|
60
|
+
|
|
63
61
|
def __repr__(self) -> str:
|
|
64
62
|
return self.__str__()
|
|
65
|
-
|
|
63
|
+
|
|
66
64
|
def _make_dat(self, data: str, name: Union[str, Path]):
|
|
67
65
|
"""
|
|
68
66
|
data: string data
|
|
@@ -71,11 +69,11 @@ class PkgData:
|
|
|
71
69
|
compressed_data = zlib.compress(str(data).encode(), zlib.Z_BEST_COMPRESSION)
|
|
72
70
|
with open(name, "wb") as file:
|
|
73
71
|
file.write(compressed_data)
|
|
74
|
-
|
|
72
|
+
|
|
75
73
|
def load_dat_data(self, evaluate: bool = False):
|
|
76
74
|
"""
|
|
77
75
|
Load ``.dat`` data from package resource
|
|
78
|
-
|
|
76
|
+
|
|
79
77
|
:param evaluate: use ``ast.literal_eval()`` to evaluate string data
|
|
80
78
|
:type evaluate: bool
|
|
81
79
|
:returns: Loaded data
|
|
@@ -98,45 +96,51 @@ class PkgData:
|
|
|
98
96
|
|
|
99
97
|
class _ManagePkgData:
|
|
100
98
|
"""Manage this package data"""
|
|
99
|
+
|
|
101
100
|
def __init__(self, pkg_data_loc: Union[str, Path]) -> None:
|
|
102
101
|
"""
|
|
103
102
|
pkg_data_loc: Package data location
|
|
104
103
|
"""
|
|
105
104
|
self.data_loc = Path(pkg_data_loc)
|
|
106
|
-
|
|
105
|
+
|
|
107
106
|
def __str__(self) -> str:
|
|
108
107
|
return f"{self.__class__.__name__}({self.data_loc.name})"
|
|
108
|
+
|
|
109
109
|
def __repr__(self) -> str:
|
|
110
110
|
return self.__str__()
|
|
111
|
-
|
|
111
|
+
|
|
112
112
|
def get_data_list(self, *, pattern: str = "*") -> List[Path]:
|
|
113
113
|
"""Get a list of data available"""
|
|
114
|
-
excludes = [
|
|
115
|
-
|
|
116
|
-
|
|
114
|
+
excludes = [
|
|
115
|
+
x for x in self.data_loc.glob("*.[pP][yY]")
|
|
116
|
+
] # exclude python scripts
|
|
117
|
+
return [
|
|
118
|
+
x for x in self.data_loc.glob(pattern) if x not in excludes and x.is_file()
|
|
119
|
+
]
|
|
120
|
+
|
|
117
121
|
@property
|
|
118
122
|
def data_list(self) -> List[str]:
|
|
119
123
|
"""List of available data"""
|
|
120
124
|
return [x.name for x in self.get_data_list()]
|
|
121
|
-
|
|
125
|
+
|
|
122
126
|
def download_all_data(self):
|
|
123
127
|
"""
|
|
124
128
|
Download all external data
|
|
125
129
|
"""
|
|
126
|
-
|
|
130
|
+
|
|
127
131
|
logger.debug("Downloading data...")
|
|
128
132
|
try:
|
|
129
133
|
from absfuyu.util.api import APIRequest
|
|
130
|
-
|
|
134
|
+
|
|
131
135
|
for data_name, data_link in _EXTERNAL_DATA.items():
|
|
132
136
|
logger.debug(f"Downloading {data_name}...")
|
|
133
137
|
data = APIRequest(data_link, encoding="utf-8")
|
|
134
138
|
data.fetch_data(update=True, json_cache=DATA_PATH.joinpath(data_name))
|
|
135
139
|
logger.debug(f"Downloading {data_name}...DONE")
|
|
136
140
|
logger.debug("Downloading data...DONE")
|
|
137
|
-
except:
|
|
141
|
+
except Exception:
|
|
138
142
|
logger.debug("Downloading data...FAILED")
|
|
139
|
-
|
|
143
|
+
|
|
140
144
|
def clear_data(self) -> None:
|
|
141
145
|
"""Clear data in data list"""
|
|
142
146
|
for x in self.get_data_list():
|
absfuyu/py.typed
ADDED
|
File without changes
|