diff options
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': { |