From c396cb54c3fc2780cf682529c3303c83ade099f0 Mon Sep 17 00:00:00 2001 From: anakin87 Date: Tue, 13 Jan 2026 09:57:27 +0100 Subject: [PATCH] chore!: qdrant - drop Python 3.9 and use X|Y typing --- integrations/qdrant/pyproject.toml | 10 +- .../components/retrievers/qdrant/retriever.py | 112 +++++++-------- .../document_stores/qdrant/converters.py | 3 +- .../document_stores/qdrant/document_store.py | 132 +++++++++--------- .../document_stores/qdrant/filters.py | 21 +-- 5 files changed, 136 insertions(+), 142 deletions(-) diff --git a/integrations/qdrant/pyproject.toml b/integrations/qdrant/pyproject.toml index 37f061b31a..f4284ded16 100644 --- a/integrations/qdrant/pyproject.toml +++ b/integrations/qdrant/pyproject.toml @@ -7,7 +7,7 @@ name = "qdrant-haystack" dynamic = ["version"] description = 'An integration of Qdrant ANN vector database backend with Haystack' readme = "README.md" -requires-python = ">=3.9" +requires-python = ">=3.10" license = "Apache-2.0" keywords = [] authors = [ @@ -18,7 +18,6 @@ classifiers = [ "License :: OSI Approved :: Apache Software License", "Development Status :: 4 - Beta", "Programming Language :: Python", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", @@ -26,7 +25,7 @@ classifiers = [ "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", ] -dependencies = ["haystack-ai>=2.11.0", "qdrant-client>=1.12.0"] +dependencies = ["haystack-ai>=2.22.0", "qdrant-client>=1.12.0"] [project.urls] Source = "https://github.com/deepset-ai/haystack-core-integrations" @@ -80,7 +79,6 @@ disallow_incomplete_defs = true [tool.ruff] -target-version = "py39" line-length = 120 [tool.ruff.lint] @@ -132,10 +130,6 @@ ignore = [ # Ignore assertions "S101", ] -unfixable = [ - # Don't touch unused imports - "F401", -] [tool.ruff.lint.flake8-tidy-imports] ban-relative-imports = "parents" diff --git a/integrations/qdrant/src/haystack_integrations/components/retrievers/qdrant/retriever.py b/integrations/qdrant/src/haystack_integrations/components/retrievers/qdrant/retriever.py index bd8e9a901e..3025014f19 100644 --- a/integrations/qdrant/src/haystack_integrations/components/retrievers/qdrant/retriever.py +++ b/integrations/qdrant/src/haystack_integrations/components/retrievers/qdrant/retriever.py @@ -1,4 +1,4 @@ -from typing import Any, Optional, Union +from typing import Any from haystack import Document, component, default_from_dict, default_to_dict from haystack.dataclasses.sparse_embedding import SparseEmbedding @@ -43,14 +43,14 @@ class QdrantEmbeddingRetriever: def __init__( self, document_store: QdrantDocumentStore, - filters: Optional[Union[dict[str, Any], models.Filter]] = None, + filters: dict[str, Any] | models.Filter | None = None, top_k: int = 10, scale_score: bool = False, return_embedding: bool = False, - filter_policy: Union[str, FilterPolicy] = FilterPolicy.REPLACE, - score_threshold: Optional[float] = None, - group_by: Optional[str] = None, - group_size: Optional[int] = None, + filter_policy: str | FilterPolicy = FilterPolicy.REPLACE, + score_threshold: float | None = None, + group_by: str | None = None, + group_size: int | None = None, ) -> None: """ Create a QdrantEmbeddingRetriever component. @@ -134,13 +134,13 @@ def from_dict(cls, data: dict[str, Any]) -> "QdrantEmbeddingRetriever": def run( self, query_embedding: list[float], - filters: Optional[Union[dict[str, Any], models.Filter]] = None, - top_k: Optional[int] = None, - scale_score: Optional[bool] = None, - return_embedding: Optional[bool] = None, - score_threshold: Optional[float] = None, - group_by: Optional[str] = None, - group_size: Optional[int] = None, + filters: dict[str, Any] | models.Filter | None = None, + top_k: int | None = None, + scale_score: bool | None = None, + return_embedding: bool | None = None, + score_threshold: float | None = None, + group_by: str | None = None, + group_size: int | None = None, ) -> dict[str, list[Document]]: """ Run the Embedding Retriever on the given input data. @@ -189,13 +189,13 @@ def run( async def run_async( self, query_embedding: list[float], - filters: Optional[Union[dict[str, Any], models.Filter]] = None, - top_k: Optional[int] = None, - scale_score: Optional[bool] = None, - return_embedding: Optional[bool] = None, - score_threshold: Optional[float] = None, - group_by: Optional[str] = None, - group_size: Optional[int] = None, + filters: dict[str, Any] | models.Filter | None = None, + top_k: int | None = None, + scale_score: bool | None = None, + return_embedding: bool | None = None, + score_threshold: float | None = None, + group_by: str | None = None, + group_size: int | None = None, ) -> dict[str, list[Document]]: """ Asynchronously run the Embedding Retriever on the given input data. @@ -271,14 +271,14 @@ class QdrantSparseEmbeddingRetriever: def __init__( self, document_store: QdrantDocumentStore, - filters: Optional[Union[dict[str, Any], models.Filter]] = None, + filters: dict[str, Any] | models.Filter | None = None, top_k: int = 10, scale_score: bool = False, return_embedding: bool = False, - filter_policy: Union[str, FilterPolicy] = FilterPolicy.REPLACE, - score_threshold: Optional[float] = None, - group_by: Optional[str] = None, - group_size: Optional[int] = None, + filter_policy: str | FilterPolicy = FilterPolicy.REPLACE, + score_threshold: float | None = None, + group_by: str | None = None, + group_size: int | None = None, ) -> None: """ Create a QdrantSparseEmbeddingRetriever component. @@ -362,13 +362,13 @@ def from_dict(cls, data: dict[str, Any]) -> "QdrantSparseEmbeddingRetriever": def run( self, query_sparse_embedding: SparseEmbedding, - filters: Optional[Union[dict[str, Any], models.Filter]] = None, - top_k: Optional[int] = None, - scale_score: Optional[bool] = None, - return_embedding: Optional[bool] = None, - score_threshold: Optional[float] = None, - group_by: Optional[str] = None, - group_size: Optional[int] = None, + filters: dict[str, Any] | models.Filter | None = None, + top_k: int | None = None, + scale_score: bool | None = None, + return_embedding: bool | None = None, + score_threshold: float | None = None, + group_by: str | None = None, + group_size: int | None = None, ) -> dict[str, list[Document]]: """ Run the Sparse Embedding Retriever on the given input data. @@ -422,13 +422,13 @@ def run( async def run_async( self, query_sparse_embedding: SparseEmbedding, - filters: Optional[Union[dict[str, Any], models.Filter]] = None, - top_k: Optional[int] = None, - scale_score: Optional[bool] = None, - return_embedding: Optional[bool] = None, - score_threshold: Optional[float] = None, - group_by: Optional[str] = None, - group_size: Optional[int] = None, + filters: dict[str, Any] | models.Filter | None = None, + top_k: int | None = None, + scale_score: bool | None = None, + return_embedding: bool | None = None, + score_threshold: float | None = None, + group_by: str | None = None, + group_size: int | None = None, ) -> dict[str, list[Document]]: """ Asynchronously run the Sparse Embedding Retriever on the given input data. @@ -515,13 +515,13 @@ class QdrantHybridRetriever: def __init__( self, document_store: QdrantDocumentStore, - filters: Optional[Union[dict[str, Any], models.Filter]] = None, + filters: dict[str, Any] | models.Filter | None = None, top_k: int = 10, return_embedding: bool = False, - filter_policy: Union[str, FilterPolicy] = FilterPolicy.REPLACE, - score_threshold: Optional[float] = None, - group_by: Optional[str] = None, - group_size: Optional[int] = None, + filter_policy: str | FilterPolicy = FilterPolicy.REPLACE, + score_threshold: float | None = None, + group_by: str | None = None, + group_size: int | None = None, ) -> None: """ Create a QdrantHybridRetriever component. @@ -600,12 +600,12 @@ def run( self, query_embedding: list[float], query_sparse_embedding: SparseEmbedding, - filters: Optional[Union[dict[str, Any], models.Filter]] = None, - top_k: Optional[int] = None, - return_embedding: Optional[bool] = None, - score_threshold: Optional[float] = None, - group_by: Optional[str] = None, - group_size: Optional[int] = None, + filters: dict[str, Any] | models.Filter | None = None, + top_k: int | None = None, + return_embedding: bool | None = None, + score_threshold: float | None = None, + group_by: str | None = None, + group_size: int | None = None, ) -> dict[str, list[Document]]: """ Run the Sparse Embedding Retriever on the given input data. @@ -660,12 +660,12 @@ async def run_async( self, query_embedding: list[float], query_sparse_embedding: SparseEmbedding, - filters: Optional[Union[dict[str, Any], models.Filter]] = None, - top_k: Optional[int] = None, - return_embedding: Optional[bool] = None, - score_threshold: Optional[float] = None, - group_by: Optional[str] = None, - group_size: Optional[int] = None, + filters: dict[str, Any] | models.Filter | None = None, + top_k: int | None = None, + return_embedding: bool | None = None, + score_threshold: float | None = None, + group_by: str | None = None, + group_size: int | None = None, ) -> dict[str, list[Document]]: """ Asynchronously run the Sparse Embedding Retriever on the given input data. diff --git a/integrations/qdrant/src/haystack_integrations/document_stores/qdrant/converters.py b/integrations/qdrant/src/haystack_integrations/document_stores/qdrant/converters.py index fcc8ff312b..94001d67ff 100644 --- a/integrations/qdrant/src/haystack_integrations/document_stores/qdrant/converters.py +++ b/integrations/qdrant/src/haystack_integrations/document_stores/qdrant/converters.py @@ -1,5 +1,4 @@ import uuid -from typing import Union from haystack import logging from haystack.dataclasses import Document @@ -58,7 +57,7 @@ def convert_id(_id: str) -> str: return uuid.uuid5(UUID_NAMESPACE, _id).hex -QdrantPoint = Union[rest.ScoredPoint, rest.Record] +QdrantPoint = rest.ScoredPoint | rest.Record def convert_qdrant_point_to_haystack_document(point: QdrantPoint, use_sparse_embeddings: bool) -> Document: diff --git a/integrations/qdrant/src/haystack_integrations/document_stores/qdrant/document_store.py b/integrations/qdrant/src/haystack_integrations/document_stores/qdrant/document_store.py index 6460bea435..96b6f64dee 100644 --- a/integrations/qdrant/src/haystack_integrations/document_stores/qdrant/document_store.py +++ b/integrations/qdrant/src/haystack_integrations/document_stores/qdrant/document_store.py @@ -1,7 +1,7 @@ import inspect from collections.abc import AsyncGenerator, Generator from itertools import islice -from typing import Any, ClassVar, Optional, Union, cast +from typing import Any, ClassVar, cast import qdrant_client from haystack import default_from_dict, default_to_dict, logging @@ -37,7 +37,7 @@ class QdrantStoreError(DocumentStoreError): pass -FilterType = dict[str, Union[dict[str, Any], list[Any], str, int, float, bool]] +FilterType = dict[str, dict[str, Any] | list[Any] | str | int | float | bool] def get_batches_from_generator(iterable: list, n: int) -> Generator: @@ -98,17 +98,17 @@ class QdrantDocumentStore: def __init__( self, - location: Optional[str] = None, - url: Optional[str] = None, + location: str | None = None, + url: str | None = None, port: int = 6333, grpc_port: int = 6334, prefer_grpc: bool = False, - https: Optional[bool] = None, - api_key: Optional[Secret] = None, - prefix: Optional[str] = None, - timeout: Optional[int] = None, - host: Optional[str] = None, - path: Optional[str] = None, + https: bool | None = None, + api_key: Secret | None = None, + prefix: str | None = None, + timeout: int | None = None, + host: str | None = None, + path: str | None = None, force_disable_check_same_thread: bool = False, index: str = "Document", embedding_dim: int = 768, @@ -119,19 +119,19 @@ def __init__( return_embedding: bool = False, progress_bar: bool = True, recreate_index: bool = False, - shard_number: Optional[int] = None, - replication_factor: Optional[int] = None, - write_consistency_factor: Optional[int] = None, - on_disk_payload: Optional[bool] = None, - hnsw_config: Optional[dict] = None, - optimizers_config: Optional[dict] = None, - wal_config: Optional[dict] = None, - quantization_config: Optional[dict] = None, + shard_number: int | None = None, + replication_factor: int | None = None, + write_consistency_factor: int | None = None, + on_disk_payload: bool | None = None, + hnsw_config: dict | None = None, + optimizers_config: dict | None = None, + wal_config: dict | None = None, + quantization_config: dict | None = None, wait_result_from_api: bool = True, - metadata: Optional[dict] = None, + metadata: dict | None = None, write_batch_size: int = 100, scroll_size: int = 10_000, - payload_fields_to_index: Optional[list[dict]] = None, + payload_fields_to_index: list[dict] | None = None, ) -> None: """ Initializes a QdrantDocumentStore. @@ -220,8 +220,8 @@ def __init__( List of payload fields to index. """ - self._client: Optional[qdrant_client.QdrantClient] = None - self._async_client: Optional[qdrant_client.AsyncQdrantClient] = None + self._client: qdrant_client.QdrantClient | None = None + self._async_client: qdrant_client.AsyncQdrantClient | None = None # Store the Qdrant client specific attributes self.location = location @@ -334,7 +334,7 @@ async def count_documents_async(self) -> int: def filter_documents( self, - filters: Optional[Union[dict[str, Any], rest.Filter]] = None, + filters: dict[str, Any] | rest.Filter | None = None, ) -> list[Document]: """ Returns the documents that match the provided filters. @@ -357,7 +357,7 @@ def filter_documents( async def filter_documents_async( self, - filters: Optional[Union[dict[str, Any], rest.Filter]] = None, + filters: dict[str, Any] | rest.Filter | None = None, ) -> list[Document]: """ Asynchronously returns the documents that match the provided filters. @@ -878,7 +878,7 @@ def to_dict(self) -> dict[str, Any]: def _get_documents_generator( self, - filters: Optional[Union[dict[str, Any], rest.Filter]] = None, + filters: dict[str, Any] | rest.Filter | None = None, ) -> Generator[Document, None, None]: """ Returns a generator that yields documents from Qdrant based on the provided filters. @@ -918,7 +918,7 @@ def _get_documents_generator( async def _get_documents_generator_async( self, - filters: Optional[Union[dict[str, Any], rest.Filter]] = None, + filters: dict[str, Any] | rest.Filter | None = None, ) -> AsyncGenerator[Document, None]: """ Returns an asynchronous generator that yields documents from Qdrant based on the provided filters. @@ -1021,13 +1021,13 @@ async def get_documents_by_id_async( def _query_by_sparse( self, query_sparse_embedding: SparseEmbedding, - filters: Optional[Union[dict[str, Any], rest.Filter]] = None, + filters: dict[str, Any] | rest.Filter | None = None, top_k: int = 10, scale_score: bool = False, return_embedding: bool = False, - score_threshold: Optional[float] = None, - group_by: Optional[str] = None, - group_size: Optional[int] = None, + score_threshold: float | None = None, + group_by: str | None = None, + group_size: int | None = None, ) -> list[Document]: """ Queries Qdrant using a sparse embedding and returns the most relevant documents. @@ -1098,13 +1098,13 @@ def _query_by_sparse( def _query_by_embedding( self, query_embedding: list[float], - filters: Optional[Union[dict[str, Any], rest.Filter]] = None, + filters: dict[str, Any] | rest.Filter | None = None, top_k: int = 10, scale_score: bool = False, return_embedding: bool = False, - score_threshold: Optional[float] = None, - group_by: Optional[str] = None, - group_size: Optional[int] = None, + score_threshold: float | None = None, + group_by: str | None = None, + group_size: int | None = None, ) -> list[Document]: """ Queries Qdrant using a dense embedding and returns the most relevant documents. @@ -1159,12 +1159,12 @@ def _query_hybrid( self, query_embedding: list[float], query_sparse_embedding: SparseEmbedding, - filters: Optional[Union[dict[str, Any], rest.Filter]] = None, + filters: dict[str, Any] | rest.Filter | None = None, top_k: int = 10, return_embedding: bool = False, - score_threshold: Optional[float] = None, - group_by: Optional[str] = None, - group_size: Optional[int] = None, + score_threshold: float | None = None, + group_by: str | None = None, + group_size: int | None = None, ) -> list[Document]: """ Retrieves documents based on dense and sparse embeddings and fuses the results using Reciprocal Rank Fusion. @@ -1271,13 +1271,13 @@ def _query_hybrid( async def _query_by_sparse_async( self, query_sparse_embedding: SparseEmbedding, - filters: Optional[Union[dict[str, Any], rest.Filter]] = None, + filters: dict[str, Any] | rest.Filter | None = None, top_k: int = 10, scale_score: bool = False, return_embedding: bool = False, - score_threshold: Optional[float] = None, - group_by: Optional[str] = None, - group_size: Optional[int] = None, + score_threshold: float | None = None, + group_by: str | None = None, + group_size: int | None = None, ) -> list[Document]: """ Asynchronously queries Qdrant using a sparse embedding and returns the most relevant documents. @@ -1351,13 +1351,13 @@ async def _query_by_sparse_async( async def _query_by_embedding_async( self, query_embedding: list[float], - filters: Optional[Union[dict[str, Any], rest.Filter]] = None, + filters: dict[str, Any] | rest.Filter | None = None, top_k: int = 10, scale_score: bool = False, return_embedding: bool = False, - score_threshold: Optional[float] = None, - group_by: Optional[str] = None, - group_size: Optional[int] = None, + score_threshold: float | None = None, + group_by: str | None = None, + group_size: int | None = None, ) -> list[Document]: """ Asynchronously queries Qdrant using a dense embedding and returns the most relevant documents. @@ -1413,12 +1413,12 @@ async def _query_hybrid_async( self, query_embedding: list[float], query_sparse_embedding: SparseEmbedding, - filters: Optional[Union[dict[str, Any], rest.Filter]] = None, + filters: dict[str, Any] | rest.Filter | None = None, top_k: int = 10, return_embedding: bool = False, - score_threshold: Optional[float] = None, - group_by: Optional[str] = None, - group_size: Optional[int] = None, + score_threshold: float | None = None, + group_by: str | None = None, + group_size: int | None = None, ) -> list[Document]: """ Asynchronously retrieves documents based on dense and sparse embeddings and fuses @@ -1543,7 +1543,7 @@ def get_distance(self, similarity: str) -> rest.Distance: ) raise QdrantStoreError(msg) from ke - def _create_payload_index(self, collection_name: str, payload_fields_to_index: Optional[list[dict]] = None) -> None: + def _create_payload_index(self, collection_name: str, payload_fields_to_index: list[dict] | None = None) -> None: """ Create payload index for the collection if payload_fields_to_index is provided. @@ -1562,7 +1562,7 @@ def _create_payload_index(self, collection_name: str, payload_fields_to_index: O ) async def _create_payload_index_async( - self, collection_name: str, payload_fields_to_index: Optional[list[dict]] = None + self, collection_name: str, payload_fields_to_index: list[dict] | None = None ) -> None: """ Asynchronously create payload index for the collection if payload_fields_to_index is provided. @@ -1590,7 +1590,7 @@ def _set_up_collection( use_sparse_embeddings: bool, sparse_idf: bool, on_disk: bool = False, - payload_fields_to_index: Optional[list[dict]] = None, + payload_fields_to_index: list[dict] | None = None, ) -> None: """ Sets up the Qdrant collection with the specified parameters. @@ -1647,7 +1647,7 @@ async def _set_up_collection_async( use_sparse_embeddings: bool, sparse_idf: bool, on_disk: bool = False, - payload_fields_to_index: Optional[list[dict]] = None, + payload_fields_to_index: list[dict] | None = None, ) -> None: """ Asynchronously sets up the Qdrant collection with the specified parameters. @@ -1700,8 +1700,8 @@ def recreate_collection( collection_name: str, distance: rest.Distance, embedding_dim: int, - on_disk: Optional[bool] = None, - use_sparse_embeddings: Optional[bool] = None, + on_disk: bool | None = None, + use_sparse_embeddings: bool | None = None, sparse_idf: bool = False, ) -> None: """ @@ -1743,8 +1743,8 @@ async def recreate_collection_async( collection_name: str, distance: rest.Distance, embedding_dim: int, - on_disk: Optional[bool] = None, - use_sparse_embeddings: Optional[bool] = None, + on_disk: bool | None = None, + use_sparse_embeddings: bool | None = None, sparse_idf: bool = False, ) -> None: """ @@ -1784,7 +1784,7 @@ async def recreate_collection_async( def _handle_duplicate_documents( self, documents: list[Document], - policy: Optional[DuplicatePolicy] = None, + policy: DuplicatePolicy | None = None, ) -> list[Document]: """ Checks whether any of the passed documents is already existing in the chosen index and returns a list of @@ -1811,7 +1811,7 @@ def _handle_duplicate_documents( async def _handle_duplicate_documents_async( self, documents: list[Document], - policy: Optional[DuplicatePolicy] = None, + policy: DuplicatePolicy | None = None, ) -> list[Document]: """ Asynchronously checks whether any of the passed documents is already existing @@ -1900,10 +1900,10 @@ def _prepare_collection_config( self, embedding_dim: int, distance: rest.Distance, - on_disk: Optional[bool] = None, - use_sparse_embeddings: Optional[bool] = None, + on_disk: bool | None = None, + use_sparse_embeddings: bool | None = None, sparse_idf: bool = False, - ) -> tuple[Union[dict[str, rest.VectorParams], rest.VectorParams], Optional[dict[str, rest.SparseVectorParams]]]: + ) -> tuple[dict[str, rest.VectorParams] | rest.VectorParams, dict[str, rest.SparseVectorParams] | None]: """ Prepares the configuration for creating or recreating a Qdrant collection. @@ -1916,9 +1916,9 @@ def _prepare_collection_config( # dense vectors configuration base_vectors_config = rest.VectorParams(size=embedding_dim, on_disk=on_disk, distance=distance) - vectors_config: Union[rest.VectorParams, dict[str, rest.VectorParams]] = base_vectors_config + vectors_config: rest.VectorParams | dict[str, rest.VectorParams] = base_vectors_config - sparse_vectors_config: Optional[dict[str, rest.SparseVectorParams]] = None + sparse_vectors_config: dict[str, rest.SparseVectorParams] | None = None if use_sparse_embeddings: # in this case, we need to define named vectors @@ -1936,7 +1936,7 @@ def _prepare_collection_config( return vectors_config, sparse_vectors_config @staticmethod - def _validate_filters(filters: Optional[Union[dict[str, Any], rest.Filter]] = None) -> None: + def _validate_filters(filters: dict[str, Any] | rest.Filter | None = None) -> None: """ Validates the filters provided for querying. diff --git a/integrations/qdrant/src/haystack_integrations/document_stores/qdrant/filters.py b/integrations/qdrant/src/haystack_integrations/document_stores/qdrant/filters.py index 345911aab0..44f1c8e36b 100644 --- a/integrations/qdrant/src/haystack_integrations/document_stores/qdrant/filters.py +++ b/integrations/qdrant/src/haystack_integrations/document_stores/qdrant/filters.py @@ -1,13 +1,14 @@ +from collections.abc import Callable from datetime import datetime -from typing import Any, Callable, Optional, Union +from typing import Any from haystack.utils.filters import COMPARISON_OPERATORS, LOGICAL_OPERATORS, FilterError from qdrant_client.http import models def convert_filters_to_qdrant( - filter_term: Optional[Union[list[dict[str, Any]], dict[str, Any], models.Filter]] = None, -) -> Optional[models.Filter]: + filter_term: list[dict[str, Any]] | dict[str, Any] | models.Filter | None = None, +) -> models.Filter | None: """Converts Haystack filters to the format used by Qdrant. :param filter_term: the haystack filter to be converted to qdrant. @@ -52,7 +53,7 @@ def _process_filter_items(filter_items: list[dict[str, Any]]) -> list[models.Con return all_conditions -def _process_logical_operator(item: dict[str, Any]) -> Optional[models.Condition]: +def _process_logical_operator(item: dict[str, Any]) -> models.Condition | None: """Process a logical operator (AND, OR, NOT) and return the corresponding condition.""" operator = item["operator"] conditions = item.get("conditions") @@ -78,7 +79,7 @@ def _process_logical_operator(item: dict[str, Any]) -> Optional[models.Condition return None -def _process_comparison_operator(item: dict[str, Any]) -> Optional[models.Condition]: +def _process_comparison_operator(item: dict[str, Any]) -> models.Condition | None: """Process a comparison operator and return the corresponding condition.""" operator = item["operator"] field = item.get("field") @@ -91,7 +92,7 @@ def _process_comparison_operator(item: dict[str, Any]) -> Optional[models.Condit return _build_comparison_condition(operator, field, value) -def _build_final_filter(conditions: list[models.Condition]) -> Optional[models.Filter]: +def _build_final_filter(conditions: list[models.Condition]) -> models.Filter | None: """Build the final filter from a list of conditions.""" if not conditions: return None @@ -178,7 +179,7 @@ def _build_nin_condition(key: str, value: list[models.ValueVariants]) -> models. ) -def _build_lt_condition(key: str, value: Union[str, float, int]) -> models.Condition: +def _build_lt_condition(key: str, value: str | float | int) -> models.Condition: if isinstance(value, str) and is_datetime_string(value): dt_value = datetime.fromisoformat(value) return models.FieldCondition(key=key, range=models.DatetimeRange(lt=dt_value)) @@ -190,7 +191,7 @@ def _build_lt_condition(key: str, value: Union[str, float, int]) -> models.Condi raise FilterError(msg) -def _build_lte_condition(key: str, value: Union[str, float, int]) -> models.Condition: +def _build_lte_condition(key: str, value: str | float | int) -> models.Condition: if isinstance(value, str) and is_datetime_string(value): dt_value = datetime.fromisoformat(value) return models.FieldCondition(key=key, range=models.DatetimeRange(lte=dt_value)) @@ -202,7 +203,7 @@ def _build_lte_condition(key: str, value: Union[str, float, int]) -> models.Cond raise FilterError(msg) -def _build_gt_condition(key: str, value: Union[str, float, int]) -> models.Condition: +def _build_gt_condition(key: str, value: str | float | int) -> models.Condition: if isinstance(value, str) and is_datetime_string(value): dt_value = datetime.fromisoformat(value) return models.FieldCondition(key=key, range=models.DatetimeRange(gt=dt_value)) @@ -214,7 +215,7 @@ def _build_gt_condition(key: str, value: Union[str, float, int]) -> models.Condi raise FilterError(msg) -def _build_gte_condition(key: str, value: Union[str, float, int]) -> models.Condition: +def _build_gte_condition(key: str, value: str | float | int) -> models.Condition: if isinstance(value, str) and is_datetime_string(value): dt_value = datetime.fromisoformat(value) return models.FieldCondition(key=key, range=models.DatetimeRange(gte=dt_value))