Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
elebumm
GitHub Repository: elebumm/RedditVideoMakerBot
Path: blob/master/utils/settings.py
327 views
1
import re
2
from pathlib import Path
3
from typing import Dict, Tuple
4
5
import toml
6
from rich.console import Console
7
8
from utils.console import handle_input
9
10
console = Console()
11
config = dict # autocomplete
12
13
14
def crawl(obj: dict, func=lambda x, y: print(x, y, end="\n"), path=None):
15
if path is None: # path Default argument value is mutable
16
path = []
17
for key in obj.keys():
18
if type(obj[key]) is dict:
19
crawl(obj[key], func, path + [key])
20
continue
21
func(path + [key], obj[key])
22
23
24
def check(value, checks, name):
25
def get_check_value(key, default_result):
26
return checks[key] if key in checks else default_result
27
28
incorrect = False
29
if value == {}:
30
incorrect = True
31
if not incorrect and "type" in checks:
32
try:
33
value = eval(checks["type"])(value)
34
except:
35
incorrect = True
36
37
if (
38
not incorrect and "options" in checks and value not in checks["options"]
39
): # FAILSTATE Value is not one of the options
40
incorrect = True
41
if (
42
not incorrect
43
and "regex" in checks
44
and (
45
(isinstance(value, str) and re.match(checks["regex"], value) is None)
46
or not isinstance(value, str)
47
)
48
): # FAILSTATE Value doesn't match regex, or has regex but is not a string.
49
incorrect = True
50
51
if (
52
not incorrect
53
and not hasattr(value, "__iter__")
54
and (
55
("nmin" in checks and checks["nmin"] is not None and value < checks["nmin"])
56
or ("nmax" in checks and checks["nmax"] is not None and value > checks["nmax"])
57
)
58
):
59
incorrect = True
60
if (
61
not incorrect
62
and hasattr(value, "__iter__")
63
and (
64
("nmin" in checks and checks["nmin"] is not None and len(value) < checks["nmin"])
65
or ("nmax" in checks and checks["nmax"] is not None and len(value) > checks["nmax"])
66
)
67
):
68
incorrect = True
69
70
if incorrect:
71
value = handle_input(
72
message=(
73
(("[blue]Example: " + str(checks["example"]) + "\n") if "example" in checks else "")
74
+ "[red]"
75
+ ("Non-optional ", "Optional ")["optional" in checks and checks["optional"] is True]
76
)
77
+ "[#C0CAF5 bold]"
78
+ str(name)
79
+ "[#F7768E bold]=",
80
extra_info=get_check_value("explanation", ""),
81
check_type=eval(get_check_value("type", "False")),
82
default=get_check_value("default", NotImplemented),
83
match=get_check_value("regex", ""),
84
err_message=get_check_value("input_error", "Incorrect input"),
85
nmin=get_check_value("nmin", None),
86
nmax=get_check_value("nmax", None),
87
oob_error=get_check_value(
88
"oob_error", "Input out of bounds(Value too high/low/long/short)"
89
),
90
options=get_check_value("options", None),
91
optional=get_check_value("optional", False),
92
)
93
return value
94
95
96
def crawl_and_check(obj: dict, path: list, checks: dict = {}, name=""):
97
if len(path) == 0:
98
return check(obj, checks, name)
99
if path[0] not in obj.keys():
100
obj[path[0]] = {}
101
obj[path[0]] = crawl_and_check(obj[path[0]], path[1:], checks, path[0])
102
return obj
103
104
105
def check_vars(path, checks):
106
global config
107
crawl_and_check(config, path, checks)
108
109
110
def check_toml(template_file, config_file) -> Tuple[bool, Dict]:
111
global config
112
config = None
113
try:
114
template = toml.load(template_file)
115
except Exception as error:
116
console.print(f"[red bold]Encountered error when trying to to load {template_file}: {error}")
117
return False
118
try:
119
config = toml.load(config_file)
120
except toml.TomlDecodeError:
121
console.print(
122
f"""[blue]Couldn't read {config_file}.
123
Overwrite it?(y/n)"""
124
)
125
if not input().startswith("y"):
126
print("Unable to read config, and not allowed to overwrite it. Giving up.")
127
return False
128
else:
129
try:
130
with open(config_file, "w") as f:
131
f.write("")
132
except:
133
console.print(
134
f"[red bold]Failed to overwrite {config_file}. Giving up.\nSuggestion: check {config_file} permissions for the user."
135
)
136
return False
137
except FileNotFoundError:
138
console.print(
139
f"""[blue]Couldn't find {config_file}
140
Creating it now."""
141
)
142
try:
143
with open(config_file, "x") as f:
144
f.write("")
145
config = {}
146
except:
147
console.print(
148
f"[red bold]Failed to write to {config_file}. Giving up.\nSuggestion: check the folder's permissions for the user."
149
)
150
return False
151
152
console.print(
153
"""\
154
[blue bold]###############################
155
# #
156
# Checking TOML configuration #
157
# #
158
###############################
159
If you see any prompts, that means that you have unset/incorrectly set variables, please input the correct values.\
160
"""
161
)
162
crawl(template, check_vars)
163
with open(config_file, "w") as f:
164
toml.dump(config, f)
165
return config
166
167
168
if __name__ == "__main__":
169
directory = Path().absolute()
170
check_toml(f"{directory}/utils/.config.template.toml", "config.toml")
171
172