mirror of
https://github.com/searxng/searxng.git
synced 2025-09-06 18:28:32 +02:00
[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
This commit is contained in:
parent
09500459fe
commit
57b9673efb
107 changed files with 1205 additions and 1251 deletions
|
@ -5,14 +5,17 @@ from __future__ import annotations
|
|||
|
||||
# pylint: disable=useless-object-inheritance
|
||||
|
||||
import typing as t
|
||||
|
||||
from base64 import urlsafe_b64encode, urlsafe_b64decode
|
||||
from zlib import compress, decompress
|
||||
from urllib.parse import parse_qs, urlencode
|
||||
from typing import Iterable, Dict, List, Optional
|
||||
from collections import OrderedDict
|
||||
from collections.abc import Iterable
|
||||
|
||||
import flask
|
||||
import babel
|
||||
import babel.core
|
||||
|
||||
import searx.plugins
|
||||
|
||||
|
@ -27,7 +30,7 @@ from searx.webutils import VALID_LANGUAGE_CODE
|
|||
COOKIE_MAX_AGE = 60 * 60 * 24 * 365 * 5 # 5 years
|
||||
DOI_RESOLVERS = list(settings['doi_resolvers'])
|
||||
|
||||
MAP_STR2BOOL: Dict[str, bool] = OrderedDict(
|
||||
MAP_STR2BOOL: dict[str, bool] = OrderedDict(
|
||||
[
|
||||
('0', False),
|
||||
('1', True),
|
||||
|
@ -47,10 +50,10 @@ class ValidationException(Exception):
|
|||
class Setting:
|
||||
"""Base class of user settings"""
|
||||
|
||||
def __init__(self, default_value, locked: bool = False):
|
||||
def __init__(self, default_value: t.Any, locked: bool = False):
|
||||
super().__init__()
|
||||
self.value = default_value
|
||||
self.locked = locked
|
||||
self.value: t.Any = default_value
|
||||
self.locked: bool = locked
|
||||
|
||||
def parse(self, data: str):
|
||||
"""Parse ``data`` and store the result at ``self.value``
|
||||
|
@ -80,9 +83,11 @@ class StringSetting(Setting):
|
|||
class EnumStringSetting(Setting):
|
||||
"""Setting of a value which can only come from the given choices"""
|
||||
|
||||
def __init__(self, default_value: str, choices: Iterable[str], locked=False):
|
||||
value: str
|
||||
|
||||
def __init__(self, default_value: str, choices: Iterable[str], locked: bool = False):
|
||||
super().__init__(default_value, locked)
|
||||
self.choices = choices
|
||||
self.choices: Iterable[str] = choices
|
||||
self._validate_selection(self.value)
|
||||
|
||||
def _validate_selection(self, selection: str):
|
||||
|
@ -98,12 +103,12 @@ class EnumStringSetting(Setting):
|
|||
class MultipleChoiceSetting(Setting):
|
||||
"""Setting of values which can only come from the given choices"""
|
||||
|
||||
def __init__(self, default_value: List[str], choices: Iterable[str], locked=False):
|
||||
def __init__(self, default_value: list[str], choices: Iterable[str], locked: bool = False):
|
||||
super().__init__(default_value, locked)
|
||||
self.choices = choices
|
||||
self.choices: Iterable[str] = choices
|
||||
self._validate_selections(self.value)
|
||||
|
||||
def _validate_selections(self, selections: List[str]):
|
||||
def _validate_selections(self, selections: list[str]):
|
||||
for item in selections:
|
||||
if item not in self.choices:
|
||||
raise ValidationException('Invalid value: "{0}"'.format(selections))
|
||||
|
@ -111,14 +116,14 @@ class MultipleChoiceSetting(Setting):
|
|||
def parse(self, data: str):
|
||||
"""Parse and validate ``data`` and store the result at ``self.value``"""
|
||||
if data == '':
|
||||
self.value = []
|
||||
self.value: list[str] = []
|
||||
return
|
||||
|
||||
elements = data.split(',')
|
||||
self._validate_selections(elements)
|
||||
self.value = elements
|
||||
|
||||
def parse_form(self, data: List[str]):
|
||||
def parse_form(self, data: list[str]):
|
||||
if self.locked:
|
||||
return
|
||||
|
||||
|
@ -135,9 +140,9 @@ class MultipleChoiceSetting(Setting):
|
|||
class SetSetting(Setting):
|
||||
"""Setting of values of type ``set`` (comma separated string)"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.values = set()
|
||||
def __init__(self, *args, **kwargs): # type: ignore
|
||||
super().__init__(*args, **kwargs) # type: ignore
|
||||
self.values: set[str] = set()
|
||||
|
||||
def get_value(self):
|
||||
"""Returns a string with comma separated values."""
|
||||
|
@ -168,7 +173,9 @@ class SetSetting(Setting):
|
|||
class SearchLanguageSetting(EnumStringSetting):
|
||||
"""Available choices may change, so user's value may not be in choices anymore"""
|
||||
|
||||
def _validate_selection(self, selection):
|
||||
value: str
|
||||
|
||||
def _validate_selection(self, selection: str):
|
||||
if selection != '' and selection != 'auto' and not VALID_LANGUAGE_CODE.match(selection):
|
||||
raise ValidationException('Invalid language code: "{0}"'.format(selection))
|
||||
|
||||
|
@ -192,9 +199,14 @@ class SearchLanguageSetting(EnumStringSetting):
|
|||
class MapSetting(Setting):
|
||||
"""Setting of a value that has to be translated in order to be storable"""
|
||||
|
||||
def __init__(self, default_value, map: Dict[str, object], locked=False): # pylint: disable=redefined-builtin
|
||||
key: str
|
||||
value: object
|
||||
|
||||
def __init__(
|
||||
self, default_value: object, map: dict[str, object], locked: bool = False
|
||||
): # pylint: disable=redefined-builtin
|
||||
super().__init__(default_value, locked)
|
||||
self.map = map
|
||||
self.map: dict[str, object] = map
|
||||
|
||||
if self.value not in self.map.values():
|
||||
raise ValidationException('Invalid default value')
|
||||
|
@ -216,7 +228,10 @@ class MapSetting(Setting):
|
|||
class BooleanSetting(Setting):
|
||||
"""Setting of a boolean value that has to be translated in order to be storable"""
|
||||
|
||||
def normalized_str(self, val):
|
||||
value: bool
|
||||
key: str
|
||||
|
||||
def normalized_str(self, val: t.Any) -> str:
|
||||
for v_str, v_obj in MAP_STR2BOOL.items():
|
||||
if val == v_obj:
|
||||
return v_str
|
||||
|
@ -236,11 +251,11 @@ class BooleanSetting(Setting):
|
|||
class BooleanChoices:
|
||||
"""Maps strings to booleans that are either true or false."""
|
||||
|
||||
def __init__(self, name: str, choices: Dict[str, bool], locked: bool = False):
|
||||
self.name = name
|
||||
self.choices = choices
|
||||
self.locked = locked
|
||||
self.default_choices = dict(choices)
|
||||
def __init__(self, name: str, choices: dict[str, bool], locked: bool = False):
|
||||
self.name: str = name
|
||||
self.choices: dict[str, bool] = choices
|
||||
self.locked: bool = locked
|
||||
self.default_choices: dict[str, bool] = dict(choices)
|
||||
|
||||
def transform_form_items(self, items):
|
||||
return items
|
||||
|
@ -257,7 +272,7 @@ class BooleanChoices:
|
|||
if enabled in self.choices:
|
||||
self.choices[enabled] = True
|
||||
|
||||
def parse_form(self, items: List[str]):
|
||||
def parse_form(self, items: list[str]):
|
||||
if self.locked:
|
||||
return
|
||||
|
||||
|
@ -327,10 +342,10 @@ class ClientPref:
|
|||
|
||||
# hint: searx.webapp.get_client_settings should be moved into this class
|
||||
|
||||
locale: babel.Locale
|
||||
locale: babel.Locale | None
|
||||
"""Locale preferred by the client."""
|
||||
|
||||
def __init__(self, locale: Optional[babel.Locale] = None):
|
||||
def __init__(self, locale: babel.Locale | None = None):
|
||||
self.locale = locale
|
||||
|
||||
@property
|
||||
|
@ -354,7 +369,7 @@ class ClientPref:
|
|||
if not al_header:
|
||||
return cls(locale=None)
|
||||
|
||||
pairs = []
|
||||
pairs: list[tuple[babel.Locale, float]] = []
|
||||
for l in al_header.split(','):
|
||||
# fmt: off
|
||||
lang, qvalue = [_.strip() for _ in (l.split(';') + ['q=1',])[:2]]
|
||||
|
@ -387,7 +402,7 @@ class Preferences:
|
|||
|
||||
super().__init__()
|
||||
|
||||
self.key_value_settings: Dict[str, Setting] = {
|
||||
self.key_value_settings: dict[str, Setting] = {
|
||||
# fmt: off
|
||||
'categories': MultipleChoiceSetting(
|
||||
['general'],
|
||||
|
@ -516,7 +531,7 @@ class Preferences:
|
|||
dict_data[x] = y[0]
|
||||
self.parse_dict(dict_data)
|
||||
|
||||
def parse_dict(self, input_data: Dict[str, str]):
|
||||
def parse_dict(self, input_data: dict[str, str]):
|
||||
"""parse preferences from request (``flask.request.form``)"""
|
||||
for user_setting_name, user_setting in input_data.items():
|
||||
if user_setting_name in self.key_value_settings:
|
||||
|
@ -530,7 +545,7 @@ class Preferences:
|
|||
elif user_setting_name == 'tokens':
|
||||
self.tokens.parse(user_setting)
|
||||
|
||||
def parse_form(self, input_data: Dict[str, str]):
|
||||
def parse_form(self, input_data: dict[str, str]):
|
||||
"""Parse formular (``<input>``) data from a ``flask.request.form``"""
|
||||
disabled_engines = []
|
||||
enabled_categories = []
|
||||
|
@ -554,12 +569,12 @@ class Preferences:
|
|||
elif user_setting_name == 'tokens':
|
||||
self.tokens.parse_form(user_setting)
|
||||
|
||||
self.key_value_settings['categories'].parse_form(enabled_categories)
|
||||
self.key_value_settings['categories'].parse_form(enabled_categories) # type: ignore
|
||||
self.engines.parse_form(disabled_engines)
|
||||
self.plugins.parse_form(disabled_plugins)
|
||||
|
||||
# cannot be used in case of engines or plugins
|
||||
def get_value(self, user_setting_name: str):
|
||||
def get_value(self, user_setting_name: str) -> t.Any:
|
||||
"""Returns the value for ``user_setting_name``"""
|
||||
ret_val = None
|
||||
if user_setting_name in self.key_value_settings:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue