summaryrefslogtreecommitdiff
path: root/searx/result_types/answer.py
diff options
context:
space:
mode:
Diffstat (limited to 'searx/result_types/answer.py')
-rw-r--r--searx/result_types/answer.py141
1 files changed, 141 insertions, 0 deletions
diff --git a/searx/result_types/answer.py b/searx/result_types/answer.py
new file mode 100644
index 000000000..1042fe00e
--- /dev/null
+++ b/searx/result_types/answer.py
@@ -0,0 +1,141 @@
+# SPDX-License-Identifier: AGPL-3.0-or-later
+"""
+Typification of the *answer* results. Results of this type are rendered in
+the :origin:`answers.html <searx/templates/simple/elements/answers.html>`
+template.
+
+----
+
+.. autoclass:: BaseAnswer
+ :members:
+ :show-inheritance:
+
+.. autoclass:: Answer
+ :members:
+ :show-inheritance:
+
+.. autoclass:: Translations
+ :members:
+ :show-inheritance:
+
+.. autoclass:: AnswerSet
+ :members:
+ :show-inheritance:
+"""
+# pylint: disable=too-few-public-methods
+
+from __future__ import annotations
+
+__all__ = ["AnswerSet", "Answer", "Translations"]
+
+import msgspec
+
+from ._base import Result
+
+
+class BaseAnswer(Result, kw_only=True):
+ """Base class of all answer types. It is not intended to build instances of
+ this class (aka *abstract*)."""
+
+
+class AnswerSet:
+ """Aggregator for :py:obj:`BaseAnswer` items in a result container."""
+
+ def __init__(self):
+ self._answerlist = []
+
+ def __len__(self):
+ return len(self._answerlist)
+
+ def __bool__(self):
+ return bool(self._answerlist)
+
+ def add(self, answer: BaseAnswer) -> None:
+ a_hash = hash(answer)
+ for i in self._answerlist:
+ if hash(i) == a_hash:
+ return
+ self._answerlist.append(answer)
+
+ def __iter__(self):
+ """Sort items in this set and iterate over the items."""
+ self._answerlist.sort(key=lambda answer: answer.template)
+ yield from self._answerlist
+
+ def __contains__(self, answer: BaseAnswer) -> bool:
+ a_hash = hash(answer)
+ for i in self._answerlist:
+ if hash(i) == a_hash:
+ return True
+ return False
+
+
+class Answer(BaseAnswer, kw_only=True):
+ """Simple answer type where the *answer* is a simple string with an optional
+ :py:obj:`url field <Result.url>` field to link a resource (article, map, ..)
+ related to the answer."""
+
+ template: str = "answer/legacy.html"
+
+ answer: str
+ """Text of the answer."""
+
+ def __hash__(self):
+ """The hash value of field *answer* is the hash value of the
+ :py:obj:`Answer` object. :py:obj:`Answer <Result.__eq__>` objects are
+ equal, when the hash values of both objects are equal."""
+ return hash(self.answer)
+
+
+class Translations(BaseAnswer, kw_only=True):
+ """Answer type with a list of translations.
+
+ The items in the list of :py:obj:`Translations.translations` are of type
+ :py:obj:`Translations.Item`:
+
+ .. code:: python
+
+ def response(resp):
+ results = []
+ ...
+ foo_1 = Translations.Item(
+ text="foobar",
+ synonyms=["bar", "foo"],
+ examples=["foo and bar are placeholders"],
+ )
+ foo_url="https://www.deepl.com/de/translator#en/de/foo"
+ ...
+ Translations(results=results, translations=[foo], url=foo_url)
+
+ """
+
+ template: str = "answer/translations.html"
+ """The template in :origin:`answer/translations.html
+ <searx/templates/simple/answer/translations.html>`"""
+
+ translations: list[Translations.Item]
+ """List of translations."""
+
+ class Item(msgspec.Struct, kw_only=True):
+ """A single element of the translations / a translation. A translation
+ consists of at least a mandatory ``text`` property (the translation) ,
+ optional properties such as *definitions*, *synonyms* and *examples* are
+ possible."""
+
+ text: str
+ """Translated text."""
+
+ transliteration: str = ""
+ """Transliteration_ of the requested translation.
+
+ .. _Transliteration: https://en.wikipedia.org/wiki/Transliteration
+ """
+
+ examples: list[str] = []
+ """List of examples for the requested translation."""
+
+ definitions: list[str] = []
+ """List of definitions for the requested translation."""
+
+ synonyms: list[str] = []
+ """List of synonyms for the requested translation."""