absfuyu 3.2.0__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 +55 -94
- 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 +110 -58
- 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 +38 -40
- 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 +36 -98
- absfuyu/util/pkl.py +8 -8
- absfuyu/util/zipped.py +17 -19
- absfuyu/version.py +137 -148
- absfuyu-3.3.3.dist-info/METADATA +124 -0
- absfuyu-3.3.3.dist-info/RECORD +59 -0
- {absfuyu-3.2.0.dist-info → absfuyu-3.3.3.dist-info}/WHEEL +1 -2
- {absfuyu-3.2.0.dist-info → absfuyu-3.3.3.dist-info}/entry_points.txt +1 -0
- {absfuyu-3.2.0.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.2.0.dist-info/METADATA +0 -216
- absfuyu-3.2.0.dist-info/RECORD +0 -55
- absfuyu-3.2.0.dist-info/top_level.txt +0 -1
absfuyu/util/performance.py
CHANGED
|
@@ -3,8 +3,8 @@ Absfuyu: Performance
|
|
|
3
3
|
--------------------
|
|
4
4
|
Performance Check
|
|
5
5
|
|
|
6
|
-
Version: 1.2.
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 1.2.3
|
|
7
|
+
Date updated: 05/04/2024 (dd/mm/yyyy)
|
|
8
8
|
|
|
9
9
|
Feature:
|
|
10
10
|
--------
|
|
@@ -15,7 +15,6 @@ Feature:
|
|
|
15
15
|
- Checker
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
|
|
19
18
|
# Module level
|
|
20
19
|
###########################################################################
|
|
21
20
|
__all__ = [
|
|
@@ -23,8 +22,6 @@ __all__ = [
|
|
|
23
22
|
"function_debug",
|
|
24
23
|
"measure_performance",
|
|
25
24
|
"retry",
|
|
26
|
-
# Functions
|
|
27
|
-
"var_check",
|
|
28
25
|
# Class
|
|
29
26
|
"Checker",
|
|
30
27
|
]
|
|
@@ -32,20 +29,23 @@ __all__ = [
|
|
|
32
29
|
|
|
33
30
|
# Library
|
|
34
31
|
###########################################################################
|
|
32
|
+
import time
|
|
33
|
+
import tracemalloc
|
|
35
34
|
from functools import wraps
|
|
36
35
|
from inspect import getsource
|
|
37
|
-
from time import perf_counter, sleep
|
|
38
|
-
import tracemalloc
|
|
39
36
|
from typing import Any, Callable, Dict, List, Union
|
|
40
37
|
|
|
41
|
-
from deprecated import
|
|
38
|
+
from deprecated.sphinx import versionadded, versionchanged
|
|
42
39
|
|
|
43
40
|
from absfuyu.general.data_extension import ListNoDunder
|
|
41
|
+
|
|
44
42
|
# from absfuyu.logger import logger, LogLevel
|
|
45
43
|
|
|
44
|
+
|
|
46
45
|
# Function
|
|
47
46
|
###########################################################################
|
|
48
|
-
|
|
47
|
+
@versionchanged(version="3.2.0", reason="Clean up code")
|
|
48
|
+
def measure_performance(func: Callable) -> Callable: # type: ignore
|
|
49
49
|
r"""
|
|
50
50
|
Measure performance of a function
|
|
51
51
|
|
|
@@ -77,18 +77,18 @@ def measure_performance(func: Callable) -> Callable:
|
|
|
77
77
|
Time elapsed (seconds): 0.000002
|
|
78
78
|
--------------------------------------
|
|
79
79
|
"""
|
|
80
|
-
|
|
80
|
+
|
|
81
81
|
@wraps(func)
|
|
82
82
|
def wrapper(*args, **kwargs) -> Any:
|
|
83
83
|
# Performance check
|
|
84
84
|
tracemalloc.start() # Start memory measure
|
|
85
|
-
start_time = perf_counter() # Start time measure
|
|
85
|
+
start_time = time.perf_counter() # Start time measure
|
|
86
86
|
output = func(*args, **kwargs) # Run function and save result into a variable
|
|
87
87
|
current, peak = tracemalloc.get_traced_memory() # Get memory stats
|
|
88
|
-
finish_time = perf_counter() # Get finished time
|
|
88
|
+
finish_time = time.perf_counter() # Get finished time
|
|
89
89
|
tracemalloc.stop() # End memory measure
|
|
90
|
-
|
|
91
|
-
# Print output
|
|
90
|
+
|
|
91
|
+
# Print output
|
|
92
92
|
print(
|
|
93
93
|
f"{'-' * 38}\n"
|
|
94
94
|
f"Function: {func.__name__}\n"
|
|
@@ -100,11 +100,12 @@ def measure_performance(func: Callable) -> Callable:
|
|
|
100
100
|
|
|
101
101
|
# Return
|
|
102
102
|
return output
|
|
103
|
-
|
|
103
|
+
|
|
104
104
|
return wrapper
|
|
105
105
|
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
@versionadded(version="3.2.0")
|
|
108
|
+
def function_debug(func: Callable) -> Callable: # type: ignore
|
|
108
109
|
"""
|
|
109
110
|
Print the function signature and return value
|
|
110
111
|
|
|
@@ -132,13 +133,14 @@ def function_debug(func: Callable) -> Callable:
|
|
|
132
133
|
Calling test(6, 8)
|
|
133
134
|
test() returned 14
|
|
134
135
|
"""
|
|
136
|
+
|
|
135
137
|
@wraps(func)
|
|
136
138
|
def wrapper(*args, **kwargs) -> Any:
|
|
137
139
|
# Get all parameters inputed
|
|
138
140
|
args_repr = [repr(a) for a in args]
|
|
139
141
|
kwargs_repr = [f"{k}={repr(v)}" for k, v in kwargs.items()]
|
|
140
142
|
signature = ", ".join(args_repr + kwargs_repr)
|
|
141
|
-
|
|
143
|
+
|
|
142
144
|
# Output
|
|
143
145
|
print(f"Calling {func.__name__}({signature})")
|
|
144
146
|
# logger.debug(f"Calling {func.__name__}({signature})")
|
|
@@ -146,10 +148,12 @@ def function_debug(func: Callable) -> Callable:
|
|
|
146
148
|
print(f"{func.__name__}() returned {repr(value)}")
|
|
147
149
|
# logger.debug(f"{func.__name__}() returned {repr(value)}")
|
|
148
150
|
return value
|
|
151
|
+
|
|
149
152
|
return wrapper
|
|
150
153
|
|
|
151
154
|
|
|
152
|
-
|
|
155
|
+
@versionadded(version="3.2.0")
|
|
156
|
+
def retry(retries: int = 3, delay: float = 1) -> Callable: # type: ignore
|
|
153
157
|
"""
|
|
154
158
|
Attempt to call a function, if it fails, try again with a specified delay.
|
|
155
159
|
|
|
@@ -191,11 +195,10 @@ def retry(retries: int = 3, delay: float = 1) -> Callable:
|
|
|
191
195
|
if retries < 1 or delay <= 0:
|
|
192
196
|
raise ValueError("retries must be >= 1, delay must be >= 0")
|
|
193
197
|
|
|
194
|
-
def decorator(func: Callable) -> Callable:
|
|
198
|
+
def decorator(func: Callable) -> Callable: # type: ignore
|
|
195
199
|
@wraps(func)
|
|
196
200
|
def wrapper(*args, **kwargs) -> Any:
|
|
197
201
|
for i in range(1, retries + 1):
|
|
198
|
-
|
|
199
202
|
try:
|
|
200
203
|
print(f"Running ({i}): {func.__name__}()")
|
|
201
204
|
return func(*args, **kwargs)
|
|
@@ -207,14 +210,16 @@ def retry(retries: int = 3, delay: float = 1) -> Callable:
|
|
|
207
210
|
break
|
|
208
211
|
else:
|
|
209
212
|
print(f"Error: {repr(e)} -> Retrying...")
|
|
210
|
-
sleep(
|
|
213
|
+
time.sleep(
|
|
214
|
+
delay
|
|
215
|
+
) # Add a delay before running the next iteration
|
|
211
216
|
|
|
212
217
|
return wrapper
|
|
213
218
|
|
|
214
219
|
return decorator
|
|
215
220
|
|
|
216
221
|
|
|
217
|
-
def _deprecated_warning(func: Callable):
|
|
222
|
+
def _deprecated_warning(func: Callable): # type: ignore
|
|
218
223
|
"""
|
|
219
224
|
Notice that the function is deprecated and should not be used
|
|
220
225
|
|
|
@@ -227,82 +232,14 @@ def _deprecated_warning(func: Callable):
|
|
|
227
232
|
-----
|
|
228
233
|
Use this as the decorator (``@deprecated_warning``)
|
|
229
234
|
"""
|
|
235
|
+
|
|
230
236
|
@wraps(func)
|
|
231
237
|
def wrapper(*args, **kwargs) -> Any:
|
|
232
238
|
print(f"[WARNING] {func.__name__}() is deprecated")
|
|
233
239
|
value = func(*args, **kwargs)
|
|
234
240
|
return value
|
|
235
|
-
return wrapper
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
@deprecated(reason="Implemented into absfuyu.util.performance.Checker()", version="3.2.0")
|
|
239
|
-
def var_check(variable: Any, full: bool = False): # del soon
|
|
240
|
-
"""
|
|
241
|
-
Check a variable [Deprecated]
|
|
242
241
|
|
|
243
|
-
|
|
244
|
-
----------
|
|
245
|
-
variable : Any
|
|
246
|
-
Variable that needed to check
|
|
247
|
-
|
|
248
|
-
full : bool
|
|
249
|
-
| ``True``: Shows full detail
|
|
250
|
-
| ``False``: Hides ``dir`` and ``docstring``
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
Example:
|
|
254
|
-
--------
|
|
255
|
-
>>> test = "test"
|
|
256
|
-
>>> var_check(test)
|
|
257
|
-
{'value': 'test', 'class': str, 'id': ...}
|
|
258
|
-
"""
|
|
259
|
-
|
|
260
|
-
# Check class
|
|
261
|
-
try:
|
|
262
|
-
clss = [variable.__name__, type(variable)]
|
|
263
|
-
except:
|
|
264
|
-
clss = type(variable)
|
|
265
|
-
|
|
266
|
-
output = dict()
|
|
267
|
-
try:
|
|
268
|
-
output = {
|
|
269
|
-
"value": variable,
|
|
270
|
-
"class": clss,
|
|
271
|
-
"id": id(variable),
|
|
272
|
-
}
|
|
273
|
-
except:
|
|
274
|
-
return None
|
|
275
|
-
|
|
276
|
-
# Docstring
|
|
277
|
-
try:
|
|
278
|
-
lc = [ # list of Python data types
|
|
279
|
-
str,
|
|
280
|
-
int, float, complex,
|
|
281
|
-
list, tuple, range,
|
|
282
|
-
dict,
|
|
283
|
-
set, frozenset,
|
|
284
|
-
bool,
|
|
285
|
-
bytes, bytearray, memoryview,
|
|
286
|
-
type(None),
|
|
287
|
-
]
|
|
288
|
-
if type(variable) in lc:
|
|
289
|
-
pass
|
|
290
|
-
else:
|
|
291
|
-
docs = variable.__doc__
|
|
292
|
-
if full:
|
|
293
|
-
output["docstring"] = docs
|
|
294
|
-
except:
|
|
295
|
-
pass
|
|
296
|
-
|
|
297
|
-
# Dir
|
|
298
|
-
try:
|
|
299
|
-
if full:
|
|
300
|
-
output["dir"] = ListNoDunder(variable.__dir__())
|
|
301
|
-
except:
|
|
302
|
-
pass
|
|
303
|
-
|
|
304
|
-
# Output
|
|
305
|
-
return output
|
|
242
|
+
return wrapper
|
|
306
243
|
|
|
307
244
|
|
|
308
245
|
# Class
|
|
@@ -323,11 +260,12 @@ class Checker:
|
|
|
323
260
|
>>> Checker(test).check()
|
|
324
261
|
{'name': None, 'value': 'test', 'class': <class 'str'>, 'id': ...}
|
|
325
262
|
"""
|
|
263
|
+
|
|
326
264
|
def __init__(self, variable: Any) -> None:
|
|
327
265
|
self.item_to_check = variable
|
|
328
266
|
|
|
329
267
|
def __str__(self) -> str:
|
|
330
|
-
return self.item_to_check.__str__()
|
|
268
|
+
return self.item_to_check.__str__() # type: ignore
|
|
331
269
|
|
|
332
270
|
def __repr__(self) -> str:
|
|
333
271
|
return f"{self.__class__.__name__}({self.item_to_check})"
|
|
@@ -337,7 +275,7 @@ class Checker:
|
|
|
337
275
|
"""``__name__`` of variable (if any)"""
|
|
338
276
|
try:
|
|
339
277
|
return self.item_to_check.__name__
|
|
340
|
-
except:
|
|
278
|
+
except Exception:
|
|
341
279
|
return None
|
|
342
280
|
|
|
343
281
|
@property
|
|
@@ -348,7 +286,7 @@ class Checker:
|
|
|
348
286
|
@property
|
|
349
287
|
def docstring(self) -> Union[str, None]:
|
|
350
288
|
"""``__doc__`` of variable (if any)"""
|
|
351
|
-
return self.item_to_check.__doc__
|
|
289
|
+
return self.item_to_check.__doc__ # type: ignore
|
|
352
290
|
|
|
353
291
|
@property
|
|
354
292
|
def class_(self) -> Any:
|
|
@@ -365,13 +303,13 @@ class Checker:
|
|
|
365
303
|
"""``dir()`` of variable"""
|
|
366
304
|
# return self.item_to_check.__dir__()
|
|
367
305
|
return ListNoDunder(self.item_to_check.__dir__())
|
|
368
|
-
|
|
306
|
+
|
|
369
307
|
@property
|
|
370
308
|
def source(self) -> Union[str, None]:
|
|
371
309
|
"""Source code of variable (if available)"""
|
|
372
310
|
try:
|
|
373
311
|
return getsource(self.item_to_check)
|
|
374
|
-
except:
|
|
312
|
+
except Exception:
|
|
375
313
|
return None
|
|
376
314
|
|
|
377
315
|
def check(self, full: bool = False) -> Dict[str, Any]:
|
|
@@ -406,4 +344,4 @@ class Checker:
|
|
|
406
344
|
# Run
|
|
407
345
|
###########################################################################
|
|
408
346
|
if __name__ == "__main__":
|
|
409
|
-
pass
|
|
347
|
+
pass
|
absfuyu/util/pkl.py
CHANGED
|
@@ -7,18 +7,15 @@ Version: 1.0.2
|
|
|
7
7
|
Last update: 24/11/2023 (dd/mm/yyyy)
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
|
-
|
|
11
10
|
# Module level
|
|
12
11
|
###########################################################################
|
|
13
|
-
__all__ = [
|
|
14
|
-
"Pickler"
|
|
15
|
-
]
|
|
12
|
+
__all__ = ["Pickler"]
|
|
16
13
|
|
|
17
14
|
|
|
18
15
|
# Library
|
|
19
16
|
###########################################################################
|
|
20
|
-
from pathlib import Path
|
|
21
17
|
import pickle
|
|
18
|
+
from pathlib import Path
|
|
22
19
|
from typing import Any
|
|
23
20
|
|
|
24
21
|
|
|
@@ -26,10 +23,13 @@ from typing import Any
|
|
|
26
23
|
###########################################################################
|
|
27
24
|
class Pickler:
|
|
28
25
|
"""Save and load pickle file"""
|
|
26
|
+
|
|
29
27
|
def __init__(self) -> None:
|
|
30
28
|
pass
|
|
29
|
+
|
|
31
30
|
def __str__(self) -> str:
|
|
32
31
|
return f"{self.__class__.__name__}()"
|
|
32
|
+
|
|
33
33
|
def __repr__(self) -> str:
|
|
34
34
|
return self.__str__()
|
|
35
35
|
|
|
@@ -37,7 +37,7 @@ class Pickler:
|
|
|
37
37
|
def save(location: Path, data: Any) -> None:
|
|
38
38
|
"""
|
|
39
39
|
Save to pickle format
|
|
40
|
-
|
|
40
|
+
|
|
41
41
|
:param location: Save location
|
|
42
42
|
:type location: Path
|
|
43
43
|
:param data: Data want to be saved
|
|
@@ -50,7 +50,7 @@ class Pickler:
|
|
|
50
50
|
def load(location: Path) -> Any:
|
|
51
51
|
"""
|
|
52
52
|
Load pickled file
|
|
53
|
-
|
|
53
|
+
|
|
54
54
|
:param location: Load location
|
|
55
55
|
:type location: Path
|
|
56
56
|
:returns: Loaded data
|
|
@@ -64,4 +64,4 @@ class Pickler:
|
|
|
64
64
|
# Run
|
|
65
65
|
###########################################################################
|
|
66
66
|
if __name__ == "__main__":
|
|
67
|
-
pass
|
|
67
|
+
pass
|
absfuyu/util/zipped.py
CHANGED
|
@@ -1,26 +1,23 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Absfuyu: Zipped
|
|
3
3
|
---------------
|
|
4
|
-
Zipping stuff
|
|
4
|
+
Zipping stuff (deprecated soon, most features already in absfuyu.util.path.Directory)
|
|
5
5
|
|
|
6
6
|
Version: 1.0.1
|
|
7
7
|
Date updated: 24/11/2023 (dd/mm/yyyy)
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
|
-
|
|
11
10
|
# Module level
|
|
12
11
|
###########################################################################
|
|
13
|
-
__all__ = [
|
|
14
|
-
"Zipper"
|
|
15
|
-
]
|
|
12
|
+
__all__ = ["Zipper"]
|
|
16
13
|
|
|
17
14
|
|
|
18
15
|
# Library
|
|
19
16
|
###########################################################################
|
|
20
|
-
from pathlib import Path
|
|
21
17
|
import shutil
|
|
22
|
-
from typing import Union
|
|
23
18
|
import zipfile
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from typing import Union
|
|
24
21
|
|
|
25
22
|
from absfuyu.logger import logger
|
|
26
23
|
|
|
@@ -28,11 +25,10 @@ from absfuyu.logger import logger
|
|
|
28
25
|
###########################################################################
|
|
29
26
|
class Zipper:
|
|
30
27
|
"""Zip file or folder"""
|
|
28
|
+
|
|
31
29
|
def __init__(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
name: Union[str, None] = None
|
|
35
|
-
) -> None:
|
|
30
|
+
self, path_to_zip: Union[str, Path], name: Union[str, None] = None
|
|
31
|
+
) -> None:
|
|
36
32
|
"""
|
|
37
33
|
path_to_zip: source location
|
|
38
34
|
name: zipped file name
|
|
@@ -43,11 +39,13 @@ class Zipper:
|
|
|
43
39
|
else:
|
|
44
40
|
self.name = name
|
|
45
41
|
self.destination = self.source_path.parent.joinpath(self.name)
|
|
42
|
+
|
|
46
43
|
def __str__(self) -> str:
|
|
47
44
|
return f"{self.__class__.__name__}({self.name})"
|
|
45
|
+
|
|
48
46
|
def __repr__(self) -> str:
|
|
49
47
|
return self.__str__()
|
|
50
|
-
|
|
48
|
+
|
|
51
49
|
def zip_stuff(self, delete_after_zip: bool = False) -> None:
|
|
52
50
|
"""
|
|
53
51
|
Zip file/folder
|
|
@@ -57,25 +55,25 @@ class Zipper:
|
|
|
57
55
|
"""
|
|
58
56
|
|
|
59
57
|
# Zip
|
|
60
|
-
logger.debug(
|
|
61
|
-
if self.source_path.is_dir():
|
|
58
|
+
logger.debug("Zipping...")
|
|
59
|
+
if self.source_path.is_dir(): # zip entire folder
|
|
62
60
|
try:
|
|
63
61
|
with zipfile.ZipFile(self.destination, "w", zipfile.ZIP_DEFLATED) as f:
|
|
64
62
|
for file in self.source_path.rglob("*"):
|
|
65
63
|
f.write(file, file.relative_to(self.source_path))
|
|
66
|
-
except:
|
|
64
|
+
except Exception:
|
|
67
65
|
logger.error("Zip failed!")
|
|
68
66
|
# shutil.make_archive(zip_file, format="zip", root_dir=zip_path) # Method 2
|
|
69
|
-
else:
|
|
67
|
+
else: # zip a file
|
|
70
68
|
# Implement later
|
|
71
69
|
pass
|
|
72
70
|
|
|
73
71
|
# Delete folder
|
|
74
72
|
if delete_after_zip:
|
|
75
73
|
try:
|
|
76
|
-
logger.debug(
|
|
74
|
+
logger.debug("Deleting unused folder...")
|
|
77
75
|
shutil.rmtree(self.source_path)
|
|
78
|
-
logger.debug(
|
|
76
|
+
logger.debug("Files deleted")
|
|
79
77
|
except OSError as e:
|
|
80
78
|
logger.error(f"Error: {e.filename} - {e.strerror}.")
|
|
81
79
|
|
|
@@ -83,4 +81,4 @@ class Zipper:
|
|
|
83
81
|
# Run
|
|
84
82
|
###########################################################################
|
|
85
83
|
if __name__ == "__main__":
|
|
86
|
-
logger.setLevel(10)
|
|
84
|
+
logger.setLevel(10)
|