diff --git a/searx/enginelib/__init__.py b/searx/enginelib/__init__.py index ed33bffd1..009e6f9a2 100644 --- a/searx/enginelib/__init__.py +++ b/searx/enginelib/__init__.py @@ -361,37 +361,43 @@ class Engine(abc.ABC): # pylint: disable=too-few-public-methods https: socks5://proxy:port """ - def setup(self, engine_settings: dict[str, t.Any]) -> bool: # pylint: disable=unused-argument + def setup(self, engine_settings: dict[str, t.Any]) -> bool | None: # pylint: disable=unused-argument """Dynamic setup of the engine settings. With this method, the engine's setup is carried out. For example, to check or dynamically adapt the values handed over in the parameter - ``engine_settings``. The return value (True/False) indicates whether - the setup was successful and the engine can be built or rejected. + ``engine_settings``. - The method is optional and is called synchronously as part of the + Whether the initialization was successful can be indicated by the return + value ``True`` or even ``False``. + + - If no return value (``None`` ) is given from this method , this is + equivalent to ``True``. + + - If an exception is thrown as part of the initialization, this is + equivalent to ``False``. + + The method is optional and is called **synchronously** as part of the initialization of the service and is therefore only suitable for simple - (local) exams/changes at the engine setting. The :py:obj:`Engine.init` - method must be used for longer tasks in which values of a remote must be - determined, for example. + (local) exams/changes at the engine setting. + + The :py:obj:`Engine.init` method must be used for longer tasks in which + values of a remote must be determined, for example. """ return True def init(self, engine_settings: dict[str, t.Any]) -> bool | None: # pylint: disable=unused-argument """Initialization of the engine. - The method is optional and asynchronous (in a thread). It is suitable, - for example, for setting up a cache (for the engine) or for querying - values (required by the engine) from a remote. + The method is optional and called **asynchronous** (in a thread). The + method is comparable to :py:obj:`Engine.setup`, it is suitable, for + caching data that first needs to be requested from a remote. - Whether the initialization was successful can be indicated by the return - value ``True`` or even ``False``. + The method is optional and runs **asynchronously** (in a thread), it is + comparable to :py:obj:`Engine.setup`. For instance, it is suitable for + caching data that first needs to be requested from a remote source. - - If no return value is given from this init method (``None``), this is - equivalent to ``True``. - - - If an exception is thrown as part of the initialization, this is - equivalent to ``False``. + The evaluation of the return value is analogous to :py:obj:`Engine.setup`. """ return True diff --git a/searx/engines/__init__.py b/searx/engines/__init__.py index 4175c9414..355cecd2c 100644 --- a/searx/engines/__init__.py +++ b/searx/engines/__init__.py @@ -269,21 +269,27 @@ def is_engine_active(engine: "Engine | types.ModuleType"): def call_engine_setup(engine: "Engine | types.ModuleType", engine_data: dict[str, t.Any]) -> bool: - setup_ok = False + + setup_ok: bool | None = False setup_func = getattr(engine, "setup", None) if setup_func is None: setup_ok = True elif not callable(setup_func): - logger.error("engine's setup method isn't a callable (is of type: %s)", type(setup_func)) + logger.error(f"engine's setup method isn't a callable (is of type: {type(setup_func)})") else: try: setup_ok = engine.setup(engine_data) except Exception as e: # pylint: disable=broad-except - logger.exception('exception : {0}'.format(e)) + logger.exception(f"(PID {os.getpid()}) {engine.name}: engine SETUP failed, exception: {e}") + setup_ok = False + + # The evaluation of the return value is analogous to Engine.init + if setup_ok is None: + setup_ok = True if not setup_ok: - logger.error("%s: Engine setup was not successful, engine is set to inactive.", engine.name) + logger.error(f"(PID {os.getpid()}) {engine.name}: engine setup was not successful") return setup_ok @@ -311,14 +317,16 @@ def load_engines(engine_list: list[dict[str, t.Any]]): for engine_data in engine_list: if engine_data.get("inactive") is True: continue + engine = load_engine(engine_data) + if engine: register_engine(engine) else: # if an engine can't be loaded (if for example the engine is missing # tor or some other requirements) its set to inactive! logger.error( - f"(PID {os.getpid()}) loading engine %s failed: set engine to inactive!", engine_data.get("name", "???") + f"(PID {os.getpid()}) {engine_data.get('name', '???')}: can't register engine (loading engine failed)" ) engine_data["inactive"] = True return engines diff --git a/searx/search/processors/__init__.py b/searx/search/processors/__init__.py index f7900d284..355e23f9d 100644 --- a/searx/search/processors/__init__.py +++ b/searx/search/processors/__init__.py @@ -16,6 +16,7 @@ __all__ = [ import typing as t +import os from searx import logger from searx import engines @@ -92,7 +93,9 @@ class ProcessorMap(dict[str, EngineProcessor]): self[eng_proc.engine.name] = eng_proc # logger.debug("registered engine processor: %s", eng_proc.engine.name) else: - logger.error("can't register engine processor: %s (init failed)", eng_proc.engine.name) + logger.error( + f"(PID {os.getpid()}) {eng_proc.engine.name}: can't register engines processor (init engine failed)" + ) return eng_proc_ok diff --git a/searx/search/processors/abstract.py b/searx/search/processors/abstract.py index a504cdcba..8c8bc5f85 100644 --- a/searx/search/processors/abstract.py +++ b/searx/search/processors/abstract.py @@ -150,19 +150,26 @@ class EngineProcessor(ABC): threading.Thread(target=__init_processor_thread, daemon=True).start() def init_engine(self) -> bool: + eng_setting = get_engine_from_settings(self.engine.name) init_ok: bool | None = False + try: init_ok = self.engine.init(eng_setting) - except Exception: # pylint: disable=broad-except - logger.exception( - f"(PID {os.getpid()}) Init method of engine %s failed due to an exception.", self.engine.name - ) + except Exception as e: # pylint: disable=broad-except + logger.exception(f"(PID {os.getpid()}) {self.engine.name}: engine INIT failed, exception: {e}") init_ok = False + # In older engines, None is returned from the init method, which is - # equivalent to indicating that the initialization was successful. + # equivalent to indicating that the initialization was successful + # (compare: Engine.setup). + if init_ok is None: init_ok = True + + if not init_ok: + logger.error(f"(PID {os.getpid()}) {self.engine.name}: engine init was not successful") + return init_ok def handle_exception(