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/util/performance.py
CHANGED
|
@@ -3,48 +3,66 @@ Absfuyu: Performance
|
|
|
3
3
|
--------------------
|
|
4
4
|
Performance Check
|
|
5
5
|
|
|
6
|
-
Version: 1.
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 1.2.3
|
|
7
|
+
Date updated: 05/04/2024 (dd/mm/yyyy)
|
|
8
8
|
|
|
9
9
|
Feature:
|
|
10
10
|
--------
|
|
11
11
|
- measure_performance
|
|
12
|
+
- function_debug
|
|
13
|
+
- retry
|
|
12
14
|
- var_check
|
|
13
|
-
-
|
|
15
|
+
- Checker
|
|
14
16
|
"""
|
|
15
17
|
|
|
16
|
-
|
|
17
18
|
# Module level
|
|
18
19
|
###########################################################################
|
|
19
20
|
__all__ = [
|
|
20
21
|
# Wrapper
|
|
22
|
+
"function_debug",
|
|
21
23
|
"measure_performance",
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"
|
|
24
|
+
"retry",
|
|
25
|
+
# Class
|
|
26
|
+
"Checker",
|
|
25
27
|
]
|
|
26
28
|
|
|
27
29
|
|
|
28
30
|
# Library
|
|
29
31
|
###########################################################################
|
|
30
|
-
|
|
32
|
+
import time
|
|
33
|
+
import tracemalloc
|
|
34
|
+
from functools import wraps
|
|
31
35
|
from inspect import getsource
|
|
32
|
-
from
|
|
33
|
-
|
|
34
|
-
from
|
|
36
|
+
from typing import Any, Callable, Dict, List, Union
|
|
37
|
+
|
|
38
|
+
from deprecated.sphinx import versionadded, versionchanged
|
|
35
39
|
|
|
36
40
|
from absfuyu.general.data_extension import ListNoDunder
|
|
37
41
|
|
|
42
|
+
# from absfuyu.logger import logger, LogLevel
|
|
43
|
+
|
|
38
44
|
|
|
39
45
|
# Function
|
|
40
46
|
###########################################################################
|
|
41
|
-
|
|
47
|
+
@versionchanged(version="3.2.0", reason="Clean up code")
|
|
48
|
+
def measure_performance(func: Callable) -> Callable: # type: ignore
|
|
42
49
|
r"""
|
|
43
50
|
Measure performance of a function
|
|
44
51
|
|
|
52
|
+
Parameters
|
|
53
|
+
----------
|
|
54
|
+
func : Callable
|
|
55
|
+
A callable function
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
Callable
|
|
60
|
+
A callable function
|
|
61
|
+
|
|
62
|
+
|
|
45
63
|
Usage
|
|
46
64
|
-----
|
|
47
|
-
Use this as
|
|
65
|
+
Use this as a decorator (``@measure_performance``)
|
|
48
66
|
|
|
49
67
|
Example:
|
|
50
68
|
--------
|
|
@@ -52,199 +70,263 @@ def measure_performance(func):
|
|
|
52
70
|
>>> def test():
|
|
53
71
|
... return 1 + 1
|
|
54
72
|
>>> test()
|
|
55
|
-
|
|
73
|
+
--------------------------------------
|
|
56
74
|
Function: test
|
|
57
75
|
Memory usage: 0.000000 MB
|
|
58
76
|
Peak memory usage: 0.000000 MB
|
|
59
77
|
Time elapsed (seconds): 0.000002
|
|
60
|
-
|
|
78
|
+
--------------------------------------
|
|
61
79
|
"""
|
|
62
|
-
|
|
63
|
-
@
|
|
64
|
-
def wrapper(*args, **kwargs):
|
|
65
|
-
#
|
|
66
|
-
|
|
67
|
-
# Start time measure
|
|
68
|
-
|
|
69
|
-
#
|
|
70
|
-
|
|
71
|
-
#
|
|
72
|
-
|
|
73
|
-
# Get finished time
|
|
74
|
-
finish_time = __perf_counter()
|
|
75
|
-
# End memory measure
|
|
76
|
-
__tracemalloc.stop()
|
|
77
|
-
|
|
80
|
+
|
|
81
|
+
@wraps(func)
|
|
82
|
+
def wrapper(*args, **kwargs) -> Any:
|
|
83
|
+
# Performance check
|
|
84
|
+
tracemalloc.start() # Start memory measure
|
|
85
|
+
start_time = time.perf_counter() # Start time measure
|
|
86
|
+
output = func(*args, **kwargs) # Run function and save result into a variable
|
|
87
|
+
current, peak = tracemalloc.get_traced_memory() # Get memory stats
|
|
88
|
+
finish_time = time.perf_counter() # Get finished time
|
|
89
|
+
tracemalloc.stop() # End memory measure
|
|
90
|
+
|
|
78
91
|
# Print output
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
"Time elapsed (seconds)": finish_time - start_time,
|
|
92
|
-
}
|
|
93
|
-
out: bool = False
|
|
94
|
-
|
|
95
|
-
print(f"""
|
|
96
|
-
{"-"*40}
|
|
97
|
-
Function: {stat["Function"]}
|
|
98
|
-
Memory usage:\t\t {stat["Memory usage"]:,.6f} MB
|
|
99
|
-
Peak memory usage:\t {stat["Peak memory usage"]:,.6f} MB
|
|
100
|
-
Time elapsed (seconds):\t {stat["Time elapsed (seconds)"]:,.6f}
|
|
101
|
-
{"-"*40}
|
|
102
|
-
""")
|
|
103
|
-
|
|
104
|
-
if out:
|
|
105
|
-
return stat
|
|
106
|
-
|
|
92
|
+
print(
|
|
93
|
+
f"{'-' * 38}\n"
|
|
94
|
+
f"Function: {func.__name__}\n"
|
|
95
|
+
f"Memory usage:\t\t {current / 10**6:,.6f} MB\n"
|
|
96
|
+
f"Peak memory usage:\t {peak / 10**6:,.6f} MB\n"
|
|
97
|
+
f"Time elapsed (seconds):\t {finish_time - start_time:,.6f}\n"
|
|
98
|
+
f"{'-' * 38}"
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
# Return
|
|
102
|
+
return output
|
|
103
|
+
|
|
107
104
|
return wrapper
|
|
108
105
|
|
|
109
106
|
|
|
110
|
-
|
|
107
|
+
@versionadded(version="3.2.0")
|
|
108
|
+
def function_debug(func: Callable) -> Callable: # type: ignore
|
|
111
109
|
"""
|
|
112
|
-
|
|
110
|
+
Print the function signature and return value
|
|
113
111
|
|
|
114
112
|
Parameters
|
|
115
113
|
----------
|
|
116
|
-
|
|
117
|
-
|
|
114
|
+
func : Callable
|
|
115
|
+
A callable function
|
|
118
116
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
117
|
+
Returns
|
|
118
|
+
-------
|
|
119
|
+
Callable
|
|
120
|
+
A callable function
|
|
122
121
|
|
|
123
122
|
|
|
123
|
+
Usage
|
|
124
|
+
-----
|
|
125
|
+
Use this as a decorator (``@function_debug``)
|
|
126
|
+
|
|
124
127
|
Example:
|
|
125
128
|
--------
|
|
126
|
-
>>>
|
|
127
|
-
>>>
|
|
128
|
-
|
|
129
|
+
>>> @function_debug
|
|
130
|
+
>>> def test(a: int, b: int):
|
|
131
|
+
... return a + b
|
|
132
|
+
>>> test(6, 8)
|
|
133
|
+
Calling test(6, 8)
|
|
134
|
+
test() returned 14
|
|
129
135
|
"""
|
|
130
|
-
|
|
131
|
-
# Check class
|
|
132
|
-
try:
|
|
133
|
-
clss = [variable.__name__, type(variable)]
|
|
134
|
-
except:
|
|
135
|
-
clss = type(variable)
|
|
136
|
-
|
|
137
|
-
output = dict()
|
|
138
|
-
try:
|
|
139
|
-
output = {
|
|
140
|
-
"value": variable,
|
|
141
|
-
"class": clss,
|
|
142
|
-
"id": id(variable),
|
|
143
|
-
}
|
|
144
|
-
except:
|
|
145
|
-
return None
|
|
146
|
-
|
|
147
|
-
# Docstring
|
|
148
|
-
try:
|
|
149
|
-
lc = [ # list of Python data types
|
|
150
|
-
str,
|
|
151
|
-
int, float, complex,
|
|
152
|
-
list, tuple, range,
|
|
153
|
-
dict,
|
|
154
|
-
set, frozenset,
|
|
155
|
-
bool,
|
|
156
|
-
bytes, bytearray, memoryview,
|
|
157
|
-
type(None),
|
|
158
|
-
]
|
|
159
|
-
if type(variable) in lc:
|
|
160
|
-
pass
|
|
161
|
-
else:
|
|
162
|
-
docs = variable.__doc__
|
|
163
|
-
if full:
|
|
164
|
-
output["docstring"] = docs
|
|
165
|
-
except:
|
|
166
|
-
pass
|
|
167
|
-
|
|
168
|
-
# Dir
|
|
169
|
-
try:
|
|
170
|
-
if full:
|
|
171
|
-
output["dir"] = ListNoDunder(variable.__dir__())
|
|
172
|
-
except:
|
|
173
|
-
pass
|
|
174
136
|
|
|
175
|
-
|
|
176
|
-
|
|
137
|
+
@wraps(func)
|
|
138
|
+
def wrapper(*args, **kwargs) -> Any:
|
|
139
|
+
# Get all parameters inputed
|
|
140
|
+
args_repr = [repr(a) for a in args]
|
|
141
|
+
kwargs_repr = [f"{k}={repr(v)}" for k, v in kwargs.items()]
|
|
142
|
+
signature = ", ".join(args_repr + kwargs_repr)
|
|
143
|
+
|
|
144
|
+
# Output
|
|
145
|
+
print(f"Calling {func.__name__}({signature})")
|
|
146
|
+
# logger.debug(f"Calling {func.__name__}({signature})")
|
|
147
|
+
value = func(*args, **kwargs)
|
|
148
|
+
print(f"{func.__name__}() returned {repr(value)}")
|
|
149
|
+
# logger.debug(f"{func.__name__}() returned {repr(value)}")
|
|
150
|
+
return value
|
|
151
|
+
|
|
152
|
+
return wrapper
|
|
177
153
|
|
|
178
154
|
|
|
179
|
-
|
|
155
|
+
@versionadded(version="3.2.0")
|
|
156
|
+
def retry(retries: int = 3, delay: float = 1) -> Callable: # type: ignore
|
|
180
157
|
"""
|
|
181
|
-
|
|
158
|
+
Attempt to call a function, if it fails, try again with a specified delay.
|
|
182
159
|
|
|
183
160
|
Parameters
|
|
184
161
|
----------
|
|
185
|
-
|
|
186
|
-
|
|
162
|
+
retries : int
|
|
163
|
+
The max amount of retries you want for the function call
|
|
164
|
+
|
|
165
|
+
delay : int
|
|
166
|
+
The delay (in seconds) between each function retry
|
|
187
167
|
|
|
188
168
|
Returns
|
|
189
169
|
-------
|
|
190
|
-
|
|
191
|
-
|
|
170
|
+
Callable
|
|
171
|
+
A callable function
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
Usage
|
|
175
|
+
-----
|
|
176
|
+
Use this as a decorator (``@retry``)
|
|
177
|
+
|
|
178
|
+
Example:
|
|
179
|
+
--------
|
|
180
|
+
>>> @retry(retries=3, delay=1)
|
|
181
|
+
>>> def test() -> None:
|
|
182
|
+
... time.sleep(1)
|
|
183
|
+
... raise Exception("Function error")
|
|
184
|
+
>>> test()
|
|
185
|
+
Running (1): test()
|
|
186
|
+
Error: Exception('Function error') -> Retrying...
|
|
187
|
+
Running (2): test()
|
|
188
|
+
Error: Exception('Function error') -> Retrying...
|
|
189
|
+
Running (3): test()
|
|
190
|
+
Error: Exception('Function error').
|
|
191
|
+
"test()" failed after 3 retries.
|
|
192
|
+
"""
|
|
193
|
+
|
|
194
|
+
# Condition
|
|
195
|
+
if retries < 1 or delay <= 0:
|
|
196
|
+
raise ValueError("retries must be >= 1, delay must be >= 0")
|
|
197
|
+
|
|
198
|
+
def decorator(func: Callable) -> Callable: # type: ignore
|
|
199
|
+
@wraps(func)
|
|
200
|
+
def wrapper(*args, **kwargs) -> Any:
|
|
201
|
+
for i in range(1, retries + 1):
|
|
202
|
+
try:
|
|
203
|
+
print(f"Running ({i}): {func.__name__}()")
|
|
204
|
+
return func(*args, **kwargs)
|
|
205
|
+
except Exception as e:
|
|
206
|
+
# Break out of the loop if the max amount of retries is exceeded
|
|
207
|
+
if i == retries:
|
|
208
|
+
print(f"Error: {repr(e)}.")
|
|
209
|
+
print(f'"{func.__name__}()" failed after {retries} retries.')
|
|
210
|
+
break
|
|
211
|
+
else:
|
|
212
|
+
print(f"Error: {repr(e)} -> Retrying...")
|
|
213
|
+
time.sleep(
|
|
214
|
+
delay
|
|
215
|
+
) # Add a delay before running the next iteration
|
|
216
|
+
|
|
217
|
+
return wrapper
|
|
218
|
+
|
|
219
|
+
return decorator
|
|
220
|
+
|
|
221
|
+
|
|
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``)
|
|
192
234
|
"""
|
|
193
|
-
|
|
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
|
|
194
243
|
|
|
195
244
|
|
|
196
245
|
# Class
|
|
197
246
|
###########################################################################
|
|
198
247
|
class Checker:
|
|
199
|
-
"""
|
|
200
|
-
|
|
201
|
-
|
|
248
|
+
"""
|
|
249
|
+
Check a variable
|
|
250
|
+
|
|
251
|
+
Parameters
|
|
252
|
+
----------
|
|
253
|
+
variable : Any
|
|
254
|
+
Variable that needed to check
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
Example:
|
|
258
|
+
--------
|
|
259
|
+
>>> test = "test"
|
|
260
|
+
>>> Checker(test).check()
|
|
261
|
+
{'name': None, 'value': 'test', 'class': <class 'str'>, 'id': ...}
|
|
262
|
+
"""
|
|
263
|
+
|
|
264
|
+
def __init__(self, variable: Any) -> None:
|
|
265
|
+
self.item_to_check = variable
|
|
266
|
+
|
|
202
267
|
def __str__(self) -> str:
|
|
203
|
-
return self.item_to_check.__str__()
|
|
268
|
+
return self.item_to_check.__str__() # type: ignore
|
|
269
|
+
|
|
204
270
|
def __repr__(self) -> str:
|
|
205
271
|
return f"{self.__class__.__name__}({self.item_to_check})"
|
|
206
272
|
|
|
207
273
|
@property
|
|
208
274
|
def name(self) -> Union[Any, None]:
|
|
275
|
+
"""``__name__`` of variable (if any)"""
|
|
209
276
|
try:
|
|
210
277
|
return self.item_to_check.__name__
|
|
211
|
-
except:
|
|
278
|
+
except Exception:
|
|
212
279
|
return None
|
|
213
280
|
|
|
214
281
|
@property
|
|
215
282
|
def value(self) -> Any:
|
|
283
|
+
"""Value of the variable"""
|
|
216
284
|
return self.item_to_check
|
|
217
285
|
|
|
218
286
|
@property
|
|
219
287
|
def docstring(self) -> Union[str, None]:
|
|
220
|
-
"""
|
|
221
|
-
return self.item_to_check.__doc__
|
|
288
|
+
"""``__doc__`` of variable (if any)"""
|
|
289
|
+
return self.item_to_check.__doc__ # type: ignore
|
|
222
290
|
|
|
223
291
|
@property
|
|
224
292
|
def class_(self) -> Any:
|
|
293
|
+
"""``class()`` of variable"""
|
|
225
294
|
return type(self.item_to_check)
|
|
226
295
|
|
|
227
296
|
@property
|
|
228
297
|
def id_(self) -> int:
|
|
298
|
+
"""``id()`` of variable"""
|
|
229
299
|
return id(self.item_to_check)
|
|
230
300
|
|
|
231
301
|
@property
|
|
232
302
|
def dir_(self) -> List[str]:
|
|
233
|
-
"""
|
|
303
|
+
"""``dir()`` of variable"""
|
|
234
304
|
# return self.item_to_check.__dir__()
|
|
235
305
|
return ListNoDunder(self.item_to_check.__dir__())
|
|
236
|
-
|
|
306
|
+
|
|
237
307
|
@property
|
|
238
308
|
def source(self) -> Union[str, None]:
|
|
239
|
-
"""
|
|
309
|
+
"""Source code of variable (if available)"""
|
|
240
310
|
try:
|
|
241
311
|
return getsource(self.item_to_check)
|
|
242
|
-
except:
|
|
312
|
+
except Exception:
|
|
243
313
|
return None
|
|
244
314
|
|
|
245
|
-
def check(self, full: bool = False):
|
|
315
|
+
def check(self, full: bool = False) -> Dict[str, Any]:
|
|
246
316
|
"""
|
|
247
|
-
Check
|
|
317
|
+
Check the variable
|
|
318
|
+
|
|
319
|
+
Parameters
|
|
320
|
+
----------
|
|
321
|
+
full : bool
|
|
322
|
+
| ``True``: Shows full detail
|
|
323
|
+
| ``False``: Hides ``dir``, ``docstring`` and source code
|
|
324
|
+
| Default: ``False``
|
|
325
|
+
|
|
326
|
+
Returns
|
|
327
|
+
-------
|
|
328
|
+
dict[str, Any]
|
|
329
|
+
Check result
|
|
248
330
|
"""
|
|
249
331
|
out = {
|
|
250
332
|
"name": self.name,
|
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)
|