diff --git a/searx/result_types/_base.py b/searx/result_types/_base.py
index 66e31c7f2..1496cbd2c 100644
--- a/searx/result_types/_base.py
+++ b/searx/result_types/_base.py
@@ -114,6 +114,25 @@ class Result(msgspec.Struct, kw_only=True):
return {f: getattr(self, f) for f in self.__struct_fields__}
+class MainResult(Result): # pylint: disable=missing-class-docstring
+
+ # open_group and close_group should not manged in the Result class (we should rop it from here!)
+ open_group: bool = False
+ close_group: bool = False
+
+ title: str = ""
+ """Link title of the result item."""
+
+ content: str = ""
+ """Extract or description of the result item"""
+
+ img_src: str = ""
+ """URL of a image that is displayed in the result item."""
+
+ thumbnail: str = ""
+ """URL of a thumbnail that is displayed in the result item."""
+
+
class LegacyResult(dict):
"""A wrapper around a legacy result item. The SearXNG core uses this class
for untyped dictionaries / to be downward compatible.
diff --git a/searx/templates/simple/result_templates/key-value.html b/searx/templates/simple/result_templates/key-value.html
index cb7f829ee..dcab4377f 100644
--- a/searx/templates/simple/result_templates/key-value.html
+++ b/searx/templates/simple/result_templates/key-value.html
@@ -1,6 +1,6 @@
{% for key, value in result.items() %}
- {% if key in ['engine', 'engines', 'template', 'score', 'category', 'positions', 'pretty_url', 'parsed_url'] %}
+ {% if key in ['engine', 'engines', 'template', 'score', 'category', 'positions', 'parsed_url'] %}
{% continue %}
{% endif %}
diff --git a/searx/webapp.py b/searx/webapp.py
index c3ce07302..9d51b5e8c 100755
--- a/searx/webapp.py
+++ b/searx/webapp.py
@@ -694,9 +694,7 @@ def search():
if 'title' in result and result['title']:
result['title'] = highlight_content(escape(result['title'] or ''), search_query.query)
- if 'url' in result:
- result['pretty_url'] = webutils.prettify_url(result['url'])
- if result.get('publishedDate'): # do not try to get a date from an empty string or a None type
+ if getattr(result, 'publishedDate', None): # do not try to get a date from an empty string or a None type
try: # test if publishedDate >= 1900 (datetime module bug)
result['pubdate'] = result['publishedDate'].strftime('%Y-%m-%d %H:%M:%S%z')
except ValueError:
@@ -706,15 +704,15 @@ def search():
# set result['open_group'] = True when the template changes from the previous result
# set result['close_group'] = True when the template changes on the next result
- if current_template != result.get('template'):
- result['open_group'] = True
+ if current_template != result.template:
+ result.open_group = True
if previous_result:
- previous_result['close_group'] = True # pylint: disable=unsupported-assignment-operation
- current_template = result.get('template')
+ previous_result.close_group = True # pylint: disable=unsupported-assignment-operation
+ current_template = result.template
previous_result = result
if previous_result:
- previous_result['close_group'] = True
+ previous_result.close_group = True
# 4.a RSS
diff --git a/tests/unit/test_webapp.py b/tests/unit/test_webapp.py
index 12c86e4f0..e8f4fcdcd 100644
--- a/tests/unit/test_webapp.py
+++ b/tests/unit/test_webapp.py
@@ -2,13 +2,13 @@
# pylint: disable=missing-module-docstring,disable=missing-class-docstring,invalid-name
import json
-from urllib.parse import ParseResult
import babel
from mock import Mock
import searx.webapp
import searx.search
import searx.search.processors
+from searx.result_types._base import MainResult
from searx.results import Timing
from searx.preferences import Preferences
@@ -31,30 +31,21 @@ class ViewsTestCase(SearxTestCase): # pylint: disable=too-many-public-methods
# set some defaults
test_results = [
- {
- 'content': 'first test content',
- 'title': 'First Test',
- 'url': 'http://first.test.xyz',
- 'engines': ['youtube', 'startpage'],
- 'engine': 'startpage',
- 'parsed_url': ParseResult(
- scheme='http', netloc='first.test.xyz', path='/', params='', query='', fragment=''
- ),
- 'template': 'default.html',
- },
- {
- 'content': 'second test content',
- 'title': 'Second Test',
- 'url': 'http://second.test.xyz',
- 'engines': ['youtube', 'startpage'],
- 'engine': 'youtube',
- 'parsed_url': ParseResult(
- scheme='http', netloc='second.test.xyz', path='/', params='', query='', fragment=''
- ),
- 'template': 'default.html',
- },
+ MainResult(
+ title="First Test",
+ url="http://first.test.xyz",
+ content="first test content",
+ engine="startpage",
+ ),
+ MainResult(
+ title="Second Test",
+ url="http://second.test.xyz",
+ content="second test content",
+ engine="youtube",
+ ),
]
-
+ for r in test_results:
+ r.normalize_result_fields()
timings = [
Timing(engine='startpage', total=0.8, load=0.7),
Timing(engine='youtube', total=0.9, load=0.6),