__main__.py 3.6 KB

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