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.

@@ -0,0 +1,266 @@
1
+ """
2
+ Absfuyu: Shutdownizer
3
+ ---------------------
4
+ This shutdowns
5
+
6
+ Version: 1.0.0
7
+ Date updated: 07/02/2025 (dd/mm/yyyy)
8
+ """
9
+
10
+ # Module level
11
+ ###########################################################################
12
+ __all__ = ["ShutDownizer", "ShutdownEngine"]
13
+
14
+
15
+ # Library
16
+ ###########################################################################
17
+ import os
18
+ import subprocess
19
+ import sys
20
+ from abc import ABC, abstractmethod
21
+ from datetime import datetime, time, timedelta
22
+ from pathlib import Path
23
+ from typing import Annotated
24
+
25
+ from absfuyu.logger import logger
26
+
27
+ # TODO: Schedule shutdown, random time shutdown, test
28
+
29
+
30
+ # Class
31
+ ###########################################################################
32
+ class ShutDownizer:
33
+ """
34
+ ShutDownizer
35
+
36
+ Shutdown tool because why not
37
+ """
38
+
39
+ def __init__(self) -> None:
40
+ self.os: str = sys.platform
41
+ logger.debug(f"Current OS: {self.os}")
42
+
43
+ if self.os in ["win32", "cygwin"]: # Windows
44
+ self.engine = ShutdownEngineWin() # type: ignore
45
+ elif self.os == "darwin": # MacOS
46
+ self.engine = ShutdownEngineMac() # type: ignore
47
+ elif self.os == "linux": # Linux
48
+ self.engine = ShutdownEngineLinux() # type: ignore
49
+ else:
50
+ raise SystemError("OS not supported")
51
+
52
+ def __str__(self) -> str:
53
+ return f"{self.__class__.__name__}({self.os})"
54
+
55
+ def __repr__(self) -> str:
56
+ return self.__str__()
57
+
58
+ def shutdown(self) -> None:
59
+ """Shutdown"""
60
+ self.engine.shutdown()
61
+
62
+ def restart(self) -> None:
63
+ """Restart"""
64
+ self.engine.restart()
65
+
66
+ def cancel(self) -> None:
67
+ """Cancel"""
68
+ self.engine.cancel()
69
+
70
+
71
+ class ShutdownEngine(ABC):
72
+ """
73
+ Abstract shutdown class for different type of OS
74
+ """
75
+
76
+ def __str__(self) -> str:
77
+ return f"{self.__class__.__name__}()"
78
+
79
+ def __repr__(self) -> str:
80
+ return self.__str__()
81
+
82
+ def _execute_cmd(self, cmd: str | list) -> None:
83
+ """Execute the cmd"""
84
+ try:
85
+ if isinstance(cmd, str):
86
+ subprocess.run(cmd.split())
87
+ elif isinstance(cmd, list):
88
+ subprocess.run(cmd)
89
+ except Exception:
90
+ logger.error(f'"{cmd}" failed to run')
91
+ raise ValueError(f'"{cmd}" failed to run') # noqa
92
+
93
+ def _execute_multiple_cmds(self, cmds: list) -> None:
94
+ if not isinstance(cmds, list):
95
+ raise ValueError("cmds must be a <list>")
96
+ for cmd in cmds:
97
+ try:
98
+ logger.debug(f"Executing: {cmd}")
99
+ self._execute_cmd(cmd)
100
+ break
101
+ except Exception:
102
+ logger.error(f'"{cmd}" failed to run')
103
+
104
+ @abstractmethod
105
+ def shutdown(self) -> None:
106
+ """Shutdown"""
107
+ pass
108
+
109
+ @abstractmethod
110
+ def restart(self) -> None:
111
+ """Restart"""
112
+ pass
113
+
114
+ @abstractmethod
115
+ def sleep(self) -> None:
116
+ """Sleep"""
117
+ pass
118
+
119
+ @abstractmethod
120
+ def abort(self) -> None:
121
+ """Abort/Cancel"""
122
+ pass
123
+
124
+ def cancel(self) -> None:
125
+ """Abort/Cancel"""
126
+ self.abort()
127
+
128
+ def _calculate_time(
129
+ self,
130
+ h: Annotated[int, "positive"] = 0,
131
+ m: Annotated[int, "positive"] = 0,
132
+ aggregate: bool = True,
133
+ ) -> int:
134
+ """This calculate time for schedule shutdown
135
+
136
+ Parameters
137
+ ----------
138
+ h : int, optional
139
+ Hours to add (24h format), by default 0
140
+ m : int, optional
141
+ Minutes to add (24h format), by default 0
142
+ aggregate : bool, optional
143
+ | This add hours and and minutes to `time.now()`, by default ``True``
144
+ | - ``True`` : Add hours and minutes to current time
145
+ | - ``False``: Use ``h`` and ``m`` as fixed time point to shutdown
146
+
147
+ Returns
148
+ -------
149
+ int
150
+ Seconds left to shutdown
151
+ """
152
+ now = datetime.now()
153
+ if aggregate:
154
+ delta = timedelta(hours=h, minutes=m)
155
+ out = delta.seconds
156
+ else:
157
+ new_time = datetime.combine(now.date(), time(hour=h, minute=m))
158
+ diff = new_time - now
159
+ out = diff.seconds
160
+ return out
161
+
162
+
163
+ class ShutdownEngineWin(ShutdownEngine):
164
+ """ShutDownizer - Windows"""
165
+
166
+ def shutdown(self) -> None:
167
+ cmds = ["shutdown -f -s -t 0"]
168
+ self._execute_multiple_cmds(cmds)
169
+
170
+ def restart(self) -> None:
171
+ cmds = ["shutdown -r"]
172
+ self._execute_multiple_cmds(cmds)
173
+
174
+ def sleep(self) -> None:
175
+ cmds = ["rundll32.exe powrprof.dll,SetSuspendState 0,1,0"]
176
+ self._execute_multiple_cmds(cmds)
177
+
178
+ def abort(self) -> None:
179
+ cmds = ["shutdown -a"]
180
+ self._execute_multiple_cmds(cmds)
181
+
182
+ def _punish(self, *, are_you_sure_about_this: bool = False) -> None:
183
+ """Create a `batch` script that shut down computer when boot up"""
184
+ if not are_you_sure_about_this:
185
+ return None
186
+ try:
187
+ startup_folder_win = Path(os.getenv("appdata")).joinpath( # type: ignore
188
+ "Microsoft", "Windows", "Start Menu", "Programs", "Startup"
189
+ )
190
+ with open(startup_folder_win.joinpath("system.bat"), "w") as f:
191
+ f.write("shutdown -f -s -t 0")
192
+ except Exception:
193
+ logger.error("Cannot write file to startup folder")
194
+
195
+
196
+ class ShutdownEngineMac(ShutdownEngine):
197
+ """ShutDownizer - MacOS"""
198
+
199
+ def shutdown(self) -> None:
200
+ cmds = [
201
+ ["osascript", "-e", 'tell application "System Events" to shut down'],
202
+ "pmset sleepnow",
203
+ "shutdown -h now",
204
+ "sudo shutdown -h now",
205
+ ]
206
+ self._execute_multiple_cmds(cmds)
207
+
208
+ def restart(self) -> None:
209
+ cmds = [
210
+ ["osascript", "-e", 'tell application "System Events" to restart'],
211
+ "shutdown -r now",
212
+ "sudo shutdown -r now",
213
+ ]
214
+ self._execute_multiple_cmds(cmds)
215
+
216
+ def sleep(self) -> None:
217
+ cmds = [
218
+ ["osascript", "-e", 'tell application "System Events" to sleep'],
219
+ "pmset sleepnow",
220
+ "shutdown -s now",
221
+ "sudo shutdown -s now",
222
+ ]
223
+ self._execute_multiple_cmds(cmds)
224
+
225
+ def abort(self) -> None:
226
+ cmds = [
227
+ ["osascript", "-e", 'tell application "System Events" to cancel shutdown'],
228
+ "killall shutdown",
229
+ "shutdown -c",
230
+ "sudo shutdown -c",
231
+ ]
232
+ self._execute_multiple_cmds(cmds)
233
+
234
+
235
+ class ShutdownEngineLinux(ShutdownEngine):
236
+ """ShutDownizer - Linux"""
237
+
238
+ def shutdown(self) -> None:
239
+ cmds = [
240
+ "gnome-session-quit --power-off",
241
+ "systemctl --user poweroff",
242
+ "sudo shutdown -h now",
243
+ ]
244
+ self._execute_multiple_cmds(cmds)
245
+
246
+ def restart(self) -> None:
247
+ cmds = [
248
+ "gnome-session-quit --reboot",
249
+ "systemctl reboot",
250
+ "sudo shutdown -r now",
251
+ ]
252
+ self._execute_multiple_cmds(cmds)
253
+
254
+ def sleep(self) -> None:
255
+ cmds = ["systemctl suspend", "sudo shutdown -s now"]
256
+ self._execute_multiple_cmds(cmds)
257
+
258
+ def abort(self) -> None:
259
+ cmds = ["sudo shutdown -c"]
260
+ self._execute_multiple_cmds(cmds)
261
+
262
+
263
+ # Run
264
+ ###########################################################################
265
+ if __name__ == "__main__":
266
+ pass
@@ -225,4 +225,4 @@ class Decimal:
225
225
  # Run
226
226
  ###########################################################################
227
227
  if __name__ == "__main__":
228
- print(str(Decimal.number(10000)))
228
+ pass
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: absfuyu
3
- Version: 4.1.1
3
+ Version: 4.2.0
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/
@@ -42,30 +42,26 @@ Provides-Extra: extra
42
42
  Requires-Dist: numpy; extra == 'extra'
43
43
  Requires-Dist: pandas; extra == 'extra'
44
44
  Provides-Extra: full
45
- Requires-Dist: absfuyu-res; extra == 'full'
46
45
  Requires-Dist: numpy; extra == 'full'
47
46
  Requires-Dist: pandas; extra == 'full'
48
47
  Requires-Dist: rich; extra == 'full'
49
48
  Requires-Dist: tqdm; extra == 'full'
50
- Provides-Extra: res
51
- Requires-Dist: absfuyu-res; extra == 'res'
52
49
  Description-Content-Type: text/markdown
53
50
 
54
51
  <div align="center">
55
- <h1 align="center">
56
- <img src="https://github.com/AbsoluteWinter/AbsoluteWinter.github.io/blob/main/absfuyu/images/repository-image-crop.png?raw=true" alt="absfuyu"/>
57
- </h1>
58
- <p align="center">
59
- <a href="https://pypi.org/project/absfuyu/"><img src="https://img.shields.io/pypi/pyversions/absfuyu?style=flat-square&logo=python" alt="PyPI Supported Versions"/></a>
60
- <a href="https://pypi.org/project/absfuyu/"><img src="https://img.shields.io/pypi/dm/absfuyu?style=flat-square&color=blue" alt="PyPI Downloads"/></a>
61
- <a href="https://pypi.org/project/absfuyu/"><img src="https://img.shields.io/pypi/v/absfuyu?style=flat-square&logo=pypi" /></a>
62
- <a><img src="https://img.shields.io/pypi/l/absfuyu?style=flat-square&logo=github&color=blue"/></a>
63
- <a><img src="https://img.shields.io/badge/code%20style-black-black?style=flat-square"/></a>
64
- <a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json&style=flat-square" alt="Ruff" style="max-width:100%;"></a>
65
- </p>
52
+ <h1 align="center">
53
+ <img src="https://github.com/AbsoluteWinter/AbsoluteWinter.github.io/blob/main/absfuyu/images/repository-image-crop.png?raw=true" alt="absfuyu"/>
54
+ </h1>
55
+ <p align="center">
56
+ <a href="https://pypi.org/project/absfuyu/"><img src="https://img.shields.io/pypi/pyversions/absfuyu?style=flat-square&logo=python" alt="PyPI Supported Versions"/></a>
57
+ <a href="https://pypi.org/project/absfuyu/"><img src="https://img.shields.io/pypi/dm/absfuyu?style=flat-square&color=blue" alt="PyPI Downloads"/></a>
58
+ <a href="https://pypi.org/project/absfuyu/"><img src="https://img.shields.io/pypi/v/absfuyu?style=flat-square&logo=pypi" /></a>
59
+ <a><img src="https://img.shields.io/pypi/l/absfuyu?style=flat-square&logo=github&color=blue"/></a>
60
+ <a><img src="https://img.shields.io/badge/code%20style-black-black?style=flat-square"/></a>
61
+ <a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json&style=flat-square" alt="Ruff" style="max-width:100%;"></a>
62
+ </p>
66
63
  </div>
67
64
 
68
-
69
65
  ---
70
66
 
71
67
  ## **SUMMARY:**
@@ -75,7 +71,7 @@ Description-Content-Type: text/markdown
75
71
  ## **INSTALLATION:**
76
72
 
77
73
  ```bash
78
- $ pip install -U absfuyu
74
+ pip install -U absfuyu
79
75
  ```
80
76
 
81
77
  ## **USAGE:**
@@ -115,7 +111,6 @@ python -m pip install -e .[full,dev]
115
111
  hatch env show
116
112
  ```
117
113
 
118
-
119
114
  ## **LICENSE:**
120
115
 
121
116
  MIT License
@@ -1,27 +1,22 @@
1
- absfuyu/__init__.py,sha256=EGTitZIqMbg-jQFJD5nJi4papdMQsCoYnr-9EnvlUmI,638
1
+ absfuyu/__init__.py,sha256=pCNxLstlkcm5DQrRNeNbP_U_9QssMWcUpS9SHvjE33k,638
2
2
  absfuyu/__main__.py,sha256=OpMwc35W5VANzw6gvlqJaJOl2H89i_frFZbleUQwDss,163
3
- absfuyu/core.py,sha256=MZQH3hpUAamGx2NM-TlIWvAnRBBwa9R9fm7F2WFe60c,1240
3
+ absfuyu/core.py,sha256=J7XASHaSjhVyf9qtDU8LDMyJrUgW-yEecgxZP16u7PI,1233
4
4
  absfuyu/everything.py,sha256=PGIXlqgxyADFPygohVYVIb7fZz72L_xXrlLX0WImuYg,788
5
5
  absfuyu/logger.py,sha256=Pue3oWYYSF03A-fVp3E137jzlZVI71mYqddic8myauQ,13141
6
6
  absfuyu/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  absfuyu/sort.py,sha256=Z9nK15WehmZjlUNwvAOwF4FhV-rFcqlXkCcehNYmo78,6827
8
8
  absfuyu/version.py,sha256=KMaeXNl93L4VU2RnTySoFv23IDyTvHfy84nyatFcKaE,14128
9
- absfuyu/cli/__init__.py,sha256=nKTbe4iPpkjtDDMJwVY36heInKDm1zyek9ags5an7s4,1105
9
+ absfuyu/cli/__init__.py,sha256=mYX6lVAat9UOI9qR-ZDFw_4WOLVA9r-jTtW8d2fBEKM,1181
10
10
  absfuyu/cli/color.py,sha256=7M3XqFllt26tv_NR5qKgyTId6wnVADtUB74cDYy8pOQ,497
11
11
  absfuyu/cli/config_group.py,sha256=FsyYm2apSyAA2PAD12CpHAizenRds_QlLf8j0AlLuVo,1230
12
- absfuyu/cli/do_group.py,sha256=HS1G9nFnqtmNVwWZiOGvu4RB6URT2VnCpEtdY9e7n2Q,4132
12
+ absfuyu/cli/do_group.py,sha256=8LdDgx3BYfhpM2d4q-SO9jA_ZcenNKLYr0Q7Hgj4TPg,2919
13
13
  absfuyu/cli/game_group.py,sha256=ySpL2hm4VCplhNY0s22kBGI5eFCdJj9fm1T58yftU74,2348
14
+ absfuyu/cli/tool_group.py,sha256=JcmzcXMcMc1OVhAkcKeUPujVlsWyn_DafsrB_1f9rD8,3155
14
15
  absfuyu/config/__init__.py,sha256=4r77tFm3mgHX8H1uWWNXC_FZ8hiSJzsYAyiStZiVj5w,8641
15
16
  absfuyu/config/config.json,sha256=-ZQnmDuLq0aAFfsrQbSNR3tq5k9Eu9IVUQgYD9htIQM,646
16
- absfuyu/extensions/__init__.py,sha256=hxeZm3w00K4GC78cDTIo5ROWiWAZw4zEmlevfOqbNvo,146
17
+ absfuyu/extensions/__init__.py,sha256=gt9YF5R5O7Pavqc8Hne0LFe0B4YOYV8gqfsiAyHqkD0,190
17
18
  absfuyu/extensions/beautiful.py,sha256=eGfmJ72UQTVvevMCr80RoyYuCYxLaHkvAm1Kk2pkqc0,5331
18
- absfuyu/extensions/dev/__init__.py,sha256=sr80dV4a2gktP3GhAYHQdFM5vDkXyTsSi74yCbnLc0E,6534
19
- absfuyu/extensions/dev/password_hash.py,sha256=AO8VSW9s9VyrTCGgrN-HLqYIUWAYFSds6vLYrhH-ako,1826
20
- absfuyu/extensions/dev/passwordlib.py,sha256=RvN-AOYann_K-OXVJOmtfTi38uYlcr7Gd2OnGe0I1og,6812
21
- absfuyu/extensions/dev/project_starter.py,sha256=RkTHwMXdChB45d7rrDuDMzo3a34-P514JlOmYHHNads,1593
22
- absfuyu/extensions/dev/shutdownizer.py,sha256=Vm9AUsUGyvRWRYAl4fp4CriSmixzBtV8ZGvqmNjdEvo,4027
23
- absfuyu/extensions/extra/__init__.py,sha256=gUB8fIOz4V9xQxk689dMe7NFFu_r-CneCsi32DtjQAo,552
24
- absfuyu/extensions/extra/data_analysis.py,sha256=JR8smS6gVRZ4jJtboshCpC3jFabVLQ8LBhWOA-sfIG4,32969
19
+ absfuyu/extensions/data_analysis.py,sha256=JR8smS6gVRZ4jJtboshCpC3jFabVLQ8LBhWOA-sfIG4,32969
25
20
  absfuyu/fun/WGS.py,sha256=Aug9BsLTawBDkjdCQ3oqWAfGGeY6ZSBV1kENrTVnlUA,9461
26
21
  absfuyu/fun/__init__.py,sha256=AOaq3NdgaK7e5hk622Wspiu6Z2biVK-jpk2FChn05rA,6366
27
22
  absfuyu/fun/tarot.py,sha256=Y0z5rNWLOmqfJV961L_9LzUORRNR89Vegy7KqgNR9xs,2539
@@ -35,14 +30,17 @@ absfuyu/general/content.py,sha256=IfX5SkgoD-sjYJrbRHRIS5-g6fGp_X65A07ViB0zLpk,17
35
30
  absfuyu/general/data_extension.py,sha256=tvZM4moHNxqOh_iT6ekFELZgfhiIoZ8SUqm9wUIaokU,48938
36
31
  absfuyu/general/generator.py,sha256=PW_4Z-YZ30StwDuUUfHD7B0qnVKMo_ZZHHKj54BzgXk,9731
37
32
  absfuyu/general/human.py,sha256=drZT1nI_YwGMOwZu8pbzf3frM-SUY15cOcnUpc4pzQk,12241
38
- absfuyu/pkg_data/__init__.py,sha256=VbUoFnUDiw_3bKZVvIzwf_ve0y97rmhfpkbbrP_ob_w,4761
33
+ absfuyu/pkg_data/__init__.py,sha256=8iHOGp-MWSao_u6a6-iQmSfMReinwbWbjR7EdrWmQeY,4867
39
34
  absfuyu/pkg_data/chemistry.pkl,sha256=kYWNa_PVffoDnzT8b9Jvimmf_GZshPe1D-SnEKERsLo,4655
35
+ absfuyu/pkg_data/passwordlib_lzma.pkl,sha256=rT5lJT8t42BATU5Cp2qFwbnZkbx-QlUgodSvR0wFY6I,891877
40
36
  absfuyu/pkg_data/tarot.pkl,sha256=ssXTCC_BQgslO5F-3a9HivbxFQ6BioIe2E1frPVi2m0,56195
41
37
  absfuyu/tools/__init__.py,sha256=VDmmMLEfiRyUWPVrPYc8JUEa5TXjLguKVnyI3YavFv0,118
42
- absfuyu/tools/checksum.py,sha256=cLSuL_ZsoroFYYVR1GhOfBbon_iXEm1OazbjYFPJabM,4393
43
- absfuyu/tools/converter.py,sha256=8jqOSdkbzzupKJcBndV5q4OBu2kWFWpV3j2IswS4Vqc,10609
38
+ absfuyu/tools/checksum.py,sha256=gB8LvOeQRRuI1dYMmNZINF0QyUKyQZiZ7oJJ0m7QMDY,4807
39
+ absfuyu/tools/converter.py,sha256=STA5NZZt5Xj0YRTup8tvh1YE2z7Y1AWRbEbU3EAS0TY,11589
44
40
  absfuyu/tools/keygen.py,sha256=drj8OUDCXrLvcVf9_Shd5UMShm_mBTxa9Sg_BrAT5yM,7356
45
41
  absfuyu/tools/obfuscator.py,sha256=kiaFvMw2RwEfZvXKdbUrEYA_AuVETivoL2eVmtUWU4w,8669
42
+ absfuyu/tools/passwordlib.py,sha256=q-KOGld-LN6ndv8HLs5Yq6iJEI9lrb_fDc4kFwh9M8c,7104
43
+ absfuyu/tools/shutdownizer.py,sha256=W5sYoqvumTKj8fYIt1D0f5BtWCHUNBB9IO65f3P4G5w,7674
46
44
  absfuyu/tools/stats.py,sha256=zZNK59qn0xqQlyw5CP3MP5WRMSxncdKZythqvgNR1lQ,5191
47
45
  absfuyu/tools/web.py,sha256=Mb5RYj1Fu5eB-mYMusyrE2JG6_ZPEf8WT72Z8q6Ep74,1406
48
46
  absfuyu/util/__init__.py,sha256=1V2DwIUt-bSiSURnk6AzfKB0HRLHwoi8_6RaIvywlzU,3716
@@ -52,10 +50,10 @@ absfuyu/util/lunar.py,sha256=xW7HcgyIRjWBhQv36RimNZIT8Ed_X83moqr5h5-Ku9k,13750
52
50
  absfuyu/util/path.py,sha256=p4Ac98FfW5pXLNRRuQ_QEx_G7-UOSBKABAg_xrOq7u4,16628
53
51
  absfuyu/util/performance.py,sha256=F-aLJ-5wmwkiOdl9_wZcFRKifL9zOahw52JeL4TbCuQ,9105
54
52
  absfuyu/util/pkl.py,sha256=ZZf6-PFC2uRGXqARNi0PGH3A0IXwMP0sYPWZJXENvak,1559
55
- absfuyu/util/shorten_number.py,sha256=_R_FhzBYDvtX_B8jA0WhVyG2G_s-kyolra9Y2gH5e4w,6603
53
+ absfuyu/util/shorten_number.py,sha256=CZRG0fh9y3bpmFnY9xy5gWEv1kceD1nJmQGKDxPbwCQ,6574
56
54
  absfuyu/util/zipped.py,sha256=CU_le1MynFwHfpajCRRJ7_A-r1jfMjt9uu72jLooW6w,3111
57
- absfuyu-4.1.1.dist-info/METADATA,sha256=dJJP-975rfpiV712uDMRZXbnOhDtmLGkfAWMfriu9L0,3794
58
- absfuyu-4.1.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
59
- absfuyu-4.1.1.dist-info/entry_points.txt,sha256=bW5CgJRTTWJ2Pywojo07sf-YucRPcnHzMmETh5avbX0,79
60
- absfuyu-4.1.1.dist-info/licenses/LICENSE,sha256=pFCHBSNSzdXwYG1AHpq7VcofI1NMQ1Fc77RzZ4Ln2O4,1097
61
- absfuyu-4.1.1.dist-info/RECORD,,
55
+ absfuyu-4.2.0.dist-info/METADATA,sha256=6uiXP8Ru7sBlWoFQmoqC2sJdBO9qu3fo5sER0rnAnu0,3737
56
+ absfuyu-4.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
57
+ absfuyu-4.2.0.dist-info/entry_points.txt,sha256=bW5CgJRTTWJ2Pywojo07sf-YucRPcnHzMmETh5avbX0,79
58
+ absfuyu-4.2.0.dist-info/licenses/LICENSE,sha256=pFCHBSNSzdXwYG1AHpq7VcofI1NMQ1Fc77RzZ4Ln2O4,1097
59
+ absfuyu-4.2.0.dist-info/RECORD,,
@@ -1,244 +0,0 @@
1
- # type: ignore
2
- # flake8: noqa
3
-
4
- """
5
- Absfuyu: Development
6
- --------------------
7
- Some stuffs that are not ready to use yet.
8
- Use at your own risk, everything is subject to change
9
-
10
- Version: 2.0.0
11
- Date updated: 23/11/2023 (dd/mm/yyyy)
12
- """
13
-
14
- # Module level
15
- ###########################################################################
16
- __all__ = [
17
- "password_check",
18
- "fib",
19
- ]
20
-
21
-
22
- # Library
23
- ###########################################################################
24
- import base64
25
- import re
26
- from collections import deque
27
- from functools import lru_cache
28
- from typing import Dict, Final, List, NamedTuple
29
-
30
-
31
- # PASSWORD CHECKER
32
- def password_check(password: str) -> bool:
33
- """
34
- Verify the strength of 'password'.
35
- Returns a dict indicating the wrong criteria.
36
- A password is considered strong if:
37
- - 8 characters length or more
38
- - 1 digit or more
39
- - 1 symbol or more
40
- - 1 uppercase letter or more
41
- - 1 lowercase letter or more
42
- """
43
-
44
- # calculating the length
45
- length_error = len(password) < 8
46
-
47
- # searching for digits
48
- digit_error = re.search(r"\d", password) is None
49
-
50
- # searching for uppercase
51
- uppercase_error = re.search(r"[A-Z]", password) is None
52
-
53
- # searching for lowercase
54
- lowercase_error = re.search(r"[a-z]", password) is None
55
-
56
- # searching for symbols
57
- symbols = re.compile(r"[ !#$%&'()*+,-./[\\\]^_`{|}~" + r'"]')
58
- symbol_error = symbols.search(password) is None
59
-
60
- detail = {
61
- "password_ok": not any(
62
- [ # overall result
63
- length_error,
64
- digit_error,
65
- uppercase_error,
66
- lowercase_error,
67
- symbol_error,
68
- ]
69
- ),
70
- "length_error": length_error,
71
- "digit_error": digit_error,
72
- "uppercase_error": uppercase_error,
73
- "lowercase_error": lowercase_error,
74
- "symbol_error": symbol_error,
75
- }
76
-
77
- return detail["password_ok"]
78
-
79
-
80
- # FIBONACCI WITH CACHE
81
- @lru_cache(maxsize=5)
82
- def fib(n: int) -> int:
83
- """Fibonacci (recursive)"""
84
- # max recursion is 484
85
- if n < 2:
86
- return n
87
- return fib(n - 1) + fib(n - 2)
88
-
89
-
90
- # https://stackoverflow.com/questions/563022/whats-python-good-practice-for-importing-and-offering-optional-features
91
- def optional_import(module: str, name: str = None, package: str = None):
92
- import importlib
93
-
94
- try:
95
- module = importlib.import_module(module)
96
- return module if name is None else getattr(module, name)
97
- except ImportError as e:
98
- if package is None:
99
- package = module
100
- msg = f"install the '{package}' package to make use of this feature"
101
- import_error = e
102
-
103
- def _failed_import(*args):
104
- raise ValueError(msg) from import_error
105
-
106
- return _failed_import
107
-
108
-
109
- def load_toml_file(toml_file: str):
110
- """
111
- Load ``.toml`` file
112
-
113
- :param toml_file: Path to ``.toml`` file
114
- """
115
- from sys import version_info as _python_version
116
-
117
- if _python_version.minor < 11:
118
- try:
119
- import tomli as tomllib # type: ignore
120
- except ImportError:
121
- raise ImportError("Please install tomli python package")
122
- except:
123
- raise SystemExit
124
- else:
125
- import tomllib
126
-
127
- with open(toml_file, "rb") as file:
128
- toml_data = tomllib.load(file)
129
- return toml_data
130
-
131
-
132
- def get_sitemap(url: str):
133
- import re
134
-
135
- import requests
136
-
137
- class Url(NamedTuple):
138
- base: str
139
- extra: str
140
-
141
- def __str__(self) -> str:
142
- return f"{self.base}{self.extra}"
143
-
144
- def __repr__(self) -> str:
145
- return f"{self.__class__.__name__}({self.base}{self.extra})"
146
-
147
- # robots.txt
148
- # sitemap.xml
149
- if not url.endswith("/"):
150
- url += "/"
151
- pattern = re.compile(
152
- r"([(http(s)?):\/\/(www\.)?a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b)([-a-zA-Z0-9@:%_\+.~#?&//=]*)",
153
- re.IGNORECASE,
154
- )
155
- try:
156
- url += "sitemap.xml"
157
- res = requests.get(url).text
158
- except:
159
- # W.I.P
160
- url += "robots.txt"
161
- res = requests.get(url).text
162
- regex = re.findall(pattern, res)
163
- return list(map(Url._make, regex))
164
-
165
-
166
- from absfuyu.general import ClassBase
167
-
168
-
169
- class SimpleStrEncrypt(ClassBase):
170
- """
171
- Simple Encryption
172
-
173
- Logic:
174
- - Base64
175
- - Shift characters
176
- """
177
-
178
- def __init__(self, times_to_base64_encode: int = 10, shift: int = 13) -> None:
179
- """
180
- :param times_to_base64_encode: How many time to base64 encode
181
- :type times_to_base64_encode: int
182
- :param shift: Shift characters to the right for how many position
183
- :type shift: int
184
- """
185
- self.times_to_base64_encode = times_to_base64_encode
186
- self.shift = shift
187
-
188
- # Support
189
- def _convert_table(self, text: str, shift: int) -> Dict[str, str]:
190
- data = text
191
-
192
- data = deque(sorted(list(set(data))))
193
- translate = data.copy()
194
- translate.rotate(shift)
195
- convert_table = dict(zip(data, translate))
196
-
197
- return convert_table
198
-
199
- @staticmethod
200
- def _use_convert_table(text: str, convert_table: Dict[str, str]) -> str:
201
- """Use convert table"""
202
- data = list(text)
203
- for i, x in enumerate(data):
204
- data[i] = convert_table[x]
205
- return "".join(data)
206
-
207
- @staticmethod
208
- def _b64encode(text: str) -> str:
209
- return base64.b64encode(text.encode()).decode()
210
-
211
- @staticmethod
212
- def _b64decode(text: str) -> str:
213
- return base64.b64decode(text).decode()
214
-
215
- # Main
216
- def encode(self, text: str) -> str:
217
- # Base64
218
- data = text
219
- for _ in range(self.times_to_base64_encode):
220
- data = self._b64encode(data)
221
-
222
- # Shift
223
- convert_table = self._convert_table(data, self.shift)
224
- return self._use_convert_table(data, convert_table)
225
-
226
- def decode(self, text: str) -> str:
227
- # Shift back
228
- data = text
229
- convert_table = self._convert_table(data, -self.shift)
230
- data = self._use_convert_table(data, convert_table)
231
-
232
- # Base64
233
- for _ in range(self.times_to_base64_encode):
234
- data = self._b64decode(data)
235
-
236
- return data
237
-
238
-
239
- # testing
240
- CON_VAR: Final[List[str]] = ["a", "b"] # Declare as final
241
-
242
-
243
- if __name__ == "__main__":
244
- print(get_sitemap("https://kingdomality.com/"))