124 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			124 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| 
								 | 
							
								# 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
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								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])
							 |