absfuyu 5.6.1__py3-none-any.whl → 6.1.2__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 +436 -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.2.dist-info}/METADATA +37 -8
  97. absfuyu-6.1.2.dist-info/RECORD +105 -0
  98. {absfuyu-5.6.1.dist-info → absfuyu-6.1.2.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.2.dist-info}/entry_points.txt +0 -0
  102. {absfuyu-5.6.1.dist-info → absfuyu-6.1.2.dist-info}/licenses/LICENSE +0 -0
absfuyu/typings.py CHANGED
@@ -3,8 +3,8 @@ Absfuyu: Core
3
3
  -------------
4
4
  Pre-defined typing
5
5
 
6
- Version: 5.6.1
7
- Date updated: 12/09/2025 (dd/mm/yyyy)
6
+ Version: 6.1.1
7
+ Date updated: 30/12/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module Package
@@ -33,21 +33,18 @@ __all__ = [
33
33
  from collections.abc import Callable
34
34
  from typing import Any, ParamSpec, Protocol, TypeVar, overload
35
35
 
36
- try:
37
- from typing import override # type: ignore
38
- except ImportError:
39
- from absfuyu.core.decorator import dummy_decorator as override
40
-
41
-
42
36
  # Type
43
37
  # ---------------------------------------------------------------------------
44
38
  # Types where neither is possible are invariant
39
+ # Type safety must be strict
45
40
  T = TypeVar("T") # Type invariant
46
41
  # Type variables that are covariant can be substituted
47
42
  # with a more specific type without causing errors
43
+ # Safe to treat a Box[int] as a Box[object]
48
44
  T_co = TypeVar("T_co", covariant=True) # Type covariant
49
45
  # Type variables that are contravariant can be substituted
50
46
  # with a more general type without causing errors
47
+ # Safe to use a Box[object] where a Box[int] is needed
51
48
  T_contra = TypeVar("T_contra", contravariant=True) # Type contravariant
52
49
 
53
50
  KT = TypeVar("KT")
absfuyu/util/__init__.py CHANGED
@@ -3,8 +3,8 @@ Absufyu: Utilities
3
3
  ------------------
4
4
  Some random utilities
5
5
 
6
- Version: 5.6.1
7
- Date updated: 12/09/2025 (dd/mm/yyyy)
6
+ Version: 6.1.1
7
+ Date updated: 30/12/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module Package
@@ -25,6 +25,7 @@ __all__ = [
25
25
  # Library
26
26
  # ---------------------------------------------------------------------------
27
27
  import pkgutil
28
+ import subprocess
28
29
  from datetime import datetime
29
30
  from string import printable
30
31
 
@@ -257,3 +258,31 @@ def convert_to_raw_unicode(text: str, partial: bool = True) -> str:
257
258
  character if character in character_set and partial else _convert(character)
258
259
  for character in text
259
260
  )
261
+
262
+
263
+ @versionadded("5.9.0")
264
+ def is_command_available(cmd: list[str] | str, err_msg: str = "") -> None:
265
+ """
266
+ Checks if the desired command available
267
+
268
+ Parameters
269
+ ----------
270
+ cmd : list[str] | str
271
+ Command to check
272
+
273
+ err_msg : str, optional
274
+ Custom error message, by default ""
275
+
276
+ Raises
277
+ ------
278
+ ValueError
279
+ When command is unvailable
280
+ """
281
+ try:
282
+ subprocess.run(
283
+ cmd,
284
+ stdout=subprocess.DEVNULL,
285
+ stderr=subprocess.DEVNULL,
286
+ )
287
+ except Exception:
288
+ raise ValueError(err_msg)
absfuyu/util/api.py CHANGED
@@ -3,8 +3,8 @@ Absufyu: API
3
3
  ------------
4
4
  Fetch data stuff
5
5
 
6
- Version: 5.6.1
7
- Date updated: 12/09/2025 (dd/mm/yyyy)
6
+ Version: 6.1.1
7
+ Date updated: 30/12/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module level
@@ -23,12 +23,15 @@ import subprocess
23
23
  from pathlib import Path
24
24
  from typing import NamedTuple
25
25
 
26
- import requests
27
-
28
26
  from absfuyu.core.baseclass import BaseClass
29
27
  from absfuyu.core.docstring import versionadded, versionchanged
30
28
  from absfuyu.logger import logger
31
29
 
30
+ try:
31
+ import requests
32
+ except ImportError:
33
+ raise ImportError("Please install requests package")
34
+
32
35
 
33
36
  # Function
34
37
  # ---------------------------------------------------------------------------
absfuyu/util/cli.py ADDED
@@ -0,0 +1,119 @@
1
+ """
2
+ Absfuyu: CLI
3
+ ------------
4
+ Custom Argument Parser
5
+
6
+ Version: 6.1.1
7
+ Date updated: 30/12/2025 (dd/mm/yyyy)
8
+ """
9
+
10
+ # Module level
11
+ # ---------------------------------------------------------------------------
12
+ __all__ = ["FuyuArgumentParser"]
13
+
14
+
15
+ # Library
16
+ # ---------------------------------------------------------------------------
17
+ import logging
18
+ import sys
19
+ from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser
20
+ from collections.abc import Callable
21
+ from typing import Any
22
+
23
+
24
+ # Class
25
+ # ---------------------------------------------------------------------------
26
+ class FuyuArgumentParser(ArgumentParser):
27
+ """
28
+ Usage:
29
+ ------
30
+ >>> import sys
31
+ >>> args = FuyuArgumentParser()
32
+ >>> args.start()
33
+ """
34
+
35
+ def __init__(
36
+ self,
37
+ prog: str | None = None,
38
+ description: str | None = None,
39
+ epilog: str | None = None,
40
+ version: str = "0.0.1",
41
+ formatter_class: Any = ArgumentDefaultsHelpFormatter,
42
+ prefix_chars: str = "-",
43
+ argument_default: Any = None,
44
+ conflict_handler: str = "error",
45
+ add_help: bool = True,
46
+ allow_abbrev: bool = True,
47
+ exit_on_error: bool = True,
48
+ ) -> None:
49
+ # Desc
50
+ if description is None:
51
+ description = f"Absfuyu CLI {version}"
52
+
53
+ # Default
54
+ self._default_args = ["--help"]
55
+
56
+ # Super
57
+ super().__init__(
58
+ prog=prog,
59
+ description=description,
60
+ epilog=epilog,
61
+ formatter_class=formatter_class,
62
+ prefix_chars=prefix_chars,
63
+ argument_default=argument_default,
64
+ conflict_handler=conflict_handler,
65
+ add_help=add_help,
66
+ allow_abbrev=allow_abbrev,
67
+ exit_on_error=exit_on_error,
68
+ )
69
+
70
+ # Add version
71
+ self.add_argument("-v", "--version", action="version", version=f"%(prog)s {version}")
72
+
73
+ # Add log level
74
+ _ll_val = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
75
+ self.add_argument(
76
+ "-ll",
77
+ "--log-level",
78
+ metavar="LOG_LEVEL",
79
+ dest="log_level",
80
+ choices=_ll_val,
81
+ default="ERROR",
82
+ help=f"Log level: {', '.join(_ll_val)}",
83
+ )
84
+
85
+ def _fuyu_set_log_level(self, log_level: str = "ERROR") -> None:
86
+ log_levels = {
87
+ "DEBUG": logging.DEBUG,
88
+ "INFO": logging.INFO,
89
+ "WARNING": logging.WARNING,
90
+ "ERROR": logging.ERROR,
91
+ "CRITICAL": logging.CRITICAL,
92
+ }
93
+ logging.basicConfig(
94
+ level=log_levels[log_level],
95
+ format="[%(asctime)s] [%(module)s] [%(name)s] [%(funcName)s] [%(levelname)-s] %(message)s",
96
+ datefmt="%Y-%m-%d %H:%M:%S",
97
+ )
98
+
99
+ def start(self, default: Callable[[], Any] | None = None):
100
+ """
101
+ Quick start for argument parser
102
+
103
+ Parameters
104
+ ----------
105
+ default : Callable[[], Any] | None, optional
106
+ | Default callable to run, by default ``None``
107
+ | Shows help on default behavior (default=None)
108
+
109
+ Returns
110
+ -------
111
+ Namespace
112
+ Namespace
113
+ """
114
+ if default is None:
115
+ args = self.parse_args(args=None if sys.argv[1:] else self._default_args)
116
+ else:
117
+ args = self.parse_args(args=None if sys.argv[1:] else default())
118
+ self._fuyu_set_log_level(getattr(args, "log_level", "ERROR"))
119
+ return args
absfuyu/util/gui.py ADDED
@@ -0,0 +1,91 @@
1
+ """
2
+ Absfuyu: GUI
3
+ ------------
4
+ Custom tkinter GUI
5
+
6
+ Version: 6.1.1
7
+ Date updated: 30/12/2025 (dd/mm/yyyy)
8
+ """
9
+
10
+ # Module level
11
+ # ---------------------------------------------------------------------------
12
+ __all__ = ["CustomTkinterApp"]
13
+
14
+
15
+ # Library
16
+ # ---------------------------------------------------------------------------
17
+ import tkinter as tk
18
+
19
+ from absfuyu.pkg_data.logo import AbsfuyuLogo
20
+
21
+
22
+ # Class
23
+ # ---------------------------------------------------------------------------
24
+ class CustomTkinterApp(tk.Tk):
25
+
26
+ def __init__(self, title: str | None = None, size: tuple[int, int] | None = None) -> None:
27
+ """
28
+ Custom Tkinter GUI
29
+
30
+ Parameters
31
+ ----------
32
+ title : str | None, optional
33
+ Title of the app, by default None
34
+
35
+ size : tuple[int, int] | None, optional
36
+ Size of the app (width, height), by default None
37
+ """
38
+ super().__init__()
39
+
40
+ # Set custom icon
41
+ self.iconphoto(True, tk.PhotoImage(data=AbsfuyuLogo.SHORT))
42
+
43
+ # Title
44
+ self.title(title)
45
+
46
+ # Set size
47
+ self._absfuyu_set_width_height(size)
48
+
49
+ # @versionadded("5.10.0")
50
+ def _absfuyu_set_width_height(self, size: tuple[int, int] | None = None) -> None:
51
+ """
52
+ Set width and height for the app.
53
+
54
+ Parameters
55
+ ----------
56
+ size : tuple[int, int] | None, optional
57
+ Size of the app (width, height), by default ``None``
58
+ (420 x 250)
59
+ """
60
+ # Set GUI appears in center
61
+ if size is None:
62
+ _width = 420
63
+ _height = 250
64
+ else:
65
+ _width, _height = size
66
+
67
+ _width_screen = self.winfo_screenwidth()
68
+ _width_screen_offset = 0.0052 # x offset mutiplier
69
+ _x_offset = int(_width_screen * _width_screen_offset)
70
+
71
+ _height_screen = self.winfo_screenheight()
72
+ _height_screen_offset = 0.0926 # y offset mutiplier
73
+ _y_offset = int(_height_screen * _height_screen_offset)
74
+
75
+ if _width > _width_screen:
76
+ _width = int(_width_screen * (1 - 0.001))
77
+ # _x_offset = 0
78
+
79
+ if _height > (_height_screen - _y_offset):
80
+ _height = int(_height_screen * (1 - 0.001))
81
+ _y_offset = 0
82
+
83
+ _x = (_width_screen / 2) - (_width / 2) - _x_offset
84
+ _y = (_height_screen / 2) - (_height / 2) - _y_offset
85
+
86
+ self.geometry(f"{_width}x{_height}+{int(_x)}+{int(_y)}")
87
+
88
+
89
+ if __name__ == "__main__":
90
+ app = CustomTkinterApp("absfuyu")
91
+ app.mainloop()
@@ -3,8 +3,8 @@ Absfuyu: Json Method
3
3
  --------------------
4
4
  ``.json`` file handling
5
5
 
6
- Version: 5.6.1
7
- Date updated: 12/09/2025 (dd/mm/yyyy)
6
+ Version: 6.1.1
7
+ Date updated: 30/12/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module level
absfuyu/util/lunar.py CHANGED
@@ -4,8 +4,8 @@ Absfuyu: Lunar calendar
4
4
  -----------------------
5
5
  Convert to lunar calendar
6
6
 
7
- Version: 5.6.1
8
- Date updated: 12/09/2025 (dd/mm/yyyy)
7
+ Version: 6.1.1
8
+ Date updated: 30/12/2025 (dd/mm/yyyy)
9
9
 
10
10
  Source:
11
11
  -------
@@ -0,0 +1,124 @@
1
+ """
2
+ Absfuyu: Package
3
+ ----------------
4
+ Package related
5
+
6
+ Version: 6.1.1
7
+ Date updated: 30/12/2025 (dd/mm/yyyy)
8
+ """
9
+
10
+ # Module level
11
+ # ---------------------------------------------------------------------------
12
+ __all__ = ["PackageManager"]
13
+
14
+
15
+ # Library
16
+ # ---------------------------------------------------------------------------
17
+ import ensurepip
18
+ import importlib
19
+ import importlib.metadata
20
+ import importlib.util
21
+ import subprocess
22
+ import sys
23
+
24
+ from absfuyu.core.baseclass import BaseClass
25
+
26
+
27
+ # Class
28
+ # ---------------------------------------------------------------------------
29
+ class PackageManager(BaseClass):
30
+ """
31
+ Utility class for checking, installing, and importing Python packages safely.
32
+ """
33
+
34
+ def __init__(
35
+ self,
36
+ package: str,
37
+ import_name: str | None = None,
38
+ auto_upgrade: bool = False,
39
+ auto_bootstrap: bool = True,
40
+ ) -> None:
41
+ """
42
+ A configurable package manager utility that can check, install, and import Python packages safely.
43
+
44
+ Parameters
45
+ ----------
46
+ package : str
47
+ The pip package name (e.g. "absfuyu", "random").
48
+
49
+ import_name : str | None
50
+ The importable module name if different from the package name (e.g. "PIL" for "pillow").
51
+
52
+ auto_upgrade : bool, by default ``False``
53
+ Whether to automatically upgrade packages during installation.
54
+
55
+ auto_bootstrap : bool, by default ``True``
56
+ Whether to automatically bootstrap pip using ensurepip if it's missing.
57
+ """
58
+ self.package = package
59
+ self.import_name = import_name
60
+ self.auto_upgrade = auto_upgrade
61
+ self.auto_bootstrap = auto_bootstrap
62
+
63
+ @property
64
+ def version(self) -> str | None:
65
+ """
66
+ Version of package if available
67
+
68
+ Returns
69
+ -------
70
+ str
71
+ Version of package
72
+
73
+ None
74
+ When package is not available
75
+ """
76
+ try:
77
+ return importlib.metadata.version(self.package or self.import_name)
78
+ except importlib.metadata.PackageNotFoundError:
79
+ return None
80
+
81
+ def _run_pip_install(self, package: str) -> None:
82
+ """
83
+ Internal helper to safely run pip install, bootstrapping pip if needed.
84
+ """
85
+ try:
86
+ import pip # noqa: F401
87
+ except ImportError:
88
+ if self.auto_bootstrap:
89
+ ensurepip.bootstrap()
90
+ else:
91
+ raise RuntimeError("pip not found and auto_bootstrap is disabled.")
92
+
93
+ cmd = [sys.executable, "-m", "pip", "install", package]
94
+ if self.auto_upgrade:
95
+ cmd.append("--upgrade")
96
+
97
+ try:
98
+ subprocess.check_call(cmd)
99
+ except subprocess.CalledProcessError as e:
100
+ raise RuntimeError(f"Failed to install {package}: {e}")
101
+
102
+ def ensure_installed(self) -> None:
103
+ """
104
+ Ensure a Python package is installed. Installs (and optionally upgrades) it if missing.
105
+ """
106
+ module_name = self.import_name or self.package
107
+
108
+ if importlib.util.find_spec(module_name) is None:
109
+ self._run_pip_install(self.package)
110
+
111
+ def ensure_import(self):
112
+ """
113
+ Ensure a Python package is importable, installing it if necessary.
114
+ Returns the imported module.
115
+ """
116
+ module_name = self.import_name or self.package
117
+
118
+ if importlib.util.find_spec(module_name) is not None:
119
+ return importlib.import_module(module_name)
120
+
121
+ self.logger.info(f"Installing missing package: {self.package} ...")
122
+
123
+ self._run_pip_install(self.package)
124
+ return importlib.import_module(module_name)