get_setting.py 3.6 KB

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