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.

Files changed (61) hide show
  1. absfuyu/__init__.py +3 -10
  2. absfuyu/__main__.py +5 -250
  3. absfuyu/cli/__init__.py +51 -0
  4. absfuyu/cli/color.py +24 -0
  5. absfuyu/cli/config_group.py +56 -0
  6. absfuyu/cli/do_group.py +76 -0
  7. absfuyu/cli/game_group.py +109 -0
  8. absfuyu/config/__init__.py +117 -100
  9. absfuyu/config/config.json +0 -7
  10. absfuyu/core.py +5 -66
  11. absfuyu/everything.py +7 -9
  12. absfuyu/extensions/beautiful.py +30 -23
  13. absfuyu/extensions/dev/__init__.py +11 -8
  14. absfuyu/extensions/dev/password_hash.py +4 -2
  15. absfuyu/extensions/dev/passwordlib.py +7 -5
  16. absfuyu/extensions/dev/project_starter.py +4 -2
  17. absfuyu/extensions/dev/shutdownizer.py +148 -0
  18. absfuyu/extensions/extra/__init__.py +1 -2
  19. absfuyu/extensions/extra/data_analysis.py +182 -107
  20. absfuyu/fun/WGS.py +50 -26
  21. absfuyu/fun/__init__.py +6 -7
  22. absfuyu/fun/tarot.py +1 -1
  23. absfuyu/game/__init__.py +75 -81
  24. absfuyu/game/game_stat.py +36 -0
  25. absfuyu/game/sudoku.py +41 -48
  26. absfuyu/game/tictactoe.py +303 -548
  27. absfuyu/game/wordle.py +56 -47
  28. absfuyu/general/__init__.py +17 -7
  29. absfuyu/general/content.py +16 -15
  30. absfuyu/general/data_extension.py +282 -90
  31. absfuyu/general/generator.py +67 -67
  32. absfuyu/general/human.py +74 -78
  33. absfuyu/logger.py +94 -68
  34. absfuyu/pkg_data/__init__.py +29 -25
  35. absfuyu/py.typed +0 -0
  36. absfuyu/sort.py +61 -47
  37. absfuyu/tools/__init__.py +0 -1
  38. absfuyu/tools/converter.py +80 -62
  39. absfuyu/tools/keygen.py +62 -67
  40. absfuyu/tools/obfuscator.py +57 -53
  41. absfuyu/tools/stats.py +24 -24
  42. absfuyu/tools/web.py +10 -9
  43. absfuyu/util/__init__.py +71 -33
  44. absfuyu/util/api.py +53 -43
  45. absfuyu/util/json_method.py +25 -27
  46. absfuyu/util/lunar.py +20 -24
  47. absfuyu/util/path.py +362 -241
  48. absfuyu/util/performance.py +217 -135
  49. absfuyu/util/pkl.py +8 -8
  50. absfuyu/util/zipped.py +17 -19
  51. absfuyu/version.py +160 -147
  52. absfuyu-3.3.3.dist-info/METADATA +124 -0
  53. absfuyu-3.3.3.dist-info/RECORD +59 -0
  54. {absfuyu-3.1.1.dist-info → absfuyu-3.3.3.dist-info}/WHEEL +1 -2
  55. {absfuyu-3.1.1.dist-info → absfuyu-3.3.3.dist-info}/entry_points.txt +1 -0
  56. {absfuyu-3.1.1.dist-info → absfuyu-3.3.3.dist-info/licenses}/LICENSE +1 -1
  57. absfuyu/extensions/dev/pkglib.py +0 -98
  58. absfuyu/game/tictactoe2.py +0 -318
  59. absfuyu-3.1.1.dist-info/METADATA +0 -215
  60. absfuyu-3.1.1.dist-info/RECORD +0 -55
  61. absfuyu-3.1.1.dist-info/top_level.txt +0 -1
@@ -3,48 +3,66 @@ Absfuyu: Performance
3
3
  --------------------
4
4
  Performance Check
5
5
 
6
- Version: 1.1.0
7
- Date updated: 11/12/2023 (dd/mm/yyyy)
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
- - source_this
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
- # Functions
23
- "var_check",
24
- "source_this",
24
+ "retry",
25
+ # Class
26
+ "Checker",
25
27
  ]
26
28
 
27
29
 
28
30
  # Library
29
31
  ###########################################################################
30
- from functools import wraps as __wraps
32
+ import time
33
+ import tracemalloc
34
+ from functools import wraps
31
35
  from inspect import getsource
32
- from time import perf_counter as __perf_counter
33
- import tracemalloc as __tracemalloc
34
- from typing import Any, Callable, List, Optional, Tuple, Union
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
- def measure_performance(func):
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 the decorator (``@measure_performance``)
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
- @__wraps(func)
64
- def wrapper(*args, **kwargs):
65
- # Start memory measure
66
- __tracemalloc.start()
67
- # Start time measure
68
- start_time = __perf_counter()
69
- # Run function
70
- func(*args, **kwargs)
71
- # Get memory stats
72
- current, peak = __tracemalloc.get_traced_memory()
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
- # print(f'{"-"*40}')
80
- # print(f'Function: {func.__name__}')
81
- # #print(f'Method: {func.__doc__}')
82
- # print(f"Memory usage:\t\t {current / 10**6:.6f} MB")
83
- # print(f"Peak memory usage:\t {peak / 10**6:.6f} MB")
84
- # print(f'Time elapsed (seconds):\t {finish_time - start_time:.6f}')
85
- # print(f'{"-"*40}')
86
-
87
- stat = {
88
- "Function": func.__name__,
89
- "Memory usage": current / 10**6,
90
- "Peak memory usage": peak / 10**6,
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
- def var_check(variable: Any, full: bool = False):
107
+ @versionadded(version="3.2.0")
108
+ def function_debug(func: Callable) -> Callable: # type: ignore
111
109
  """
112
- Check a variable
110
+ Print the function signature and return value
113
111
 
114
112
  Parameters
115
113
  ----------
116
- variable : Any
117
- Variable that needed to check
114
+ func : Callable
115
+ A callable function
118
116
 
119
- full : bool
120
- | ``True``: Shows full detail
121
- | ``False``: Hides ``dir`` and ``docstring``
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
- >>> test = "test"
127
- >>> var_check(test)
128
- {'value': 'test', 'class': str, 'id': ...}
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
- # Output
176
- return output
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
- def source_this(function: Callable) -> str:
155
+ @versionadded(version="3.2.0")
156
+ def retry(retries: int = 3, delay: float = 1) -> Callable: # type: ignore
180
157
  """
181
- Show the source code of a function
158
+ Attempt to call a function, if it fails, try again with a specified delay.
182
159
 
183
160
  Parameters
184
161
  ----------
185
- function : Callable
186
- Just put in the function name
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
- str
191
- Source code
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
- return getsource(function)
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
- """Check a variable"""
200
- def __init__(self, checker: Any) -> None:
201
- self.item_to_check = checker
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
- """:returns: ``self.item_to_check.__doc__``"""
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
- """:returns: ``dir(self.item_to_check)``"""
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
- """:returns: Source code"""
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
- self,
33
- path_to_zip: Union[str, Path],
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(f"Zipping...")
61
- if self.source_path.is_dir(): # zip entire folder
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: # zip a file
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(f"Deleting unused folder...")
74
+ logger.debug("Deleting unused folder...")
77
75
  shutil.rmtree(self.source_path)
78
- logger.debug(f"Files deleted")
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)