2"""Implementation of the default settings.
5from __future__
import annotations
12from base64
import b64decode
13from os.path
import dirname, abspath
15from typing_extensions
import override
16from .sxng_locales
import sxng_locales
18searx_dir = abspath(dirname(__file__))
20logger = logging.getLogger(
'searx')
21OUTPUT_FORMATS = [
'html',
'csv',
'json',
'rss']
22SXNG_LOCALE_TAGS = [
'all',
'auto'] + list(l[0]
for l
in sxng_locales)
23SIMPLE_STYLE = (
'auto',
'light',
'dark',
'black')
24CATEGORIES_AS_TABS: dict[str, dict[str, t.Any]] = {
49TypeDefinition: t.TypeAlias = (
50 tuple[
None, bool, type]
51 | tuple[
None, type, type]
56 | tuple[str | int, ...]
59TypeDefinitionArg: t.TypeAlias = type | TypeDefinition
63 """Check and update a setting value"""
67 type_definition_arg: TypeDefinitionArg,
68 default: t.Any =
None,
69 environ_name: str |
None =
None,
72 type_definition_arg
if isinstance(type_definition_arg, tuple)
else (type_definition_arg,)
79 types_str = [td.__name__
if isinstance(td, type)
else repr(td)
for td
in self.
type_definition]
80 return ', '.join(types_str)
85 type_list = tuple(t
for t
in self.
type_definition if isinstance(t, type))
86 if not isinstance(value, type_list):
90 if value == _UNDEFINED:
96 value = STR_TO_BOOL[value.lower()]
103 """Check the value is a sublist of type definition."""
107 if not isinstance(value, list):
108 raise ValueError(
'The value has to a list')
115 """Check and update a setting value that is a directory path"""
120 if not os.path.isdir(value):
121 raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), value)
131 """str are base64 decoded"""
135 if isinstance(value, str):
136 value = b64decode(value)
140def apply_schema(settings: dict[str, t.Any], schema: dict[str, t.Any], path_list: list[str]):
142 for key, value
in schema.items():
143 if isinstance(value, SettingsValue):
145 settings[key] = value(settings.get(key, _UNDEFINED))
146 except Exception
as e:
148 logger.error(
'%s: %s',
'.'.join([*path_list, key]), e)
150 elif isinstance(value, dict):
151 error = error
or apply_schema(settings.setdefault(key, {}), schema[key], [*path_list, key])
153 settings.setdefault(key, value)
154 if len(path_list) == 0
and error:
155 raise ValueError(
'Invalid settings.yml')
159SCHEMA: dict[str, t.Any] = {
163 'privacypolicy_url':
SettingsValue((
None,
False, str),
None),
165 'donation_url':
SettingsValue((bool, str),
"https://docs.searxng.org/donate.html"),
170 'issue_url':
SettingsValue(str,
'https://github.com/searxng/searxng/issues'),
171 'new_issue_url':
SettingsValue(str,
'https://github.com/searxng/searxng/issues/new'),
173 'public_instances':
SettingsValue((
False, str),
'https://searx.space'),
174 'wiki_url':
SettingsValue((
False, str),
'https://github.com/searxng/searxng/wiki'),
182 'default_lang':
SettingsValue(tuple(SXNG_LOCALE_TAGS + [
'']),
''),
187 'SearxEngineAccessDenied':
SettingsValue(numbers.Real, 86400),
189 'SearxEngineTooManyRequests':
SettingsValue(numbers.Real, 3600),
190 'cf_SearxEngineCaptcha':
SettingsValue(numbers.Real, 1296000),
191 'cf_SearxEngineAccessDenied':
SettingsValue(numbers.Real, 86400),
192 'recaptcha_SearxEngineCaptcha':
SettingsValue(numbers.Real, 604800),
199 'bind_address':
SettingsValue(str,
'127.0.0.1',
'SEARXNG_BIND_ADDRESS'),
201 'public_instance':
SettingsValue(bool,
False,
'SEARXNG_PUBLIC_INSTANCE'),
202 'secret_key':
SettingsValue(str, environ_name=
'SEARXNG_SECRET'),
203 'base_url':
SettingsValue((
False, str),
False,
'SEARXNG_BASE_URL'),
204 'image_proxy':
SettingsValue(bool,
False,
'SEARXNG_IMAGE_PROXY'),
205 'http_protocol_version':
SettingsValue((
'1.0',
'1.1'),
'1.0'),
206 'method':
SettingsValue((
'POST',
'GET'),
'POST',
'SEARXNG_METHOD'),
211 'url':
SettingsValue((
None,
False, str),
False,
'SEARXNG_REDIS_URL'),
214 'url':
SettingsValue((
None,
False, str),
False,
'SEARXNG_VALKEY_URL'),
229 'cache_url':
SettingsValue(str,
'https://web.archive.org/web/'),
232 'url_formatting':
SettingsValue((
'pretty',
'full',
'host'),
'pretty'),
242 'max_request_timeout':
SettingsValue((
None, numbers.Real),
None),
262 'categories_as_tabs':
SettingsValue(dict, CATEGORIES_AS_TABS),
None check_type_definition(self, list[t.Any] value)
t.Any __call__(self, t.Any value)
t.Any check_type_definition(self, t.Any value)
t.Any __call__(self, t.Any value)
None check_type_definition(self, t.Any value)
t.Any __call__(self, t.Any value)
__init__(self, TypeDefinitionArg type_definition_arg, t.Any default=None, str|None environ_name=None)
apply_schema(dict[str, t.Any] settings, dict[str, t.Any] schema, list[str] path_list)