answer.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. # SPDX-License-Identifier: AGPL-3.0-or-later
  2. """
  3. Typification of the *answer* results. Results of this type are rendered in
  4. the :origin:`answers.html <searx/templates/simple/elements/answers.html>`
  5. template.
  6. ----
  7. .. autoclass:: BaseAnswer
  8. :members:
  9. :show-inheritance:
  10. .. autoclass:: Answer
  11. :members:
  12. :show-inheritance:
  13. .. autoclass:: Translations
  14. :members:
  15. :show-inheritance:
  16. .. autoclass:: AnswerSet
  17. :members:
  18. :show-inheritance:
  19. """
  20. # pylint: disable=too-few-public-methods
  21. from __future__ import annotations
  22. __all__ = ["AnswerSet", "Answer", "Translations"]
  23. import msgspec
  24. from ._base import Result
  25. class BaseAnswer(Result, kw_only=True):
  26. """Base class of all answer types. It is not intended to build instances of
  27. this class (aka *abstract*)."""
  28. class AnswerSet:
  29. """Aggregator for :py:obj:`BaseAnswer` items in a result container."""
  30. def __init__(self):
  31. self._answerlist = []
  32. def __len__(self):
  33. return len(self._answerlist)
  34. def __bool__(self):
  35. return bool(self._answerlist)
  36. def add(self, answer: BaseAnswer) -> None:
  37. a_hash = hash(answer)
  38. for i in self._answerlist:
  39. if hash(i) == a_hash:
  40. return
  41. self._answerlist.append(answer)
  42. def __iter__(self):
  43. """Sort items in this set and iterate over the items."""
  44. self._answerlist.sort(key=lambda answer: answer.template)
  45. yield from self._answerlist
  46. def __contains__(self, answer: BaseAnswer) -> bool:
  47. a_hash = hash(answer)
  48. for i in self._answerlist:
  49. if hash(i) == a_hash:
  50. return True
  51. return False
  52. class Answer(BaseAnswer, kw_only=True):
  53. """Simple answer type where the *answer* is a simple string with an optional
  54. :py:obj:`url field <Result.url>` field to link a resource (article, map, ..)
  55. related to the answer."""
  56. template: str = "answer/legacy.html"
  57. answer: str
  58. """Text of the answer."""
  59. def __hash__(self):
  60. """The hash value of field *answer* is the hash value of the
  61. :py:obj:`Answer` object. :py:obj:`Answer <Result.__eq__>` objects are
  62. equal, when the hash values of both objects are equal."""
  63. return hash(self.answer)
  64. class Translations(BaseAnswer, kw_only=True):
  65. """Answer type with a list of translations.
  66. The items in the list of :py:obj:`Translations.translations` are of type
  67. :py:obj:`Translations.Item`:
  68. .. code:: python
  69. def response(resp):
  70. results = []
  71. ...
  72. foo_1 = Translations.Item(
  73. text="foobar",
  74. synonyms=["bar", "foo"],
  75. examples=["foo and bar are placeholders"],
  76. )
  77. foo_url="https://www.deepl.com/de/translator#en/de/foo"
  78. ...
  79. Translations(results=results, translations=[foo], url=foo_url)
  80. """
  81. template: str = "answer/translations.html"
  82. """The template in :origin:`answer/translations.html
  83. <searx/templates/simple/answer/translations.html>`"""
  84. translations: list[Translations.Item]
  85. """List of translations."""
  86. def __post_init__(self):
  87. if not self.translations:
  88. raise ValueError("Translation does not have an item in the list translations")
  89. class Item(msgspec.Struct, kw_only=True):
  90. """A single element of the translations / a translation. A translation
  91. consists of at least a mandatory ``text`` property (the translation) ,
  92. optional properties such as *definitions*, *synonyms* and *examples* are
  93. possible."""
  94. text: str
  95. """Translated text."""
  96. transliteration: str = ""
  97. """Transliteration_ of the requested translation.
  98. .. _Transliteration: https://en.wikipedia.org/wiki/Transliteration
  99. """
  100. examples: list[str] = []
  101. """List of examples for the requested translation."""
  102. definitions: list[str] = []
  103. """List of definitions for the requested translation."""
  104. synonyms: list[str] = []
  105. """List of synonyms for the requested translation."""