absfuyu 5.12.1__py3-none-any.whl → 5.13.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 (84) hide show
  1. absfuyu/__init__.py +1 -1
  2. absfuyu/__main__.py +1 -1
  3. absfuyu/cli/__init__.py +1 -1
  4. absfuyu/cli/color.py +1 -1
  5. absfuyu/cli/config_group.py +1 -1
  6. absfuyu/cli/do_group.py +1 -1
  7. absfuyu/cli/game_group.py +1 -1
  8. absfuyu/cli/tool_group.py +18 -4
  9. absfuyu/config/__init__.py +1 -1
  10. absfuyu/core/__init__.py +1 -1
  11. absfuyu/core/baseclass.py +1 -1
  12. absfuyu/core/baseclass2.py +1 -1
  13. absfuyu/core/decorator.py +1 -1
  14. absfuyu/core/docstring.py +1 -1
  15. absfuyu/core/dummy_cli.py +1 -1
  16. absfuyu/core/dummy_func.py +1 -1
  17. absfuyu/dxt/__init__.py +1 -1
  18. absfuyu/dxt/base_type.py +93 -0
  19. absfuyu/dxt/dictext.py +8 -6
  20. absfuyu/dxt/dxt_support.py +1 -1
  21. absfuyu/dxt/intext.py +76 -3
  22. absfuyu/dxt/listext.py +1 -1
  23. absfuyu/dxt/strext.py +1 -1
  24. absfuyu/extra/__init__.py +1 -1
  25. absfuyu/extra/beautiful.py +1 -1
  26. absfuyu/extra/da/__init__.py +1 -1
  27. absfuyu/extra/da/dadf.py +1 -1
  28. absfuyu/extra/da/dadf_base.py +1 -1
  29. absfuyu/extra/da/df_func.py +1 -1
  30. absfuyu/extra/da/mplt.py +1 -1
  31. absfuyu/extra/data_analysis.py +1 -1
  32. absfuyu/extra/pdf.py +1 -1
  33. absfuyu/extra/picture.py +386 -0
  34. absfuyu/extra/rclone.py +1 -1
  35. absfuyu/extra/xml.py +1 -1
  36. absfuyu/fun/__init__.py +1 -1
  37. absfuyu/fun/rubik.py +1 -1
  38. absfuyu/fun/tarot.py +1 -1
  39. absfuyu/game/__init__.py +1 -1
  40. absfuyu/game/game_stat.py +1 -1
  41. absfuyu/game/schulte.py +1 -1
  42. absfuyu/game/sudoku.py +1 -1
  43. absfuyu/game/tictactoe.py +1 -1
  44. absfuyu/game/wordle.py +1 -1
  45. absfuyu/general/__init__.py +1 -1
  46. absfuyu/general/content.py +1 -1
  47. absfuyu/general/human.py +1 -1
  48. absfuyu/general/shape.py +1 -1
  49. absfuyu/general/tax.py +1 -1
  50. absfuyu/logger.py +1 -1
  51. absfuyu/pkg_data/__init__.py +1 -1
  52. absfuyu/pkg_data/deprecated.py +1 -1
  53. absfuyu/pkg_data/logo.py +1 -1
  54. absfuyu/sort.py +1 -1
  55. absfuyu/tools/__init__.py +1 -1
  56. absfuyu/tools/checksum.py +1 -1
  57. absfuyu/tools/converter.py +1 -1
  58. absfuyu/tools/generator.py +24 -7
  59. absfuyu/tools/inspector.py +1 -1
  60. absfuyu/tools/keygen.py +1 -1
  61. absfuyu/tools/obfuscator.py +1 -1
  62. absfuyu/tools/passwordlib.py +1 -1
  63. absfuyu/tools/shutdownizer.py +1 -1
  64. absfuyu/tools/sw.py +1 -1
  65. absfuyu/tools/web.py +1 -1
  66. absfuyu/typings.py +1 -1
  67. absfuyu/util/__init__.py +1 -1
  68. absfuyu/util/api.py +1 -1
  69. absfuyu/util/cli.py +1 -1
  70. absfuyu/util/gui.py +1 -1
  71. absfuyu/util/json_method.py +1 -1
  72. absfuyu/util/lunar.py +1 -1
  73. absfuyu/util/path.py +1 -1
  74. absfuyu/util/performance.py +1 -1
  75. absfuyu/util/shorten_number.py +1 -1
  76. absfuyu/util/text_table.py +1 -1
  77. absfuyu/util/zipped.py +1 -1
  78. absfuyu/version.py +1 -1
  79. {absfuyu-5.12.1.dist-info → absfuyu-5.13.0.dist-info}/METADATA +10 -1
  80. absfuyu-5.13.0.dist-info/RECORD +88 -0
  81. absfuyu-5.12.1.dist-info/RECORD +0 -86
  82. {absfuyu-5.12.1.dist-info → absfuyu-5.13.0.dist-info}/WHEEL +0 -0
  83. {absfuyu-5.12.1.dist-info → absfuyu-5.13.0.dist-info}/entry_points.txt +0 -0
  84. {absfuyu-5.12.1.dist-info → absfuyu-5.13.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,386 @@
1
+ """
2
+ Absfuyu: Picture
3
+ ----------------
4
+ Image converter
5
+
6
+
7
+ Version: 5.13.0
8
+ Date updated: 02/11/2025 (dd/mm/yyyy)
9
+ """
10
+
11
+ # Module level
12
+ # ---------------------------------------------------------------------------
13
+ __all__ = ["ImgConverter"]
14
+
15
+
16
+ # Library
17
+ # ---------------------------------------------------------------------------
18
+ import logging
19
+ import shutil
20
+ from functools import partial
21
+ from pathlib import Path
22
+ from typing import Any, Literal, Protocol
23
+
24
+ from absfuyu.core.dummy_func import tqdm as tqdm_base
25
+ from absfuyu.util.path import DirectorySelectMixin
26
+
27
+ try:
28
+ from PIL import Image
29
+ from PIL.ImageFile import ImageFile
30
+ except ImportError:
31
+ from subprocess import run
32
+
33
+ from absfuyu.config import ABSFUYU_CONFIG
34
+
35
+ if ABSFUYU_CONFIG._get_setting("auto-install-extra").value: # type: ignore
36
+ cmd = "python -m pip install -U absfuyu[pic]".split()
37
+ run(cmd)
38
+ else:
39
+ raise SystemExit("This feature is in absfuyu[pic] package") # noqa: B904
40
+
41
+ try:
42
+ from pillow_heif import register_heif_opener # type: ignore
43
+ except ImportError:
44
+ from absfuyu.core.dummy_func import dummy_function as register_heif_opener
45
+ register_heif_opener()
46
+
47
+
48
+ # Setup
49
+ # ---------------------------------------------------------------------------
50
+ tqdm = partial(tqdm_base, unit_scale=True, dynamic_ncols=True)
51
+ SupportedImageExtension = Literal[".jpg", ".jpeg", ".png", ".webp"]
52
+
53
+
54
+ # Exporter/Converter
55
+ # ---------------------------------------------------------------------------
56
+ class SupportImageConverter(Protocol):
57
+ # Callable[[ImageFile, Path], None]
58
+ def __call__(self, image: ImageFile, path: Path, **params: Any) -> None: ...
59
+
60
+
61
+ def _image_convert_default(image: ImageFile, path: Path, **params: Any) -> None:
62
+ """
63
+ Default convert image function
64
+
65
+ Parameters
66
+ ----------
67
+ image : ImageFile
68
+ Image file
69
+
70
+ path : Path
71
+ Path to export
72
+ """
73
+ image.save(path, **params)
74
+
75
+
76
+ def _image_convert_webp(image: ImageFile, path: Path, **params: Any) -> None:
77
+ """
78
+ Convert image to .webp format (with custom settings)
79
+
80
+ Parameters
81
+ ----------
82
+ image : ImageFile
83
+ Image file
84
+
85
+ path : Path
86
+ Path to export
87
+ """
88
+ image.save(
89
+ path,
90
+ format="WEBP",
91
+ lossless=True,
92
+ quality=100,
93
+ alpha_quality=100,
94
+ method=4,
95
+ exact=False, # If true, preserve the transparent RGB values. Otherwise, discard invisible RGB values for better compression. Defaults to false.
96
+ **params,
97
+ )
98
+
99
+
100
+ def _image_convert_png(image: ImageFile, path: Path, **params: Any) -> None:
101
+ """
102
+ Convert image to .png format (with custom settings)
103
+
104
+ Parameters
105
+ ----------
106
+ image : ImageFile
107
+ Image file
108
+
109
+ path : Path
110
+ Path to export
111
+ """
112
+ image.save(
113
+ path,
114
+ format="PNG",
115
+ # optimize=True,
116
+ compress_level=6,
117
+ **params,
118
+ )
119
+
120
+
121
+ def _image_convert_jpg(image: ImageFile, path: Path, **params: Any) -> None:
122
+ """
123
+ Convert image to .jpg format (with custom settings)
124
+
125
+ Parameters
126
+ ----------
127
+ image : ImageFile
128
+ Image file
129
+
130
+ path : Path
131
+ Path to export
132
+ """
133
+ image.convert("RGB")
134
+ image.save(
135
+ path,
136
+ format="JPG",
137
+ optimize=True,
138
+ keep_rgb=True,
139
+ **params,
140
+ )
141
+
142
+
143
+ # Class
144
+ # ---------------------------------------------------------------------------
145
+ class ImgConverter(DirectorySelectMixin):
146
+ _IMAGE_CONVERTER: dict[str, SupportImageConverter] = {
147
+ "default": _image_convert_default,
148
+ ".webp": _image_convert_webp,
149
+ ".png": _image_convert_png,
150
+ ".jpg": _image_convert_jpg,
151
+ ".jpeg": _image_convert_jpg,
152
+ }
153
+
154
+ def __init__(
155
+ self,
156
+ source_path: str | Path,
157
+ create_if_not_exist: bool = False,
158
+ backup_dir_name: str | None = None,
159
+ logger: logging.Logger | None = None,
160
+ ) -> None:
161
+ super().__init__(source_path, create_if_not_exist)
162
+
163
+ # Supported image extension
164
+ self._supported_image_format = [".png", ".jpeg", ".jpg", ".webp"]
165
+ self._register_heif_format()
166
+
167
+ # Backup
168
+ if backup_dir_name is None:
169
+ backup_dir_name = "ZZZ_Backup"
170
+ self.backup_path = self.source_path.joinpath(backup_dir_name)
171
+
172
+ # Not available yet
173
+ self.logger = logger
174
+
175
+ # Extra format
176
+ @classmethod
177
+ def install_all_extension(cls) -> None:
178
+ """
179
+ Install all extra package to unlock all features
180
+ """
181
+ extra = [
182
+ "pillow_heif", # heic support
183
+ "defusedxml", # xmp
184
+ "olefile",
185
+ ]
186
+ base = ["pip", "install", "-U"]
187
+ base.extend(extra)
188
+
189
+ import subprocess
190
+
191
+ subprocess.run(base)
192
+
193
+ def _register_heif_format(self) -> None:
194
+ """
195
+ Try to register .heif format
196
+
197
+ ``pillow_heif`` package required
198
+ """
199
+ try:
200
+ from pillow_heif import register_heif_opener # type: ignore
201
+
202
+ self._supported_image_format.append(".heic")
203
+ self._supported_image_format.append(".heif")
204
+ except ImportError:
205
+ pass
206
+
207
+ @property
208
+ def supported_image_format(self) -> list[str]:
209
+ """
210
+ Supported image format
211
+
212
+ Returns
213
+ -------
214
+ list[str]
215
+ Supported image format
216
+ """
217
+ return self._supported_image_format
218
+
219
+ @classmethod
220
+ def add_converter(cls, format_name: str, converter_func: SupportImageConverter) -> None:
221
+ """
222
+ Add image converter function to a format
223
+
224
+ Parameters
225
+ ----------
226
+ format_name : str
227
+ Image format name
228
+
229
+ converter_func : SupportImageConverter
230
+ Converter function
231
+
232
+
233
+ Example:
234
+ --------
235
+ >>> ImgConverter.add_converter(".png", convert_to_png)
236
+ """
237
+ cls._IMAGE_CONVERTER[format_name] = converter_func
238
+
239
+ # Support
240
+ def _make_suffix_selection(self, exclude_suffix: str) -> tuple[str, ...]:
241
+ """
242
+ Make suffix selection (exclude the image with converted to suffix)
243
+
244
+ Parameters
245
+ ----------
246
+ exclude_suffix : str
247
+ Converted to suffix
248
+
249
+ Returns
250
+ -------
251
+ tuple[str, ...]
252
+ Suffix selection
253
+ """
254
+ out = []
255
+ for x in self._supported_image_format:
256
+ if x.lower() == exclude_suffix.lower():
257
+ continue
258
+ out.append(x.lower())
259
+ out.append(x.upper())
260
+ return tuple(out)
261
+
262
+ def _make_backup(self, src_file: Path) -> None:
263
+ dest = self.backup_path.joinpath(src_file.name)
264
+ shutil.move(src_file, dest)
265
+
266
+ # Convert
267
+ def _image_convert_legacy(
268
+ self,
269
+ path: Path,
270
+ to_extension: SupportedImageExtension | None = None,
271
+ lossless: bool = True,
272
+ compression_level: int | None = None,
273
+ ) -> None:
274
+ """
275
+ Convert image to other format (settings are mostly for .webp format)
276
+
277
+ Parameters
278
+ ----------
279
+ path : Path
280
+ Path to image
281
+
282
+ to_extension : SupportedImageExtension | None, optional
283
+ New image format, by default None
284
+
285
+ lossless : bool, optional
286
+ Lossless compression, by default True
287
+
288
+ compression_level : int | None, optional
289
+ Compression level, by default None
290
+ """
291
+ # Load image
292
+ new_suffix = path.suffix if to_extension is None else to_extension
293
+ image = Image.open(path)
294
+
295
+ # Extract metadata
296
+ # exif = image.info.get("exif")
297
+ # xmp = image.getxmp()
298
+ # icc_profile = image.info.get("icc_profile")
299
+ xmp = image.info.get("xmp")
300
+ exif = image.getexif()
301
+ icc_profile = image.info.get("icc_profile")
302
+ # print(image.info.keys())
303
+
304
+ # Save
305
+ image.save(
306
+ path.with_suffix(new_suffix),
307
+ format=new_suffix[1:].upper(),
308
+ lossless=lossless,
309
+ quality=100,
310
+ alpha_quality=100,
311
+ method=(4 if compression_level is None else compression_level),
312
+ exact=False, # If true, preserve the transparent RGB values. Otherwise, discard invisible RGB values for better compression. Defaults to false.
313
+ exif=exif,
314
+ icc_profile=icc_profile,
315
+ xmp=xmp,
316
+ )
317
+
318
+ def _image_convert(
319
+ self,
320
+ path: Path,
321
+ to_extension: str | None = None,
322
+ ) -> None:
323
+ """
324
+ Convert image to other format
325
+
326
+ Parameters
327
+ ----------
328
+ path : Path
329
+ Path to image
330
+
331
+ to_extension : SupportedImageExtension | None, optional
332
+ New image format, by default None
333
+ """
334
+ # Load image
335
+ new_suffix = path.suffix if to_extension is None else to_extension
336
+ image = Image.open(path)
337
+
338
+ # Extract metadata
339
+ xmp = image.info.get("xmp")
340
+ exif = image.getexif()
341
+ icc_profile = image.info.get("icc_profile")
342
+
343
+ # Save
344
+ convert_func = self._IMAGE_CONVERTER.get(new_suffix, _image_convert_default)
345
+ # self.logger.debug(f"Using {convert_func}")
346
+ convert_func(
347
+ image,
348
+ path.with_suffix(new_suffix),
349
+ exif=exif,
350
+ icc_profile=icc_profile,
351
+ xmp=xmp,
352
+ )
353
+
354
+ def img_convert(self, to_extension: SupportedImageExtension | str, backup: bool = True) -> None:
355
+ """
356
+ Convert images in directory to desire format
357
+
358
+ Parameters
359
+ ----------
360
+ to_extension : SupportedImageExtension
361
+ Format to convert
362
+
363
+ backup : bool
364
+ Move pictures to a backup folder
365
+
366
+ Raises
367
+ ------
368
+ NotImplementedError
369
+ Not supported image format
370
+ """
371
+ if to_extension not in self._supported_image_format:
372
+ raise NotImplementedError("Format not supported")
373
+
374
+ imgs = self.select_all(*self._make_suffix_selection(to_extension))
375
+
376
+ for x in tqdm(imgs, desc=f"Converting to {to_extension}"):
377
+ try:
378
+ self._image_convert(x, to_extension=to_extension)
379
+
380
+ if backup:
381
+ self.backup_path.mkdir(parents=True, exist_ok=True)
382
+ self._make_backup(x)
383
+ except TypeError as err:
384
+ print(f" TYPE ERROR: {x} - {err}")
385
+ except Exception as err:
386
+ print(f" ERROR: {x} - {err}")
absfuyu/extra/rclone.py CHANGED
@@ -3,7 +3,7 @@ Absfuyu: Rclone decrypt
3
3
  -----------------------
4
4
  Rclone decryptor
5
5
 
6
- Version: 5.12.0
6
+ Version: 5.13.0
7
7
  Date updated: 17/10/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
absfuyu/extra/xml.py CHANGED
@@ -3,7 +3,7 @@ Absfuyu: XML
3
3
  ------------
4
4
  XML Tool [W.I.P]
5
5
 
6
- Version: 5.12.0
6
+ Version: 5.13.0
7
7
  Date updated: 17/10/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
absfuyu/fun/__init__.py CHANGED
@@ -3,7 +3,7 @@ Absfuyu: Fun
3
3
  ------------
4
4
  Some fun or weird stuff
5
5
 
6
- Version: 5.12.0
6
+ Version: 5.13.0
7
7
  Date updated: 17/10/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
absfuyu/fun/rubik.py CHANGED
@@ -3,7 +3,7 @@ Absfuyu: Fun
3
3
  ------------
4
4
  Rubik
5
5
 
6
- Version: 5.12.0
6
+ Version: 5.13.0
7
7
  Date updated: 17/10/2025 (dd/mm/yyyy)
8
8
 
9
9
 
absfuyu/fun/tarot.py CHANGED
@@ -4,7 +4,7 @@ Absfuyu: Tarot
4
4
  Tarot stuff
5
5
 
6
6
 
7
- Version: 5.12.0
7
+ Version: 5.13.0
8
8
  Date updated: 17/10/2025 (dd/mm/yyyy)
9
9
 
10
10
  Usage:
absfuyu/game/__init__.py CHANGED
@@ -3,7 +3,7 @@ Absfuyu: Game
3
3
  -------------
4
4
  Contain some game that can be played on terminal
5
5
 
6
- Version: 5.12.0
6
+ Version: 5.13.0
7
7
  Date updated: 17/10/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
absfuyu/game/game_stat.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
2
  Game: Game Stat
3
3
 
4
- Version: 5.12.0
4
+ Version: 5.13.0
5
5
  Date updated: 17/10/2025 (dd/mm/yyyy)
6
6
  """
7
7
 
absfuyu/game/schulte.py CHANGED
@@ -2,7 +2,7 @@
2
2
  Game: Schulte
3
3
  -------------
4
4
 
5
- Version: 5.12.0
5
+ Version: 5.13.0
6
6
  Date updated: 17/10/2025 (dd/mm/yyyy)
7
7
  """
8
8
 
absfuyu/game/sudoku.py CHANGED
@@ -3,7 +3,7 @@ Game: Sudoku
3
3
  ------------
4
4
  Sudoku 9x9 Solver
5
5
 
6
- Version: 5.12.0
6
+ Version: 5.13.0
7
7
  Date updated: 17/10/2025 (dd/mm/yyyy)
8
8
 
9
9
  Credit:
absfuyu/game/tictactoe.py CHANGED
@@ -2,7 +2,7 @@
2
2
  Game: Tic Tac Toe
3
3
  -----------------
4
4
 
5
- Version: 5.12.0
5
+ Version: 5.13.0
6
6
  Date updated: 17/10/2025 (dd/mm/yyyy)
7
7
  """
8
8
 
absfuyu/game/wordle.py CHANGED
@@ -2,7 +2,7 @@
2
2
  Game: Wordle Solver
3
3
  -------------------
4
4
 
5
- Version: 5.12.0
5
+ Version: 5.13.0
6
6
  Date updated: 17/10/2025 (dd/mm/yyyy)
7
7
 
8
8
  Usage:
@@ -3,7 +3,7 @@ Absfuyu: General
3
3
  ----------------
4
4
  Collection of useful classes
5
5
 
6
- Version: 5.12.0
6
+ Version: 5.13.0
7
7
  Date updated: 17/10/2025 (dd/mm/yyyy)
8
8
 
9
9
  Features:
@@ -3,7 +3,7 @@ Absfuyu: Content
3
3
  ----------------
4
4
  Handle .txt file
5
5
 
6
- Version: 5.12.0
6
+ Version: 5.13.0
7
7
  Date updated: 17/10/2025 (dd/mm/yyyy)
8
8
 
9
9
  Usage:
absfuyu/general/human.py CHANGED
@@ -3,7 +3,7 @@ Absfuyu: Human
3
3
  --------------
4
4
  Human related stuff
5
5
 
6
- Version: 5.12.0
6
+ Version: 5.13.0
7
7
  Date updated: 17/10/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
absfuyu/general/shape.py CHANGED
@@ -3,7 +3,7 @@ Absfuyu: Shape
3
3
  --------------
4
4
  Shapes
5
5
 
6
- Version: 5.12.0
6
+ Version: 5.13.0
7
7
  Date updated: 17/10/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
absfuyu/general/tax.py CHANGED
@@ -3,7 +3,7 @@ Absfuyu: Tax calculator
3
3
  -----------------------
4
4
  Tax calculator
5
5
 
6
- Version: 5.12.0
6
+ Version: 5.13.0
7
7
  Date updated: 17/10/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
absfuyu/logger.py CHANGED
@@ -3,7 +3,7 @@ Absfuyu: Logger
3
3
  ---------------
4
4
  Custom Logger Module
5
5
 
6
- Version: 5.12.0
6
+ Version: 5.13.0
7
7
  Date updated: 17/10/2025 (dd/mm/yyyy)
8
8
 
9
9
  Usage:
@@ -3,7 +3,7 @@ Absfuyu: Package data
3
3
  ---------------------
4
4
  Load package data
5
5
 
6
- Version: 5.12.0
6
+ Version: 5.13.0
7
7
  Date updated: 17/10/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
@@ -3,7 +3,7 @@ Absfuyu: Package data
3
3
  ---------------------
4
4
  Deprecated (but might have some use)
5
5
 
6
- Version: 5.12.0
6
+ Version: 5.13.0
7
7
  Date updated: 17/10/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
absfuyu/pkg_data/logo.py CHANGED
@@ -3,7 +3,7 @@ Absfuyu: Logo
3
3
  -------------
4
4
  Absfuyu logo in base64 string for easy access
5
5
 
6
- Version: 5.12.0
6
+ Version: 5.13.0
7
7
  Date updated: 17/10/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
absfuyu/sort.py CHANGED
@@ -3,7 +3,7 @@ Absfuyu: Sort
3
3
  -------------
4
4
  Sort Module
5
5
 
6
- Version: 5.12.0
6
+ Version: 5.13.0
7
7
  Date updated: 17/10/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
absfuyu/tools/__init__.py CHANGED
@@ -3,7 +3,7 @@ Absfuyu: Tools
3
3
  --------------
4
4
  Some useful tools
5
5
 
6
- Version: 5.12.0
6
+ Version: 5.13.0
7
7
  Date updated: 17/10/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
absfuyu/tools/checksum.py CHANGED
@@ -3,7 +3,7 @@ Absufyu: Checksum
3
3
  -----------------
4
4
  Check MD5, SHA256, ...
5
5
 
6
- Version: 5.12.0
6
+ Version: 5.13.0
7
7
  Date updated: 17/10/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
@@ -3,7 +3,7 @@ Absufyu: Converter
3
3
  ------------------
4
4
  Convert stuff
5
5
 
6
- Version: 5.12.0
6
+ Version: 5.13.0
7
7
  Date updated: 17/10/2025 (dd/mm/yyyy)
8
8
 
9
9
  Feature:
@@ -3,8 +3,8 @@ Absfuyu: Generator
3
3
  ------------------
4
4
  This generate stuff (Not python's ``generator``)
5
5
 
6
- Version: 5.12.0
7
- Date updated: 17/10/2025 (dd/mm/yyyy)
6
+ Version: 5.13.0
7
+ Date updated: 28/10/2025 (dd/mm/yyyy)
8
8
 
9
9
  Features:
10
10
  ---------
@@ -25,7 +25,7 @@ import string
25
25
  from collections.abc import Collection, Sequence
26
26
  from itertools import chain, combinations
27
27
  from random import choice
28
- from typing import TypeVar, cast, overload
28
+ from typing import Literal, TypeVar, cast, overload
29
29
 
30
30
  from absfuyu.core.baseclass import GetClassMembersMixin
31
31
  from absfuyu.core.docstring import deprecated
@@ -78,6 +78,25 @@ class Generator(GetClassMembersMixin):
78
78
  """
79
79
 
80
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
+
81
100
  @staticmethod
82
101
  @deprecated("5.2.0", reason="Use generate_string2() instead.")
83
102
  def generate_string(
@@ -86,7 +105,7 @@ class Generator(GetClassMembersMixin):
86
105
  times: int = 1,
87
106
  unique: bool = False,
88
107
  string_type_if_1: bool = False,
89
- ):
108
+ ) -> str | list[str]:
90
109
  """
91
110
  Generate a list of random string from character set (Random string generator).
92
111
  Deprecated
@@ -394,9 +413,7 @@ class Generator(GetClassMembersMixin):
394
413
 
395
414
  @overload
396
415
  @staticmethod
397
- def combinations_range(
398
- collection: Collection[T], *, min_len: int = 1, max_len: int = 0
399
- ) -> list[tuple[T, ...]]: ...
416
+ def combinations_range(collection: Collection[T], *, min_len: int = 1, max_len: int = 0) -> list[tuple[T, ...]]: ...
400
417
 
401
418
  @staticmethod
402
419
  def combinations_range(