From 2d66ea48db05556120c46c910391c0679b189315 Mon Sep 17 00:00:00 2001 From: Miguel Grinberg Date: Fri, 18 Oct 2024 17:27:13 +0100 Subject: [PATCH] typing of the `meta` attribute of hits --- elasticsearch_dsl/utils.py | 12 +++++++++++- examples/async/parent_child.py | 2 +- examples/async/sparse_vectors.py | 2 +- examples/async/vectors.py | 2 +- examples/parent_child.py | 2 +- examples/sparse_vectors.py | 2 +- examples/vectors.py | 2 +- utils/generator.py | 10 +++++----- 8 files changed, 22 insertions(+), 12 deletions(-) diff --git a/elasticsearch_dsl/utils.py b/elasticsearch_dsl/utils.py index e85a17e0..476778f8 100644 --- a/elasticsearch_dsl/utils.py +++ b/elasticsearch_dsl/utils.py @@ -28,6 +28,7 @@ Iterable, Iterator, List, + Mapping, Optional, Tuple, Type, @@ -48,6 +49,7 @@ from .field import Field from .index_base import IndexBase from .response import Hit # noqa: F401 + from .types import Hit as HitBaseType UsingType: TypeAlias = Union[str, "Elasticsearch"] AsyncUsingType: TypeAlias = Union[str, "AsyncElasticsearch"] @@ -468,7 +470,15 @@ def _clone(self) -> Self: return c -class HitMeta(AttrDict[Any]): +if TYPE_CHECKING: + HitMetaBase = HitBaseType +else: + HitMetaBase = AttrDict[Any] + + +class HitMeta(HitMetaBase): + inner_hits: Mapping[str, Any] + def __init__( self, document: Dict[str, Any], diff --git a/examples/async/parent_child.py b/examples/async/parent_child.py index 2a74d2d4..80c8f63a 100644 --- a/examples/async/parent_child.py +++ b/examples/async/parent_child.py @@ -190,7 +190,7 @@ async def get_answers(self) -> List[Any]: elasticsearch. """ if "inner_hits" in self.meta and "answer" in self.meta.inner_hits: - return cast(List[Any], self.meta.inner_hits.answer.hits) + return cast(List[Any], self.meta.inner_hits["answer"].hits) return [a async for a in self.search_answers()] async def save(self, **kwargs: Any) -> None: # type: ignore[override] diff --git a/examples/async/sparse_vectors.py b/examples/async/sparse_vectors.py index 458798a3..962ecda8 100644 --- a/examples/async/sparse_vectors.py +++ b/examples/async/sparse_vectors.py @@ -186,7 +186,7 @@ async def main() -> None: ) print(f"Summary: {hit.summary}") if args.show_inner_hits: - for passage in hit.meta.inner_hits.passages: + for passage in hit.meta.inner_hits["passages"]: print(f" - [Score: {passage.meta.score}] {passage.content!r}") print("") diff --git a/examples/async/vectors.py b/examples/async/vectors.py index b58c184e..e17cbf3e 100644 --- a/examples/async/vectors.py +++ b/examples/async/vectors.py @@ -175,7 +175,7 @@ async def main() -> None: ) print(f"Summary: {hit.summary}") if args.show_inner_hits: - for passage in hit.meta.inner_hits.passages: + for passage in hit.meta.inner_hits["passages"]: print(f" - [Score: {passage.meta.score}] {passage.content!r}") print("") diff --git a/examples/parent_child.py b/examples/parent_child.py index 6d20dde2..25a2e9a7 100644 --- a/examples/parent_child.py +++ b/examples/parent_child.py @@ -189,7 +189,7 @@ def get_answers(self) -> List[Any]: elasticsearch. """ if "inner_hits" in self.meta and "answer" in self.meta.inner_hits: - return cast(List[Any], self.meta.inner_hits.answer.hits) + return cast(List[Any], self.meta.inner_hits["answer"].hits) return [a for a in self.search_answers()] def save(self, **kwargs: Any) -> None: # type: ignore[override] diff --git a/examples/sparse_vectors.py b/examples/sparse_vectors.py index ba853e8c..408e0df8 100644 --- a/examples/sparse_vectors.py +++ b/examples/sparse_vectors.py @@ -185,7 +185,7 @@ def main() -> None: ) print(f"Summary: {hit.summary}") if args.show_inner_hits: - for passage in hit.meta.inner_hits.passages: + for passage in hit.meta.inner_hits["passages"]: print(f" - [Score: {passage.meta.score}] {passage.content!r}") print("") diff --git a/examples/vectors.py b/examples/vectors.py index ef1342ee..d6ecd6e2 100644 --- a/examples/vectors.py +++ b/examples/vectors.py @@ -174,7 +174,7 @@ def main() -> None: ) print(f"Summary: {hit.summary}") if args.show_inner_hits: - for passage in hit.meta.inner_hits.passages: + for passage in hit.meta.inner_hits["passages"]: print(f" - [Score: {passage.meta.score}] {passage.content!r}") print("") diff --git a/utils/generator.py b/utils/generator.py index 40272932..231bc242 100644 --- a/utils/generator.py +++ b/utils/generator.py @@ -702,12 +702,12 @@ def interface_to_python_class( # types via generics, each in array or object configurations. # Typing this attribute proved very difficult. A solution # that worked with mypy and pyright is to type "buckets" - # with the array (list) form, and create a `buckets_as_dict` - # property that is typed appropriate for accessing the - # buckets when in object (dictionary) form. + # for the list form, and create a `buckets_as_dict` + # property that is typed appropriately for accessing the + # buckets in dictionary form. # The generic type is assumed to be the first in the list, - # which is a simplification that should be removed when a - # more complete implementation of generic is added. + # which is a simplification that should be improved when a + # more complete implementation of generics is added. if generics[0]["type"]["name"] == "Void": generic_type = "Any" else: