absfuyu 5.1.0__py3-none-any.whl → 5.3.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 (73) hide show
  1. absfuyu/__init__.py +1 -1
  2. absfuyu/__main__.py +3 -3
  3. absfuyu/cli/__init__.py +1 -1
  4. absfuyu/cli/color.py +3 -3
  5. absfuyu/cli/config_group.py +2 -2
  6. absfuyu/cli/do_group.py +12 -2
  7. absfuyu/cli/game_group.py +2 -2
  8. absfuyu/cli/tool_group.py +2 -3
  9. absfuyu/config/__init__.py +1 -1
  10. absfuyu/core/__init__.py +1 -1
  11. absfuyu/core/baseclass.py +32 -2
  12. absfuyu/core/baseclass2.py +1 -1
  13. absfuyu/core/decorator.py +4 -4
  14. absfuyu/core/docstring.py +43 -25
  15. absfuyu/core/dummy_cli.py +1 -1
  16. absfuyu/core/dummy_func.py +4 -4
  17. absfuyu/dxt/__init__.py +1 -1
  18. absfuyu/dxt/dictext.py +5 -2
  19. absfuyu/dxt/dxt_support.py +1 -1
  20. absfuyu/dxt/intext.py +5 -2
  21. absfuyu/dxt/listext.py +405 -127
  22. absfuyu/dxt/strext.py +75 -15
  23. absfuyu/extra/__init__.py +1 -1
  24. absfuyu/extra/beautiful.py +1 -1
  25. absfuyu/extra/da/__init__.py +1 -1
  26. absfuyu/extra/da/dadf.py +56 -4
  27. absfuyu/extra/da/dadf_base.py +1 -1
  28. absfuyu/extra/da/df_func.py +1 -1
  29. absfuyu/extra/da/mplt.py +1 -1
  30. absfuyu/extra/data_analysis.py +3 -3
  31. absfuyu/fun/__init__.py +1 -1
  32. absfuyu/fun/tarot.py +1 -1
  33. absfuyu/game/__init__.py +1 -1
  34. absfuyu/game/game_stat.py +1 -1
  35. absfuyu/game/sudoku.py +1 -1
  36. absfuyu/game/tictactoe.py +2 -3
  37. absfuyu/game/wordle.py +1 -1
  38. absfuyu/general/__init__.py +1 -1
  39. absfuyu/general/content.py +2 -2
  40. absfuyu/general/human.py +1 -1
  41. absfuyu/general/shape.py +1 -1
  42. absfuyu/logger.py +1 -1
  43. absfuyu/pkg_data/__init__.py +1 -1
  44. absfuyu/pkg_data/deprecated.py +1 -1
  45. absfuyu/sort.py +1 -1
  46. absfuyu/tools/__init__.py +16 -13
  47. absfuyu/tools/checksum.py +2 -2
  48. absfuyu/tools/converter.py +29 -8
  49. absfuyu/tools/generator.py +251 -110
  50. absfuyu/tools/inspector.py +84 -40
  51. absfuyu/tools/keygen.py +1 -1
  52. absfuyu/tools/obfuscator.py +2 -2
  53. absfuyu/tools/passwordlib.py +3 -4
  54. absfuyu/tools/shutdownizer.py +1 -1
  55. absfuyu/tools/web.py +1 -1
  56. absfuyu/typings.py +136 -0
  57. absfuyu/util/__init__.py +18 -4
  58. absfuyu/util/api.py +36 -16
  59. absfuyu/util/json_method.py +43 -14
  60. absfuyu/util/lunar.py +1 -1
  61. absfuyu/util/path.py +158 -4
  62. absfuyu/util/performance.py +120 -5
  63. absfuyu/util/shorten_number.py +1 -1
  64. absfuyu/util/text_table.py +235 -45
  65. absfuyu/util/zipped.py +4 -3
  66. absfuyu/version.py +2 -2
  67. {absfuyu-5.1.0.dist-info → absfuyu-5.3.0.dist-info}/METADATA +1 -1
  68. absfuyu-5.3.0.dist-info/RECORD +76 -0
  69. absfuyu/core/typings.py +0 -40
  70. absfuyu-5.1.0.dist-info/RECORD +0 -76
  71. {absfuyu-5.1.0.dist-info → absfuyu-5.3.0.dist-info}/WHEEL +0 -0
  72. {absfuyu-5.1.0.dist-info → absfuyu-5.3.0.dist-info}/entry_points.txt +0 -0
  73. {absfuyu-5.1.0.dist-info → absfuyu-5.3.0.dist-info}/licenses/LICENSE +0 -0
@@ -3,21 +3,22 @@ Absfuyu: Inspector
3
3
  ------------------
4
4
  Inspector
5
5
 
6
- Version: 5.1.0
7
- Date updated: 10/03/2025 (dd/mm/yyyy)
6
+ Version: 5.2.0
7
+ Date updated: 16/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module level
11
11
  # ---------------------------------------------------------------------------
12
- __all__ = ["Inspector"]
12
+ __all__ = ["Inspector", "inspect_all"]
13
13
 
14
14
  # Library
15
15
  # ---------------------------------------------------------------------------
16
- import inspect
16
+ import inspect as _inspect
17
17
  import os
18
+ from functools import partial
18
19
  from textwrap import TextWrapper
19
20
  from textwrap import shorten as text_shorten
20
- from typing import Any
21
+ from typing import Any, Literal, overload
21
22
 
22
23
  from absfuyu.core.baseclass import (
23
24
  AutoREPRMixin,
@@ -33,7 +34,8 @@ from absfuyu.util.text_table import OneColumnTableMaker
33
34
  # TODO: rewrite with each class for docs, method, property, attr, param, title
34
35
  class Inspector(AutoREPRMixin):
35
36
  """
36
- Inspect an object
37
+ Inspect an object.
38
+ By default shows object's docstring and attribute (if any).
37
39
 
38
40
  Parameters
39
41
  ----------
@@ -42,7 +44,7 @@ class Inspector(AutoREPRMixin):
42
44
 
43
45
  line_length: int | None
44
46
  Number of cols in inspect output (Split line every line_length).
45
- Set to ``None`` to use ``os.get_terminal_size()``, by default ``88``
47
+ Set to ``None`` to use ``os.get_terminal_size()``, by default ``None``
46
48
 
47
49
  include_docs : bool, optional
48
50
  Include docstring, by default ``True``
@@ -54,7 +56,7 @@ class Inspector(AutoREPRMixin):
54
56
  Include object's methods (if any), by default ``False``
55
57
 
56
58
  include_property : bool, optional
57
- Include object's properties (if any), by default ``True``
59
+ Include object's properties (if any), by default ``False``
58
60
 
59
61
  include_attribute : bool, optional
60
62
  Include object's attributes (if any), by default ``True``
@@ -65,27 +67,63 @@ class Inspector(AutoREPRMixin):
65
67
  include_all : bool, optional
66
68
  Include all infomation availble, by default ``False``
67
69
 
70
+ max_textwrap_lines : int, optional
71
+ Maximum lines for the output's header (class, signature, repr).
72
+ Must be >= 1, by default ``8``
73
+
74
+ style : Literal["normal", "bold", "dashed", "double", "rounded"], optional
75
+ Style for the table, by default ``"normal"``
76
+
68
77
 
69
78
  Example:
70
79
  --------
71
80
  >>> print(Inspector(<object>, **kwargs))
72
81
  """
73
82
 
83
+ @overload
84
+ def __init__(self, obj: Any) -> None: ...
85
+
86
+ @overload
87
+ def __init__(self, obj: Any, *, include_all: Literal[True] = ...) -> None: ...
88
+
89
+ @overload
90
+ def __init__(
91
+ self,
92
+ obj: Any,
93
+ *,
94
+ line_length: int | None = None,
95
+ include_docs: bool = True,
96
+ include_mro: bool = False,
97
+ include_method: bool = False,
98
+ include_property: bool = False,
99
+ include_attribute: bool = True,
100
+ include_private: bool = False,
101
+ max_textwrap_lines: int = 8,
102
+ style: Literal["normal", "bold", "dashed", "double", "rounded"] = "normal",
103
+ ) -> None: ...
104
+
74
105
  def __init__(
75
106
  self,
76
107
  obj: Any,
77
108
  *,
78
- line_length: int | None = 88,
109
+ # Line length
110
+ line_length: int | None = None,
111
+ line_length_offset: int = 0, # line_length += line_length_offset (when line_length=None)
112
+ max_textwrap_lines: int = 8,
113
+ # Include
79
114
  include_docs: bool = True,
80
115
  include_mro: bool = False,
81
116
  include_method: bool = False,
82
- include_property: bool = True,
117
+ include_property: bool = False,
83
118
  include_attribute: bool = True,
84
119
  include_private: bool = False,
85
120
  include_all: bool = False,
121
+ # Style
122
+ style: Literal["normal", "bold", "dashed", "double", "rounded"] = "normal",
86
123
  ) -> None:
87
124
  """
88
- Inspect an object
125
+ Inspect an object.
126
+ By default shows object's docstring and attribute (if any).
89
127
 
90
128
  Parameters
91
129
  ----------
@@ -94,7 +132,7 @@ class Inspector(AutoREPRMixin):
94
132
 
95
133
  line_length: int | None
96
134
  Number of cols in inspect output (Split line every line_length).
97
- Set to ``None`` to use ``os.get_terminal_size()``, by default ``88``
135
+ Set to ``None`` to use ``os.get_terminal_size()``, by default ``None``
98
136
 
99
137
  include_docs : bool, optional
100
138
  Include docstring, by default ``True``
@@ -106,7 +144,7 @@ class Inspector(AutoREPRMixin):
106
144
  Include object's methods (if any), by default ``False``
107
145
 
108
146
  include_property : bool, optional
109
- Include object's properties (if any), by default ``True``
147
+ Include object's properties (if any), by default ``False``
110
148
 
111
149
  include_attribute : bool, optional
112
150
  Include object's attributes (if any), by default ``True``
@@ -117,6 +155,13 @@ class Inspector(AutoREPRMixin):
117
155
  include_all : bool, optional
118
156
  Include all infomation availble, by default ``False``
119
157
 
158
+ max_textwrap_lines : int, optional
159
+ Maximum lines for the output's header (class, signature, repr).
160
+ Must be >= 1, by default ``8``
161
+
162
+ style : Literal["normal", "bold", "dashed", "double", "rounded"], optional
163
+ Style for the table, by default ``"normal"``
164
+
120
165
 
121
166
  Example:
122
167
  --------
@@ -129,6 +174,7 @@ class Inspector(AutoREPRMixin):
129
174
  self.include_property = include_property
130
175
  self.include_attribute = include_attribute
131
176
  self.include_private = include_private
177
+ self._style = style
132
178
 
133
179
  if include_all:
134
180
  self.include_docs = True
@@ -141,7 +187,7 @@ class Inspector(AutoREPRMixin):
141
187
  # Setup line length
142
188
  if line_length is None:
143
189
  try:
144
- self._linelength = os.get_terminal_size().columns
190
+ self._linelength = os.get_terminal_size().columns + line_length_offset
145
191
  except OSError:
146
192
  self._linelength = 88
147
193
  elif isinstance(line_length, (int, float)):
@@ -156,7 +202,7 @@ class Inspector(AutoREPRMixin):
156
202
  subsequent_indent="",
157
203
  tabsize=4,
158
204
  break_long_words=True,
159
- max_lines=8,
205
+ max_lines=max(max_textwrap_lines, 1),
160
206
  )
161
207
 
162
208
  # Output
@@ -167,18 +213,10 @@ class Inspector(AutoREPRMixin):
167
213
 
168
214
  # Support
169
215
  def _long_list_terminal_size(self, long_list: list) -> list:
170
- max_name_len = max([len(x) for x in long_list]) + 1
171
- cols = 1
172
-
173
- if max_name_len <= self._linelength - 4:
174
- cols = (self._linelength - 4) // max_name_len
175
- splitted_chunk: list[list[str]] = ListExt(long_list).split_chunk(cols)
176
-
177
- mod_chunk = ListExt(
178
- [[x.ljust(max_name_len, " ") for x in chunk] for chunk in splitted_chunk]
179
- ).apply(lambda x: "".join(x))
180
-
181
- return list(mod_chunk)
216
+ ll = ListExt(long_list).wrap_to_column(
217
+ self._linelength, margin=4, transpose=True
218
+ )
219
+ return list(ll)
182
220
 
183
221
  # Signature
184
222
  def _make_title(self) -> str:
@@ -189,9 +227,9 @@ class Inspector(AutoREPRMixin):
189
227
  title_str = (
190
228
  str(self.obj)
191
229
  if (
192
- inspect.isclass(self.obj)
230
+ _inspect.isclass(self.obj)
193
231
  or callable(self.obj)
194
- or inspect.ismodule(self.obj)
232
+ or _inspect.ismodule(self.obj)
195
233
  )
196
234
  else str(type(self.obj))
197
235
  )
@@ -199,17 +237,17 @@ class Inspector(AutoREPRMixin):
199
237
 
200
238
  def _get_signature_prefix(self) -> str:
201
239
  # signature prefix
202
- if inspect.isclass(self.obj):
240
+ if _inspect.isclass(self.obj):
203
241
  return "class"
204
- elif inspect.iscoroutinefunction(self.obj):
242
+ elif _inspect.iscoroutinefunction(self.obj):
205
243
  return "async def"
206
- elif inspect.isfunction(self.obj):
244
+ elif _inspect.isfunction(self.obj):
207
245
  return "def"
208
246
  return ""
209
247
 
210
248
  def get_parameters(self) -> list[str] | None:
211
249
  try:
212
- sig = inspect.signature(self.obj)
250
+ sig = _inspect.signature(self.obj)
213
251
  except (ValueError, AttributeError, TypeError):
214
252
  return None
215
253
  return [str(x) for x in sig.parameters.values()]
@@ -221,7 +259,7 @@ class Inspector(AutoREPRMixin):
221
259
  """
222
260
  try:
223
261
  return self._text_wrapper.wrap(
224
- f"{self._get_signature_prefix()} {self.obj.__name__}{inspect.signature(self.obj)}"
262
+ f"{self._get_signature_prefix()} {self.obj.__name__}{_inspect.signature(self.obj)}"
225
263
  )
226
264
  # not class, func | not type | is module
227
265
  except (ValueError, AttributeError, TypeError):
@@ -229,9 +267,8 @@ class Inspector(AutoREPRMixin):
229
267
 
230
268
  # Method and property
231
269
  def _get_method_property(self) -> MethodNPropertyResult:
232
- # if inspect.isclass(self.obj) or inspect.ismodule(self.obj):
233
- if inspect.isclass(self.obj):
234
- # TODO: Support enum type
270
+ # if _inspect.isclass(self.obj) or inspect.ismodule(self.obj):
271
+ if _inspect.isclass(self.obj):
235
272
  tmpcls = type(
236
273
  "tmpcls",
237
274
  (
@@ -271,7 +308,7 @@ class Inspector(AutoREPRMixin):
271
308
  Inspector's workflow:
272
309
  03. Get docstring and strip
273
310
  """
274
- docs: str | None = inspect.getdoc(self.obj)
311
+ docs: str | None = _inspect.getdoc(self.obj)
275
312
 
276
313
  if docs is None:
277
314
  return ""
@@ -367,7 +404,7 @@ class Inspector(AutoREPRMixin):
367
404
 
368
405
  # Output
369
406
  def _make_output(self) -> OneColumnTableMaker:
370
- table = OneColumnTableMaker(self._linelength)
407
+ table = OneColumnTableMaker(self._linelength, style=self._style)
371
408
  body: list[str] = []
372
409
 
373
410
  # Signature
@@ -394,7 +431,9 @@ class Inspector(AutoREPRMixin):
394
431
 
395
432
  # Method & Property
396
433
  try:
397
- method_n_properties = self._get_method_property().flatten_value().pack()
434
+ method_n_properties = (
435
+ self._get_method_property().flatten_value().pack().sort()
436
+ )
398
437
  if self.include_method:
399
438
  ml = [
400
439
  text_shorten(f"- {x}", self._linelength - 4)
@@ -431,3 +470,8 @@ class Inspector(AutoREPRMixin):
431
470
 
432
471
  def detail_str(self) -> str:
433
472
  return self._inspect_output.make_table()
473
+
474
+
475
+ # Partial
476
+ # ---------------------------------------------------------------------------
477
+ inspect_all = partial(Inspector, line_length=None, include_all=True)
absfuyu/tools/keygen.py CHANGED
@@ -5,7 +5,7 @@ Mod7 product key generator (90's)
5
5
 
6
6
  This is for educational and informative purposes only.
7
7
 
8
- Version: 5.1.0
8
+ Version: 5.2.0
9
9
  Date updated: 10/03/2025 (dd/mm/yyyy)
10
10
  """
11
11
 
@@ -3,8 +3,8 @@ Absfuyu: Obfuscator
3
3
  -------------------
4
4
  Obfuscate code
5
5
 
6
- Version: 5.1.0
7
- Date updated: 10/03/2025 (dd/mm/yyyy)
6
+ Version: 5.2.0
7
+ Date updated: 11/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module level
@@ -3,8 +3,8 @@ Absfuyu: Passwordlib
3
3
  --------------------
4
4
  Password library
5
5
 
6
- Version: 5.1.0
7
- Date updated: 10/03/2025 (dd/mm/yyyy)
6
+ Version: 5.2.0
7
+ Date updated: 15/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module level
@@ -27,7 +27,6 @@ from absfuyu.dxt import DictExt, Text
27
27
  from absfuyu.logger import logger
28
28
  from absfuyu.pkg_data import DataList, DataLoader
29
29
  from absfuyu.tools.generator import Charset, Generator
30
- from absfuyu.util import set_min
31
30
 
32
31
 
33
32
  # Function
@@ -213,7 +212,7 @@ class PasswordGenerator(BaseClass):
213
212
  while True:
214
213
  pwd = Generator.generate_string(
215
214
  charset=charset,
216
- size=set_min(length, min_value=8), # type: ignore
215
+ size=max(length, 8), # type: ignore
217
216
  times=1,
218
217
  string_type_if_1=True,
219
218
  )
@@ -3,7 +3,7 @@ Absfuyu: Shutdownizer
3
3
  ---------------------
4
4
  This shutdowns
5
5
 
6
- Version: 5.1.0
6
+ Version: 5.2.0
7
7
  Date updated: 10/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
absfuyu/tools/web.py CHANGED
@@ -3,7 +3,7 @@ Absfuyu: Web
3
3
  ------------
4
4
  Web, ``request``, ``BeautifulSoup`` stuff
5
5
 
6
- Version: 5.1.0
6
+ Version: 5.2.0
7
7
  Date updated: 10/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
absfuyu/typings.py ADDED
@@ -0,0 +1,136 @@
1
+ """
2
+ Absfuyu: Core
3
+ -------------
4
+ Pre-defined typing
5
+
6
+ Version: 5.2.0
7
+ Date updated: 14/03/2025 (dd/mm/yyyy)
8
+ """
9
+
10
+ # Module Package
11
+ # ---------------------------------------------------------------------------
12
+ __all__ = [
13
+ # Type
14
+ "T",
15
+ "T_co",
16
+ "T_contra",
17
+ "P",
18
+ "R",
19
+ "_CALLABLE",
20
+ "CT",
21
+ "N",
22
+ "_Number",
23
+ "override",
24
+ # Protocol
25
+ "SupportsShowMethods",
26
+ ]
27
+
28
+
29
+ # Library
30
+ # ---------------------------------------------------------------------------
31
+ from collections.abc import Callable
32
+ from typing import Any, ParamSpec, Protocol, TypeVar, overload
33
+
34
+ try:
35
+ from typing import override # type: ignore
36
+ except ImportError:
37
+ from absfuyu.core.decorator import dummy_decorator as override
38
+
39
+
40
+ # Type
41
+ # ---------------------------------------------------------------------------
42
+ # Types where neither is possible are invariant
43
+ T = TypeVar("T") # Type invariant
44
+ # Type variables that are covariant can be substituted
45
+ # with a more specific type without causing errors
46
+ T_co = TypeVar("T_co", covariant=True) # Type covariant
47
+ # Type variables that are contravariant can be substituted
48
+ # with a more general type without causing errors
49
+ T_contra = TypeVar("T_contra", contravariant=True) # Type contravariant
50
+
51
+ # Callable
52
+ P = ParamSpec("P") # Parameter type
53
+ R = TypeVar("R") # Return type - Can be anything
54
+ _CALLABLE = Callable[P, R]
55
+
56
+ # Class type - Can be any subtype of `type`
57
+ CT = TypeVar("CT", bound=type)
58
+
59
+ # Number type
60
+ N = TypeVar("N", int, float) # Must be int or float
61
+ _Number = int | float
62
+
63
+
64
+ # Protocol
65
+ # ---------------------------------------------------------------------------
66
+ class SupportsShowMethods(Protocol):
67
+ """
68
+ Support class with ``show_all_methods()``
69
+ and ``show_all_properties()`` method
70
+ from ``absfuyu.core.basclass.ShowAllMethodsMixin``
71
+ """
72
+
73
+ @overload
74
+ @classmethod
75
+ def show_all_methods(cls) -> dict[str, list[str]]: ...
76
+
77
+ @overload
78
+ @classmethod
79
+ def show_all_methods(
80
+ cls,
81
+ print_result: bool = False,
82
+ include_classmethod: bool = True,
83
+ classmethod_indicator: str = "<classmethod>",
84
+ include_staticmethod: bool = True,
85
+ staticmethod_indicator: str = "<staticmethod>",
86
+ include_private_method: bool = False,
87
+ ) -> dict[str, list[str]]: ...
88
+
89
+ @classmethod
90
+ def show_all_methods(cls, *args, **kwargs) -> Any: ...
91
+
92
+ @overload
93
+ @classmethod
94
+ def show_all_properties(cls) -> dict[str, list[str]]: ...
95
+
96
+ @overload
97
+ @classmethod
98
+ def show_all_properties(
99
+ cls, print_result: bool = False
100
+ ) -> dict[str, list[str]]: ...
101
+
102
+ @classmethod
103
+ def show_all_properties(cls, *args, **kwargs) -> Any: ...
104
+
105
+
106
+ # Note
107
+ # ---------------------------------------------------------------------------
108
+ # Iterable : __iter__
109
+ # Iterator(Iterable) : __next__, __iter__
110
+ # Reversible(Iterable) : __reversed__, __iter__
111
+ # Sized : __len__
112
+ # Container : __contains__
113
+ # Collection(Sized, Iterable, Container) : __len__, __iter__, __contains__
114
+ # Set(Collection) : __contains__, __iter__, __len__
115
+ # MutableSet(Set) : __contains__, __iter__, __len__
116
+ # Mapping(Collection) : __getitem__, __iter__, and __len__
117
+ # MutableMapping(Mapping) : __getitem__, __setitem__, __delitem__,__iter__, __len__
118
+ # Sequence(Reversible, Collection) : __reversed__, __len__, __iter__, __contains__
119
+ # MutableSequence(Sequence) : __getitem__, __setitem__, __delitem__, __reversed__, __len__, __iter__, __contains__
120
+
121
+ # Iterable : str, dict, list, tuple, set
122
+ # Iterator(Iterable) : Generator
123
+ # Reversible(Iterable) : str, dict, list, tuple
124
+ # Sized : str, dict, list, tuple, set
125
+ # Container : str, dict, list, tuple, set
126
+ # Collection(Sized, Iterable, Container) : str, dict, list, tuple, set
127
+ # Set(Collection) : set
128
+ # MutableSet(Set) : set
129
+ # Mapping(Collection) : dict
130
+ # MutableMapping(Mapping) : dict
131
+ # Sequence(Reversible, Collection) : str, list, tuple
132
+ # MutableSequence(Sequence) : list
133
+
134
+ # __iter__: for <...> in <...>
135
+ # __len__: len(<...>)
136
+ # __contains__: if <...> in <...>
absfuyu/util/__init__.py CHANGED
@@ -3,10 +3,20 @@ Absufyu: Utilities
3
3
  ------------------
4
4
  Some random utilities
5
5
 
6
- Version: 5.1.0
7
- Date updated: 10/03/2025 (dd/mm/yyyy)
6
+ Version: 5.2.0
7
+ Date updated: 12/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
+ # Module Package
11
+ # ---------------------------------------------------------------------------
12
+ __all__ = [
13
+ "get_installed_package",
14
+ "set_min",
15
+ "set_max",
16
+ "set_min_max",
17
+ "stop_after_day",
18
+ ]
19
+
10
20
  # Library
11
21
  # ---------------------------------------------------------------------------
12
22
  import pkgutil
@@ -137,8 +147,12 @@ def set_min_max(
137
147
  >>> set_min_max(808)
138
148
  100
139
149
  """
140
- current_value = set_min(current_value, min_value=min_value)
141
- current_value = set_max(current_value, max_value=max_value)
150
+ # Set min
151
+ # current_value = set_min(current_value, min_value=min_value)
152
+ current_value = max(current_value, min_value)
153
+ # Set max
154
+ # current_value = set_max(current_value, max_value=max_value)
155
+ current_value = min(current_value, max_value)
142
156
  return current_value
143
157
 
144
158
 
absfuyu/util/api.py CHANGED
@@ -3,8 +3,8 @@ Absufyu: API
3
3
  ------------
4
4
  Fetch data stuff
5
5
 
6
- Version: 5.1.0
7
- Date updated: 10/03/2025 (dd/mm/yyyy)
6
+ Version: 5.2.0
7
+ Date updated: 12/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module level
@@ -25,7 +25,8 @@ from typing import NamedTuple
25
25
 
26
26
  import requests
27
27
 
28
- from absfuyu.core import versionadded, versionchanged
28
+ from absfuyu.core.baseclass import BaseClass
29
+ from absfuyu.core.docstring import versionadded, versionchanged
29
30
  from absfuyu.logger import logger
30
31
 
31
32
 
@@ -33,8 +34,15 @@ from absfuyu.logger import logger
33
34
  # ---------------------------------------------------------------------------
34
35
  class PingResult(NamedTuple):
35
36
  """
36
- :param host: Host name/IP
37
- :param result: Ping result in ms
37
+ Ping result
38
+
39
+ Parameters
40
+ ----------
41
+ host : str
42
+ Host name/IP
43
+
44
+ result : str
45
+ Ping result in ms
38
46
  """
39
47
 
40
48
  host: str
@@ -90,28 +98,40 @@ def ping_windows(host: list[str], ping_count: int = 3) -> list[PingResult]:
90
98
 
91
99
  # Class
92
100
  # ---------------------------------------------------------------------------
93
- class APIRequest:
94
- """API data with cache feature"""
101
+ class APIRequest(BaseClass):
102
+ """
103
+ API data with cache feature
104
+
105
+ Parameters
106
+ ----------
107
+ api_url : str
108
+ API link
109
+
110
+ encoding : str | None, optional
111
+ Data encoding, by default ``"utf-8"``
112
+ """
95
113
 
96
114
  def __init__(
97
115
  self,
98
116
  api_url: str,
99
- *, # Use "*" to force using keyword in function parameter | Example: APIRequest(url, encoding="utf-8")
117
+ *,
100
118
  encoding: str | None = "utf-8",
101
119
  ) -> None:
102
120
  """
103
- :param api_url: api link
104
- :param encoding: data encoding (Default: utf-8)
121
+ Create APIRequest instance
122
+
123
+ Parameters
124
+ ----------
125
+ api_url : str
126
+ API link
127
+
128
+ encoding : str | None, optional
129
+ Data encoding, by default ``"utf-8"``
105
130
  """
131
+
106
132
  self.url = api_url
107
133
  self.encoding = encoding
108
134
 
109
- def __str__(self) -> str:
110
- return f"{self.__class__.__name__}({self.url})"
111
-
112
- def __repr__(self) -> str:
113
- return self.__str__()
114
-
115
135
  def fetch_data(self, *, update: bool = False, json_cache: str | Path):
116
136
  """
117
137
  Fetch data from an API then cache it for later use