get_setting.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. # SPDX-License-Identifier: AGPL-3.0-or-later
  2. """build environment used by shell scripts
  3. """
  4. # set path
  5. import sys
  6. import importlib.util
  7. import re
  8. from pathlib import Path
  9. repo_root = Path(__file__).resolve().parent.parent
  10. # If you add or remove variables here, do not forget to update:
  11. # - ./docs/admin/engines/settings.rst
  12. # - ./docs/dev/makefile.rst (section make buildenv)
  13. name_val = [
  14. ("SEARXNG_URL", "server.base_url"),
  15. ("SEARXNG_PORT", "server.port"),
  16. ("SEARXNG_BIND_ADDRESS", "server.bind_address"),
  17. ]
  18. def main(setting_name):
  19. settings_path = repo_root / "searx" / "settings.yml"
  20. with open(settings_path) as f:
  21. settings = parse_yaml(f.read())
  22. print(get_setting_value(settings, setting_name))
  23. def get_setting_value(settings, name):
  24. value = settings
  25. for a in name.split("."):
  26. value = value[a]
  27. if value is True:
  28. value = "1"
  29. elif value is False:
  30. value = ""
  31. return value
  32. def parse_yaml(yaml_str):
  33. """A simple YAML parser that converts a YAML string to a Python dictionary.
  34. This parser can handle nested dictionaries, but does not handle list or JSON
  35. like structures.
  36. Good enough parser to get the values of server.base_url, server.port and
  37. server.bind_address
  38. """
  39. def get_type_and_value_without_comment(line):
  40. """Extract value without comment and quote
  41. Returns a tuple:
  42. 1. str or None: str when the value is written inside quote, None otherwise
  43. 2. the value without quote if any
  44. """
  45. match = re.search(r"\"(.*)\"(\s+#)?|\'(.*)\'(\s+#)?|([^#]*)(\s+#)?", line)
  46. if match:
  47. g = match.groups()
  48. if g[0] is not None:
  49. return str, g[0]
  50. elif g[2] is not None:
  51. return str, g[2]
  52. elif g[4] is not None:
  53. return None, g[4].strip()
  54. return None, line.strip()
  55. # fmt: off
  56. true_values = ("y", "Y", "yes", "Yes", "YES", "true", "True", "TRUE", "on", "On", "ON",)
  57. false_values = ("n", "N", "no", "No", "NO", "false", "False", "FALSE", "off", "Off", "OFF",)
  58. # fmt: on
  59. def process_line(line):
  60. """Extract key and value from a line, considering its indentation."""
  61. if ": " in line:
  62. key, value = line.split(": ", 1)
  63. key = key.strip()
  64. value_type, value = get_type_and_value_without_comment(value)
  65. if value in true_values and value_type is None:
  66. value = True
  67. elif value in false_values and value_type is None:
  68. value = False
  69. elif value.replace(".", "").isdigit() and value_type is None:
  70. for t in (int, float):
  71. try:
  72. value = t(value)
  73. break
  74. except ValueError:
  75. continue
  76. return key, value
  77. return None, None
  78. def get_indentation_level(line):
  79. """Determine the indentation level of a line."""
  80. return len(line) - len(line.lstrip())
  81. yaml_dict = {}
  82. lines = yaml_str.split("\n")
  83. stack = [yaml_dict]
  84. for line in lines:
  85. if not line.strip():
  86. continue # Skip empty lines
  87. indentation_level = get_indentation_level(line)
  88. # Assuming 2 spaces per indentation level
  89. # see .yamllint.yml
  90. current_level = indentation_level // 2
  91. # Adjust the stack based on the current indentation level
  92. while len(stack) > current_level + 1:
  93. stack.pop()
  94. if line.endswith(":"):
  95. key = line[0:-1].strip()
  96. new_dict = {}
  97. stack[-1][key] = new_dict
  98. stack.append(new_dict)
  99. else:
  100. key, value = process_line(line)
  101. if key is not None:
  102. stack[-1][key] = value
  103. return yaml_dict
  104. if __name__ == "__main__":
  105. main(sys.argv[1])