absfuyu 5.6.1__py3-none-any.whl → 6.1.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 (102) hide show
  1. absfuyu/__init__.py +5 -3
  2. absfuyu/__main__.py +2 -2
  3. absfuyu/cli/__init__.py +13 -2
  4. absfuyu/cli/audio_group.py +98 -0
  5. absfuyu/cli/color.py +2 -2
  6. absfuyu/cli/config_group.py +2 -2
  7. absfuyu/cli/do_group.py +2 -2
  8. absfuyu/cli/game_group.py +20 -2
  9. absfuyu/cli/tool_group.py +68 -4
  10. absfuyu/config/__init__.py +3 -3
  11. absfuyu/core/__init__.py +10 -6
  12. absfuyu/core/baseclass.py +104 -34
  13. absfuyu/core/baseclass2.py +43 -2
  14. absfuyu/core/decorator.py +2 -2
  15. absfuyu/core/docstring.py +4 -2
  16. absfuyu/core/dummy_cli.py +3 -3
  17. absfuyu/core/dummy_func.py +2 -2
  18. absfuyu/dxt/__init__.py +2 -2
  19. absfuyu/dxt/base_type.py +93 -0
  20. absfuyu/dxt/dictext.py +188 -6
  21. absfuyu/dxt/dxt_support.py +2 -2
  22. absfuyu/dxt/intext.py +72 -4
  23. absfuyu/dxt/listext.py +495 -23
  24. absfuyu/dxt/strext.py +2 -2
  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 +2 -2
  31. absfuyu/extra/da/__init__.py +39 -3
  32. absfuyu/extra/da/dadf.py +458 -29
  33. absfuyu/extra/da/dadf_base.py +2 -2
  34. absfuyu/extra/da/df_func.py +89 -5
  35. absfuyu/extra/da/mplt.py +2 -2
  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 +4 -6
  45. absfuyu/extra/rclone.py +253 -0
  46. absfuyu/extra/xml.py +90 -0
  47. absfuyu/fun/__init__.py +2 -20
  48. absfuyu/fun/rubik.py +2 -2
  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 -2
  55. absfuyu/game/wordle.py +6 -4
  56. absfuyu/general/__init__.py +2 -2
  57. absfuyu/general/content.py +2 -2
  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 +2 -2
  72. absfuyu/tools/checksum.py +119 -4
  73. absfuyu/tools/converter.py +2 -2
  74. absfuyu/tools/generator.py +24 -7
  75. absfuyu/tools/inspector.py +2 -2
  76. absfuyu/tools/keygen.py +2 -2
  77. absfuyu/tools/obfuscator.py +2 -2
  78. absfuyu/tools/passwordlib.py +2 -2
  79. absfuyu/tools/shutdownizer.py +3 -8
  80. absfuyu/tools/sw.py +213 -10
  81. absfuyu/tools/web.py +10 -13
  82. absfuyu/typings.py +5 -8
  83. absfuyu/util/__init__.py +31 -2
  84. absfuyu/util/api.py +7 -4
  85. absfuyu/util/cli.py +119 -0
  86. absfuyu/util/gui.py +91 -0
  87. absfuyu/util/json_method.py +2 -2
  88. absfuyu/util/lunar.py +2 -2
  89. absfuyu/util/package.py +124 -0
  90. absfuyu/util/path.py +313 -4
  91. absfuyu/util/performance.py +2 -2
  92. absfuyu/util/shorten_number.py +206 -13
  93. absfuyu/util/text_table.py +2 -2
  94. absfuyu/util/zipped.py +2 -2
  95. absfuyu/version.py +22 -19
  96. {absfuyu-5.6.1.dist-info → absfuyu-6.1.3.dist-info}/METADATA +37 -8
  97. absfuyu-6.1.3.dist-info/RECORD +105 -0
  98. {absfuyu-5.6.1.dist-info → absfuyu-6.1.3.dist-info}/WHEEL +1 -1
  99. absfuyu/extra/data_analysis.py +0 -21
  100. absfuyu-5.6.1.dist-info/RECORD +0 -79
  101. {absfuyu-5.6.1.dist-info → absfuyu-6.1.3.dist-info}/entry_points.txt +0 -0
  102. {absfuyu-5.6.1.dist-info → absfuyu-6.1.3.dist-info}/licenses/LICENSE +0 -0
absfuyu/fun/rubik.py CHANGED
@@ -3,8 +3,8 @@ Absfuyu: Fun
3
3
  ------------
4
4
  Rubik
5
5
 
6
- Version: 5.6.1
7
- Date updated: 12/09/2025 (dd/mm/yyyy)
6
+ Version: 6.1.2
7
+ Date updated: 30/12/2025 (dd/mm/yyyy)
8
8
 
9
9
 
10
10
  Version added: 5.4.0
absfuyu/fun/tarot.py CHANGED
@@ -4,8 +4,8 @@ Absfuyu: Tarot
4
4
  Tarot stuff
5
5
 
6
6
 
7
- Version: 5.6.1
8
- Date updated: 12/09/2025 (dd/mm/yyyy)
7
+ Version: 6.1.2
8
+ Date updated: 30/12/2025 (dd/mm/yyyy)
9
9
 
10
10
  Usage:
11
11
  ------
absfuyu/game/__init__.py CHANGED
@@ -3,8 +3,8 @@ Absfuyu: Game
3
3
  -------------
4
4
  Contain some game that can be played on terminal
5
5
 
6
- Version: 5.6.1
7
- Date updated: 12/09/2025 (dd/mm/yyyy)
6
+ Version: 6.1.2
7
+ Date updated: 30/12/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module level
absfuyu/game/game_stat.py CHANGED
@@ -1,8 +1,8 @@
1
1
  """
2
2
  Game: Game Stat
3
3
 
4
- Version: 5.6.1
5
- Date updated: 12/09/2025 (dd/mm/yyyy)
4
+ Version: 6.1.2
5
+ Date updated: 30/12/2025 (dd/mm/yyyy)
6
6
  """
7
7
 
8
8
  # Module level
@@ -0,0 +1,78 @@
1
+ """
2
+ Game: Schulte
3
+ -------------
4
+
5
+ Version: 6.1.2
6
+ Date updated: 30/12/2025 (dd/mm/yyyy)
7
+ """
8
+
9
+ # Module level
10
+ # ---------------------------------------------------------------------------
11
+ __all__ = ["SchulteTable"]
12
+
13
+
14
+ # Library
15
+ # ---------------------------------------------------------------------------
16
+ from absfuyu.core.baseclass import BaseClass
17
+ from absfuyu.dxt import ListExt
18
+ from absfuyu.util.text_table import BoxStyle, get_box_drawing_character
19
+
20
+
21
+ # Function
22
+ # ---------------------------------------------------------------------------
23
+ def draw_grid(data: list[list[int]], style: BoxStyle = "normal"):
24
+ chars = get_box_drawing_character(style=style)
25
+ rows = len(data)
26
+ cols = len(data[0])
27
+
28
+ # find max width for padding
29
+ cell_width = max(len(str(x)) for row in data for x in row) + 2
30
+
31
+ def horizontal_border(left: str, middle: str, right: str) -> str:
32
+ return left + (chars.HORIZONTAL * cell_width + middle) * (cols - 1) + chars.HORIZONTAL * cell_width + right
33
+
34
+ # top border
35
+ print(horizontal_border(chars.UPPER_LEFT_CORNER, chars.HORIZONTAL_DOWN, chars.UPPER_RIGHT_CORNER))
36
+
37
+ for i, row in enumerate(data):
38
+ # content line
39
+ line = chars.VERTICAL + "".join(f"{str(val):^{cell_width}}" + chars.VERTICAL for val in row)
40
+ print(line)
41
+
42
+ # middle or bottom border
43
+ if i < rows - 1:
44
+ print(horizontal_border(chars.VERTICAL_RIGHT, chars.CROSS, chars.VERTICAL_LEFT))
45
+ else:
46
+ print(horizontal_border(chars.LOWER_LEFT_CORNER, chars.HORIZONTAL_UP, chars.LOWER_RIGHT_CORNER))
47
+
48
+
49
+ # Class
50
+ # ---------------------------------------------------------------------------
51
+ class SchulteTable(BaseClass):
52
+ """
53
+ A Schulte Table is a cognitive training tool consisting of a grid filled
54
+ with randomly placed numbers. The task is to find and select all the numbers
55
+ in ascending order as quickly as possible. This exercise helps improve
56
+ visual attention, focus, processing speed, mental flexibility,
57
+ and peripheral vision.
58
+ """
59
+
60
+ def __init__(self, size: int = 5) -> None:
61
+ self.size = max(size, 1)
62
+
63
+ def make_table(self) -> None:
64
+ data = ListExt(range(1, self.size**2 + 1)).shuffle().split_chunk(self.size)
65
+ draw_grid(data)
66
+
67
+ # def play(self):
68
+ # """GUI"""
69
+ # from absfuyu.util.gui import CustomTkinterApp
70
+
71
+ # class Schulte(CustomTkinterApp):
72
+ # def __init__(self, title: str | None = None, size: tuple[int, int] | None = None) -> None:
73
+ # super().__init__(title=title, size=size)
74
+
75
+
76
+ if __name__ == "__main__":
77
+ t = SchulteTable(5)
78
+ print(t)
absfuyu/game/sudoku.py CHANGED
@@ -3,8 +3,8 @@ Game: Sudoku
3
3
  ------------
4
4
  Sudoku 9x9 Solver
5
5
 
6
- Version: 5.6.1
7
- Date updated: 12/09/2025 (dd/mm/yyyy)
6
+ Version: 6.1.2
7
+ Date updated: 30/12/2025 (dd/mm/yyyy)
8
8
 
9
9
  Credit:
10
10
  -------
absfuyu/game/tictactoe.py CHANGED
@@ -2,8 +2,8 @@
2
2
  Game: Tic Tac Toe
3
3
  -----------------
4
4
 
5
- Version: 5.6.1
6
- Date updated: 12/09/2025 (dd/mm/yyyy)
5
+ Version: 6.1.2
6
+ Date updated: 30/12/2025 (dd/mm/yyyy)
7
7
  """
8
8
 
9
9
  # Module level
absfuyu/game/wordle.py CHANGED
@@ -2,8 +2,8 @@
2
2
  Game: Wordle Solver
3
3
  -------------------
4
4
 
5
- Version: 5.6.1
6
- Date updated: 12/09/2025 (dd/mm/yyyy)
5
+ Version: 6.1.2
6
+ Date updated: 30/12/2025 (dd/mm/yyyy)
7
7
 
8
8
  Usage:
9
9
  ------
@@ -27,8 +27,6 @@ import string
27
27
  from collections import Counter
28
28
  from itertools import chain
29
29
 
30
- import requests
31
-
32
30
  # Class
33
31
  # ---------------------------------------------------------------------------
34
32
  OFFLINE_WORDS = """\
@@ -123,6 +121,8 @@ class Wordle:
123
121
  Try to fetch words list from online source
124
122
  """
125
123
  try:
124
+ import requests
125
+
126
126
  dict_link = "https://raw.githubusercontent.com/dwyl/english-words/master/words_dictionary.json"
127
127
  res = requests.get(dict_link)
128
128
  word_list: list[str] = list(res.json().keys())
@@ -134,6 +134,8 @@ class Wordle:
134
134
  and set(word) < self._ALLOWABLE_CHARACTERS
135
135
  }
136
136
  )
137
+ except ImportError:
138
+ raise ImportError("Please install requests package")
137
139
  except Exception:
138
140
  pass
139
141
 
@@ -3,8 +3,8 @@ Absfuyu: General
3
3
  ----------------
4
4
  Collection of useful classes
5
5
 
6
- Version: 5.6.1
7
- Date updated: 12/09/2025 (dd/mm/yyyy)
6
+ Version: 6.1.2
7
+ Date updated: 30/12/2025 (dd/mm/yyyy)
8
8
 
9
9
  Features:
10
10
  ---------
@@ -3,8 +3,8 @@ Absfuyu: Content
3
3
  ----------------
4
4
  Handle .txt file
5
5
 
6
- Version: 5.6.1
7
- Date updated: 12/09/2025 (dd/mm/yyyy)
6
+ Version: 6.1.2
7
+ Date updated: 30/12/2025 (dd/mm/yyyy)
8
8
 
9
9
  Usage:
10
10
  ------
absfuyu/general/human.py CHANGED
@@ -3,8 +3,8 @@ Absfuyu: Human
3
3
  --------------
4
4
  Human related stuff
5
5
 
6
- Version: 5.6.1
7
- Date updated: 12/09/2025 (dd/mm/yyyy)
6
+ Version: 6.1.2
7
+ Date updated: 30/12/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module level
@@ -0,0 +1,213 @@
1
+ """
2
+ Absfuyu: Relative resolution
3
+ ----------------------------
4
+ Relative resolution
5
+
6
+ Use with screen resolution getter like ``tkinter``, ``ctypes``, ``screeninfo`` is recommended
7
+
8
+ Version: 6.1.2
9
+ Date updated: 30/12/2025 (dd/mm/yyyy)
10
+ """
11
+
12
+ # Module level
13
+ # ---------------------------------------------------------------------------
14
+ __all__ = ["RelativeResoluton", "RelativeResolutonTranslater"]
15
+
16
+
17
+ # Library
18
+ # ---------------------------------------------------------------------------
19
+ from fractions import Fraction
20
+ from typing import Self, overload
21
+
22
+ from absfuyu.core.baseclass import BaseClass
23
+
24
+
25
+ # Class
26
+ # ---------------------------------------------------------------------------
27
+ class RelativeResoluton(BaseClass):
28
+ def __init__(self, x: int, y: int) -> None:
29
+ """
30
+ Resolution
31
+
32
+ Parameters
33
+ ----------
34
+ x : int
35
+ Normally width
36
+
37
+ y : int
38
+ Normally height
39
+
40
+ Raises
41
+ ------
42
+ ValueError
43
+ When x or y < 1
44
+ """
45
+ if x < 1 or y < 1:
46
+ raise ValueError("Resolution must be >= 1")
47
+
48
+ self.x = x
49
+ self.y = y
50
+
51
+ @property
52
+ def ratio(self) -> Fraction:
53
+ """
54
+ Ratio of the resolution
55
+ """
56
+ return Fraction(self.x, self.y)
57
+
58
+ def scale_by(self, by: int | float | Fraction, /) -> Self:
59
+ """
60
+ Scale the resolution by an amount
61
+
62
+ Parameters
63
+ ----------
64
+ by : int | float | Fraction
65
+ Amount to scale
66
+
67
+ Returns
68
+ -------
69
+ Self
70
+ New scaled resolution
71
+ """
72
+ if isinstance(by, Fraction):
73
+ x = int(self.x * by.numerator / by.denominator)
74
+ y = int(self.y * by.numerator / by.denominator)
75
+ else:
76
+ x = int(self.x * by)
77
+ y = int(self.y * by)
78
+ return self.__class__(x, y)
79
+
80
+ @overload
81
+ def get_point_relative(self, x: int, y: int, /) -> tuple[Fraction, Fraction]: ...
82
+ @overload
83
+ def get_point_relative(self, x: int, y: int, /, *, strict: bool = True) -> tuple[Fraction, Fraction]: ...
84
+ def get_point_relative(self, x: int, y: int, /, *, strict: bool = True) -> tuple[Fraction, Fraction]:
85
+ """
86
+ Get relative point from fixed point.
87
+
88
+ Parameters
89
+ ----------
90
+ x : int
91
+ Normally width
92
+
93
+ y : int
94
+ Normally height
95
+
96
+ strict : bool, optional
97
+ Convert ``x`` and ``y`` into type int first, by default ``True``
98
+
99
+ Returns
100
+ -------
101
+ tuple[Fraction, Fraction]
102
+ Relative point
103
+ """
104
+ if strict:
105
+ x = int(x)
106
+ y = int(y)
107
+ x_rel = Fraction(x, self.x)
108
+ y_rel = Fraction(y, self.y)
109
+ return x_rel, y_rel
110
+
111
+ def get_fixed_point(self, x_rel: Fraction, y_rel: Fraction, /) -> tuple[int, int]:
112
+ """
113
+ Get fixed point from relative point.
114
+
115
+ Parameters
116
+ ----------
117
+ x_rel : Fraction
118
+ Normally width
119
+
120
+ y_rel : Fraction
121
+ Normally height
122
+
123
+ Returns
124
+ -------
125
+ tuple[int, int]
126
+ Fixed point
127
+ """
128
+ x = int(self.x * x_rel.numerator / x_rel.denominator)
129
+ y = int(self.y * y_rel.numerator / y_rel.denominator)
130
+ return x, y
131
+
132
+
133
+ class RelativeResolutonTranslater(RelativeResoluton):
134
+ """
135
+ Relative resolution translater
136
+
137
+ It is recommended to use with screen resolution getter like
138
+ ``tkinter``, ``ctypes``, ``screeninfo``, ``pyautogui``
139
+
140
+
141
+ Example:
142
+ --------
143
+ >>> import tkinter as tk
144
+ >>> root = tk.Tk()
145
+ >>> width, height = root.winfo_screenwidth(), root.winfo_screenheight()
146
+ >>> rr = RelativeResolutonTranslater(width, height)
147
+ >>> rr.add_target_scale((1920, 1080))
148
+ >>> rr.t(1280, 720)
149
+
150
+ >>> import tkinter as tk
151
+ >>> root = tk.Tk()
152
+ >>> width, height = root.winfo_screenwidth(), root.winfo_screenheight()
153
+ >>> rr = RelativeResolutonTranslater(1920, 1080)
154
+ >>> rr.add_target_scale((width, height))
155
+ >>> rr.t(1280, 720)
156
+ """
157
+
158
+ def __init__(self, x: int, y: int) -> None:
159
+ super().__init__(x, y)
160
+ self._target_scale = Fraction(1, 1)
161
+
162
+ @overload
163
+ def add_target_scale(self, target: int | float, /) -> None: ...
164
+ @overload
165
+ def add_target_scale(self, target: Fraction, /) -> None: ...
166
+ @overload
167
+ def add_target_scale(self, target: tuple[int, int], /) -> None: ...
168
+ def add_target_scale(self, target: tuple[int, int] | Fraction | int | float, /) -> None:
169
+ """
170
+ Add target scale to scale resolution to
171
+
172
+ Parameters
173
+ ----------
174
+ target : tuple[int, int] | Fraction | int | float
175
+ Target scale (tuple[int, int] for desire resolution)
176
+
177
+ Raises
178
+ ------
179
+ NotImplementedError
180
+ When ratio of new and old resolution is not equal
181
+ """
182
+ if isinstance(target, tuple): # Resolution
183
+ if self.ratio == Fraction(*target): # Same ratio
184
+ self._target_scale = Fraction(target[0] / self.x)
185
+ else:
186
+ raise NotImplementedError("Resolution's ratio conversion not supported")
187
+ else:
188
+ self._target_scale = Fraction(target)
189
+
190
+ def translate_point(self, x: int, y: int, /) -> tuple[int, int]:
191
+ """
192
+ Translate point(x, y) to target_scale fixed point through relative point.
193
+
194
+ Parameters
195
+ ----------
196
+ x : int
197
+ Normally width
198
+
199
+ y : int
200
+ Normally height
201
+
202
+ Returns
203
+ -------
204
+ tuple[int, int]
205
+ Translated point
206
+ """
207
+ x_rel, y_rel = self.get_point_relative(x, y)
208
+ fixed_point = self.scale_by(self._target_scale).get_fixed_point(x_rel, y_rel)
209
+ return fixed_point
210
+
211
+ def t(self, x: int, y: int, /) -> tuple[int, int]:
212
+ """Wrapper for self.translate_point"""
213
+ return self.translate_point(x, y)
absfuyu/general/shape.py CHANGED
@@ -3,8 +3,8 @@ Absfuyu: Shape
3
3
  --------------
4
4
  Shapes
5
5
 
6
- Version: 5.6.1
7
- Date updated: 12/09/2025 (dd/mm/yyyy)
6
+ Version: 6.1.2
7
+ Date updated: 30/12/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module level
@@ -33,12 +33,7 @@ __all__ = [
33
33
  # ---------------------------------------------------------------------------
34
34
  import math
35
35
  from abc import ABC, abstractmethod
36
- from typing import ClassVar, Self
37
-
38
- try:
39
- from typing import override # type: ignore
40
- except ImportError:
41
- from absfuyu.core.decorator import dummy_decorator as override
36
+ from typing import ClassVar, Self, override
42
37
 
43
38
  from absfuyu.core import BaseClass
44
39