absfuyu 2.8.1__py3-none-any.whl → 3.1.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 +13 -10
- absfuyu/__main__.py +55 -38
- absfuyu/config/config.json +3 -3
- absfuyu/core.py +39 -25
- absfuyu/everything.py +4 -5
- absfuyu/extensions/__init__.py +3 -2
- absfuyu/extensions/dev/__init__.py +162 -19
- absfuyu/extensions/dev/password_hash.py +11 -10
- absfuyu/extensions/dev/passwordlib.py +256 -0
- absfuyu/extensions/dev/pkglib.py +53 -57
- absfuyu/extensions/dev/project_starter.py +58 -0
- absfuyu/extensions/dev/shutdownizer.py +8 -0
- absfuyu/extensions/extra/data_analysis.py +687 -119
- absfuyu/fun/__init__.py +88 -118
- absfuyu/fun/tarot.py +32 -34
- absfuyu/game/tictactoe2.py +90 -78
- absfuyu/{collections → general}/__init__.py +14 -12
- absfuyu/{collections → general}/content.py +105 -87
- absfuyu/{collections → general}/data_extension.py +652 -172
- absfuyu/{collections → general}/generator.py +65 -4
- absfuyu/{collections → general}/human.py +28 -3
- absfuyu/pkg_data/__init__.py +14 -36
- absfuyu/pkg_data/chemistry.pkl +0 -0
- absfuyu/pkg_data/tarot.pkl +0 -0
- absfuyu/tools/converter.py +58 -31
- absfuyu/tools/obfuscator.py +4 -4
- absfuyu/tools/stats.py +4 -4
- absfuyu/tools/web.py +2 -2
- absfuyu/util/lunar.py +144 -123
- absfuyu/util/path.py +22 -3
- absfuyu/util/performance.py +101 -14
- absfuyu/version.py +93 -84
- {absfuyu-2.8.1.dist-info → absfuyu-3.1.0.dist-info}/METADATA +63 -33
- absfuyu-3.1.0.dist-info/RECORD +55 -0
- {absfuyu-2.8.1.dist-info → absfuyu-3.1.0.dist-info}/WHEEL +1 -1
- absfuyu-3.1.0.dist-info/entry_points.txt +2 -0
- absfuyu/pkg_data/chemistry.json +0 -6268
- absfuyu/pkg_data/tarot.json +0 -2593
- absfuyu-2.8.1.dist-info/RECORD +0 -52
- absfuyu-2.8.1.dist-info/entry_points.txt +0 -2
- {absfuyu-2.8.1.dist-info → absfuyu-3.1.0.dist-info}/LICENSE +0 -0
- {absfuyu-2.8.1.dist-info → absfuyu-3.1.0.dist-info}/top_level.txt +0 -0
|
@@ -8,7 +8,6 @@ from typing import Union as __Union
|
|
|
8
8
|
from typing import NewType as __NewType
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
|
|
12
11
|
# Define type
|
|
13
12
|
##############################################################
|
|
14
13
|
Password = __NewType("Password", str)
|
|
@@ -16,7 +15,7 @@ Salt = __NewType("Salt", str)
|
|
|
16
15
|
Key = __NewType("Key", str)
|
|
17
16
|
Salt_V = __NewType("Salt_V", bytes)
|
|
18
17
|
Key_V = __NewType("Key_V", bytes)
|
|
19
|
-
Combo = __Dict[__Union[Salt,Key], __Union[Salt_V,Key_V]]
|
|
18
|
+
Combo = __Dict[__Union[Salt, Key], __Union[Salt_V, Key_V]]
|
|
20
19
|
|
|
21
20
|
|
|
22
21
|
# Function
|
|
@@ -38,10 +37,11 @@ def password_hash(password: Password) -> Combo:
|
|
|
38
37
|
}
|
|
39
38
|
return out
|
|
40
39
|
|
|
40
|
+
|
|
41
41
|
def password_hash_check(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
password: Password,
|
|
43
|
+
combo: Combo,
|
|
44
|
+
) -> bool:
|
|
45
45
|
"""
|
|
46
46
|
Compare hashes between 2 passwords
|
|
47
47
|
"""
|
|
@@ -50,7 +50,7 @@ def password_hash_check(
|
|
|
50
50
|
compare_key = combo["key"]
|
|
51
51
|
else:
|
|
52
52
|
return None
|
|
53
|
-
|
|
53
|
+
|
|
54
54
|
key = __hash.pbkdf2_hmac(
|
|
55
55
|
hash_name="sha256",
|
|
56
56
|
password=password.encode("utf-8"),
|
|
@@ -58,7 +58,7 @@ def password_hash_check(
|
|
|
58
58
|
iterations=100000,
|
|
59
59
|
)
|
|
60
60
|
|
|
61
|
-
if key==compare_key:
|
|
61
|
+
if key == compare_key:
|
|
62
62
|
return True
|
|
63
63
|
else:
|
|
64
64
|
return False
|
|
@@ -66,12 +66,13 @@ def password_hash_check(
|
|
|
66
66
|
|
|
67
67
|
def tj():
|
|
68
68
|
import json
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
|
|
70
|
+
combo = password_hash("lmao")
|
|
71
|
+
for k, v in combo.items():
|
|
71
72
|
combo[k] = str(v)
|
|
72
73
|
j = json.dumps(combo, indent=4)
|
|
73
74
|
return j
|
|
74
75
|
|
|
75
76
|
|
|
76
77
|
if __name__ == "__main__":
|
|
77
|
-
print(tj())
|
|
78
|
+
print(tj())
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Absfuyu: Passwordlib
|
|
3
|
+
--------------------
|
|
4
|
+
Password library
|
|
5
|
+
|
|
6
|
+
Version: 1.0.0dev1
|
|
7
|
+
Date updated: 30/11/2023 (dd/mm/yyyy)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# Library
|
|
12
|
+
###########################################################################
|
|
13
|
+
# from collections import namedtuple
|
|
14
|
+
import hashlib
|
|
15
|
+
import os
|
|
16
|
+
import random
|
|
17
|
+
import re
|
|
18
|
+
from typing import List, Dict, Optional, Union
|
|
19
|
+
|
|
20
|
+
from absfuyu_res import DATA
|
|
21
|
+
|
|
22
|
+
from absfuyu.logger import logger
|
|
23
|
+
from absfuyu.general.data_extension import DictExt, Text
|
|
24
|
+
from absfuyu.general.generator import Generator, Charset
|
|
25
|
+
from absfuyu.util import set_min
|
|
26
|
+
from absfuyu.util.pkl import Pickler
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# Function
|
|
30
|
+
###########################################################################
|
|
31
|
+
def password_check(password: str) -> bool:
|
|
32
|
+
"""
|
|
33
|
+
Verify the strength of ``password``.
|
|
34
|
+
A password is considered strong if:
|
|
35
|
+
|
|
36
|
+
- 8 characters length or more
|
|
37
|
+
- 1 digit or more
|
|
38
|
+
- 1 symbol or more
|
|
39
|
+
- 1 uppercase letter or more
|
|
40
|
+
- 1 lowercase letter or more
|
|
41
|
+
|
|
42
|
+
:param password: Password want to be checked
|
|
43
|
+
:type password: str
|
|
44
|
+
:rtype: bool
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
# calculating the length
|
|
48
|
+
length_error = len(password) < 8
|
|
49
|
+
|
|
50
|
+
# searching for digits
|
|
51
|
+
digit_error = re.search(r"\d", password) is None
|
|
52
|
+
|
|
53
|
+
# searching for uppercase
|
|
54
|
+
uppercase_error = re.search(r"[A-Z]", password) is None
|
|
55
|
+
|
|
56
|
+
# searching for lowercase
|
|
57
|
+
lowercase_error = re.search(r"[a-z]", password) is None
|
|
58
|
+
|
|
59
|
+
# searching for symbols
|
|
60
|
+
symbols = re.compile(r"[ !#$%&'()*+,-./[\\\]^_`{|}~" + r'"]')
|
|
61
|
+
symbol_error = symbols.search(password) is None
|
|
62
|
+
|
|
63
|
+
detail = {
|
|
64
|
+
"length_error": length_error,
|
|
65
|
+
"digit_error": digit_error,
|
|
66
|
+
"uppercase_error": uppercase_error,
|
|
67
|
+
"lowercase_error": lowercase_error,
|
|
68
|
+
"symbol_error": symbol_error,
|
|
69
|
+
}
|
|
70
|
+
logger.debug(f"Password error summary: {detail}")
|
|
71
|
+
|
|
72
|
+
return not any(
|
|
73
|
+
[
|
|
74
|
+
length_error,
|
|
75
|
+
digit_error,
|
|
76
|
+
uppercase_error,
|
|
77
|
+
lowercase_error,
|
|
78
|
+
symbol_error,
|
|
79
|
+
]
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# Class
|
|
84
|
+
###########################################################################
|
|
85
|
+
class Password:
|
|
86
|
+
"""Password"""
|
|
87
|
+
|
|
88
|
+
def __init__(self) -> None:
|
|
89
|
+
"""doc_string"""
|
|
90
|
+
self.password: str = None
|
|
91
|
+
self._words: List[str] = Pickler.load(DATA.PASSWORDLIB)
|
|
92
|
+
|
|
93
|
+
def __str__(self) -> str:
|
|
94
|
+
return f"{self.__class__.__name__}()"
|
|
95
|
+
|
|
96
|
+
def __repr__(self) -> str:
|
|
97
|
+
return self.__str__()
|
|
98
|
+
|
|
99
|
+
def password_hash(self):
|
|
100
|
+
"""
|
|
101
|
+
Generate hash for password
|
|
102
|
+
"""
|
|
103
|
+
salt = os.urandom(32)
|
|
104
|
+
key = hashlib.pbkdf2_hmac(
|
|
105
|
+
hash_name="sha256",
|
|
106
|
+
password=self.password.encode("utf-8"),
|
|
107
|
+
salt=salt,
|
|
108
|
+
iterations=100000,
|
|
109
|
+
)
|
|
110
|
+
out = {
|
|
111
|
+
"salt": salt,
|
|
112
|
+
"key": key,
|
|
113
|
+
}
|
|
114
|
+
return out
|
|
115
|
+
|
|
116
|
+
@staticmethod
|
|
117
|
+
def password_check(password: str):
|
|
118
|
+
data = Text(password).analyze()
|
|
119
|
+
data.__setitem__("length", len(password))
|
|
120
|
+
data = DictExt(data).apply(lambda x: True if x > 0 else False)
|
|
121
|
+
return data
|
|
122
|
+
|
|
123
|
+
@property
|
|
124
|
+
def words(self) -> List[str]:
|
|
125
|
+
"""
|
|
126
|
+
Word list to generate passphrase
|
|
127
|
+
|
|
128
|
+
:rtype: list[str]
|
|
129
|
+
"""
|
|
130
|
+
return self._words
|
|
131
|
+
|
|
132
|
+
# Password generator
|
|
133
|
+
@staticmethod
|
|
134
|
+
def generate_password(
|
|
135
|
+
length: int = 8,
|
|
136
|
+
include_uppercase: bool = True,
|
|
137
|
+
include_number: bool = True,
|
|
138
|
+
include_special: bool = True,
|
|
139
|
+
) -> str:
|
|
140
|
+
r"""
|
|
141
|
+
Generate a random password
|
|
142
|
+
|
|
143
|
+
Parameters
|
|
144
|
+
----------
|
|
145
|
+
length : int
|
|
146
|
+
| Length of the password.
|
|
147
|
+
| Minimum value: ``8``
|
|
148
|
+
| (Default: ``8``)
|
|
149
|
+
|
|
150
|
+
include_uppercase : bool
|
|
151
|
+
Include uppercase character in the password (Default: ``True``)
|
|
152
|
+
|
|
153
|
+
include_number : bool
|
|
154
|
+
Include digit character in the password (Default: ``True``)
|
|
155
|
+
|
|
156
|
+
include_special : bool
|
|
157
|
+
Include special character in the password (Default: ``True``)
|
|
158
|
+
|
|
159
|
+
Returns
|
|
160
|
+
-------
|
|
161
|
+
str
|
|
162
|
+
Generated password
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
Example:
|
|
166
|
+
--------
|
|
167
|
+
>>> Password.generate_password()
|
|
168
|
+
[T&b@mq2
|
|
169
|
+
"""
|
|
170
|
+
charset = Charset.LOWERCASE
|
|
171
|
+
check = 0
|
|
172
|
+
|
|
173
|
+
if include_uppercase:
|
|
174
|
+
charset += Charset.UPPERCASE
|
|
175
|
+
check += 1
|
|
176
|
+
|
|
177
|
+
if include_number:
|
|
178
|
+
charset += Charset.DIGIT
|
|
179
|
+
check += 1
|
|
180
|
+
|
|
181
|
+
if include_special:
|
|
182
|
+
charset += r"[ !#$%&'()*+,-./[\\\]^_`{|}~" + r'"]'
|
|
183
|
+
check += 1
|
|
184
|
+
|
|
185
|
+
while True:
|
|
186
|
+
pwd = Generator.generate_string(
|
|
187
|
+
charset=charset,
|
|
188
|
+
size=set_min(length, min_value=8),
|
|
189
|
+
times=1,
|
|
190
|
+
string_type_if_1=True,
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
analyze = Text(pwd).analyze() # Count each type of char
|
|
194
|
+
|
|
195
|
+
s = sum([1 for x in analyze.values() if x > 0])
|
|
196
|
+
if s > check: # Break loop if each type of char has atleast 1
|
|
197
|
+
break
|
|
198
|
+
return pwd
|
|
199
|
+
|
|
200
|
+
def generate_passphrase(
|
|
201
|
+
self,
|
|
202
|
+
num_of_blocks: int = 5,
|
|
203
|
+
block_divider: Optional[str] = None,
|
|
204
|
+
first_letter_cap: bool = True,
|
|
205
|
+
include_number: bool = True,
|
|
206
|
+
) -> str:
|
|
207
|
+
"""
|
|
208
|
+
Generate a random passphrase
|
|
209
|
+
|
|
210
|
+
Parameters
|
|
211
|
+
----------
|
|
212
|
+
num_of_blocks : int
|
|
213
|
+
Number of word used (Default: ``5``)
|
|
214
|
+
|
|
215
|
+
block_divider : str
|
|
216
|
+
Character symbol that between each word (Default: ``"-"``)
|
|
217
|
+
|
|
218
|
+
first_letter_cap : bool
|
|
219
|
+
Capitalize first character of each word (Default: ``True``)
|
|
220
|
+
|
|
221
|
+
include_number : bool
|
|
222
|
+
Add number to the end of each word (Default: ``True``)
|
|
223
|
+
|
|
224
|
+
Returns
|
|
225
|
+
-------
|
|
226
|
+
str
|
|
227
|
+
Generated passphrase
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
Example:
|
|
231
|
+
--------
|
|
232
|
+
>>> print(Password().generate_passphrase())
|
|
233
|
+
Myomectomies7-Sully4-Torpedomen7-Netful2-Begaud8
|
|
234
|
+
"""
|
|
235
|
+
|
|
236
|
+
def convert_func(value: str):
|
|
237
|
+
if first_letter_cap:
|
|
238
|
+
value = value.title()
|
|
239
|
+
if include_number:
|
|
240
|
+
value += str(random.choice(range(0, 10)))
|
|
241
|
+
return value
|
|
242
|
+
|
|
243
|
+
if not block_divider:
|
|
244
|
+
block_divider = "-"
|
|
245
|
+
|
|
246
|
+
return block_divider.join(
|
|
247
|
+
[convert_func(random.choice(self.words)) for _ in range(num_of_blocks)]
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
# Run
|
|
252
|
+
###########################################################################
|
|
253
|
+
if __name__ == "__main__":
|
|
254
|
+
logger.setLevel(10)
|
|
255
|
+
# print(os.urandom(32))
|
|
256
|
+
print(Password.password_check(Password.generate_password()))
|
absfuyu/extensions/dev/pkglib.py
CHANGED
|
@@ -1,51 +1,74 @@
|
|
|
1
|
-
from
|
|
2
|
-
from typing import Dict, List, Union
|
|
1
|
+
from typing import Dict, List
|
|
3
2
|
|
|
4
3
|
# json
|
|
5
4
|
__all_lib = {
|
|
6
5
|
"native": [
|
|
7
|
-
"os",
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
6
|
+
"os",
|
|
7
|
+
"random",
|
|
8
|
+
"string",
|
|
9
|
+
"subprocess",
|
|
10
|
+
"typing",
|
|
11
|
+
"hashlib",
|
|
12
|
+
"datetime",
|
|
13
|
+
"json",
|
|
14
|
+
"sys",
|
|
15
|
+
"math",
|
|
16
|
+
"base64",
|
|
17
|
+
"codecs",
|
|
18
|
+
"zlib",
|
|
19
|
+
"inspect",
|
|
20
|
+
"functools",
|
|
21
|
+
"tracemalloc",
|
|
22
|
+
"re",
|
|
23
|
+
"collections",
|
|
24
|
+
"urllib",
|
|
25
|
+
"time",
|
|
26
|
+
"pathlib",
|
|
27
|
+
"itertools",
|
|
28
|
+
"argparse",
|
|
29
|
+
"operator",
|
|
30
|
+
"shutil",
|
|
11
31
|
],
|
|
12
32
|
"external": [
|
|
13
|
-
"rich",
|
|
14
|
-
"
|
|
33
|
+
"rich",
|
|
34
|
+
"click",
|
|
35
|
+
"colorama",
|
|
36
|
+
"requests",
|
|
37
|
+
"numpy",
|
|
38
|
+
"pandas",
|
|
39
|
+
"matplotlib",
|
|
40
|
+
"absfuyu_res",
|
|
41
|
+
"importlib_resources",
|
|
15
42
|
],
|
|
16
43
|
"dev-only": [
|
|
17
|
-
"twine",
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"
|
|
23
|
-
],
|
|
24
|
-
"future": [
|
|
25
|
-
"scikit-learn", "opencv-python",
|
|
44
|
+
"twine",
|
|
45
|
+
"black",
|
|
46
|
+
"pytest",
|
|
47
|
+
"tox",
|
|
48
|
+
"build",
|
|
49
|
+
"coverage",
|
|
26
50
|
],
|
|
27
51
|
}
|
|
28
52
|
|
|
29
53
|
LibraryDict = Dict[str, List[str]]
|
|
30
54
|
|
|
55
|
+
|
|
31
56
|
def show_lib_from_json(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
to_json: bool = True
|
|
35
|
-
) -> str:
|
|
57
|
+
lib_dict: LibraryDict, hidden: bool = False, to_json: bool = True
|
|
58
|
+
) -> str:
|
|
36
59
|
"""
|
|
37
60
|
Show libraries
|
|
38
|
-
|
|
61
|
+
|
|
39
62
|
lib_dict: a dict that converted from jso
|
|
40
63
|
hidden: import as __[lib name]
|
|
41
64
|
to_json: save as json format
|
|
42
65
|
"""
|
|
43
66
|
|
|
44
|
-
catergory = [x for x in lib_dict.keys()]
|
|
45
|
-
libs = [x for x in lib_dict.values()]
|
|
67
|
+
catergory = [x for x in lib_dict.keys()] # get keys
|
|
68
|
+
libs = [x for x in lib_dict.values()] # get values
|
|
46
69
|
|
|
47
|
-
lib_import = []
|
|
48
|
-
for lib_list in libs:
|
|
70
|
+
lib_import = [] # New list
|
|
71
|
+
for lib_list in libs: # Take each lib list in a list of lib list
|
|
49
72
|
temp = []
|
|
50
73
|
for item in sorted(list(set(lib_list))):
|
|
51
74
|
if hidden:
|
|
@@ -59,44 +82,17 @@ def show_lib_from_json(
|
|
|
59
82
|
|
|
60
83
|
if to_json:
|
|
61
84
|
import json
|
|
85
|
+
|
|
62
86
|
return str(json.dumps(new_lib, indent=4))
|
|
63
87
|
else:
|
|
64
88
|
out_text = ""
|
|
65
89
|
for idx, val in enumerate(catergory):
|
|
66
90
|
out_text += f"# {val} libs\n"
|
|
67
91
|
for x in lib_import[idx]:
|
|
68
|
-
out_text += x+"\n"
|
|
92
|
+
out_text += x + "\n"
|
|
69
93
|
out_text += "\n"
|
|
70
94
|
return out_text
|
|
71
95
|
|
|
72
96
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
name: Union[str, None] = None,
|
|
76
|
-
description: Union[str, None] = None,
|
|
77
|
-
epilog: Union[str, None] = None,
|
|
78
|
-
*,
|
|
79
|
-
version: str = "",
|
|
80
|
-
add_help: bool = True,
|
|
81
|
-
) -> ArgumentParser:
|
|
82
|
-
arg_parser = ArgumentParser(
|
|
83
|
-
prog=name,
|
|
84
|
-
description=description,
|
|
85
|
-
epilog=epilog,
|
|
86
|
-
add_help=add_help,
|
|
87
|
-
formatter_class=ArgumentDefaultsHelpFormatter,
|
|
88
|
-
# allow_abbrev=False, # Disable long options recognize
|
|
89
|
-
# exit_on_error=True
|
|
90
|
-
)
|
|
91
|
-
arg_parser.add_argument("--version", action="version",
|
|
92
|
-
version=f"%(prog)s {version}")
|
|
93
|
-
_ll_val = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
|
|
94
|
-
arg_parser.add_argument(
|
|
95
|
-
"--log-level",
|
|
96
|
-
metavar="LOG_LEVEL",
|
|
97
|
-
dest="log_level",
|
|
98
|
-
choices=_ll_val,
|
|
99
|
-
default="INFO",
|
|
100
|
-
help=f"Log level: {_ll_val}"
|
|
101
|
-
)
|
|
102
|
-
return arg_parser
|
|
97
|
+
if __name__ == "__main__":
|
|
98
|
+
print(show_lib_from_json(__all_lib, 0, 0))
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Absfuyu: Project starter
|
|
3
|
+
------------------------
|
|
4
|
+
|
|
5
|
+
Version: 1.0.0dev1
|
|
6
|
+
Date updated: 01/12/2023 (dd/mm/yyyy)
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# Module level
|
|
11
|
+
###########################################################################
|
|
12
|
+
__all__ = ["get_parser"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# Library
|
|
16
|
+
###########################################################################
|
|
17
|
+
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
|
|
18
|
+
from typing import Optional
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# Function
|
|
22
|
+
###########################################################################
|
|
23
|
+
def get_parser(
|
|
24
|
+
name: Optional[str] = None,
|
|
25
|
+
description: Optional[str] = None,
|
|
26
|
+
epilog: Optional[str] = None,
|
|
27
|
+
*,
|
|
28
|
+
version: str = "",
|
|
29
|
+
add_help: bool = True,
|
|
30
|
+
) -> ArgumentParser:
|
|
31
|
+
arg_parser = ArgumentParser(
|
|
32
|
+
prog=name,
|
|
33
|
+
description=description,
|
|
34
|
+
epilog=epilog,
|
|
35
|
+
add_help=add_help,
|
|
36
|
+
formatter_class=ArgumentDefaultsHelpFormatter,
|
|
37
|
+
# allow_abbrev=False, # Disable long options recognize
|
|
38
|
+
# exit_on_error=True
|
|
39
|
+
)
|
|
40
|
+
arg_parser.add_argument(
|
|
41
|
+
"--version", action="version", version=f"%(prog)s {version}"
|
|
42
|
+
)
|
|
43
|
+
_ll_val = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
|
|
44
|
+
arg_parser.add_argument(
|
|
45
|
+
"--log-level",
|
|
46
|
+
metavar="LOG_LEVEL",
|
|
47
|
+
dest="log_level",
|
|
48
|
+
choices=_ll_val,
|
|
49
|
+
default="INFO",
|
|
50
|
+
help=f"Log level: {_ll_val}",
|
|
51
|
+
)
|
|
52
|
+
return arg_parser
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# Run
|
|
56
|
+
###########################################################################
|
|
57
|
+
if __name__ == "__main__":
|
|
58
|
+
pass
|