-
Notifications
You must be signed in to change notification settings - Fork 3
/
config.py
142 lines (122 loc) · 4.65 KB
/
config.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
from typing import Any
import fa_paths
import re
class Config_Missing(ValueError):
pass
class Conf_Editor:
def __init__(self) -> None:
self.unsaved = False
self.inContext = False
def load(self):
if self.unsaved:
raise RuntimeError("Unsaved Changes")
if not self.inContext:
raise RuntimeError("Not in context")
section = ""
self.c = (c := {section: ""})
with open(fa_paths.CONFIG, "r", newline="") as fp:
for line in fp:
if m := re.match(r"(?m)^[ \t]*\[([^\r\n\]]+)\]", line):
section = m.group(1)
c[section] = ""
c[section] += line
def get_setting(self, section, setting):
if not self.inContext:
raise RuntimeError("Not in context")
if section not in self.c:
self.c[section] = f"[{section}]\n"
if m := re.search(rf"(?m)^[ \t]*{setting}[ \t]*=(.*)", self.c[section]):
return m.group(1).strip()
if m := re.search(rf"(?m)^[ \t]*;[ \t]*{setting}[ \t]*=(.*)", self.c[section]):
return m.group(1).strip()
raise Config_Missing(f"No {setting} setting found in {section} section.")
def set_setting(self, section, setting, value, force=False):
if not self.inContext:
raise RuntimeError("Not in context")
self.unsaved = True
set_string = f"{setting}={value.strip()}\n"
(self.c[section], n) = re.subn(
rf"(?m)^[ \t]*{setting}[ \t]*=(.*)\r?\n", set_string, self.c[section]
)
if n == 1:
return
if n > 1:
raise ValueError(
f"Duplicate setting [{setting}] found in section [{section}]"
)
(self.c[section], n) = re.subn(
rf"(?m)^[ \t]*;[ \t]*{setting}[ \t]*=(.*)\r?\n",
set_string,
self.c[section],
count=1,
)
if n == 0:
if not force:
raise Config_Missing(
f"Setting [{setting}] not found in section [{section}]"
)
self.c[section] += set_string
def toggle(self, section, setting):
val = self.get_setting(section, setting)
val = "true" if val == "false" else "false"
self.set_setting(section, setting, val)
return 0
def save(self):
if not self.inContext:
raise RuntimeError("Not in context")
with open(fa_paths.CONFIG, "w", newline="") as fp:
for section in self.c.values():
fp.write(section)
self.unsaved = False
def __enter__(self):
if self.inContext:
raise RuntimeError("config is already open")
self.inContext = True
self.load()
def __exit__(self, exc_type, exc_val, exc_tb):
if self.unsaved:
self.save()
self.inContext = False
def __del__(self):
if self.unsaved:
raise RuntimeError("Unsaved Changes")
def __remake_section_names():
from contextlib import redirect_stdout
c = current_conf
print(c.c.keys())
with open("config_autogen.py", "w") as fp:
with redirect_stdout(fp):
print(
f"#file autogenerated by {__name__}.{__remake_section_names.__name__}"
)
print("import config_helper as __ch")
for k, text in c.c.items():
class_name = k.replace("-", "_")
if not class_name:
if m := re.search(r"\bversion=(.*)", text):
print(f"version={int(m.group(1))}")
continue
print(f"class __{class_name}_h1(object):")
for line in text.splitlines():
if m := re.match(r"[ \t]*;?[ \t]*([\w-]+)[ \t]*=", line):
setting = m.group(1)
print(
f" {setting.replace('-','_'):20}=({repr(k)},{repr(setting)})"
)
print(
f"class __{class_name}_h2(__ch.my_awesome_getter_setter,__{class_name}_h1):"
)
print(" pass")
print(f"{class_name}=__{class_name}_h2()")
current_conf = Conf_Editor()
from config_autogen import *
# with current_conf:
# conf_ver=int(current_conf.get_setting("","version"))
# if version < conf_ver:
# print(f"Newer conf.ini version [{conf_ver}] detected. Please inform Factorio-Access maintainers.")
if __name__ == "__main__":
__remake_section_names()
# print(sound.alerts_volume)
# sound.alerts_volume='0.65'
# print(sound.alerts_volume)
# current_conf.save()