Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
github-actions[bot] committed Oct 29, 2024
2 parents d19bd68 + b176323 commit 7a6b599
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 46 deletions.
9 changes: 5 additions & 4 deletions searx/limiter.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,18 +128,19 @@
LIMITER_CFG_SCHEMA = Path(__file__).parent / "limiter.toml"
"""Base configuration (schema) of the botdetection."""

LIMITER_CFG = Path('/etc/searxng/limiter.toml')
"""Local Limiter configuration."""

CFG_DEPRECATED = {
# "dummy.old.foo": "config 'dummy.old.foo' exists only for tests. Don't use it in your real project config."
}


def get_cfg() -> config.Config:
global CFG # pylint: disable=global-statement

if CFG is None:
CFG = config.Config.from_toml(LIMITER_CFG_SCHEMA, LIMITER_CFG, CFG_DEPRECATED)
from . import settings_loader # pylint: disable=import-outside-toplevel

cfg_file = (settings_loader.get_user_cfg_folder() or Path("/etc/searxng")) / "limiter.toml"
CFG = config.Config.from_toml(LIMITER_CFG_SCHEMA, cfg_file, CFG_DEPRECATED)
return CFG


Expand Down
14 changes: 9 additions & 5 deletions searx/plugins/calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
from multiprocessing import Process, Queue
from typing import Callable

import babel.numbers
import flask
import babel
from flask_babel import gettext

from searx.plugins import logger
Expand Down Expand Up @@ -100,14 +101,17 @@ def post_search(_request, search):
# replace commonly used math operators with their proper Python operator
query = query.replace("x", "*").replace(":", "/")

# use UI language
ui_locale = babel.Locale.parse(flask.request.preferences.get_value('locale'), sep='-')

# parse the number system in a localized way
def _decimal(match: re.Match) -> str:
val = match.string[match.start() : match.end()]
val = babel.numbers.parse_decimal(val, search.search_query.locale, numbering_system="latn")
val = babel.numbers.parse_decimal(val, ui_locale, numbering_system="latn")
return str(val)

decimal = search.search_query.locale.number_symbols["latn"]["decimal"]
group = search.search_query.locale.number_symbols["latn"]["group"]
decimal = ui_locale.number_symbols["latn"]["decimal"]
group = ui_locale.number_symbols["latn"]["group"]
query = re.sub(f"[0-9]+[{decimal}|{group}][0-9]+[{decimal}|{group}]?[0-9]?", _decimal, query)

# only numbers and math operators are accepted
Expand All @@ -121,6 +125,6 @@ def _decimal(match: re.Match) -> str:
result = timeout_func(0.05, _eval_expr, query_py_formatted)
if result is None or result == "":
return True
result = babel.numbers.format_decimal(result, locale=search.search_query.locale)
result = babel.numbers.format_decimal(result, locale=ui_locale)
search.result_container.answers['calculate'] = {'answer': f"{search.search_query.query} = {result}"}
return True
2 changes: 1 addition & 1 deletion searx/webapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ def pre_request():
preferences.parse_dict({"language": language})
logger.debug('set language %s (from browser)', preferences.get_value("language"))

# locale is defined neither in settings nor in preferences
# UI locale is defined neither in settings nor in preferences
# use browser headers
if not preferences.get_value("locale"):
locale = _get_browser_language(request, LOCALE_NAMES.keys())
Expand Down
90 changes: 54 additions & 36 deletions tests/unit/test_plugin_calculator.py
Original file line number Diff line number Diff line change
@@ -1,73 +1,89 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
# pylint: disable=missing-module-docstring

from mock import Mock
import flask
from parameterized.parameterized import parameterized
from searx import plugins
from searx import preferences
from tests import SearxTestCase
from .test_utils import random_string

from .test_plugins import get_search_mock


class PluginCalculator(SearxTestCase): # pylint: disable=missing-class-docstring

def setUp(self):
from searx import webapp # pylint: disable=import-outside-toplevel

self.webapp = webapp
self.store = plugins.PluginStore()
plugin = plugins.load_and_initialize_plugin('searx.plugins.calculator', False, (None, {}))
self.store.register(plugin)
self.preferences = preferences.Preferences(["simple"], ["general"], {}, self.store)
self.preferences.parse_dict({"locale": "en"})

def test_plugin_store_init(self):
self.assertEqual(1, len(self.store.plugins))

def test_single_page_number_true(self):
request = Mock(remote_addr='127.0.0.1')
search = get_search_mock(query=random_string(10), pageno=2)
result = self.store.call(self.store.plugins, 'post_search', request, search)
with self.webapp.app.test_request_context():
flask.request.preferences = self.preferences
search = get_search_mock(query=random_string(10), pageno=2)
result = self.store.call(self.store.plugins, 'post_search', flask.request, search)

self.assertTrue(result)
self.assertNotIn('calculate', search.result_container.answers)

def test_long_query_true(self):
request = Mock(remote_addr='127.0.0.1')
search = get_search_mock(query=random_string(101), pageno=1)
result = self.store.call(self.store.plugins, 'post_search', request, search)
with self.webapp.app.test_request_context():
flask.request.preferences = self.preferences
search = get_search_mock(query=random_string(101), pageno=1)
result = self.store.call(self.store.plugins, 'post_search', flask.request, search)

self.assertTrue(result)
self.assertNotIn('calculate', search.result_container.answers)

def test_alpha_true(self):
request = Mock(remote_addr='127.0.0.1')
search = get_search_mock(query=random_string(10), pageno=1)
result = self.store.call(self.store.plugins, 'post_search', request, search)
with self.webapp.app.test_request_context():
flask.request.preferences = self.preferences
search = get_search_mock(query=random_string(10), pageno=1)
result = self.store.call(self.store.plugins, 'post_search', flask.request, search)

self.assertTrue(result)
self.assertNotIn('calculate', search.result_container.answers)

@parameterized.expand(
[
("1+1", "2", "en-US"),
("1-1", "0", "en-US"),
("1*1", "1", "en-US"),
("1/1", "1", "en-US"),
("1**1", "1", "en-US"),
("1^1", "1", "en-US"),
("1,000.0+1,000.0", "2,000", "en-US"),
("1.0+1.0", "2", "en-US"),
("1.0-1.0", "0", "en-US"),
("1.0*1.0", "1", "en-US"),
("1.0/1.0", "1", "en-US"),
("1.0**1.0", "1", "en-US"),
("1.0^1.0", "1", "en-US"),
("1.000,0+1.000,0", "2.000", "de-DE"),
("1,0+1,0", "2", "de-DE"),
("1,0-1,0", "0", "de-DE"),
("1,0*1,0", "1", "de-DE"),
("1,0/1,0", "1", "de-DE"),
("1,0**1,0", "1", "de-DE"),
("1,0^1,0", "1", "de-DE"),
("1+1", "2", "en"),
("1-1", "0", "en"),
("1*1", "1", "en"),
("1/1", "1", "en"),
("1**1", "1", "en"),
("1^1", "1", "en"),
("1,000.0+1,000.0", "2,000", "en"),
("1.0+1.0", "2", "en"),
("1.0-1.0", "0", "en"),
("1.0*1.0", "1", "en"),
("1.0/1.0", "1", "en"),
("1.0**1.0", "1", "en"),
("1.0^1.0", "1", "en"),
("1.000,0+1.000,0", "2.000", "de"),
("1,0+1,0", "2", "de"),
("1,0-1,0", "0", "de"),
("1,0*1,0", "1", "de"),
("1,0/1,0", "1", "de"),
("1,0**1,0", "1", "de"),
("1,0^1,0", "1", "de"),
]
)
def test_localized_query(self, operation: str, contains_result: str, lang: str):
request = Mock(remote_addr='127.0.0.1')
search = get_search_mock(query=operation, lang=lang, pageno=1)
result = self.store.call(self.store.plugins, 'post_search', request, search)
with self.webapp.app.test_request_context():
self.preferences.parse_dict({"locale": lang})
flask.request.preferences = self.preferences
search = get_search_mock(query=operation, lang=lang, pageno=1)
result = self.store.call(self.store.plugins, 'post_search', flask.request, search)

self.assertTrue(result)
self.assertIn('calculate', search.result_container.answers)
self.assertIn(contains_result, search.result_container.answers['calculate']['answer'])
Expand All @@ -78,8 +94,10 @@ def test_localized_query(self, operation: str, contains_result: str, lang: str):
]
)
def test_invalid_operations(self, operation):
request = Mock(remote_addr='127.0.0.1')
search = get_search_mock(query=operation, pageno=1)
result = self.store.call(self.store.plugins, 'post_search', request, search)
with self.webapp.app.test_request_context():
flask.request.preferences = self.preferences
search = get_search_mock(query=operation, pageno=1)
result = self.store.call(self.store.plugins, 'post_search', flask.request, search)

self.assertTrue(result)
self.assertNotIn('calculate', search.result_container.answers)

0 comments on commit 7a6b599

Please sign in to comment.