diff options
author | Grant Lanham <contact@grantlanham.com> | 2024-10-05 16:10:56 +0200 |
---|---|---|
committer | Markus Heiser <markus.heiser@darmarIT.de> | 2024-10-15 08:10:52 +0200 |
commit | 3e87354f0ea62d5e2cf22bba136f0e5fdf71cb81 (patch) | |
tree | fe3004ab9f7e3ef56c29b6d1b84d392fade1319f /searx/plugins | |
parent | d448def1a66afe9e0b702ac25ca921526a3f0ca2 (diff) | |
download | searxng-3e87354f0ea62d5e2cf22bba136f0e5fdf71cb81.tar.gz searxng-3e87354f0ea62d5e2cf22bba136f0e5fdf71cb81.zip |
[fix] float operations in calculator plugin
This patch adds an additional *isinstance* check within the ast parser to check
for float along with int, fixing the underlying issue.
Co-Authored: Markus Heiser <markus.heiser@darmarit.de>
Diffstat (limited to 'searx/plugins')
-rw-r--r-- | searx/plugins/calculator.py | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/searx/plugins/calculator.py b/searx/plugins/calculator.py index d963aa304..403b04d57 100644 --- a/searx/plugins/calculator.py +++ b/searx/plugins/calculator.py @@ -3,9 +3,12 @@ """ import ast +import re import operator from multiprocessing import Process, Queue +from typing import Callable +import babel.numbers from flask_babel import gettext from searx.plugins import logger @@ -19,7 +22,7 @@ plugin_id = 'calculator' logger = logger.getChild(plugin_id) -operators = { +operators: dict[type, Callable] = { ast.Add: operator.add, ast.Sub: operator.sub, ast.Mult: operator.mul, @@ -39,11 +42,15 @@ def _eval_expr(expr): >>> _eval_expr('1 + 2*3**(4^5) / (6 + -7)') -5.0 """ - return _eval(ast.parse(expr, mode='eval').body) + try: + return _eval(ast.parse(expr, mode='eval').body) + except ZeroDivisionError: + # This is undefined + return "" def _eval(node): - if isinstance(node, ast.Constant) and isinstance(node.value, int): + if isinstance(node, ast.Constant) and isinstance(node.value, (int, float)): return node.value if isinstance(node, ast.BinOp): @@ -93,6 +100,16 @@ def post_search(_request, search): # replace commonly used math operators with their proper Python operator query = query.replace("x", "*").replace(":", "/") + # 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") + return str(val) + + decimal = search.search_query.locale.number_symbols["latn"]["decimal"] + group = search.search_query.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 if any(str.isalpha(c) for c in query): return True @@ -102,10 +119,8 @@ def post_search(_request, search): # Prevent the runtime from being longer than 50 ms result = timeout_func(0.05, _eval_expr, query_py_formatted) - if result is None: + if result is None or result == "": return True - result = str(result) - - if result != query: - search.result_container.answers['calculate'] = {'answer': f"{query} = {result}"} + result = babel.numbers.format_decimal(result, locale=search.search_query.locale) + search.result_container.answers['calculate'] = {'answer': f"{search.search_query.query} = {result}"} return True |