__main__.py 3.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. # SPDX-License-Identifier: AGPL-3.0-or-later
  2. # lint: pylint
  3. # pylint: disable=missing-module-docstring, missing-function-docstring
  4. import sys
  5. import io
  6. import os
  7. import argparse
  8. import logging
  9. import searx.search
  10. import searx.search.checker
  11. from searx.search import PROCESSORS
  12. from searx.engines import engine_shortcuts
  13. # configure logging
  14. root = logging.getLogger()
  15. handler = logging.StreamHandler(sys.stdout)
  16. for h in root.handlers:
  17. root.removeHandler(h)
  18. root.addHandler(handler)
  19. # color only for a valid terminal
  20. if sys.stdout.isatty() and os.environ.get('TERM') not in ['dumb', 'unknown']:
  21. RESET_SEQ = "\033[0m"
  22. COLOR_SEQ = "\033[1;%dm"
  23. BOLD_SEQ = "\033[1m"
  24. BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = map(lambda i: COLOR_SEQ % (30 + i), range(8))
  25. else:
  26. RESET_SEQ = ""
  27. COLOR_SEQ = ""
  28. BOLD_SEQ = ""
  29. BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = "", "", "", "", "", "", "", ""
  30. # equivalent of 'python -u' (unbuffered stdout, stderr)
  31. stdout = io.TextIOWrapper(open(sys.stdout.fileno(), 'wb', 0), write_through=True)
  32. stderr = io.TextIOWrapper(open(sys.stderr.fileno(), 'wb', 0), write_through=True)
  33. # iterator of processors
  34. def iter_processor(engine_name_list):
  35. if len(engine_name_list) > 0:
  36. for name in engine_name_list:
  37. name = engine_shortcuts.get(name, name)
  38. processor = PROCESSORS.get(name)
  39. if processor is not None:
  40. yield name, processor
  41. else:
  42. stdout.write(f'{BOLD_SEQ}Engine {name:30}{RESET_SEQ}{RED}Engine does not exist{RESET_SEQ}')
  43. else:
  44. for name, processor in searx.search.PROCESSORS.items():
  45. yield name, processor
  46. # actual check & display
  47. def run(engine_name_list, verbose):
  48. searx.search.initialize()
  49. for name, processor in iter_processor(engine_name_list):
  50. stdout.write(f'{BOLD_SEQ}Engine {name:30}{RESET_SEQ}Checking\n')
  51. if not sys.stdout.isatty():
  52. stderr.write(f'{BOLD_SEQ}Engine {name:30}{RESET_SEQ}Checking\n')
  53. checker = searx.search.checker.Checker(processor)
  54. checker.run()
  55. if checker.test_results.succesfull:
  56. stdout.write(f'{BOLD_SEQ}Engine {name:30}{RESET_SEQ}{GREEN}OK{RESET_SEQ}\n')
  57. if verbose:
  58. stdout.write(f' {"found languages":15}: {" ".join(sorted(list(checker.test_results.languages)))}\n')
  59. else:
  60. stdout.write(f'{BOLD_SEQ}Engine {name:30}{RESET_SEQ}{RESET_SEQ}{RED}Error{RESET_SEQ}')
  61. if not verbose:
  62. errors = [test_name + ': ' + error for test_name, error in checker.test_results]
  63. stdout.write(f'{RED}Error {str(errors)}{RESET_SEQ}\n')
  64. else:
  65. stdout.write('\n')
  66. stdout.write(f' {"found languages":15}: {" ".join(sorted(list(checker.test_results.languages)))}\n')
  67. for test_name, logs in checker.test_results.logs.items():
  68. for log in logs:
  69. log = map(lambda l: l if isinstance(l, str) else repr(l), log)
  70. stdout.write(f' {test_name:15}: {RED}{" ".join(log)}{RESET_SEQ}\n')
  71. # call by setup.py
  72. def main():
  73. parser = argparse.ArgumentParser(description='Check searx engines.')
  74. parser.add_argument('engine_name_list', metavar='engine name', type=str, nargs='*',
  75. help='engines name or shortcut list. Empty for all engines.')
  76. parser.add_argument('--verbose', '-v',
  77. action='store_true', dest='verbose',
  78. help='Display details about the test results',
  79. default=False)
  80. args = parser.parse_args()
  81. run(args.engine_name_list, args.verbose)
  82. if __name__ == '__main__':
  83. main()