absfuyu 4.1.1__py3-none-any.whl → 4.2.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 CHANGED
@@ -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.1.1"
25
+ __version__ = "4.2.0"
26
26
  __all__ = [
27
27
  "core",
28
28
  "config",
absfuyu/cli/__init__.py CHANGED
@@ -3,8 +3,8 @@ ABSFUYU
3
3
  -------
4
4
  COMMAND LINE INTERFACE
5
5
 
6
- Version: 1.0.0
7
- Date updated: 14/04/2024 (dd/mm/yyyy)
6
+ Version: 1.1.0
7
+ Date updated: 09/02/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  __all__ = ["cli"]
@@ -19,6 +19,7 @@ from absfuyu.cli.color import COLOR
19
19
  from absfuyu.cli.config_group import config_group
20
20
  from absfuyu.cli.do_group import do_group
21
21
  from absfuyu.cli.game_group import game_group
22
+ from absfuyu.cli.tool_group import tool_group
22
23
 
23
24
  # Color stuff
24
25
  colorama.init(autoreset=True)
@@ -48,4 +49,5 @@ def cli() -> None:
48
49
  cli.add_command(config_group)
49
50
  cli.add_command(do_group)
50
51
  cli.add_command(game_group)
52
+ cli.add_command(tool_group)
51
53
  cli.add_command(version)
absfuyu/cli/do_group.py CHANGED
@@ -3,14 +3,13 @@ ABSFUYU CLI
3
3
  -----------
4
4
  Do
5
5
 
6
- Version: 1.3.1
7
- Date updated: 01/02/2025 (dd/mm/yyyy)
6
+ Version: 1.4.0
7
+ Date updated: 07/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
14
13
 
15
14
  import click
16
15
 
@@ -18,7 +17,7 @@ from absfuyu import __title__
18
17
  from absfuyu.cli.color import COLOR
19
18
  from absfuyu.core import __package_feature__
20
19
  from absfuyu.general.human import Human2
21
- from absfuyu.tools.checksum import Checksum
20
+ from absfuyu.tools.shutdownizer import ShutDownizer
22
21
  from absfuyu.util.zipped import Zipper
23
22
  from absfuyu.version import PkgVersion
24
23
 
@@ -82,7 +81,11 @@ def fs(date: str, number_string: str) -> None:
82
81
  @click.command(name="info")
83
82
  @click.argument("date", type=str)
84
83
  def info(date: str) -> None:
85
- """Day info"""
84
+ """
85
+ Day info, format: yyyymmdd
86
+
87
+ Remake this
88
+ """
86
89
 
87
90
  instance = Human2(date)
88
91
  print(instance.info())
@@ -98,61 +101,11 @@ def unzip_files_in_dir(dir: str) -> None:
98
101
  print("Done")
99
102
 
100
103
 
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)
104
+ @click.command(name="shutdown")
105
+ def os_shutdown() -> None:
106
+ """Shutdown"""
107
+ engine = ShutDownizer()
108
+ engine.shutdown()
156
109
 
157
110
 
158
111
  @click.group(name="do")
@@ -167,4 +120,4 @@ do_group.add_command(advice)
167
120
  do_group.add_command(fs)
168
121
  do_group.add_command(info)
169
122
  do_group.add_command(unzip_files_in_dir)
170
- do_group.add_command(file_checksum)
123
+ do_group.add_command(os_shutdown)
@@ -0,0 +1,136 @@
1
+ """
2
+ ABSFUYU CLI
3
+ -----------
4
+ Tool
5
+
6
+ Version: 1.0.0
7
+ Date updated: 10/02/2025 (dd/mm/yyyy)
8
+ """
9
+
10
+ __all__ = ["tool_group"]
11
+
12
+ from typing import Literal
13
+
14
+ import click
15
+
16
+ from absfuyu.tools.checksum import Checksum
17
+ from absfuyu.tools.converter import Base64EncodeDecode, Text2Chemistry
18
+
19
+
20
+ @click.command(name="checksum")
21
+ @click.argument("file_path", type=str)
22
+ @click.option(
23
+ "--hashmode",
24
+ "-m",
25
+ "hash_mode",
26
+ type=click.Choice(["md5", "sha1", "sha256", "sha512"]),
27
+ default="sha256",
28
+ show_default=True,
29
+ help="Hash mode",
30
+ )
31
+ @click.option(
32
+ "--save-result",
33
+ "-s",
34
+ "save_result",
35
+ type=bool,
36
+ default=False,
37
+ is_flag=True,
38
+ show_default=True,
39
+ help="Save checksum result to file",
40
+ )
41
+ @click.option(
42
+ "--recursive",
43
+ "-r",
44
+ "recursive_mode",
45
+ type=bool,
46
+ default=False,
47
+ is_flag=True,
48
+ show_default=True,
49
+ help="Do checksum for every file in the folder (including child folder)",
50
+ )
51
+ @click.option(
52
+ "--compare",
53
+ "-c",
54
+ "hash_to_compare",
55
+ type=str,
56
+ default=None,
57
+ show_default=True,
58
+ help="Hash to compare",
59
+ )
60
+ def file_checksum(
61
+ file_path: str,
62
+ hash_mode: str | Literal["md5", "sha1", "sha256", "sha512"],
63
+ save_result: bool,
64
+ recursive_mode: bool,
65
+ hash_to_compare: str,
66
+ ) -> None:
67
+ """Checksum for file/directory"""
68
+ # print(hash_mode, save_result, recursive_mode)
69
+ instance = Checksum(file_path, hash_mode=hash_mode, save_result_to_file=save_result)
70
+ res = instance.checksum(recursive=recursive_mode)
71
+ if hash_to_compare:
72
+ print(res == hash_to_compare)
73
+ else:
74
+ print(res)
75
+
76
+
77
+ @click.command(name="t2c")
78
+ @click.argument("text", type=str)
79
+ def text2chem(text: str) -> None:
80
+ """Convert text into chemistry symbol"""
81
+ engine = Text2Chemistry()
82
+ out = engine.convert(text)
83
+ print(Text2Chemistry.beautify_result(out))
84
+
85
+
86
+ @click.command(name="e")
87
+ @click.argument("text", type=str)
88
+ def base64encode(text: str) -> None:
89
+ """Convert text to base64"""
90
+ print(Base64EncodeDecode.encode(text))
91
+
92
+
93
+ @click.command(name="d")
94
+ @click.argument("text", type=str)
95
+ def base64decode(text: str) -> None:
96
+ """Convert base64 to text"""
97
+ print(Base64EncodeDecode.decode(text))
98
+
99
+
100
+ @click.command(name="img")
101
+ @click.option(
102
+ "--data-tag",
103
+ "-d",
104
+ "data_tag",
105
+ type=bool,
106
+ default=False,
107
+ is_flag=True,
108
+ show_default=True,
109
+ help="Add data tag before base64 string",
110
+ )
111
+ @click.argument("img_path", type=str)
112
+ def base64convert_img(img_path: str, data_tag: bool) -> None:
113
+ """Convert img to base64"""
114
+ print(Base64EncodeDecode.encode_image(img_path, data_tag=data_tag))
115
+
116
+
117
+ @click.group(name="b64")
118
+ def base64_group():
119
+ """Base64 encode decode"""
120
+ pass
121
+
122
+
123
+ base64_group.add_command(base64encode)
124
+ base64_group.add_command(base64decode)
125
+ base64_group.add_command(base64convert_img)
126
+
127
+
128
+ @click.group(name="tool")
129
+ def tool_group() -> None:
130
+ """Tools"""
131
+ pass
132
+
133
+
134
+ tool_group.add_command(file_checksum)
135
+ tool_group.add_command(base64_group)
136
+ tool_group.add_command(text2chem)
absfuyu/core.py CHANGED
@@ -3,8 +3,8 @@ Absfuyu: Core
3
3
  -------------
4
4
  Contain type hints and other stuffs
5
5
 
6
- Version: 2.3.1
7
- Date updated: 01/02/2025 (dd/mm/yyyy)
6
+ Version: 2.3.2
7
+ Date updated: 11/02/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module Package
@@ -18,7 +18,7 @@ __all__ = [
18
18
  "DATA_PATH",
19
19
  ]
20
20
 
21
- __package_feature__ = ["beautiful", "extra", "res", "full", "dev"]
21
+ __package_feature__ = ["beautiful", "extra", "full", "dev"]
22
22
 
23
23
 
24
24
  # Library
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Absfuyu: Extension
3
3
  ------------------
4
+ Features that require additional libraries
4
5
 
5
6
  Version: 1.0.1
6
7
  Date updated: 24/11/2023 (dd/mm/yyyy)
@@ -26,9 +26,9 @@ from absfuyu.logger import logger
26
26
  ###########################################################################
27
27
  _EXTERNAL_DATA = {
28
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
29
  "tarot.json": "https://raw.githubusercontent.com/dariusk/corpora/master/data/divination/tarot_interpretations.json",
31
30
  "word_list.json": "https://raw.githubusercontent.com/dwyl/english-words/master/words_dictionary.json",
31
+ # "countries.json": "https://raw.githubusercontent.com/dr5hn/countries-states-cities-database/refs/heads/master/json/countries.json",
32
32
  }
33
33
 
34
34
 
@@ -37,6 +37,7 @@ _EXTERNAL_DATA = {
37
37
  class DataList:
38
38
  CHEMISTRY = files("absfuyu.pkg_data").joinpath("chemistry.pkl")
39
39
  TAROT = files("absfuyu.pkg_data").joinpath("tarot.pkl")
40
+ PASSWORDLIB = files("absfuyu.pkg_data").joinpath("passwordlib_lzma.pkl")
40
41
 
41
42
 
42
43
  class PkgData:
Binary file
absfuyu/tools/checksum.py CHANGED
@@ -3,8 +3,8 @@ Absufyu: Checksum
3
3
  -----------------
4
4
  Check MD5, SHA256, ...
5
5
 
6
- Version: 1.1.0
7
- Date updated: 01/02/2025 (dd/mm/yyyy)
6
+ Version: 1.1.1
7
+ Date updated: 05/02/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module level
@@ -58,6 +58,17 @@ class Checksum:
58
58
  hash_mode: str | Literal["md5", "sha1", "sha256", "sha512"] = "sha256",
59
59
  save_result_to_file: bool = False,
60
60
  ) -> None:
61
+ """Checksum engine
62
+
63
+ Parameters
64
+ ----------
65
+ path : str | Path
66
+ Path to file/directory to perform checksum
67
+ hash_mode : str | Literal["md5", "sha1", "sha256", "sha512"], optional
68
+ Hash mode, by default "sha256"
69
+ save_result_to_file : bool, optional
70
+ Save checksum result(s) to file, by default False
71
+ """
61
72
  self.path = Path(path)
62
73
  self.hash_mode = hash_mode
63
74
  self.save_result_to_file = save_result_to_file
@@ -109,7 +120,7 @@ class Checksum:
109
120
  str
110
121
  Checksum hash
111
122
  """
112
- if self.path.absolute().is_dir():
123
+ if self.path.absolute().is_dir(): # Dir
113
124
  new_path = self.path.joinpath(self.checksum_result_file_name)
114
125
  # List of files
115
126
  if recursive:
@@ -125,7 +136,7 @@ class Checksum:
125
136
  name = x.relative_to(self.path)
126
137
  res.append(f"{self._checksum_operation(x)} | {name}")
127
138
  output = "\n".join(res)
128
- else:
139
+ else: # File
129
140
  new_path = self.path.with_name(self.checksum_result_file_name)
130
141
  output = self._checksum_operation(self.path)
131
142
 
@@ -3,8 +3,8 @@ Absufyu: Converter
3
3
  ------------------
4
4
  Convert stuff
5
5
 
6
- Version: 1.3.0
7
- Date updated: 01/02/2025 (dd/mm/yyyy)
6
+ Version: 1.4.0
7
+ Date updated: 10/02/2025 (dd/mm/yyyy)
8
8
 
9
9
  Feature:
10
10
  --------
@@ -26,6 +26,7 @@ import re
26
26
  import string
27
27
  from itertools import chain, combinations
28
28
  from pathlib import Path
29
+ from typing import Self
29
30
 
30
31
  from absfuyu.core import CLITextColor
31
32
  from absfuyu.logger import logger
@@ -58,7 +59,7 @@ class Base64EncodeDecode:
58
59
  img_path : Path | str
59
60
  Path to image
60
61
  data_tag : bool, optional
61
- Add data tag before base64 string, by default False
62
+ Add data tag before base64 string, by default ``False``
62
63
 
63
64
  Returns
64
65
  -------
@@ -76,8 +77,6 @@ class Base64EncodeDecode:
76
77
  class ChemistryElement:
77
78
  """Chemistry Element"""
78
79
 
79
- _VERSION = (1, 1, 0)
80
-
81
80
  def __init__(self, name: str, number: int, symbol: str, atomic_mass: float) -> None:
82
81
  """
83
82
  name: element name
@@ -111,7 +110,7 @@ class ChemistryElement:
111
110
  }
112
111
 
113
112
  @classmethod
114
- def from_dict(cls, data: dict[str, str | int | float]) -> "ChemistryElement":
113
+ def from_dict(cls, data: dict[str, str | int | float]) -> Self:
115
114
  """
116
115
  Convert from ``dict`` data
117
116
 
@@ -159,7 +158,7 @@ class Text2Chemistry:
159
158
  # logger.debug(available)
160
159
  return base.difference(available)
161
160
 
162
- def convert(self, text: str) -> list[list[ChemistryElement]]:
161
+ def convert(self, text: str) -> list[list[ChemistryElement]] | list:
163
162
  """
164
163
  Convert text to chemistry symbol
165
164
 
@@ -231,6 +230,36 @@ class Text2Chemistry:
231
230
 
232
231
  return output
233
232
 
233
+ @staticmethod
234
+ def beautify_result(
235
+ result: list[list[ChemistryElement]] | list,
236
+ ) -> str: # Added in version 4.2.0
237
+ """Beautify the result from ``Text2Chemistry.convert()``
238
+
239
+ Parameters
240
+ ----------
241
+ result : list[list[ChemistryElement]] | list
242
+ Convert ``Text2Chemistry.convert()`` result
243
+
244
+ Returns
245
+ -------
246
+ str
247
+ Beautified output
248
+ """
249
+ if len(result) == 0:
250
+ res = "No possible combination"
251
+ else:
252
+ msg = []
253
+ for i, solution in enumerate(result, start=1):
254
+ msg.append(f"Option {i:02}: {', '.join([x.symbol for x in solution])}")
255
+ for x in solution:
256
+ msg.append(
257
+ f"{x.symbol} ({x.number}. {x.name} - {round(x.atomic_mass, 2)})"
258
+ )
259
+ msg.append("---")
260
+ res = "\n".join(msg)
261
+ return res
262
+
234
263
 
235
264
  class Str2Pixel:
236
265
  """Convert str into pixel"""
@@ -1,36 +1,37 @@
1
- # type: ignore
2
- # flake8: noqa
3
-
4
1
  """
5
2
  Absfuyu: Passwordlib
6
3
  --------------------
7
4
  Password library
8
5
 
9
- Version: 1.0.0dev1
10
- Date updated: 30/11/2023 (dd/mm/yyyy)
6
+ Version: 1.0.0
7
+ Date updated: 11/02/2025 (dd/mm/yyyy)
11
8
  """
12
9
 
10
+ # Module level
11
+ ###########################################################################
12
+ __all__ = ["PasswordGenerator"]
13
+
14
+
13
15
  # Library
14
16
  ###########################################################################
15
- # from collections import namedtuple
16
17
  import hashlib
18
+ import lzma
17
19
  import os
18
20
  import random
19
21
  import re
20
- from typing import List, Optional
21
-
22
- from absfuyu_res import DATA
22
+ from typing import NamedTuple, Optional
23
23
 
24
24
  from absfuyu.general.data_extension import DictExt, Text
25
25
  from absfuyu.general.generator import Charset, Generator
26
26
  from absfuyu.logger import logger
27
+ from absfuyu.pkg_data import DataList
27
28
  from absfuyu.util import set_min
28
29
  from absfuyu.util.pkl import Pickler
29
30
 
30
31
 
31
32
  # Function
32
33
  ###########################################################################
33
- def password_check(password: str) -> bool:
34
+ def _password_check(password: str) -> bool:
34
35
  """
35
36
  Verify the strength of ``password``.
36
37
  A password is considered strong if:
@@ -84,13 +85,13 @@ def password_check(password: str) -> bool:
84
85
 
85
86
  # Class
86
87
  ###########################################################################
87
- class Password:
88
- """Password"""
88
+ class PasswordHash(NamedTuple):
89
+ salt: bytes
90
+ key: bytes
89
91
 
90
- def __init__(self) -> None:
91
- """doc_string"""
92
- self.password: str = None
93
- self._words: List[str] = Pickler.load(DATA.PASSWORDLIB)
92
+
93
+ class PasswordGenerator:
94
+ """Password Generator"""
94
95
 
95
96
  def __str__(self) -> str:
96
97
  return f"{self.__class__.__name__}()"
@@ -98,38 +99,31 @@ class Password:
98
99
  def __repr__(self) -> str:
99
100
  return self.__str__()
100
101
 
101
- def password_hash(self):
102
+ @staticmethod
103
+ def password_hash(password: str) -> PasswordHash:
102
104
  """
103
105
  Generate hash for password
104
106
  """
105
107
  salt = os.urandom(32)
106
108
  key = hashlib.pbkdf2_hmac(
107
109
  hash_name="sha256",
108
- password=self.password.encode("utf-8"),
110
+ password=password.encode("utf-8"),
109
111
  salt=salt,
110
112
  iterations=100000,
111
113
  )
112
- out = {
113
- "salt": salt,
114
- "key": key,
115
- }
114
+ # out = {
115
+ # "salt": salt,
116
+ # "key": key,
117
+ # }
118
+ out = PasswordHash(salt, key)
116
119
  return out
117
120
 
118
121
  @staticmethod
119
- def password_check(password: str):
122
+ def password_check(password: str) -> dict:
120
123
  data = Text(password).analyze()
124
+ data = DictExt(data).apply(lambda x: True if x > 0 else False) # type: ignore
121
125
  data.__setitem__("length", len(password))
122
- data = DictExt(data).apply(lambda x: True if x > 0 else False)
123
- return data
124
-
125
- @property
126
- def words(self) -> List[str]:
127
- """
128
- Word list to generate passphrase
129
-
130
- :rtype: list[str]
131
- """
132
- return self._words
126
+ return dict(data)
133
127
 
134
128
  # Password generator
135
129
  @staticmethod
@@ -187,24 +181,26 @@ class Password:
187
181
  while True:
188
182
  pwd = Generator.generate_string(
189
183
  charset=charset,
190
- size=set_min(length, min_value=8),
184
+ size=set_min(length, min_value=8), # type: ignore
191
185
  times=1,
192
186
  string_type_if_1=True,
193
187
  )
194
188
 
195
189
  analyze = Text(pwd).analyze() # Count each type of char
196
190
 
197
- s = sum([1 for x in analyze.values() if x > 0])
191
+ s = sum([1 for x in analyze.values() if x > 0]) # type: ignore
198
192
  if s > check: # Break loop if each type of char has atleast 1
199
193
  break
200
- return pwd
194
+ return pwd # type: ignore
201
195
 
196
+ @staticmethod
202
197
  def generate_passphrase(
203
- self,
204
198
  num_of_blocks: int = 5,
205
199
  block_divider: Optional[str] = None,
206
200
  first_letter_cap: bool = True,
207
201
  include_number: bool = True,
202
+ *,
203
+ custom_word_list: list[str] | None = None,
208
204
  ) -> str:
209
205
  """
210
206
  Generate a random passphrase
@@ -223,6 +219,9 @@ class Password:
223
219
  include_number : bool
224
220
  Add number to the end of each word (Default: ``True``)
225
221
 
222
+ custom_word_list : list[str] | None
223
+ Custom word list for passphrase generation, by default uses a list of 360K+ words
224
+
226
225
  Returns
227
226
  -------
228
227
  str
@@ -234,25 +233,28 @@ class Password:
234
233
  >>> print(Password().generate_passphrase())
235
234
  Myomectomies7-Sully4-Torpedomen7-Netful2-Begaud8
236
235
  """
237
-
238
- def convert_func(value: str):
239
- if first_letter_cap:
240
- value = value.title()
241
- if include_number:
242
- value += str(random.choice(range(10)))
243
- return value
236
+ words: list[str] = (
237
+ (lzma.decompress(Pickler.load(DataList.PASSWORDLIB)).decode().split(",")) # type: ignore
238
+ if not custom_word_list
239
+ else custom_word_list
240
+ )
244
241
 
245
242
  if not block_divider:
246
243
  block_divider = "-"
247
244
 
248
- return block_divider.join(
249
- [convert_func(random.choice(self.words)) for _ in range(num_of_blocks)]
250
- )
245
+ dat = [random.choice(words) for _ in range(num_of_blocks)]
246
+
247
+ if first_letter_cap:
248
+ dat = list(map(lambda x: x.title(), dat))
249
+
250
+ if include_number:
251
+ idx = random.choice(range(5))
252
+ dat[idx] += str(random.choice(range(10)))
253
+
254
+ return block_divider.join(dat)
251
255
 
252
256
 
253
257
  # Run
254
258
  ###########################################################################
255
259
  if __name__ == "__main__":
256
260
  logger.setLevel(10)
257
- # print(os.urandom(32))
258
- print(Password.password_check(Password.generate_password()))