diff options
| author | Markus Heiser <markus.heiser@darmarit.de> | 2025-08-22 17:17:51 +0200 |
|---|---|---|
| committer | Markus Heiser <markus.heiser@darmarIT.de> | 2025-09-03 13:37:36 +0200 |
| commit | 57b9673efb1b4fd18a3ac15e26da642201e2cd33 (patch) | |
| tree | 79d3ecd365a1669a1109aa7e5dd3636bc1041d96 /searx/settings_defaults.py | |
| parent | 09500459feffa414dc7a0601bdb164464a8b0454 (diff) | |
[mod] addition of various type hints / tbc
- pyright configuration [1]_
- stub files: types-lxml [2]_
- addition of various type hints
- enable use of new type system features on older Python versions [3]_
- ``.tool-versions`` - set python to lowest version we support (3.10.18) [4]_:
Older versions typically lack some typing features found in newer Python
versions. Therefore, for local type checking (before commit), it is necessary
to use the older Python interpreter.
.. [1] https://docs.basedpyright.com/v1.20.0/configuration/config-files/
.. [2] https://pypi.org/project/types-lxml/
.. [3] https://typing-extensions.readthedocs.io/en/latest/#
.. [4] https://mise.jdx.dev/configuration.html#tool-versions
Signed-off-by: Markus Heiser <markus.heiser@darmarit.de>
Format: reST
Diffstat (limited to 'searx/settings_defaults.py')
| -rw-r--r-- | searx/settings_defaults.py | 59 |
1 files changed, 40 insertions, 19 deletions
diff --git a/searx/settings_defaults.py b/searx/settings_defaults.py index 9f8539755..fd7d6d8cc 100644 --- a/searx/settings_defaults.py +++ b/searx/settings_defaults.py @@ -2,8 +2,9 @@ """Implementation of the default settings. """ +from __future__ import annotations -import typing +import typing as t import numbers import errno import os @@ -11,6 +12,7 @@ import logging from base64 import b64decode from os.path import dirname, abspath +from typing_extensions import override from .sxng_locales import sxng_locales searx_dir = abspath(dirname(__file__)) @@ -19,7 +21,7 @@ logger = logging.getLogger('searx') OUTPUT_FORMATS = ['html', 'csv', 'json', 'rss'] SXNG_LOCALE_TAGS = ['all', 'auto'] + list(l[0] for l in sxng_locales) SIMPLE_STYLE = ('auto', 'light', 'dark', 'black') -CATEGORIES_AS_TABS = { +CATEGORIES_AS_TABS: dict[str, dict[str, t.Any]] = { 'general': {}, 'images': {}, 'videos': {}, @@ -41,35 +43,50 @@ STR_TO_BOOL = { } _UNDEFINED = object() +# This type definition for SettingsValue.type_definition is incomplete, but it +# helps to significantly reduce the most common error messages regarding type +# annotations. +TypeDefinition: t.TypeAlias = ( # pylint: disable=invalid-name + tuple[None, bool, type] + | tuple[None, type, type] + | tuple[None, type] + | tuple[bool, type] + | tuple[type, type] + | tuple[type] + | tuple[str | int, ...] +) + +TypeDefinitionArg: t.TypeAlias = type | TypeDefinition # pylint: disable=invalid-name + class SettingsValue: """Check and update a setting value""" def __init__( self, - type_definition: typing.Union[None, typing.Any, typing.Tuple[typing.Any]] = None, - default: typing.Any = None, - environ_name: str = None, + type_definition_arg: TypeDefinitionArg, + default: t.Any = None, + environ_name: str | None = None, ): - self.type_definition = ( - type_definition if type_definition is None or isinstance(type_definition, tuple) else (type_definition,) + self.type_definition: TypeDefinition = ( + type_definition_arg if isinstance(type_definition_arg, tuple) else (type_definition_arg,) ) - self.default = default - self.environ_name = environ_name + self.default: t.Any = default + self.environ_name: str | None = environ_name @property def type_definition_repr(self): - types_str = [t.__name__ if isinstance(t, type) else repr(t) for t in self.type_definition] + types_str = [td.__name__ if isinstance(td, type) else repr(td) for td in self.type_definition] return ', '.join(types_str) - def check_type_definition(self, value: typing.Any) -> None: + def check_type_definition(self, value: t.Any) -> None: if value in self.type_definition: return type_list = tuple(t for t in self.type_definition if isinstance(t, type)) if not isinstance(value, type_list): raise ValueError('The value has to be one of these types/values: {}'.format(self.type_definition_repr)) - def __call__(self, value: typing.Any) -> typing.Any: + def __call__(self, value: t.Any) -> t.Any: if value == _UNDEFINED: value = self.default # override existing value with environ @@ -85,7 +102,8 @@ class SettingsValue: class SettingSublistValue(SettingsValue): """Check the value is a sublist of type definition.""" - def check_type_definition(self, value: typing.Any) -> typing.Any: + @override + def check_type_definition(self, value: list[t.Any]) -> None: if not isinstance(value, list): raise ValueError('The value has to a list') for item in value: @@ -96,12 +114,14 @@ class SettingSublistValue(SettingsValue): class SettingsDirectoryValue(SettingsValue): """Check and update a setting value that is a directory path""" - def check_type_definition(self, value: typing.Any) -> typing.Any: + @override + def check_type_definition(self, value: t.Any) -> t.Any: super().check_type_definition(value) if not os.path.isdir(value): raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), value) - def __call__(self, value: typing.Any) -> typing.Any: + @override + def __call__(self, value: t.Any) -> t.Any: if value == '': value = self.default return super().__call__(value) @@ -110,13 +130,14 @@ class SettingsDirectoryValue(SettingsValue): class SettingsBytesValue(SettingsValue): """str are base64 decoded""" - def __call__(self, value: typing.Any) -> typing.Any: + @override + def __call__(self, value: t.Any) -> t.Any: if isinstance(value, str): value = b64decode(value) return super().__call__(value) -def apply_schema(settings, schema, path_list): +def apply_schema(settings: dict[str, t.Any], schema: dict[str, t.Any], path_list: list[str]): error = False for key, value in schema.items(): if isinstance(value, SettingsValue): @@ -135,7 +156,7 @@ def apply_schema(settings, schema, path_list): return error -SCHEMA = { +SCHEMA: dict[str, t.Any] = { 'general': { 'debug': SettingsValue(bool, False, 'SEARXNG_DEBUG'), 'instance_name': SettingsValue(str, 'SearXNG'), @@ -159,7 +180,7 @@ SCHEMA = { 'autocomplete_min': SettingsValue(int, 4), 'favicon_resolver': SettingsValue(str, ''), 'default_lang': SettingsValue(tuple(SXNG_LOCALE_TAGS + ['']), ''), - 'languages': SettingSublistValue(SXNG_LOCALE_TAGS, SXNG_LOCALE_TAGS), + 'languages': SettingSublistValue(SXNG_LOCALE_TAGS, SXNG_LOCALE_TAGS), # type: ignore 'ban_time_on_fail': SettingsValue(numbers.Real, 5), 'max_ban_time_on_fail': SettingsValue(numbers.Real, 120), 'suspended_times': { |