absfuyu 4.0.0__tar.gz → 4.1.1__tar.gz
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-4.0.0 → absfuyu-4.1.1}/LICENSE +21 -21
- {absfuyu-4.0.0 → absfuyu-4.1.1}/PKG-INFO +2 -1
- {absfuyu-4.0.0 → absfuyu-4.1.1}/pyproject.toml +42 -12
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/__init__.py +1 -1
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/cli/do_group.py +62 -2
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/core.py +14 -2
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/game/__init__.py +1 -1
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/game/game_stat.py +1 -1
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/general/content.py +7 -7
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/general/data_extension.py +3 -3
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/general/generator.py +4 -2
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/logger.py +2 -2
- absfuyu-4.1.1/src/absfuyu/tools/checksum.py +143 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/tools/converter.py +26 -2
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/tools/obfuscator.py +1 -1
- absfuyu-4.1.1/src/absfuyu/util/shorten_number.py +228 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_everything.py +7 -2
- {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_tarot.py +3 -3
- {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_util.py +34 -6
- {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_version.py +13 -14
- {absfuyu-4.0.0 → absfuyu-4.1.1}/.gitignore +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/README.md +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/dev_requirements.txt +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/docs/Makefile +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/docs/conf.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/docs/index.rst +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/docs/info.md +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/docs/make.bat +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/docs/modules.rst +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/images/repository-image-crop.png +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/images/repository-image-white.png +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/images/repository-image.png +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/__main__.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/cli/__init__.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/cli/color.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/cli/config_group.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/cli/game_group.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/config/__init__.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/config/config.json +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/everything.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/extensions/__init__.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/extensions/beautiful.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/extensions/dev/__init__.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/extensions/dev/password_hash.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/extensions/dev/passwordlib.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/extensions/dev/project_starter.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/extensions/dev/shutdownizer.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/extensions/extra/__init__.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/extensions/extra/data_analysis.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/fun/WGS.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/fun/__init__.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/fun/tarot.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/game/sudoku.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/game/tictactoe.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/game/wordle.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/general/__init__.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/general/human.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/pkg_data/__init__.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/pkg_data/chemistry.pkl +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/pkg_data/tarot.pkl +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/py.typed +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/sort.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/tools/__init__.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/tools/keygen.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/tools/stats.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/tools/web.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/util/__init__.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/util/api.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/util/json_method.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/util/lunar.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/util/path.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/util/performance.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/util/pkl.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/util/zipped.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/version.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/__init__.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/conftest.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_beautiful.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_config.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_data_analysis.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_data_extension.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_extensions.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_fun.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_game.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_generator.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_logger.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_passwordlib.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_pkg_data.py +0 -0
- {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_tools.py +0 -0
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2022-
|
|
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.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: absfuyu
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.1.1
|
|
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
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# 4. Build package (hatch build)
|
|
6
6
|
# 5. Generating docs (hatch run docs:build)
|
|
7
7
|
# 6. Publish packge (hatch publish)
|
|
8
|
-
## Run entire workflow: hatch run workflow
|
|
8
|
+
## Run entire workflow: hatch run workflow:<major | minor | patch>
|
|
9
9
|
## `hatch env show` for more information
|
|
10
10
|
|
|
11
11
|
# MARK: BUILD ====================
|
|
@@ -60,7 +60,7 @@ Issues = "https://github.com/AbsoluteWinter/absfuyu-public/issues"
|
|
|
60
60
|
|
|
61
61
|
[project.optional-dependencies]
|
|
62
62
|
res = ["absfuyu-res"]
|
|
63
|
-
full = ["absfuyu-res", "numpy", "pandas", "rich"]
|
|
63
|
+
full = ["absfuyu-res", "numpy", "pandas", "rich", "tqdm"]
|
|
64
64
|
beautiful = ["rich"]
|
|
65
65
|
extra = ["numpy", "pandas"]
|
|
66
66
|
dev = ["hatch", "pytest"]
|
|
@@ -171,12 +171,12 @@ detached = true
|
|
|
171
171
|
skip-install = true
|
|
172
172
|
description = """
|
|
173
173
|
Package workflow:
|
|
174
|
-
hatch run workflow
|
|
174
|
+
hatch run workflow:<option>
|
|
175
175
|
|
|
176
|
-
|
|
177
|
-
-
|
|
178
|
-
-
|
|
179
|
-
-
|
|
176
|
+
Options:
|
|
177
|
+
- patch: release version patch
|
|
178
|
+
- minor: release version minor
|
|
179
|
+
- major: release version major
|
|
180
180
|
"""
|
|
181
181
|
|
|
182
182
|
[tool.hatch.envs.workflow.scripts]
|
|
@@ -186,25 +186,54 @@ test = [
|
|
|
186
186
|
"hatch run all:test", # Test
|
|
187
187
|
]
|
|
188
188
|
build = [
|
|
189
|
+
# Update license year - Convert to hex due to unable to run multiple lines
|
|
190
|
+
# Source code:
|
|
191
|
+
# import re;from datetime import datetime;from pathlib import Path
|
|
192
|
+
# print("Updating license year...");p=r"([12]\d{3})(-[12]\d{3})?"
|
|
193
|
+
# n=str(datetime.now().year);l=list(Path.cwd().glob("*license*"))[0]
|
|
194
|
+
# with open(l)as f:c=f.readlines()
|
|
195
|
+
# for i,x in enumerate(c):
|
|
196
|
+
# s=re.search(p,x);y=s.groups()[0]if s else n
|
|
197
|
+
# if y!=n:c[i]=re.sub(p,f"{y}-{n}",x)
|
|
198
|
+
# with open(l,"w",encoding="utf-8")as f:f.writelines(c)
|
|
199
|
+
# print("License year updated")
|
|
200
|
+
"""
|
|
201
|
+
python -c \"exec(bytes.fromhex('696d706f72742072653b66726f6d20646174657\
|
|
202
|
+
4696d6520696d706f7274206461746574696d653b66726f6d20706174686c696220696d\
|
|
203
|
+
706f727420506174680a7072696e7428225570646174696e67206c6963656e736520796\
|
|
204
|
+
561722e2e2e22293b703d7222285b31325d5c647b337d29282d5b31325d5c647b337d29\
|
|
205
|
+
3f220a6e3d737472286461746574696d652e6e6f7728292e79656172293b6c3d6c69737\
|
|
206
|
+
428506174682e63776428292e676c6f6228222a6c6963656e73652a2229295b305d0a77\
|
|
207
|
+
697468206f70656e286c29617320663a633d662e726561646c696e657328290a666f722\
|
|
208
|
+
0692c7820696e20656e756d65726174652863293a0a20202020733d72652e7365617263\
|
|
209
|
+
6828702c78293b793d732e67726f75707328295b305d6966207320656c7365206e0a202\
|
|
210
|
+
0202069662079213d6e3a635b695d3d72652e73756228702c66227b797d2d7b6e7d222c\
|
|
211
|
+
78290a77697468206f70656e286c2c2277222c656e636f64696e673d227574662d38222\
|
|
212
|
+
9617320663a662e77726974656c696e65732863290a7072696e7428224c6963656e7365\
|
|
213
|
+
207965617220757064617465642229').decode('utf-8'))\"
|
|
214
|
+
""",
|
|
215
|
+
# "python support_scripts/update_license_year.py", # Update license year
|
|
189
216
|
"hatch clean", # Clean dist/ folder
|
|
190
217
|
"hatch -v build", # Build package
|
|
191
218
|
"hatch run docs:build", # Build docs
|
|
192
|
-
"hatch publish", # Publish
|
|
193
219
|
]
|
|
194
|
-
|
|
220
|
+
patch = [
|
|
195
221
|
"test",
|
|
196
222
|
"hatch version patch", # Bump version patch
|
|
197
223
|
"build",
|
|
224
|
+
"hatch publish", # Publish
|
|
198
225
|
]
|
|
199
|
-
|
|
226
|
+
minor = [
|
|
200
227
|
"test",
|
|
201
228
|
"hatch version minor", # Bump version minor
|
|
202
229
|
"build",
|
|
230
|
+
"hatch publish", # Publish
|
|
203
231
|
]
|
|
204
|
-
|
|
232
|
+
major = [
|
|
205
233
|
"test",
|
|
206
234
|
"hatch version major", # Bump version major
|
|
207
235
|
"build",
|
|
236
|
+
"hatch publish", # Publish
|
|
208
237
|
]
|
|
209
238
|
|
|
210
239
|
# MARK: TOOL: pytest
|
|
@@ -223,7 +252,7 @@ markers = [ # pytest -m <marker> -v
|
|
|
223
252
|
|
|
224
253
|
# MARK: TOOL: mypy
|
|
225
254
|
[tool.mypy]
|
|
226
|
-
|
|
255
|
+
python_version = "3.11"
|
|
227
256
|
mypy_path = "src"
|
|
228
257
|
check_untyped_defs = true
|
|
229
258
|
# disallow_any_generics = true
|
|
@@ -279,6 +308,7 @@ ignore = [
|
|
|
279
308
|
"tests/*" = [
|
|
280
309
|
"F401", # imported but unused
|
|
281
310
|
]
|
|
311
|
+
"shorten_number.py" = ["B007"] # Loop control variable not used within loop body
|
|
282
312
|
|
|
283
313
|
# MARK: TOOL: black
|
|
284
314
|
[tool.black]
|
|
@@ -3,13 +3,14 @@ ABSFUYU CLI
|
|
|
3
3
|
-----------
|
|
4
4
|
Do
|
|
5
5
|
|
|
6
|
-
Version: 1.
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 1.3.1
|
|
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
|
|
20
22
|
from absfuyu.util.zipped import Zipper
|
|
21
23
|
from absfuyu.version import PkgVersion
|
|
22
24
|
|
|
@@ -96,6 +98,63 @@ 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
|
+
"--save-result",
|
|
114
|
+
"-s",
|
|
115
|
+
"save_result",
|
|
116
|
+
type=bool,
|
|
117
|
+
default=False,
|
|
118
|
+
is_flag=True,
|
|
119
|
+
show_default=True,
|
|
120
|
+
help="Save checksum result to file",
|
|
121
|
+
)
|
|
122
|
+
@click.option(
|
|
123
|
+
"--recursive",
|
|
124
|
+
"-r",
|
|
125
|
+
"recursive_mode",
|
|
126
|
+
type=bool,
|
|
127
|
+
default=False,
|
|
128
|
+
is_flag=True,
|
|
129
|
+
show_default=True,
|
|
130
|
+
help="Do checksum for every file in the folder (including child folder)",
|
|
131
|
+
)
|
|
132
|
+
@click.option(
|
|
133
|
+
"--compare",
|
|
134
|
+
"-c",
|
|
135
|
+
"hash_to_compare",
|
|
136
|
+
type=str,
|
|
137
|
+
default=None,
|
|
138
|
+
show_default=True,
|
|
139
|
+
help="Hash to compare",
|
|
140
|
+
)
|
|
141
|
+
def file_checksum(
|
|
142
|
+
file_path: str,
|
|
143
|
+
hash_mode: str | Literal["md5", "sha1", "sha256", "sha512"],
|
|
144
|
+
save_result: bool,
|
|
145
|
+
recursive_mode: bool,
|
|
146
|
+
hash_to_compare: str,
|
|
147
|
+
) -> None:
|
|
148
|
+
"""Checksum for file"""
|
|
149
|
+
# print(hash_mode, save_result, recursive_mode)
|
|
150
|
+
instance = Checksum(file_path, hash_mode=hash_mode, save_result_to_file=save_result)
|
|
151
|
+
res = instance.checksum(recursive=recursive_mode)
|
|
152
|
+
if hash_to_compare:
|
|
153
|
+
print(res == hash_to_compare)
|
|
154
|
+
else:
|
|
155
|
+
print(res)
|
|
156
|
+
|
|
157
|
+
|
|
99
158
|
@click.group(name="do")
|
|
100
159
|
def do_group() -> None:
|
|
101
160
|
"""Perform functionalities"""
|
|
@@ -108,3 +167,4 @@ do_group.add_command(advice)
|
|
|
108
167
|
do_group.add_command(fs)
|
|
109
168
|
do_group.add_command(info)
|
|
110
169
|
do_group.add_command(unzip_files_in_dir)
|
|
170
|
+
do_group.add_command(file_checksum)
|
|
@@ -3,8 +3,8 @@ Absfuyu: Core
|
|
|
3
3
|
-------------
|
|
4
4
|
Contain type hints and other stuffs
|
|
5
5
|
|
|
6
|
-
Version: 2.
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 2.3.1
|
|
7
|
+
Date updated: 01/02/2025 (dd/mm/yyyy)
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
# Module Package
|
|
@@ -21,6 +21,9 @@ __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
|
|
25
28
|
|
|
26
29
|
|
|
@@ -43,3 +46,12 @@ class CLITextColor:
|
|
|
43
46
|
CORE_PATH = files("absfuyu")
|
|
44
47
|
CONFIG_PATH = CORE_PATH.joinpath("config", "config.json")
|
|
45
48
|
DATA_PATH = CORE_PATH.joinpath("pkg_data")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# tqdm wrapper
|
|
52
|
+
try:
|
|
53
|
+
tqdm = import_module("tqdm").tqdm
|
|
54
|
+
except ModuleNotFoundError:
|
|
55
|
+
|
|
56
|
+
def tqdm(iterable, **kwargs):
|
|
57
|
+
return iterable
|
|
@@ -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
|
|
432
|
-
)
|
|
433
|
-
assert (
|
|
434
|
-
tag_separate_symbol
|
|
435
|
-
)
|
|
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(
|
|
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}")
|
|
@@ -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,143 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Absufyu: Checksum
|
|
3
|
+
-----------------
|
|
4
|
+
Check MD5, SHA256, ...
|
|
5
|
+
|
|
6
|
+
Version: 1.1.0
|
|
7
|
+
Date updated: 01/02/2025 (dd/mm/yyyy)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
# Module level
|
|
11
|
+
###########################################################################
|
|
12
|
+
__all__ = ["Checksum", "checksum_operation"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# Library
|
|
16
|
+
###########################################################################
|
|
17
|
+
import hashlib
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import Literal
|
|
20
|
+
|
|
21
|
+
from absfuyu.core import tqdm
|
|
22
|
+
|
|
23
|
+
# Function
|
|
24
|
+
###########################################################################
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# Deprecated
|
|
28
|
+
def checksum_operation(
|
|
29
|
+
file: Path | str,
|
|
30
|
+
hash_mode: str | Literal["md5", "sha1", "sha256", "sha512"] = "sha256",
|
|
31
|
+
) -> str:
|
|
32
|
+
"""This performs checksum"""
|
|
33
|
+
if hash_mode.lower() == "md5":
|
|
34
|
+
hash_engine = hashlib.md5()
|
|
35
|
+
elif hash_mode.lower() == "sha1":
|
|
36
|
+
hash_engine = hashlib.sha1()
|
|
37
|
+
elif hash_mode.lower() == "sha256":
|
|
38
|
+
hash_engine = hashlib.sha256()
|
|
39
|
+
elif hash_mode.lower() == "sha512":
|
|
40
|
+
hash_engine = hashlib.sha512()
|
|
41
|
+
else:
|
|
42
|
+
hash_engine = hashlib.md5()
|
|
43
|
+
|
|
44
|
+
with open(Path(file), "rb") as f:
|
|
45
|
+
while True:
|
|
46
|
+
data = f.read(4096)
|
|
47
|
+
if len(data) == 0:
|
|
48
|
+
break
|
|
49
|
+
else:
|
|
50
|
+
hash_engine.update(data)
|
|
51
|
+
return hash_engine.hexdigest()
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class Checksum:
|
|
55
|
+
def __init__(
|
|
56
|
+
self,
|
|
57
|
+
path: str | Path,
|
|
58
|
+
hash_mode: str | Literal["md5", "sha1", "sha256", "sha512"] = "sha256",
|
|
59
|
+
save_result_to_file: bool = False,
|
|
60
|
+
) -> None:
|
|
61
|
+
self.path = Path(path)
|
|
62
|
+
self.hash_mode = hash_mode
|
|
63
|
+
self.save_result_to_file = save_result_to_file
|
|
64
|
+
self.checksum_result_file_name = "checksum_results.txt"
|
|
65
|
+
|
|
66
|
+
def _get_hash_engine(self):
|
|
67
|
+
hash_mode = self.hash_mode
|
|
68
|
+
if hash_mode.lower() == "md5":
|
|
69
|
+
hash_engine = hashlib.md5()
|
|
70
|
+
elif hash_mode.lower() == "sha1":
|
|
71
|
+
hash_engine = hashlib.sha1()
|
|
72
|
+
elif hash_mode.lower() == "sha256":
|
|
73
|
+
hash_engine = hashlib.sha256()
|
|
74
|
+
elif hash_mode.lower() == "sha512":
|
|
75
|
+
hash_engine = hashlib.sha512()
|
|
76
|
+
else:
|
|
77
|
+
hash_engine = hashlib.md5()
|
|
78
|
+
return hash_engine
|
|
79
|
+
|
|
80
|
+
def _checksum_operation(
|
|
81
|
+
self,
|
|
82
|
+
file: Path | str,
|
|
83
|
+
) -> str:
|
|
84
|
+
"""This performs checksum"""
|
|
85
|
+
|
|
86
|
+
hash_engine = self._get_hash_engine().copy()
|
|
87
|
+
with open(Path(file), "rb") as f:
|
|
88
|
+
# Read and hash the file in 4K chunks. Reading the whole
|
|
89
|
+
# file at once might consume a lot of memory if it is
|
|
90
|
+
# large.
|
|
91
|
+
while True:
|
|
92
|
+
data = f.read(4096)
|
|
93
|
+
if len(data) == 0:
|
|
94
|
+
break
|
|
95
|
+
else:
|
|
96
|
+
hash_engine.update(data)
|
|
97
|
+
return hash_engine.hexdigest() # type: ignore
|
|
98
|
+
|
|
99
|
+
def checksum(self, recursive: bool = True) -> str:
|
|
100
|
+
"""Perform checksum
|
|
101
|
+
|
|
102
|
+
Parameters
|
|
103
|
+
----------
|
|
104
|
+
recursive : bool, optional
|
|
105
|
+
Do checksum for every file in the folder (including child folder), by default True
|
|
106
|
+
|
|
107
|
+
Returns
|
|
108
|
+
-------
|
|
109
|
+
str
|
|
110
|
+
Checksum hash
|
|
111
|
+
"""
|
|
112
|
+
if self.path.absolute().is_dir():
|
|
113
|
+
new_path = self.path.joinpath(self.checksum_result_file_name)
|
|
114
|
+
# List of files
|
|
115
|
+
if recursive:
|
|
116
|
+
file_list: list[Path] = [
|
|
117
|
+
x for x in self.path.glob("**/*") if x.is_file()
|
|
118
|
+
]
|
|
119
|
+
else:
|
|
120
|
+
file_list = [x for x in self.path.glob("*") if x.is_file()]
|
|
121
|
+
|
|
122
|
+
# Checksum
|
|
123
|
+
res = []
|
|
124
|
+
for x in tqdm(file_list, desc="Calculating hash", unit_scale=True):
|
|
125
|
+
name = x.relative_to(self.path)
|
|
126
|
+
res.append(f"{self._checksum_operation(x)} | {name}")
|
|
127
|
+
output = "\n".join(res)
|
|
128
|
+
else:
|
|
129
|
+
new_path = self.path.with_name(self.checksum_result_file_name)
|
|
130
|
+
output = self._checksum_operation(self.path)
|
|
131
|
+
|
|
132
|
+
# Save result
|
|
133
|
+
if self.save_result_to_file:
|
|
134
|
+
with open(new_path, "w", encoding="utf-8") as f:
|
|
135
|
+
f.write(output)
|
|
136
|
+
|
|
137
|
+
return output
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
# Run
|
|
141
|
+
###########################################################################
|
|
142
|
+
if __name__ == "__main__":
|
|
143
|
+
pass
|
|
@@ -3,8 +3,8 @@ Absufyu: Converter
|
|
|
3
3
|
------------------
|
|
4
4
|
Convert stuff
|
|
5
5
|
|
|
6
|
-
Version: 1.
|
|
7
|
-
Date updated:
|
|
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))
|