absfuyu 3.4.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/game/sudoku.py CHANGED
@@ -3,8 +3,8 @@ Game: Sudoku
3
3
  ------------
4
4
  Sudoku 9x9 Solver
5
5
 
6
- Version: 1.0.2
7
- Date updated: 24/11/2023 (mm/dd/yyyy)
6
+ Version: 1.0.3
7
+ Date updated: 15/11/2024 (dd/mm/yyyy)
8
8
 
9
9
  Credit:
10
10
  -------
@@ -15,11 +15,12 @@ Credit:
15
15
  __all__ = ["Sudoku"]
16
16
 
17
17
 
18
- from typing import List, Literal, Tuple
18
+ from typing import Literal
19
19
 
20
20
 
21
21
  class Sudoku:
22
- def __init__(self, sudoku_data: List[List[int]]) -> None:
22
+
23
+ def __init__(self, sudoku_data: list[list[int]]) -> None:
23
24
  self.data = sudoku_data
24
25
  # self._original = sudoku_data # Make backup
25
26
  self._row_len = len(self.data)
@@ -194,7 +195,7 @@ class Sudoku:
194
195
  # Return None when there is no empty cell
195
196
  return None
196
197
 
197
- def _is_valid(self, number: int, position: Tuple[int, int]) -> bool:
198
+ def _is_valid(self, number: int, position: tuple[int, int]) -> bool:
198
199
  """
199
200
  Check valid number value in row, column, box
200
201
  """
absfuyu/game/tictactoe.py CHANGED
@@ -2,8 +2,8 @@
2
2
  Game: Tic Tac Toe
3
3
  -----------------
4
4
 
5
- Version: 2.0.3
6
- Date updated: 05/04/2024 (mm/dd/yyyy)
5
+ Version: 2.0.4
6
+ Date updated: 15/11/2024 (dd/mm/yyyy)
7
7
  """
8
8
 
9
9
  __all__ = ["TicTacToe", "GameMode"]
@@ -11,11 +11,11 @@ __all__ = ["TicTacToe", "GameMode"]
11
11
 
12
12
  import random
13
13
  import time
14
- from typing import List, Literal, NamedTuple
14
+ from typing import Literal, NamedTuple
15
15
 
16
16
  from absfuyu.core import CLITextColor
17
17
 
18
- BoardGame = List[List[str]]
18
+ BoardGame = list[list[str]]
19
19
 
20
20
 
21
21
  class Pos(NamedTuple):
@@ -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)
@@ -3,8 +3,8 @@ Absfuyu: Data extension
3
3
  -----------------------
4
4
  Extension for data type such as ``list``, ``str``, ``dict``, ...
5
5
 
6
- Version: 1.15.0
7
- Date updated: 27/04/2024 (dd/mm/yyyy)
6
+ Version: 1.15.2
7
+ Date updated: 06/01/2025 (dd/mm/yyyy)
8
8
 
9
9
  Features:
10
10
  ---------
@@ -47,23 +47,7 @@ import operator
47
47
  import random
48
48
  from collections import Counter
49
49
  from itertools import accumulate, chain, groupby
50
- from sys import version_info as _python_version
51
- from typing import (
52
- Any,
53
- Callable,
54
- Dict,
55
- List,
56
- NamedTuple,
57
- Optional,
58
- Tuple,
59
- TypedDict,
60
- Union,
61
- )
62
-
63
- if _python_version.minor >= 11:
64
- from typing import NotRequired, Self
65
- else:
66
- from typing_extensions import NotRequired, Self # type: ignore
50
+ from typing import Any, Callable, NamedTuple, NotRequired, Self, TypedDict, Union
67
51
 
68
52
  from deprecated.sphinx import versionadded, versionchanged
69
53
 
@@ -74,7 +58,7 @@ from absfuyu.util import set_min, set_min_max
74
58
 
75
59
  # Function
76
60
  ###########################################################################
77
- def _dict_bool(dict_object: dict, option: bool) -> Optional[dict]:
61
+ def _dict_bool(dict_object: dict, option: bool) -> dict | None:
78
62
  """
79
63
  Support function DictBool class
80
64
  """
@@ -93,7 +77,7 @@ def _dict_bool(dict_object: dict, option: bool) -> Optional[dict]:
93
77
  class Pow:
94
78
  """Number power by a number"""
95
79
 
96
- def __init__(self, number: Union[int, float], power_by: Union[int, float]) -> None:
80
+ def __init__(self, number: int | float, power_by: int | float) -> None:
97
81
  self.number = number
98
82
  self.power_by = power_by
99
83
 
@@ -107,7 +91,7 @@ class Pow:
107
91
  def __repr__(self) -> str:
108
92
  return self.__str__()
109
93
 
110
- def to_list(self) -> List[Union[int, float]]:
94
+ def to_list(self) -> list[int | float]:
111
95
  """
112
96
  Convert into list
113
97
 
@@ -132,7 +116,7 @@ class ListREPR(list):
132
116
  return _compress_list_for_print(self, 9)
133
117
 
134
118
 
135
- class ListNoDunder(List[str]):
119
+ class ListNoDunder(list[str]):
136
120
  """Use with ``object.__dir__()``"""
137
121
 
138
122
  def __repr__(self) -> str:
@@ -140,7 +124,7 @@ class ListNoDunder(List[str]):
140
124
  return out.__repr__()
141
125
 
142
126
 
143
- class DictBoolTrue(Dict[Any, bool]):
127
+ class DictBoolTrue(dict[Any, bool]):
144
128
  """Only show items when ``values == True`` in ``__repr__()``"""
145
129
 
146
130
  def __repr__(self) -> str:
@@ -148,7 +132,7 @@ class DictBoolTrue(Dict[Any, bool]):
148
132
  return _dict_bool(temp, True).__repr__()
149
133
 
150
134
 
151
- class DictBoolFalse(Dict[Any, bool]):
135
+ class DictBoolFalse(dict[Any, bool]):
152
136
  """Only show items when ``values == False`` in ``__repr__()``"""
153
137
 
154
138
  def __repr__(self) -> str:
@@ -206,8 +190,8 @@ class DictAnalyzeResult(NamedTuple):
206
190
  Result for ``DictExt.analyze()``
207
191
  """
208
192
 
209
- max_value: Union[int, float]
210
- min_value: Union[int, float]
193
+ max_value: int | float
194
+ min_value: int | float
211
195
  max_list: list
212
196
  min_list: list
213
197
 
@@ -220,7 +204,7 @@ class Text(str):
220
204
  ``str`` extension
221
205
  """
222
206
 
223
- def divide(self, string_split_size: int = 60) -> List[str]:
207
+ def divide(self, string_split_size: int = 60) -> list[str]:
224
208
  """
225
209
  Divide long string into smaller size
226
210
 
@@ -255,8 +239,8 @@ class Text(str):
255
239
  self,
256
240
  split_size: int = 60,
257
241
  split_var_len: int = 12,
258
- custom_var_name: Optional[str] = None,
259
- ) -> List[str]:
242
+ custom_var_name: str | None = None,
243
+ ) -> list[str]:
260
244
  """
261
245
  Divide long string into smaller size,
262
246
  then assign a random variable to splited
@@ -318,7 +302,7 @@ class Text(str):
318
302
  output.append(f"{splt_name[i]}='{temp[i]}'")
319
303
  else:
320
304
  for i in range(splt_len):
321
- output.append(f"{custom_var_name}{i+1}='{temp[i]}'")
305
+ output.append(f"{custom_var_name}{i + 1}='{temp[i]}'")
322
306
 
323
307
  # joined variable
324
308
  temp = []
@@ -335,9 +319,9 @@ class Text(str):
335
319
  if i == 0:
336
320
  temp.append(f"{custom_var_name}=")
337
321
  if i == splt_len - 1:
338
- temp.append(f"{custom_var_name}{i+1}")
322
+ temp.append(f"{custom_var_name}{i + 1}")
339
323
  else:
340
- temp.append(f"{custom_var_name}{i+1}+")
324
+ temp.append(f"{custom_var_name}{i + 1}+")
341
325
 
342
326
  output.append("".join(temp))
343
327
  if custom_var_name is None:
@@ -546,7 +530,7 @@ class Text(str):
546
530
  temp[i] = x.upper()
547
531
  return self.__class__("".join(temp))
548
532
 
549
- def to_list(self) -> List[str]:
533
+ def to_list(self) -> list[str]:
550
534
  """
551
535
  Convert into list
552
536
 
@@ -625,7 +609,7 @@ class Text(str):
625
609
  return sum(out)
626
610
 
627
611
  @versionadded(version="3.3.0")
628
- def hapax(self, strict: bool = False) -> List[str]:
612
+ def hapax(self, strict: bool = False) -> list[str]:
629
613
  """
630
614
  A hapax legomenon (often abbreviated to hapax)
631
615
  is a word which occurs only once in either
@@ -656,9 +640,9 @@ class Text(str):
656
640
  >>> test.hapax(strict=True)
657
641
  ['b']
658
642
  """
659
- word_list: List[str] = self.lower().split()
643
+ word_list: list[str] = self.lower().split()
660
644
  if strict:
661
- remove_characters: List[str] = list(r"\"'.,:;|()[]{}\/!@#$%^&*-_=+?<>`~")
645
+ remove_characters: list[str] = list(r"\"'.,:;|()[]{}\/!@#$%^&*-_=+?<>`~")
662
646
  temp = str(self)
663
647
  for x in remove_characters:
664
648
  temp = temp.replace(x, "")
@@ -845,7 +829,7 @@ class IntNumber(int):
845
829
 
846
830
  else:
847
831
  # Faster way to check
848
- perfect_number_index: List[int] = [
832
+ perfect_number_index: list[int] = [
849
833
  61,
850
834
  89,
851
835
  107,
@@ -982,7 +966,7 @@ class IntNumber(int):
982
966
  return self.is_palindromic() and self.is_prime()
983
967
 
984
968
  # calculation stuff
985
- @versionchanged(version="3.3.0", reason="Fix bug")
969
+ @versionchanged(version="4.0.0", reason="Update")
986
970
  def lcm(self, with_number: int) -> Self:
987
971
  """
988
972
  Least common multiple of ``self`` and ``with_number``
@@ -1004,10 +988,7 @@ class IntNumber(int):
1004
988
  >>> test.lcm(5)
1005
989
  510
1006
990
  """
1007
- try:
1008
- return self.__class__(math.lcm(self, with_number))
1009
- except AttributeError: # Python < 3.9
1010
- return self.__class__((self * with_number) // math.gcd(self, with_number))
991
+ return self.__class__(math.lcm(self, with_number))
1011
992
 
1012
993
  @versionchanged(version="3.3.0", reason="Fix bug")
1013
994
  def gcd(self, with_number: int) -> Self:
@@ -1072,7 +1053,7 @@ class IntNumber(int):
1072
1053
  logger.debug(f"Sum after loop: {number}")
1073
1054
  return self.__class__(number)
1074
1055
 
1075
- def divisible_list(self, short_form: bool = True) -> List[int]:
1056
+ def divisible_list(self, short_form: bool = True) -> list[int]:
1076
1057
  """
1077
1058
  A list of divisible number
1078
1059
 
@@ -1106,7 +1087,7 @@ class IntNumber(int):
1106
1087
  # return ListREPR(divi_list) ## FIX LATER
1107
1088
  return divi_list
1108
1089
 
1109
- def prime_factor(self, short_form: bool = True) -> Union[List[int], List[Pow]]:
1090
+ def prime_factor(self, short_form: bool = True) -> Union[list[int], list[Pow]]:
1110
1091
  """
1111
1092
  Prime factor
1112
1093
 
@@ -1156,7 +1137,7 @@ class IntNumber(int):
1156
1137
  return factors
1157
1138
 
1158
1139
  # analyze
1159
- def analyze(self, short_form: bool = True) -> Dict[str, Dict[str, Any]]:
1140
+ def analyze(self, short_form: bool = True) -> dict[str, dict[str, Any]]:
1160
1141
  """
1161
1142
  Analyze the number with almost all ``IntNumber`` method
1162
1143
 
@@ -1236,7 +1217,7 @@ class ListExt(list):
1236
1217
  >>> test.stringify()
1237
1218
  ['1', '1', '1', '2', '2', '3']
1238
1219
  """
1239
- return ListExt(map(str, self))
1220
+ return self.__class__(map(str, self))
1240
1221
 
1241
1222
  def head(self, number_of_items: int = 5) -> list:
1242
1223
  """
@@ -1318,9 +1299,9 @@ class ListExt(list):
1318
1299
  def freq(
1319
1300
  self,
1320
1301
  sort: bool = False,
1321
- num_of_first_char: Optional[int] = None,
1302
+ num_of_first_char: int | None = None,
1322
1303
  appear_increment: bool = False,
1323
- ) -> Union[dict, List[int]]:
1304
+ ) -> Union[dict, list[int]]:
1324
1305
  """
1325
1306
  Find frequency of each item in list
1326
1307
 
@@ -1383,7 +1364,7 @@ class ListExt(list):
1383
1364
  logger.debug(times_appear)
1384
1365
 
1385
1366
  if appear_increment:
1386
- times_appear_increment: List[int] = list(
1367
+ times_appear_increment: list[int] = list(
1387
1368
  accumulate(times_appear.values(), operator.add)
1388
1369
  )
1389
1370
  logger.debug(times_appear_increment)
@@ -1391,7 +1372,7 @@ class ListExt(list):
1391
1372
  else:
1392
1373
  return times_appear
1393
1374
 
1394
- def slice_points(self, points: list) -> List[list]:
1375
+ def slice_points(self, points: list) -> list[list]:
1395
1376
  """
1396
1377
  Slices a list at specific indices into constituent lists.
1397
1378
 
@@ -1474,7 +1455,7 @@ class ListExt(list):
1474
1455
  >>> test.len_items()
1475
1456
  [3, 3, 5]
1476
1457
  """
1477
- out = ListExt([len(str(x)) for x in self])
1458
+ out = self.__class__([len(str(x)) for x in self])
1478
1459
  # out = ListExt(map(lambda x: len(str(x)), self))
1479
1460
  logger.debug(out)
1480
1461
  return out
@@ -1566,13 +1547,13 @@ class ListExt(list):
1566
1547
  return self.__class__([list(g) for _, g in temp])
1567
1548
 
1568
1549
  @staticmethod
1569
- def _group_by_unique(iterable: list) -> List[list]:
1550
+ def _group_by_unique(iterable: list) -> list[list]:
1570
1551
  """
1571
1552
  Static method for ``group_by_unique``
1572
1553
  """
1573
1554
  return list([list(g) for _, g in groupby(iterable)])
1574
1555
 
1575
- def group_by_pair_value(self, max_loop: int = 3) -> List[list]:
1556
+ def group_by_pair_value(self, max_loop: int = 3) -> list[list]:
1576
1557
  """
1577
1558
  Assume each ``list`` in ``list`` is a pair value,
1578
1559
  returns a ``list`` contain all paired value
@@ -1607,7 +1588,7 @@ class ListExt(list):
1607
1588
 
1608
1589
  # Init loop
1609
1590
  for _ in range(int(set_min(max_loop, min_value=3))):
1610
- temp: Dict[Any, list] = {}
1591
+ temp: dict[Any, list] = {}
1611
1592
  # Make dict{key: all `item` that contains `key`}
1612
1593
  for item in iter:
1613
1594
  for x in item:
@@ -1641,10 +1622,10 @@ class ListExt(list):
1641
1622
  ['test', 'test', 'test', 'test']
1642
1623
  """
1643
1624
  try:
1644
- return ListExt(chain(*self))
1625
+ return self.__class__(chain(*self))
1645
1626
  except Exception:
1646
1627
  temp = list(map(lambda x: x if isinstance(x, list) else [x], self))
1647
- return ListExt(chain(*temp))
1628
+ return self.__class__(chain(*temp))
1648
1629
 
1649
1630
  def numbering(self, start: int = 0) -> Self:
1650
1631
  """
@@ -1670,10 +1651,10 @@ class ListExt(list):
1670
1651
  [(0, 9), (1, 9), (2, 9)]
1671
1652
  """
1672
1653
  start = int(set_min(start, min_value=0))
1673
- return ListExt(enumerate(self, start=start))
1654
+ return self.__class__(enumerate(self, start=start))
1674
1655
 
1675
1656
  @staticmethod
1676
- def _numbering(iterable: list, start: int = 0) -> List[Tuple[int, Any]]:
1657
+ def _numbering(iterable: list, start: int = 0) -> list[tuple[int, Any]]:
1677
1658
  """
1678
1659
  Static method for ``numbering``
1679
1660
  """
@@ -1717,8 +1698,8 @@ class DictExt(dict):
1717
1698
  try:
1718
1699
  dct: dict = self.copy()
1719
1700
 
1720
- max_val: Union[int, float] = max(list(dct.values()))
1721
- min_val: Union[int, float] = min(list(dct.values()))
1701
+ max_val: int | float = max(list(dct.values()))
1702
+ min_val: int | float = min(list(dct.values()))
1722
1703
  max_list = []
1723
1704
  min_list = []
1724
1705
 
@@ -1798,8 +1779,8 @@ class DictExt(dict):
1798
1779
  @versionadded(version="3.4.0")
1799
1780
  def aggregate(
1800
1781
  self,
1801
- other_dict: Dict[Any, Union[int, float]],
1802
- default_value: Union[int, float] = 0,
1782
+ other_dict: dict[Any, int | float],
1783
+ default_value: int | float = 0,
1803
1784
  ) -> Self:
1804
1785
  """Dict with value type int or float"""
1805
1786
  out = {
@@ -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
 
@@ -3,8 +3,8 @@ Absfuyu: Package data
3
3
  ---------------------
4
4
  Load package data
5
5
 
6
- Version: 2.2.2
7
- Date updated: 30/11/2023 (dd/mm/yyyy)
6
+ Version: 2.2.3
7
+ Date updated: 14/11/2024 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module level
@@ -16,18 +16,8 @@ __all__ = ["PkgData"]
16
16
  ###########################################################################
17
17
  import zlib
18
18
  from ast import literal_eval
19
- from importlib.resources import read_binary
19
+ from importlib.resources import files, read_binary
20
20
  from pathlib import Path
21
- from sys import version_info as _python_version
22
- from typing import List, Union
23
-
24
- if _python_version.minor >= 10:
25
- from importlib.resources import files
26
- else:
27
- try:
28
- from importlib_resources import files # type: ignore
29
- except Exception:
30
- raise ImportError("Please install importlib-resources") # noqa: B904
31
21
 
32
22
  from absfuyu.core import DATA_PATH
33
23
  from absfuyu.logger import logger
@@ -61,7 +51,7 @@ class PkgData:
61
51
  def __repr__(self) -> str:
62
52
  return self.__str__()
63
53
 
64
- def _make_dat(self, data: str, name: Union[str, Path]):
54
+ def _make_dat(self, data: str, name: str | Path):
65
55
  """
66
56
  data: string data
67
57
  name: name and location of the data
@@ -90,14 +80,14 @@ class PkgData:
90
80
 
91
81
  :param new_data: Data to be updated
92
82
  """
93
- self._make_dat(data=new_data, name=DATA_PATH.joinpath(self.name))
83
+ self._make_dat(data=new_data, name=DATA_PATH.joinpath(self.name)) # type:ignore
94
84
  logger.debug("Data updated")
95
85
 
96
86
 
97
87
  class _ManagePkgData:
98
88
  """Manage this package data"""
99
89
 
100
- def __init__(self, pkg_data_loc: Union[str, Path]) -> None:
90
+ def __init__(self, pkg_data_loc: str | Path) -> None:
101
91
  """
102
92
  pkg_data_loc: Package data location
103
93
  """
@@ -109,7 +99,7 @@ class _ManagePkgData:
109
99
  def __repr__(self) -> str:
110
100
  return self.__str__()
111
101
 
112
- def get_data_list(self, *, pattern: str = "*") -> List[Path]:
102
+ def get_data_list(self, *, pattern: str = "*") -> list[Path]:
113
103
  """Get a list of data available"""
114
104
  excludes = [
115
105
  x for x in self.data_loc.glob("*.[pP][yY]")
@@ -119,7 +109,7 @@ class _ManagePkgData:
119
109
  ]
120
110
 
121
111
  @property
122
- def data_list(self) -> List[str]:
112
+ def data_list(self) -> list[str]:
123
113
  """List of available data"""
124
114
  return [x.name for x in self.get_data_list()]
125
115
 
@@ -135,7 +125,10 @@ class _ManagePkgData:
135
125
  for data_name, data_link in _EXTERNAL_DATA.items():
136
126
  logger.debug(f"Downloading {data_name}...")
137
127
  data = APIRequest(data_link, encoding="utf-8")
138
- data.fetch_data(update=True, json_cache=DATA_PATH.joinpath(data_name))
128
+ data.fetch_data(
129
+ update=True,
130
+ json_cache=DATA_PATH.joinpath(data_name), # type:ignore
131
+ )
139
132
  logger.debug(f"Downloading {data_name}...DONE")
140
133
  logger.debug("Downloading data...DONE")
141
134
  except Exception:
@@ -147,7 +140,7 @@ class _ManagePkgData:
147
140
  x.unlink()
148
141
 
149
142
 
150
- PACKAGE_DATA = _ManagePkgData(DATA_PATH)
143
+ PACKAGE_DATA = _ManagePkgData(DATA_PATH) # type:ignore
151
144
 
152
145
 
153
146
  # Run
@@ -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