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