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
|
# SPDX-License-Identifier: AGPL-3.0-or-later
"""build environment used by shell scripts
"""
# set path
import sys
import importlib.util
import re
from pathlib import Path
repo_root = Path(__file__).resolve().parent.parent
# If you add or remove variables here, do not forget to update:
# - ./docs/admin/engines/settings.rst
# - ./docs/dev/makefile.rst (section make buildenv)
name_val = [
("SEARXNG_URL", "server.base_url"),
("SEARXNG_PORT", "server.port"),
("SEARXNG_BIND_ADDRESS", "server.bind_address"),
]
def main(setting_name):
settings_path = repo_root / "searx" / "settings.yml"
with open(settings_path) as f:
settings = parse_yaml(f.read())
print(get_setting_value(settings, setting_name))
def get_setting_value(settings, name):
value = settings
for a in name.split("."):
value = value[a]
if value is True:
value = "1"
elif value is False:
value = ""
return value
def parse_yaml(yaml_str):
"""A simple YAML parser that converts a YAML string to a Python dictionary.
This parser can handle nested dictionaries, but does not handle list or JSON
like structures.
Good enough parser to get the values of server.base_url, server.port and
server.bind_address
"""
def get_type_and_value_without_comment(line):
"""Extract value without comment and quote
Returns a tuple:
1. str or None: str when the value is written inside quote, None otherwise
2. the value without quote if any
"""
match = re.search(r"\"(.*)\"(\s+#)?|\'(.*)\'(\s+#)?|([^#]*)(\s+#)?", line)
if match:
g = match.groups()
if g[0] is not None:
return str, g[0]
elif g[2] is not None:
return str, g[2]
elif g[4] is not None:
return None, g[4].strip()
return None, line.strip()
# fmt: off
true_values = ("y", "Y", "yes", "Yes", "YES", "true", "True", "TRUE", "on", "On", "ON",)
false_values = ("n", "N", "no", "No", "NO", "false", "False", "FALSE", "off", "Off", "OFF",)
# fmt: on
def process_line(line):
"""Extract key and value from a line, considering its indentation."""
if ": " in line:
key, value = line.split(": ", 1)
key = key.strip()
value_type, value = get_type_and_value_without_comment(value)
if value in true_values and value_type is None:
value = True
elif value in false_values and value_type is None:
value = False
elif value.replace(".", "").isdigit() and value_type is None:
for t in (int, float):
try:
value = t(value)
break
except ValueError:
continue
return key, value
return None, None
def get_indentation_level(line):
"""Determine the indentation level of a line."""
return len(line) - len(line.lstrip())
yaml_dict = {}
lines = yaml_str.split("\n")
stack = [yaml_dict]
for line in lines:
if not line.strip():
continue # Skip empty lines
indentation_level = get_indentation_level(line)
# Assuming 2 spaces per indentation level
# see .yamllint.yml
current_level = indentation_level // 2
# Adjust the stack based on the current indentation level
while len(stack) > current_level + 1:
stack.pop()
if line.endswith(":"):
key = line[0:-1].strip()
new_dict = {}
stack[-1][key] = new_dict
stack.append(new_dict)
else:
key, value = process_line(line)
if key is not None:
stack[-1][key] = value
return yaml_dict
if __name__ == "__main__":
main(sys.argv[1])
|