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/dictext.py ADDED
@@ -0,0 +1,201 @@
1
+ """
2
+ Absfuyu: Data Extension
3
+ -----------------------
4
+ dict extension
5
+
6
+ Version: 5.0.0
7
+ Date updated: 25/02/2025 (dd/mm/yyyy)
8
+ """
9
+
10
+ # Module Package
11
+ # ---------------------------------------------------------------------------
12
+ __all__ = ["DictExt", "DictAnalyzeResult"]
13
+
14
+
15
+ # Library
16
+ # ---------------------------------------------------------------------------
17
+ import operator
18
+ from collections.abc import Callable
19
+ from typing import Any, NamedTuple, Self
20
+
21
+ from absfuyu.core import ShowAllMethodsMixin, versionadded, versionchanged
22
+
23
+
24
+ # Class
25
+ # ---------------------------------------------------------------------------
26
+ class DictAnalyzeResult(NamedTuple):
27
+ """
28
+ Result for ``DictExt.analyze()``
29
+ """
30
+
31
+ max_value: int | float
32
+ min_value: int | float
33
+ max_list: list
34
+ min_list: list
35
+
36
+
37
+ class DictExt(ShowAllMethodsMixin, dict):
38
+ """
39
+ ``dict`` extension
40
+ """
41
+
42
+ @versionchanged("3.3.0", reason="Updated return type")
43
+ def analyze(self) -> DictAnalyzeResult:
44
+ """
45
+ Analyze all the key values (``int``, ``float``)
46
+ in ``dict`` then return highest/lowest index
47
+
48
+ Returns
49
+ -------
50
+ dict
51
+ Analyzed data
52
+
53
+
54
+ Example:
55
+ --------
56
+ >>> test = DictExt({
57
+ ... "abc": 9,
58
+ ... "def": 9,
59
+ ... "ghi": 8,
60
+ ... "jkl": 1,
61
+ ... "mno": 1
62
+ ... })
63
+ >>> test.analyze()
64
+ DictAnalyzeResult(max_value=9, min_value=1, max_list=[('abc', 9), ('def', 9)], min_list=[('jkl', 1), ('mno', 1)])
65
+ """
66
+ try:
67
+ dct: dict = self.copy()
68
+
69
+ max_val: int | float = max(list(dct.values()))
70
+ min_val: int | float = min(list(dct.values()))
71
+ max_list = []
72
+ min_list = []
73
+
74
+ for k, v in dct.items():
75
+ if v == max_val:
76
+ max_list.append((k, v))
77
+ if v == min_val:
78
+ min_list.append((k, v))
79
+
80
+ return DictAnalyzeResult(max_val, min_val, max_list, min_list)
81
+
82
+ except TypeError:
83
+ err_msg = "Value must be int or float"
84
+ # logger.error(err_msg)
85
+ raise ValueError(err_msg) # noqa: B904
86
+
87
+ def swap_items(self) -> Self:
88
+ """
89
+ Swap ``dict.keys()`` with ``dict.values()``
90
+
91
+ Returns
92
+ -------
93
+ DictExt
94
+ Swapped dict
95
+
96
+
97
+ Example:
98
+ --------
99
+ >>> test = DictExt({"abc": 9})
100
+ >>> test.swap_items()
101
+ {9: 'abc'}
102
+ """
103
+ # return self.__class__(zip(self.values(), self.keys()))
104
+ return self.__class__({v: k for k, v in self.items()})
105
+
106
+ def apply(self, func: Callable, apply_to_value: bool = True) -> Self:
107
+ """
108
+ Apply function to ``DictExt.keys()`` or ``DictExt.values()``
109
+
110
+ Parameters
111
+ ----------
112
+ func : Callable
113
+ Callable function
114
+
115
+ apply_to_value : bool
116
+ | ``True``: Apply ``func`` to ``DictExt.values()``
117
+ | ``False``: Apply ``func`` to ``DictExt.keys()``
118
+
119
+ Returns
120
+ -------
121
+ DictExt
122
+ DictExt
123
+
124
+
125
+ Example:
126
+ --------
127
+ >>> test = DictExt({"abc": 9})
128
+ >>> test.apply(str)
129
+ {'abc': '9'}
130
+ """
131
+ if apply_to_value:
132
+ new_dict = {k: func(v) for k, v in self.items()}
133
+ else:
134
+ new_dict = {func(k): v for k, v in self.items()}
135
+ return self.__class__(new_dict)
136
+
137
+ @versionchanged("5.0.0", reason="Updated to handle more types and operator")
138
+ @versionadded("3.4.0")
139
+ def aggregate(
140
+ self,
141
+ other_dict: dict,
142
+ default_value: Any = 0,
143
+ operator_func: Callable[[Any, Any], Any] = operator.add, # operator add
144
+ ) -> Self:
145
+ """
146
+ Aggregates the values of the current dictionary with another dictionary.
147
+
148
+ For each unique key, this method applies the specified operator to the values
149
+ from both dictionaries. If a key exists in only one dictionary, its value is used.
150
+ If an error occurs during aggregation (e.g., incompatible types), the values
151
+ from both dictionaries are returned as a list.
152
+
153
+ Parameters
154
+ ----------
155
+ other_dict : dict
156
+ The dictionary to aggregate with.
157
+
158
+ default_value : Any, optional
159
+ The value to use for missing keys, by default ``0``
160
+
161
+
162
+ operator_func : Callable[[Any, Any], Any], optional
163
+ A function that takes two arguments and returns a single value,
164
+ by default ``operator.add``
165
+
166
+ Returns
167
+ -------
168
+ Self
169
+ A new instance of the aggregated dictionary.
170
+
171
+
172
+ Example:
173
+ --------
174
+ >>> test = DictExt({"test": 5, "test2": 9})
175
+ >>> agg = {"test1": 10, "test2": 1}
176
+ >>> print(test.aggregate(agg))
177
+ {'test1': 10, 'test': 5, 'test2': 10}
178
+
179
+ >>> test = DictExt({"test": 5, "test2": 9})
180
+ >>> agg = {"test1": 10, "test2": "1"}
181
+ >>> print(test.aggregate(agg))
182
+ {'test1': 10, 'test': 5, 'test2': [9, '1']}
183
+ """
184
+ merged_output = {}
185
+
186
+ # Create a set of all unique keys from both dictionaries
187
+ all_keys = set(self) | set(other_dict)
188
+
189
+ for k in all_keys:
190
+ # Retrieve values with default fallback
191
+ value_self = self.get(k, default_value)
192
+ value_other = other_dict.get(k, default_value)
193
+
194
+ try:
195
+ # Attempt to apply the operator for existing keys
196
+ merged_output[k] = operator_func(value_self, value_other)
197
+ except TypeError:
198
+ # If a TypeError occurs (e.g., if values are not compatible), store values as a list
199
+ merged_output[k] = [value_self, value_other]
200
+
201
+ return self.__class__(merged_output)
@@ -0,0 +1,79 @@
1
+ """
2
+ Absfuyu: Data Extension
3
+ -----------------------
4
+ Support classes
5
+
6
+ Version: 5.0.0
7
+ Date updated: 22/02/2025 (dd/mm/yyyy)
8
+ """
9
+
10
+ # Module Package
11
+ # ---------------------------------------------------------------------------
12
+ __all__ = ["DictBoolTrue", "DictBoolFalse"]
13
+
14
+
15
+ # Library
16
+ # ---------------------------------------------------------------------------
17
+ from typing import Any
18
+
19
+ from absfuyu.logger import _compress_list_for_print
20
+
21
+
22
+ # Dict Boolean Masking Repr
23
+ # ---------------------------------------------------------------------------
24
+ def _dict_bool(dict_object: dict, option: bool) -> dict | None:
25
+ """
26
+ Support function DictBool class
27
+ """
28
+ out = dict()
29
+ for k, v in dict_object.items():
30
+ if v == option:
31
+ out[k] = v
32
+ if out:
33
+ return out
34
+ else:
35
+ return None
36
+
37
+
38
+ class DictBoolTrue(dict[Any, bool]):
39
+ """Only show items when ``values == True`` in ``__repr__()``"""
40
+
41
+ def __repr__(self) -> str:
42
+ temp = self.copy()
43
+ return _dict_bool(temp, True).__repr__()
44
+
45
+
46
+ class DictBoolFalse(dict[Any, bool]):
47
+ """Only show items when ``values == False`` in ``__repr__()``"""
48
+
49
+ def __repr__(self) -> str:
50
+ temp = self.copy()
51
+ return _dict_bool(temp, False).__repr__()
52
+
53
+
54
+ # ---------------------------------------------------------------------------
55
+ class ListREPR(list):
56
+ """Show ``list`` in shorter form"""
57
+
58
+ def __repr__(self) -> str:
59
+ return _compress_list_for_print(self, 9)
60
+
61
+
62
+ class ListNoDunder(list[str]):
63
+ """Use with ``object.__dir__()``"""
64
+
65
+ def __repr__(self) -> str:
66
+ out = [x for x in self if not x.startswith("__")]
67
+ return out.__repr__()
68
+
69
+
70
+ # class DictNoDunder(dict): # W.I.P
71
+ # """Remove dunder methods in ``__repr__()`` of dict"""
72
+
73
+ # def __repr__(self) -> str:
74
+ # temp = self.copy()
75
+ # out = dict()
76
+ # for k, v in temp.items():
77
+ # if not str(k).startswith("__"):
78
+ # out.__setattr__(k, v)
79
+ # return out.__repr__()