summaryrefslogtreecommitdiff
path: root/searx/result_types
diff options
context:
space:
mode:
authorFabian Freund <mail@fabi.online>2026-04-28 23:42:29 +0800
committerGitHub <noreply@github.com>2026-04-28 17:42:29 +0200
commited5955a5c7ff3dc5cfca4fcdd57d2eef4564049b (patch)
treeaa41ec80fb7f882e8c74c7e269d21d7a0d54efe7 /searx/result_types
parenta7ac696b4a146af905397b8b9a07b18f4cd42bb5 (diff)
[fix] Result.defaults_from() inverted logic (#6019)
The bug was introduced in commit 8769b7c6d (typification of result items); this patch fixes the bug and also addresses the peculiarity that fields can be set but contain no *usable* value: If a field is set (exists) but contains an empty string or the value ``None``, it is also considered *not set*. This also ensures that an integer 0 is evaluated *as set*! Co-Authored: Markus Heiser <markus.heiser@darmarit.de>
Diffstat (limited to 'searx/result_types')
-rw-r--r--searx/result_types/_base.py24
1 files changed, 13 insertions, 11 deletions
diff --git a/searx/result_types/_base.py b/searx/result_types/_base.py
index 04e95dc07..e83be4382 100644
--- a/searx/result_types/_base.py
+++ b/searx/result_types/_base.py
@@ -32,7 +32,7 @@ import msgspec
from searx import logger as log
WHITESPACE_REGEX = re.compile('( |\t|\n)+', re.M | re.U)
-UNKNOWN = object()
+UNSET = object()
def _normalize_url_fields(result: "Result | LegacyResult"):
@@ -326,12 +326,13 @@ class Result(msgspec.Struct, kw_only=True):
def defaults_from(self, other: "Result"):
"""Fields not set in *self* will be updated from the field values of the
- *other*.
+ *other*. If a field is set (exists) but contains an empty string
+ or the value ``None``, it is also considered *not set*.
"""
for field_name in self.__struct_fields__:
- self_val = getattr(self, field_name, False)
- other_val = getattr(other, field_name, False)
- if self_val:
+ self_val = getattr(self, field_name, UNSET)
+ other_val = getattr(other, field_name, UNSET)
+ if self_val is UNSET and other_val not in (UNSET, "", None):
setattr(self, field_name, other_val)
@@ -440,8 +441,6 @@ class LegacyResult(dict[str, t.Any]):
Do not use this class in your own implementations!
"""
- UNSET: object = object()
-
# emulate field types from type class Result
url: str | None
template: str
@@ -512,7 +511,7 @@ class LegacyResult(dict[str, t.Any]):
)
def __getattr__(self, name: str, default: t.Any = UNSET) -> t.Any:
- if default == self.UNSET and name not in self:
+ if default == UNSET and name not in self:
raise AttributeError(f"LegacyResult object has no field named: {name}")
return self[name]
@@ -563,9 +562,12 @@ class LegacyResult(dict[str, t.Any]):
self.engines.add(self.engine)
def defaults_from(self, other: "LegacyResult"):
- for k, v in other.items():
- if not self.get(k):
- self[k] = v
+ # If a field is set (exists) but contains an empty string or the value
+ # ``None``, it is also considered *not set*.
+ for field_name, other_val in other.items():
+ self_val = self.get(field_name, UNSET)
+ if self_val is UNSET and other_val not in ("", UNSET):
+ self[field_name] = other_val
def filter_urls(self, filter_func: "Callable[[Result | LegacyResult, str, str], str | bool]"):
"""See :py:obj:`Result.filter_urls`"""