summaryrefslogtreecommitdiff
path: root/searx/settings_defaults.py
diff options
context:
space:
mode:
Diffstat (limited to 'searx/settings_defaults.py')
-rw-r--r--searx/settings_defaults.py59
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': {