absfuyu 3.4.0__py3-none-any.whl → 4.0.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 +1 -1
- absfuyu/cli/do_group.py +14 -2
- absfuyu/config/__init__.py +13 -13
- absfuyu/core.py +5 -16
- absfuyu/extensions/extra/data_analysis.py +74 -28
- absfuyu/fun/__init__.py +24 -23
- absfuyu/fun/tarot.py +6 -7
- absfuyu/game/__init__.py +1 -1
- absfuyu/game/sudoku.py +6 -5
- absfuyu/game/tictactoe.py +4 -4
- absfuyu/general/data_extension.py +41 -60
- absfuyu/pkg_data/__init__.py +13 -20
- absfuyu/tools/converter.py +9 -10
- absfuyu/util/__init__.py +13 -14
- absfuyu/util/api.py +7 -7
- absfuyu/util/json_method.py +9 -9
- absfuyu/util/lunar.py +7 -8
- absfuyu/util/path.py +23 -21
- absfuyu/util/performance.py +8 -8
- absfuyu/util/zipped.py +18 -6
- {absfuyu-3.4.0.dist-info → absfuyu-4.0.0.dist-info}/METADATA +5 -9
- {absfuyu-3.4.0.dist-info → absfuyu-4.0.0.dist-info}/RECORD +25 -25
- {absfuyu-3.4.0.dist-info → absfuyu-4.0.0.dist-info}/WHEEL +1 -1
- {absfuyu-3.4.0.dist-info → absfuyu-4.0.0.dist-info}/entry_points.txt +0 -0
- {absfuyu-3.4.0.dist-info → absfuyu-4.0.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -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.
|
|
7
|
-
Date updated:
|
|
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
|
|
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) ->
|
|
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:
|
|
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) ->
|
|
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(
|
|
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(
|
|
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(
|
|
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:
|
|
210
|
-
min_value:
|
|
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) ->
|
|
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:
|
|
259
|
-
) ->
|
|
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
|
|
@@ -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) ->
|
|
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) ->
|
|
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:
|
|
643
|
+
word_list: list[str] = self.lower().split()
|
|
660
644
|
if strict:
|
|
661
|
-
remove_characters:
|
|
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:
|
|
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="
|
|
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
|
-
|
|
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) ->
|
|
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[
|
|
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) ->
|
|
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
|
|
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:
|
|
1302
|
+
num_of_first_char: int | None = None,
|
|
1322
1303
|
appear_increment: bool = False,
|
|
1323
|
-
) -> Union[dict,
|
|
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:
|
|
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) ->
|
|
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 =
|
|
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) ->
|
|
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) ->
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
1654
|
+
return self.__class__(enumerate(self, start=start))
|
|
1674
1655
|
|
|
1675
1656
|
@staticmethod
|
|
1676
|
-
def _numbering(iterable: list, start: int = 0) ->
|
|
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:
|
|
1721
|
-
min_val:
|
|
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:
|
|
1802
|
-
default_value:
|
|
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 = {
|
absfuyu/pkg_data/__init__.py
CHANGED
|
@@ -3,8 +3,8 @@ Absfuyu: Package data
|
|
|
3
3
|
---------------------
|
|
4
4
|
Load package data
|
|
5
5
|
|
|
6
|
-
Version: 2.2.
|
|
7
|
-
Date updated:
|
|
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:
|
|
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:
|
|
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 = "*") ->
|
|
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) ->
|
|
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(
|
|
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
|
absfuyu/tools/converter.py
CHANGED
|
@@ -3,8 +3,8 @@ Absufyu: Converter
|
|
|
3
3
|
------------------
|
|
4
4
|
Convert stuff
|
|
5
5
|
|
|
6
|
-
Version: 1.2.
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 1.2.3
|
|
7
|
+
Date updated: 25/11/2024 (dd/mm/yyyy)
|
|
8
8
|
|
|
9
9
|
Feature:
|
|
10
10
|
--------
|
|
@@ -25,7 +25,6 @@ import math
|
|
|
25
25
|
import re
|
|
26
26
|
import string
|
|
27
27
|
from itertools import chain, combinations
|
|
28
|
-
from typing import Dict, List, Union
|
|
29
28
|
|
|
30
29
|
from absfuyu.core import CLITextColor
|
|
31
30
|
from absfuyu.logger import logger
|
|
@@ -74,7 +73,7 @@ class ChemistryElement:
|
|
|
74
73
|
# return self.symbol
|
|
75
74
|
return f"{self.__class__.__name__}({self.symbol})"
|
|
76
75
|
|
|
77
|
-
def to_dict(self) ->
|
|
76
|
+
def to_dict(self) -> dict[str, str | int | float]:
|
|
78
77
|
"""
|
|
79
78
|
Output content to dict
|
|
80
79
|
|
|
@@ -88,7 +87,7 @@ class ChemistryElement:
|
|
|
88
87
|
}
|
|
89
88
|
|
|
90
89
|
@classmethod
|
|
91
|
-
def from_dict(cls, data:
|
|
90
|
+
def from_dict(cls, data: dict[str, str | int | float]) -> "ChemistryElement":
|
|
92
91
|
"""
|
|
93
92
|
Convert from ``dict`` data
|
|
94
93
|
|
|
@@ -114,11 +113,11 @@ class Text2Chemistry:
|
|
|
114
113
|
def __repr__(self) -> str:
|
|
115
114
|
return self.__str__()
|
|
116
115
|
|
|
117
|
-
def _load_chemistry_data(self) ->
|
|
116
|
+
def _load_chemistry_data(self) -> list[ChemistryElement]:
|
|
118
117
|
"""
|
|
119
118
|
Load chemistry pickle data
|
|
120
119
|
"""
|
|
121
|
-
data:
|
|
120
|
+
data: list[dict] = Pickler.load(self.data_location) # type: ignore
|
|
122
121
|
return [ChemistryElement.from_dict(x) for x in data]
|
|
123
122
|
|
|
124
123
|
@property
|
|
@@ -136,7 +135,7 @@ class Text2Chemistry:
|
|
|
136
135
|
# logger.debug(available)
|
|
137
136
|
return base.difference(available)
|
|
138
137
|
|
|
139
|
-
def convert(self, text: str) ->
|
|
138
|
+
def convert(self, text: str) -> list[list[ChemistryElement]]:
|
|
140
139
|
"""
|
|
141
140
|
Convert text to chemistry symbol
|
|
142
141
|
|
|
@@ -163,7 +162,7 @@ class Text2Chemistry:
|
|
|
163
162
|
data = self._load_chemistry_data()
|
|
164
163
|
|
|
165
164
|
# List possible elements
|
|
166
|
-
possible_elements:
|
|
165
|
+
possible_elements: list[ChemistryElement] = []
|
|
167
166
|
for i, letter in enumerate(text_lower):
|
|
168
167
|
for element in data:
|
|
169
168
|
if element.symbol.lower().startswith(
|
|
@@ -219,7 +218,7 @@ class Str2Pixel:
|
|
|
219
218
|
str_data: str,
|
|
220
219
|
*,
|
|
221
220
|
pixel_size: int = 2,
|
|
222
|
-
pixel_symbol_overwrite:
|
|
221
|
+
pixel_symbol_overwrite: str | None = None,
|
|
223
222
|
) -> None:
|
|
224
223
|
"""
|
|
225
224
|
str_data: Pixel string data (Format: <number_of_pixel><color_code>)
|
absfuyu/util/__init__.py
CHANGED
|
@@ -3,15 +3,14 @@ Absufyu: Utilities
|
|
|
3
3
|
------------------
|
|
4
4
|
Some random utilities
|
|
5
5
|
|
|
6
|
-
Version: 1.5.
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 1.5.2
|
|
7
|
+
Date updated: 25/11/2024 (dd/mm/yyyy)
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
# Library
|
|
11
11
|
###########################################################################
|
|
12
12
|
import pkgutil
|
|
13
13
|
from datetime import datetime
|
|
14
|
-
from typing import Optional, Union
|
|
15
14
|
|
|
16
15
|
from absfuyu.logger import logger
|
|
17
16
|
|
|
@@ -34,10 +33,10 @@ def get_installed_package():
|
|
|
34
33
|
|
|
35
34
|
|
|
36
35
|
def set_min(
|
|
37
|
-
current_value:
|
|
36
|
+
current_value: int | float,
|
|
38
37
|
*,
|
|
39
|
-
min_value:
|
|
40
|
-
) ->
|
|
38
|
+
min_value: int | float = 0,
|
|
39
|
+
) -> int | float:
|
|
41
40
|
"""
|
|
42
41
|
Return ``min_value`` when ``current_value`` < ``min_value``
|
|
43
42
|
|
|
@@ -67,10 +66,10 @@ def set_min(
|
|
|
67
66
|
|
|
68
67
|
|
|
69
68
|
def set_max(
|
|
70
|
-
current_value:
|
|
69
|
+
current_value: int | float,
|
|
71
70
|
*,
|
|
72
|
-
max_value:
|
|
73
|
-
) ->
|
|
71
|
+
max_value: int | float = 100,
|
|
72
|
+
) -> int | float:
|
|
74
73
|
"""
|
|
75
74
|
Return ``max_value`` when ``current_value`` > ``max_value``
|
|
76
75
|
|
|
@@ -100,11 +99,11 @@ def set_max(
|
|
|
100
99
|
|
|
101
100
|
|
|
102
101
|
def set_min_max(
|
|
103
|
-
current_value:
|
|
102
|
+
current_value: int | float,
|
|
104
103
|
*,
|
|
105
|
-
min_value:
|
|
106
|
-
max_value:
|
|
107
|
-
) ->
|
|
104
|
+
min_value: int | float = 0,
|
|
105
|
+
max_value: int | float = 100,
|
|
106
|
+
) -> int | float:
|
|
108
107
|
"""
|
|
109
108
|
Return ``min_value`` | ``max_value`` when ``current_value``
|
|
110
109
|
is outside ``[min_value, max_value]``
|
|
@@ -139,7 +138,7 @@ def set_min_max(
|
|
|
139
138
|
|
|
140
139
|
|
|
141
140
|
def stop_after_day(
|
|
142
|
-
year:
|
|
141
|
+
year: int | None = None, month: int | None = None, day: int | None = None
|
|
143
142
|
) -> None:
|
|
144
143
|
"""
|
|
145
144
|
Stop working after specified day.
|
absfuyu/util/api.py
CHANGED
|
@@ -3,8 +3,8 @@ Absufyu: API
|
|
|
3
3
|
------------
|
|
4
4
|
Fetch data stuff
|
|
5
5
|
|
|
6
|
-
Version: 1.2.
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 1.2.1
|
|
7
|
+
Date updated: 15/11/2024 (dd/mm/yyyy)
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
# Module level
|
|
@@ -21,7 +21,7 @@ import json
|
|
|
21
21
|
import re
|
|
22
22
|
import subprocess
|
|
23
23
|
from pathlib import Path
|
|
24
|
-
from typing import
|
|
24
|
+
from typing import NamedTuple
|
|
25
25
|
|
|
26
26
|
import requests
|
|
27
27
|
from deprecated.sphinx import versionchanged
|
|
@@ -42,7 +42,7 @@ class PingResult(NamedTuple):
|
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
@versionchanged(version="3.4.0", reason="Change function's return")
|
|
45
|
-
def ping_windows(host:
|
|
45
|
+
def ping_windows(host: list[str], ping_count: int = 3) -> list[PingResult]:
|
|
46
46
|
"""
|
|
47
47
|
Ping web
|
|
48
48
|
|
|
@@ -66,7 +66,7 @@ def ping_windows(host: List[str], ping_count: int = 3) -> List[PingResult]:
|
|
|
66
66
|
>>> ping_windows(["1.1.1.1", "google.com"])
|
|
67
67
|
['1.1.1.1 : xxms', 'google.com : xxms']
|
|
68
68
|
"""
|
|
69
|
-
out:
|
|
69
|
+
out: list[PingResult] = []
|
|
70
70
|
|
|
71
71
|
for ip in host:
|
|
72
72
|
output = subprocess.run(
|
|
@@ -96,7 +96,7 @@ class APIRequest:
|
|
|
96
96
|
self,
|
|
97
97
|
api_url: str,
|
|
98
98
|
*, # Use "*" to force using keyword in function parameter | Example: APIRequest(url, encoding="utf-8")
|
|
99
|
-
encoding:
|
|
99
|
+
encoding: str | None = "utf-8",
|
|
100
100
|
) -> None:
|
|
101
101
|
"""
|
|
102
102
|
:param api_url: api link
|
|
@@ -111,7 +111,7 @@ class APIRequest:
|
|
|
111
111
|
def __repr__(self) -> str:
|
|
112
112
|
return self.__str__()
|
|
113
113
|
|
|
114
|
-
def fetch_data(self, *, update: bool = False, json_cache:
|
|
114
|
+
def fetch_data(self, *, update: bool = False, json_cache: str | Path):
|
|
115
115
|
"""
|
|
116
116
|
Fetch data from an API then cache it for later use
|
|
117
117
|
|
absfuyu/util/json_method.py
CHANGED
|
@@ -3,8 +3,8 @@ Absfuyu: Json Method
|
|
|
3
3
|
--------------------
|
|
4
4
|
``.json`` file handling
|
|
5
5
|
|
|
6
|
-
Version: 1.1.
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 1.1.4
|
|
7
|
+
Date updated: 15/11/2024 (dd/mm/yyyy)
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
# Module level
|
|
@@ -16,7 +16,7 @@ __all__ = ["JsonFile"]
|
|
|
16
16
|
###########################################################################
|
|
17
17
|
import json
|
|
18
18
|
from pathlib import Path
|
|
19
|
-
from typing import Any
|
|
19
|
+
from typing import Any
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
# Function
|
|
@@ -38,10 +38,10 @@ class JsonFile:
|
|
|
38
38
|
|
|
39
39
|
def __init__(
|
|
40
40
|
self,
|
|
41
|
-
json_file_location:
|
|
41
|
+
json_file_location: str | Path,
|
|
42
42
|
*,
|
|
43
|
-
encoding:
|
|
44
|
-
indent:
|
|
43
|
+
encoding: str | None = "utf-8",
|
|
44
|
+
indent: int | str | None = 4,
|
|
45
45
|
sort_keys: bool = True,
|
|
46
46
|
) -> None:
|
|
47
47
|
"""
|
|
@@ -54,7 +54,7 @@ class JsonFile:
|
|
|
54
54
|
self.encoding = encoding
|
|
55
55
|
self.indent = indent
|
|
56
56
|
self.sort_keys = sort_keys
|
|
57
|
-
self.data:
|
|
57
|
+
self.data: dict[Any, Any] = {}
|
|
58
58
|
|
|
59
59
|
def __str__(self) -> str:
|
|
60
60
|
return f"{self.__class__.__name__}({self.json_file_location.name})"
|
|
@@ -62,7 +62,7 @@ class JsonFile:
|
|
|
62
62
|
def __repr__(self) -> str:
|
|
63
63
|
return self.__str__()
|
|
64
64
|
|
|
65
|
-
def load_json(self) ->
|
|
65
|
+
def load_json(self) -> dict[Any, Any]:
|
|
66
66
|
"""
|
|
67
67
|
Load ``.json`` file
|
|
68
68
|
|
|
@@ -79,7 +79,7 @@ class JsonFile:
|
|
|
79
79
|
with open(self.json_file_location, "w", encoding=self.encoding) as file:
|
|
80
80
|
file.writelines(json_data)
|
|
81
81
|
|
|
82
|
-
def update_data(self, data:
|
|
82
|
+
def update_data(self, data: dict[Any, Any]) -> None:
|
|
83
83
|
"""
|
|
84
84
|
Update ``.json`` data without save
|
|
85
85
|
|