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.

Files changed (89) hide show
  1. {absfuyu-4.0.0 → absfuyu-4.1.1}/LICENSE +21 -21
  2. {absfuyu-4.0.0 → absfuyu-4.1.1}/PKG-INFO +2 -1
  3. {absfuyu-4.0.0 → absfuyu-4.1.1}/pyproject.toml +42 -12
  4. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/__init__.py +1 -1
  5. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/cli/do_group.py +62 -2
  6. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/core.py +14 -2
  7. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/game/__init__.py +1 -1
  8. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/game/game_stat.py +1 -1
  9. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/general/content.py +7 -7
  10. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/general/data_extension.py +3 -3
  11. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/general/generator.py +4 -2
  12. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/logger.py +2 -2
  13. absfuyu-4.1.1/src/absfuyu/tools/checksum.py +143 -0
  14. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/tools/converter.py +26 -2
  15. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/tools/obfuscator.py +1 -1
  16. absfuyu-4.1.1/src/absfuyu/util/shorten_number.py +228 -0
  17. {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_everything.py +7 -2
  18. {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_tarot.py +3 -3
  19. {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_util.py +34 -6
  20. {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_version.py +13 -14
  21. {absfuyu-4.0.0 → absfuyu-4.1.1}/.gitignore +0 -0
  22. {absfuyu-4.0.0 → absfuyu-4.1.1}/README.md +0 -0
  23. {absfuyu-4.0.0 → absfuyu-4.1.1}/dev_requirements.txt +0 -0
  24. {absfuyu-4.0.0 → absfuyu-4.1.1}/docs/Makefile +0 -0
  25. {absfuyu-4.0.0 → absfuyu-4.1.1}/docs/conf.py +0 -0
  26. {absfuyu-4.0.0 → absfuyu-4.1.1}/docs/index.rst +0 -0
  27. {absfuyu-4.0.0 → absfuyu-4.1.1}/docs/info.md +0 -0
  28. {absfuyu-4.0.0 → absfuyu-4.1.1}/docs/make.bat +0 -0
  29. {absfuyu-4.0.0 → absfuyu-4.1.1}/docs/modules.rst +0 -0
  30. {absfuyu-4.0.0 → absfuyu-4.1.1}/images/repository-image-crop.png +0 -0
  31. {absfuyu-4.0.0 → absfuyu-4.1.1}/images/repository-image-white.png +0 -0
  32. {absfuyu-4.0.0 → absfuyu-4.1.1}/images/repository-image.png +0 -0
  33. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/__main__.py +0 -0
  34. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/cli/__init__.py +0 -0
  35. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/cli/color.py +0 -0
  36. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/cli/config_group.py +0 -0
  37. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/cli/game_group.py +0 -0
  38. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/config/__init__.py +0 -0
  39. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/config/config.json +0 -0
  40. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/everything.py +0 -0
  41. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/extensions/__init__.py +0 -0
  42. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/extensions/beautiful.py +0 -0
  43. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/extensions/dev/__init__.py +0 -0
  44. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/extensions/dev/password_hash.py +0 -0
  45. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/extensions/dev/passwordlib.py +0 -0
  46. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/extensions/dev/project_starter.py +0 -0
  47. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/extensions/dev/shutdownizer.py +0 -0
  48. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/extensions/extra/__init__.py +0 -0
  49. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/extensions/extra/data_analysis.py +0 -0
  50. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/fun/WGS.py +0 -0
  51. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/fun/__init__.py +0 -0
  52. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/fun/tarot.py +0 -0
  53. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/game/sudoku.py +0 -0
  54. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/game/tictactoe.py +0 -0
  55. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/game/wordle.py +0 -0
  56. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/general/__init__.py +0 -0
  57. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/general/human.py +0 -0
  58. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/pkg_data/__init__.py +0 -0
  59. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/pkg_data/chemistry.pkl +0 -0
  60. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/pkg_data/tarot.pkl +0 -0
  61. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/py.typed +0 -0
  62. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/sort.py +0 -0
  63. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/tools/__init__.py +0 -0
  64. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/tools/keygen.py +0 -0
  65. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/tools/stats.py +0 -0
  66. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/tools/web.py +0 -0
  67. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/util/__init__.py +0 -0
  68. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/util/api.py +0 -0
  69. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/util/json_method.py +0 -0
  70. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/util/lunar.py +0 -0
  71. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/util/path.py +0 -0
  72. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/util/performance.py +0 -0
  73. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/util/pkl.py +0 -0
  74. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/util/zipped.py +0 -0
  75. {absfuyu-4.0.0 → absfuyu-4.1.1}/src/absfuyu/version.py +0 -0
  76. {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/__init__.py +0 -0
  77. {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/conftest.py +0 -0
  78. {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_beautiful.py +0 -0
  79. {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_config.py +0 -0
  80. {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_data_analysis.py +0 -0
  81. {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_data_extension.py +0 -0
  82. {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_extensions.py +0 -0
  83. {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_fun.py +0 -0
  84. {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_game.py +0 -0
  85. {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_generator.py +0 -0
  86. {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_logger.py +0 -0
  87. {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_passwordlib.py +0 -0
  88. {absfuyu-4.0.0 → absfuyu-4.1.1}/tests/test_pkg_data.py +0 -0
  89. {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-2024 AbsoluteWinter
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2022-2025 AbsoluteWinter
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: absfuyu
3
- Version: 4.0.0
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:perform
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:perform
174
+ hatch run workflow:<option>
175
175
 
176
- Note:
177
- - perform: bump version patch
178
- - perform2: bump version minor
179
- - perform3: bump version major
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
- perform = [
220
+ patch = [
195
221
  "test",
196
222
  "hatch version patch", # Bump version patch
197
223
  "build",
224
+ "hatch publish", # Publish
198
225
  ]
199
- perform2 = [
226
+ minor = [
200
227
  "test",
201
228
  "hatch version minor", # Bump version minor
202
229
  "build",
230
+ "hatch publish", # Publish
203
231
  ]
204
- perform3 = [
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
- # python_version = "3.8"
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]
@@ -22,7 +22,7 @@ Using in cmd (`absfuyu[cli]` required):
22
22
  __title__ = "absfuyu"
23
23
  __author__ = "AbsoluteWinter"
24
24
  __license__ = "MIT License"
25
- __version__ = "4.0.0"
25
+ __version__ = "4.1.1"
26
26
  __all__ = [
27
27
  "core",
28
28
  "config",
@@ -3,13 +3,14 @@ ABSFUYU CLI
3
3
  -----------
4
4
  Do
5
5
 
6
- Version: 1.2.0
7
- Date updated: 07/01/2025 (dd/mm/yyyy)
6
+ Version: 1.3.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.2.1
7
- Date updated: 14/11/2024 (dd/mm/yyyy)
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
@@ -82,7 +82,7 @@ def game_escapeLoop() -> None:
82
82
  print(x)
83
83
  stop_time = time.time()
84
84
  break
85
- print(f"= Escaped in {stop_time-start_time:,.2f}s =")
85
+ print(f"= Escaped in {stop_time - start_time:,.2f}s =")
86
86
 
87
87
 
88
88
  # Rock Paper Scissors
@@ -26,7 +26,7 @@ class GameStats:
26
26
  def _update_win_rate(self) -> None:
27
27
  try:
28
28
  self._win_rate = self.win / (self.win + self.draw + self.lose)
29
- self.win_rate = f"{self._win_rate*100:,.2f}%"
29
+ self.win_rate = f"{self._win_rate * 100:,.2f}%"
30
30
  except ZeroDivisionError:
31
31
  self._win_rate = 0
32
32
  self.win_rate = "N/A"
@@ -427,12 +427,12 @@ class ContentLoader:
427
427
  self.tag_dictionary = tag_dictionary
428
428
 
429
429
  # symbol stuff
430
- assert (
431
- comment_symbol != split_symbol
432
- ), "comment_symbol and split_symbol should have different values"
433
- assert (
434
- tag_separate_symbol != split_symbol
435
- ), "tag_separate_symbol and split_symbol should have different values"
430
+ assert comment_symbol != split_symbol, (
431
+ "comment_symbol and split_symbol should have different values"
432
+ )
433
+ assert tag_separate_symbol != split_symbol, (
434
+ "tag_separate_symbol and split_symbol should have different values"
435
+ )
436
436
  self.comment_symbol: str = comment_symbol
437
437
  self.split_symbol: str = split_symbol
438
438
  self.tag_separate_symbol: str = tag_separate_symbol
@@ -485,7 +485,7 @@ class ContentLoader:
485
485
  if x.startswith(self.comment_symbol) or len(x) == 0:
486
486
  continue # skip comment and empty lines
487
487
  logger.debug(
488
- f"### Loop {i+1} #####################################################################"
488
+ f"### Loop {i + 1} #####################################################################"
489
489
  )
490
490
 
491
491
  temp = x.split(self.split_symbol)
@@ -302,7 +302,7 @@ class Text(str):
302
302
  output.append(f"{splt_name[i]}='{temp[i]}'")
303
303
  else:
304
304
  for i in range(splt_len):
305
- output.append(f"{custom_var_name}{i+1}='{temp[i]}'")
305
+ output.append(f"{custom_var_name}{i + 1}='{temp[i]}'")
306
306
 
307
307
  # joined variable
308
308
  temp = []
@@ -319,9 +319,9 @@ class Text(str):
319
319
  if i == 0:
320
320
  temp.append(f"{custom_var_name}=")
321
321
  if i == splt_len - 1:
322
- temp.append(f"{custom_var_name}{i+1}")
322
+ temp.append(f"{custom_var_name}{i + 1}")
323
323
  else:
324
- temp.append(f"{custom_var_name}{i+1}+")
324
+ temp.append(f"{custom_var_name}{i + 1}+")
325
325
 
326
326
  output.append("".join(temp))
327
327
  if custom_var_name is None:
@@ -156,7 +156,9 @@ class Generator:
156
156
 
157
157
  while count < times:
158
158
  s = "".join(choice(char_lst) for _ in range(size))
159
- logger.debug(f"Time generated: {count+1}. Remaining: {times-count-1}. {s}")
159
+ logger.debug(
160
+ f"Time generated: {count + 1}. Remaining: {times - count - 1}. {s}"
161
+ )
160
162
  if not unique:
161
163
  unique_string.append(s)
162
164
  count += 1
@@ -274,7 +276,7 @@ class Generator:
274
276
  if num[i] >= 10: # type: ignore
275
277
  num[i] -= 9 # type: ignore
276
278
  sum += num[i] # type: ignore
277
- logger.debug(f"Loop {i+1}: {num[i]}, {sum}")
279
+ logger.debug(f"Loop {i + 1}: {num[i]}, {sum}")
278
280
 
279
281
  out = (10 - (sum % 10)) % 10
280
282
  logger.debug(f"Output: {out}")
@@ -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.2.3
7
- Date updated: 25/11/2024 (dd/mm/yyyy)
6
+ Version: 1.3.0
7
+ Date updated: 01/02/2025 (dd/mm/yyyy)
8
8
 
9
9
  Feature:
10
10
  --------
@@ -25,6 +25,7 @@ import math
25
25
  import re
26
26
  import string
27
27
  from itertools import chain, combinations
28
+ from pathlib import Path
28
29
 
29
30
  from absfuyu.core import CLITextColor
30
31
  from absfuyu.logger import logger
@@ -48,6 +49,29 @@ class Base64EncodeDecode:
48
49
  def decode(data: str) -> str:
49
50
  return base64.b64decode(data).decode()
50
51
 
52
+ @staticmethod
53
+ def encode_image(img_path: Path | str, data_tag: bool = False) -> str:
54
+ """Encode image file into base64 string
55
+
56
+ Parameters
57
+ ----------
58
+ img_path : Path | str
59
+ Path to image
60
+ data_tag : bool, optional
61
+ Add data tag before base64 string, by default False
62
+
63
+ Returns
64
+ -------
65
+ str
66
+ Encoded image
67
+ """
68
+ img = Path(img_path)
69
+ with open(img, "rb") as img_file:
70
+ b64_data = base64.b64encode(img_file.read()).decode("utf-8")
71
+ if data_tag:
72
+ return f"data:image/{img.suffix[1:]};charset=utf-8;base64,{b64_data}"
73
+ return b64_data
74
+
51
75
 
52
76
  class ChemistryElement:
53
77
  """Chemistry Element"""
@@ -217,7 +217,7 @@ class Obfuscator:
217
217
  )
218
218
  for x in bait_lst:
219
219
  output.append(
220
- f"{x}='{gen.generate_string(charset=Charset.DEFAULT,size=self.split_every_length,times=1,string_type_if_1=True)}'"
220
+ f"{x}='{gen.generate_string(charset=Charset.DEFAULT, size=self.split_every_length, times=1, string_type_if_1=True)}'"
221
221
  )
222
222
 
223
223
  random_eval_text = str(random.randint(1, 100))