absfuyu 4.1.1__py3-none-any.whl → 5.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 +4 -4
- absfuyu/__main__.py +13 -1
- absfuyu/cli/__init__.py +4 -2
- absfuyu/cli/color.py +7 -0
- absfuyu/cli/do_group.py +9 -91
- absfuyu/cli/tool_group.py +136 -0
- absfuyu/config/__init__.py +17 -34
- absfuyu/core/__init__.py +49 -0
- absfuyu/core/baseclass.py +299 -0
- absfuyu/core/baseclass2.py +165 -0
- absfuyu/core/decorator.py +67 -0
- absfuyu/core/docstring.py +163 -0
- absfuyu/core/dummy_cli.py +67 -0
- absfuyu/core/dummy_func.py +47 -0
- absfuyu/dxt/__init__.py +42 -0
- absfuyu/dxt/dictext.py +201 -0
- absfuyu/dxt/dxt_support.py +79 -0
- absfuyu/dxt/intext.py +586 -0
- absfuyu/dxt/listext.py +508 -0
- absfuyu/dxt/strext.py +530 -0
- absfuyu/{extensions → extra}/__init__.py +3 -2
- absfuyu/extra/beautiful.py +251 -0
- absfuyu/{extensions/extra → extra}/data_analysis.py +51 -82
- absfuyu/fun/__init__.py +110 -135
- absfuyu/fun/tarot.py +9 -17
- absfuyu/game/__init__.py +6 -0
- absfuyu/game/game_stat.py +6 -0
- absfuyu/game/sudoku.py +7 -1
- absfuyu/game/tictactoe.py +12 -5
- absfuyu/game/wordle.py +14 -8
- absfuyu/general/__init__.py +6 -79
- absfuyu/general/content.py +22 -36
- absfuyu/general/generator.py +17 -42
- absfuyu/general/human.py +108 -228
- absfuyu/general/shape.py +1334 -0
- absfuyu/logger.py +8 -13
- absfuyu/pkg_data/__init__.py +137 -99
- absfuyu/pkg_data/deprecated.py +133 -0
- absfuyu/pkg_data/passwordlib_lzma.pkl +0 -0
- absfuyu/sort.py +6 -130
- absfuyu/tools/__init__.py +2 -2
- absfuyu/tools/checksum.py +44 -22
- absfuyu/tools/converter.py +82 -50
- absfuyu/tools/keygen.py +25 -30
- absfuyu/tools/obfuscator.py +246 -112
- absfuyu/tools/passwordlib.py +330 -0
- absfuyu/tools/shutdownizer.py +287 -0
- absfuyu/tools/web.py +2 -9
- absfuyu/util/__init__.py +15 -15
- absfuyu/util/api.py +10 -15
- absfuyu/util/json_method.py +7 -24
- absfuyu/util/lunar.py +3 -9
- absfuyu/util/path.py +22 -27
- absfuyu/util/performance.py +43 -67
- absfuyu/util/shorten_number.py +65 -14
- absfuyu/util/zipped.py +9 -15
- absfuyu-5.0.0.dist-info/METADATA +143 -0
- absfuyu-5.0.0.dist-info/RECORD +68 -0
- absfuyu/core.py +0 -57
- absfuyu/everything.py +0 -32
- absfuyu/extensions/beautiful.py +0 -188
- absfuyu/extensions/dev/__init__.py +0 -244
- absfuyu/extensions/dev/password_hash.py +0 -80
- absfuyu/extensions/dev/passwordlib.py +0 -258
- absfuyu/extensions/dev/project_starter.py +0 -60
- absfuyu/extensions/dev/shutdownizer.py +0 -156
- absfuyu/extensions/extra/__init__.py +0 -24
- absfuyu/fun/WGS.py +0 -134
- absfuyu/general/data_extension.py +0 -1796
- absfuyu/tools/stats.py +0 -226
- absfuyu/util/pkl.py +0 -67
- absfuyu-4.1.1.dist-info/METADATA +0 -121
- absfuyu-4.1.1.dist-info/RECORD +0 -61
- {absfuyu-4.1.1.dist-info → absfuyu-5.0.0.dist-info}/WHEEL +0 -0
- {absfuyu-4.1.1.dist-info → absfuyu-5.0.0.dist-info}/entry_points.txt +0 -0
- {absfuyu-4.1.1.dist-info → absfuyu-5.0.0.dist-info}/licenses/LICENSE +0 -0
absfuyu/logger.py
CHANGED
|
@@ -14,7 +14,7 @@ Usage:
|
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
16
|
# Module level
|
|
17
|
-
|
|
17
|
+
# ---------------------------------------------------------------------------
|
|
18
18
|
__all__ = [
|
|
19
19
|
# logger
|
|
20
20
|
"logger",
|
|
@@ -25,7 +25,7 @@ __all__ = [
|
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
# Library
|
|
28
|
-
|
|
28
|
+
# ---------------------------------------------------------------------------
|
|
29
29
|
import logging
|
|
30
30
|
import math
|
|
31
31
|
from logging.handlers import RotatingFileHandler as _RFH
|
|
@@ -35,7 +35,7 @@ from typing import Any, Optional, Union
|
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
# Setup
|
|
38
|
-
|
|
38
|
+
# ---------------------------------------------------------------------------
|
|
39
39
|
class LogLevel:
|
|
40
40
|
"""
|
|
41
41
|
``logging``'s log level wrapper + custom log level
|
|
@@ -70,11 +70,12 @@ console_handler.setLevel(LogLevel.TRACE) # Minimum log level
|
|
|
70
70
|
console_handler.setFormatter(
|
|
71
71
|
logging.Formatter(_LogFormat.CONSOLE, datefmt="%Y-%m-%d %H:%M:%S")
|
|
72
72
|
)
|
|
73
|
-
logger.addHandler(console_handler)
|
|
73
|
+
# logger.addHandler(console_handler)
|
|
74
|
+
logger.addHandler(logging.NullHandler())
|
|
74
75
|
|
|
75
76
|
|
|
76
77
|
# Functions
|
|
77
|
-
|
|
78
|
+
# ---------------------------------------------------------------------------
|
|
78
79
|
def _compress_list_for_print(iterable: list, max_visible: Optional[int] = 5) -> str:
|
|
79
80
|
"""
|
|
80
81
|
Compress the list to be more log-readable
|
|
@@ -100,7 +101,7 @@ def _compress_list_for_print(iterable: list, max_visible: Optional[int] = 5) ->
|
|
|
100
101
|
# temp = [iterable[:cut_idx_1], ["..."], iterable[len(iterable)-cut_idx_2:]]
|
|
101
102
|
# out = list(chain.from_iterable(temp))
|
|
102
103
|
# 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
|
|
104
|
+
out = f"{str(iterable[:cut_idx_1])[:-1]}, ..., {str(iterable[len(iterable) - cut_idx_2 :])[1:]}" # Version 3
|
|
104
105
|
# logger.debug(out)
|
|
105
106
|
return f"{out} [Len: {len(iterable)}]"
|
|
106
107
|
|
|
@@ -158,7 +159,7 @@ def compress_for_log(object_: Any, max_visible: Optional[int] = None) -> str:
|
|
|
158
159
|
|
|
159
160
|
|
|
160
161
|
# Class
|
|
161
|
-
|
|
162
|
+
# ---------------------------------------------------------------------------
|
|
162
163
|
class _CustomLogger:
|
|
163
164
|
"""
|
|
164
165
|
Custom logger [W.I.P]
|
|
@@ -341,9 +342,3 @@ class _CustomLogger:
|
|
|
341
342
|
if level_num < logging.DEBUG:
|
|
342
343
|
self._console_handler.setLevel(level_num)
|
|
343
344
|
self.logger.setLevel(level_num)
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
# Run
|
|
347
|
-
###########################################################################
|
|
348
|
-
if __name__ == "__main__":
|
|
349
|
-
logger.setLevel(LogLevel.DEBUG)
|
absfuyu/pkg_data/__init__.py
CHANGED
|
@@ -3,147 +3,185 @@ Absfuyu: Package data
|
|
|
3
3
|
---------------------
|
|
4
4
|
Load package data
|
|
5
5
|
|
|
6
|
-
Version:
|
|
6
|
+
Version: 5.0.0
|
|
7
7
|
Date updated: 14/11/2024 (dd/mm/yyyy)
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
# Module level
|
|
11
|
-
|
|
12
|
-
__all__ = [
|
|
11
|
+
# ---------------------------------------------------------------------------
|
|
12
|
+
__all__ = [
|
|
13
|
+
"Pickler",
|
|
14
|
+
"BasicLZMAOperation",
|
|
15
|
+
"DataLoader",
|
|
16
|
+
# "DataList", # Disable due to Sphinx show real path, still importable
|
|
17
|
+
]
|
|
13
18
|
|
|
14
19
|
|
|
15
20
|
# Library
|
|
16
|
-
|
|
17
|
-
import
|
|
18
|
-
|
|
19
|
-
from
|
|
21
|
+
# ---------------------------------------------------------------------------
|
|
22
|
+
import lzma
|
|
23
|
+
import pickle
|
|
24
|
+
from enum import Enum
|
|
25
|
+
from importlib.resources import files
|
|
20
26
|
from pathlib import Path
|
|
27
|
+
from typing import Any
|
|
21
28
|
|
|
22
|
-
from absfuyu.core import
|
|
23
|
-
from absfuyu.logger import logger
|
|
24
|
-
|
|
25
|
-
# External Data
|
|
26
|
-
###########################################################################
|
|
27
|
-
_EXTERNAL_DATA = {
|
|
28
|
-
"chemistry.json": "https://raw.githubusercontent.com/Bowserinator/Periodic-Table-JSON/master/PeriodicTableJSON.json",
|
|
29
|
-
"countries.json": "https://github.com/dr5hn/countries-states-cities-database/blob/master/countries.json",
|
|
30
|
-
"tarot.json": "https://raw.githubusercontent.com/dariusk/corpora/master/data/divination/tarot_interpretations.json",
|
|
31
|
-
"word_list.json": "https://raw.githubusercontent.com/dwyl/english-words/master/words_dictionary.json",
|
|
32
|
-
}
|
|
29
|
+
from absfuyu.core import BaseClass, versionadded
|
|
33
30
|
|
|
34
31
|
|
|
35
32
|
# Class
|
|
36
|
-
|
|
37
|
-
class DataList:
|
|
33
|
+
# ---------------------------------------------------------------------------
|
|
34
|
+
class DataList(Enum):
|
|
38
35
|
CHEMISTRY = files("absfuyu.pkg_data").joinpath("chemistry.pkl")
|
|
39
36
|
TAROT = files("absfuyu.pkg_data").joinpath("tarot.pkl")
|
|
37
|
+
PASSWORDLIB = files("absfuyu.pkg_data").joinpath("passwordlib_lzma.pkl")
|
|
40
38
|
|
|
41
39
|
|
|
42
|
-
class
|
|
43
|
-
"""
|
|
40
|
+
class Pickler(BaseClass):
|
|
41
|
+
"""
|
|
42
|
+
A utility class for saving and loading data using the pickle format.
|
|
44
43
|
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
This class provides static methods for serializing Python objects to a file
|
|
45
|
+
using the ``pickle`` module and deserializing them back from a file.
|
|
46
|
+
It simplifies the process of saving and loading data to and from pickle files.
|
|
47
|
+
"""
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
@staticmethod
|
|
50
|
+
def save(location: Path, data: Any) -> None:
|
|
51
|
+
"""
|
|
52
|
+
Serializes and saves the given data to a file using the pickle format.
|
|
50
53
|
|
|
51
|
-
|
|
52
|
-
|
|
54
|
+
Parameters
|
|
55
|
+
----------
|
|
56
|
+
location : Path
|
|
57
|
+
The path to the file where the data will be saved.
|
|
53
58
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
data: string data
|
|
57
|
-
name: name and location of the data
|
|
59
|
+
data : Any
|
|
60
|
+
The Python object to be serialized and saved.
|
|
58
61
|
"""
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
file.write(compressed_data)
|
|
62
|
+
with open(Path(location), "wb") as file:
|
|
63
|
+
pickle.dump(data, file)
|
|
62
64
|
|
|
63
|
-
|
|
65
|
+
@staticmethod
|
|
66
|
+
def load(location: Path):
|
|
64
67
|
"""
|
|
65
|
-
|
|
68
|
+
Loads and deserializes data from a file that is in pickle format.
|
|
66
69
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
:
|
|
70
|
-
|
|
71
|
-
"""
|
|
72
|
-
compressed_data = read_binary("absfuyu.pkg_data", self.name)
|
|
73
|
-
data = zlib.decompress(compressed_data).decode()
|
|
74
|
-
# return data
|
|
75
|
-
return literal_eval(data) if evaluate else data
|
|
70
|
+
Parameters
|
|
71
|
+
----------
|
|
72
|
+
location : Path
|
|
73
|
+
The path to the pickle file to load.
|
|
76
74
|
|
|
77
|
-
|
|
75
|
+
Returns
|
|
76
|
+
-------
|
|
77
|
+
Any
|
|
78
|
+
The deserialized Python object loaded from the file.
|
|
78
79
|
"""
|
|
79
|
-
|
|
80
|
+
with open(Path(location), "rb") as file:
|
|
81
|
+
data = pickle.load(file)
|
|
82
|
+
return data
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@versionadded("5.0.0")
|
|
86
|
+
class BasicLZMAOperation(BaseClass):
|
|
87
|
+
"""
|
|
88
|
+
A class for basic LZMA compression and decompression operations,
|
|
89
|
+
integrated with pickle for saving and loading compressed data.
|
|
80
90
|
|
|
81
|
-
|
|
91
|
+
This class provides static methods to compress data using LZMA,
|
|
92
|
+
save the compressed data to a pickle file, load compressed data
|
|
93
|
+
from a pickle file, and decompress LZMA-compressed data.
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
@staticmethod
|
|
97
|
+
def save_to_pickle(location: Path, data: bytes) -> None:
|
|
82
98
|
"""
|
|
83
|
-
|
|
84
|
-
|
|
99
|
+
Compresses the given byte data using LZMA and saves the compressed
|
|
100
|
+
data to a file using pickle serialization.
|
|
101
|
+
|
|
102
|
+
Parameters
|
|
103
|
+
----------
|
|
104
|
+
location : Path
|
|
105
|
+
The path to the file where the compressed data will be saved.
|
|
85
106
|
|
|
107
|
+
data : bytes
|
|
108
|
+
The byte data to be compressed and saved.
|
|
86
109
|
|
|
87
|
-
class _ManagePkgData:
|
|
88
|
-
"""Manage this package data"""
|
|
89
110
|
|
|
90
|
-
|
|
111
|
+
Example:
|
|
112
|
+
--------
|
|
113
|
+
>>> data = b"This is some example data to compress."
|
|
114
|
+
>>> BasicLZMAOperation.save_to_pickle(Path("compressed_data.pkl"), data)
|
|
91
115
|
"""
|
|
92
|
-
|
|
116
|
+
compressed_data = lzma.compress(data)
|
|
117
|
+
Pickler.save(location=location, data=compressed_data)
|
|
118
|
+
|
|
119
|
+
@staticmethod
|
|
120
|
+
def load(data: Any) -> bytes:
|
|
93
121
|
"""
|
|
94
|
-
|
|
122
|
+
Decompresses LZMA-compressed data.
|
|
95
123
|
|
|
96
|
-
|
|
97
|
-
|
|
124
|
+
Parameters
|
|
125
|
+
----------
|
|
126
|
+
data : Any
|
|
127
|
+
The LZMA-compressed data to be decompressed.
|
|
98
128
|
|
|
99
|
-
|
|
100
|
-
|
|
129
|
+
Returns
|
|
130
|
+
-------
|
|
131
|
+
bytes
|
|
132
|
+
The decompressed data.
|
|
133
|
+
"""
|
|
134
|
+
return lzma.decompress(data)
|
|
101
135
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
] # exclude python scripts
|
|
107
|
-
return [
|
|
108
|
-
x for x in self.data_loc.glob(pattern) if x not in excludes and x.is_file()
|
|
109
|
-
]
|
|
136
|
+
@staticmethod
|
|
137
|
+
def load_from_pickle(location: Path) -> bytes:
|
|
138
|
+
"""
|
|
139
|
+
Loads LZMA-compressed data from a pickle file, decompresses it.
|
|
110
140
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
141
|
+
Parameters
|
|
142
|
+
----------
|
|
143
|
+
location : Path
|
|
144
|
+
The path to the pickle file containing the LZMA-compressed data.
|
|
115
145
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
146
|
+
Returns
|
|
147
|
+
-------
|
|
148
|
+
bytes
|
|
149
|
+
The decompressed data.
|
|
119
150
|
"""
|
|
151
|
+
compressed_data = Pickler.load(location=location)
|
|
152
|
+
return lzma.decompress(compressed_data)
|
|
120
153
|
|
|
121
|
-
logger.debug("Downloading data...")
|
|
122
|
-
try:
|
|
123
|
-
from absfuyu.util.api import APIRequest
|
|
124
|
-
|
|
125
|
-
for data_name, data_link in _EXTERNAL_DATA.items():
|
|
126
|
-
logger.debug(f"Downloading {data_name}...")
|
|
127
|
-
data = APIRequest(data_link, encoding="utf-8")
|
|
128
|
-
data.fetch_data(
|
|
129
|
-
update=True,
|
|
130
|
-
json_cache=DATA_PATH.joinpath(data_name), # type:ignore
|
|
131
|
-
)
|
|
132
|
-
logger.debug(f"Downloading {data_name}...DONE")
|
|
133
|
-
logger.debug("Downloading data...DONE")
|
|
134
|
-
except Exception:
|
|
135
|
-
logger.debug("Downloading data...FAILED")
|
|
136
154
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
155
|
+
@versionadded("5.0.0")
|
|
156
|
+
class DataLoader(BaseClass):
|
|
157
|
+
"""A class to load package data"""
|
|
158
|
+
|
|
159
|
+
def __init__(self, data: DataList) -> None:
|
|
160
|
+
"""
|
|
161
|
+
Initializes the DataLoader with a DataList object.
|
|
141
162
|
|
|
163
|
+
Parameters
|
|
164
|
+
----------
|
|
165
|
+
data : DataList
|
|
166
|
+
A ``DataList`` object containing information about the data file to be loaded.
|
|
167
|
+
It is expected to have a ``'value'`` attribute representing the file path.
|
|
168
|
+
"""
|
|
169
|
+
self.data = data
|
|
142
170
|
|
|
143
|
-
|
|
171
|
+
def load(self):
|
|
172
|
+
"""
|
|
173
|
+
Loads data from the specified file, handling different file formats automatically.
|
|
144
174
|
|
|
175
|
+
Returns
|
|
176
|
+
-------
|
|
177
|
+
Any
|
|
178
|
+
The loaded data from the file.
|
|
179
|
+
"""
|
|
180
|
+
try:
|
|
181
|
+
data_name: str = self.data.value.stem # type: ignore
|
|
182
|
+
except Exception:
|
|
183
|
+
data_name: str = self.data.value.name.split(".")[0] # type: ignore
|
|
145
184
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
logger.setLevel(10)
|
|
185
|
+
if data_name.endswith("lzma"):
|
|
186
|
+
return BasicLZMAOperation.load_from_pickle(self.data.value) # type: ignore
|
|
187
|
+
return Pickler.load(self.data.value) # type: ignore
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Absfuyu: Package data
|
|
3
|
+
---------------------
|
|
4
|
+
Deprecated (but might have some use)
|
|
5
|
+
|
|
6
|
+
Version: 2.2.3
|
|
7
|
+
Date updated: 14/11/2024 (dd/mm/yyyy)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
# Library
|
|
11
|
+
# ---------------------------------------------------------------------------
|
|
12
|
+
import zlib
|
|
13
|
+
from ast import literal_eval
|
|
14
|
+
from importlib.resources import files, read_binary
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
from absfuyu.core import BaseClass
|
|
18
|
+
from absfuyu.logger import logger
|
|
19
|
+
|
|
20
|
+
# External Data
|
|
21
|
+
# ---------------------------------------------------------------------------
|
|
22
|
+
# These are sources of data
|
|
23
|
+
_EXTERNAL_DATA = {
|
|
24
|
+
"chemistry.json": "https://raw.githubusercontent.com/Bowserinator/Periodic-Table-JSON/master/PeriodicTableJSON.json",
|
|
25
|
+
"tarot.json": "https://raw.githubusercontent.com/dariusk/corpora/master/data/divination/tarot_interpretations.json",
|
|
26
|
+
"word_list.json": "https://raw.githubusercontent.com/dwyl/english-words/master/words_dictionary.json",
|
|
27
|
+
# "countries.json": "https://raw.githubusercontent.com/dr5hn/countries-states-cities-database/refs/heads/master/json/countries.json",
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# Deprecated
|
|
32
|
+
# ---------------------------------------------------------------------------
|
|
33
|
+
DATA_PATH = files("absfuyu.pkg_data")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class _DatMaker(BaseClass):
|
|
37
|
+
"""
|
|
38
|
+
Package data ``.dat`` maker/loader
|
|
39
|
+
|
|
40
|
+
*Deprecated since version 5.0.0*
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(self, data_name: str) -> None:
|
|
44
|
+
self.name = data_name
|
|
45
|
+
|
|
46
|
+
def _make_dat(self, data: str, name: str | Path):
|
|
47
|
+
"""
|
|
48
|
+
:param data: string data
|
|
49
|
+
:param name: name and location of the data
|
|
50
|
+
"""
|
|
51
|
+
compressed_data = zlib.compress(str(data).encode(), zlib.Z_BEST_COMPRESSION)
|
|
52
|
+
with open(name, "wb") as file:
|
|
53
|
+
file.write(compressed_data)
|
|
54
|
+
|
|
55
|
+
def load_dat_data(self, evaluate: bool = False):
|
|
56
|
+
"""
|
|
57
|
+
Load ``.dat`` data from package resource
|
|
58
|
+
|
|
59
|
+
:param evaluate: use ``ast.literal_eval()`` to evaluate string data
|
|
60
|
+
:type evaluate: bool
|
|
61
|
+
:returns: Loaded data
|
|
62
|
+
:rtype: Any
|
|
63
|
+
"""
|
|
64
|
+
compressed_data = read_binary("absfuyu.pkg_data", self.name)
|
|
65
|
+
data = zlib.decompress(compressed_data).decode()
|
|
66
|
+
# return data
|
|
67
|
+
return literal_eval(data) if evaluate else data
|
|
68
|
+
|
|
69
|
+
def update_data(self, new_data: str):
|
|
70
|
+
"""
|
|
71
|
+
Update existing data
|
|
72
|
+
|
|
73
|
+
:param new_data: Data to be updated
|
|
74
|
+
"""
|
|
75
|
+
self._make_dat(data=new_data, name=DATA_PATH.joinpath(self.name)) # type:ignore
|
|
76
|
+
logger.debug("Data updated")
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class _ManagePkgData(BaseClass):
|
|
80
|
+
"""
|
|
81
|
+
Manage this package data
|
|
82
|
+
|
|
83
|
+
*Deprecated since version 5.0.0*
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
def __init__(self, pkg_data_loc: str | Path) -> None:
|
|
87
|
+
"""
|
|
88
|
+
pkg_data_loc: Package data location
|
|
89
|
+
"""
|
|
90
|
+
self.data_loc = Path(pkg_data_loc)
|
|
91
|
+
|
|
92
|
+
def __str__(self) -> str:
|
|
93
|
+
return f"{self.__class__.__name__}({self.data_loc.name})"
|
|
94
|
+
|
|
95
|
+
def get_data_list(self, *, pattern: str = "*") -> list[Path]:
|
|
96
|
+
"""Get a list of data available"""
|
|
97
|
+
excludes = [
|
|
98
|
+
x for x in self.data_loc.glob("*.[pP][yY]")
|
|
99
|
+
] # exclude python scripts
|
|
100
|
+
return [
|
|
101
|
+
x for x in self.data_loc.glob(pattern) if x not in excludes and x.is_file()
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def data_list(self) -> list[str]:
|
|
106
|
+
"""List of available data"""
|
|
107
|
+
return [x.name for x in self.get_data_list()]
|
|
108
|
+
|
|
109
|
+
def download_all_data(self):
|
|
110
|
+
"""
|
|
111
|
+
Download all external data
|
|
112
|
+
"""
|
|
113
|
+
|
|
114
|
+
logger.debug("Downloading data...")
|
|
115
|
+
try:
|
|
116
|
+
from absfuyu.util.api import APIRequest
|
|
117
|
+
|
|
118
|
+
for data_name, data_link in _EXTERNAL_DATA.items():
|
|
119
|
+
logger.debug(f"Downloading {data_name}...")
|
|
120
|
+
data = APIRequest(data_link, encoding="utf-8")
|
|
121
|
+
data.fetch_data(
|
|
122
|
+
update=True,
|
|
123
|
+
json_cache=DATA_PATH.joinpath(data_name), # type: ignore
|
|
124
|
+
)
|
|
125
|
+
logger.debug(f"Downloading {data_name}...DONE")
|
|
126
|
+
logger.debug("Downloading data...DONE")
|
|
127
|
+
except Exception:
|
|
128
|
+
logger.debug("Downloading data...FAILED")
|
|
129
|
+
|
|
130
|
+
def clear_data(self) -> None:
|
|
131
|
+
"""Clear data in data list"""
|
|
132
|
+
for x in self.get_data_list():
|
|
133
|
+
x.unlink()
|
|
Binary file
|
absfuyu/sort.py
CHANGED
|
@@ -1,22 +1,18 @@
|
|
|
1
|
-
# type: ignore
|
|
2
1
|
"""
|
|
3
2
|
Absfuyu: Sort
|
|
4
3
|
-------------
|
|
5
4
|
Sort Module
|
|
6
5
|
|
|
7
|
-
Version: 1.
|
|
8
|
-
Date updated:
|
|
6
|
+
Version: 1.3.0
|
|
7
|
+
Date updated: 11/02/2025 (mm/dd/yyyy)
|
|
9
8
|
"""
|
|
10
9
|
|
|
11
10
|
# Module level
|
|
12
|
-
|
|
11
|
+
# ---------------------------------------------------------------------------
|
|
13
12
|
__all__ = [
|
|
14
13
|
# Sort
|
|
15
14
|
"selection_sort",
|
|
16
15
|
"insertion_sort",
|
|
17
|
-
# Alphabet
|
|
18
|
-
"alphabetAppear",
|
|
19
|
-
"AlphabetAppearResult",
|
|
20
16
|
# Search
|
|
21
17
|
"linear_search",
|
|
22
18
|
"binary_search",
|
|
@@ -24,22 +20,12 @@ __all__ = [
|
|
|
24
20
|
|
|
25
21
|
|
|
26
22
|
# Library
|
|
27
|
-
|
|
28
|
-
import
|
|
29
|
-
from collections import Counter
|
|
30
|
-
from itertools import accumulate
|
|
31
|
-
from typing import Any, Dict, List, NamedTuple, Union
|
|
32
|
-
|
|
33
|
-
from deprecated import deprecated
|
|
34
|
-
from deprecated.sphinx import (
|
|
35
|
-
deprecated as sphinx_deprecated, # versionadded,; versionchanged,
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
from absfuyu.logger import logger
|
|
23
|
+
# ---------------------------------------------------------------------------
|
|
24
|
+
from typing import Any
|
|
39
25
|
|
|
40
26
|
|
|
41
27
|
# Functions
|
|
42
|
-
|
|
28
|
+
# ---------------------------------------------------------------------------
|
|
43
29
|
def selection_sort(iterable: list, reverse: bool = False) -> list:
|
|
44
30
|
"""
|
|
45
31
|
Sort the list with selection sort (bubble sort) algorithm
|
|
@@ -100,110 +86,6 @@ def insertion_sort(iterable: list) -> list:
|
|
|
100
86
|
return iterable
|
|
101
87
|
|
|
102
88
|
|
|
103
|
-
def _alphabetAppear_old(
|
|
104
|
-
lst: List[str],
|
|
105
|
-
) -> List[Union[Dict[str, int], List[int]]]:
|
|
106
|
-
r"""
|
|
107
|
-
Summary
|
|
108
|
-
-------
|
|
109
|
-
Make a dict that show the frequency of
|
|
110
|
-
item name's first character in list
|
|
111
|
-
in alphabet order
|
|
112
|
-
|
|
113
|
-
For example:
|
|
114
|
-
|
|
115
|
-
>>> ["apple","bee","book"]
|
|
116
|
-
|
|
117
|
-
freq = {"a": 1, "b": 2}
|
|
118
|
-
|
|
119
|
-
Parameters
|
|
120
|
-
----------
|
|
121
|
-
lst : list
|
|
122
|
-
list that want to be analyzed
|
|
123
|
-
|
|
124
|
-
Returns
|
|
125
|
-
-------
|
|
126
|
-
list
|
|
127
|
-
analyzed list (list[0])
|
|
128
|
-
apperance incremental value index (list[1])
|
|
129
|
-
"""
|
|
130
|
-
|
|
131
|
-
al_char = [x[0] for x in selection_sort(lst)]
|
|
132
|
-
times_appear = dict()
|
|
133
|
-
for x in al_char:
|
|
134
|
-
if x in times_appear:
|
|
135
|
-
times_appear[x] += 1
|
|
136
|
-
else:
|
|
137
|
-
times_appear[x] = 1
|
|
138
|
-
|
|
139
|
-
times_appear_increment = []
|
|
140
|
-
total = 0
|
|
141
|
-
for x in times_appear.values():
|
|
142
|
-
total += x
|
|
143
|
-
times_appear_increment.append(total)
|
|
144
|
-
|
|
145
|
-
# first item is character frequency
|
|
146
|
-
# second item is incremental index list
|
|
147
|
-
return [times_appear, times_appear_increment]
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
class AlphabetAppearResult(NamedTuple):
|
|
151
|
-
times_appear: Dict[str, int]
|
|
152
|
-
times_appear_increment: List[int]
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
@deprecated(version="3.0.0", reason="In absfuyu ``ListExt``")
|
|
156
|
-
@sphinx_deprecated(version="3.0.0", reason="In absfuyu ``ListExt``")
|
|
157
|
-
def alphabetAppear(iterable: list, num_of_char_sorted: int = 1) -> AlphabetAppearResult:
|
|
158
|
-
"""
|
|
159
|
-
Make a dict that show the frequency of
|
|
160
|
-
item name's first character in list
|
|
161
|
-
in alphabet order
|
|
162
|
-
|
|
163
|
-
Parameters
|
|
164
|
-
----------
|
|
165
|
-
iterable : list
|
|
166
|
-
List that want to be analyzed
|
|
167
|
-
|
|
168
|
-
num_of_char_sorted : int
|
|
169
|
-
Number of first character taken into account to sort
|
|
170
|
-
(default: ``1`` - first character in each item)
|
|
171
|
-
|
|
172
|
-
Returns
|
|
173
|
-
-------
|
|
174
|
-
AlphabetAppearResult
|
|
175
|
-
| Analyzed list (``AlphabetAppearResult.times_appear``)
|
|
176
|
-
| Apperance incremental value index (``AlphabetAppearResult.times_appear_increment``)
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
Example:
|
|
180
|
-
--------
|
|
181
|
-
>>> alphabetAppear(["apple", "bee", "book"])
|
|
182
|
-
AlphabetAppearResult(times_appear={'a': 1, 'b': 2}, times_appear_increment=[1, 3])
|
|
183
|
-
"""
|
|
184
|
-
|
|
185
|
-
if not isinstance(num_of_char_sorted, int):
|
|
186
|
-
logger.debug("num_of_char_sorted is not int")
|
|
187
|
-
num_of_char_sorted = 1
|
|
188
|
-
if num_of_char_sorted < 1:
|
|
189
|
-
logger.debug("num_of_char_sorted < 1")
|
|
190
|
-
num_of_char_sorted = 1
|
|
191
|
-
if num_of_char_sorted > min([len(str(x)) for x in iterable]):
|
|
192
|
-
logger.debug("num_of_char_sorted > item length")
|
|
193
|
-
num_of_char_sorted = min([len(str(x)) for x in iterable])
|
|
194
|
-
temp = Counter([str(x)[:num_of_char_sorted] for x in iterable])
|
|
195
|
-
times_appear = dict(sorted(temp.items()))
|
|
196
|
-
logger.debug(times_appear)
|
|
197
|
-
|
|
198
|
-
temp = accumulate(times_appear.values(), operator.add)
|
|
199
|
-
times_appear_increment: List[int] = list(temp)
|
|
200
|
-
logger.debug(times_appear_increment)
|
|
201
|
-
|
|
202
|
-
# first item is character frequency
|
|
203
|
-
# second item is incremental index list
|
|
204
|
-
return AlphabetAppearResult(times_appear, times_appear_increment)
|
|
205
|
-
|
|
206
|
-
|
|
207
89
|
def linear_search(iterable: list, key: Any) -> int:
|
|
208
90
|
"""
|
|
209
91
|
Returns the position of ``key`` in the list
|
|
@@ -256,9 +138,3 @@ def binary_search(iterable: list, key: Any) -> int:
|
|
|
256
138
|
if iterable[middle] < key:
|
|
257
139
|
left = middle + 1
|
|
258
140
|
return -1
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
# Run
|
|
262
|
-
###########################################################################
|
|
263
|
-
if __name__ == "__main__":
|
|
264
|
-
logger.setLevel(10)
|
absfuyu/tools/__init__.py
CHANGED