absfuyu 4.0.0__py3-none-any.whl → 4.1.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.

absfuyu/__init__.py CHANGED
@@ -22,7 +22,7 @@ Using in cmd (`absfuyu[cli]` required):
22
22
  __title__ = "absfuyu"
23
23
  __author__ = "AbsoluteWinter"
24
24
  __license__ = "MIT License"
25
- __version__ = "4.0.0"
25
+ __version__ = "4.1.0"
26
26
  __all__ = [
27
27
  "core",
28
28
  "config",
absfuyu/cli/do_group.py CHANGED
@@ -3,13 +3,14 @@ ABSFUYU CLI
3
3
  -----------
4
4
  Do
5
5
 
6
- Version: 1.2.0
7
- Date updated: 07/01/2025 (dd/mm/yyyy)
6
+ Version: 1.3.0
7
+ Date updated: 01/02/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  __all__ = ["do_group"]
11
11
 
12
12
  import subprocess
13
+ from typing import Literal
13
14
 
14
15
  import click
15
16
 
@@ -17,6 +18,7 @@ from absfuyu import __title__
17
18
  from absfuyu.cli.color import COLOR
18
19
  from absfuyu.core import __package_feature__
19
20
  from absfuyu.general.human import Human2
21
+ from absfuyu.tools.checksum import checksum_operation
20
22
  from absfuyu.util.zipped import Zipper
21
23
  from absfuyu.version import PkgVersion
22
24
 
@@ -96,6 +98,40 @@ def unzip_files_in_dir(dir: str) -> None:
96
98
  print("Done")
97
99
 
98
100
 
101
+ @click.command(name="checksum")
102
+ @click.argument("file_path", type=str)
103
+ @click.option(
104
+ "--hashmode",
105
+ "-m",
106
+ "hash_mode",
107
+ type=click.Choice(["md5", "sha1", "sha256", "sha512"]),
108
+ default="sha256",
109
+ show_default=True,
110
+ help="Hash mode",
111
+ )
112
+ @click.option(
113
+ "--compare",
114
+ "-c",
115
+ "hash_to_compare",
116
+ type=str,
117
+ default=None,
118
+ show_default=True,
119
+ help="Hash to compare",
120
+ )
121
+ def file_checksum(
122
+ file_path: str,
123
+ hash_mode: str | Literal["md5", "sha1", "sha256", "sha512"],
124
+ hash_to_compare: str,
125
+ ) -> None:
126
+ """Checksum for file"""
127
+
128
+ res = checksum_operation(file_path, hash_mode=hash_mode)
129
+ if hash_to_compare:
130
+ print(res == hash_to_compare)
131
+ else:
132
+ print(res)
133
+
134
+
99
135
  @click.group(name="do")
100
136
  def do_group() -> None:
101
137
  """Perform functionalities"""
@@ -108,3 +144,4 @@ do_group.add_command(advice)
108
144
  do_group.add_command(fs)
109
145
  do_group.add_command(info)
110
146
  do_group.add_command(unzip_files_in_dir)
147
+ do_group.add_command(file_checksum)
absfuyu/core.py CHANGED
@@ -3,8 +3,8 @@ Absfuyu: Core
3
3
  -------------
4
4
  Contain type hints and other stuffs
5
5
 
6
- Version: 2.2.1
7
- Date updated: 14/11/2024 (dd/mm/yyyy)
6
+ Version: 2.3.0
7
+ Date updated: 01/02/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module Package
@@ -21,7 +21,11 @@ __all__ = [
21
21
  __package_feature__ = ["beautiful", "extra", "res", "full", "dev"]
22
22
 
23
23
 
24
+ # Library
25
+ ###########################################################################
26
+ from importlib import import_module
24
27
  from importlib.resources import files
28
+ from typing import Iterable
25
29
 
26
30
 
27
31
  class CLITextColor:
@@ -43,3 +47,12 @@ class CLITextColor:
43
47
  CORE_PATH = files("absfuyu")
44
48
  CONFIG_PATH = CORE_PATH.joinpath("config", "config.json")
45
49
  DATA_PATH = CORE_PATH.joinpath("pkg_data")
50
+
51
+
52
+ # tqdm wrapper
53
+ try:
54
+ tqdm = import_module("tqdm").tqdm
55
+ except ModuleNotFoundError:
56
+
57
+ def tqdm(iterable: Iterable, **kwargs):
58
+ return iterable
absfuyu/game/__init__.py CHANGED
@@ -82,7 +82,7 @@ def game_escapeLoop() -> None:
82
82
  print(x)
83
83
  stop_time = time.time()
84
84
  break
85
- print(f"= Escaped in {stop_time-start_time:,.2f}s =")
85
+ print(f"= Escaped in {stop_time - start_time:,.2f}s =")
86
86
 
87
87
 
88
88
  # Rock Paper Scissors
absfuyu/game/game_stat.py CHANGED
@@ -26,7 +26,7 @@ class GameStats:
26
26
  def _update_win_rate(self) -> None:
27
27
  try:
28
28
  self._win_rate = self.win / (self.win + self.draw + self.lose)
29
- self.win_rate = f"{self._win_rate*100:,.2f}%"
29
+ self.win_rate = f"{self._win_rate * 100:,.2f}%"
30
30
  except ZeroDivisionError:
31
31
  self._win_rate = 0
32
32
  self.win_rate = "N/A"
@@ -427,12 +427,12 @@ class ContentLoader:
427
427
  self.tag_dictionary = tag_dictionary
428
428
 
429
429
  # symbol stuff
430
- assert (
431
- comment_symbol != split_symbol
432
- ), "comment_symbol and split_symbol should have different values"
433
- assert (
434
- tag_separate_symbol != split_symbol
435
- ), "tag_separate_symbol and split_symbol should have different values"
430
+ assert comment_symbol != split_symbol, (
431
+ "comment_symbol and split_symbol should have different values"
432
+ )
433
+ assert tag_separate_symbol != split_symbol, (
434
+ "tag_separate_symbol and split_symbol should have different values"
435
+ )
436
436
  self.comment_symbol: str = comment_symbol
437
437
  self.split_symbol: str = split_symbol
438
438
  self.tag_separate_symbol: str = tag_separate_symbol
@@ -485,7 +485,7 @@ class ContentLoader:
485
485
  if x.startswith(self.comment_symbol) or len(x) == 0:
486
486
  continue # skip comment and empty lines
487
487
  logger.debug(
488
- f"### Loop {i+1} #####################################################################"
488
+ f"### Loop {i + 1} #####################################################################"
489
489
  )
490
490
 
491
491
  temp = x.split(self.split_symbol)
@@ -302,7 +302,7 @@ class Text(str):
302
302
  output.append(f"{splt_name[i]}='{temp[i]}'")
303
303
  else:
304
304
  for i in range(splt_len):
305
- output.append(f"{custom_var_name}{i+1}='{temp[i]}'")
305
+ output.append(f"{custom_var_name}{i + 1}='{temp[i]}'")
306
306
 
307
307
  # joined variable
308
308
  temp = []
@@ -319,9 +319,9 @@ class Text(str):
319
319
  if i == 0:
320
320
  temp.append(f"{custom_var_name}=")
321
321
  if i == splt_len - 1:
322
- temp.append(f"{custom_var_name}{i+1}")
322
+ temp.append(f"{custom_var_name}{i + 1}")
323
323
  else:
324
- temp.append(f"{custom_var_name}{i+1}+")
324
+ temp.append(f"{custom_var_name}{i + 1}+")
325
325
 
326
326
  output.append("".join(temp))
327
327
  if custom_var_name is None:
@@ -156,7 +156,9 @@ class Generator:
156
156
 
157
157
  while count < times:
158
158
  s = "".join(choice(char_lst) for _ in range(size))
159
- logger.debug(f"Time generated: {count+1}. Remaining: {times-count-1}. {s}")
159
+ logger.debug(
160
+ f"Time generated: {count + 1}. Remaining: {times - count - 1}. {s}"
161
+ )
160
162
  if not unique:
161
163
  unique_string.append(s)
162
164
  count += 1
@@ -274,7 +276,7 @@ class Generator:
274
276
  if num[i] >= 10: # type: ignore
275
277
  num[i] -= 9 # type: ignore
276
278
  sum += num[i] # type: ignore
277
- logger.debug(f"Loop {i+1}: {num[i]}, {sum}")
279
+ logger.debug(f"Loop {i + 1}: {num[i]}, {sum}")
278
280
 
279
281
  out = (10 - (sum % 10)) % 10
280
282
  logger.debug(f"Output: {out}")
absfuyu/logger.py CHANGED
@@ -100,7 +100,7 @@ def _compress_list_for_print(iterable: list, max_visible: Optional[int] = 5) ->
100
100
  # temp = [iterable[:cut_idx_1], ["..."], iterable[len(iterable)-cut_idx_2:]]
101
101
  # out = list(chain.from_iterable(temp))
102
102
  # out = [*iterable[:cut_idx_1], "...", *iterable[len(iterable)-cut_idx_2:]] # Version 2
103
- out = f"{str(iterable[:cut_idx_1])[:-1]}, ...,{str(iterable[len(iterable)-cut_idx_2:])[1:]}" # Version 3
103
+ out = f"{str(iterable[:cut_idx_1])[:-1]}, ...,{str(iterable[len(iterable) - cut_idx_2 :])[1:]}" # Version 3
104
104
  # logger.debug(out)
105
105
  return f"{out} [Len: {len(iterable)}]"
106
106
 
@@ -123,7 +123,7 @@ def _compress_string_for_print(text: str, max_visible: Optional[int] = 120) -> s
123
123
  return str(text)
124
124
  else:
125
125
  cut_idx = math.floor((max_visible - 3) / 2)
126
- temp = f"{text[:cut_idx]}...{text[len(text)-cut_idx:]}"
126
+ temp = f"{text[:cut_idx]}...{text[len(text) - cut_idx :]}"
127
127
  return f"{temp} [Len: {len(text)}]"
128
128
 
129
129
 
@@ -0,0 +1,56 @@
1
+ """
2
+ Absufyu: Checksum
3
+ -----------------
4
+ Check MD5, SHA256, ...
5
+
6
+ Version: 1.0.0
7
+ Date updated: 01/02/2025 (dd/mm/yyyy)
8
+ """
9
+
10
+ # Module level
11
+ ###########################################################################
12
+ __all__ = ["checksum_operation"]
13
+
14
+
15
+ # Library
16
+ ###########################################################################
17
+ import hashlib
18
+ from pathlib import Path
19
+ from typing import Literal
20
+
21
+
22
+ # Function
23
+ ###########################################################################
24
+ def checksum_operation(
25
+ file: Path | str,
26
+ hash_mode: str | Literal["md5", "sha1", "sha256", "sha512"] = "sha256",
27
+ ) -> str:
28
+ """This performs checksum"""
29
+ if hash_mode.lower() == "md5":
30
+ hash_engine = hashlib.md5()
31
+ elif hash_mode.lower() == "sha1":
32
+ hash_engine = hashlib.sha1()
33
+ elif hash_mode.lower() == "sha256":
34
+ hash_engine = hashlib.sha256()
35
+ elif hash_mode.lower() == "sha512":
36
+ hash_engine = hashlib.sha512()
37
+ else:
38
+ hash_engine = hashlib.md5()
39
+
40
+ with open(Path(file), "rb") as f:
41
+ # Read and hash the file in 4K chunks. Reading the whole
42
+ # file at once might consume a lot of memory if it is
43
+ # large.
44
+ while True:
45
+ data = f.read(4096)
46
+ if len(data) == 0:
47
+ break
48
+ else:
49
+ hash_engine.update(data)
50
+ return hash_engine.hexdigest()
51
+
52
+
53
+ # Run
54
+ ###########################################################################
55
+ if __name__ == "__main__":
56
+ pass
@@ -3,8 +3,8 @@ Absufyu: Converter
3
3
  ------------------
4
4
  Convert stuff
5
5
 
6
- Version: 1.2.3
7
- Date updated: 25/11/2024 (dd/mm/yyyy)
6
+ Version: 1.3.0
7
+ Date updated: 01/02/2025 (dd/mm/yyyy)
8
8
 
9
9
  Feature:
10
10
  --------
@@ -25,6 +25,7 @@ import math
25
25
  import re
26
26
  import string
27
27
  from itertools import chain, combinations
28
+ from pathlib import Path
28
29
 
29
30
  from absfuyu.core import CLITextColor
30
31
  from absfuyu.logger import logger
@@ -48,6 +49,29 @@ class Base64EncodeDecode:
48
49
  def decode(data: str) -> str:
49
50
  return base64.b64decode(data).decode()
50
51
 
52
+ @staticmethod
53
+ def encode_image(img_path: Path | str, data_tag: bool = False) -> str:
54
+ """Encode image file into base64 string
55
+
56
+ Parameters
57
+ ----------
58
+ img_path : Path | str
59
+ Path to image
60
+ data_tag : bool, optional
61
+ Add data tag before base64 string, by default False
62
+
63
+ Returns
64
+ -------
65
+ str
66
+ Encoded image
67
+ """
68
+ img = Path(img_path)
69
+ with open(img, "rb") as img_file:
70
+ b64_data = base64.b64encode(img_file.read()).decode("utf-8")
71
+ if data_tag:
72
+ return f"data:image/{img.suffix[1:]};charset=utf-8;base64,{b64_data}"
73
+ return b64_data
74
+
51
75
 
52
76
  class ChemistryElement:
53
77
  """Chemistry Element"""
@@ -217,7 +217,7 @@ class Obfuscator:
217
217
  )
218
218
  for x in bait_lst:
219
219
  output.append(
220
- f"{x}='{gen.generate_string(charset=Charset.DEFAULT,size=self.split_every_length,times=1,string_type_if_1=True)}'"
220
+ f"{x}='{gen.generate_string(charset=Charset.DEFAULT, size=self.split_every_length, times=1, string_type_if_1=True)}'"
221
221
  )
222
222
 
223
223
  random_eval_text = str(random.randint(1, 100))
@@ -0,0 +1,228 @@
1
+ """
2
+ Absfuyu: Shorten number
3
+ ---------------
4
+ Short number base on suffixes
5
+
6
+ Version: 1.0.0
7
+ Last update: 01/02/2025 (dd/mm/yyyy)
8
+ """
9
+
10
+ # Module level
11
+ ###########################################################################
12
+ __all__ = ["UnitSuffixFactory", "CommonUnitSuffixesFactory", "Decimal"]
13
+
14
+
15
+ # Library
16
+ ###########################################################################
17
+ from dataclasses import dataclass, field
18
+ from typing import Annotated, NamedTuple, Self
19
+
20
+
21
+ # Class
22
+ ###########################################################################
23
+ class UnitSuffixFactory(NamedTuple):
24
+ base: int
25
+ short_name: list[str]
26
+ full_name: list[str]
27
+
28
+
29
+ class CommonUnitSuffixesFactory:
30
+ NUMBER = UnitSuffixFactory(
31
+ 1000,
32
+ [
33
+ "",
34
+ "K",
35
+ "M",
36
+ "B",
37
+ "T",
38
+ "Qa",
39
+ "Qi",
40
+ "Sx",
41
+ "Sp",
42
+ "Oc",
43
+ "No",
44
+ "Dc",
45
+ "Ud",
46
+ "Dd",
47
+ "Td",
48
+ "Qad",
49
+ "Qid",
50
+ "Sxd",
51
+ "Spd",
52
+ "Ocd",
53
+ "Nod",
54
+ "Vg",
55
+ "Uvg",
56
+ "Dvg",
57
+ "Tvg",
58
+ "Qavg",
59
+ "Qivg",
60
+ "Sxvg",
61
+ "Spvg",
62
+ "Ovg",
63
+ "Nvg",
64
+ "Tg",
65
+ "Utg",
66
+ "Dtg",
67
+ "Ttg",
68
+ "Qatg",
69
+ "Qitg",
70
+ "Sxtg",
71
+ "Sptg",
72
+ "Otg",
73
+ "Ntg",
74
+ ],
75
+ [
76
+ "", # < Thousand
77
+ "Thousand",
78
+ "Million",
79
+ "Billion", # 1e9
80
+ "Trillion",
81
+ "Quadrillion",
82
+ "Quintillion",
83
+ "Sextillion",
84
+ "Septillion",
85
+ "Octillion",
86
+ "Nonillion",
87
+ "Decillion", # 1e33
88
+ "Undecillion",
89
+ "Duodecillion",
90
+ "Tredecillion",
91
+ "Quattuordecillion",
92
+ "Quindecillion",
93
+ "Sexdecillion",
94
+ "Septendecillion",
95
+ "Octodecillion",
96
+ "Novemdecillion",
97
+ "Vigintillion", # 1e63
98
+ "Unvigintillion",
99
+ "Duovigintillion",
100
+ "Tresvigintillion",
101
+ "Quattuorvigintillion",
102
+ "Quinvigintillion",
103
+ "Sesvigintillion",
104
+ "Septemvigintillion",
105
+ "Octovigintillion",
106
+ "Novemvigintillion",
107
+ "Trigintillion", # 1e93
108
+ "Untrigintillion",
109
+ "Duotrigintillion",
110
+ "Trestrigintillion",
111
+ "Quattuortrigintillion",
112
+ "Quintrigintillion",
113
+ "Sestrigintillion",
114
+ "Septentrigintillion",
115
+ "Octotrigintillion",
116
+ "Noventrigintillion", # 1e120
117
+ ],
118
+ )
119
+ DATA_SIZE = UnitSuffixFactory(
120
+ 1024,
121
+ ["b", "Kb", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", "BB"],
122
+ [
123
+ "byte",
124
+ "kilobyte",
125
+ "megabyte",
126
+ "gigabyte",
127
+ "terabyte",
128
+ "petabyte",
129
+ "exabyte",
130
+ "zetabyte",
131
+ "yottabyte",
132
+ "brontobyte",
133
+ ],
134
+ )
135
+
136
+
137
+ @dataclass
138
+ class Decimal:
139
+ """
140
+ Shorten large number
141
+
142
+ :param original_value: Value to shorten
143
+ :param base: Short by base (must be > 0)
144
+ :param suffixes: List of suffixes to use (ascending order)
145
+ :param factory: ``UnitSuffixFactory`` to use (will overwrite ``base`` and ``suffixes``)
146
+ :param suffix_full_name: Use suffix full name (default: False)
147
+ """
148
+
149
+ original_value: int | float = field(repr=False)
150
+ base: Annotated[int, "positive", "not_zero"] = field(repr=False, default=1000)
151
+ suffixes: list[str] = field(repr=False, default_factory=list)
152
+ factory: UnitSuffixFactory | None = field(repr=False, default=None)
153
+ suffix_full_name: bool = field(repr=False, default=False)
154
+ # Post init
155
+ value: int | float = field(init=False)
156
+ suffix: str = field(init=False)
157
+
158
+ def __post_init__(self) -> None:
159
+ self._get_factory()
160
+ self.value, self.suffix = self._convert_decimal()
161
+
162
+ def __str__(self) -> str:
163
+ return self.to_text()
164
+
165
+ @classmethod
166
+ def number(cls, value: int | float, suffix_full_name: bool = False) -> Self:
167
+ """Decimal for normal large number"""
168
+ return cls(
169
+ value,
170
+ factory=CommonUnitSuffixesFactory.NUMBER,
171
+ suffix_full_name=suffix_full_name,
172
+ )
173
+
174
+ @classmethod
175
+ def data_size(cls, value: int | float, suffix_full_name: bool = False) -> Self:
176
+ """Decimal for data size"""
177
+ return cls(
178
+ value,
179
+ factory=CommonUnitSuffixesFactory.DATA_SIZE,
180
+ suffix_full_name=suffix_full_name,
181
+ )
182
+
183
+ @staticmethod
184
+ def scientific_short(value: int | float) -> str:
185
+ """Short number in scientific format"""
186
+ return f"{value:.2e}"
187
+
188
+ def _get_factory(self) -> None:
189
+ if self.factory:
190
+ self.base = self.factory.base
191
+ self.suffixes = (
192
+ self.factory.full_name
193
+ if self.suffix_full_name
194
+ else self.factory.short_name
195
+ )
196
+
197
+ def _convert_decimal(self) -> tuple[float, str]:
198
+ """Convert to smaller number"""
199
+ suffix = self.suffixes[0] if len(self.suffixes) > 0 else ""
200
+ unit = 1
201
+ for i, suffix in enumerate(self.suffixes):
202
+ unit = self.base**i
203
+ if self.original_value < unit * self.base:
204
+ break
205
+ output = self.original_value / unit
206
+ return output, suffix
207
+
208
+ def to_text(
209
+ self, decimal: int = 2, *, separator: str = " ", float_only: bool = True
210
+ ) -> str:
211
+ """
212
+ Convert to string
213
+
214
+ :param decimal: Round up to which decimal
215
+ :param separator: Character between value and suffix, default: ``" "``
216
+ :param float_only: Returns value as <float> instead of <int> when ``decimal = 0``
217
+ """
218
+ val = self.value.__round__(decimal)
219
+ formatted_value = f"{val:,}"
220
+ if not float_only and decimal == 0:
221
+ formatted_value = f"{int(val):,}"
222
+ return f"{formatted_value}{separator}{self.suffix}"
223
+
224
+
225
+ # Run
226
+ ###########################################################################
227
+ if __name__ == "__main__":
228
+ print(str(Decimal.number(10000)))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: absfuyu
3
- Version: 4.0.0
3
+ Version: 4.1.0
4
4
  Summary: A small collection of code
5
5
  Project-URL: Homepage, https://github.com/AbsoluteWinter/absfuyu-public
6
6
  Project-URL: Documentation, https://absolutewinter.github.io/absfuyu-docs/
@@ -46,6 +46,7 @@ Requires-Dist: absfuyu-res; extra == 'full'
46
46
  Requires-Dist: numpy; extra == 'full'
47
47
  Requires-Dist: pandas; extra == 'full'
48
48
  Requires-Dist: rich; extra == 'full'
49
+ Requires-Dist: tqdm; extra == 'full'
49
50
  Provides-Extra: res
50
51
  Requires-Dist: absfuyu-res; extra == 'res'
51
52
  Description-Content-Type: text/markdown
@@ -1,15 +1,15 @@
1
- absfuyu/__init__.py,sha256=3QPuQhsAV4d3FaiT_3HTn6df1fPKIPDCxng8qpVULDU,638
1
+ absfuyu/__init__.py,sha256=H-4MDDeiuQVuYt4Qrv8ae8286dc3Vv2JHgOkU6VxCKw,638
2
2
  absfuyu/__main__.py,sha256=OpMwc35W5VANzw6gvlqJaJOl2H89i_frFZbleUQwDss,163
3
- absfuyu/core.py,sha256=NW8veKHacn7hPqlnVXLGEmj_gzip2R3JgfFNwUTuwtU,959
3
+ absfuyu/core.py,sha256=pGN-tBD5S_p0lm3f0clPujnH9n6JZSD1cqNilBM-ZK0,1279
4
4
  absfuyu/everything.py,sha256=PGIXlqgxyADFPygohVYVIb7fZz72L_xXrlLX0WImuYg,788
5
- absfuyu/logger.py,sha256=vT0CniqNv-cNXbtkhu1jaOhehHvlInHQt1PFsna5qIY,13135
5
+ absfuyu/logger.py,sha256=Pue3oWYYSF03A-fVp3E137jzlZVI71mYqddic8myauQ,13141
6
6
  absfuyu/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  absfuyu/sort.py,sha256=Z9nK15WehmZjlUNwvAOwF4FhV-rFcqlXkCcehNYmo78,6827
8
8
  absfuyu/version.py,sha256=KMaeXNl93L4VU2RnTySoFv23IDyTvHfy84nyatFcKaE,14128
9
9
  absfuyu/cli/__init__.py,sha256=nKTbe4iPpkjtDDMJwVY36heInKDm1zyek9ags5an7s4,1105
10
10
  absfuyu/cli/color.py,sha256=7M3XqFllt26tv_NR5qKgyTId6wnVADtUB74cDYy8pOQ,497
11
11
  absfuyu/cli/config_group.py,sha256=FsyYm2apSyAA2PAD12CpHAizenRds_QlLf8j0AlLuVo,1230
12
- absfuyu/cli/do_group.py,sha256=xjdMhivqFLvK-beNoOhQBl5c2mB9gcFMdmBKlCWFfL4,2645
12
+ absfuyu/cli/do_group.py,sha256=_GzTrxZwVtrTl3kTd_MQTstX5DKQTjDbFgHmlghanP0,3533
13
13
  absfuyu/cli/game_group.py,sha256=ySpL2hm4VCplhNY0s22kBGI5eFCdJj9fm1T58yftU74,2348
14
14
  absfuyu/config/__init__.py,sha256=4r77tFm3mgHX8H1uWWNXC_FZ8hiSJzsYAyiStZiVj5w,8641
15
15
  absfuyu/config/config.json,sha256=-ZQnmDuLq0aAFfsrQbSNR3tq5k9Eu9IVUQgYD9htIQM,646
@@ -25,23 +25,24 @@ absfuyu/extensions/extra/data_analysis.py,sha256=JR8smS6gVRZ4jJtboshCpC3jFabVLQ8
25
25
  absfuyu/fun/WGS.py,sha256=Aug9BsLTawBDkjdCQ3oqWAfGGeY6ZSBV1kENrTVnlUA,9461
26
26
  absfuyu/fun/__init__.py,sha256=AOaq3NdgaK7e5hk622Wspiu6Z2biVK-jpk2FChn05rA,6366
27
27
  absfuyu/fun/tarot.py,sha256=Y0z5rNWLOmqfJV961L_9LzUORRNR89Vegy7KqgNR9xs,2539
28
- absfuyu/game/__init__.py,sha256=Nnkhnca6aw-kg98kExhUeX78dqu_ivQzB_pFvyI21XE,4417
29
- absfuyu/game/game_stat.py,sha256=4limsvYGw_t2PMZXrGfivouc4SDexFcc9f3SjXGVj_o,961
28
+ absfuyu/game/__init__.py,sha256=qOPsnjKXSc1LobDQmF131BrBIyOEy0oddFRCEHsg8P8,4419
29
+ absfuyu/game/game_stat.py,sha256=xayD7zkcR76m-5UOx8flEE5MO_LEZoCe6FnFyPg4YE4,963
30
30
  absfuyu/game/sudoku.py,sha256=zMsQ2opVFpREZMdSmu2ZXwV4mu463rRLdwrGV9qwg2s,10130
31
31
  absfuyu/game/tictactoe.py,sha256=OfI7WHxxiAbhuRAt8qsDG1BJuc3hlhX4N6-HORq9fbI,9603
32
32
  absfuyu/game/wordle.py,sha256=1RpgB8fBgcL_E2TgbTFXjZHtzthJQysCAl0fbK_LG5w,101336
33
33
  absfuyu/general/__init__.py,sha256=6AJZ7Ul6l8MKaqEwRD2ktQUIBfhTPaDUYDQB7MUQ5rc,2481
34
- absfuyu/general/content.py,sha256=7yhl-6Rhyp2geNpuKQkuhxor3EcyovW3COdiYsmjUDI,17441
35
- absfuyu/general/data_extension.py,sha256=iCuJq_x7XDhhxUzu86rt7iQd170urGjCiPG3dcw88rk,48932
36
- absfuyu/general/generator.py,sha256=pozKlZgTqKxzwsKR6-tI8Lel0qTjTMubv4T3Zk7ifEQ,9691
34
+ absfuyu/general/content.py,sha256=IfX5SkgoD-sjYJrbRHRIS5-g6fGp_X65A07ViB0zLpk,17443
35
+ absfuyu/general/data_extension.py,sha256=tvZM4moHNxqOh_iT6ekFELZgfhiIoZ8SUqm9wUIaokU,48938
36
+ absfuyu/general/generator.py,sha256=PW_4Z-YZ30StwDuUUfHD7B0qnVKMo_ZZHHKj54BzgXk,9731
37
37
  absfuyu/general/human.py,sha256=drZT1nI_YwGMOwZu8pbzf3frM-SUY15cOcnUpc4pzQk,12241
38
38
  absfuyu/pkg_data/__init__.py,sha256=VbUoFnUDiw_3bKZVvIzwf_ve0y97rmhfpkbbrP_ob_w,4761
39
39
  absfuyu/pkg_data/chemistry.pkl,sha256=kYWNa_PVffoDnzT8b9Jvimmf_GZshPe1D-SnEKERsLo,4655
40
40
  absfuyu/pkg_data/tarot.pkl,sha256=ssXTCC_BQgslO5F-3a9HivbxFQ6BioIe2E1frPVi2m0,56195
41
41
  absfuyu/tools/__init__.py,sha256=VDmmMLEfiRyUWPVrPYc8JUEa5TXjLguKVnyI3YavFv0,118
42
- absfuyu/tools/converter.py,sha256=tHIuunrEoX8wai0lXda3nQBKr2ymO5-cxy0dEIuOsVc,9871
42
+ absfuyu/tools/checksum.py,sha256=33DlwXRqPcatuNJ14NG9gJLe3y5RgnJm0w0dkSFurhU,1563
43
+ absfuyu/tools/converter.py,sha256=8jqOSdkbzzupKJcBndV5q4OBu2kWFWpV3j2IswS4Vqc,10609
43
44
  absfuyu/tools/keygen.py,sha256=drj8OUDCXrLvcVf9_Shd5UMShm_mBTxa9Sg_BrAT5yM,7356
44
- absfuyu/tools/obfuscator.py,sha256=c1HMEg40BY9XM_dHK1mokjHE9Sp5Vd083oFxvPnFrKA,8666
45
+ absfuyu/tools/obfuscator.py,sha256=kiaFvMw2RwEfZvXKdbUrEYA_AuVETivoL2eVmtUWU4w,8669
45
46
  absfuyu/tools/stats.py,sha256=zZNK59qn0xqQlyw5CP3MP5WRMSxncdKZythqvgNR1lQ,5191
46
47
  absfuyu/tools/web.py,sha256=Mb5RYj1Fu5eB-mYMusyrE2JG6_ZPEf8WT72Z8q6Ep74,1406
47
48
  absfuyu/util/__init__.py,sha256=1V2DwIUt-bSiSURnk6AzfKB0HRLHwoi8_6RaIvywlzU,3716
@@ -51,9 +52,10 @@ absfuyu/util/lunar.py,sha256=xW7HcgyIRjWBhQv36RimNZIT8Ed_X83moqr5h5-Ku9k,13750
51
52
  absfuyu/util/path.py,sha256=p4Ac98FfW5pXLNRRuQ_QEx_G7-UOSBKABAg_xrOq7u4,16628
52
53
  absfuyu/util/performance.py,sha256=F-aLJ-5wmwkiOdl9_wZcFRKifL9zOahw52JeL4TbCuQ,9105
53
54
  absfuyu/util/pkl.py,sha256=ZZf6-PFC2uRGXqARNi0PGH3A0IXwMP0sYPWZJXENvak,1559
55
+ absfuyu/util/shorten_number.py,sha256=_R_FhzBYDvtX_B8jA0WhVyG2G_s-kyolra9Y2gH5e4w,6603
54
56
  absfuyu/util/zipped.py,sha256=CU_le1MynFwHfpajCRRJ7_A-r1jfMjt9uu72jLooW6w,3111
55
- absfuyu-4.0.0.dist-info/METADATA,sha256=t6D2KuZnSo6spME1rJtjEReUJ9nlv8pK9lxEJGixqnA,3757
56
- absfuyu-4.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
57
- absfuyu-4.0.0.dist-info/entry_points.txt,sha256=bW5CgJRTTWJ2Pywojo07sf-YucRPcnHzMmETh5avbX0,79
58
- absfuyu-4.0.0.dist-info/licenses/LICENSE,sha256=_tQM-uZht2y-26_MHcIasBp8gtJ2YmvLOezIbhixrAA,1076
59
- absfuyu-4.0.0.dist-info/RECORD,,
57
+ absfuyu-4.1.0.dist-info/METADATA,sha256=xcjNv6lMttGHr7okEXP4HHZ2V2hGAhFV74q_zpBDBMw,3794
58
+ absfuyu-4.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
59
+ absfuyu-4.1.0.dist-info/entry_points.txt,sha256=bW5CgJRTTWJ2Pywojo07sf-YucRPcnHzMmETh5avbX0,79
60
+ absfuyu-4.1.0.dist-info/licenses/LICENSE,sha256=pFCHBSNSzdXwYG1AHpq7VcofI1NMQ1Fc77RzZ4Ln2O4,1097
61
+ absfuyu-4.1.0.dist-info/RECORD,,
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2022-2024 AbsoluteWinter
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2022-2025 AbsoluteWinter
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.