[mod] preferences.py: add and use BooleanSetting for checkbox preferences

This commit is contained in:
Bnyro 2023-08-22 15:35:46 +02:00 committed by Markus Heiser
parent e5535ec078
commit 1428385d1c
1 changed files with 52 additions and 57 deletions

View File

@ -9,6 +9,7 @@ from base64 import urlsafe_b64encode, urlsafe_b64decode
from zlib import compress, decompress from zlib import compress, decompress
from urllib.parse import parse_qs, urlencode from urllib.parse import parse_qs, urlencode
from typing import Iterable, Dict, List, Optional from typing import Iterable, Dict, List, Optional
from collections import OrderedDict
import flask import flask
import babel import babel
@ -24,6 +25,18 @@ from searx.engines import DEFAULT_CATEGORY
COOKIE_MAX_AGE = 60 * 60 * 24 * 365 * 5 # 5 years COOKIE_MAX_AGE = 60 * 60 * 24 * 365 * 5 # 5 years
DOI_RESOLVERS = list(settings['doi_resolvers']) DOI_RESOLVERS = list(settings['doi_resolvers'])
MAP_STR2BOOL: Dict[str, bool] = OrderedDict(
[
('0', False),
('1', True),
('on', True),
('off', False),
('True', True),
('False', False),
('none', False),
]
)
class ValidationException(Exception): class ValidationException(Exception):
@ -199,6 +212,26 @@ class MapSetting(Setting):
resp.set_cookie(name, self.key, max_age=COOKIE_MAX_AGE) resp.set_cookie(name, self.key, max_age=COOKIE_MAX_AGE)
class BooleanSetting(Setting):
"""Setting of a boolean value that has to be translated in order to be storable"""
def normalized_str(self, val):
for v_str, v_obj in MAP_STR2BOOL.items():
if val == v_obj:
return v_str
raise ValueError("Invalid value: %s (%s) is not a boolean!" % (repr(val), type(val)))
def parse(self, data: str):
"""Parse and validate ``data`` and store the result at ``self.value``"""
self.value = MAP_STR2BOOL[data]
self.key = self.normalized_str(self.value) # pylint: disable=attribute-defined-outside-init
def save(self, name: str, resp: flask.Response):
"""Save cookie ``name`` in the HTTP response object"""
if hasattr(self, 'key'):
resp.set_cookie(name, self.key, max_age=COOKIE_MAX_AGE)
class BooleanChoices: class BooleanChoices:
"""Maps strings to booleans that are either true or false.""" """Maps strings to booleans that are either true or false."""
@ -375,17 +408,9 @@ class Preferences:
locked=is_locked('autocomplete'), locked=is_locked('autocomplete'),
choices=list(autocomplete.backends.keys()) + [''] choices=list(autocomplete.backends.keys()) + ['']
), ),
'image_proxy': MapSetting( 'image_proxy': BooleanSetting(
settings['server']['image_proxy'], settings['server']['image_proxy'],
locked=is_locked('image_proxy'), locked=is_locked('image_proxy')
map={
'': settings['server']['image_proxy'],
'0': False,
'1': True,
'True': True,
'False': False,
'on': True
}
), ),
'method': EnumStringSetting( 'method': EnumStringSetting(
settings['server']['method'], settings['server']['method'],
@ -406,16 +431,9 @@ class Preferences:
locked=is_locked('theme'), locked=is_locked('theme'),
choices=themes choices=themes
), ),
'results_on_new_tab': MapSetting( 'results_on_new_tab': BooleanSetting(
settings['ui']['results_on_new_tab'], settings['ui']['results_on_new_tab'],
locked=is_locked('results_on_new_tab'), locked=is_locked('results_on_new_tab')
map={
'0': False,
'1': True,
'False': False,
'True': True,
'on': True
}
), ),
'doi_resolver': MultipleChoiceSetting( 'doi_resolver': MultipleChoiceSetting(
[settings['default_doi_resolver'], ], [settings['default_doi_resolver'], ],
@ -427,51 +445,21 @@ class Preferences:
locked=is_locked('simple_style'), locked=is_locked('simple_style'),
choices=['', 'auto', 'light', 'dark'] choices=['', 'auto', 'light', 'dark']
), ),
'center_alignment': MapSetting( 'center_alignment': BooleanSetting(
settings['ui']['center_alignment'], settings['ui']['center_alignment'],
locked=is_locked('center_alignment'), locked=is_locked('center_alignment')
map={
'0': False,
'1': True,
'False': False,
'True': True,
'on': True
}
), ),
'advanced_search': MapSetting( 'advanced_search': BooleanSetting(
settings['ui']['advanced_search'], settings['ui']['advanced_search'],
locked=is_locked('advanced_search'), locked=is_locked('advanced_search')
map={
'0': False,
'1': True,
'False': False,
'True': True,
'on': True,
}
), ),
'query_in_title': MapSetting( 'query_in_title': BooleanSetting(
settings['ui']['query_in_title'], settings['ui']['query_in_title'],
locked=is_locked('query_in_title'), locked=is_locked('query_in_title')
map={
'': settings['ui']['query_in_title'],
'0': False,
'1': True,
'True': True,
'False': False,
'on': True
}
), ),
'infinite_scroll': MapSetting( 'infinite_scroll': BooleanSetting(
settings['ui']['infinite_scroll'], settings['ui']['infinite_scroll'],
locked=is_locked('infinite_scroll'), locked=is_locked('infinite_scroll')
map={
'': settings['ui']['infinite_scroll'],
'0': False,
'1': True,
'True': True,
'False': False,
'on': True
}
), ),
# fmt: on # fmt: on
} }
@ -534,6 +522,13 @@ class Preferences:
disabled_engines = [] disabled_engines = []
enabled_categories = [] enabled_categories = []
disabled_plugins = [] disabled_plugins = []
# boolean preferences are not sent by the form if they're false,
# so we have to add them as false manually if they're not sent (then they would be true)
for key, setting in self.key_value_settings.items():
if key not in input_data.keys() and isinstance(setting, BooleanSetting):
input_data[key] = 'False'
for user_setting_name, user_setting in input_data.items(): for user_setting_name, user_setting in input_data.items():
if user_setting_name in self.key_value_settings: if user_setting_name in self.key_value_settings:
self.key_value_settings[user_setting_name].parse(user_setting) self.key_value_settings[user_setting_name].parse(user_setting)