absfuyu 5.0.0__py3-none-any.whl → 6.1.2__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 (103) hide show
  1. absfuyu/__init__.py +5 -3
  2. absfuyu/__main__.py +3 -3
  3. absfuyu/cli/__init__.py +13 -2
  4. absfuyu/cli/audio_group.py +98 -0
  5. absfuyu/cli/color.py +30 -14
  6. absfuyu/cli/config_group.py +9 -2
  7. absfuyu/cli/do_group.py +23 -6
  8. absfuyu/cli/game_group.py +27 -2
  9. absfuyu/cli/tool_group.py +81 -11
  10. absfuyu/config/__init__.py +3 -3
  11. absfuyu/core/__init__.py +12 -8
  12. absfuyu/core/baseclass.py +929 -96
  13. absfuyu/core/baseclass2.py +44 -3
  14. absfuyu/core/decorator.py +70 -4
  15. absfuyu/core/docstring.py +64 -41
  16. absfuyu/core/dummy_cli.py +3 -3
  17. absfuyu/core/dummy_func.py +19 -6
  18. absfuyu/dxt/__init__.py +2 -2
  19. absfuyu/dxt/base_type.py +93 -0
  20. absfuyu/dxt/dictext.py +204 -16
  21. absfuyu/dxt/dxt_support.py +2 -2
  22. absfuyu/dxt/intext.py +151 -34
  23. absfuyu/dxt/listext.py +969 -127
  24. absfuyu/dxt/strext.py +77 -17
  25. absfuyu/extra/__init__.py +2 -2
  26. absfuyu/extra/audio/__init__.py +8 -0
  27. absfuyu/extra/audio/_util.py +57 -0
  28. absfuyu/extra/audio/convert.py +192 -0
  29. absfuyu/extra/audio/lossless.py +281 -0
  30. absfuyu/extra/beautiful.py +3 -2
  31. absfuyu/extra/da/__init__.py +72 -0
  32. absfuyu/extra/da/dadf.py +1600 -0
  33. absfuyu/extra/da/dadf_base.py +186 -0
  34. absfuyu/extra/da/df_func.py +181 -0
  35. absfuyu/extra/da/mplt.py +219 -0
  36. absfuyu/extra/ggapi/__init__.py +8 -0
  37. absfuyu/extra/ggapi/gdrive.py +223 -0
  38. absfuyu/extra/ggapi/glicense.py +148 -0
  39. absfuyu/extra/ggapi/glicense_df.py +186 -0
  40. absfuyu/extra/ggapi/gsheet.py +88 -0
  41. absfuyu/extra/img/__init__.py +30 -0
  42. absfuyu/extra/img/converter.py +402 -0
  43. absfuyu/extra/img/dup_check.py +291 -0
  44. absfuyu/extra/pdf.py +87 -0
  45. absfuyu/extra/rclone.py +253 -0
  46. absfuyu/extra/xml.py +90 -0
  47. absfuyu/fun/__init__.py +7 -20
  48. absfuyu/fun/rubik.py +442 -0
  49. absfuyu/fun/tarot.py +2 -2
  50. absfuyu/game/__init__.py +2 -2
  51. absfuyu/game/game_stat.py +2 -2
  52. absfuyu/game/schulte.py +78 -0
  53. absfuyu/game/sudoku.py +2 -2
  54. absfuyu/game/tictactoe.py +2 -3
  55. absfuyu/game/wordle.py +6 -4
  56. absfuyu/general/__init__.py +4 -4
  57. absfuyu/general/content.py +4 -4
  58. absfuyu/general/human.py +2 -2
  59. absfuyu/general/resrel.py +213 -0
  60. absfuyu/general/shape.py +3 -8
  61. absfuyu/general/tax.py +344 -0
  62. absfuyu/logger.py +806 -59
  63. absfuyu/numbers/__init__.py +13 -0
  64. absfuyu/numbers/number_to_word.py +321 -0
  65. absfuyu/numbers/shorten_number.py +303 -0
  66. absfuyu/numbers/time_duration.py +217 -0
  67. absfuyu/pkg_data/__init__.py +2 -2
  68. absfuyu/pkg_data/deprecated.py +2 -2
  69. absfuyu/pkg_data/logo.py +1462 -0
  70. absfuyu/sort.py +4 -4
  71. absfuyu/tools/__init__.py +28 -2
  72. absfuyu/tools/checksum.py +144 -9
  73. absfuyu/tools/converter.py +120 -34
  74. absfuyu/tools/generator.py +461 -0
  75. absfuyu/tools/inspector.py +752 -0
  76. absfuyu/tools/keygen.py +2 -2
  77. absfuyu/tools/obfuscator.py +47 -9
  78. absfuyu/tools/passwordlib.py +89 -25
  79. absfuyu/tools/shutdownizer.py +3 -8
  80. absfuyu/tools/sw.py +718 -0
  81. absfuyu/tools/web.py +10 -13
  82. absfuyu/typings.py +138 -0
  83. absfuyu/util/__init__.py +114 -6
  84. absfuyu/util/api.py +41 -18
  85. absfuyu/util/cli.py +119 -0
  86. absfuyu/util/gui.py +91 -0
  87. absfuyu/util/json_method.py +43 -14
  88. absfuyu/util/lunar.py +2 -2
  89. absfuyu/util/package.py +124 -0
  90. absfuyu/util/path.py +702 -82
  91. absfuyu/util/performance.py +122 -7
  92. absfuyu/util/shorten_number.py +244 -21
  93. absfuyu/util/text_table.py +481 -0
  94. absfuyu/util/zipped.py +8 -7
  95. absfuyu/version.py +79 -59
  96. {absfuyu-5.0.0.dist-info → absfuyu-6.1.2.dist-info}/METADATA +52 -11
  97. absfuyu-6.1.2.dist-info/RECORD +105 -0
  98. {absfuyu-5.0.0.dist-info → absfuyu-6.1.2.dist-info}/WHEEL +1 -1
  99. absfuyu/extra/data_analysis.py +0 -1078
  100. absfuyu/general/generator.py +0 -303
  101. absfuyu-5.0.0.dist-info/RECORD +0 -68
  102. {absfuyu-5.0.0.dist-info → absfuyu-6.1.2.dist-info}/entry_points.txt +0 -0
  103. {absfuyu-5.0.0.dist-info → absfuyu-6.1.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,461 @@
1
+ """
2
+ Absfuyu: Generator
3
+ ------------------
4
+ This generate stuff (Not python's ``generator``)
5
+
6
+ Version: 6.1.1
7
+ Date updated: 30/12/2025 (dd/mm/yyyy)
8
+
9
+ Features:
10
+ ---------
11
+ - Generate random string
12
+ - Generate key
13
+ - Generate check digit
14
+ - Generate combinations of list in range
15
+ """
16
+
17
+ # Module level
18
+ # ---------------------------------------------------------------------------
19
+ __all__ = ["Charset", "Generator"]
20
+
21
+
22
+ # Library
23
+ # ---------------------------------------------------------------------------
24
+ import string
25
+ from collections.abc import Collection, Sequence
26
+ from itertools import chain, combinations
27
+ from random import choice
28
+ from typing import Literal, TypeVar, cast, overload
29
+
30
+ from absfuyu.core.baseclass import GetClassMembersMixin
31
+ from absfuyu.core.docstring import deprecated
32
+ from absfuyu.util import set_min_max
33
+
34
+ # Type
35
+ # ---------------------------------------------------------------------------
36
+ T = TypeVar("T")
37
+
38
+
39
+ # Class
40
+ # ---------------------------------------------------------------------------
41
+ class Charset:
42
+ """
43
+ Character set data class
44
+ """
45
+
46
+ DEFAULT: str = string.ascii_letters + string.digits
47
+ ALPHABET: str = string.ascii_letters
48
+ FULL: str = string.ascii_letters + string.digits + string.punctuation
49
+ UPPERCASE: str = string.ascii_uppercase
50
+ LOWERCASE: str = string.ascii_lowercase
51
+ DIGIT: str = string.digits
52
+ SPECIAL: str = string.punctuation
53
+ ALL: str = string.printable
54
+ PRODUCT_KEY: str = (
55
+ "BCDFGHJKMNPQRTVWXY2346789" # Charset that various key makers use
56
+ )
57
+
58
+ def __str__(self) -> str:
59
+ charset = [x for x in self.__class__.__dict__.keys() if not x.startswith("__")]
60
+ return f"List of Character set: {charset}"
61
+
62
+ def __repr__(self) -> str:
63
+ charset = [x for x in self.__class__.__dict__.keys() if not x.startswith("__")]
64
+ clsname = self.__class__.__name__
65
+ return f"{clsname}({', '.join(charset)})"
66
+
67
+
68
+ class Generator(GetClassMembersMixin):
69
+ """
70
+ Generator that generate stuffs
71
+
72
+ Features:
73
+ ---------
74
+ - Generate random string
75
+ - Generate key
76
+ - Generate check digit
77
+ - Generate combinations of list in range
78
+ """
79
+
80
+ # Generate string
81
+ @overload
82
+ @staticmethod
83
+ def generate_string( # type: ignore
84
+ charset: str = Charset.DEFAULT,
85
+ size: int = 8,
86
+ times: int = 1,
87
+ unique: bool = False,
88
+ ) -> list[str]: ...
89
+
90
+ @overload
91
+ @staticmethod
92
+ def generate_string(
93
+ charset: str = Charset.DEFAULT,
94
+ size: int = 8,
95
+ times: int = 1,
96
+ unique: bool = False,
97
+ string_type_if_1: Literal[True] = ...,
98
+ ) -> str: ...
99
+
100
+ @staticmethod
101
+ @deprecated("5.2.0", reason="Use generate_string2() instead.")
102
+ def generate_string(
103
+ charset: str = Charset.DEFAULT,
104
+ size: int = 8,
105
+ times: int = 1,
106
+ unique: bool = False,
107
+ string_type_if_1: bool = False,
108
+ ) -> str | list[str]:
109
+ """
110
+ Generate a list of random string from character set (Random string generator).
111
+ Deprecated
112
+
113
+ Parameters
114
+ ----------
115
+ charset : str, optional
116
+ - Use custom character set or character sets already defined in ``Charset``
117
+ - ``Charset.DEFAULT``: character in [a-zA-Z0-9] (default)
118
+ - ``Charset.ALPHABET``: character in [a-zA-Z]
119
+ - ``Charset.FULL``: character in [a-zA-Z0-9] + special characters
120
+ - ``Charset.UPPERCASE``: character in [A-Z]
121
+ - ``Charset.LOWERCASE``: character in [a-z]
122
+ - ``Charset.DIGIT``: character in [0-9]
123
+ - ``Charset.SPECIAL``: character in [!@#$%^&*()_+=-]
124
+ - ``Charset.ALL``: character in every printable character
125
+
126
+ size : int, optional
127
+ Length of each string in list, by default ``8``
128
+
129
+ times : int, optional
130
+ How many random string generated, by default ``1``
131
+
132
+ unique : bool, optional
133
+ Each generated text is unique, by default ``False``
134
+
135
+ string_type_if_1 : bool, optional
136
+ Return a ``str`` type result if ``times == 1``,
137
+ by default ``False``
138
+
139
+ Returns
140
+ -------
141
+ list
142
+ List of random string generated
143
+
144
+ str
145
+ When ``string_type_if_1`` is ``True``
146
+ """
147
+
148
+ try:
149
+ char_lst = list(charset)
150
+ except Exception:
151
+ char_lst = charset # type: ignore # ! review this sometime
152
+
153
+ unique_string = []
154
+ count = 0
155
+
156
+ while count < times:
157
+ s = "".join(choice(char_lst) for _ in range(size))
158
+ if not unique:
159
+ unique_string.append(s)
160
+ count += 1
161
+ else:
162
+ if s not in unique_string:
163
+ unique_string.append(s)
164
+ count += 1
165
+
166
+ if string_type_if_1 and times == 1:
167
+ return unique_string[0]
168
+ else:
169
+ return unique_string
170
+
171
+ @overload
172
+ @staticmethod
173
+ def generate_string2() -> list[str]: ...
174
+
175
+ @overload
176
+ @staticmethod
177
+ def generate_string2(
178
+ charset: str = Charset.DEFAULT,
179
+ length: int = 8,
180
+ times: int = 1,
181
+ unique: bool = False,
182
+ ) -> list[str]: ...
183
+
184
+ @overload
185
+ @staticmethod
186
+ def generate_string2(
187
+ charset: Sequence[str],
188
+ length: int = 8,
189
+ times: int = 1,
190
+ unique: bool = False,
191
+ ) -> list[str]: ...
192
+
193
+ @staticmethod
194
+ def generate_string2(
195
+ charset: Sequence[str] | Charset | str = Charset.DEFAULT,
196
+ length: int = 8,
197
+ times: int = 1,
198
+ unique: bool = False,
199
+ ) -> list[str]:
200
+ """
201
+ Generate a list of random string from character set (Random string generator).
202
+ Improved version.
203
+
204
+ Parameters
205
+ ----------
206
+ charset : Sequence[str] | Charset | str, optional
207
+ - Use custom character set or character sets already defined in ``Charset``
208
+ - ``Charset.DEFAULT``: character in [a-zA-Z0-9] (default)
209
+ - ``Charset.ALPHABET``: character in [a-zA-Z]
210
+ - ``Charset.FULL``: character in [a-zA-Z0-9] + special characters
211
+ - ``Charset.UPPERCASE``: character in [A-Z]
212
+ - ``Charset.LOWERCASE``: character in [a-z]
213
+ - ``Charset.DIGIT``: character in [0-9]
214
+ - ``Charset.SPECIAL``: character in [!@#$%^&*()_+=-]
215
+ - ``Charset.ALL``: character in every printable character
216
+
217
+ length : int, optional
218
+ Length of each string in list, by default ``8``
219
+
220
+ times : int, optional
221
+ How many random string generated, by default ``1``
222
+
223
+ unique : bool, optional
224
+ Each generated text is unique, by default ``False``
225
+
226
+ Returns
227
+ -------
228
+ list[str]
229
+ List of random generated string.
230
+
231
+ Raises
232
+ ------
233
+ TypeError
234
+ When ``charset`` not in correct type.
235
+
236
+
237
+ Example:
238
+ --------
239
+ >>> Generator.generate_string2(times=3)
240
+ ['67Xfh1fv', 'iChcGz9P', 'u82fNzlm']
241
+ """
242
+
243
+ # Type check
244
+ if isinstance(charset, str):
245
+ character_list: list[str] = list(charset)
246
+ elif isinstance(charset, Sequence):
247
+ character_list = cast(list, charset)
248
+ else:
249
+ raise TypeError("Not a valid type.")
250
+
251
+ # Setup
252
+ generated_strings: list[str] = []
253
+ unique_generated_strings: set[str] = set[str]()
254
+ times_ = max(1, times)
255
+
256
+ while True:
257
+ random_string = "".join(choice(character_list) for _ in range(length))
258
+ if unique:
259
+ unique_generated_strings.add(random_string)
260
+ else:
261
+ generated_strings.append(random_string)
262
+
263
+ # Break condition
264
+ if (
265
+ len(unique_generated_strings) >= times_
266
+ or len(generated_strings) >= times_
267
+ ):
268
+ break
269
+
270
+ return list(unique_generated_strings) if unique else generated_strings
271
+
272
+ # Generate key
273
+ @overload
274
+ @classmethod
275
+ def generate_key(cls) -> str: ...
276
+
277
+ @overload
278
+ @classmethod
279
+ def generate_key(
280
+ cls,
281
+ charset: str = Charset.PRODUCT_KEY,
282
+ letter_per_block: int = 5,
283
+ number_of_block: int = 5,
284
+ sep: str = "-",
285
+ ) -> str: ...
286
+
287
+ @classmethod
288
+ def generate_key(
289
+ cls,
290
+ charset: str = Charset.PRODUCT_KEY,
291
+ letter_per_block: int = 5,
292
+ number_of_block: int = 5,
293
+ sep: str = "-",
294
+ ) -> str:
295
+ """
296
+ Generate custom key.
297
+
298
+ Parameters
299
+ ----------
300
+ charset : Charset | str, optional
301
+ Character set, by default ``Charset.PRODUCT_KEY``
302
+
303
+ letter_per_block : int, optional
304
+ Number of letter per key block, by default ``5``
305
+
306
+ number_of_block : int, optional
307
+ Number of key block, by default ``5``
308
+
309
+ sep : str, optional
310
+ Key block separator, by default ``-``
311
+
312
+ Returns
313
+ -------
314
+ str
315
+ Generated key
316
+
317
+
318
+ Example:
319
+ --------
320
+ >>> Generator.generate_key(letter_per_block=10, number_of_block=2)
321
+ 'VKKPJVYD2H-M7R687QCV2'
322
+ """
323
+ out = sep.join(
324
+ cls.generate_string2(
325
+ charset,
326
+ length=letter_per_block,
327
+ times=number_of_block,
328
+ unique=False,
329
+ )
330
+ )
331
+ return out
332
+
333
+ # Generate check digit
334
+ @overload
335
+ @staticmethod
336
+ def generate_check_digit(number: int) -> int: ...
337
+
338
+ @overload
339
+ @staticmethod
340
+ def generate_check_digit(number: list[int]) -> int: ...
341
+
342
+ @overload
343
+ @staticmethod
344
+ def generate_check_digit(number: str) -> int: ...
345
+
346
+ @staticmethod
347
+ def generate_check_digit(number: int | list[int] | str) -> int:
348
+ """
349
+ Check digit generator.
350
+
351
+ "A check digit is a form of redundancy check used for
352
+ error detection on identification numbers, such as
353
+ bank account numbers, which are used in an application
354
+ where they will at least sometimes be input manually.
355
+ It is analogous to a binary parity bit used to
356
+ check for errors in computer-generated data.
357
+ It consists of one or more digits (or letters) computed
358
+ by an algorithm from the other digits (or letters) in the sequence input.
359
+ With a check digit, one can detect simple errors in
360
+ the input of a series of characters (usually digits)
361
+ such as a single mistyped digit or some permutations
362
+ of two successive digits." (Wikipedia)
363
+
364
+ This function use Luhn's algorithm to calculate.
365
+
366
+ Parameters
367
+ ----------
368
+ number : int
369
+ Number to calculate check digit
370
+
371
+ Returns
372
+ -------
373
+ int
374
+ Check digit
375
+
376
+
377
+ Example:
378
+ --------
379
+ >>> Generator.generate_check_digit(4129984562545)
380
+ 7
381
+ """
382
+
383
+ # Type handle
384
+ if isinstance(number, int):
385
+ # Turn into list[int] then reverse the order
386
+ num = [int(x) for x in list(str(number))][::-1]
387
+ elif isinstance(number, str):
388
+ num = [int(x) for x in list(number)][::-1]
389
+ elif isinstance(number, list):
390
+ num = number[::-1]
391
+ else:
392
+ raise TypeError("Variable `number` is not correct type.")
393
+
394
+ sum = 0
395
+
396
+ # for i in range(len(num)):
397
+ for idx, _ in enumerate(num):
398
+ if idx % 2 == 0:
399
+ # double value of the even-th digit
400
+ num[idx] *= 2
401
+ # sum the character of digit if it's >= 10
402
+ if num[idx] >= 10:
403
+ num[idx] -= 9
404
+ sum += num[idx]
405
+
406
+ out = (10 - (sum % 10)) % 10
407
+ return out
408
+
409
+ # Generate combinations range
410
+ @overload
411
+ @staticmethod
412
+ def combinations_range(collection: Collection[T]) -> list[tuple[T, ...]]: ...
413
+
414
+ @overload
415
+ @staticmethod
416
+ def combinations_range(collection: Collection[T], *, min_len: int = 1, max_len: int = 0) -> list[tuple[T, ...]]: ...
417
+
418
+ @staticmethod
419
+ def combinations_range(
420
+ collection: Collection[T], *, min_len: int = 1, max_len: int = 0
421
+ ) -> list[tuple[T, ...]]:
422
+ """
423
+ Generate all combinations of a ``collection`` from ``min_len`` to ``max_len``
424
+
425
+ Parameters
426
+ ----------
427
+ collection : Collection[T]
428
+ A collection (Iterable with ``__len__``) that need to generate combination
429
+
430
+ min_len : int, optional
431
+ Minimum ``r`` of ``combinations``, by default ``1``
432
+
433
+ max_len : int, optional
434
+ Maximum ``r`` of ``combinations``, by default ``0`` (len of ``collection``)
435
+
436
+ Returns
437
+ -------
438
+ list[tuple]
439
+ A list of all combinations from range(``min_len``, ``max_len``) of ``collection``
440
+
441
+
442
+ Example:
443
+ --------
444
+ >>> Generator.combinations_range([1, 2, 3], min_len=2)
445
+ [(1, 2), (1, 3), (2, 3), (1, 2, 3)]
446
+ """
447
+ # Restrain
448
+ len_iter = len(
449
+ collection
450
+ ) # with collection.abc.Iterable, use len(list(collection))
451
+ if max_len < 1:
452
+ max_len = len_iter
453
+ max_len = int(min(max_len, len_iter))
454
+ min_len = int(set_min_max(min_len, min_value=1, max_value=max_len))
455
+
456
+ # Return
457
+ return list(
458
+ chain.from_iterable(
459
+ combinations(collection, i) for i in range(min_len, max_len + 1)
460
+ )
461
+ )