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.

Files changed (72) hide show
  1. absfuyu/__init__.py +4 -4
  2. absfuyu/__main__.py +13 -1
  3. absfuyu/cli/__init__.py +2 -2
  4. absfuyu/cli/color.py +9 -2
  5. absfuyu/cli/config_group.py +2 -2
  6. absfuyu/cli/do_group.py +2 -37
  7. absfuyu/cli/game_group.py +2 -2
  8. absfuyu/cli/tool_group.py +7 -7
  9. absfuyu/config/__init__.py +17 -34
  10. absfuyu/core/__init__.py +49 -0
  11. absfuyu/core/baseclass.py +299 -0
  12. absfuyu/core/baseclass2.py +165 -0
  13. absfuyu/core/decorator.py +67 -0
  14. absfuyu/core/docstring.py +166 -0
  15. absfuyu/core/dummy_cli.py +67 -0
  16. absfuyu/core/dummy_func.py +49 -0
  17. absfuyu/dxt/__init__.py +42 -0
  18. absfuyu/dxt/dictext.py +201 -0
  19. absfuyu/dxt/dxt_support.py +79 -0
  20. absfuyu/dxt/intext.py +586 -0
  21. absfuyu/dxt/listext.py +508 -0
  22. absfuyu/dxt/strext.py +530 -0
  23. absfuyu/extra/__init__.py +12 -0
  24. absfuyu/extra/beautiful.py +252 -0
  25. absfuyu/{extensions → extra}/data_analysis.py +51 -82
  26. absfuyu/fun/__init__.py +110 -135
  27. absfuyu/fun/tarot.py +11 -19
  28. absfuyu/game/__init__.py +8 -2
  29. absfuyu/game/game_stat.py +8 -2
  30. absfuyu/game/sudoku.py +9 -3
  31. absfuyu/game/tictactoe.py +14 -7
  32. absfuyu/game/wordle.py +16 -10
  33. absfuyu/general/__init__.py +8 -81
  34. absfuyu/general/content.py +24 -38
  35. absfuyu/general/human.py +108 -228
  36. absfuyu/general/shape.py +1334 -0
  37. absfuyu/logger.py +10 -15
  38. absfuyu/pkg_data/__init__.py +137 -100
  39. absfuyu/pkg_data/deprecated.py +133 -0
  40. absfuyu/sort.py +6 -130
  41. absfuyu/tools/__init__.py +2 -2
  42. absfuyu/tools/checksum.py +33 -22
  43. absfuyu/tools/converter.py +51 -48
  44. absfuyu/{general → tools}/generator.py +17 -42
  45. absfuyu/tools/keygen.py +25 -30
  46. absfuyu/tools/obfuscator.py +246 -112
  47. absfuyu/tools/passwordlib.py +100 -30
  48. absfuyu/tools/shutdownizer.py +68 -47
  49. absfuyu/tools/web.py +4 -11
  50. absfuyu/util/__init__.py +17 -17
  51. absfuyu/util/api.py +10 -15
  52. absfuyu/util/json_method.py +7 -24
  53. absfuyu/util/lunar.py +5 -11
  54. absfuyu/util/path.py +22 -27
  55. absfuyu/util/performance.py +43 -67
  56. absfuyu/util/shorten_number.py +65 -14
  57. absfuyu/util/zipped.py +11 -17
  58. absfuyu/version.py +59 -42
  59. {absfuyu-4.2.0.dist-info → absfuyu-5.0.1.dist-info}/METADATA +41 -14
  60. absfuyu-5.0.1.dist-info/RECORD +68 -0
  61. absfuyu/core.py +0 -57
  62. absfuyu/everything.py +0 -32
  63. absfuyu/extensions/__init__.py +0 -12
  64. absfuyu/extensions/beautiful.py +0 -188
  65. absfuyu/fun/WGS.py +0 -134
  66. absfuyu/general/data_extension.py +0 -1796
  67. absfuyu/tools/stats.py +0 -226
  68. absfuyu/util/pkl.py +0 -67
  69. absfuyu-4.2.0.dist-info/RECORD +0 -59
  70. {absfuyu-4.2.0.dist-info → absfuyu-5.0.1.dist-info}/WHEEL +0 -0
  71. {absfuyu-4.2.0.dist-info → absfuyu-5.0.1.dist-info}/entry_points.txt +0 -0
  72. {absfuyu-4.2.0.dist-info → absfuyu-5.0.1.dist-info}/licenses/LICENSE +0 -0
absfuyu/dxt/listext.py ADDED
@@ -0,0 +1,508 @@
1
+ """
2
+ Absfuyu: Data Extension
3
+ -----------------------
4
+ list extension
5
+
6
+ Version: 5.0.0
7
+ Date updated: 25/02/2025 (dd/mm/yyyy)
8
+ """
9
+
10
+ # Module Package
11
+ # ---------------------------------------------------------------------------
12
+ __all__ = ["ListExt"]
13
+
14
+
15
+ # Library
16
+ # ---------------------------------------------------------------------------
17
+ import operator
18
+ import random
19
+ from collections import Counter
20
+ from collections.abc import Callable
21
+ from itertools import accumulate, chain, groupby
22
+ from typing import Any, Self
23
+
24
+ from absfuyu.core import ShowAllMethodsMixin, deprecated
25
+ from absfuyu.util import set_min, set_min_max
26
+
27
+
28
+ # Class
29
+ # ---------------------------------------------------------------------------
30
+ class ListExt(ShowAllMethodsMixin, list):
31
+ """
32
+ ``list`` extension
33
+ """
34
+
35
+ def stringify(self) -> Self:
36
+ """
37
+ Convert all item in ``list`` into string
38
+
39
+ Returns
40
+ -------
41
+ ListExt
42
+ A list with all items with type <str`>
43
+
44
+
45
+ Example:
46
+ --------
47
+ >>> test = ListExt([1, 1, 1, 2, 2, 3])
48
+ >>> test.stringify()
49
+ ['1', '1', '1', '2', '2', '3']
50
+ """
51
+ return self.__class__(map(str, self))
52
+
53
+ def head(self, number_of_items: int = 5) -> list:
54
+ """
55
+ Show first ``number_of_items`` items in ``ListExt``
56
+
57
+ Parameters
58
+ ----------
59
+ number_of_items : int
60
+ | Number of items to shows at once
61
+ | (Default: ``5``)
62
+
63
+ Returns
64
+ -------
65
+ list
66
+ Filtered list
67
+ """
68
+ number_of_items = int(
69
+ set_min_max(number_of_items, min_value=0, max_value=len(self))
70
+ )
71
+ return self[:number_of_items]
72
+
73
+ def tail(self, number_of_items: int = 5) -> list:
74
+ """
75
+ Show last ``number_of_items`` items in ``ListExt``
76
+
77
+ Parameters
78
+ ----------
79
+ number_of_items : int
80
+ | Number of items to shows at once
81
+ | (Default: ``5``)
82
+
83
+ Returns
84
+ -------
85
+ list
86
+ Filtered list
87
+ """
88
+ number_of_items = int(
89
+ set_min_max(number_of_items, min_value=0, max_value=len(self))
90
+ )
91
+ return self[::-1][:number_of_items][::-1]
92
+
93
+ def sorts(self, reverse: bool = False) -> Self:
94
+ """
95
+ Sort all items (with different type) in ``list``
96
+
97
+ Parameters
98
+ ----------
99
+ reverse : bool
100
+ | if ``True`` then sort in descending order
101
+ | if ``False`` then sort in ascending order
102
+ | (Default: ``False``)
103
+
104
+ Returns
105
+ -------
106
+ ListExt
107
+ A sorted list
108
+
109
+
110
+ Example:
111
+ --------
112
+ >>> test = ListExt([9, "abc", 3.5, "aaa", 1, 1.4])
113
+ >>> test.sorts()
114
+ [1, 9, 'aaa', 'abc', 1.4, 3.5]
115
+ """
116
+ lst = self.copy()
117
+ type_weights: dict = {}
118
+ for x in lst:
119
+ if type(x) not in type_weights:
120
+ type_weights[type(x)] = len(type_weights)
121
+ # logger.debug(f"Type weight: {type_weights}")
122
+
123
+ output = sorted(
124
+ lst, key=lambda x: (type_weights[type(x)], str(x)), reverse=reverse
125
+ )
126
+
127
+ # logger.debug(output)
128
+ return self.__class__(output)
129
+
130
+ def freq(
131
+ self,
132
+ sort: bool = False,
133
+ num_of_first_char: int | None = None,
134
+ appear_increment: bool = False,
135
+ ) -> dict | list[int]:
136
+ """
137
+ Find frequency of each item in list
138
+
139
+ Parameters
140
+ ----------
141
+ sort : bool
142
+ | if ``True``: Sorts the output in ascending order
143
+ | if ``False``: No sort
144
+
145
+ num_of_first_char : int | None
146
+ | Number of first character taken into account to sort
147
+ | (Default: ``None``)
148
+ | (num_of_first_char = ``1``: first character in each item)
149
+
150
+ appear_increment : bool
151
+ | return incremental index list of each item when sort
152
+ | (Default: ``False``)
153
+
154
+ Returns
155
+ -------
156
+ dict
157
+ A dict that show frequency
158
+
159
+ list[int]
160
+ Incremental index list
161
+
162
+
163
+ Example:
164
+ --------
165
+ >>> test = ListExt([1, 1, 2, 3, 5, 5])
166
+ >>> test.freq()
167
+ {1: 2, 2: 1, 3: 1, 5: 2}
168
+
169
+ >>> test = ListExt([1, 1, 2, 3, 3, 4, 5, 6])
170
+ >>> test.freq(appear_increment=True)
171
+ [2, 3, 5, 6, 7, 8]
172
+ """
173
+
174
+ if sort:
175
+ data = self.sorts().copy()
176
+ else:
177
+ data = self.copy()
178
+
179
+ if num_of_first_char is None:
180
+ temp = Counter(data)
181
+ else:
182
+ max_char: int = min([len(str(x)) for x in data])
183
+ # logger.debug(f"Max character: {max_char}")
184
+ if num_of_first_char not in range(1, max_char):
185
+ # logger.debug(f"Not in {range(1, max_char)}. Using default value...")
186
+ temp = Counter(data)
187
+ else:
188
+ # logger.debug(f"Freq of first {num_of_first_char} char")
189
+ temp = Counter([str(x)[:num_of_first_char] for x in data])
190
+
191
+ try:
192
+ times_appear = dict(sorted(temp.items()))
193
+ except Exception:
194
+ times_appear = dict(self.__class__(temp.items()).sorts())
195
+ # logger.debug(times_appear)
196
+
197
+ if appear_increment:
198
+ times_appear_increment: list[int] = list(
199
+ accumulate(times_appear.values(), operator.add)
200
+ )
201
+ # logger.debug(times_appear_increment)
202
+ return times_appear_increment # incremental index list
203
+ else:
204
+ return times_appear # character frequency
205
+
206
+ def slice_points(self, points: list[int]) -> list[list]:
207
+ """
208
+ Splits a list into sublists based on specified split points (indices).
209
+
210
+ This method divides the original list into multiple sublists. The ``points``
211
+ argument provides the indices at which the list should be split. The resulting
212
+ list of lists contains the sublists created by these splits. The original
213
+ list is not modified.
214
+
215
+ Parameters
216
+ ----------
217
+ points : list
218
+ A list of integer indices representing the points at which to split
219
+ the list. These indices are *exclusive* of the starting sublist
220
+ but *inclusive* of the ending sublist.
221
+
222
+ Returns
223
+ -------
224
+ list[list]
225
+ A list of lists, where each inner list is a slice of the original list
226
+ defined by the provided split points.
227
+
228
+
229
+ Example:
230
+ --------
231
+ >>> test = ListExt([1, 1, 2, 3, 3, 4, 5, 6])
232
+ >>> test.slice_points([2, 5])
233
+ [[1, 1], [2, 3, 3], [4, 5, 6]]
234
+ >>> test.slice_points([0, 1, 2, 3, 4, 5, 6, 7, 8])
235
+ [[], [1], [1], [2], [3], [3], [4], [5], [6]]
236
+ >>> test.slice_points([])
237
+ [[1, 1, 2, 3, 3, 4, 5, 6]]
238
+ """
239
+ points.append(len(self))
240
+ data = self.copy()
241
+ # return [data[points[i]:points[i+1]] for i in range(len(points)-1)]
242
+ return [data[i1:i2] for i1, i2 in zip([0] + points[:-1], points)]
243
+
244
+ def pick_one(self) -> Any:
245
+ """
246
+ Pick one random items from ``list``
247
+
248
+ Returns
249
+ -------
250
+ Any
251
+ Random value
252
+
253
+
254
+ Example:
255
+ --------
256
+ >>> test = ListExt(["foo", "bar"])
257
+ >>> test.pick_one()
258
+ 'bar'
259
+ """
260
+ if len(self) != 0:
261
+ out = random.choice(self)
262
+ # logger.debug(out)
263
+ return out
264
+ else:
265
+ # logger.debug("List empty!")
266
+ raise IndexError("List empty!")
267
+
268
+ def get_random(self, number_of_items: int = 5) -> list:
269
+ """
270
+ Get ``number_of_items`` random items in ``ListExt``
271
+
272
+ Parameters
273
+ ----------
274
+ number_of_items : int
275
+ | Number random of items
276
+ | (Default: ``5``)
277
+
278
+ Returns
279
+ -------
280
+ list
281
+ Filtered list
282
+ """
283
+ return [self.pick_one() for _ in range(number_of_items)]
284
+
285
+ def len_items(self) -> Self:
286
+ """
287
+ ``len()`` for every item in ``list[str]``
288
+
289
+ Returns
290
+ -------
291
+ ListExt
292
+ List of ``len()``'ed value
293
+
294
+
295
+ Example:
296
+ --------
297
+ >>> test = ListExt(["foo", "bar", "pizza"])
298
+ >>> test.len_items()
299
+ [3, 3, 5]
300
+ """
301
+ out = self.__class__([len(str(x)) for x in self])
302
+ # out = ListExt(map(lambda x: len(str(x)), self))
303
+ # logger.debug(out)
304
+ return out
305
+
306
+ def mean_len(self) -> float:
307
+ """
308
+ Average length of every item
309
+
310
+ Returns
311
+ -------
312
+ float
313
+ Average length
314
+
315
+
316
+ Example:
317
+ --------
318
+ >>> test = ListExt(["foo", "bar", "pizza"])
319
+ >>> test.mean_len()
320
+ 3.6666666666666665
321
+ """
322
+ out = sum(self.len_items()) / len(self)
323
+ # logger.debug(out)
324
+ return out
325
+
326
+ def apply(self, func: Callable) -> Self:
327
+ """
328
+ Apply function to each entry
329
+
330
+ Parameters
331
+ ----------
332
+ func : Callable
333
+ Callable function
334
+
335
+ Returns
336
+ -------
337
+ ListExt
338
+ ListExt
339
+
340
+
341
+ Example:
342
+ --------
343
+ >>> test = ListExt([1, 2, 3])
344
+ >>> test.apply(str)
345
+ ['1', '2', '3']
346
+ """
347
+ # return __class__(func(x) for x in self)
348
+ return self.__class__(map(func, self))
349
+
350
+ def unique(self) -> Self:
351
+ """
352
+ Remove duplicates
353
+
354
+ Returns
355
+ -------
356
+ ListExt
357
+ Duplicates removed list
358
+
359
+
360
+ Example:
361
+ --------
362
+ >>> test = ListExt([1, 1, 1, 2, 2, 3])
363
+ >>> test.unique()
364
+ [1, 2, 3]
365
+ """
366
+ return self.__class__(set(self))
367
+
368
+ def group_by_unique(self) -> Self:
369
+ """
370
+ Group duplicated elements into list
371
+
372
+ Returns
373
+ -------
374
+ ListExt
375
+ Grouped value
376
+
377
+
378
+ Example:
379
+ --------
380
+ >>> test = ListExt([1, 2, 3, 1, 3, 3, 2])
381
+ >>> test.group_by_unique()
382
+ [[1, 1], [2, 2], [3, 3, 3]]
383
+ """
384
+ # Old
385
+ # out = self.sorts().slice_points(self.freq(appear_increment=True))
386
+ # return __class__(out[:-1])
387
+
388
+ # New
389
+ temp = groupby(self.sorts())
390
+ return self.__class__([list(g) for _, g in temp])
391
+
392
+ def group_by_pair_value(self, max_loop: int = 3) -> list[list]:
393
+ """
394
+ Assume each ``list`` in ``list`` is a pair value,
395
+ returns a ``list`` contain all paired value
396
+
397
+ Parameters
398
+ ----------
399
+ max_loop : int
400
+ Times to run functions (minimum: ``3``)
401
+
402
+ Returns
403
+ -------
404
+ list[list]
405
+ Grouped value
406
+
407
+
408
+ Example:
409
+ --------
410
+ >>> test = ListExt([[1, 2], [2, 3], [4, 3], [5, 6]])
411
+ >>> test.group_by_pair_value()
412
+ [[1, 2, 3, 4], [5, 6]]
413
+
414
+ >>> test = ListExt([[8, 3], [4, 6], [6, 3], [5, 2], [7, 2]])
415
+ >>> test.group_by_pair_value()
416
+ [[8, 3, 4, 6], [2, 5, 7]]
417
+
418
+ >>> test = ListExt([["a", 4], ["b", 4], [5, "c"]])
419
+ >>> test.group_by_pair_value()
420
+ [['a', 4, 'b'], ['c', 5]]
421
+ """
422
+
423
+ iter = self.copy()
424
+
425
+ # Init loop
426
+ for _ in range(int(set_min(max_loop, min_value=3))):
427
+ temp: dict[Any, list] = {}
428
+ # Make dict{key: all `item` that contains `key`}
429
+ for item in iter:
430
+ for x in item:
431
+ if temp.get(x, None) is None:
432
+ temp[x] = [item]
433
+ else:
434
+ temp[x].append(item)
435
+
436
+ # Flatten dict.values
437
+ for k, v in temp.items():
438
+ temp[k] = list(set(chain(*v)))
439
+
440
+ iter = list(temp.values())
441
+
442
+ return list(x for x, _ in groupby(iter))
443
+
444
+ def flatten(self) -> Self:
445
+ """
446
+ Flatten the list
447
+
448
+ Returns
449
+ -------
450
+ ListExt
451
+ Flattened list
452
+
453
+
454
+ Example:
455
+ --------
456
+ >>> test = ListExt([["test"], ["test", "test"], ["test"]])
457
+ >>> test.flatten()
458
+ ['test', 'test', 'test', 'test']
459
+ """
460
+ try:
461
+ # return self.__class__(sum(self, start=[]))
462
+ return self.__class__(chain(*self))
463
+ except Exception:
464
+ temp = list(map(lambda x: x if isinstance(x, list) else [x], self))
465
+ return self.__class__(chain(*temp))
466
+
467
+ def numbering(self, start: int = 0) -> Self:
468
+ """
469
+ Number the item in list
470
+ (``enumerate`` wrapper)
471
+
472
+ Parameters
473
+ ----------
474
+ start : int
475
+ Start from which number
476
+ (Default: ``0``)
477
+
478
+ Returns
479
+ -------
480
+ ListExt
481
+ Counted list
482
+
483
+
484
+ Example:
485
+ --------
486
+ >>> test = ListExt([9, 9, 9])
487
+ >>> test.numbering()
488
+ [(0, 9), (1, 9), (2, 9)]
489
+ """
490
+ start = int(set_min(start, min_value=0))
491
+ return self.__class__(enumerate(self, start=start))
492
+
493
+ @staticmethod
494
+ @deprecated("5.0.0")
495
+ def _group_by_unique(iterable: list) -> list[list]:
496
+ """
497
+ Static method for ``group_by_unique``
498
+ """
499
+ return list([list(g) for _, g in groupby(iterable)])
500
+
501
+ @staticmethod
502
+ @deprecated("5.0.0")
503
+ def _numbering(iterable: list, start: int = 0) -> list[tuple[int, Any]]:
504
+ """
505
+ Static method for ``numbering``
506
+ """
507
+ start = int(set_min(start, min_value=0))
508
+ return list(enumerate(iterable, start=start))