__main__.py 4.0 KB

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