2"""Abstract base classes for engine request processors.
10from abc
import abstractmethod, ABC
11from timeit
import default_timer
13from searx
import settings, logger
16from searx.metrics import histogram_observe, counter_inc, count_exception, count_error
17from searx.exceptions import SearxEngineAccessDeniedException, SearxEngineResponseException
23logger = logger.getChild(
'searx.search.processor')
24SUSPENDED_STATUS: dict[int | str,
'SuspendedStatus'] = {}
28 """Class to handle suspend state."""
30 __slots__ =
'suspend_end_time',
'suspend_reason',
'continuous_errors',
'lock'
33 self.
lock: threading.Lock = threading.Lock()
42 def suspend(self, suspended_time: int, suspend_reason: str):
46 if suspended_time
is None:
48 settings[
'search'][
'max_ban_time_on_fail'],
53 logger.debug(
'Suspend for %i seconds', suspended_time)
64 """Base classes used for all types of request processors."""
66 __slots__ =
'engine',
'engine_name',
'suspended_status',
'logger'
68 def __init__(self, engine:
"Engine|ModuleType", engine_name: str):
71 self.
logger: logging.Logger = engines[engine_name].logger
79 except SearxEngineResponseException
as exc:
80 self.
logger.warning(
'Fail to initialize // %s', exc)
82 self.
logger.exception(
'Fail to initialize')
84 self.
logger.debug(
'Initialized')
88 return hasattr(self.
engine,
'init')
92 if isinstance(exception_or_message, BaseException):
93 exception_class = exception_or_message.__class__
94 module_name = getattr(exception_class,
'__module__',
'builtins')
95 module_name =
'' if module_name ==
'builtins' else module_name +
'.'
96 error_message = module_name + exception_class.__qualname__
98 error_message = exception_or_message
99 result_container.add_unresponsive_engine(self.
engine_name, error_message)
101 counter_inc(
'engine', self.
engine_name,
'search',
'count',
'error')
102 if isinstance(exception_or_message, BaseException):
103 count_exception(self.
engine_name, exception_or_message)
105 count_error(self.
engine_name, exception_or_message)
108 suspended_time =
None
109 if isinstance(exception_or_message, SearxEngineAccessDeniedException):
110 suspended_time = exception_or_message.suspended_time
115 result_container.extend(self.
engine_name, search_results)
116 engine_time = default_timer() - start_time
117 page_load_time = get_time_for_thread()
118 result_container.add_timing(self.
engine_name, engine_time, page_load_time)
120 counter_inc(
'engine', self.
engine_name,
'search',
'count',
'successful')
121 histogram_observe(engine_time,
'engine', self.
engine_name,
'time',
'total')
122 if page_load_time
is not None:
123 histogram_observe(page_load_time,
'engine', self.
engine_name,
'time',
'http')
126 if getattr(threading.current_thread(),
'_timeout',
False):
131 if search_results
is not None:
137 result_container.add_unresponsive_engine(
143 def get_params(self, search_query, engine_category) -> dict[str, t.Any]:
144 """Returns a set of (see :ref:`request params <engine request arguments>`) or
145 ``None`` if request is not supported.
147 Not supported conditions (``None`` is returned):
149 - A page-number > 1 when engine does not support paging.
150 - A time range when the engine does not support time range.
153 if search_query.pageno > 1
and not self.
engine.paging:
157 max_page = self.
engine.max_page
or settings[
'search'][
'max_page']
158 if max_page
and max_page < search_query.pageno:
162 if search_query.time_range
and not self.
engine.time_range_support:
166 params[
"query"] = search_query.query
167 params[
'category'] = engine_category
168 params[
'pageno'] = search_query.pageno
169 params[
'safesearch'] = search_query.safesearch
170 params[
'time_range'] = search_query.time_range
171 params[
'engine_data'] = search_query.engine_data.get(self.
engine_name, {})
172 params[
'searxng_locale'] = search_query.lang
181 if hasattr(self.
engine,
'language')
and self.
engine.language:
182 params[
'language'] = self.
engine.language
184 params[
'language'] = search_query.lang
189 def search(self, query, params, result_container, start_time, timeout_limit):
193 tests = getattr(self.engine,
'tests',
None)
195 tests = getattr(self.engine,
'additional_tests', {})
196 tests.update(self.get_default_tests())
__init__(self, "Engine|ModuleType" engine, str engine_name)
handle_exception(self, result_container, exception_or_message, suspend=False)
dict[str, t.Any] get_params(self, search_query, engine_category)
extend_container_if_suspended(self, result_container)
has_initialize_function(self)
_extend_container_basic(self, result_container, start_time, search_results)
extend_container(self, result_container, start_time, search_results)
SuspendedStatus suspended_status
suspend(self, int suspended_time, str suspend_reason)