absfuyu 4.2.0__py3-none-any.whl → 5.0.1__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 +4 -4
- absfuyu/__main__.py +13 -1
- absfuyu/cli/__init__.py +2 -2
- absfuyu/cli/color.py +9 -2
- absfuyu/cli/config_group.py +2 -2
- absfuyu/cli/do_group.py +2 -37
- absfuyu/cli/game_group.py +2 -2
- absfuyu/cli/tool_group.py +7 -7
- absfuyu/config/__init__.py +17 -34
- absfuyu/core/__init__.py +49 -0
- absfuyu/core/baseclass.py +299 -0
- absfuyu/core/baseclass2.py +165 -0
- absfuyu/core/decorator.py +67 -0
- absfuyu/core/docstring.py +166 -0
- absfuyu/core/dummy_cli.py +67 -0
- absfuyu/core/dummy_func.py +49 -0
- absfuyu/dxt/__init__.py +42 -0
- absfuyu/dxt/dictext.py +201 -0
- absfuyu/dxt/dxt_support.py +79 -0
- absfuyu/dxt/intext.py +586 -0
- absfuyu/dxt/listext.py +508 -0
- absfuyu/dxt/strext.py +530 -0
- absfuyu/extra/__init__.py +12 -0
- absfuyu/extra/beautiful.py +252 -0
- absfuyu/{extensions → extra}/data_analysis.py +51 -82
- absfuyu/fun/__init__.py +110 -135
- absfuyu/fun/tarot.py +11 -19
- absfuyu/game/__init__.py +8 -2
- absfuyu/game/game_stat.py +8 -2
- absfuyu/game/sudoku.py +9 -3
- absfuyu/game/tictactoe.py +14 -7
- absfuyu/game/wordle.py +16 -10
- absfuyu/general/__init__.py +8 -81
- absfuyu/general/content.py +24 -38
- absfuyu/general/human.py +108 -228
- absfuyu/general/shape.py +1334 -0
- absfuyu/logger.py +10 -15
- absfuyu/pkg_data/__init__.py +137 -100
- absfuyu/pkg_data/deprecated.py +133 -0
- absfuyu/sort.py +6 -130
- absfuyu/tools/__init__.py +2 -2
- absfuyu/tools/checksum.py +33 -22
- absfuyu/tools/converter.py +51 -48
- absfuyu/{general → tools}/generator.py +17 -42
- absfuyu/tools/keygen.py +25 -30
- absfuyu/tools/obfuscator.py +246 -112
- absfuyu/tools/passwordlib.py +100 -30
- absfuyu/tools/shutdownizer.py +68 -47
- absfuyu/tools/web.py +4 -11
- absfuyu/util/__init__.py +17 -17
- absfuyu/util/api.py +10 -15
- absfuyu/util/json_method.py +7 -24
- absfuyu/util/lunar.py +5 -11
- absfuyu/util/path.py +22 -27
- absfuyu/util/performance.py +43 -67
- absfuyu/util/shorten_number.py +65 -14
- absfuyu/util/zipped.py +11 -17
- absfuyu/version.py +59 -42
- {absfuyu-4.2.0.dist-info → absfuyu-5.0.1.dist-info}/METADATA +41 -14
- absfuyu-5.0.1.dist-info/RECORD +68 -0
- absfuyu/core.py +0 -57
- absfuyu/everything.py +0 -32
- absfuyu/extensions/__init__.py +0 -12
- absfuyu/extensions/beautiful.py +0 -188
- absfuyu/fun/WGS.py +0 -134
- absfuyu/general/data_extension.py +0 -1796
- absfuyu/tools/stats.py +0 -226
- absfuyu/util/pkl.py +0 -67
- absfuyu-4.2.0.dist-info/RECORD +0 -59
- {absfuyu-4.2.0.dist-info → absfuyu-5.0.1.dist-info}/WHEEL +0 -0
- {absfuyu-4.2.0.dist-info → absfuyu-5.0.1.dist-info}/entry_points.txt +0 -0
- {absfuyu-4.2.0.dist-info → absfuyu-5.0.1.dist-info}/licenses/LICENSE +0 -0
absfuyu/util/path.py
CHANGED
|
@@ -3,8 +3,8 @@ Absfuyu: Path
|
|
|
3
3
|
-------------
|
|
4
4
|
Path related
|
|
5
5
|
|
|
6
|
-
Version:
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 5.0.0
|
|
7
|
+
Date updated: 22/02/2025 (dd/mm/yyyy)
|
|
8
8
|
|
|
9
9
|
Feature:
|
|
10
10
|
--------
|
|
@@ -13,7 +13,7 @@ Feature:
|
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
15
|
# Module level
|
|
16
|
-
|
|
16
|
+
# ---------------------------------------------------------------------------
|
|
17
17
|
__all__ = [
|
|
18
18
|
# Main
|
|
19
19
|
"Directory",
|
|
@@ -25,7 +25,7 @@ __all__ = [
|
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
# Library
|
|
28
|
-
|
|
28
|
+
# ---------------------------------------------------------------------------
|
|
29
29
|
import os
|
|
30
30
|
import re
|
|
31
31
|
import shutil
|
|
@@ -34,14 +34,13 @@ from functools import partial
|
|
|
34
34
|
from pathlib import Path
|
|
35
35
|
from typing import Any, Literal, NamedTuple
|
|
36
36
|
|
|
37
|
-
from
|
|
38
|
-
|
|
39
|
-
from absfuyu.logger import LogLevel, logger
|
|
37
|
+
from absfuyu.core import versionadded
|
|
38
|
+
from absfuyu.logger import logger
|
|
40
39
|
|
|
41
40
|
|
|
42
41
|
# Support Class
|
|
43
|
-
|
|
44
|
-
@versionadded(
|
|
42
|
+
# ---------------------------------------------------------------------------
|
|
43
|
+
@versionadded("3.3.0")
|
|
45
44
|
class FileOrFolderWithModificationTime(NamedTuple):
|
|
46
45
|
"""
|
|
47
46
|
File or Folder with modification time
|
|
@@ -54,9 +53,11 @@ class FileOrFolderWithModificationTime(NamedTuple):
|
|
|
54
53
|
modification_time: datetime
|
|
55
54
|
|
|
56
55
|
|
|
57
|
-
@versionadded(
|
|
56
|
+
@versionadded("3.3.0")
|
|
58
57
|
class DirectoryInfo(NamedTuple):
|
|
59
|
-
"""
|
|
58
|
+
"""
|
|
59
|
+
Information of a directory
|
|
60
|
+
"""
|
|
60
61
|
|
|
61
62
|
files: int
|
|
62
63
|
folders: int
|
|
@@ -65,7 +66,7 @@ class DirectoryInfo(NamedTuple):
|
|
|
65
66
|
|
|
66
67
|
|
|
67
68
|
# Class - Directory | version 3.4.0: Remake Directory into modular class
|
|
68
|
-
|
|
69
|
+
# ---------------------------------------------------------------------------
|
|
69
70
|
class DirectoryBase:
|
|
70
71
|
def __init__(
|
|
71
72
|
self,
|
|
@@ -113,21 +114,21 @@ class DirectoryBase:
|
|
|
113
114
|
|
|
114
115
|
# Everything
|
|
115
116
|
@property
|
|
116
|
-
@versionadded(
|
|
117
|
+
@versionadded("3.3.0")
|
|
117
118
|
def everything(self) -> list[Path]:
|
|
118
119
|
"""
|
|
119
120
|
Every folders and files in this Directory
|
|
120
121
|
"""
|
|
121
122
|
return list(x for x in self.source_path.glob("**/*"))
|
|
122
123
|
|
|
123
|
-
@versionadded(
|
|
124
|
+
@versionadded("3.3.0")
|
|
124
125
|
def _every_folder(self) -> list[Path]:
|
|
125
126
|
"""
|
|
126
127
|
Every folders in this Directory
|
|
127
128
|
"""
|
|
128
129
|
return list(x for x in self.source_path.glob("**/*") if x.is_dir())
|
|
129
130
|
|
|
130
|
-
@versionadded(
|
|
131
|
+
@versionadded("3.3.0")
|
|
131
132
|
def _every_file(self) -> list[Path]:
|
|
132
133
|
"""
|
|
133
134
|
Every folders in this Directory
|
|
@@ -135,7 +136,7 @@ class DirectoryBase:
|
|
|
135
136
|
return list(x for x in self.source_path.glob("**/*") if x.is_file())
|
|
136
137
|
|
|
137
138
|
# Quick information
|
|
138
|
-
@versionadded(
|
|
139
|
+
@versionadded("3.3.0")
|
|
139
140
|
def quick_info(self) -> DirectoryInfo:
|
|
140
141
|
"""
|
|
141
142
|
Quick information about this Directory
|
|
@@ -396,7 +397,7 @@ class Directory(DirectoryBasicOperation, DirectoryTree):
|
|
|
396
397
|
]
|
|
397
398
|
|
|
398
399
|
@staticmethod
|
|
399
|
-
@versionadded(
|
|
400
|
+
@versionadded("3.3.0")
|
|
400
401
|
def _split_dir(list_of_path: list[Path]) -> list[list[str]]:
|
|
401
402
|
"""
|
|
402
403
|
Split pathname by ``os.sep``
|
|
@@ -450,9 +451,9 @@ class Directory(DirectoryBasicOperation, DirectoryTree):
|
|
|
450
451
|
Folder structure ready to print
|
|
451
452
|
"""
|
|
452
453
|
# Check for tab and sub-dir symbol
|
|
453
|
-
if
|
|
454
|
+
if tab_symbol is None:
|
|
454
455
|
tab_symbol = "\t"
|
|
455
|
-
if
|
|
456
|
+
if sub_dir_symbol is None:
|
|
456
457
|
sub_dir_symbol = "|-- "
|
|
457
458
|
|
|
458
459
|
temp: list[list[str]] = self._split_dir(list_of_path)
|
|
@@ -504,7 +505,7 @@ class Directory(DirectoryBasicOperation, DirectoryTree):
|
|
|
504
505
|
|
|
505
506
|
|
|
506
507
|
# Class - SaveFileAs
|
|
507
|
-
|
|
508
|
+
# ---------------------------------------------------------------------------
|
|
508
509
|
class SaveFileAs:
|
|
509
510
|
"""File as multiple file type"""
|
|
510
511
|
|
|
@@ -554,12 +555,6 @@ class SaveFileAs:
|
|
|
554
555
|
|
|
555
556
|
|
|
556
557
|
# Dev and Test new feature before get added to the main class
|
|
557
|
-
|
|
558
|
+
# ---------------------------------------------------------------------------
|
|
558
559
|
class _NewDirFeature(Directory):
|
|
559
560
|
pass
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
# Run
|
|
563
|
-
###########################################################################
|
|
564
|
-
if __name__ == "__main__":
|
|
565
|
-
logger.setLevel(LogLevel.DEBUG)
|
absfuyu/util/performance.py
CHANGED
|
@@ -3,8 +3,8 @@ Absfuyu: Performance
|
|
|
3
3
|
--------------------
|
|
4
4
|
Performance Check
|
|
5
5
|
|
|
6
|
-
Version:
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 5.0.0
|
|
7
|
+
Date updated: 22/02/2025 (dd/mm/yyyy)
|
|
8
8
|
|
|
9
9
|
Feature:
|
|
10
10
|
--------
|
|
@@ -16,7 +16,7 @@ Feature:
|
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
18
|
# Module level
|
|
19
|
-
|
|
19
|
+
# ---------------------------------------------------------------------------
|
|
20
20
|
__all__ = [
|
|
21
21
|
# Wrapper
|
|
22
22
|
"function_debug",
|
|
@@ -28,36 +28,39 @@ __all__ = [
|
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
# Library
|
|
31
|
-
|
|
31
|
+
# ---------------------------------------------------------------------------
|
|
32
32
|
import time
|
|
33
33
|
import tracemalloc
|
|
34
|
+
from collections.abc import Callable
|
|
34
35
|
from functools import wraps
|
|
35
36
|
from inspect import getsource
|
|
36
|
-
from typing import Any,
|
|
37
|
+
from typing import Any, ParamSpec, TypeVar
|
|
37
38
|
|
|
38
|
-
from
|
|
39
|
+
from absfuyu.core import versionadded, versionchanged
|
|
40
|
+
from absfuyu.dxt import ListNoDunder
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
# Type
|
|
43
|
+
# ---------------------------------------------------------------------------
|
|
44
|
+
P = ParamSpec("P") # Parameter type
|
|
45
|
+
R = TypeVar("R") # Return type
|
|
43
46
|
|
|
44
47
|
|
|
45
48
|
# Function
|
|
46
|
-
|
|
47
|
-
@versionchanged(
|
|
48
|
-
def measure_performance(
|
|
49
|
+
# ---------------------------------------------------------------------------
|
|
50
|
+
@versionchanged("3.2.0", reason="Updated functionality")
|
|
51
|
+
def measure_performance(f: Callable[P, R]) -> Callable[P, R]:
|
|
49
52
|
r"""
|
|
50
53
|
Measure performance of a function
|
|
51
54
|
|
|
52
55
|
Parameters
|
|
53
56
|
----------
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
f : Callable [P, R]
|
|
58
|
+
Function to measure
|
|
56
59
|
|
|
57
60
|
Returns
|
|
58
61
|
-------
|
|
59
62
|
Callable
|
|
60
|
-
A
|
|
63
|
+
A decorated function
|
|
61
64
|
|
|
62
65
|
|
|
63
66
|
Usage
|
|
@@ -76,14 +79,15 @@ def measure_performance(func: Callable) -> Callable: # type: ignore
|
|
|
76
79
|
Peak memory usage: 0.000000 MB
|
|
77
80
|
Time elapsed (seconds): 0.000002
|
|
78
81
|
--------------------------------------
|
|
82
|
+
|
|
79
83
|
"""
|
|
80
84
|
|
|
81
|
-
@wraps(
|
|
82
|
-
def wrapper(*args, **kwargs) ->
|
|
85
|
+
@wraps(f)
|
|
86
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
|
83
87
|
# Performance check
|
|
84
88
|
tracemalloc.start() # Start memory measure
|
|
85
89
|
start_time = time.perf_counter() # Start time measure
|
|
86
|
-
output =
|
|
90
|
+
output = f(*args, **kwargs) # Run function and save result into a variable
|
|
87
91
|
current, peak = tracemalloc.get_traced_memory() # Get memory stats
|
|
88
92
|
finish_time = time.perf_counter() # Get finished time
|
|
89
93
|
tracemalloc.stop() # End memory measure
|
|
@@ -91,7 +95,7 @@ def measure_performance(func: Callable) -> Callable: # type: ignore
|
|
|
91
95
|
# Print output
|
|
92
96
|
print(
|
|
93
97
|
f"{'-' * 38}\n"
|
|
94
|
-
f"Function: {
|
|
98
|
+
f"Function: {f.__name__}\n"
|
|
95
99
|
f"Memory usage:\t\t {current / 10**6:,.6f} MB\n"
|
|
96
100
|
f"Peak memory usage:\t {peak / 10**6:,.6f} MB\n"
|
|
97
101
|
f"Time elapsed (seconds):\t {finish_time - start_time:,.6f}\n"
|
|
@@ -104,20 +108,20 @@ def measure_performance(func: Callable) -> Callable: # type: ignore
|
|
|
104
108
|
return wrapper
|
|
105
109
|
|
|
106
110
|
|
|
107
|
-
@versionadded(
|
|
108
|
-
def function_debug(
|
|
111
|
+
@versionadded("3.2.0")
|
|
112
|
+
def function_debug(f: Callable[P, R]) -> Callable[P, R]:
|
|
109
113
|
"""
|
|
110
114
|
Print the function signature and return value
|
|
111
115
|
|
|
112
116
|
Parameters
|
|
113
117
|
----------
|
|
114
118
|
func : Callable
|
|
115
|
-
|
|
119
|
+
Function to debug
|
|
116
120
|
|
|
117
121
|
Returns
|
|
118
122
|
-------
|
|
119
123
|
Callable
|
|
120
|
-
A
|
|
124
|
+
A decorated function
|
|
121
125
|
|
|
122
126
|
|
|
123
127
|
Usage
|
|
@@ -134,26 +138,26 @@ def function_debug(func: Callable) -> Callable: # type: ignore
|
|
|
134
138
|
test() returned 14
|
|
135
139
|
"""
|
|
136
140
|
|
|
137
|
-
@wraps(
|
|
138
|
-
def wrapper(*args, **kwargs) ->
|
|
141
|
+
@wraps(f)
|
|
142
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
|
139
143
|
# Get all parameters inputed
|
|
140
144
|
args_repr = [repr(a) for a in args]
|
|
141
145
|
kwargs_repr = [f"{k}={repr(v)}" for k, v in kwargs.items()]
|
|
142
146
|
signature = ", ".join(args_repr + kwargs_repr)
|
|
143
147
|
|
|
144
148
|
# Output
|
|
145
|
-
print(f"Calling {
|
|
149
|
+
print(f"Calling {f.__name__}({signature})")
|
|
146
150
|
# logger.debug(f"Calling {func.__name__}({signature})")
|
|
147
|
-
value =
|
|
148
|
-
print(f"{
|
|
151
|
+
value = f(*args, **kwargs)
|
|
152
|
+
print(f"{f.__name__}() returned {repr(value)}")
|
|
149
153
|
# logger.debug(f"{func.__name__}() returned {repr(value)}")
|
|
150
154
|
return value
|
|
151
155
|
|
|
152
156
|
return wrapper
|
|
153
157
|
|
|
154
158
|
|
|
155
|
-
@versionadded(
|
|
156
|
-
def retry(retries: int
|
|
159
|
+
@versionadded("3.2.0")
|
|
160
|
+
def retry(retries: int, delay: float = 1):
|
|
157
161
|
"""
|
|
158
162
|
Attempt to call a function, if it fails, try again with a specified delay.
|
|
159
163
|
|
|
@@ -168,7 +172,7 @@ def retry(retries: int = 3, delay: float = 1) -> Callable: # type: ignore
|
|
|
168
172
|
Returns
|
|
169
173
|
-------
|
|
170
174
|
Callable
|
|
171
|
-
A
|
|
175
|
+
A decorated function
|
|
172
176
|
|
|
173
177
|
|
|
174
178
|
Usage
|
|
@@ -195,18 +199,18 @@ def retry(retries: int = 3, delay: float = 1) -> Callable: # type: ignore
|
|
|
195
199
|
if retries < 1 or delay <= 0:
|
|
196
200
|
raise ValueError("retries must be >= 1, delay must be >= 0")
|
|
197
201
|
|
|
198
|
-
def decorator(
|
|
199
|
-
@wraps(
|
|
200
|
-
def wrapper(*args, **kwargs)
|
|
202
|
+
def decorator(f: Callable[P, R]) -> Callable[P, R]:
|
|
203
|
+
@wraps(f)
|
|
204
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs):
|
|
201
205
|
for i in range(1, retries + 1):
|
|
202
206
|
try:
|
|
203
|
-
print(f"Running ({i}): {
|
|
204
|
-
return
|
|
207
|
+
print(f"Running ({i}): {f.__name__}()")
|
|
208
|
+
return f(*args, **kwargs)
|
|
205
209
|
except Exception as e:
|
|
206
210
|
# Break out of the loop if the max amount of retries is exceeded
|
|
207
211
|
if i == retries:
|
|
208
212
|
print(f"Error: {repr(e)}.")
|
|
209
|
-
print(f'"{
|
|
213
|
+
print(f'"{f.__name__}()" failed after {retries} retries.')
|
|
210
214
|
break
|
|
211
215
|
else:
|
|
212
216
|
print(f"Error: {repr(e)} -> Retrying...")
|
|
@@ -219,31 +223,9 @@ def retry(retries: int = 3, delay: float = 1) -> Callable: # type: ignore
|
|
|
219
223
|
return decorator
|
|
220
224
|
|
|
221
225
|
|
|
222
|
-
def _deprecated_warning(func: Callable): # type: ignore
|
|
223
|
-
"""
|
|
224
|
-
Notice that the function is deprecated and should not be used
|
|
225
|
-
|
|
226
|
-
Parameters
|
|
227
|
-
----------
|
|
228
|
-
func : Callable
|
|
229
|
-
A callable function
|
|
230
|
-
|
|
231
|
-
Usage
|
|
232
|
-
-----
|
|
233
|
-
Use this as the decorator (``@deprecated_warning``)
|
|
234
|
-
"""
|
|
235
|
-
|
|
236
|
-
@wraps(func)
|
|
237
|
-
def wrapper(*args, **kwargs) -> Any:
|
|
238
|
-
print(f"[WARNING] {func.__name__}() is deprecated")
|
|
239
|
-
value = func(*args, **kwargs)
|
|
240
|
-
return value
|
|
241
|
-
|
|
242
|
-
return wrapper
|
|
243
|
-
|
|
244
|
-
|
|
245
226
|
# Class
|
|
246
|
-
|
|
227
|
+
# ---------------------------------------------------------------------------
|
|
228
|
+
# TODO: Rewrite this with inspect
|
|
247
229
|
class Checker:
|
|
248
230
|
"""
|
|
249
231
|
Check a variable
|
|
@@ -339,9 +321,3 @@ class Checker:
|
|
|
339
321
|
out["docs"] = self.docstring
|
|
340
322
|
out["source"] = self.source
|
|
341
323
|
return out
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
# Run
|
|
345
|
-
###########################################################################
|
|
346
|
-
if __name__ == "__main__":
|
|
347
|
-
pass
|
absfuyu/util/shorten_number.py
CHANGED
|
@@ -1,31 +1,47 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Absfuyu: Shorten number
|
|
3
|
-
|
|
3
|
+
-----------------------
|
|
4
4
|
Short number base on suffixes
|
|
5
5
|
|
|
6
|
-
Version:
|
|
7
|
-
|
|
6
|
+
Version: 5.0.0
|
|
7
|
+
Date updated: 24/02/2025 (dd/mm/yyyy)
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
# Module level
|
|
11
|
-
|
|
12
|
-
__all__ = [
|
|
11
|
+
# ---------------------------------------------------------------------------
|
|
12
|
+
__all__ = [
|
|
13
|
+
"UnitSuffixFactory",
|
|
14
|
+
"CommonUnitSuffixesFactory",
|
|
15
|
+
"Decimal",
|
|
16
|
+
"shorten_number",
|
|
17
|
+
]
|
|
13
18
|
|
|
14
19
|
|
|
15
20
|
# Library
|
|
16
|
-
|
|
21
|
+
# ---------------------------------------------------------------------------
|
|
22
|
+
from collections.abc import Callable
|
|
17
23
|
from dataclasses import dataclass, field
|
|
18
|
-
from
|
|
24
|
+
from functools import wraps
|
|
25
|
+
from typing import Annotated, NamedTuple, ParamSpec, Self, TypeVar
|
|
26
|
+
|
|
27
|
+
from absfuyu.core import versionadded
|
|
28
|
+
|
|
29
|
+
# Type
|
|
30
|
+
# ---------------------------------------------------------------------------
|
|
31
|
+
P = ParamSpec("P") # Parameter type
|
|
32
|
+
N = TypeVar("N", int, float) # Number type
|
|
19
33
|
|
|
20
34
|
|
|
21
35
|
# Class
|
|
22
|
-
|
|
36
|
+
# ---------------------------------------------------------------------------
|
|
37
|
+
@versionadded("4.1.0")
|
|
23
38
|
class UnitSuffixFactory(NamedTuple):
|
|
24
39
|
base: int
|
|
25
40
|
short_name: list[str]
|
|
26
41
|
full_name: list[str]
|
|
27
42
|
|
|
28
43
|
|
|
44
|
+
@versionadded("4.1.0")
|
|
29
45
|
class CommonUnitSuffixesFactory:
|
|
30
46
|
NUMBER = UnitSuffixFactory(
|
|
31
47
|
1000,
|
|
@@ -135,6 +151,7 @@ class CommonUnitSuffixesFactory:
|
|
|
135
151
|
|
|
136
152
|
|
|
137
153
|
@dataclass
|
|
154
|
+
@versionadded("4.1.0")
|
|
138
155
|
class Decimal:
|
|
139
156
|
"""
|
|
140
157
|
Shorten large number
|
|
@@ -160,7 +177,7 @@ class Decimal:
|
|
|
160
177
|
self.value, self.suffix = self._convert_decimal()
|
|
161
178
|
|
|
162
179
|
def __str__(self) -> str:
|
|
163
|
-
return self.to_text()
|
|
180
|
+
return self.to_text().strip()
|
|
164
181
|
|
|
165
182
|
@classmethod
|
|
166
183
|
def number(cls, value: int | float, suffix_full_name: bool = False) -> Self:
|
|
@@ -186,7 +203,7 @@ class Decimal:
|
|
|
186
203
|
return f"{value:.2e}"
|
|
187
204
|
|
|
188
205
|
def _get_factory(self) -> None:
|
|
189
|
-
if self.factory:
|
|
206
|
+
if self.factory is not None:
|
|
190
207
|
self.base = self.factory.base
|
|
191
208
|
self.suffixes = (
|
|
192
209
|
self.factory.full_name
|
|
@@ -222,7 +239,41 @@ class Decimal:
|
|
|
222
239
|
return f"{formatted_value}{separator}{self.suffix}"
|
|
223
240
|
|
|
224
241
|
|
|
225
|
-
#
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
242
|
+
# Decorator
|
|
243
|
+
# ---------------------------------------------------------------------------
|
|
244
|
+
@versionadded("5.0.0")
|
|
245
|
+
def shorten_number(f: Callable[P, N]) -> Callable[P, Decimal]:
|
|
246
|
+
"""
|
|
247
|
+
Shorten the number value by name
|
|
248
|
+
|
|
249
|
+
Parameters
|
|
250
|
+
----------
|
|
251
|
+
f : Callable[P, N]
|
|
252
|
+
Function that return ``int`` or ``float``
|
|
253
|
+
|
|
254
|
+
Returns
|
|
255
|
+
-------
|
|
256
|
+
Callable[P, Decimal]
|
|
257
|
+
Function that return ``Decimal``
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
Usage
|
|
261
|
+
-----
|
|
262
|
+
Use this as a decorator (``@shorten_number``)
|
|
263
|
+
|
|
264
|
+
Example:
|
|
265
|
+
--------
|
|
266
|
+
>>> import random
|
|
267
|
+
>>> @shorten_number
|
|
268
|
+
>>> def big_num() -> int:
|
|
269
|
+
... random.randint(100000000, 10000000000)
|
|
270
|
+
>>> big_num()
|
|
271
|
+
4.20 B
|
|
272
|
+
"""
|
|
273
|
+
|
|
274
|
+
@wraps(f)
|
|
275
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> Decimal:
|
|
276
|
+
value = Decimal.number(f(*args, **kwargs))
|
|
277
|
+
return value
|
|
278
|
+
|
|
279
|
+
return wrapper
|
absfuyu/util/zipped.py
CHANGED
|
@@ -3,26 +3,29 @@ Absfuyu: Zipped
|
|
|
3
3
|
---------------
|
|
4
4
|
Zipping stuff (deprecated soon, most features already in absfuyu.util.path.Directory)
|
|
5
5
|
|
|
6
|
-
Version:
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 5.0.0
|
|
7
|
+
Date updated: 22/02/2025 (dd/mm/yyyy)
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
# Module level
|
|
11
|
-
|
|
12
|
-
__all__ = [
|
|
11
|
+
# ---------------------------------------------------------------------------
|
|
12
|
+
__all__ = [
|
|
13
|
+
"Zipper",
|
|
14
|
+
]
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
# Library
|
|
16
|
-
|
|
18
|
+
# ---------------------------------------------------------------------------
|
|
17
19
|
import shutil
|
|
18
20
|
import zipfile
|
|
19
21
|
from pathlib import Path
|
|
20
22
|
|
|
23
|
+
from absfuyu.core import BaseClass, versionadded
|
|
21
24
|
from absfuyu.logger import logger
|
|
22
25
|
|
|
23
26
|
|
|
24
|
-
|
|
25
|
-
class Zipper:
|
|
27
|
+
# ---------------------------------------------------------------------------
|
|
28
|
+
class Zipper(BaseClass):
|
|
26
29
|
"""Zip file or folder"""
|
|
27
30
|
|
|
28
31
|
def __init__(self, path_to_zip: str | Path, name: str | None = None) -> None:
|
|
@@ -40,9 +43,6 @@ class Zipper:
|
|
|
40
43
|
def __str__(self) -> str:
|
|
41
44
|
return f"{self.__class__.__name__}({self.name})"
|
|
42
45
|
|
|
43
|
-
def __repr__(self) -> str:
|
|
44
|
-
return self.__str__()
|
|
45
|
-
|
|
46
46
|
def zip_stuff(self, delete_after_zip: bool = False) -> None:
|
|
47
47
|
"""
|
|
48
48
|
Zip file/folder
|
|
@@ -74,7 +74,7 @@ class Zipper:
|
|
|
74
74
|
except OSError as e:
|
|
75
75
|
logger.error(f"Error: {e.filename} - {e.strerror}.")
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
@versionadded("4.0.0")
|
|
78
78
|
def unzip(self):
|
|
79
79
|
"""
|
|
80
80
|
Unzip every archive files in directory
|
|
@@ -88,9 +88,3 @@ class Zipper:
|
|
|
88
88
|
shutil.unpack_archive(temp, temp.parent.joinpath(temp.stem))
|
|
89
89
|
else:
|
|
90
90
|
shutil.unpack_archive(x, x.parent.joinpath(x.stem))
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
# Run
|
|
94
|
-
###########################################################################
|
|
95
|
-
if __name__ == "__main__":
|
|
96
|
-
logger.setLevel(10)
|