summaryrefslogtreecommitdiff
path: root/utils/get_setting.py
blob: fa8d9cf8f07d222500dcc081516c43532ce89884 (plain)
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])