From 5327bc9ec4644197c0adc4d02b7fbec0dda3b8fd Mon Sep 17 00:00:00 2001 From: Erick Friis Date: Thu, 28 Mar 2024 08:54:57 -0700 Subject: [PATCH] elasticsearch[patch]: move to repo (#19620) --- libs/partners/elasticsearch/LICENSE | 21 - libs/partners/elasticsearch/Makefile | 60 - libs/partners/elasticsearch/README.md | 80 +- .../langchain_elasticsearch/__init__.py | 19 - .../langchain_elasticsearch/_utilities.py | 108 -- .../langchain_elasticsearch/chat_history.py | 154 -- .../langchain_elasticsearch/client.py | 40 - .../langchain_elasticsearch/embeddings.py | 208 -- .../langchain_elasticsearch/py.typed | 0 .../langchain_elasticsearch/retrievers.py | 98 - .../langchain_elasticsearch/vectorstores.py | 1286 ------------- libs/partners/elasticsearch/poetry.lock | 1672 ----------------- libs/partners/elasticsearch/pyproject.toml | 96 - .../elasticsearch/scripts/check_imports.py | 17 - .../elasticsearch/scripts/check_pydantic.sh | 27 - .../elasticsearch/scripts/lint_imports.sh | 17 - libs/partners/elasticsearch/tests/__init__.py | 0 .../elasticsearch/tests/fake_embeddings.py | 55 - .../tests/integration_tests/__init__.py | 0 .../integration_tests/_test_utilities.py | 42 - .../integration_tests/docker-compose.yml | 35 - .../integration_tests/test_chat_history.py | 89 - .../tests/integration_tests/test_compile.py | 7 - .../integration_tests/test_embeddings.py | 48 - .../integration_tests/test_retrievers.py | 178 -- .../integration_tests/test_vectorstores.py | 929 --------- .../tests/unit_tests/__init__.py | 0 .../tests/unit_tests/test_imports.py | 15 - .../tests/unit_tests/test_vectorstores.py | 34 - 29 files changed, 2 insertions(+), 5333 deletions(-) delete mode 100644 libs/partners/elasticsearch/LICENSE delete mode 100644 libs/partners/elasticsearch/Makefile delete mode 100644 libs/partners/elasticsearch/langchain_elasticsearch/__init__.py delete mode 100644 libs/partners/elasticsearch/langchain_elasticsearch/_utilities.py delete mode 100644 libs/partners/elasticsearch/langchain_elasticsearch/chat_history.py delete mode 100644 libs/partners/elasticsearch/langchain_elasticsearch/client.py delete mode 100644 libs/partners/elasticsearch/langchain_elasticsearch/embeddings.py delete mode 100644 libs/partners/elasticsearch/langchain_elasticsearch/py.typed delete mode 100644 libs/partners/elasticsearch/langchain_elasticsearch/retrievers.py delete mode 100644 libs/partners/elasticsearch/langchain_elasticsearch/vectorstores.py delete mode 100644 libs/partners/elasticsearch/poetry.lock delete mode 100644 libs/partners/elasticsearch/pyproject.toml delete mode 100644 libs/partners/elasticsearch/scripts/check_imports.py delete mode 100755 libs/partners/elasticsearch/scripts/check_pydantic.sh delete mode 100755 libs/partners/elasticsearch/scripts/lint_imports.sh delete mode 100644 libs/partners/elasticsearch/tests/__init__.py delete mode 100644 libs/partners/elasticsearch/tests/fake_embeddings.py delete mode 100644 libs/partners/elasticsearch/tests/integration_tests/__init__.py delete mode 100644 libs/partners/elasticsearch/tests/integration_tests/_test_utilities.py delete mode 100644 libs/partners/elasticsearch/tests/integration_tests/docker-compose.yml delete mode 100644 libs/partners/elasticsearch/tests/integration_tests/test_chat_history.py delete mode 100644 libs/partners/elasticsearch/tests/integration_tests/test_compile.py delete mode 100644 libs/partners/elasticsearch/tests/integration_tests/test_embeddings.py delete mode 100644 libs/partners/elasticsearch/tests/integration_tests/test_retrievers.py delete mode 100644 libs/partners/elasticsearch/tests/integration_tests/test_vectorstores.py delete mode 100644 libs/partners/elasticsearch/tests/unit_tests/__init__.py delete mode 100644 libs/partners/elasticsearch/tests/unit_tests/test_imports.py delete mode 100644 libs/partners/elasticsearch/tests/unit_tests/test_vectorstores.py diff --git a/libs/partners/elasticsearch/LICENSE b/libs/partners/elasticsearch/LICENSE deleted file mode 100644 index fc0602feec..0000000000 --- a/libs/partners/elasticsearch/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2024 LangChain, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/libs/partners/elasticsearch/Makefile b/libs/partners/elasticsearch/Makefile deleted file mode 100644 index 9ada9f6fc7..0000000000 --- a/libs/partners/elasticsearch/Makefile +++ /dev/null @@ -1,60 +0,0 @@ -.PHONY: all format lint test tests integration_tests docker_tests help extended_tests - -# Default target executed when no arguments are given to make. -all: help - -install: - poetry install - -# Define a variable for the test file path. -TEST_FILE ?= tests/unit_tests/ -integration_test integration_tests: TEST_FILE=tests/integration_tests/ - -test tests integration_test integration_tests: - poetry run pytest $(TEST_FILE) - - -###################### -# LINTING AND FORMATTING -###################### - -# Define a variable for Python and notebook files. -PYTHON_FILES=. -MYPY_CACHE=.mypy_cache -lint format: PYTHON_FILES=. -lint_diff format_diff: PYTHON_FILES=$(shell git diff --relative=libs/partners/elasticsearch --name-only --diff-filter=d master | grep -E '\.py$$|\.ipynb$$') -lint_package: PYTHON_FILES=langchain_elasticsearch -lint_tests: PYTHON_FILES=tests -lint_tests: MYPY_CACHE=.mypy_cache_test - -lint lint_diff lint_package lint_tests: - poetry run ruff . - poetry run ruff format $(PYTHON_FILES) --diff - poetry run ruff --select I $(PYTHON_FILES) - mkdir $(MYPY_CACHE); poetry run mypy $(PYTHON_FILES) --cache-dir $(MYPY_CACHE) - -format format_diff: - poetry run ruff format $(PYTHON_FILES) - poetry run ruff --select I --fix $(PYTHON_FILES) - -spell_check: - poetry run codespell --toml pyproject.toml - -spell_fix: - poetry run codespell --toml pyproject.toml -w - -check_imports: $(shell find langchain_elasticsearch -name '*.py') - poetry run python ./scripts/check_imports.py $^ - -###################### -# HELP -###################### - -help: - @echo '----' - @echo 'check_imports - check imports' - @echo 'format - run code formatters' - @echo 'lint - run linters' - @echo 'test - run unit tests' - @echo 'tests - run unit tests' - @echo 'test TEST_FILE= - run all tests in file' diff --git a/libs/partners/elasticsearch/README.md b/libs/partners/elasticsearch/README.md index 77b4047e40..8bcc4cdbb4 100644 --- a/libs/partners/elasticsearch/README.md +++ b/libs/partners/elasticsearch/README.md @@ -1,81 +1,5 @@ # langchain-elasticsearch -This package contains the LangChain integration with Elasticsearch. +This package has moved! -## Installation - -```bash -pip install -U langchain-elasticsearch -``` - -## Elasticsearch setup - -### Elastic Cloud - -You need a running Elasticsearch deployment. The easiest way to start one is through [Elastic Cloud](https://cloud.elastic.co/). -You can sign up for a [free trial](https://www.elastic.co/cloud/cloud-trial-overview). - -1. [Create a deployment](https://www.elastic.co/guide/en/cloud/current/ec-create-deployment.html) -2. Get your Cloud ID: - 1. In the [Elastic Cloud console](https://cloud.elastic.co), click "Manage" next to your deployment - 2. Copy the Cloud ID and paste it into the `es_cloud_id` parameter below -3. Create an API key: - 1. In the [Elastic Cloud console](https://cloud.elastic.co), click "Open" next to your deployment - 2. In the left-hand side menu, go to "Stack Management", then to "API Keys" - 3. Click "Create API key" - 4. Enter a name for the API key and click "Create" - 5. Copy the API key and paste it into the `es_api_key` parameter below - -### Elastic Cloud - -Alternatively, you can run Elasticsearch via Docker as described in the [docs](https://python.langchain.com/docs/integrations/vectorstores/elasticsearch). - -## Usage - -### ElasticsearchStore - -The `ElasticsearchStore` class exposes Elasticsearch as a vector store. - -```python -from langchain_elasticsearch import ElasticsearchStore - -embeddings = ... # use a LangChain Embeddings class or ElasticsearchEmbeddings - -vectorstore = ElasticsearchStore( - es_cloud_id="your-cloud-id", - es_api_key="your-api-key", - index_name="your-index-name", - embeddings=embeddings, -) -``` - -### ElasticsearchEmbeddings - -The `ElasticsearchEmbeddings` class provides an interface to generate embeddings using a model -deployed in an Elasticsearch cluster. - -```python -from langchain_elasticsearch import ElasticsearchEmbeddings - -embeddings = ElasticsearchEmbeddings.from_credentials( - model_id="your-model-id", - input_field="your-input-field", - es_cloud_id="your-cloud-id", - es_api_key="your-api-key", -) -``` - -### ElasticsearchChatMessageHistory - -The `ElasticsearchChatMessageHistory` class stores chat histories in Elasticsearch. - -```python -from langchain_elasticsearch import ElasticsearchChatMessageHistory - -chat_history = ElasticsearchChatMessageHistory( - index="your-index-name", - session_id="your-session-id", - es_cloud_id="your-cloud-id", - es_api_key="your-api-key", -) -``` +https://github.com/langchain-ai/langchain-elastic/tree/main/libs/elasticsearch diff --git a/libs/partners/elasticsearch/langchain_elasticsearch/__init__.py b/libs/partners/elasticsearch/langchain_elasticsearch/__init__.py deleted file mode 100644 index d98781bc9a..0000000000 --- a/libs/partners/elasticsearch/langchain_elasticsearch/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -from langchain_elasticsearch.chat_history import ElasticsearchChatMessageHistory -from langchain_elasticsearch.embeddings import ElasticsearchEmbeddings -from langchain_elasticsearch.retrievers import ElasticsearchRetriever -from langchain_elasticsearch.vectorstores import ( - ApproxRetrievalStrategy, - ElasticsearchStore, - ExactRetrievalStrategy, - SparseRetrievalStrategy, -) - -__all__ = [ - "ApproxRetrievalStrategy", - "ElasticsearchChatMessageHistory", - "ElasticsearchEmbeddings", - "ElasticsearchRetriever", - "ElasticsearchStore", - "ExactRetrievalStrategy", - "SparseRetrievalStrategy", -] diff --git a/libs/partners/elasticsearch/langchain_elasticsearch/_utilities.py b/libs/partners/elasticsearch/langchain_elasticsearch/_utilities.py deleted file mode 100644 index 33b302241e..0000000000 --- a/libs/partners/elasticsearch/langchain_elasticsearch/_utilities.py +++ /dev/null @@ -1,108 +0,0 @@ -from enum import Enum -from typing import List, Union - -import numpy as np -from elasticsearch import BadRequestError, ConflictError, Elasticsearch, NotFoundError -from langchain_core import __version__ as langchain_version - -Matrix = Union[List[List[float]], List[np.ndarray], np.ndarray] - - -class DistanceStrategy(str, Enum): - """Enumerator of the Distance strategies for calculating distances - between vectors.""" - - EUCLIDEAN_DISTANCE = "EUCLIDEAN_DISTANCE" - MAX_INNER_PRODUCT = "MAX_INNER_PRODUCT" - DOT_PRODUCT = "DOT_PRODUCT" - JACCARD = "JACCARD" - COSINE = "COSINE" - - -def with_user_agent_header(client: Elasticsearch, header_prefix: str) -> Elasticsearch: - headers = dict(client._headers) - headers.update({"user-agent": f"{header_prefix}/{langchain_version}"}) - return client.options(headers=headers) - - -def maximal_marginal_relevance( - query_embedding: np.ndarray, - embedding_list: list, - lambda_mult: float = 0.5, - k: int = 4, -) -> List[int]: - """Calculate maximal marginal relevance.""" - if min(k, len(embedding_list)) <= 0: - return [] - if query_embedding.ndim == 1: - query_embedding = np.expand_dims(query_embedding, axis=0) - similarity_to_query = cosine_similarity(query_embedding, embedding_list)[0] - most_similar = int(np.argmax(similarity_to_query)) - idxs = [most_similar] - selected = np.array([embedding_list[most_similar]]) - while len(idxs) < min(k, len(embedding_list)): - best_score = -np.inf - idx_to_add = -1 - similarity_to_selected = cosine_similarity(embedding_list, selected) - for i, query_score in enumerate(similarity_to_query): - if i in idxs: - continue - redundant_score = max(similarity_to_selected[i]) - equation_score = ( - lambda_mult * query_score - (1 - lambda_mult) * redundant_score - ) - if equation_score > best_score: - best_score = equation_score - idx_to_add = i - idxs.append(idx_to_add) - selected = np.append(selected, [embedding_list[idx_to_add]], axis=0) - return idxs - - -def cosine_similarity(X: Matrix, Y: Matrix) -> np.ndarray: - """Row-wise cosine similarity between two equal-width matrices.""" - if len(X) == 0 or len(Y) == 0: - return np.array([]) - - X = np.array(X) - Y = np.array(Y) - if X.shape[1] != Y.shape[1]: - raise ValueError( - f"Number of columns in X and Y must be the same. X has shape {X.shape} " - f"and Y has shape {Y.shape}." - ) - try: - import simsimd as simd # type: ignore - - X = np.array(X, dtype=np.float32) - Y = np.array(Y, dtype=np.float32) - Z = 1 - simd.cdist(X, Y, metric="cosine") - if isinstance(Z, float): - return np.array([Z]) - return np.array(Z) - except ImportError: - X_norm = np.linalg.norm(X, axis=1) - Y_norm = np.linalg.norm(Y, axis=1) - # Ignore divide by zero errors run time warnings as those are handled below. - with np.errstate(divide="ignore", invalid="ignore"): - similarity = np.dot(X, Y.T) / np.outer(X_norm, Y_norm) - similarity[np.isnan(similarity) | np.isinf(similarity)] = 0.0 - return similarity - - -def check_if_model_deployed(client: Elasticsearch, model_id: str) -> None: - try: - dummy = {"x": "y"} - client.ml.infer_trained_model(model_id=model_id, docs=[dummy]) - except NotFoundError as err: - raise err - except ConflictError as err: - raise NotFoundError( - f"model '{model_id}' not found, please deploy it first", - meta=err.meta, - body=err.body, - ) from err - except BadRequestError: - # This error is expected because we do not know the expected document - # shape and just use a dummy doc above. - pass diff --git a/libs/partners/elasticsearch/langchain_elasticsearch/chat_history.py b/libs/partners/elasticsearch/langchain_elasticsearch/chat_history.py deleted file mode 100644 index 5d75beae50..0000000000 --- a/libs/partners/elasticsearch/langchain_elasticsearch/chat_history.py +++ /dev/null @@ -1,154 +0,0 @@ -import json -import logging -from time import time -from typing import TYPE_CHECKING, List, Optional - -from langchain_core.chat_history import BaseChatMessageHistory -from langchain_core.messages import ( - BaseMessage, - message_to_dict, - messages_from_dict, -) - -from langchain_elasticsearch._utilities import with_user_agent_header -from langchain_elasticsearch.client import create_elasticsearch_client - -if TYPE_CHECKING: - from elasticsearch import Elasticsearch - -logger = logging.getLogger(__name__) - - -class ElasticsearchChatMessageHistory(BaseChatMessageHistory): - """Chat message history that stores history in Elasticsearch. - - Args: - es_url: URL of the Elasticsearch instance to connect to. - es_cloud_id: Cloud ID of the Elasticsearch instance to connect to. - es_user: Username to use when connecting to Elasticsearch. - es_password: Password to use when connecting to Elasticsearch. - es_api_key: API key to use when connecting to Elasticsearch. - es_connection: Optional pre-existing Elasticsearch connection. - esnsure_ascii: Used to escape ASCII symbols in json.dumps. Defaults to True. - index: Name of the index to use. - session_id: Arbitrary key that is used to store the messages - of a single chat session. - """ - - def __init__( - self, - index: str, - session_id: str, - *, - es_connection: Optional["Elasticsearch"] = None, - es_url: Optional[str] = None, - es_cloud_id: Optional[str] = None, - es_user: Optional[str] = None, - es_api_key: Optional[str] = None, - es_password: Optional[str] = None, - esnsure_ascii: Optional[bool] = True, - ): - self.index: str = index - self.session_id: str = session_id - self.ensure_ascii = esnsure_ascii - - # Initialize Elasticsearch client from passed client arg or connection info - if es_connection is not None: - self.client = es_connection - elif es_url is not None or es_cloud_id is not None: - try: - self.client = create_elasticsearch_client( - url=es_url, - username=es_user, - password=es_password, - cloud_id=es_cloud_id, - api_key=es_api_key, - ) - except Exception as err: - logger.error(f"Error connecting to Elasticsearch: {err}") - raise err - else: - raise ValueError( - """Either provide a pre-existing Elasticsearch connection, \ - or valid credentials for creating a new connection.""" - ) - - self.client = with_user_agent_header(self.client, "langchain-py-ms") - - if self.client.indices.exists(index=index): - logger.debug( - f"Chat history index {index} already exists, skipping creation." - ) - else: - logger.debug(f"Creating index {index} for storing chat history.") - - self.client.indices.create( - index=index, - mappings={ - "properties": { - "session_id": {"type": "keyword"}, - "created_at": {"type": "date"}, - "history": {"type": "text"}, - } - }, - ) - - @property - def messages(self) -> List[BaseMessage]: # type: ignore[override] - """Retrieve the messages from Elasticsearch""" - try: - from elasticsearch import ApiError - - result = self.client.search( - index=self.index, - query={"term": {"session_id": self.session_id}}, - sort="created_at:asc", - ) - except ApiError as err: - logger.error(f"Could not retrieve messages from Elasticsearch: {err}") - raise err - - if result and len(result["hits"]["hits"]) > 0: - items = [ - json.loads(document["_source"]["history"]) - for document in result["hits"]["hits"] - ] - else: - items = [] - - return messages_from_dict(items) - - def add_message(self, message: BaseMessage) -> None: - """Add a message to the chat session in Elasticsearch""" - try: - from elasticsearch import ApiError - - self.client.index( - index=self.index, - document={ - "session_id": self.session_id, - "created_at": round(time() * 1000), - "history": json.dumps( - message_to_dict(message), - ensure_ascii=bool(self.ensure_ascii), - ), - }, - refresh=True, - ) - except ApiError as err: - logger.error(f"Could not add message to Elasticsearch: {err}") - raise err - - def clear(self) -> None: - """Clear session memory in Elasticsearch""" - try: - from elasticsearch import ApiError - - self.client.delete_by_query( - index=self.index, - query={"term": {"session_id": self.session_id}}, - refresh=True, - ) - except ApiError as err: - logger.error(f"Could not clear session memory in Elasticsearch: {err}") - raise err diff --git a/libs/partners/elasticsearch/langchain_elasticsearch/client.py b/libs/partners/elasticsearch/langchain_elasticsearch/client.py deleted file mode 100644 index 3e4b546081..0000000000 --- a/libs/partners/elasticsearch/langchain_elasticsearch/client.py +++ /dev/null @@ -1,40 +0,0 @@ -from typing import Any, Dict, Optional - -from elasticsearch import Elasticsearch - - -def create_elasticsearch_client( - url: Optional[str] = None, - cloud_id: Optional[str] = None, - api_key: Optional[str] = None, - username: Optional[str] = None, - password: Optional[str] = None, - params: Optional[Dict[str, Any]] = None, -) -> Elasticsearch: - if url and cloud_id: - raise ValueError( - "Both es_url and cloud_id are defined. Please provide only one." - ) - - connection_params: Dict[str, Any] = {} - - if url: - connection_params["hosts"] = [url] - elif cloud_id: - connection_params["cloud_id"] = cloud_id - else: - raise ValueError("Please provide either elasticsearch_url or cloud_id.") - - if api_key: - connection_params["api_key"] = api_key - elif username and password: - connection_params["basic_auth"] = (username, password) - - if params is not None: - connection_params.update(params) - - es_client = Elasticsearch(**connection_params) - - es_client.info() # test connection - - return es_client diff --git a/libs/partners/elasticsearch/langchain_elasticsearch/embeddings.py b/libs/partners/elasticsearch/langchain_elasticsearch/embeddings.py deleted file mode 100644 index 50e8705b17..0000000000 --- a/libs/partners/elasticsearch/langchain_elasticsearch/embeddings.py +++ /dev/null @@ -1,208 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING, List, Optional - -from elasticsearch import Elasticsearch -from langchain_core.embeddings import Embeddings -from langchain_core.utils import get_from_env - -if TYPE_CHECKING: - from elasticsearch.client import MlClient - - -class ElasticsearchEmbeddings(Embeddings): - """Elasticsearch embedding models. - - This class provides an interface to generate embeddings using a model deployed - in an Elasticsearch cluster. It requires an Elasticsearch connection object - and the model_id of the model deployed in the cluster. - - In Elasticsearch you need to have an embedding model loaded and deployed. - - https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-trained-model.html - - https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-deploy-models.html - """ # noqa: E501 - - def __init__( - self, - client: MlClient, - model_id: str, - *, - input_field: str = "text_field", - ): - """ - Initialize the ElasticsearchEmbeddings instance. - - Args: - client (MlClient): An Elasticsearch ML client object. - model_id (str): The model_id of the model deployed in the Elasticsearch - cluster. - input_field (str): The name of the key for the input text field in the - document. Defaults to 'text_field'. - """ - self.client = client - self.model_id = model_id - self.input_field = input_field - - @classmethod - def from_credentials( - cls, - model_id: str, - *, - es_cloud_id: Optional[str] = None, - es_api_key: Optional[str] = None, - input_field: str = "text_field", - ) -> ElasticsearchEmbeddings: - """Instantiate embeddings from Elasticsearch credentials. - - Args: - model_id (str): The model_id of the model deployed in the Elasticsearch - cluster. - input_field (str): The name of the key for the input text field in the - document. Defaults to 'text_field'. - es_cloud_id: (str, optional): The Elasticsearch cloud ID to connect to. - es_user: (str, optional): Elasticsearch username. - es_password: (str, optional): Elasticsearch password. - - Example: - .. code-block:: python - - from langchain_elasticserach.embeddings import ElasticsearchEmbeddings - - # Define the model ID and input field name (if different from default) - model_id = "your_model_id" - # Optional, only if different from 'text_field' - input_field = "your_input_field" - - # Credentials can be passed in two ways. Either set the env vars - # ES_CLOUD_ID, ES_USER, ES_PASSWORD and they will be automatically - # pulled in, or pass them in directly as kwargs. - embeddings = ElasticsearchEmbeddings.from_credentials( - model_id, - input_field=input_field, - # es_cloud_id="foo", - # es_user="bar", - # es_password="baz", - ) - - documents = [ - "This is an example document.", - "Another example document to generate embeddings for.", - ] - embeddings_generator.embed_documents(documents) - """ - from elasticsearch.client import MlClient - - es_cloud_id = es_cloud_id or get_from_env("es_cloud_id", "ES_CLOUD_ID") - es_api_key = es_api_key or get_from_env("es_api_key", "ES_API_KEY") - - # Connect to Elasticsearch - es_connection = Elasticsearch(cloud_id=es_cloud_id, api_key=es_api_key) - client = MlClient(es_connection) - return cls(client, model_id, input_field=input_field) - - @classmethod - def from_es_connection( - cls, - model_id: str, - es_connection: Elasticsearch, - input_field: str = "text_field", - ) -> ElasticsearchEmbeddings: - """ - Instantiate embeddings from an existing Elasticsearch connection. - - This method provides a way to create an instance of the ElasticsearchEmbeddings - class using an existing Elasticsearch connection. The connection object is used - to create an MlClient, which is then used to initialize the - ElasticsearchEmbeddings instance. - - Args: - model_id (str): The model_id of the model deployed in the Elasticsearch cluster. - es_connection (elasticsearch.Elasticsearch): An existing Elasticsearch - connection object. input_field (str, optional): The name of the key for the - input text field in the document. Defaults to 'text_field'. - - Returns: - ElasticsearchEmbeddings: An instance of the ElasticsearchEmbeddings class. - - Example: - .. code-block:: python - - from elasticsearch import Elasticsearch - - from langchain_elasticsearch.embeddings import ElasticsearchEmbeddings - - # Define the model ID and input field name (if different from default) - model_id = "your_model_id" - # Optional, only if different from 'text_field' - input_field = "your_input_field" - - # Create Elasticsearch connection - es_connection = Elasticsearch( - hosts=["localhost:9200"], http_auth=("user", "password") - ) - - # Instantiate ElasticsearchEmbeddings using the existing connection - embeddings = ElasticsearchEmbeddings.from_es_connection( - model_id, - es_connection, - input_field=input_field, - ) - - documents = [ - "This is an example document.", - "Another example document to generate embeddings for.", - ] - embeddings_generator.embed_documents(documents) - """ - from elasticsearch.client import MlClient - - # Create an MlClient from the given Elasticsearch connection - client = MlClient(es_connection) - - # Return a new instance of the ElasticsearchEmbeddings class with - # the MlClient, model_id, and input_field - return cls(client, model_id, input_field=input_field) - - def _embedding_func(self, texts: List[str]) -> List[List[float]]: - """ - Generate embeddings for the given texts using the Elasticsearch model. - - Args: - texts (List[str]): A list of text strings to generate embeddings for. - - Returns: - List[List[float]]: A list of embeddings, one for each text in the input - list. - """ - response = self.client.infer_trained_model( - model_id=self.model_id, docs=[{self.input_field: text} for text in texts] - ) - - embeddings = [doc["predicted_value"] for doc in response["inference_results"]] - return embeddings - - def embed_documents(self, texts: List[str]) -> List[List[float]]: - """ - Generate embeddings for a list of documents. - - Args: - texts (List[str]): A list of document text strings to generate embeddings - for. - - Returns: - List[List[float]]: A list of embeddings, one for each document in the input - list. - """ - return self._embedding_func(texts) - - def embed_query(self, text: str) -> List[float]: - """ - Generate an embedding for a single query text. - - Args: - text (str): The query text to generate an embedding for. - - Returns: - List[float]: The embedding for the input query text. - """ - return self._embedding_func([text])[0] diff --git a/libs/partners/elasticsearch/langchain_elasticsearch/py.typed b/libs/partners/elasticsearch/langchain_elasticsearch/py.typed deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libs/partners/elasticsearch/langchain_elasticsearch/retrievers.py b/libs/partners/elasticsearch/langchain_elasticsearch/retrievers.py deleted file mode 100644 index 1e58e7c1aa..0000000000 --- a/libs/partners/elasticsearch/langchain_elasticsearch/retrievers.py +++ /dev/null @@ -1,98 +0,0 @@ -import logging -from typing import Any, Callable, Dict, List, Optional - -from elasticsearch import Elasticsearch -from langchain_core.callbacks import CallbackManagerForRetrieverRun -from langchain_core.documents import Document -from langchain_core.retrievers import BaseRetriever - -from langchain_elasticsearch._utilities import with_user_agent_header -from langchain_elasticsearch.client import create_elasticsearch_client - -logger = logging.getLogger(__name__) - - -class ElasticsearchRetriever(BaseRetriever): - """ - Elasticsearch retriever - - Args: - es_client: Elasticsearch client connection. Alternatively you can use the - `from_es_params` method with parameters to initialize the client. - index_name: The name of the index to query. - body_func: Function to create an Elasticsearch DSL query body from a search - string. The returned query body must fit what you would normally send in a - POST request the the _search endpoint. If applicable, it also includes - parameters the `size` parameter etc. - content_field: The document field name that contains the page content. - document_mapper: Function to map Elasticsearch hits to LangChain Documents. - """ - - es_client: Elasticsearch - index_name: str - body_func: Callable[[str], Dict] - content_field: Optional[str] = None - document_mapper: Optional[Callable[[Dict], Document]] = None - - def __init__(self, **kwargs: Any) -> None: - super().__init__(**kwargs) - - if self.content_field is None and self.document_mapper is None: - raise ValueError("One of content_field or document_mapper must be defined.") - if self.content_field is not None and self.document_mapper is not None: - raise ValueError( - "Both content_field and document_mapper are defined. " - "Please provide only one." - ) - - self.document_mapper = self.document_mapper or self._field_mapper - self.es_client = with_user_agent_header(self.es_client, "langchain-py-r") - - @staticmethod - def from_es_params( - index_name: str, - body_func: Callable[[str], Dict], - content_field: Optional[str] = None, - document_mapper: Optional[Callable[[Dict], Document]] = None, - url: Optional[str] = None, - cloud_id: Optional[str] = None, - api_key: Optional[str] = None, - username: Optional[str] = None, - password: Optional[str] = None, - params: Optional[Dict[str, Any]] = None, - ) -> "ElasticsearchRetriever": - client = None - try: - client = create_elasticsearch_client( - url=url, - cloud_id=cloud_id, - api_key=api_key, - username=username, - password=password, - params=params, - ) - except Exception as err: - logger.error(f"Error connecting to Elasticsearch: {err}") - raise err - - return ElasticsearchRetriever( - es_client=client, - index_name=index_name, - body_func=body_func, - content_field=content_field, - document_mapper=document_mapper, - ) - - def _get_relevant_documents( - self, query: str, *, run_manager: CallbackManagerForRetrieverRun - ) -> List[Document]: - if not self.es_client or not self.document_mapper: - raise ValueError("faulty configuration") # should not happen - - body = self.body_func(query) - results = self.es_client.search(index=self.index_name, body=body) - return [self.document_mapper(hit) for hit in results["hits"]["hits"]] - - def _field_mapper(self, hit: Dict[str, Any]) -> Document: - content = hit["_source"].pop(self.content_field) - return Document(page_content=content, metadata=hit) diff --git a/libs/partners/elasticsearch/langchain_elasticsearch/vectorstores.py b/libs/partners/elasticsearch/langchain_elasticsearch/vectorstores.py deleted file mode 100644 index b3c0b5baf4..0000000000 --- a/libs/partners/elasticsearch/langchain_elasticsearch/vectorstores.py +++ /dev/null @@ -1,1286 +0,0 @@ -import logging -import uuid -from abc import ABC, abstractmethod -from typing import ( - Any, - Callable, - Dict, - Iterable, - List, - Literal, - Optional, - Tuple, - Union, -) - -import numpy as np -from elasticsearch import Elasticsearch -from elasticsearch.helpers import BulkIndexError, bulk -from langchain_core.documents import Document -from langchain_core.embeddings import Embeddings -from langchain_core.vectorstores import VectorStore - -from langchain_elasticsearch._utilities import ( - DistanceStrategy, - check_if_model_deployed, - maximal_marginal_relevance, - with_user_agent_header, -) - -logger = logging.getLogger(__name__) - - -class BaseRetrievalStrategy(ABC): - """Base class for `Elasticsearch` retrieval strategies.""" - - @abstractmethod - def query( - self, - query_vector: Union[List[float], None], - query: Union[str, None], - *, - k: int, - fetch_k: int, - vector_query_field: str, - text_field: str, - filter: List[dict], - similarity: Union[DistanceStrategy, None], - ) -> Dict: - """ - Executes when a search is performed on the store. - - Args: - query_vector: The query vector, - or None if not using vector-based query. - query: The text query, or None if not using text-based query. - k: The total number of results to retrieve. - fetch_k: The number of results to fetch initially. - vector_query_field: The field containing the vector - representations in the index. - text_field: The field containing the text data in the index. - filter: List of filter clauses to apply to the query. - similarity: The similarity strategy to use, or None if not using one. - - Returns: - Dict: The Elasticsearch query body. - """ - - @abstractmethod - def index( - self, - dims_length: Union[int, None], - vector_query_field: str, - similarity: Union[DistanceStrategy, None], - ) -> Dict: - """ - Executes when the index is created. - - Args: - dims_length: Numeric length of the embedding vectors, - or None if not using vector-based query. - vector_query_field: The field containing the vector - representations in the index. - similarity: The similarity strategy to use, - or None if not using one. - - Returns: - Dict: The Elasticsearch settings and mappings for the strategy. - """ - - def before_index_setup( - self, client: "Elasticsearch", text_field: str, vector_query_field: str - ) -> None: - """ - Executes before the index is created. Used for setting up - any required Elasticsearch resources like a pipeline. - - Args: - client: The Elasticsearch client. - text_field: The field containing the text data in the index. - vector_query_field: The field containing the vector - representations in the index. - """ - - def require_inference(self) -> bool: - """ - Returns whether or not the strategy requires inference - to be performed on the text before it is added to the index. - - Returns: - bool: Whether or not the strategy requires inference - to be performed on the text before it is added to the index. - """ - return True - - -class ApproxRetrievalStrategy(BaseRetrievalStrategy): - """Approximate retrieval strategy using the `HNSW` algorithm.""" - - def __init__( - self, - query_model_id: Optional[str] = None, - hybrid: Optional[bool] = False, - rrf: Optional[Union[dict, bool]] = True, - ): - self.query_model_id = query_model_id - self.hybrid = hybrid - - # RRF has two optional parameters - # 'rank_constant', 'window_size' - # https://www.elastic.co/guide/en/elasticsearch/reference/current/rrf.html - self.rrf = rrf - - def query( - self, - query_vector: Union[List[float], None], - query: Union[str, None], - k: int, - fetch_k: int, - vector_query_field: str, - text_field: str, - filter: List[dict], - similarity: Union[DistanceStrategy, None], - ) -> Dict: - knn = { - "filter": filter, - "field": vector_query_field, - "k": k, - "num_candidates": fetch_k, - } - - # Embedding provided via the embedding function - if query_vector and not self.query_model_id: - knn["query_vector"] = query_vector - - # Case 2: Used when model has been deployed to - # Elasticsearch and can infer the query vector from the query text - elif query and self.query_model_id: - knn["query_vector_builder"] = { - "text_embedding": { - "model_id": self.query_model_id, # use 'model_id' argument - "model_text": query, # use 'query' argument - } - } - - else: - raise ValueError( - "You must provide an embedding function or a" - " query_model_id to perform a similarity search." - ) - - # If hybrid, add a query to the knn query - # RRF is used to even the score from the knn query and text query - # RRF has two optional parameters: {'rank_constant':int, 'window_size':int} - # https://www.elastic.co/guide/en/elasticsearch/reference/current/rrf.html - if self.hybrid: - query_body = { - "knn": knn, - "query": { - "bool": { - "must": [ - { - "match": { - text_field: { - "query": query, - } - } - } - ], - "filter": filter, - } - }, - } - - if isinstance(self.rrf, dict): - query_body["rank"] = {"rrf": self.rrf} - elif isinstance(self.rrf, bool) and self.rrf is True: - query_body["rank"] = {"rrf": {}} - - return query_body - else: - return {"knn": knn} - - def before_index_setup( - self, client: "Elasticsearch", text_field: str, vector_query_field: str - ) -> None: - if self.query_model_id: - check_if_model_deployed(client, self.query_model_id) - - def index( - self, - dims_length: Union[int, None], - vector_query_field: str, - similarity: Union[DistanceStrategy, None], - ) -> Dict: - """Create the mapping for the Elasticsearch index.""" - - if similarity is DistanceStrategy.COSINE: - similarityAlgo = "cosine" - elif similarity is DistanceStrategy.EUCLIDEAN_DISTANCE: - similarityAlgo = "l2_norm" - elif similarity is DistanceStrategy.DOT_PRODUCT: - similarityAlgo = "dot_product" - elif similarity is DistanceStrategy.MAX_INNER_PRODUCT: - similarityAlgo = "max_inner_product" - else: - raise ValueError(f"Similarity {similarity} not supported.") - - return { - "mappings": { - "properties": { - vector_query_field: { - "type": "dense_vector", - "dims": dims_length, - "index": True, - "similarity": similarityAlgo, - }, - } - } - } - - -class ExactRetrievalStrategy(BaseRetrievalStrategy): - """Exact retrieval strategy using the `script_score` query.""" - - def query( - self, - query_vector: Union[List[float], None], - query: Union[str, None], - k: int, - fetch_k: int, - vector_query_field: str, - text_field: str, - filter: Union[List[dict], None], - similarity: Union[DistanceStrategy, None], - ) -> Dict: - if similarity is DistanceStrategy.COSINE: - similarityAlgo = ( - f"cosineSimilarity(params.query_vector, '{vector_query_field}') + 1.0" - ) - elif similarity is DistanceStrategy.EUCLIDEAN_DISTANCE: - similarityAlgo = ( - f"1 / (1 + l2norm(params.query_vector, '{vector_query_field}'))" - ) - elif similarity is DistanceStrategy.DOT_PRODUCT: - similarityAlgo = f""" - double value = dotProduct(params.query_vector, '{vector_query_field}'); - return sigmoid(1, Math.E, -value); - """ - else: - raise ValueError(f"Similarity {similarity} not supported.") - - queryBool: Dict = {"match_all": {}} - if filter: - queryBool = {"bool": {"filter": filter}} - - return { - "query": { - "script_score": { - "query": queryBool, - "script": { - "source": similarityAlgo, - "params": {"query_vector": query_vector}, - }, - }, - } - } - - def index( - self, - dims_length: Union[int, None], - vector_query_field: str, - similarity: Union[DistanceStrategy, None], - ) -> Dict: - """Create the mapping for the Elasticsearch index.""" - - return { - "mappings": { - "properties": { - vector_query_field: { - "type": "dense_vector", - "dims": dims_length, - "index": False, - }, - } - } - } - - -class SparseRetrievalStrategy(BaseRetrievalStrategy): - """Sparse retrieval strategy using the `text_expansion` processor.""" - - def __init__(self, model_id: Optional[str] = None): - self.model_id = model_id or ".elser_model_1" - - def query( - self, - query_vector: Union[List[float], None], - query: Union[str, None], - k: int, - fetch_k: int, - vector_query_field: str, - text_field: str, - filter: List[dict], - similarity: Union[DistanceStrategy, None], - ) -> Dict: - return { - "query": { - "bool": { - "must": [ - { - "text_expansion": { - f"{vector_query_field}.tokens": { - "model_id": self.model_id, - "model_text": query, - } - } - } - ], - "filter": filter, - } - } - } - - def _get_pipeline_name(self) -> str: - return f"{self.model_id}_sparse_embedding" - - def before_index_setup( - self, client: "Elasticsearch", text_field: str, vector_query_field: str - ) -> None: - if self.model_id: - check_if_model_deployed(client, self.model_id) - - # Create a pipeline for the model - client.ingest.put_pipeline( - id=self._get_pipeline_name(), - description="Embedding pipeline for langchain vectorstore", - processors=[ - { - "inference": { - "model_id": self.model_id, - "target_field": vector_query_field, - "field_map": {text_field: "text_field"}, - "inference_config": { - "text_expansion": {"results_field": "tokens"} - }, - } - } - ], - ) - - def index( - self, - dims_length: Union[int, None], - vector_query_field: str, - similarity: Union[DistanceStrategy, None], - ) -> Dict: - return { - "mappings": { - "properties": { - vector_query_field: { - "properties": {"tokens": {"type": "rank_features"}} - } - } - }, - "settings": {"default_pipeline": self._get_pipeline_name()}, - } - - def require_inference(self) -> bool: - return False - - -class ElasticsearchStore(VectorStore): - """`Elasticsearch` vector store. - - Example: - .. code-block:: python - - from langchain_elasticsearch.vectorstores import ElasticsearchStore - from langchain_openai import OpenAIEmbeddings - - vectorstore = ElasticsearchStore( - embedding=OpenAIEmbeddings(), - index_name="langchain-demo", - es_url="http://localhost:9200" - ) - - Args: - index_name: Name of the Elasticsearch index to create. - es_url: URL of the Elasticsearch instance to connect to. - cloud_id: Cloud ID of the Elasticsearch instance to connect to. - es_user: Username to use when connecting to Elasticsearch. - es_password: Password to use when connecting to Elasticsearch. - es_api_key: API key to use when connecting to Elasticsearch. - es_connection: Optional pre-existing Elasticsearch connection. - vector_query_field: Optional. Name of the field to store - the embedding vectors in. - query_field: Optional. Name of the field to store the texts in. - strategy: Optional. Retrieval strategy to use when searching the index. - Defaults to ApproxRetrievalStrategy. Can be one of - ExactRetrievalStrategy, ApproxRetrievalStrategy, - or SparseRetrievalStrategy. - distance_strategy: Optional. Distance strategy to use when - searching the index. - Defaults to COSINE. Can be one of COSINE, - EUCLIDEAN_DISTANCE, MAX_INNER_PRODUCT or DOT_PRODUCT. - - If you want to use a cloud hosted Elasticsearch instance, you can pass in the - cloud_id argument instead of the es_url argument. - - Example: - .. code-block:: python - - from langchain_elasticsearch.vectorstores import ElasticsearchStore - from langchain_openai import OpenAIEmbeddings - - vectorstore = ElasticsearchStore( - embedding=OpenAIEmbeddings(), - index_name="langchain-demo", - es_cloud_id="" - es_user="elastic", - es_password="" - ) - - You can also connect to an existing Elasticsearch instance by passing in a - pre-existing Elasticsearch connection via the es_connection argument. - - Example: - .. code-block:: python - - from langchain_elasticsearch.vectorstores import ElasticsearchStore - from langchain_openai import OpenAIEmbeddings - - from elasticsearch import Elasticsearch - - es_connection = Elasticsearch("http://localhost:9200") - - vectorstore = ElasticsearchStore( - embedding=OpenAIEmbeddings(), - index_name="langchain-demo", - es_connection=es_connection - ) - - ElasticsearchStore by default uses the ApproxRetrievalStrategy, which uses the - HNSW algorithm to perform approximate nearest neighbor search. This is the - fastest and most memory efficient algorithm. - - If you want to use the Brute force / Exact strategy for searching vectors, you - can pass in the ExactRetrievalStrategy to the ElasticsearchStore constructor. - - Example: - .. code-block:: python - - from langchain_elasticsearch.vectorstores import ElasticsearchStore - from langchain_openai import OpenAIEmbeddings - - vectorstore = ElasticsearchStore( - embedding=OpenAIEmbeddings(), - index_name="langchain-demo", - es_url="http://localhost:9200", - strategy=ElasticsearchStore.ExactRetrievalStrategy() - ) - - Both strategies require that you know the similarity metric you want to use - when creating the index. The default is cosine similarity, but you can also - use dot product or euclidean distance. - - Example: - .. code-block:: python - - from langchain_elasticsearch.vectorstores import ElasticsearchStore - from langchain_openai import OpenAIEmbeddings - from langchain_community.vectorstores.utils import DistanceStrategy - - vectorstore = ElasticsearchStore( - "langchain-demo", - embedding=OpenAIEmbeddings(), - es_url="http://localhost:9200", - distance_strategy="DOT_PRODUCT" - ) - - """ - - def __init__( - self, - index_name: str, - *, - embedding: Optional[Embeddings] = None, - es_connection: Optional["Elasticsearch"] = None, - es_url: Optional[str] = None, - es_cloud_id: Optional[str] = None, - es_user: Optional[str] = None, - es_api_key: Optional[str] = None, - es_password: Optional[str] = None, - vector_query_field: str = "vector", - query_field: str = "text", - distance_strategy: Optional[ - Literal[ - DistanceStrategy.COSINE, - DistanceStrategy.DOT_PRODUCT, - DistanceStrategy.EUCLIDEAN_DISTANCE, - DistanceStrategy.MAX_INNER_PRODUCT, - ] - ] = None, - strategy: BaseRetrievalStrategy = ApproxRetrievalStrategy(), - es_params: Optional[Dict[str, Any]] = None, - ): - self.embedding = embedding - self.index_name = index_name - self.query_field = query_field - self.vector_query_field = vector_query_field - self.distance_strategy = ( - DistanceStrategy.COSINE - if distance_strategy is None - else DistanceStrategy[distance_strategy] - ) - self.strategy = strategy - - if es_connection is not None: - self.client = es_connection - elif es_url is not None or es_cloud_id is not None: - self.client = ElasticsearchStore.connect_to_elasticsearch( - es_url=es_url, - username=es_user, - password=es_password, - cloud_id=es_cloud_id, - api_key=es_api_key, - es_params=es_params, - ) - else: - raise ValueError( - """Either provide a pre-existing Elasticsearch connection, \ - or valid credentials for creating a new connection.""" - ) - - self.client = with_user_agent_header(self.client, "langchain-py-vs") - - @staticmethod - def connect_to_elasticsearch( - *, - es_url: Optional[str] = None, - cloud_id: Optional[str] = None, - api_key: Optional[str] = None, - username: Optional[str] = None, - password: Optional[str] = None, - es_params: Optional[Dict[str, Any]] = None, - ) -> "Elasticsearch": - if es_url and cloud_id: - raise ValueError( - "Both es_url and cloud_id are defined. Please provide only one." - ) - - connection_params: Dict[str, Any] = {} - - if es_url: - connection_params["hosts"] = [es_url] - elif cloud_id: - connection_params["cloud_id"] = cloud_id - else: - raise ValueError("Please provide either elasticsearch_url or cloud_id.") - - if api_key: - connection_params["api_key"] = api_key - elif username and password: - connection_params["basic_auth"] = (username, password) - - if es_params is not None: - connection_params.update(es_params) - - es_client = Elasticsearch(**connection_params) - try: - es_client.info() - except Exception as e: - logger.error(f"Error connecting to Elasticsearch: {e}") - raise e - - return es_client - - @property - def embeddings(self) -> Optional[Embeddings]: - return self.embedding - - def similarity_search( - self, - query: str, - k: int = 4, - fetch_k: int = 50, - filter: Optional[List[dict]] = None, - **kwargs: Any, - ) -> List[Document]: - """Return Elasticsearch documents most similar to query. - - Args: - query: Text to look up documents similar to. - k: Number of Documents to return. Defaults to 4. - fetch_k (int): Number of Documents to fetch to pass to knn num_candidates. - filter: Array of Elasticsearch filter clauses to apply to the query. - - Returns: - List of Documents most similar to the query, - in descending order of similarity. - """ - - results = self._search( - query=query, k=k, fetch_k=fetch_k, filter=filter, **kwargs - ) - return [doc for doc, _ in results] - - def max_marginal_relevance_search( - self, - query: str, - k: int = 4, - fetch_k: int = 20, - lambda_mult: float = 0.5, - fields: Optional[List[str]] = None, - **kwargs: Any, - ) -> List[Document]: - """Return docs selected using the maximal marginal relevance. - - Maximal marginal relevance optimizes for similarity to query AND diversity - among selected documents. - - Args: - query (str): Text to look up documents similar to. - k (int): Number of Documents to return. Defaults to 4. - fetch_k (int): Number of Documents to fetch to pass to MMR algorithm. - lambda_mult (float): Number between 0 and 1 that determines the degree - of diversity among the results with 0 corresponding - to maximum diversity and 1 to minimum diversity. - Defaults to 0.5. - fields: Other fields to get from elasticsearch source. These fields - will be added to the document metadata. - - Returns: - List[Document]: A list of Documents selected by maximal marginal relevance. - """ - if self.embedding is None: - raise ValueError("You must provide an embedding function to perform MMR") - remove_vector_query_field_from_metadata = True - if fields is None: - fields = [self.vector_query_field] - elif self.vector_query_field not in fields: - fields.append(self.vector_query_field) - else: - remove_vector_query_field_from_metadata = False - - # Embed the query - query_embedding = self.embedding.embed_query(query) - - # Fetch the initial documents - got_docs = self._search( - query_vector=query_embedding, k=fetch_k, fields=fields, **kwargs - ) - - # Get the embeddings for the fetched documents - got_embeddings = [doc.metadata[self.vector_query_field] for doc, _ in got_docs] - - # Select documents using maximal marginal relevance - selected_indices = maximal_marginal_relevance( - np.array(query_embedding), got_embeddings, lambda_mult=lambda_mult, k=k - ) - selected_docs = [got_docs[i][0] for i in selected_indices] - - if remove_vector_query_field_from_metadata: - for doc in selected_docs: - del doc.metadata[self.vector_query_field] - - return selected_docs - - @staticmethod - def _identity_fn(score: float) -> float: - return score - - def _select_relevance_score_fn(self) -> Callable[[float], float]: - """ - The 'correct' relevance function - may differ depending on a few things, including: - - the distance / similarity metric used by the VectorStore - - the scale of your embeddings (OpenAI's are unit normed. Many others are not!) - - embedding dimensionality - - etc. - - Vectorstores should define their own selection based method of relevance. - """ - # All scores from Elasticsearch are already normalized similarities: - # https://www.elastic.co/guide/en/elasticsearch/reference/current/dense-vector.html#dense-vector-params - return self._identity_fn - - def similarity_search_with_score( - self, query: str, k: int = 4, filter: Optional[List[dict]] = None, **kwargs: Any - ) -> List[Tuple[Document, float]]: - """Return Elasticsearch documents most similar to query, along with scores. - - Args: - query: Text to look up documents similar to. - k: Number of Documents to return. Defaults to 4. - filter: Array of Elasticsearch filter clauses to apply to the query. - - Returns: - List of Documents most similar to the query and score for each - """ - if isinstance(self.strategy, ApproxRetrievalStrategy) and self.strategy.hybrid: - raise ValueError("scores are currently not supported in hybrid mode") - - return self._search(query=query, k=k, filter=filter, **kwargs) - - def similarity_search_by_vector_with_relevance_scores( - self, - embedding: List[float], - k: int = 4, - filter: Optional[List[Dict]] = None, - **kwargs: Any, - ) -> List[Tuple[Document, float]]: - """Return Elasticsearch documents most similar to query, along with scores. - - Args: - embedding: Embedding to look up documents similar to. - k: Number of Documents to return. Defaults to 4. - filter: Array of Elasticsearch filter clauses to apply to the query. - - Returns: - List of Documents most similar to the embedding and score for each - """ - if isinstance(self.strategy, ApproxRetrievalStrategy) and self.strategy.hybrid: - raise ValueError("scores are currently not supported in hybrid mode") - - return self._search(query_vector=embedding, k=k, filter=filter, **kwargs) - - def _search( - self, - query: Optional[str] = None, - k: int = 4, - query_vector: Union[List[float], None] = None, - fetch_k: int = 50, - fields: Optional[List[str]] = None, - filter: Optional[List[dict]] = None, - custom_query: Optional[Callable[[Dict, Union[str, None]], Dict]] = None, - doc_builder: Optional[Callable[[Dict], Document]] = None, - **kwargs: Any, - ) -> List[Tuple[Document, float]]: - """Return Elasticsearch documents most similar to query, along with scores. - - Args: - query: Text to look up documents similar to. - k: Number of Documents to return. Defaults to 4. - query_vector: Embedding to look up documents similar to. - fetch_k: Number of candidates to fetch from each shard. - Defaults to 50. - fields: List of fields to return from Elasticsearch. - Defaults to only returning the text field. - filter: Array of Elasticsearch filter clauses to apply to the query. - custom_query: Function to modify the Elasticsearch - query body before it is sent to Elasticsearch. - - Returns: - List of Documents most similar to the query and score for each - """ - if fields is None: - fields = [] - - if "metadata" not in fields: - fields.append("metadata") - - if self.query_field not in fields: - fields.append(self.query_field) - - if self.embedding and query is not None: - query_vector = self.embedding.embed_query(query) - - query_body = self.strategy.query( - query_vector=query_vector, - query=query, - k=k, - fetch_k=fetch_k, - vector_query_field=self.vector_query_field, - text_field=self.query_field, - filter=filter or [], - similarity=self.distance_strategy, - ) - - logger.debug(f"Query body: {query_body}") - - if custom_query is not None: - query_body = custom_query(query_body, query) - logger.debug(f"Calling custom_query, Query body now: {query_body}") - # Perform the kNN search on the Elasticsearch index and return the results. - response = self.client.search( - index=self.index_name, - **query_body, - size=k, - source=True, - source_includes=fields, - ) - - def default_doc_builder(hit: Dict) -> Document: - return Document( - page_content=hit["_source"].get(self.query_field, ""), - metadata=hit["_source"]["metadata"], - ) - - doc_builder = doc_builder or default_doc_builder - - docs_and_scores = [] - for hit in response["hits"]["hits"]: - for field in fields: - if field in hit["_source"] and field not in [ - "metadata", - self.query_field, - ]: - if "metadata" not in hit["_source"]: - hit["_source"]["metadata"] = {} - hit["_source"]["metadata"][field] = hit["_source"][field] - - docs_and_scores.append( - ( - doc_builder(hit), - hit["_score"], - ) - ) - return docs_and_scores - - def delete( - self, - ids: Optional[List[str]] = None, - refresh_indices: Optional[bool] = True, - **kwargs: Any, - ) -> Optional[bool]: - """Delete documents from the Elasticsearch index. - - Args: - ids: List of ids of documents to delete. - refresh_indices: Whether to refresh the index - after deleting documents. Defaults to True. - """ - body = [] - - if ids is None: - raise ValueError("ids must be provided.") - - for _id in ids: - body.append({"_op_type": "delete", "_index": self.index_name, "_id": _id}) - - if len(body) > 0: - try: - bulk(self.client, body, refresh=refresh_indices, ignore_status=404) - logger.debug(f"Deleted {len(body)} texts from index") - - return True - except BulkIndexError as e: - logger.error(f"Error deleting texts: {e}") - firstError = e.errors[0].get("index", {}).get("error", {}) - logger.error(f"First error reason: {firstError.get('reason')}") - raise e - - else: - logger.debug("No texts to delete from index") - return False - - def _create_index_if_not_exists( - self, index_name: str, dims_length: Optional[int] = None - ) -> None: - """Create the Elasticsearch index if it doesn't already exist. - - Args: - index_name: Name of the Elasticsearch index to create. - dims_length: Length of the embedding vectors. - """ - - if self.client.indices.exists(index=index_name): - logger.debug(f"Index {index_name} already exists. Skipping creation.") - - else: - if dims_length is None and self.strategy.require_inference(): - raise ValueError( - "Cannot create index without specifying dims_length " - "when the index doesn't already exist. We infer " - "dims_length from the first embedding. Check that " - "you have provided an embedding function." - ) - - self.strategy.before_index_setup( - client=self.client, - text_field=self.query_field, - vector_query_field=self.vector_query_field, - ) - - indexSettings = self.strategy.index( - vector_query_field=self.vector_query_field, - dims_length=dims_length, - similarity=self.distance_strategy, - ) - logger.debug( - f"Creating index {index_name} with mappings {indexSettings['mappings']}" - ) - self.client.indices.create(index=index_name, **indexSettings) - - def __add( - self, - texts: Iterable[str], - embeddings: Optional[List[List[float]]], - metadatas: Optional[List[Dict[Any, Any]]] = None, - ids: Optional[List[str]] = None, - refresh_indices: bool = True, - create_index_if_not_exists: bool = True, - bulk_kwargs: Optional[Dict] = None, - **kwargs: Any, - ) -> List[str]: - bulk_kwargs = bulk_kwargs or {} - ids = ids or [str(uuid.uuid4()) for _ in texts] - requests = [] - - if create_index_if_not_exists: - if embeddings: - dims_length = len(embeddings[0]) - else: - dims_length = None - - self._create_index_if_not_exists( - index_name=self.index_name, dims_length=dims_length - ) - - for i, text in enumerate(texts): - metadata = metadatas[i] if metadatas else {} - - request = { - "_op_type": "index", - "_index": self.index_name, - self.query_field: text, - "metadata": metadata, - "_id": ids[i], - } - if embeddings: - request[self.vector_query_field] = embeddings[i] - - requests.append(request) - - if len(requests) > 0: - try: - success, failed = bulk( - self.client, - requests, - stats_only=True, - refresh=refresh_indices, - **bulk_kwargs, - ) - logger.debug( - f"Added {success} and failed to add {failed} texts to index" - ) - - logger.debug(f"added texts {ids} to index") - return ids - except BulkIndexError as e: - logger.error(f"Error adding texts: {e}") - firstError = e.errors[0].get("index", {}).get("error", {}) - logger.error(f"First error reason: {firstError.get('reason')}") - raise e - - else: - logger.debug("No texts to add to index") - return [] - - def add_texts( - self, - texts: Iterable[str], - metadatas: Optional[List[Dict[Any, Any]]] = None, - ids: Optional[List[str]] = None, - refresh_indices: bool = True, - create_index_if_not_exists: bool = True, - bulk_kwargs: Optional[Dict] = None, - **kwargs: Any, - ) -> List[str]: - """Run more texts through the embeddings and add to the vectorstore. - - Args: - texts: Iterable of strings to add to the vectorstore. - metadatas: Optional list of metadatas associated with the texts. - ids: Optional list of ids to associate with the texts. - refresh_indices: Whether to refresh the Elasticsearch indices - after adding the texts. - create_index_if_not_exists: Whether to create the Elasticsearch - index if it doesn't already exist. - *bulk_kwargs: Additional arguments to pass to Elasticsearch bulk. - - chunk_size: Optional. Number of texts to add to the - index at a time. Defaults to 500. - - Returns: - List of ids from adding the texts into the vectorstore. - """ - if self.embedding is not None: - # If no search_type requires inference, we use the provided - # embedding function to embed the texts. - embeddings = self.embedding.embed_documents(list(texts)) - else: - # the search_type doesn't require inference, so we don't need to - # embed the texts. - embeddings = None - - return self.__add( - texts, - embeddings, - metadatas=metadatas, - ids=ids, - refresh_indices=refresh_indices, - create_index_if_not_exists=create_index_if_not_exists, - bulk_kwargs=bulk_kwargs, - kwargs=kwargs, - ) - - def add_embeddings( - self, - text_embeddings: Iterable[Tuple[str, List[float]]], - metadatas: Optional[List[dict]] = None, - ids: Optional[List[str]] = None, - refresh_indices: bool = True, - create_index_if_not_exists: bool = True, - bulk_kwargs: Optional[Dict] = None, - **kwargs: Any, - ) -> List[str]: - """Add the given texts and embeddings to the vectorstore. - - Args: - text_embeddings: Iterable pairs of string and embedding to - add to the vectorstore. - metadatas: Optional list of metadatas associated with the texts. - ids: Optional list of unique IDs. - refresh_indices: Whether to refresh the Elasticsearch indices - after adding the texts. - create_index_if_not_exists: Whether to create the Elasticsearch - index if it doesn't already exist. - *bulk_kwargs: Additional arguments to pass to Elasticsearch bulk. - - chunk_size: Optional. Number of texts to add to the - index at a time. Defaults to 500. - - Returns: - List of ids from adding the texts into the vectorstore. - """ - texts, embeddings = zip(*text_embeddings) - return self.__add( - list(texts), - list(embeddings), - metadatas=metadatas, - ids=ids, - refresh_indices=refresh_indices, - create_index_if_not_exists=create_index_if_not_exists, - bulk_kwargs=bulk_kwargs, - kwargs=kwargs, - ) - - @classmethod - def from_texts( - cls, - texts: List[str], - embedding: Optional[Embeddings] = None, - metadatas: Optional[List[Dict[str, Any]]] = None, - bulk_kwargs: Optional[Dict] = None, - **kwargs: Any, - ) -> "ElasticsearchStore": - """Construct ElasticsearchStore wrapper from raw documents. - - Example: - .. code-block:: python - - from langchain_elasticsearch.vectorstores import ElasticsearchStore - from langchain_openai import OpenAIEmbeddings - - db = ElasticsearchStore.from_texts( - texts, - // embeddings optional if using - // a strategy that doesn't require inference - embeddings, - index_name="langchain-demo", - es_url="http://localhost:9200" - ) - - Args: - texts: List of texts to add to the Elasticsearch index. - embedding: Embedding function to use to embed the texts. - metadatas: Optional list of metadatas associated with the texts. - index_name: Name of the Elasticsearch index to create. - es_url: URL of the Elasticsearch instance to connect to. - cloud_id: Cloud ID of the Elasticsearch instance to connect to. - es_user: Username to use when connecting to Elasticsearch. - es_password: Password to use when connecting to Elasticsearch. - es_api_key: API key to use when connecting to Elasticsearch. - es_connection: Optional pre-existing Elasticsearch connection. - vector_query_field: Optional. Name of the field to - store the embedding vectors in. - query_field: Optional. Name of the field to store the texts in. - distance_strategy: Optional. Name of the distance - strategy to use. Defaults to "COSINE". - can be one of "COSINE", - "EUCLIDEAN_DISTANCE", "DOT_PRODUCT", - "MAX_INNER_PRODUCT". - bulk_kwargs: Optional. Additional arguments to pass to - Elasticsearch bulk. - """ - - elasticsearchStore = ElasticsearchStore._create_cls_from_kwargs( - embedding=embedding, **kwargs - ) - - # Encode the provided texts and add them to the newly created index. - elasticsearchStore.add_texts( - texts, metadatas=metadatas, bulk_kwargs=bulk_kwargs - ) - - return elasticsearchStore - - @staticmethod - def _create_cls_from_kwargs( - embedding: Optional[Embeddings] = None, **kwargs: Any - ) -> "ElasticsearchStore": - index_name = kwargs.get("index_name") - - if index_name is None: - raise ValueError("Please provide an index_name.") - - es_connection = kwargs.get("es_connection") - es_cloud_id = kwargs.get("es_cloud_id") - es_url = kwargs.get("es_url") - es_user = kwargs.get("es_user") - es_password = kwargs.get("es_password") - es_api_key = kwargs.get("es_api_key") - vector_query_field = kwargs.get("vector_query_field") - query_field = kwargs.get("query_field") - distance_strategy = kwargs.get("distance_strategy") - strategy = kwargs.get("strategy", ElasticsearchStore.ApproxRetrievalStrategy()) - - optional_args = {} - - if vector_query_field is not None: - optional_args["vector_query_field"] = vector_query_field - - if query_field is not None: - optional_args["query_field"] = query_field - - return ElasticsearchStore( - index_name=index_name, - embedding=embedding, - es_url=es_url, - es_connection=es_connection, - es_cloud_id=es_cloud_id, - es_user=es_user, - es_password=es_password, - es_api_key=es_api_key, - strategy=strategy, - distance_strategy=distance_strategy, - **optional_args, - ) - - @classmethod - def from_documents( - cls, - documents: List[Document], - embedding: Optional[Embeddings] = None, - bulk_kwargs: Optional[Dict] = None, - **kwargs: Any, - ) -> "ElasticsearchStore": - """Construct ElasticsearchStore wrapper from documents. - - Example: - .. code-block:: python - - from langchain_elasticsearch.vectorstores import ElasticsearchStore - from langchain_openai import OpenAIEmbeddings - - db = ElasticsearchStore.from_documents( - texts, - embeddings, - index_name="langchain-demo", - es_url="http://localhost:9200" - ) - - Args: - texts: List of texts to add to the Elasticsearch index. - embedding: Embedding function to use to embed the texts. - Do not provide if using a strategy - that doesn't require inference. - metadatas: Optional list of metadatas associated with the texts. - index_name: Name of the Elasticsearch index to create. - es_url: URL of the Elasticsearch instance to connect to. - cloud_id: Cloud ID of the Elasticsearch instance to connect to. - es_user: Username to use when connecting to Elasticsearch. - es_password: Password to use when connecting to Elasticsearch. - es_api_key: API key to use when connecting to Elasticsearch. - es_connection: Optional pre-existing Elasticsearch connection. - vector_query_field: Optional. Name of the field - to store the embedding vectors in. - query_field: Optional. Name of the field to store the texts in. - bulk_kwargs: Optional. Additional arguments to pass to - Elasticsearch bulk. - """ - - elasticsearchStore = ElasticsearchStore._create_cls_from_kwargs( - embedding=embedding, **kwargs - ) - # Encode the provided texts and add them to the newly created index. - elasticsearchStore.add_documents(documents, bulk_kwargs=bulk_kwargs) - - return elasticsearchStore - - @staticmethod - def ExactRetrievalStrategy() -> "ExactRetrievalStrategy": - """Used to perform brute force / exact - nearest neighbor search via script_score.""" - return ExactRetrievalStrategy() - - @staticmethod - def ApproxRetrievalStrategy( - query_model_id: Optional[str] = None, - hybrid: Optional[bool] = False, - rrf: Optional[Union[dict, bool]] = True, - ) -> "ApproxRetrievalStrategy": - """Used to perform approximate nearest neighbor search - using the HNSW algorithm. - - At build index time, this strategy will create a - dense vector field in the index and store the - embedding vectors in the index. - - At query time, the text will either be embedded using the - provided embedding function or the query_model_id - will be used to embed the text using the model - deployed to Elasticsearch. - - if query_model_id is used, do not provide an embedding function. - - Args: - query_model_id: Optional. ID of the model to use to - embed the query text within the stack. Requires - embedding model to be deployed to Elasticsearch. - hybrid: Optional. If True, will perform a hybrid search - using both the knn query and a text query. - Defaults to False. - rrf: Optional. rrf is Reciprocal Rank Fusion. - When `hybrid` is True, - and `rrf` is True, then rrf: {}. - and `rrf` is False, then rrf is omitted. - and isinstance(rrf, dict) is True, then pass in the dict values. - rrf could be passed for adjusting 'rank_constant' and 'window_size'. - """ - return ApproxRetrievalStrategy( - query_model_id=query_model_id, hybrid=hybrid, rrf=rrf - ) - - @staticmethod - def SparseVectorRetrievalStrategy( - model_id: Optional[str] = None, - ) -> "SparseRetrievalStrategy": - """Used to perform sparse vector search via text_expansion. - Used for when you want to use ELSER model to perform document search. - - At build index time, this strategy will create a pipeline that - will embed the text using the ELSER model and store the - resulting tokens in the index. - - At query time, the text will be embedded using the ELSER - model and the resulting tokens will be used to - perform a text_expansion query. - - Args: - model_id: Optional. Default is ".elser_model_1". - ID of the model to use to embed the query text - within the stack. Requires embedding model to be - deployed to Elasticsearch. - """ - return SparseRetrievalStrategy(model_id=model_id) diff --git a/libs/partners/elasticsearch/poetry.lock b/libs/partners/elasticsearch/poetry.lock deleted file mode 100644 index 5ad6c8e6da..0000000000 --- a/libs/partners/elasticsearch/poetry.lock +++ /dev/null @@ -1,1672 +0,0 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. - -[[package]] -name = "aiohttp" -version = "3.9.3" -description = "Async http client/server framework (asyncio)" -optional = false -python-versions = ">=3.8" -files = [ - {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:939677b61f9d72a4fa2a042a5eee2a99a24001a67c13da113b2e30396567db54"}, - {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1f5cd333fcf7590a18334c90f8c9147c837a6ec8a178e88d90a9b96ea03194cc"}, - {file = "aiohttp-3.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82e6aa28dd46374f72093eda8bcd142f7771ee1eb9d1e223ff0fa7177a96b4a5"}, - {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f56455b0c2c7cc3b0c584815264461d07b177f903a04481dfc33e08a89f0c26b"}, - {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bca77a198bb6e69795ef2f09a5f4c12758487f83f33d63acde5f0d4919815768"}, - {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e083c285857b78ee21a96ba1eb1b5339733c3563f72980728ca2b08b53826ca5"}, - {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab40e6251c3873d86ea9b30a1ac6d7478c09277b32e14745d0d3c6e76e3c7e29"}, - {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df822ee7feaaeffb99c1a9e5e608800bd8eda6e5f18f5cfb0dc7eeb2eaa6bbec"}, - {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:acef0899fea7492145d2bbaaaec7b345c87753168589cc7faf0afec9afe9b747"}, - {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cd73265a9e5ea618014802ab01babf1940cecb90c9762d8b9e7d2cc1e1969ec6"}, - {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a78ed8a53a1221393d9637c01870248a6f4ea5b214a59a92a36f18151739452c"}, - {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6b0e029353361f1746bac2e4cc19b32f972ec03f0f943b390c4ab3371840aabf"}, - {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7cf5c9458e1e90e3c390c2639f1017a0379a99a94fdfad3a1fd966a2874bba52"}, - {file = "aiohttp-3.9.3-cp310-cp310-win32.whl", hash = "sha256:3e59c23c52765951b69ec45ddbbc9403a8761ee6f57253250c6e1536cacc758b"}, - {file = "aiohttp-3.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:055ce4f74b82551678291473f66dc9fb9048a50d8324278751926ff0ae7715e5"}, - {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b88f9386ff1ad91ace19d2a1c0225896e28815ee09fc6a8932fded8cda97c3d"}, - {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c46956ed82961e31557b6857a5ca153c67e5476972e5f7190015018760938da2"}, - {file = "aiohttp-3.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:07b837ef0d2f252f96009e9b8435ec1fef68ef8b1461933253d318748ec1acdc"}, - {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad46e6f620574b3b4801c68255492e0159d1712271cc99d8bdf35f2043ec266"}, - {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ed3e046ea7b14938112ccd53d91c1539af3e6679b222f9469981e3dac7ba1ce"}, - {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:039df344b45ae0b34ac885ab5b53940b174530d4dd8a14ed8b0e2155b9dddccb"}, - {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7943c414d3a8d9235f5f15c22ace69787c140c80b718dcd57caaade95f7cd93b"}, - {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84871a243359bb42c12728f04d181a389718710129b36b6aad0fc4655a7647d4"}, - {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5eafe2c065df5401ba06821b9a054d9cb2848867f3c59801b5d07a0be3a380ae"}, - {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9d3c9b50f19704552f23b4eaea1fc082fdd82c63429a6506446cbd8737823da3"}, - {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:f033d80bc6283092613882dfe40419c6a6a1527e04fc69350e87a9df02bbc283"}, - {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2c895a656dd7e061b2fd6bb77d971cc38f2afc277229ce7dd3552de8313a483e"}, - {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1f5a71d25cd8106eab05f8704cd9167b6e5187bcdf8f090a66c6d88b634802b4"}, - {file = "aiohttp-3.9.3-cp311-cp311-win32.whl", hash = "sha256:50fca156d718f8ced687a373f9e140c1bb765ca16e3d6f4fe116e3df7c05b2c5"}, - {file = "aiohttp-3.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:5fe9ce6c09668063b8447f85d43b8d1c4e5d3d7e92c63173e6180b2ac5d46dd8"}, - {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:38a19bc3b686ad55804ae931012f78f7a534cce165d089a2059f658f6c91fa60"}, - {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:770d015888c2a598b377bd2f663adfd947d78c0124cfe7b959e1ef39f5b13869"}, - {file = "aiohttp-3.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee43080e75fc92bf36219926c8e6de497f9b247301bbf88c5c7593d931426679"}, - {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52df73f14ed99cee84865b95a3d9e044f226320a87af208f068ecc33e0c35b96"}, - {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc9b311743a78043b26ffaeeb9715dc360335e5517832f5a8e339f8a43581e4d"}, - {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b955ed993491f1a5da7f92e98d5dad3c1e14dc175f74517c4e610b1f2456fb11"}, - {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:504b6981675ace64c28bf4a05a508af5cde526e36492c98916127f5a02354d53"}, - {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6fe5571784af92b6bc2fda8d1925cccdf24642d49546d3144948a6a1ed58ca5"}, - {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ba39e9c8627edc56544c8628cc180d88605df3892beeb2b94c9bc857774848ca"}, - {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e5e46b578c0e9db71d04c4b506a2121c0cb371dd89af17a0586ff6769d4c58c1"}, - {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:938a9653e1e0c592053f815f7028e41a3062e902095e5a7dc84617c87267ebd5"}, - {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:c3452ea726c76e92f3b9fae4b34a151981a9ec0a4847a627c43d71a15ac32aa6"}, - {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ff30218887e62209942f91ac1be902cc80cddb86bf00fbc6783b7a43b2bea26f"}, - {file = "aiohttp-3.9.3-cp312-cp312-win32.whl", hash = "sha256:38f307b41e0bea3294a9a2a87833191e4bcf89bb0365e83a8be3a58b31fb7f38"}, - {file = "aiohttp-3.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:b791a3143681a520c0a17e26ae7465f1b6f99461a28019d1a2f425236e6eedb5"}, - {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ed621426d961df79aa3b963ac7af0d40392956ffa9be022024cd16297b30c8c"}, - {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7f46acd6a194287b7e41e87957bfe2ad1ad88318d447caf5b090012f2c5bb528"}, - {file = "aiohttp-3.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:feeb18a801aacb098220e2c3eea59a512362eb408d4afd0c242044c33ad6d542"}, - {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f734e38fd8666f53da904c52a23ce517f1b07722118d750405af7e4123933511"}, - {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b40670ec7e2156d8e57f70aec34a7216407848dfe6c693ef131ddf6e76feb672"}, - {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdd215b7b7fd4a53994f238d0f46b7ba4ac4c0adb12452beee724ddd0743ae5d"}, - {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:017a21b0df49039c8f46ca0971b3a7fdc1f56741ab1240cb90ca408049766168"}, - {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e99abf0bba688259a496f966211c49a514e65afa9b3073a1fcee08856e04425b"}, - {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:648056db9a9fa565d3fa851880f99f45e3f9a771dd3ff3bb0c048ea83fb28194"}, - {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8aacb477dc26797ee089721536a292a664846489c49d3ef9725f992449eda5a8"}, - {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:522a11c934ea660ff8953eda090dcd2154d367dec1ae3c540aff9f8a5c109ab4"}, - {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5bce0dc147ca85caa5d33debc4f4d65e8e8b5c97c7f9f660f215fa74fc49a321"}, - {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b4af9f25b49a7be47c0972139e59ec0e8285c371049df1a63b6ca81fdd216a2"}, - {file = "aiohttp-3.9.3-cp38-cp38-win32.whl", hash = "sha256:298abd678033b8571995650ccee753d9458dfa0377be4dba91e4491da3f2be63"}, - {file = "aiohttp-3.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:69361bfdca5468c0488d7017b9b1e5ce769d40b46a9f4a2eed26b78619e9396c"}, - {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0fa43c32d1643f518491d9d3a730f85f5bbaedcbd7fbcae27435bb8b7a061b29"}, - {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:835a55b7ca49468aaaac0b217092dfdff370e6c215c9224c52f30daaa735c1c1"}, - {file = "aiohttp-3.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06a9b2c8837d9a94fae16c6223acc14b4dfdff216ab9b7202e07a9a09541168f"}, - {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abf151955990d23f84205286938796c55ff11bbfb4ccfada8c9c83ae6b3c89a3"}, - {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59c26c95975f26e662ca78fdf543d4eeaef70e533a672b4113dd888bd2423caa"}, - {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f95511dd5d0e05fd9728bac4096319f80615aaef4acbecb35a990afebe953b0e"}, - {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:595f105710293e76b9dc09f52e0dd896bd064a79346234b521f6b968ffdd8e58"}, - {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7c8b816c2b5af5c8a436df44ca08258fc1a13b449393a91484225fcb7545533"}, - {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f1088fa100bf46e7b398ffd9904f4808a0612e1d966b4aa43baa535d1b6341eb"}, - {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f59dfe57bb1ec82ac0698ebfcdb7bcd0e99c255bd637ff613760d5f33e7c81b3"}, - {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:361a1026c9dd4aba0109e4040e2aecf9884f5cfe1b1b1bd3d09419c205e2e53d"}, - {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:363afe77cfcbe3a36353d8ea133e904b108feea505aa4792dad6585a8192c55a"}, - {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e2c45c208c62e955e8256949eb225bd8b66a4c9b6865729a786f2aa79b72e9d"}, - {file = "aiohttp-3.9.3-cp39-cp39-win32.whl", hash = "sha256:f7217af2e14da0856e082e96ff637f14ae45c10a5714b63c77f26d8884cf1051"}, - {file = "aiohttp-3.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:27468897f628c627230dba07ec65dc8d0db566923c48f29e084ce382119802bc"}, - {file = "aiohttp-3.9.3.tar.gz", hash = "sha256:90842933e5d1ff760fae6caca4b2b3edba53ba8f4b71e95dacf2818a2aca06f7"}, -] - -[package.dependencies] -aiosignal = ">=1.1.2" -async-timeout = {version = ">=4.0,<5.0", markers = "python_version < \"3.11\""} -attrs = ">=17.3.0" -frozenlist = ">=1.1.1" -multidict = ">=4.5,<7.0" -yarl = ">=1.0,<2.0" - -[package.extras] -speedups = ["Brotli", "aiodns", "brotlicffi"] - -[[package]] -name = "aiosignal" -version = "1.3.1" -description = "aiosignal: a list of registered asynchronous callbacks" -optional = false -python-versions = ">=3.7" -files = [ - {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, - {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, -] - -[package.dependencies] -frozenlist = ">=1.1.0" - -[[package]] -name = "annotated-types" -version = "0.6.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -files = [ - {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"}, - {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"}, -] - -[package.dependencies] -typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""} - -[[package]] -name = "anyio" -version = "4.3.0" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -optional = false -python-versions = ">=3.8" -files = [ - {file = "anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"}, - {file = "anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6"}, -] - -[package.dependencies] -exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} -idna = ">=2.8" -sniffio = ">=1.1" -typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} - -[package.extras] -doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] -trio = ["trio (>=0.23)"] - -[[package]] -name = "async-timeout" -version = "4.0.3" -description = "Timeout context manager for asyncio programs" -optional = false -python-versions = ">=3.7" -files = [ - {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, - {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, -] - -[[package]] -name = "attrs" -version = "23.2.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.7" -files = [ - {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, - {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, -] - -[package.extras] -cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] -dev = ["attrs[tests]", "pre-commit"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] -tests = ["attrs[tests-no-zope]", "zope-interface"] -tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] -tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] - -[[package]] -name = "certifi" -version = "2024.2.2" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.6" -files = [ - {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, - {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, -] - -[[package]] -name = "charset-normalizer" -version = "3.3.2" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.7.0" -files = [ - {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, - {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, -] - -[[package]] -name = "codespell" -version = "2.2.6" -description = "Codespell" -optional = false -python-versions = ">=3.8" -files = [ - {file = "codespell-2.2.6-py3-none-any.whl", hash = "sha256:9ee9a3e5df0990604013ac2a9f22fa8e57669c827124a2e961fe8a1da4cacc07"}, - {file = "codespell-2.2.6.tar.gz", hash = "sha256:a8c65d8eb3faa03deabab6b3bbe798bea72e1799c7e9e955d57eca4096abcff9"}, -] - -[package.extras] -dev = ["Pygments", "build", "chardet", "pre-commit", "pytest", "pytest-cov", "pytest-dependency", "ruff", "tomli", "twine"] -hard-encoding-detection = ["chardet"] -toml = ["tomli"] -types = ["chardet (>=5.1.0)", "mypy", "pytest", "pytest-cov", "pytest-dependency"] - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "dataclasses-json" -version = "0.6.4" -description = "Easily serialize dataclasses to and from JSON." -optional = false -python-versions = ">=3.7,<4.0" -files = [ - {file = "dataclasses_json-0.6.4-py3-none-any.whl", hash = "sha256:f90578b8a3177f7552f4e1a6e535e84293cd5da421fcce0642d49c0d7bdf8df2"}, - {file = "dataclasses_json-0.6.4.tar.gz", hash = "sha256:73696ebf24936560cca79a2430cbc4f3dd23ac7bf46ed17f38e5e5e7657a6377"}, -] - -[package.dependencies] -marshmallow = ">=3.18.0,<4.0.0" -typing-inspect = ">=0.4.0,<1" - -[[package]] -name = "elastic-transport" -version = "8.12.0" -description = "Transport classes and utilities shared among Python Elastic client libraries" -optional = false -python-versions = ">=3.7" -files = [ - {file = "elastic-transport-8.12.0.tar.gz", hash = "sha256:48839b942fcce199eece1558ecea6272e116c58da87ca8d495ef12eb61effaf7"}, - {file = "elastic_transport-8.12.0-py3-none-any.whl", hash = "sha256:87d9dc9dee64a05235e7624ed7e6ab6e5ca16619aa7a6d22e853273b9f1cfbee"}, -] - -[package.dependencies] -certifi = "*" -urllib3 = ">=1.26.2,<3" - -[package.extras] -develop = ["aiohttp", "furo", "mock", "pytest", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "pytest-mock", "requests", "sphinx (>2)", "sphinx-autodoc-typehints", "trustme"] - -[[package]] -name = "elasticsearch" -version = "8.12.1" -description = "Python client for Elasticsearch" -optional = false -python-versions = ">=3.7" -files = [ - {file = "elasticsearch-8.12.1-py3-none-any.whl", hash = "sha256:cc459b7e0fb88dc85b43b9d7d254cffad552b0063a3e0a12290c8fa5f138c038"}, - {file = "elasticsearch-8.12.1.tar.gz", hash = "sha256:00c997720fbd0f2afe5417c8193cf65d116817a0250de0521e30c3e81f00b8ac"}, -] - -[package.dependencies] -elastic-transport = ">=8,<9" - -[package.extras] -async = ["aiohttp (>=3,<4)"] -requests = ["requests (>=2.4.0,<3.0.0)"] - -[[package]] -name = "exceptiongroup" -version = "1.2.0" -description = "Backport of PEP 654 (exception groups)" -optional = false -python-versions = ">=3.7" -files = [ - {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, - {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, -] - -[package.extras] -test = ["pytest (>=6)"] - -[[package]] -name = "freezegun" -version = "1.4.0" -description = "Let your Python tests travel through time" -optional = false -python-versions = ">=3.7" -files = [ - {file = "freezegun-1.4.0-py3-none-any.whl", hash = "sha256:55e0fc3c84ebf0a96a5aa23ff8b53d70246479e9a68863f1fcac5a3e52f19dd6"}, - {file = "freezegun-1.4.0.tar.gz", hash = "sha256:10939b0ba0ff5adaecf3b06a5c2f73071d9678e507c5eaedb23c761d56ac774b"}, -] - -[package.dependencies] -python-dateutil = ">=2.7" - -[[package]] -name = "frozenlist" -version = "1.4.1" -description = "A list-like structure which implements collections.abc.MutableSequence" -optional = false -python-versions = ">=3.8" -files = [ - {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"}, - {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"}, - {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"}, - {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"}, - {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"}, - {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"}, - {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"}, - {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"}, - {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"}, - {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"}, - {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"}, - {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"}, - {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"}, - {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"}, - {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"}, -] - -[[package]] -name = "greenlet" -version = "3.0.3" -description = "Lightweight in-process concurrent programming" -optional = false -python-versions = ">=3.7" -files = [ - {file = "greenlet-3.0.3-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9da2bd29ed9e4f15955dd1595ad7bc9320308a3b766ef7f837e23ad4b4aac31a"}, - {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d353cadd6083fdb056bb46ed07e4340b0869c305c8ca54ef9da3421acbdf6881"}, - {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dca1e2f3ca00b84a396bc1bce13dd21f680f035314d2379c4160c98153b2059b"}, - {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ed7fb269f15dc662787f4119ec300ad0702fa1b19d2135a37c2c4de6fadfd4a"}, - {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd4f49ae60e10adbc94b45c0b5e6a179acc1736cf7a90160b404076ee283cf83"}, - {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:73a411ef564e0e097dbe7e866bb2dda0f027e072b04da387282b02c308807405"}, - {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7f362975f2d179f9e26928c5b517524e89dd48530a0202570d55ad6ca5d8a56f"}, - {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:649dde7de1a5eceb258f9cb00bdf50e978c9db1b996964cd80703614c86495eb"}, - {file = "greenlet-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:68834da854554926fbedd38c76e60c4a2e3198c6fbed520b106a8986445caaf9"}, - {file = "greenlet-3.0.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:b1b5667cced97081bf57b8fa1d6bfca67814b0afd38208d52538316e9422fc61"}, - {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52f59dd9c96ad2fc0d5724107444f76eb20aaccb675bf825df6435acb7703559"}, - {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:afaff6cf5200befd5cec055b07d1c0a5a06c040fe5ad148abcd11ba6ab9b114e"}, - {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe754d231288e1e64323cfad462fcee8f0288654c10bdf4f603a39ed923bef33"}, - {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2797aa5aedac23af156bbb5a6aa2cd3427ada2972c828244eb7d1b9255846379"}, - {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7f009caad047246ed379e1c4dbcb8b020f0a390667ea74d2387be2998f58a22"}, - {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c5e1536de2aad7bf62e27baf79225d0d64360d4168cf2e6becb91baf1ed074f3"}, - {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:894393ce10ceac937e56ec00bb71c4c2f8209ad516e96033e4b3b1de270e200d"}, - {file = "greenlet-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:1ea188d4f49089fc6fb283845ab18a2518d279c7cd9da1065d7a84e991748728"}, - {file = "greenlet-3.0.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:70fb482fdf2c707765ab5f0b6655e9cfcf3780d8d87355a063547b41177599be"}, - {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4d1ac74f5c0c0524e4a24335350edad7e5f03b9532da7ea4d3c54d527784f2e"}, - {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149e94a2dd82d19838fe4b2259f1b6b9957d5ba1b25640d2380bea9c5df37676"}, - {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15d79dd26056573940fcb8c7413d84118086f2ec1a8acdfa854631084393efcc"}, - {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b7db1ebff4ba09aaaeae6aa491daeb226c8150fc20e836ad00041bcb11230"}, - {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fcd2469d6a2cf298f198f0487e0a5b1a47a42ca0fa4dfd1b6862c999f018ebbf"}, - {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1f672519db1796ca0d8753f9e78ec02355e862d0998193038c7073045899f305"}, - {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2516a9957eed41dd8f1ec0c604f1cdc86758b587d964668b5b196a9db5bfcde6"}, - {file = "greenlet-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:bba5387a6975598857d86de9eac14210a49d554a77eb8261cc68b7d082f78ce2"}, - {file = "greenlet-3.0.3-cp37-cp37m-macosx_11_0_universal2.whl", hash = "sha256:5b51e85cb5ceda94e79d019ed36b35386e8c37d22f07d6a751cb659b180d5274"}, - {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:daf3cb43b7cf2ba96d614252ce1684c1bccee6b2183a01328c98d36fcd7d5cb0"}, - {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99bf650dc5d69546e076f413a87481ee1d2d09aaaaaca058c9251b6d8c14783f"}, - {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dd6e660effd852586b6a8478a1d244b8dc90ab5b1321751d2ea15deb49ed414"}, - {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3391d1e16e2a5a1507d83e4a8b100f4ee626e8eca43cf2cadb543de69827c4c"}, - {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e1f145462f1fa6e4a4ae3c0f782e580ce44d57c8f2c7aae1b6fa88c0b2efdb41"}, - {file = "greenlet-3.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1a7191e42732df52cb5f39d3527217e7ab73cae2cb3694d241e18f53d84ea9a7"}, - {file = "greenlet-3.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0448abc479fab28b00cb472d278828b3ccca164531daab4e970a0458786055d6"}, - {file = "greenlet-3.0.3-cp37-cp37m-win32.whl", hash = "sha256:b542be2440edc2d48547b5923c408cbe0fc94afb9f18741faa6ae970dbcb9b6d"}, - {file = "greenlet-3.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:01bc7ea167cf943b4c802068e178bbf70ae2e8c080467070d01bfa02f337ee67"}, - {file = "greenlet-3.0.3-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:1996cb9306c8595335bb157d133daf5cf9f693ef413e7673cb07e3e5871379ca"}, - {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ddc0f794e6ad661e321caa8d2f0a55ce01213c74722587256fb6566049a8b04"}, - {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9db1c18f0eaad2f804728c67d6c610778456e3e1cc4ab4bbd5eeb8e6053c6fc"}, - {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7170375bcc99f1a2fbd9c306f5be8764eaf3ac6b5cb968862cad4c7057756506"}, - {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b66c9c1e7ccabad3a7d037b2bcb740122a7b17a53734b7d72a344ce39882a1b"}, - {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:098d86f528c855ead3479afe84b49242e174ed262456c342d70fc7f972bc13c4"}, - {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:81bb9c6d52e8321f09c3d165b2a78c680506d9af285bfccbad9fb7ad5a5da3e5"}, - {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd096eb7ffef17c456cfa587523c5f92321ae02427ff955bebe9e3c63bc9f0da"}, - {file = "greenlet-3.0.3-cp38-cp38-win32.whl", hash = "sha256:d46677c85c5ba00a9cb6f7a00b2bfa6f812192d2c9f7d9c4f6a55b60216712f3"}, - {file = "greenlet-3.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:419b386f84949bf0e7c73e6032e3457b82a787c1ab4a0e43732898a761cc9dbf"}, - {file = "greenlet-3.0.3-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:da70d4d51c8b306bb7a031d5cff6cc25ad253affe89b70352af5f1cb68e74b53"}, - {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086152f8fbc5955df88382e8a75984e2bb1c892ad2e3c80a2508954e52295257"}, - {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d73a9fe764d77f87f8ec26a0c85144d6a951a6c438dfe50487df5595c6373eac"}, - {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7dcbe92cc99f08c8dd11f930de4d99ef756c3591a5377d1d9cd7dd5e896da71"}, - {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1551a8195c0d4a68fac7a4325efac0d541b48def35feb49d803674ac32582f61"}, - {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:64d7675ad83578e3fc149b617a444fab8efdafc9385471f868eb5ff83e446b8b"}, - {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b37eef18ea55f2ffd8f00ff8fe7c8d3818abd3e25fb73fae2ca3b672e333a7a6"}, - {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:77457465d89b8263bca14759d7c1684df840b6811b2499838cc5b040a8b5b113"}, - {file = "greenlet-3.0.3-cp39-cp39-win32.whl", hash = "sha256:57e8974f23e47dac22b83436bdcf23080ade568ce77df33159e019d161ce1d1e"}, - {file = "greenlet-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:c5ee858cfe08f34712f548c3c363e807e7186f03ad7a5039ebadb29e8c6be067"}, - {file = "greenlet-3.0.3.tar.gz", hash = "sha256:43374442353259554ce33599da8b692d5aa96f8976d567d4badf263371fbe491"}, -] - -[package.extras] -docs = ["Sphinx", "furo"] -test = ["objgraph", "psutil"] - -[[package]] -name = "idna" -version = "3.6" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.5" -files = [ - {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, - {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, -] - -[[package]] -name = "iniconfig" -version = "2.0.0" -description = "brain-dead simple config-ini parsing" -optional = false -python-versions = ">=3.7" -files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, -] - -[[package]] -name = "jsonpatch" -version = "1.33" -description = "Apply JSON-Patches (RFC 6902)" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" -files = [ - {file = "jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade"}, - {file = "jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c"}, -] - -[package.dependencies] -jsonpointer = ">=1.9" - -[[package]] -name = "jsonpointer" -version = "2.4" -description = "Identify specific nodes in a JSON document (RFC 6901)" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" -files = [ - {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"}, - {file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"}, -] - -[[package]] -name = "langchain" -version = "0.1.11" -description = "Building applications with LLMs through composability" -optional = false -python-versions = ">=3.8.1,<4.0" -files = [] -develop = true - -[package.dependencies] -aiohttp = "^3.8.3" -async-timeout = {version = "^4.0.0", markers = "python_version < \"3.11\""} -dataclasses-json = ">= 0.5.7, < 0.7" -jsonpatch = "^1.33" -langchain-community = ">=0.0.25,<0.1" -langchain-core = ">=0.1.29,<0.2" -langchain-text-splitters = ">=0.0.1,<0.1" -langsmith = "^0.1.17" -numpy = "^1" -pydantic = ">=1,<3" -PyYAML = ">=5.3" -requests = "^2" -SQLAlchemy = ">=1.4,<3" -tenacity = "^8.1.0" - -[package.extras] -all = [] -azure = ["azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-textanalytics (>=5.3.0,<6.0.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-core (>=1.26.4,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "azure-search-documents (==11.4.0b8)", "openai (<2)"] -clarifai = ["clarifai (>=9.1.0)"] -cli = ["typer (>=0.9.0,<0.10.0)"] -cohere = ["cohere (>=4,<5)"] -docarray = ["docarray[hnswlib] (>=0.32.0,<0.33.0)"] -embeddings = ["sentence-transformers (>=2,<3)"] -extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cohere (>=4,<5)", "couchbase (>=4.1.9,<5.0.0)", "dashvector (>=1.0.1,<2.0.0)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "langchain-openai (>=0.0.2,<0.1)", "lxml (>=4.9.2,<5.0.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "openai (<2)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] -javascript = ["esprima (>=4.0.1,<5.0.0)"] -llms = ["clarifai (>=9.1.0)", "cohere (>=4,<5)", "huggingface_hub (>=0,<1)", "manifest-ml (>=0.0.1,<0.0.2)", "nlpcloud (>=1,<2)", "openai (<2)", "openlm (>=0.0.5,<0.0.6)", "torch (>=1,<3)", "transformers (>=4,<5)"] -openai = ["openai (<2)", "tiktoken (>=0.3.2,<0.6.0)"] -qdrant = ["qdrant-client (>=1.3.1,<2.0.0)"] -text-helpers = ["chardet (>=5.1.0,<6.0.0)"] - -[package.source] -type = "directory" -url = "../../langchain" - -[[package]] -name = "langchain-community" -version = "0.0.25" -description = "Community contributed LangChain integrations." -optional = false -python-versions = ">=3.8.1,<4.0" -files = [ - {file = "langchain_community-0.0.25-py3-none-any.whl", hash = "sha256:09b931ba710b1a10e449396d59f38575e0554acd527287937c33a2c4abdc6d83"}, - {file = "langchain_community-0.0.25.tar.gz", hash = "sha256:b6c8c14cd6ec2635e51e3974bf78a8de3b959bbedb4af55aad164f8cf392f0c5"}, -] - -[package.dependencies] -aiohttp = ">=3.8.3,<4.0.0" -dataclasses-json = ">=0.5.7,<0.7" -langchain-core = ">=0.1.28,<0.2.0" -langsmith = ">=0.1.0,<0.2.0" -numpy = ">=1,<2" -PyYAML = ">=5.3" -requests = ">=2,<3" -SQLAlchemy = ">=1.4,<3" -tenacity = ">=8.1.0,<9.0.0" - -[package.extras] -cli = ["typer (>=0.9.0,<0.10.0)"] -extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "azure-ai-documentintelligence (>=1.0.0b1,<2.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cohere (>=4,<5)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "elasticsearch (>=8.12.0,<9.0.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "gradientai (>=1.4.0,<2.0.0)", "hdbcli (>=2.19.21,<3.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "httpx (>=0.24.1,<0.25.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "lxml (>=4.9.2,<5.0.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "nvidia-riva-client (>=2.14.0,<3.0.0)", "oci (>=2.119.1,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "oracle-ads (>=2.9.1,<3.0.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "tree-sitter (>=0.20.2,<0.21.0)", "tree-sitter-languages (>=1.8.0,<2.0.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)", "zhipuai (>=1.0.7,<2.0.0)"] - -[[package]] -name = "langchain-core" -version = "0.1.29" -description = "Building applications with LLMs through composability" -optional = false -python-versions = ">=3.8.1,<4.0" -files = [] -develop = true - -[package.dependencies] -anyio = ">=3,<5" -jsonpatch = "^1.33" -langsmith = "^0.1.0" -packaging = "^23.2" -pydantic = ">=1,<3" -PyYAML = ">=5.3" -requests = "^2" -tenacity = "^8.1.0" - -[package.extras] -extended-testing = ["jinja2 (>=3,<4)"] - -[package.source] -type = "directory" -url = "../../core" - -[[package]] -name = "langchain-text-splitters" -version = "0.0.1" -description = "LangChain text splitting utilities" -optional = false -python-versions = ">=3.8.1,<4.0" -files = [] -develop = true - -[package.dependencies] -langchain-core = "^0.1.28" - -[package.extras] -extended-testing = ["lxml (>=5.1.0,<6.0.0)"] - -[package.source] -type = "directory" -url = "../../text-splitters" - -[[package]] -name = "langsmith" -version = "0.1.21" -description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." -optional = false -python-versions = ">=3.8.1,<4.0" -files = [ - {file = "langsmith-0.1.21-py3-none-any.whl", hash = "sha256:ac3d455d9651879ed306500a0504a2b9b9909225ab178e2446a8bace75e65e23"}, - {file = "langsmith-0.1.21.tar.gz", hash = "sha256:eef6b8a0d3bec7fcfc69ac5b35a16365ffac025dab0c1a4d77d6a7f7d3bbd3de"}, -] - -[package.dependencies] -orjson = ">=3.9.14,<4.0.0" -pydantic = ">=1,<3" -requests = ">=2,<3" - -[[package]] -name = "marshmallow" -version = "3.21.1" -description = "A lightweight library for converting complex datatypes to and from native Python datatypes." -optional = false -python-versions = ">=3.8" -files = [ - {file = "marshmallow-3.21.1-py3-none-any.whl", hash = "sha256:f085493f79efb0644f270a9bf2892843142d80d7174bbbd2f3713f2a589dc633"}, - {file = "marshmallow-3.21.1.tar.gz", hash = "sha256:4e65e9e0d80fc9e609574b9983cf32579f305c718afb30d7233ab818571768c3"}, -] - -[package.dependencies] -packaging = ">=17.0" - -[package.extras] -dev = ["marshmallow[tests]", "pre-commit (>=3.5,<4.0)", "tox"] -docs = ["alabaster (==0.7.16)", "autodocsumm (==0.2.12)", "sphinx (==7.2.6)", "sphinx-issues (==4.0.0)", "sphinx-version-warning (==1.1.2)"] -tests = ["pytest", "pytz", "simplejson"] - -[[package]] -name = "multidict" -version = "6.0.5" -description = "multidict implementation" -optional = false -python-versions = ">=3.7" -files = [ - {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, - {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, - {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"}, - {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"}, - {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"}, - {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"}, - {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"}, - {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"}, - {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"}, - {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, - {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, - {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, - {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"}, - {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"}, - {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"}, - {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"}, - {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"}, - {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"}, - {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"}, - {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"}, - {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"}, - {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"}, - {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"}, - {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"}, - {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"}, - {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, - {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, -] - -[[package]] -name = "mypy" -version = "0.991" -description = "Optional static typing for Python" -optional = false -python-versions = ">=3.7" -files = [ - {file = "mypy-0.991-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7d17e0a9707d0772f4a7b878f04b4fd11f6f5bcb9b3813975a9b13c9332153ab"}, - {file = "mypy-0.991-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0714258640194d75677e86c786e80ccf294972cc76885d3ebbb560f11db0003d"}, - {file = "mypy-0.991-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0c8f3be99e8a8bd403caa8c03be619544bc2c77a7093685dcf308c6b109426c6"}, - {file = "mypy-0.991-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc9ec663ed6c8f15f4ae9d3c04c989b744436c16d26580eaa760ae9dd5d662eb"}, - {file = "mypy-0.991-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4307270436fd7694b41f913eb09210faff27ea4979ecbcd849e57d2da2f65305"}, - {file = "mypy-0.991-cp310-cp310-win_amd64.whl", hash = "sha256:901c2c269c616e6cb0998b33d4adbb4a6af0ac4ce5cd078afd7bc95830e62c1c"}, - {file = "mypy-0.991-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d13674f3fb73805ba0c45eb6c0c3053d218aa1f7abead6e446d474529aafc372"}, - {file = "mypy-0.991-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1c8cd4fb70e8584ca1ed5805cbc7c017a3d1a29fb450621089ffed3e99d1857f"}, - {file = "mypy-0.991-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:209ee89fbb0deed518605edddd234af80506aec932ad28d73c08f1400ef80a33"}, - {file = "mypy-0.991-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37bd02ebf9d10e05b00d71302d2c2e6ca333e6c2a8584a98c00e038db8121f05"}, - {file = "mypy-0.991-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:26efb2fcc6b67e4d5a55561f39176821d2adf88f2745ddc72751b7890f3194ad"}, - {file = "mypy-0.991-cp311-cp311-win_amd64.whl", hash = "sha256:3a700330b567114b673cf8ee7388e949f843b356a73b5ab22dd7cff4742a5297"}, - {file = "mypy-0.991-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:1f7d1a520373e2272b10796c3ff721ea1a0712288cafaa95931e66aa15798813"}, - {file = "mypy-0.991-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:641411733b127c3e0dab94c45af15fea99e4468f99ac88b39efb1ad677da5711"}, - {file = "mypy-0.991-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3d80e36b7d7a9259b740be6d8d906221789b0d836201af4234093cae89ced0cd"}, - {file = "mypy-0.991-cp37-cp37m-win_amd64.whl", hash = "sha256:e62ebaad93be3ad1a828a11e90f0e76f15449371ffeecca4a0a0b9adc99abcef"}, - {file = "mypy-0.991-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b86ce2c1866a748c0f6faca5232059f881cda6dda2a893b9a8373353cfe3715a"}, - {file = "mypy-0.991-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ac6e503823143464538efda0e8e356d871557ef60ccd38f8824a4257acc18d93"}, - {file = "mypy-0.991-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0cca5adf694af539aeaa6ac633a7afe9bbd760df9d31be55ab780b77ab5ae8bf"}, - {file = "mypy-0.991-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a12c56bf73cdab116df96e4ff39610b92a348cc99a1307e1da3c3768bbb5b135"}, - {file = "mypy-0.991-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:652b651d42f155033a1967739788c436491b577b6a44e4c39fb340d0ee7f0d70"}, - {file = "mypy-0.991-cp38-cp38-win_amd64.whl", hash = "sha256:4175593dc25d9da12f7de8de873a33f9b2b8bdb4e827a7cae952e5b1a342e243"}, - {file = "mypy-0.991-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:98e781cd35c0acf33eb0295e8b9c55cdbef64fcb35f6d3aa2186f289bed6e80d"}, - {file = "mypy-0.991-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6d7464bac72a85cb3491c7e92b5b62f3dcccb8af26826257760a552a5e244aa5"}, - {file = "mypy-0.991-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c9166b3f81a10cdf9b49f2d594b21b31adadb3d5e9db9b834866c3258b695be3"}, - {file = "mypy-0.991-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8472f736a5bfb159a5e36740847808f6f5b659960115ff29c7cecec1741c648"}, - {file = "mypy-0.991-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e80e758243b97b618cdf22004beb09e8a2de1af481382e4d84bc52152d1c476"}, - {file = "mypy-0.991-cp39-cp39-win_amd64.whl", hash = "sha256:74e259b5c19f70d35fcc1ad3d56499065c601dfe94ff67ae48b85596b9ec1461"}, - {file = "mypy-0.991-py3-none-any.whl", hash = "sha256:de32edc9b0a7e67c2775e574cb061a537660e51210fbf6006b0b36ea695ae9bb"}, - {file = "mypy-0.991.tar.gz", hash = "sha256:3c0165ba8f354a6d9881809ef29f1a9318a236a6d81c690094c5df32107bde06"}, -] - -[package.dependencies] -mypy-extensions = ">=0.4.3" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = ">=3.10" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -install-types = ["pip"] -python2 = ["typed-ast (>=1.4.0,<2)"] -reports = ["lxml"] - -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.5" -files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, -] - -[[package]] -name = "numpy" -version = "1.24.4" -description = "Fundamental package for array computing in Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "numpy-1.24.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0bfb52d2169d58c1cdb8cc1f16989101639b34c7d3ce60ed70b19c63eba0b64"}, - {file = "numpy-1.24.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ed094d4f0c177b1b8e7aa9cba7d6ceed51c0e569a5318ac0ca9a090680a6a1b1"}, - {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79fc682a374c4a8ed08b331bef9c5f582585d1048fa6d80bc6c35bc384eee9b4"}, - {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ffe43c74893dbf38c2b0a1f5428760a1a9c98285553c89e12d70a96a7f3a4d6"}, - {file = "numpy-1.24.4-cp310-cp310-win32.whl", hash = "sha256:4c21decb6ea94057331e111a5bed9a79d335658c27ce2adb580fb4d54f2ad9bc"}, - {file = "numpy-1.24.4-cp310-cp310-win_amd64.whl", hash = "sha256:b4bea75e47d9586d31e892a7401f76e909712a0fd510f58f5337bea9572c571e"}, - {file = "numpy-1.24.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f136bab9c2cfd8da131132c2cf6cc27331dd6fae65f95f69dcd4ae3c3639c810"}, - {file = "numpy-1.24.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2926dac25b313635e4d6cf4dc4e51c8c0ebfed60b801c799ffc4c32bf3d1254"}, - {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:222e40d0e2548690405b0b3c7b21d1169117391c2e82c378467ef9ab4c8f0da7"}, - {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7215847ce88a85ce39baf9e89070cb860c98fdddacbaa6c0da3ffb31b3350bd5"}, - {file = "numpy-1.24.4-cp311-cp311-win32.whl", hash = "sha256:4979217d7de511a8d57f4b4b5b2b965f707768440c17cb70fbf254c4b225238d"}, - {file = "numpy-1.24.4-cp311-cp311-win_amd64.whl", hash = "sha256:b7b1fc9864d7d39e28f41d089bfd6353cb5f27ecd9905348c24187a768c79694"}, - {file = "numpy-1.24.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1452241c290f3e2a312c137a9999cdbf63f78864d63c79039bda65ee86943f61"}, - {file = "numpy-1.24.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:04640dab83f7c6c85abf9cd729c5b65f1ebd0ccf9de90b270cd61935eef0197f"}, - {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5425b114831d1e77e4b5d812b69d11d962e104095a5b9c3b641a218abcc050e"}, - {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd80e219fd4c71fc3699fc1dadac5dcf4fd882bfc6f7ec53d30fa197b8ee22dc"}, - {file = "numpy-1.24.4-cp38-cp38-win32.whl", hash = "sha256:4602244f345453db537be5314d3983dbf5834a9701b7723ec28923e2889e0bb2"}, - {file = "numpy-1.24.4-cp38-cp38-win_amd64.whl", hash = "sha256:692f2e0f55794943c5bfff12b3f56f99af76f902fc47487bdfe97856de51a706"}, - {file = "numpy-1.24.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2541312fbf09977f3b3ad449c4e5f4bb55d0dbf79226d7724211acc905049400"}, - {file = "numpy-1.24.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9667575fb6d13c95f1b36aca12c5ee3356bf001b714fc354eb5465ce1609e62f"}, - {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3a86ed21e4f87050382c7bc96571755193c4c1392490744ac73d660e8f564a9"}, - {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d11efb4dbecbdf22508d55e48d9c8384db795e1b7b51ea735289ff96613ff74d"}, - {file = "numpy-1.24.4-cp39-cp39-win32.whl", hash = "sha256:6620c0acd41dbcb368610bb2f4d83145674040025e5536954782467100aa8835"}, - {file = "numpy-1.24.4-cp39-cp39-win_amd64.whl", hash = "sha256:befe2bf740fd8373cf56149a5c23a0f601e82869598d41f8e188a0e9869926f8"}, - {file = "numpy-1.24.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:31f13e25b4e304632a4619d0e0777662c2ffea99fcae2029556b17d8ff958aef"}, - {file = "numpy-1.24.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95f7ac6540e95bc440ad77f56e520da5bf877f87dca58bd095288dce8940532a"}, - {file = "numpy-1.24.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e98f220aa76ca2a977fe435f5b04d7b3470c0a2e6312907b37ba6068f26787f2"}, - {file = "numpy-1.24.4.tar.gz", hash = "sha256:80f5e3a4e498641401868df4208b74581206afbee7cf7b8329daae82676d9463"}, -] - -[[package]] -name = "orjson" -version = "3.9.15" -description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" -optional = false -python-versions = ">=3.8" -files = [ - {file = "orjson-3.9.15-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:d61f7ce4727a9fa7680cd6f3986b0e2c732639f46a5e0156e550e35258aa313a"}, - {file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4feeb41882e8aa17634b589533baafdceb387e01e117b1ec65534ec724023d04"}, - {file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fbbeb3c9b2edb5fd044b2a070f127a0ac456ffd079cb82746fc84af01ef021a4"}, - {file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b66bcc5670e8a6b78f0313bcb74774c8291f6f8aeef10fe70e910b8040f3ab75"}, - {file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2973474811db7b35c30248d1129c64fd2bdf40d57d84beed2a9a379a6f57d0ab"}, - {file = "orjson-3.9.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fe41b6f72f52d3da4db524c8653e46243c8c92df826ab5ffaece2dba9cccd58"}, - {file = "orjson-3.9.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4228aace81781cc9d05a3ec3a6d2673a1ad0d8725b4e915f1089803e9efd2b99"}, - {file = "orjson-3.9.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6f7b65bfaf69493c73423ce9db66cfe9138b2f9ef62897486417a8fcb0a92bfe"}, - {file = "orjson-3.9.15-cp310-none-win32.whl", hash = "sha256:2d99e3c4c13a7b0fb3792cc04c2829c9db07838fb6973e578b85c1745e7d0ce7"}, - {file = "orjson-3.9.15-cp310-none-win_amd64.whl", hash = "sha256:b725da33e6e58e4a5d27958568484aa766e825e93aa20c26c91168be58e08cbb"}, - {file = "orjson-3.9.15-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:c8e8fe01e435005d4421f183038fc70ca85d2c1e490f51fb972db92af6e047c2"}, - {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87f1097acb569dde17f246faa268759a71a2cb8c96dd392cd25c668b104cad2f"}, - {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff0f9913d82e1d1fadbd976424c316fbc4d9c525c81d047bbdd16bd27dd98cfc"}, - {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8055ec598605b0077e29652ccfe9372247474375e0e3f5775c91d9434e12d6b1"}, - {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6768a327ea1ba44c9114dba5fdda4a214bdb70129065cd0807eb5f010bfcbb5"}, - {file = "orjson-3.9.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12365576039b1a5a47df01aadb353b68223da413e2e7f98c02403061aad34bde"}, - {file = "orjson-3.9.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:71c6b009d431b3839d7c14c3af86788b3cfac41e969e3e1c22f8a6ea13139404"}, - {file = "orjson-3.9.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e18668f1bd39e69b7fed19fa7cd1cd110a121ec25439328b5c89934e6d30d357"}, - {file = "orjson-3.9.15-cp311-none-win32.whl", hash = "sha256:62482873e0289cf7313461009bf62ac8b2e54bc6f00c6fabcde785709231a5d7"}, - {file = "orjson-3.9.15-cp311-none-win_amd64.whl", hash = "sha256:b3d336ed75d17c7b1af233a6561cf421dee41d9204aa3cfcc6c9c65cd5bb69a8"}, - {file = "orjson-3.9.15-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:82425dd5c7bd3adfe4e94c78e27e2fa02971750c2b7ffba648b0f5d5cc016a73"}, - {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c51378d4a8255b2e7c1e5cc430644f0939539deddfa77f6fac7b56a9784160a"}, - {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6ae4e06be04dc00618247c4ae3f7c3e561d5bc19ab6941427f6d3722a0875ef7"}, - {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bcef128f970bb63ecf9a65f7beafd9b55e3aaf0efc271a4154050fc15cdb386e"}, - {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b72758f3ffc36ca566ba98a8e7f4f373b6c17c646ff8ad9b21ad10c29186f00d"}, - {file = "orjson-3.9.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c57bc7b946cf2efa67ac55766e41764b66d40cbd9489041e637c1304400494"}, - {file = "orjson-3.9.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:946c3a1ef25338e78107fba746f299f926db408d34553b4754e90a7de1d44068"}, - {file = "orjson-3.9.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2f256d03957075fcb5923410058982aea85455d035607486ccb847f095442bda"}, - {file = "orjson-3.9.15-cp312-none-win_amd64.whl", hash = "sha256:5bb399e1b49db120653a31463b4a7b27cf2fbfe60469546baf681d1b39f4edf2"}, - {file = "orjson-3.9.15-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:b17f0f14a9c0ba55ff6279a922d1932e24b13fc218a3e968ecdbf791b3682b25"}, - {file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f6cbd8e6e446fb7e4ed5bac4661a29e43f38aeecbf60c4b900b825a353276a1"}, - {file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:76bc6356d07c1d9f4b782813094d0caf1703b729d876ab6a676f3aaa9a47e37c"}, - {file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fdfa97090e2d6f73dced247a2f2d8004ac6449df6568f30e7fa1a045767c69a6"}, - {file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7413070a3e927e4207d00bd65f42d1b780fb0d32d7b1d951f6dc6ade318e1b5a"}, - {file = "orjson-3.9.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9cf1596680ac1f01839dba32d496136bdd5d8ffb858c280fa82bbfeb173bdd40"}, - {file = "orjson-3.9.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:809d653c155e2cc4fd39ad69c08fdff7f4016c355ae4b88905219d3579e31eb7"}, - {file = "orjson-3.9.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:920fa5a0c5175ab14b9c78f6f820b75804fb4984423ee4c4f1e6d748f8b22bc1"}, - {file = "orjson-3.9.15-cp38-none-win32.whl", hash = "sha256:2b5c0f532905e60cf22a511120e3719b85d9c25d0e1c2a8abb20c4dede3b05a5"}, - {file = "orjson-3.9.15-cp38-none-win_amd64.whl", hash = "sha256:67384f588f7f8daf040114337d34a5188346e3fae6c38b6a19a2fe8c663a2f9b"}, - {file = "orjson-3.9.15-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:6fc2fe4647927070df3d93f561d7e588a38865ea0040027662e3e541d592811e"}, - {file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34cbcd216e7af5270f2ffa63a963346845eb71e174ea530867b7443892d77180"}, - {file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f541587f5c558abd93cb0de491ce99a9ef8d1ae29dd6ab4dbb5a13281ae04cbd"}, - {file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:92255879280ef9c3c0bcb327c5a1b8ed694c290d61a6a532458264f887f052cb"}, - {file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:05a1f57fb601c426635fcae9ddbe90dfc1ed42245eb4c75e4960440cac667262"}, - {file = "orjson-3.9.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ede0bde16cc6e9b96633df1631fbcd66491d1063667f260a4f2386a098393790"}, - {file = "orjson-3.9.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e88b97ef13910e5f87bcbc4dd7979a7de9ba8702b54d3204ac587e83639c0c2b"}, - {file = "orjson-3.9.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:57d5d8cf9c27f7ef6bc56a5925c7fbc76b61288ab674eb352c26ac780caa5b10"}, - {file = "orjson-3.9.15-cp39-none-win32.whl", hash = "sha256:001f4eb0ecd8e9ebd295722d0cbedf0748680fb9998d3993abaed2f40587257a"}, - {file = "orjson-3.9.15-cp39-none-win_amd64.whl", hash = "sha256:ea0b183a5fe6b2b45f3b854b0d19c4e932d6f5934ae1f723b07cf9560edd4ec7"}, - {file = "orjson-3.9.15.tar.gz", hash = "sha256:95cae920959d772f30ab36d3b25f83bb0f3be671e986c72ce22f8fa700dae061"}, -] - -[[package]] -name = "packaging" -version = "23.2" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.7" -files = [ - {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, - {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, -] - -[[package]] -name = "pluggy" -version = "1.4.0" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, - {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - -[[package]] -name = "pydantic" -version = "2.6.3" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pydantic-2.6.3-py3-none-any.whl", hash = "sha256:72c6034df47f46ccdf81869fddb81aade68056003900a8724a4f160700016a2a"}, - {file = "pydantic-2.6.3.tar.gz", hash = "sha256:e07805c4c7f5c6826e33a1d4c9d47950d7eaf34868e2690f8594d2e30241f11f"}, -] - -[package.dependencies] -annotated-types = ">=0.4.0" -pydantic-core = "2.16.3" -typing-extensions = ">=4.6.1" - -[package.extras] -email = ["email-validator (>=2.0.0)"] - -[[package]] -name = "pydantic-core" -version = "2.16.3" -description = "" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pydantic_core-2.16.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:75b81e678d1c1ede0785c7f46690621e4c6e63ccd9192af1f0bd9d504bbb6bf4"}, - {file = "pydantic_core-2.16.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9c865a7ee6f93783bd5d781af5a4c43dadc37053a5b42f7d18dc019f8c9d2bd1"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:162e498303d2b1c036b957a1278fa0899d02b2842f1ff901b6395104c5554a45"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f583bd01bbfbff4eaee0868e6fc607efdfcc2b03c1c766b06a707abbc856187"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b926dd38db1519ed3043a4de50214e0d600d404099c3392f098a7f9d75029ff8"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:716b542728d4c742353448765aa7cdaa519a7b82f9564130e2b3f6766018c9ec"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4ad7f7ee1a13d9cb49d8198cd7d7e3aa93e425f371a68235f784e99741561f"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd87f48924f360e5d1c5f770d6155ce0e7d83f7b4e10c2f9ec001c73cf475c99"}, - {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0df446663464884297c793874573549229f9eca73b59360878f382a0fc085979"}, - {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4df8a199d9f6afc5ae9a65f8f95ee52cae389a8c6b20163762bde0426275b7db"}, - {file = "pydantic_core-2.16.3-cp310-none-win32.whl", hash = "sha256:456855f57b413f077dff513a5a28ed838dbbb15082ba00f80750377eed23d132"}, - {file = "pydantic_core-2.16.3-cp310-none-win_amd64.whl", hash = "sha256:732da3243e1b8d3eab8c6ae23ae6a58548849d2e4a4e03a1924c8ddf71a387cb"}, - {file = "pydantic_core-2.16.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:519ae0312616026bf4cedc0fe459e982734f3ca82ee8c7246c19b650b60a5ee4"}, - {file = "pydantic_core-2.16.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b3992a322a5617ded0a9f23fd06dbc1e4bd7cf39bc4ccf344b10f80af58beacd"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d62da299c6ecb04df729e4b5c52dc0d53f4f8430b4492b93aa8de1f541c4aac"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2acca2be4bb2f2147ada8cac612f8a98fc09f41c89f87add7256ad27332c2fda"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b662180108c55dfbf1280d865b2d116633d436cfc0bba82323554873967b340"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e7c6ed0dc9d8e65f24f5824291550139fe6f37fac03788d4580da0d33bc00c97"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1bb0827f56654b4437955555dc3aeeebeddc47c2d7ed575477f082622c49e"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e56f8186d6210ac7ece503193ec84104da7ceb98f68ce18c07282fcc2452e76f"}, - {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:936e5db01dd49476fa8f4383c259b8b1303d5dd5fb34c97de194560698cc2c5e"}, - {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:33809aebac276089b78db106ee692bdc9044710e26f24a9a2eaa35a0f9fa70ba"}, - {file = "pydantic_core-2.16.3-cp311-none-win32.whl", hash = "sha256:ded1c35f15c9dea16ead9bffcde9bb5c7c031bff076355dc58dcb1cb436c4721"}, - {file = "pydantic_core-2.16.3-cp311-none-win_amd64.whl", hash = "sha256:d89ca19cdd0dd5f31606a9329e309d4fcbb3df860960acec32630297d61820df"}, - {file = "pydantic_core-2.16.3-cp311-none-win_arm64.whl", hash = "sha256:6162f8d2dc27ba21027f261e4fa26f8bcb3cf9784b7f9499466a311ac284b5b9"}, - {file = "pydantic_core-2.16.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f56ae86b60ea987ae8bcd6654a887238fd53d1384f9b222ac457070b7ac4cff"}, - {file = "pydantic_core-2.16.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9bd22a2a639e26171068f8ebb5400ce2c1bc7d17959f60a3b753ae13c632975"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4204e773b4b408062960e65468d5346bdfe139247ee5f1ca2a378983e11388a2"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f651dd19363c632f4abe3480a7c87a9773be27cfe1341aef06e8759599454120"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aaf09e615a0bf98d406657e0008e4a8701b11481840be7d31755dc9f97c44053"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8e47755d8152c1ab5b55928ab422a76e2e7b22b5ed8e90a7d584268dd49e9c6b"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:500960cb3a0543a724a81ba859da816e8cf01b0e6aaeedf2c3775d12ee49cade"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf6204fe865da605285c34cf1172879d0314ff267b1c35ff59de7154f35fdc2e"}, - {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d33dd21f572545649f90c38c227cc8631268ba25c460b5569abebdd0ec5974ca"}, - {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:49d5d58abd4b83fb8ce763be7794d09b2f50f10aa65c0f0c1696c677edeb7cbf"}, - {file = "pydantic_core-2.16.3-cp312-none-win32.whl", hash = "sha256:f53aace168a2a10582e570b7736cc5bef12cae9cf21775e3eafac597e8551fbe"}, - {file = "pydantic_core-2.16.3-cp312-none-win_amd64.whl", hash = "sha256:0d32576b1de5a30d9a97f300cc6a3f4694c428d956adbc7e6e2f9cad279e45ed"}, - {file = "pydantic_core-2.16.3-cp312-none-win_arm64.whl", hash = "sha256:ec08be75bb268473677edb83ba71e7e74b43c008e4a7b1907c6d57e940bf34b6"}, - {file = "pydantic_core-2.16.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b1f6f5938d63c6139860f044e2538baeee6f0b251a1816e7adb6cbce106a1f01"}, - {file = "pydantic_core-2.16.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2a1ef6a36fdbf71538142ed604ad19b82f67b05749512e47f247a6ddd06afdc7"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:704d35ecc7e9c31d48926150afada60401c55efa3b46cd1ded5a01bdffaf1d48"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d937653a696465677ed583124b94a4b2d79f5e30b2c46115a68e482c6a591c8a"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9803edf8e29bd825f43481f19c37f50d2b01899448273b3a7758441b512acf8"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72282ad4892a9fb2da25defeac8c2e84352c108705c972db82ab121d15f14e6d"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f752826b5b8361193df55afcdf8ca6a57d0232653494ba473630a83ba50d8c9"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4384a8f68ddb31a0b0c3deae88765f5868a1b9148939c3f4121233314ad5532c"}, - {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4b2bf78342c40b3dc830880106f54328928ff03e357935ad26c7128bbd66ce8"}, - {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:13dcc4802961b5f843a9385fc821a0b0135e8c07fc3d9949fd49627c1a5e6ae5"}, - {file = "pydantic_core-2.16.3-cp38-none-win32.whl", hash = "sha256:e3e70c94a0c3841e6aa831edab1619ad5c511199be94d0c11ba75fe06efe107a"}, - {file = "pydantic_core-2.16.3-cp38-none-win_amd64.whl", hash = "sha256:ecdf6bf5f578615f2e985a5e1f6572e23aa632c4bd1dc67f8f406d445ac115ed"}, - {file = "pydantic_core-2.16.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:bda1ee3e08252b8d41fa5537413ffdddd58fa73107171a126d3b9ff001b9b820"}, - {file = "pydantic_core-2.16.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:21b888c973e4f26b7a96491c0965a8a312e13be108022ee510248fe379a5fa23"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be0ec334369316fa73448cc8c982c01e5d2a81c95969d58b8f6e272884df0074"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5b6079cc452a7c53dd378c6f881ac528246b3ac9aae0f8eef98498a75657805"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee8d5f878dccb6d499ba4d30d757111847b6849ae07acdd1205fffa1fc1253c"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7233d65d9d651242a68801159763d09e9ec96e8a158dbf118dc090cd77a104c9"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6119dc90483a5cb50a1306adb8d52c66e447da88ea44f323e0ae1a5fcb14256"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:578114bc803a4c1ff9946d977c221e4376620a46cf78da267d946397dc9514a8"}, - {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d8f99b147ff3fcf6b3cc60cb0c39ea443884d5559a30b1481e92495f2310ff2b"}, - {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4ac6b4ce1e7283d715c4b729d8f9dab9627586dafce81d9eaa009dd7f25dd972"}, - {file = "pydantic_core-2.16.3-cp39-none-win32.whl", hash = "sha256:e7774b570e61cb998490c5235740d475413a1f6de823169b4cf94e2fe9e9f6b2"}, - {file = "pydantic_core-2.16.3-cp39-none-win_amd64.whl", hash = "sha256:9091632a25b8b87b9a605ec0e61f241c456e9248bfdcf7abdf344fdb169c81cf"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:36fa178aacbc277bc6b62a2c3da95226520da4f4e9e206fdf076484363895d2c"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:dcca5d2bf65c6fb591fff92da03f94cd4f315972f97c21975398bd4bd046854a"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a72fb9963cba4cd5793854fd12f4cfee731e86df140f59ff52a49b3552db241"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b60cc1a081f80a2105a59385b92d82278b15d80ebb3adb200542ae165cd7d183"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cbcc558401de90a746d02ef330c528f2e668c83350f045833543cd57ecead1ad"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fee427241c2d9fb7192b658190f9f5fd6dfe41e02f3c1489d2ec1e6a5ab1e04a"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f4cb85f693044e0f71f394ff76c98ddc1bc0953e48c061725e540396d5c8a2e1"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b29eeb887aa931c2fcef5aa515d9d176d25006794610c264ddc114c053bf96fe"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a425479ee40ff021f8216c9d07a6a3b54b31c8267c6e17aa88b70d7ebd0e5e5b"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5c5cbc703168d1b7a838668998308018a2718c2130595e8e190220238addc96f"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99b6add4c0b39a513d323d3b93bc173dac663c27b99860dd5bf491b240d26137"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f76ee558751746d6a38f89d60b6228fa174e5172d143886af0f85aa306fd89"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:00ee1c97b5364b84cb0bd82e9bbf645d5e2871fb8c58059d158412fee2d33d8a"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:287073c66748f624be4cef893ef9174e3eb88fe0b8a78dc22e88eca4bc357ca6"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ed25e1835c00a332cb10c683cd39da96a719ab1dfc08427d476bce41b92531fc"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:86b3d0033580bd6bbe07590152007275bd7af95f98eaa5bd36f3da219dcd93da"}, - {file = "pydantic_core-2.16.3.tar.gz", hash = "sha256:1cac689f80a3abab2d3c0048b29eea5751114054f032a941a32de4c852c59cad"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "pytest" -version = "7.4.4" -description = "pytest: simple powerful testing with Python" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, - {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=0.12,<2.0" -tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} - -[package.extras] -testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] - -[[package]] -name = "pytest-asyncio" -version = "0.21.1" -description = "Pytest support for asyncio" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pytest-asyncio-0.21.1.tar.gz", hash = "sha256:40a7eae6dded22c7b604986855ea48400ab15b069ae38116e8c01238e9eeb64d"}, - {file = "pytest_asyncio-0.21.1-py3-none-any.whl", hash = "sha256:8666c1c8ac02631d7c51ba282e0c69a8a452b211ffedf2599099845da5c5c37b"}, -] - -[package.dependencies] -pytest = ">=7.0.0" - -[package.extras] -docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] -testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"] - -[[package]] -name = "pytest-mock" -version = "3.12.0" -description = "Thin-wrapper around the mock package for easier use with pytest" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pytest-mock-3.12.0.tar.gz", hash = "sha256:31a40f038c22cad32287bb43932054451ff5583ff094bca6f675df2f8bc1a6e9"}, - {file = "pytest_mock-3.12.0-py3-none-any.whl", hash = "sha256:0972719a7263072da3a21c7f4773069bcc7486027d7e8e1f81d98a47e701bc4f"}, -] - -[package.dependencies] -pytest = ">=5.0" - -[package.extras] -dev = ["pre-commit", "pytest-asyncio", "tox"] - -[[package]] -name = "pytest-watcher" -version = "0.3.5" -description = "Automatically rerun your tests on file modifications" -optional = false -python-versions = ">=3.7.0,<4.0.0" -files = [ - {file = "pytest_watcher-0.3.5-py3-none-any.whl", hash = "sha256:af00ca52c7be22dc34c0fd3d7ffef99057207a73b05dc5161fe3b2fe91f58130"}, - {file = "pytest_watcher-0.3.5.tar.gz", hash = "sha256:8896152460ba2b1a8200c12117c6611008ec96c8b2d811f0a05ab8a82b043ff8"}, -] - -[package.dependencies] -tomli = {version = ">=2.0.1,<3.0.0", markers = "python_version < \"3.11\""} -watchdog = ">=2.0.0" - -[[package]] -name = "python-dateutil" -version = "2.9.0.post0" -description = "Extensions to the standard Python datetime module" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -files = [ - {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, - {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, -] - -[package.dependencies] -six = ">=1.5" - -[[package]] -name = "pyyaml" -version = "6.0.1" -description = "YAML parser and emitter for Python" -optional = false -python-versions = ">=3.6" -files = [ - {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, - {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, - {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, - {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, - {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, - {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, - {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, - {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, - {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, - {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, - {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, - {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, - {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, - {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, -] - -[[package]] -name = "requests" -version = "2.31.0" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.7" -files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "ruff" -version = "0.1.15" -description = "An extremely fast Python linter and code formatter, written in Rust." -optional = false -python-versions = ">=3.7" -files = [ - {file = "ruff-0.1.15-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:5fe8d54df166ecc24106db7dd6a68d44852d14eb0729ea4672bb4d96c320b7df"}, - {file = "ruff-0.1.15-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6f0bfbb53c4b4de117ac4d6ddfd33aa5fc31beeaa21d23c45c6dd249faf9126f"}, - {file = "ruff-0.1.15-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0d432aec35bfc0d800d4f70eba26e23a352386be3a6cf157083d18f6f5881c8"}, - {file = "ruff-0.1.15-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9405fa9ac0e97f35aaddf185a1be194a589424b8713e3b97b762336ec79ff807"}, - {file = "ruff-0.1.15-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c66ec24fe36841636e814b8f90f572a8c0cb0e54d8b5c2d0e300d28a0d7bffec"}, - {file = "ruff-0.1.15-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:6f8ad828f01e8dd32cc58bc28375150171d198491fc901f6f98d2a39ba8e3ff5"}, - {file = "ruff-0.1.15-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86811954eec63e9ea162af0ffa9f8d09088bab51b7438e8b6488b9401863c25e"}, - {file = "ruff-0.1.15-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fd4025ac5e87d9b80e1f300207eb2fd099ff8200fa2320d7dc066a3f4622dc6b"}, - {file = "ruff-0.1.15-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b17b93c02cdb6aeb696effecea1095ac93f3884a49a554a9afa76bb125c114c1"}, - {file = "ruff-0.1.15-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:ddb87643be40f034e97e97f5bc2ef7ce39de20e34608f3f829db727a93fb82c5"}, - {file = "ruff-0.1.15-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:abf4822129ed3a5ce54383d5f0e964e7fef74a41e48eb1dfad404151efc130a2"}, - {file = "ruff-0.1.15-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6c629cf64bacfd136c07c78ac10a54578ec9d1bd2a9d395efbee0935868bf852"}, - {file = "ruff-0.1.15-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1bab866aafb53da39c2cadfb8e1c4550ac5340bb40300083eb8967ba25481447"}, - {file = "ruff-0.1.15-py3-none-win32.whl", hash = "sha256:2417e1cb6e2068389b07e6fa74c306b2810fe3ee3476d5b8a96616633f40d14f"}, - {file = "ruff-0.1.15-py3-none-win_amd64.whl", hash = "sha256:3837ac73d869efc4182d9036b1405ef4c73d9b1f88da2413875e34e0d6919587"}, - {file = "ruff-0.1.15-py3-none-win_arm64.whl", hash = "sha256:9a933dfb1c14ec7a33cceb1e49ec4a16b51ce3c20fd42663198746efc0427360"}, - {file = "ruff-0.1.15.tar.gz", hash = "sha256:f6dfa8c1b21c913c326919056c390966648b680966febcb796cc9d1aaab8564e"}, -] - -[[package]] -name = "six" -version = "1.16.0" -description = "Python 2 and 3 compatibility utilities" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] - -[[package]] -name = "sniffio" -version = "1.3.1" -description = "Sniff out which async library your code is running under" -optional = false -python-versions = ">=3.7" -files = [ - {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, - {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, -] - -[[package]] -name = "sqlalchemy" -version = "2.0.28" -description = "Database Abstraction Library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "SQLAlchemy-2.0.28-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0b148ab0438f72ad21cb004ce3bdaafd28465c4276af66df3b9ecd2037bf252"}, - {file = "SQLAlchemy-2.0.28-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bbda76961eb8f27e6ad3c84d1dc56d5bc61ba8f02bd20fcf3450bd421c2fcc9c"}, - {file = "SQLAlchemy-2.0.28-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feea693c452d85ea0015ebe3bb9cd15b6f49acc1a31c28b3c50f4db0f8fb1e71"}, - {file = "SQLAlchemy-2.0.28-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5da98815f82dce0cb31fd1e873a0cb30934971d15b74e0d78cf21f9e1b05953f"}, - {file = "SQLAlchemy-2.0.28-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a5adf383c73f2d49ad15ff363a8748319ff84c371eed59ffd0127355d6ea1da"}, - {file = "SQLAlchemy-2.0.28-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56856b871146bfead25fbcaed098269d90b744eea5cb32a952df00d542cdd368"}, - {file = "SQLAlchemy-2.0.28-cp310-cp310-win32.whl", hash = "sha256:943aa74a11f5806ab68278284a4ddd282d3fb348a0e96db9b42cb81bf731acdc"}, - {file = "SQLAlchemy-2.0.28-cp310-cp310-win_amd64.whl", hash = "sha256:c6c4da4843e0dabde41b8f2e8147438330924114f541949e6318358a56d1875a"}, - {file = "SQLAlchemy-2.0.28-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46a3d4e7a472bfff2d28db838669fc437964e8af8df8ee1e4548e92710929adc"}, - {file = "SQLAlchemy-2.0.28-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0d3dd67b5d69794cfe82862c002512683b3db038b99002171f624712fa71aeaa"}, - {file = "SQLAlchemy-2.0.28-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61e2e41656a673b777e2f0cbbe545323dbe0d32312f590b1bc09da1de6c2a02"}, - {file = "SQLAlchemy-2.0.28-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0315d9125a38026227f559488fe7f7cee1bd2fbc19f9fd637739dc50bb6380b2"}, - {file = "SQLAlchemy-2.0.28-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:af8ce2d31679006e7b747d30a89cd3ac1ec304c3d4c20973f0f4ad58e2d1c4c9"}, - {file = "SQLAlchemy-2.0.28-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:81ba314a08c7ab701e621b7ad079c0c933c58cdef88593c59b90b996e8b58fa5"}, - {file = "SQLAlchemy-2.0.28-cp311-cp311-win32.whl", hash = "sha256:1ee8bd6d68578e517943f5ebff3afbd93fc65f7ef8f23becab9fa8fb315afb1d"}, - {file = "SQLAlchemy-2.0.28-cp311-cp311-win_amd64.whl", hash = "sha256:ad7acbe95bac70e4e687a4dc9ae3f7a2f467aa6597049eeb6d4a662ecd990bb6"}, - {file = "SQLAlchemy-2.0.28-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d3499008ddec83127ab286c6f6ec82a34f39c9817f020f75eca96155f9765097"}, - {file = "SQLAlchemy-2.0.28-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9b66fcd38659cab5d29e8de5409cdf91e9986817703e1078b2fdaad731ea66f5"}, - {file = "SQLAlchemy-2.0.28-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bea30da1e76cb1acc5b72e204a920a3a7678d9d52f688f087dc08e54e2754c67"}, - {file = "SQLAlchemy-2.0.28-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:124202b4e0edea7f08a4db8c81cc7859012f90a0d14ba2bf07c099aff6e96462"}, - {file = "SQLAlchemy-2.0.28-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e23b88c69497a6322b5796c0781400692eca1ae5532821b39ce81a48c395aae9"}, - {file = "SQLAlchemy-2.0.28-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b6303bfd78fb3221847723104d152e5972c22367ff66edf09120fcde5ddc2e2"}, - {file = "SQLAlchemy-2.0.28-cp312-cp312-win32.whl", hash = "sha256:a921002be69ac3ab2cf0c3017c4e6a3377f800f1fca7f254c13b5f1a2f10022c"}, - {file = "SQLAlchemy-2.0.28-cp312-cp312-win_amd64.whl", hash = "sha256:b4a2cf92995635b64876dc141af0ef089c6eea7e05898d8d8865e71a326c0385"}, - {file = "SQLAlchemy-2.0.28-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e91b5e341f8c7f1e5020db8e5602f3ed045a29f8e27f7f565e0bdee3338f2c7"}, - {file = "SQLAlchemy-2.0.28-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45c7b78dfc7278329f27be02c44abc0d69fe235495bb8e16ec7ef1b1a17952db"}, - {file = "SQLAlchemy-2.0.28-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3eba73ef2c30695cb7eabcdb33bb3d0b878595737479e152468f3ba97a9c22a4"}, - {file = "SQLAlchemy-2.0.28-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5df5d1dafb8eee89384fb7a1f79128118bc0ba50ce0db27a40750f6f91aa99d5"}, - {file = "SQLAlchemy-2.0.28-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2858bbab1681ee5406650202950dc8f00e83b06a198741b7c656e63818633526"}, - {file = "SQLAlchemy-2.0.28-cp37-cp37m-win32.whl", hash = "sha256:9461802f2e965de5cff80c5a13bc945abea7edaa1d29360b485c3d2b56cdb075"}, - {file = "SQLAlchemy-2.0.28-cp37-cp37m-win_amd64.whl", hash = "sha256:a6bec1c010a6d65b3ed88c863d56b9ea5eeefdf62b5e39cafd08c65f5ce5198b"}, - {file = "SQLAlchemy-2.0.28-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:843a882cadebecc655a68bd9a5b8aa39b3c52f4a9a5572a3036fb1bb2ccdc197"}, - {file = "SQLAlchemy-2.0.28-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:dbb990612c36163c6072723523d2be7c3eb1517bbdd63fe50449f56afafd1133"}, - {file = "SQLAlchemy-2.0.28-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7e4baf9161d076b9a7e432fce06217b9bd90cfb8f1d543d6e8c4595627edb9"}, - {file = "SQLAlchemy-2.0.28-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0a5354cb4de9b64bccb6ea33162cb83e03dbefa0d892db88a672f5aad638a75"}, - {file = "SQLAlchemy-2.0.28-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:fffcc8edc508801ed2e6a4e7b0d150a62196fd28b4e16ab9f65192e8186102b6"}, - {file = "SQLAlchemy-2.0.28-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aca7b6d99a4541b2ebab4494f6c8c2f947e0df4ac859ced575238e1d6ca5716b"}, - {file = "SQLAlchemy-2.0.28-cp38-cp38-win32.whl", hash = "sha256:8c7f10720fc34d14abad5b647bc8202202f4948498927d9f1b4df0fb1cf391b7"}, - {file = "SQLAlchemy-2.0.28-cp38-cp38-win_amd64.whl", hash = "sha256:243feb6882b06a2af68ecf4bec8813d99452a1b62ba2be917ce6283852cf701b"}, - {file = "SQLAlchemy-2.0.28-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fc4974d3684f28b61b9a90fcb4c41fb340fd4b6a50c04365704a4da5a9603b05"}, - {file = "SQLAlchemy-2.0.28-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:87724e7ed2a936fdda2c05dbd99d395c91ea3c96f029a033a4a20e008dd876bf"}, - {file = "SQLAlchemy-2.0.28-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68722e6a550f5de2e3cfe9da6afb9a7dd15ef7032afa5651b0f0c6b3adb8815d"}, - {file = "SQLAlchemy-2.0.28-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:328529f7c7f90adcd65aed06a161851f83f475c2f664a898af574893f55d9e53"}, - {file = "SQLAlchemy-2.0.28-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:df40c16a7e8be7413b885c9bf900d402918cc848be08a59b022478804ea076b8"}, - {file = "SQLAlchemy-2.0.28-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:426f2fa71331a64f5132369ede5171c52fd1df1bd9727ce621f38b5b24f48750"}, - {file = "SQLAlchemy-2.0.28-cp39-cp39-win32.whl", hash = "sha256:33157920b233bc542ce497a81a2e1452e685a11834c5763933b440fedd1d8e2d"}, - {file = "SQLAlchemy-2.0.28-cp39-cp39-win_amd64.whl", hash = "sha256:2f60843068e432311c886c5f03c4664acaef507cf716f6c60d5fde7265be9d7b"}, - {file = "SQLAlchemy-2.0.28-py3-none-any.whl", hash = "sha256:78bb7e8da0183a8301352d569900d9d3594c48ac21dc1c2ec6b3121ed8b6c986"}, - {file = "SQLAlchemy-2.0.28.tar.gz", hash = "sha256:dd53b6c4e6d960600fd6532b79ee28e2da489322fcf6648738134587faf767b6"}, -] - -[package.dependencies] -greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""} -typing-extensions = ">=4.6.0" - -[package.extras] -aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"] -aioodbc = ["aioodbc", "greenlet (!=0.4.17)"] -aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing_extensions (!=3.10.0.1)"] -asyncio = ["greenlet (!=0.4.17)"] -asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"] -mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"] -mssql = ["pyodbc"] -mssql-pymssql = ["pymssql"] -mssql-pyodbc = ["pyodbc"] -mypy = ["mypy (>=0.910)"] -mysql = ["mysqlclient (>=1.4.0)"] -mysql-connector = ["mysql-connector-python"] -oracle = ["cx_oracle (>=8)"] -oracle-oracledb = ["oracledb (>=1.0.1)"] -postgresql = ["psycopg2 (>=2.7)"] -postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"] -postgresql-pg8000 = ["pg8000 (>=1.29.1)"] -postgresql-psycopg = ["psycopg (>=3.0.7)"] -postgresql-psycopg2binary = ["psycopg2-binary"] -postgresql-psycopg2cffi = ["psycopg2cffi"] -postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] -pymysql = ["pymysql"] -sqlcipher = ["sqlcipher3_binary"] - -[[package]] -name = "syrupy" -version = "4.6.1" -description = "Pytest Snapshot Test Utility" -optional = false -python-versions = ">=3.8.1,<4" -files = [ - {file = "syrupy-4.6.1-py3-none-any.whl", hash = "sha256:203e52f9cb9fa749cf683f29bd68f02c16c3bc7e7e5fe8f2fc59bdfe488ce133"}, - {file = "syrupy-4.6.1.tar.gz", hash = "sha256:37a835c9ce7857eeef86d62145885e10b3cb9615bc6abeb4ce404b3f18e1bb36"}, -] - -[package.dependencies] -pytest = ">=7.0.0,<9.0.0" - -[[package]] -name = "tenacity" -version = "8.2.3" -description = "Retry code until it succeeds" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tenacity-8.2.3-py3-none-any.whl", hash = "sha256:ce510e327a630c9e1beaf17d42e6ffacc88185044ad85cf74c0a8887c6a0f88c"}, - {file = "tenacity-8.2.3.tar.gz", hash = "sha256:5398ef0d78e63f40007c1fb4c0bff96e1911394d2fa8d194f77619c05ff6cc8a"}, -] - -[package.extras] -doc = ["reno", "sphinx", "tornado (>=4.5)"] - -[[package]] -name = "tomli" -version = "2.0.1" -description = "A lil' TOML parser" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, -] - -[[package]] -name = "typing-extensions" -version = "4.10.0" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -files = [ - {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"}, - {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, -] - -[[package]] -name = "typing-inspect" -version = "0.9.0" -description = "Runtime inspection utilities for typing module." -optional = false -python-versions = "*" -files = [ - {file = "typing_inspect-0.9.0-py3-none-any.whl", hash = "sha256:9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f"}, - {file = "typing_inspect-0.9.0.tar.gz", hash = "sha256:b23fc42ff6f6ef6954e4852c1fb512cdd18dbea03134f91f856a95ccc9461f78"}, -] - -[package.dependencies] -mypy-extensions = ">=0.3.0" -typing-extensions = ">=3.7.4" - -[[package]] -name = "urllib3" -version = "2.2.1" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.8" -files = [ - {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, - {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -h2 = ["h2 (>=4,<5)"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] - -[[package]] -name = "watchdog" -version = "4.0.0" -description = "Filesystem events monitoring" -optional = false -python-versions = ">=3.8" -files = [ - {file = "watchdog-4.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:39cb34b1f1afbf23e9562501673e7146777efe95da24fab5707b88f7fb11649b"}, - {file = "watchdog-4.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c522392acc5e962bcac3b22b9592493ffd06d1fc5d755954e6be9f4990de932b"}, - {file = "watchdog-4.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6c47bdd680009b11c9ac382163e05ca43baf4127954c5f6d0250e7d772d2b80c"}, - {file = "watchdog-4.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8350d4055505412a426b6ad8c521bc7d367d1637a762c70fdd93a3a0d595990b"}, - {file = "watchdog-4.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c17d98799f32e3f55f181f19dd2021d762eb38fdd381b4a748b9f5a36738e935"}, - {file = "watchdog-4.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4986db5e8880b0e6b7cd52ba36255d4793bf5cdc95bd6264806c233173b1ec0b"}, - {file = "watchdog-4.0.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:11e12fafb13372e18ca1bbf12d50f593e7280646687463dd47730fd4f4d5d257"}, - {file = "watchdog-4.0.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5369136a6474678e02426bd984466343924d1df8e2fd94a9b443cb7e3aa20d19"}, - {file = "watchdog-4.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76ad8484379695f3fe46228962017a7e1337e9acadafed67eb20aabb175df98b"}, - {file = "watchdog-4.0.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:45cc09cc4c3b43fb10b59ef4d07318d9a3ecdbff03abd2e36e77b6dd9f9a5c85"}, - {file = "watchdog-4.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eed82cdf79cd7f0232e2fdc1ad05b06a5e102a43e331f7d041e5f0e0a34a51c4"}, - {file = "watchdog-4.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ba30a896166f0fee83183cec913298151b73164160d965af2e93a20bbd2ab605"}, - {file = "watchdog-4.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d18d7f18a47de6863cd480734613502904611730f8def45fc52a5d97503e5101"}, - {file = "watchdog-4.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2895bf0518361a9728773083908801a376743bcc37dfa252b801af8fd281b1ca"}, - {file = "watchdog-4.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:87e9df830022488e235dd601478c15ad73a0389628588ba0b028cb74eb72fed8"}, - {file = "watchdog-4.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6e949a8a94186bced05b6508faa61b7adacc911115664ccb1923b9ad1f1ccf7b"}, - {file = "watchdog-4.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6a4db54edea37d1058b08947c789a2354ee02972ed5d1e0dca9b0b820f4c7f92"}, - {file = "watchdog-4.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d31481ccf4694a8416b681544c23bd271f5a123162ab603c7d7d2dd7dd901a07"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:8fec441f5adcf81dd240a5fe78e3d83767999771630b5ddfc5867827a34fa3d3"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:6a9c71a0b02985b4b0b6d14b875a6c86ddea2fdbebd0c9a720a806a8bbffc69f"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:557ba04c816d23ce98a06e70af6abaa0485f6d94994ec78a42b05d1c03dcbd50"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:d0f9bd1fd919134d459d8abf954f63886745f4660ef66480b9d753a7c9d40927"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:f9b2fdca47dc855516b2d66eef3c39f2672cbf7e7a42e7e67ad2cbfcd6ba107d"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:73c7a935e62033bd5e8f0da33a4dcb763da2361921a69a5a95aaf6c93aa03a87"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:6a80d5cae8c265842c7419c560b9961561556c4361b297b4c431903f8c33b269"}, - {file = "watchdog-4.0.0-py3-none-win32.whl", hash = "sha256:8f9a542c979df62098ae9c58b19e03ad3df1c9d8c6895d96c0d51da17b243b1c"}, - {file = "watchdog-4.0.0-py3-none-win_amd64.whl", hash = "sha256:f970663fa4f7e80401a7b0cbeec00fa801bf0287d93d48368fc3e6fa32716245"}, - {file = "watchdog-4.0.0-py3-none-win_ia64.whl", hash = "sha256:9a03e16e55465177d416699331b0f3564138f1807ecc5f2de9d55d8f188d08c7"}, - {file = "watchdog-4.0.0.tar.gz", hash = "sha256:e3e7065cbdabe6183ab82199d7a4f6b3ba0a438c5a512a68559846ccb76a78ec"}, -] - -[package.extras] -watchmedo = ["PyYAML (>=3.10)"] - -[[package]] -name = "yarl" -version = "1.9.4" -description = "Yet another URL library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e"}, - {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2"}, - {file = "yarl-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541"}, - {file = "yarl-1.9.4-cp310-cp310-win32.whl", hash = "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d"}, - {file = "yarl-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"}, - {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"}, - {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"}, - {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"}, - {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"}, - {file = "yarl-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434"}, - {file = "yarl-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749"}, - {file = "yarl-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3"}, - {file = "yarl-1.9.4-cp38-cp38-win32.whl", hash = "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece"}, - {file = "yarl-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0"}, - {file = "yarl-1.9.4-cp39-cp39-win32.whl", hash = "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575"}, - {file = "yarl-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15"}, - {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"}, - {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"}, -] - -[package.dependencies] -idna = ">=2.0" -multidict = ">=4.0" - -[metadata] -lock-version = "2.0" -python-versions = ">=3.8.1,<4.0" -content-hash = "5475c831b3bcde3a804f1528e2ad2028e7cfb7981dc8790081d66aa8a3769460" diff --git a/libs/partners/elasticsearch/pyproject.toml b/libs/partners/elasticsearch/pyproject.toml deleted file mode 100644 index 71552bdf28..0000000000 --- a/libs/partners/elasticsearch/pyproject.toml +++ /dev/null @@ -1,96 +0,0 @@ -[tool.poetry] -name = "langchain-elasticsearch" -version = "0.1.1" -description = "An integration package connecting Elasticsearch and LangChain" -authors = [] -readme = "README.md" -repository = "https://github.com/langchain-ai/langchain" -license = "MIT" - -[tool.poetry.urls] -"Source Code" = "https://github.com/langchain-ai/langchain/tree/master/libs/partners/elasticsearch" - -[tool.poetry.dependencies] -python = ">=3.8.1,<4.0" -langchain-core = "^0.1" -elasticsearch = "^8.12.0" -numpy = "^1" - -[tool.poetry.group.test] -optional = true - -[tool.poetry.group.test.dependencies] -pytest = "^7.3.0" -freezegun = "^1.2.2" -pytest-mock = "^3.10.0" -syrupy = "^4.0.2" -pytest-watcher = "^0.3.4" -pytest-asyncio = "^0.21.1" -langchain = { path = "../../langchain", develop = true } -langchain-core = { path = "../../core", develop = true } -langchain-text-splitters = {path = "../../text-splitters", develop = true} - -[tool.poetry.group.codespell] -optional = true - -[tool.poetry.group.codespell.dependencies] -codespell = "^2.2.0" - -[tool.poetry.group.lint] -optional = true - -[tool.poetry.group.lint.dependencies] -ruff = "^0.1.5" - -[tool.poetry.group.typing.dependencies] -mypy = "^0.991" -langchain-core = { path = "../../core", develop = true } - -[tool.poetry.group.dev] -optional = true - -[tool.poetry.group.dev.dependencies] -langchain-core = { path = "../../core", develop = true } - -[tool.poetry.group.test_integration] -optional = true - -[tool.poetry.group.test_integration.dependencies] - - -[tool.ruff] -select = [ - "E", # pycodestyle - "F", # pyflakes - "I", # isort -] - -[tool.mypy] -disallow_untyped_defs = "True" - -[tool.coverage.run] -omit = ["tests/*"] - -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" - -[tool.pytest.ini_options] -# --strict-markers will raise errors on unknown marks. -# https://docs.pytest.org/en/7.1.x/how-to/mark.html#raising-errors-on-unknown-marks -# -# https://docs.pytest.org/en/7.1.x/reference/reference.html -# --strict-config any warnings encountered while parsing the `pytest` -# section of the configuration file raise errors. -# -# https://github.com/tophat/syrupy -# --snapshot-warn-unused Prints a warning on unused snapshots rather than fail the test suite. -addopts = "--snapshot-warn-unused --strict-markers --strict-config --durations=5" -# Registering custom markers. -# https://docs.pytest.org/en/7.1.x/example/markers.html#registering-markers -markers = [ - "requires: mark tests as requiring a specific library", - "asyncio: mark tests as requiring asyncio", - "compile: mark placeholder test used to compile integration tests without running them", -] -asyncio_mode = "auto" diff --git a/libs/partners/elasticsearch/scripts/check_imports.py b/libs/partners/elasticsearch/scripts/check_imports.py deleted file mode 100644 index fd21a4975b..0000000000 --- a/libs/partners/elasticsearch/scripts/check_imports.py +++ /dev/null @@ -1,17 +0,0 @@ -import sys -import traceback -from importlib.machinery import SourceFileLoader - -if __name__ == "__main__": - files = sys.argv[1:] - has_failure = False - for file in files: - try: - SourceFileLoader("x", file).load_module() - except Exception: - has_faillure = True - print(file) - traceback.print_exc() - print() - - sys.exit(1 if has_failure else 0) diff --git a/libs/partners/elasticsearch/scripts/check_pydantic.sh b/libs/partners/elasticsearch/scripts/check_pydantic.sh deleted file mode 100755 index 06b5bb81ae..0000000000 --- a/libs/partners/elasticsearch/scripts/check_pydantic.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -# -# This script searches for lines starting with "import pydantic" or "from pydantic" -# in tracked files within a Git repository. -# -# Usage: ./scripts/check_pydantic.sh /path/to/repository - -# Check if a path argument is provided -if [ $# -ne 1 ]; then - echo "Usage: $0 /path/to/repository" - exit 1 -fi - -repository_path="$1" - -# Search for lines matching the pattern within the specified repository -result=$(git -C "$repository_path" grep -E '^import pydantic|^from pydantic') - -# Check if any matching lines were found -if [ -n "$result" ]; then - echo "ERROR: The following lines need to be updated:" - echo "$result" - echo "Please replace the code with an import from langchain_core.pydantic_v1." - echo "For example, replace 'from pydantic import BaseModel'" - echo "with 'from langchain_core.pydantic_v1 import BaseModel'" - exit 1 -fi diff --git a/libs/partners/elasticsearch/scripts/lint_imports.sh b/libs/partners/elasticsearch/scripts/lint_imports.sh deleted file mode 100755 index 695613c7ba..0000000000 --- a/libs/partners/elasticsearch/scripts/lint_imports.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -set -eu - -# Initialize a variable to keep track of errors -errors=0 - -# make sure not importing from langchain or langchain_experimental -git --no-pager grep '^from langchain\.' . && errors=$((errors+1)) -git --no-pager grep '^from langchain_experimental\.' . && errors=$((errors+1)) - -# Decide on an exit status based on the errors -if [ "$errors" -gt 0 ]; then - exit 1 -else - exit 0 -fi diff --git a/libs/partners/elasticsearch/tests/__init__.py b/libs/partners/elasticsearch/tests/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libs/partners/elasticsearch/tests/fake_embeddings.py b/libs/partners/elasticsearch/tests/fake_embeddings.py deleted file mode 100644 index d12df58d92..0000000000 --- a/libs/partners/elasticsearch/tests/fake_embeddings.py +++ /dev/null @@ -1,55 +0,0 @@ -"""Fake Embedding class for testing purposes.""" - -from typing import List - -from langchain_core.embeddings import Embeddings - -fake_texts = ["foo", "bar", "baz"] - - -class FakeEmbeddings(Embeddings): - """Fake embeddings functionality for testing.""" - - def embed_documents(self, texts: List[str]) -> List[List[float]]: - """Return simple embeddings. - Embeddings encode each text as its index.""" - return [[float(1.0)] * 9 + [float(i)] for i in range(len(texts))] - - async def aembed_documents(self, texts: List[str]) -> List[List[float]]: - return self.embed_documents(texts) - - def embed_query(self, text: str) -> List[float]: - """Return constant query embeddings. - Embeddings are identical to embed_documents(texts)[0]. - Distance to each text will be that text's index, - as it was passed to embed_documents.""" - return [float(1.0)] * 9 + [float(0.0)] - - async def aembed_query(self, text: str) -> List[float]: - return self.embed_query(text) - - -class ConsistentFakeEmbeddings(FakeEmbeddings): - """Fake embeddings which remember all the texts seen so far to return consistent - vectors for the same texts.""" - - def __init__(self, dimensionality: int = 10) -> None: - self.known_texts: List[str] = [] - self.dimensionality = dimensionality - - def embed_documents(self, texts: List[str]) -> List[List[float]]: - """Return consistent embeddings for each text seen so far.""" - out_vectors = [] - for text in texts: - if text not in self.known_texts: - self.known_texts.append(text) - vector = [float(1.0)] * (self.dimensionality - 1) + [ - float(self.known_texts.index(text)) - ] - out_vectors.append(vector) - return out_vectors - - def embed_query(self, text: str) -> List[float]: - """Return consistent embeddings for the text, if seen before, or a constant - one if the text is unknown.""" - return self.embed_documents([text])[0] diff --git a/libs/partners/elasticsearch/tests/integration_tests/__init__.py b/libs/partners/elasticsearch/tests/integration_tests/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libs/partners/elasticsearch/tests/integration_tests/_test_utilities.py b/libs/partners/elasticsearch/tests/integration_tests/_test_utilities.py deleted file mode 100644 index 742a0a5d12..0000000000 --- a/libs/partners/elasticsearch/tests/integration_tests/_test_utilities.py +++ /dev/null @@ -1,42 +0,0 @@ -import os -from typing import Any, Dict, List - -from elastic_transport import Transport -from elasticsearch import Elasticsearch - - -def clear_test_indices(es: Elasticsearch) -> None: - index_names = es.indices.get(index="_all").keys() - for index_name in index_names: - if index_name.startswith("test_"): - es.indices.delete(index=index_name) - es.indices.refresh(index="_all") - - -def requests_saving_es_client() -> Elasticsearch: - class CustomTransport(Transport): - def __init__(self, *args: Any, **kwargs: Any) -> None: - super().__init__(*args, **kwargs) - self.requests: List[Dict] = [] - - def perform_request(self, *args, **kwargs): # type: ignore - self.requests.append(kwargs) - return super().perform_request(*args, **kwargs) - - es_url = os.environ.get("ES_URL", "http://localhost:9200") - cloud_id = os.environ.get("ES_CLOUD_ID") - api_key = os.environ.get("ES_API_KEY") - - if cloud_id: - # Running this integration test with Elastic Cloud - # Required for in-stack inference testing (ELSER + model_id) - es = Elasticsearch( - cloud_id=cloud_id, - api_key=api_key, - transport_class=CustomTransport, - ) - else: - # Running this integration test with local docker instance - es = Elasticsearch(hosts=[es_url], transport_class=CustomTransport) - - return es diff --git a/libs/partners/elasticsearch/tests/integration_tests/docker-compose.yml b/libs/partners/elasticsearch/tests/integration_tests/docker-compose.yml deleted file mode 100644 index b39daa6ffa..0000000000 --- a/libs/partners/elasticsearch/tests/integration_tests/docker-compose.yml +++ /dev/null @@ -1,35 +0,0 @@ -version: "3" - -services: - elasticsearch: - image: docker.elastic.co/elasticsearch/elasticsearch:8.12.1 # https://www.docker.elastic.co/r/elasticsearch/elasticsearch - environment: - - discovery.type=single-node - - xpack.security.enabled=false # security has been disabled, so no login or password is required. - - xpack.security.http.ssl.enabled=false - - xpack.license.self_generated.type=trial - ports: - - "9200:9200" - healthcheck: - test: - [ - "CMD-SHELL", - "curl --silent --fail http://localhost:9200/_cluster/health || exit 1" - ] - interval: 10s - retries: 60 - - kibana: - image: docker.elastic.co/kibana/kibana:8.12.1 - environment: - - ELASTICSEARCH_URL=http://elasticsearch:9200 - ports: - - "5601:5601" - healthcheck: - test: - [ - "CMD-SHELL", - "curl --silent --fail http://localhost:5601/login || exit 1" - ] - interval: 10s - retries: 60 diff --git a/libs/partners/elasticsearch/tests/integration_tests/test_chat_history.py b/libs/partners/elasticsearch/tests/integration_tests/test_chat_history.py deleted file mode 100644 index 8c13b2d0d6..0000000000 --- a/libs/partners/elasticsearch/tests/integration_tests/test_chat_history.py +++ /dev/null @@ -1,89 +0,0 @@ -import json -import os -import uuid -from typing import Generator, Union - -import pytest -from langchain.memory import ConversationBufferMemory -from langchain_core.messages import message_to_dict - -from langchain_elasticsearch.chat_history import ElasticsearchChatMessageHistory - -""" -cd tests/integration_tests -docker-compose up elasticsearch - -By default runs against local docker instance of Elasticsearch. -To run against Elastic Cloud, set the following environment variables: -- ES_CLOUD_ID -- ES_USERNAME -- ES_PASSWORD -""" - - -class TestElasticsearch: - @pytest.fixture(scope="class", autouse=True) - def elasticsearch_connection(self) -> Union[dict, Generator[dict, None, None]]: - # Run this integration test against Elasticsearch on localhost, - # or an Elastic Cloud instance - from elasticsearch import Elasticsearch - - es_url = os.environ.get("ES_URL", "http://localhost:9200") - es_cloud_id = os.environ.get("ES_CLOUD_ID") - es_api_key = os.environ.get("ES_API_KEY") - - if es_cloud_id: - es = Elasticsearch( - cloud_id=es_cloud_id, - api_key=es_api_key, - ) - yield { - "es_cloud_id": es_cloud_id, - "es_api_key": es_api_key, - } - - else: - # Running this integration test with local docker instance - es = Elasticsearch(hosts=es_url) - yield {"es_url": es_url} - - # Clear all indexes - index_names = es.indices.get(index="_all").keys() - for index_name in index_names: - if index_name.startswith("test_"): - es.indices.delete(index=index_name) - es.indices.refresh(index="_all") - - @pytest.fixture(scope="function") - def index_name(self) -> str: - """Return the index name.""" - return f"test_{uuid.uuid4().hex}" - - def test_memory_with_message_store( - self, elasticsearch_connection: dict, index_name: str - ) -> None: - """Test the memory with a message store.""" - # setup Elasticsearch as a message store - message_history = ElasticsearchChatMessageHistory( - **elasticsearch_connection, index=index_name, session_id="test-session" - ) - - memory = ConversationBufferMemory( - memory_key="baz", chat_memory=message_history, return_messages=True - ) - - # add some messages - memory.chat_memory.add_ai_message("This is me, the AI") - memory.chat_memory.add_user_message("This is me, the human") - - # get the message history from the memory store and turn it into a json - messages = memory.chat_memory.messages - messages_json = json.dumps([message_to_dict(msg) for msg in messages]) - - assert "This is me, the AI" in messages_json - assert "This is me, the human" in messages_json - - # remove the record from Elasticsearch, so the next test run won't pick it up - memory.chat_memory.clear() - - assert memory.chat_memory.messages == [] diff --git a/libs/partners/elasticsearch/tests/integration_tests/test_compile.py b/libs/partners/elasticsearch/tests/integration_tests/test_compile.py deleted file mode 100644 index 33ecccdfa0..0000000000 --- a/libs/partners/elasticsearch/tests/integration_tests/test_compile.py +++ /dev/null @@ -1,7 +0,0 @@ -import pytest - - -@pytest.mark.compile -def test_placeholder() -> None: - """Used for compiling integration tests without running any real tests.""" - pass diff --git a/libs/partners/elasticsearch/tests/integration_tests/test_embeddings.py b/libs/partners/elasticsearch/tests/integration_tests/test_embeddings.py deleted file mode 100644 index c512bb7415..0000000000 --- a/libs/partners/elasticsearch/tests/integration_tests/test_embeddings.py +++ /dev/null @@ -1,48 +0,0 @@ -"""Test elasticsearch_embeddings embeddings.""" - -import pytest -from langchain_core.utils import get_from_env - -from langchain_elasticsearch.embeddings import ElasticsearchEmbeddings - -# deployed with -# https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-text-emb-vector-search-example.html -DEFAULT_MODEL = "sentence-transformers__msmarco-minilm-l-12-v3" -DEFAULT_NUM_DIMENSIONS = "384" - - -@pytest.fixture -def model_id() -> str: - return get_from_env("model_id", "MODEL_ID", DEFAULT_MODEL) - - -@pytest.fixture -def expected_num_dimensions() -> int: - return int( - get_from_env( - "expected_num_dimensions", "EXPECTED_NUM_DIMENSIONS", DEFAULT_NUM_DIMENSIONS - ) - ) - - -def test_elasticsearch_embedding_documents( - model_id: str, expected_num_dimensions: int -) -> None: - """Test Elasticsearch embedding documents.""" - documents = ["foo bar", "bar foo", "foo"] - embedding = ElasticsearchEmbeddings.from_credentials(model_id) - output = embedding.embed_documents(documents) - assert len(output) == 3 - assert len(output[0]) == expected_num_dimensions - assert len(output[1]) == expected_num_dimensions - assert len(output[2]) == expected_num_dimensions - - -def test_elasticsearch_embedding_query( - model_id: str, expected_num_dimensions: int -) -> None: - """Test Elasticsearch embedding query.""" - document = "foo bar" - embedding = ElasticsearchEmbeddings.from_credentials(model_id) - output = embedding.embed_query(document) - assert len(output) == expected_num_dimensions diff --git a/libs/partners/elasticsearch/tests/integration_tests/test_retrievers.py b/libs/partners/elasticsearch/tests/integration_tests/test_retrievers.py deleted file mode 100644 index 59c02449b2..0000000000 --- a/libs/partners/elasticsearch/tests/integration_tests/test_retrievers.py +++ /dev/null @@ -1,178 +0,0 @@ -"""Test ElasticsearchRetriever functionality.""" - -import os -import re -import uuid -from typing import Any, Dict - -import pytest -from elasticsearch import Elasticsearch -from langchain_core.documents import Document - -from langchain_elasticsearch.retrievers import ElasticsearchRetriever - -from ._test_utilities import requests_saving_es_client - -""" -cd tests/integration_tests -docker-compose up elasticsearch - -By default runs against local docker instance of Elasticsearch. -To run against Elastic Cloud, set the following environment variables: -- ES_CLOUD_ID -- ES_API_KEY -""" - - -def index_test_data(es_client: Elasticsearch, index_name: str, field_name: str) -> None: - docs = [(1, "foo bar"), (2, "bar"), (3, "foo"), (4, "baz"), (5, "foo baz")] - for identifier, text in docs: - es_client.index( - index=index_name, - document={field_name: text, "another_field": 1}, - id=str(identifier), - refresh=True, - ) - - -class TestElasticsearchRetriever: - @pytest.fixture(scope="function") - def es_client(self) -> Any: - return requests_saving_es_client() - - @pytest.fixture(scope="function") - def index_name(self) -> str: - """Return the index name.""" - return f"test_{uuid.uuid4().hex}" - - def test_user_agent_header(self, es_client: Elasticsearch, index_name: str) -> None: - """Test that the user agent header is set correctly.""" - - retriever = ElasticsearchRetriever( - index_name=index_name, - body_func=lambda _: {"query": {"match_all": {}}}, - content_field="text", - es_client=es_client, - ) - - assert retriever.es_client - user_agent = retriever.es_client._headers["User-Agent"] - assert ( - re.match(r"^langchain-py-r/\d+\.\d+\.\d+$", user_agent) is not None - ), f"The string '{user_agent}' does not match the expected pattern." - - index_test_data(es_client, index_name, "text") - retriever.get_relevant_documents("foo") - - search_request = es_client.transport.requests[-1] # type: ignore[attr-defined] - user_agent = search_request["headers"]["User-Agent"] - assert ( - re.match(r"^langchain-py-r/\d+\.\d+\.\d+$", user_agent) is not None - ), f"The string '{user_agent}' does not match the expected pattern." - - def test_init_url(self, index_name: str) -> None: - """Test end-to-end indexing and search.""" - - text_field = "text" - - def body_func(query: str) -> Dict: - return {"query": {"match": {text_field: {"query": query}}}} - - es_url = os.environ.get("ES_URL", "http://localhost:9200") - cloud_id = os.environ.get("ES_CLOUD_ID") - api_key = os.environ.get("ES_API_KEY") - - config = ( - {"cloud_id": cloud_id, "api_key": api_key} if cloud_id else {"url": es_url} - ) - - retriever = ElasticsearchRetriever.from_es_params( - index_name=index_name, - body_func=body_func, - content_field=text_field, - **config, # type: ignore[arg-type] - ) - - index_test_data(retriever.es_client, index_name, text_field) - result = retriever.get_relevant_documents("foo") - - assert {r.page_content for r in result} == {"foo", "foo bar", "foo baz"} - assert {r.metadata["_id"] for r in result} == {"3", "1", "5"} - for r in result: - assert set(r.metadata.keys()) == {"_index", "_id", "_score", "_source"} - assert text_field not in r.metadata["_source"] - assert "another_field" in r.metadata["_source"] - - def test_init_client(self, es_client: Elasticsearch, index_name: str) -> None: - """Test end-to-end indexing and search.""" - - text_field = "text" - - def body_func(query: str) -> Dict: - return {"query": {"match": {text_field: {"query": query}}}} - - retriever = ElasticsearchRetriever( - index_name=index_name, - body_func=body_func, - content_field=text_field, - es_client=es_client, - ) - - index_test_data(es_client, index_name, text_field) - result = retriever.get_relevant_documents("foo") - - assert {r.page_content for r in result} == {"foo", "foo bar", "foo baz"} - assert {r.metadata["_id"] for r in result} == {"3", "1", "5"} - for r in result: - assert set(r.metadata.keys()) == {"_index", "_id", "_score", "_source"} - assert text_field not in r.metadata["_source"] - assert "another_field" in r.metadata["_source"] - - def test_custom_mapper(self, es_client: Elasticsearch, index_name: str) -> None: - """Test custom document maper""" - - text_field = "text" - meta = {"some_field": 12} - - def body_func(query: str) -> Dict: - return {"query": {"match": {text_field: {"query": query}}}} - - def id_as_content(hit: Dict) -> Document: - return Document(page_content=hit["_id"], metadata=meta) - - retriever = ElasticsearchRetriever( - index_name=index_name, - body_func=body_func, - document_mapper=id_as_content, - es_client=es_client, - ) - - index_test_data(es_client, index_name, text_field) - result = retriever.get_relevant_documents("foo") - - assert [r.page_content for r in result] == ["3", "1", "5"] - assert [r.metadata for r in result] == [meta, meta, meta] - - def test_fail_content_field_and_mapper(self, es_client: Elasticsearch) -> None: - """Raise exception if both content_field and document_mapper are specified.""" - - with pytest.raises(ValueError): - ElasticsearchRetriever( - content_field="text", - document_mapper=lambda x: x, - index_name="foo", - body_func=lambda x: x, - es_client=es_client, - ) - - def test_fail_neither_content_field_nor_mapper( - self, es_client: Elasticsearch - ) -> None: - """Raise exception if neither content_field nor document_mapper are specified""" - - with pytest.raises(ValueError): - ElasticsearchRetriever( - index_name="foo", - body_func=lambda x: x, - es_client=es_client, - ) diff --git a/libs/partners/elasticsearch/tests/integration_tests/test_vectorstores.py b/libs/partners/elasticsearch/tests/integration_tests/test_vectorstores.py deleted file mode 100644 index 3ac6d456fb..0000000000 --- a/libs/partners/elasticsearch/tests/integration_tests/test_vectorstores.py +++ /dev/null @@ -1,929 +0,0 @@ -"""Test ElasticsearchStore functionality.""" - -import logging -import os -import re -import uuid -from typing import Any, Dict, Generator, List, Union - -import pytest -from elasticsearch import Elasticsearch, NotFoundError -from elasticsearch.helpers import BulkIndexError -from langchain_core.documents import Document - -from langchain_elasticsearch.vectorstores import ElasticsearchStore - -from ..fake_embeddings import ( - ConsistentFakeEmbeddings, - FakeEmbeddings, -) -from ._test_utilities import clear_test_indices, requests_saving_es_client - -logging.basicConfig(level=logging.DEBUG) - -""" -cd tests/integration_tests -docker-compose up elasticsearch - -By default runs against local docker instance of Elasticsearch. -To run against Elastic Cloud, set the following environment variables: -- ES_CLOUD_ID -- ES_API_KEY - -Some of the tests require the following models to be deployed in the ML Node: -- elser (can be downloaded and deployed through Kibana and trained models UI) -- sentence-transformers__all-minilm-l6-v2 (can be deployed - through API, loaded via eland) - -These tests that require the models to be deployed are skipped by default. -Enable them by adding the model name to the modelsDeployed list below. -""" - -modelsDeployed: List[str] = [ - # ".elser_model_1", - # "sentence-transformers__all-minilm-l6-v2", -] - - -class TestElasticsearch: - @classmethod - def setup_class(cls) -> None: - if not os.getenv("OPENAI_API_KEY"): - raise ValueError("OPENAI_API_KEY environment variable is not set") - - @pytest.fixture(scope="class", autouse=True) - def elasticsearch_connection(self) -> Union[dict, Generator[dict, None, None]]: - es_url = os.environ.get("ES_URL", "http://localhost:9200") - cloud_id = os.environ.get("ES_CLOUD_ID") - api_key = os.environ.get("ES_API_KEY") - - if cloud_id: - # Running this integration test with Elastic Cloud - # Required for in-stack inference testing (ELSER + model_id) - es = Elasticsearch( - cloud_id=cloud_id, - api_key=api_key, - ) - yield { - "es_cloud_id": cloud_id, - "es_api_key": api_key, - } - - else: - # Running this integration test with local docker instance - es = Elasticsearch(hosts=es_url) - yield {"es_url": es_url} - - # clear indices - clear_test_indices(es) - - # clear all test pipelines - try: - response = es.ingest.get_pipeline(id="test_*,*_sparse_embedding") - - for pipeline_id, _ in response.items(): - try: - es.ingest.delete_pipeline(id=pipeline_id) - print(f"Deleted pipeline: {pipeline_id}") # noqa: T201 - except Exception as e: - print(f"Pipeline error: {e}") # noqa: T201 - except Exception: - pass - - return None - - @pytest.fixture(scope="function") - def es_client(self) -> Any: - return requests_saving_es_client() - - @pytest.fixture(scope="function") - def index_name(self) -> str: - """Return the index name.""" - return f"test_{uuid.uuid4().hex}" - - def test_similarity_search_without_metadata( - self, elasticsearch_connection: dict, index_name: str - ) -> None: - """Test end to end construction and search without metadata.""" - - def assert_query(query_body: dict, query: str) -> dict: - assert query_body == { - "knn": { - "field": "vector", - "filter": [], - "k": 1, - "num_candidates": 50, - "query_vector": [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0], - } - } - return query_body - - texts = ["foo", "bar", "baz"] - docsearch = ElasticsearchStore.from_texts( - texts, - FakeEmbeddings(), - **elasticsearch_connection, - index_name=index_name, - ) - output = docsearch.similarity_search("foo", k=1, custom_query=assert_query) - assert output == [Document(page_content="foo")] - - async def test_similarity_search_without_metadata_async( - self, elasticsearch_connection: dict, index_name: str - ) -> None: - """Test end to end construction and search without metadata.""" - texts = ["foo", "bar", "baz"] - docsearch = ElasticsearchStore.from_texts( - texts, - FakeEmbeddings(), - **elasticsearch_connection, - index_name=index_name, - ) - output = await docsearch.asimilarity_search("foo", k=1) - assert output == [Document(page_content="foo")] - - def test_add_embeddings( - self, elasticsearch_connection: dict, index_name: str - ) -> None: - """ - Test add_embeddings, which accepts pre-built embeddings instead of - using inference for the texts. - This allows you to separate the embeddings text and the page_content - for better proximity between user's question and embedded text. - For example, your embedding text can be a question, whereas page_content - is the answer. - """ - embeddings = ConsistentFakeEmbeddings() - text_input = ["foo1", "foo2", "foo3"] - metadatas = [{"page": i} for i in range(len(text_input))] - - """In real use case, embedding_input can be questions for each text""" - embedding_input = ["foo2", "foo3", "foo1"] - embedding_vectors = embeddings.embed_documents(embedding_input) - - docsearch = ElasticsearchStore._create_cls_from_kwargs( - embeddings, - **elasticsearch_connection, - index_name=index_name, - ) - docsearch.add_embeddings(list(zip(text_input, embedding_vectors)), metadatas) - output = docsearch.similarity_search("foo1", k=1) - assert output == [Document(page_content="foo3", metadata={"page": 2})] - - def test_similarity_search_with_metadata( - self, elasticsearch_connection: dict, index_name: str - ) -> None: - """Test end to end construction and search with metadata.""" - texts = ["foo", "bar", "baz"] - metadatas = [{"page": i} for i in range(len(texts))] - docsearch = ElasticsearchStore.from_texts( - texts, - ConsistentFakeEmbeddings(), - metadatas=metadatas, - **elasticsearch_connection, - index_name=index_name, - ) - - output = docsearch.similarity_search("foo", k=1) - assert output == [Document(page_content="foo", metadata={"page": 0})] - - output = docsearch.similarity_search("bar", k=1) - assert output == [Document(page_content="bar", metadata={"page": 1})] - - def test_similarity_search_with_filter( - self, elasticsearch_connection: dict, index_name: str - ) -> None: - """Test end to end construction and search with metadata.""" - texts = ["foo", "foo", "foo"] - metadatas = [{"page": i} for i in range(len(texts))] - docsearch = ElasticsearchStore.from_texts( - texts, - FakeEmbeddings(), - metadatas=metadatas, - **elasticsearch_connection, - index_name=index_name, - ) - - def assert_query(query_body: dict, query: str) -> dict: - assert query_body == { - "knn": { - "field": "vector", - "filter": [{"term": {"metadata.page": "1"}}], - "k": 3, - "num_candidates": 50, - "query_vector": [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0], - } - } - return query_body - - output = docsearch.similarity_search( - query="foo", - k=3, - filter=[{"term": {"metadata.page": "1"}}], - custom_query=assert_query, - ) - assert output == [Document(page_content="foo", metadata={"page": 1})] - - def test_similarity_search_with_doc_builder( - self, elasticsearch_connection: dict, index_name: str - ) -> None: - texts = ["foo", "foo", "foo"] - metadatas = [{"page": i} for i in range(len(texts))] - docsearch = ElasticsearchStore.from_texts( - texts, - FakeEmbeddings(), - metadatas=metadatas, - **elasticsearch_connection, - index_name=index_name, - ) - - def custom_document_builder(_: Dict) -> Document: - return Document( - page_content="Mock content!", - metadata={ - "page_number": -1, - "original_filename": "Mock filename!", - }, - ) - - output = docsearch.similarity_search( - query="foo", k=1, doc_builder=custom_document_builder - ) - assert output[0].page_content == "Mock content!" - assert output[0].metadata["page_number"] == -1 - assert output[0].metadata["original_filename"] == "Mock filename!" - - def test_similarity_search_exact_search( - self, elasticsearch_connection: dict, index_name: str - ) -> None: - """Test end to end construction and search with metadata.""" - texts = ["foo", "bar", "baz"] - docsearch = ElasticsearchStore.from_texts( - texts, - FakeEmbeddings(), - **elasticsearch_connection, - index_name=index_name, - strategy=ElasticsearchStore.ExactRetrievalStrategy(), - ) - - expected_query = { - "query": { - "script_score": { - "query": {"match_all": {}}, - "script": { - "source": "cosineSimilarity(params.query_vector, 'vector') + 1.0", # noqa: E501 - "params": { - "query_vector": [ - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 0.0, - ] - }, - }, - } - } - } - - def assert_query(query_body: dict, query: str) -> dict: - assert query_body == expected_query - return query_body - - output = docsearch.similarity_search("foo", k=1, custom_query=assert_query) - assert output == [Document(page_content="foo")] - - def test_similarity_search_exact_search_with_filter( - self, elasticsearch_connection: dict, index_name: str - ) -> None: - """Test end to end construction and search with metadata.""" - texts = ["foo", "bar", "baz"] - metadatas = [{"page": i} for i in range(len(texts))] - docsearch = ElasticsearchStore.from_texts( - texts, - FakeEmbeddings(), - **elasticsearch_connection, - index_name=index_name, - metadatas=metadatas, - strategy=ElasticsearchStore.ExactRetrievalStrategy(), - ) - - def assert_query(query_body: dict, query: str) -> dict: - expected_query = { - "query": { - "script_score": { - "query": {"bool": {"filter": [{"term": {"metadata.page": 0}}]}}, - "script": { - "source": "cosineSimilarity(params.query_vector, 'vector') + 1.0", # noqa: E501 - "params": { - "query_vector": [ - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 0.0, - ] - }, - }, - } - } - } - assert query_body == expected_query - return query_body - - output = docsearch.similarity_search( - "foo", - k=1, - custom_query=assert_query, - filter=[{"term": {"metadata.page": 0}}], - ) - assert output == [Document(page_content="foo", metadata={"page": 0})] - - def test_similarity_search_exact_search_distance_dot_product( - self, elasticsearch_connection: dict, index_name: str - ) -> None: - """Test end to end construction and search with metadata.""" - texts = ["foo", "bar", "baz"] - docsearch = ElasticsearchStore.from_texts( - texts, - FakeEmbeddings(), - **elasticsearch_connection, - index_name=index_name, - strategy=ElasticsearchStore.ExactRetrievalStrategy(), - distance_strategy="DOT_PRODUCT", - ) - - def assert_query(query_body: dict, query: str) -> dict: - assert query_body == { - "query": { - "script_score": { - "query": {"match_all": {}}, - "script": { - "source": """ - double value = dotProduct(params.query_vector, 'vector'); - return sigmoid(1, Math.E, -value); - """, - "params": { - "query_vector": [ - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 0.0, - ] - }, - }, - } - } - } - return query_body - - output = docsearch.similarity_search("foo", k=1, custom_query=assert_query) - assert output == [Document(page_content="foo")] - - def test_similarity_search_exact_search_unknown_distance_strategy( - self, elasticsearch_connection: dict, index_name: str - ) -> None: - """Test end to end construction and search with unknown distance strategy.""" - - with pytest.raises(KeyError): - texts = ["foo", "bar", "baz"] - ElasticsearchStore.from_texts( - texts, - FakeEmbeddings(), - **elasticsearch_connection, - index_name=index_name, - strategy=ElasticsearchStore.ExactRetrievalStrategy(), - distance_strategy="NOT_A_STRATEGY", - ) - - def test_max_marginal_relevance_search( - self, elasticsearch_connection: dict, index_name: str - ) -> None: - """Test max marginal relevance search.""" - texts = ["foo", "bar", "baz"] - docsearch = ElasticsearchStore.from_texts( - texts, - FakeEmbeddings(), - **elasticsearch_connection, - index_name=index_name, - strategy=ElasticsearchStore.ExactRetrievalStrategy(), - ) - - mmr_output = docsearch.max_marginal_relevance_search(texts[0], k=3, fetch_k=3) - sim_output = docsearch.similarity_search(texts[0], k=3) - assert mmr_output == sim_output - - mmr_output = docsearch.max_marginal_relevance_search(texts[0], k=2, fetch_k=3) - assert len(mmr_output) == 2 - assert mmr_output[0].page_content == texts[0] - assert mmr_output[1].page_content == texts[1] - - mmr_output = docsearch.max_marginal_relevance_search( - texts[0], - k=2, - fetch_k=3, - lambda_mult=0.1, # more diversity - ) - assert len(mmr_output) == 2 - assert mmr_output[0].page_content == texts[0] - assert mmr_output[1].page_content == texts[2] - - # if fetch_k < k, then the output will be less than k - mmr_output = docsearch.max_marginal_relevance_search(texts[0], k=3, fetch_k=2) - assert len(mmr_output) == 2 - - def test_similarity_search_approx_with_hybrid_search( - self, elasticsearch_connection: dict, index_name: str - ) -> None: - """Test end to end construction and search with metadata.""" - texts = ["foo", "bar", "baz"] - docsearch = ElasticsearchStore.from_texts( - texts, - FakeEmbeddings(), - **elasticsearch_connection, - index_name=index_name, - strategy=ElasticsearchStore.ApproxRetrievalStrategy(hybrid=True), - ) - - def assert_query(query_body: dict, query: str) -> dict: - assert query_body == { - "knn": { - "field": "vector", - "filter": [], - "k": 1, - "num_candidates": 50, - "query_vector": [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0], - }, - "query": { - "bool": { - "filter": [], - "must": [{"match": {"text": {"query": "foo"}}}], - } - }, - "rank": {"rrf": {}}, - } - return query_body - - output = docsearch.similarity_search("foo", k=1, custom_query=assert_query) - assert output == [Document(page_content="foo")] - - def test_similarity_search_approx_with_hybrid_search_rrf( - self, es_client: Any, elasticsearch_connection: dict, index_name: str - ) -> None: - """Test end to end construction and rrf hybrid search with metadata.""" - from functools import partial - from typing import Optional - - # 1. check query_body is okay - rrf_test_cases: List[Optional[Union[dict, bool]]] = [ - True, - False, - {"rank_constant": 1, "window_size": 5}, - ] - for rrf_test_case in rrf_test_cases: - texts = ["foo", "bar", "baz"] - docsearch = ElasticsearchStore.from_texts( - texts, - FakeEmbeddings(), - **elasticsearch_connection, - index_name=index_name, - strategy=ElasticsearchStore.ApproxRetrievalStrategy( - hybrid=True, rrf=rrf_test_case - ), - ) - - def assert_query( - query_body: dict, - query: str, - rrf: Optional[Union[dict, bool]] = True, - ) -> dict: - cmp_query_body = { - "knn": { - "field": "vector", - "filter": [], - "k": 3, - "num_candidates": 50, - "query_vector": [ - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 1.0, - 0.0, - ], - }, - "query": { - "bool": { - "filter": [], - "must": [{"match": {"text": {"query": "foo"}}}], - } - }, - } - - if isinstance(rrf, dict): - cmp_query_body["rank"] = {"rrf": rrf} - elif isinstance(rrf, bool) and rrf is True: - cmp_query_body["rank"] = {"rrf": {}} - - assert query_body == cmp_query_body - - return query_body - - ## without fetch_k parameter - output = docsearch.similarity_search( - "foo", k=3, custom_query=partial(assert_query, rrf=rrf_test_case) - ) - - # 2. check query result is okay - es_output = es_client.search( - index=index_name, - query={ - "bool": { - "filter": [], - "must": [{"match": {"text": {"query": "foo"}}}], - } - }, - knn={ - "field": "vector", - "filter": [], - "k": 3, - "num_candidates": 50, - "query_vector": [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0], - }, - size=3, - rank={"rrf": {"rank_constant": 1, "window_size": 5}}, - ) - - assert [o.page_content for o in output] == [ - e["_source"]["text"] for e in es_output["hits"]["hits"] - ] - - # 3. check rrf default option is okay - docsearch = ElasticsearchStore.from_texts( - texts, - FakeEmbeddings(), - **elasticsearch_connection, - index_name=index_name, - strategy=ElasticsearchStore.ApproxRetrievalStrategy(hybrid=True), - ) - - ## with fetch_k parameter - output = docsearch.similarity_search( - "foo", k=3, fetch_k=50, custom_query=assert_query - ) - - def test_similarity_search_approx_with_custom_query_fn( - self, elasticsearch_connection: dict, index_name: str - ) -> None: - """test that custom query function is called - with the query string and query body""" - - def my_custom_query(query_body: dict, query: str) -> dict: - assert query == "foo" - assert query_body == { - "knn": { - "field": "vector", - "filter": [], - "k": 1, - "num_candidates": 50, - "query_vector": [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0], - } - } - return {"query": {"match": {"text": {"query": "bar"}}}} - - """Test end to end construction and search with metadata.""" - texts = ["foo", "bar", "baz"] - docsearch = ElasticsearchStore.from_texts( - texts, FakeEmbeddings(), **elasticsearch_connection, index_name=index_name - ) - output = docsearch.similarity_search("foo", k=1, custom_query=my_custom_query) - assert output == [Document(page_content="bar")] - - @pytest.mark.skipif( - "sentence-transformers__all-minilm-l6-v2" not in modelsDeployed, - reason="Sentence Transformers model not deployed in ML Node, skipping test", - ) - def test_similarity_search_with_approx_infer_instack( - self, elasticsearch_connection: dict, index_name: str - ) -> None: - """test end to end with approx retrieval strategy and inference in-stack""" - docsearch = ElasticsearchStore( - index_name=index_name, - strategy=ElasticsearchStore.ApproxRetrievalStrategy( - query_model_id="sentence-transformers__all-minilm-l6-v2" - ), - query_field="text_field", - vector_query_field="vector_query_field.predicted_value", - **elasticsearch_connection, - ) - - # setting up the pipeline for inference - docsearch.client.ingest.put_pipeline( - id="test_pipeline", - processors=[ - { - "inference": { - "model_id": "sentence-transformers__all-minilm-l6-v2", - "field_map": {"query_field": "text_field"}, - "target_field": "vector_query_field", - } - } - ], - ) - - # creating a new index with the pipeline, - # not relying on langchain to create the index - docsearch.client.indices.create( - index=index_name, - mappings={ - "properties": { - "text_field": {"type": "text"}, - "vector_query_field": { - "properties": { - "predicted_value": { - "type": "dense_vector", - "dims": 384, - "index": True, - "similarity": "l2_norm", - } - } - }, - } - }, - settings={"index": {"default_pipeline": "test_pipeline"}}, - ) - - # adding documents to the index - texts = ["foo", "bar", "baz"] - - for i, text in enumerate(texts): - docsearch.client.create( - index=index_name, - id=str(i), - document={"text_field": text, "metadata": {}}, - ) - - docsearch.client.indices.refresh(index=index_name) - - def assert_query(query_body: dict, query: str) -> dict: - assert query_body == { - "knn": { - "filter": [], - "field": "vector_query_field.predicted_value", - "k": 1, - "num_candidates": 50, - "query_vector_builder": { - "text_embedding": { - "model_id": "sentence-transformers__all-minilm-l6-v2", - "model_text": "foo", - } - }, - } - } - return query_body - - output = docsearch.similarity_search("foo", k=1, custom_query=assert_query) - assert output == [Document(page_content="foo")] - - output = docsearch.similarity_search("bar", k=1) - assert output == [Document(page_content="bar")] - - @pytest.mark.skipif( - ".elser_model_1" not in modelsDeployed, - reason="ELSER not deployed in ML Node, skipping test", - ) - def test_similarity_search_with_sparse_infer_instack( - self, elasticsearch_connection: dict, index_name: str - ) -> None: - """test end to end with sparse retrieval strategy and inference in-stack""" - texts = ["foo", "bar", "baz"] - docsearch = ElasticsearchStore.from_texts( - texts, - **elasticsearch_connection, - index_name=index_name, - strategy=ElasticsearchStore.SparseVectorRetrievalStrategy(), - ) - output = docsearch.similarity_search("foo", k=1) - assert output == [Document(page_content="foo")] - - def test_deployed_model_check_fails_approx( - self, elasticsearch_connection: dict, index_name: str - ) -> None: - """test that exceptions are raised if a specified model is not deployed""" - with pytest.raises(NotFoundError): - ElasticsearchStore.from_texts( - texts=["foo", "bar", "baz"], - embedding=ConsistentFakeEmbeddings(10), - **elasticsearch_connection, - index_name=index_name, - strategy=ElasticsearchStore.ApproxRetrievalStrategy( - query_model_id="non-existing model ID", - ), - ) - - def test_deployed_model_check_fails_sparse( - self, elasticsearch_connection: dict, index_name: str - ) -> None: - """test that exceptions are raised if a specified model is not deployed""" - with pytest.raises(NotFoundError): - ElasticsearchStore.from_texts( - texts=["foo", "bar", "baz"], - **elasticsearch_connection, - index_name=index_name, - strategy=ElasticsearchStore.SparseVectorRetrievalStrategy( - model_id="non-existing model ID" - ), - ) - - def test_elasticsearch_with_relevance_score( - self, elasticsearch_connection: dict, index_name: str - ) -> None: - """Test to make sure the relevance score is scaled to 0-1.""" - texts = ["foo", "bar", "baz"] - metadatas = [{"page": str(i)} for i in range(len(texts))] - embeddings = FakeEmbeddings() - - docsearch = ElasticsearchStore.from_texts( - index_name=index_name, - texts=texts, - embedding=embeddings, - metadatas=metadatas, - **elasticsearch_connection, - ) - - embedded_query = embeddings.embed_query("foo") - output = docsearch.similarity_search_by_vector_with_relevance_scores( - embedding=embedded_query, k=1 - ) - assert output == [(Document(page_content="foo", metadata={"page": "0"}), 1.0)] - - def test_elasticsearch_with_relevance_threshold( - self, elasticsearch_connection: dict, index_name: str - ) -> None: - """Test to make sure the relevance threshold is respected.""" - texts = ["foo", "bar", "baz"] - metadatas = [{"page": str(i)} for i in range(len(texts))] - embeddings = FakeEmbeddings() - - docsearch = ElasticsearchStore.from_texts( - index_name=index_name, - texts=texts, - embedding=embeddings, - metadatas=metadatas, - **elasticsearch_connection, - ) - - # Find a good threshold for testing - query_string = "foo" - embedded_query = embeddings.embed_query(query_string) - top3 = docsearch.similarity_search_by_vector_with_relevance_scores( - embedding=embedded_query, k=3 - ) - similarity_of_second_ranked = top3[1][1] - assert len(top3) == 3 - - # Test threshold - retriever = docsearch.as_retriever( - search_type="similarity_score_threshold", - search_kwargs={"score_threshold": similarity_of_second_ranked}, - ) - output = retriever.get_relevant_documents(query=query_string) - - assert output == [ - top3[0][0], - top3[1][0], - # third ranked is out - ] - - def test_elasticsearch_delete_ids( - self, elasticsearch_connection: dict, index_name: str - ) -> None: - """Test delete methods from vector store.""" - texts = ["foo", "bar", "baz", "gni"] - metadatas = [{"page": i} for i in range(len(texts))] - docsearch = ElasticsearchStore( - embedding=ConsistentFakeEmbeddings(), - **elasticsearch_connection, - index_name=index_name, - ) - - ids = docsearch.add_texts(texts, metadatas) - output = docsearch.similarity_search("foo", k=10) - assert len(output) == 4 - - docsearch.delete(ids[1:3]) - output = docsearch.similarity_search("foo", k=10) - assert len(output) == 2 - - docsearch.delete(["not-existing"]) - output = docsearch.similarity_search("foo", k=10) - assert len(output) == 2 - - docsearch.delete([ids[0]]) - output = docsearch.similarity_search("foo", k=10) - assert len(output) == 1 - - docsearch.delete([ids[3]]) - output = docsearch.similarity_search("gni", k=10) - assert len(output) == 0 - - def test_elasticsearch_indexing_exception_error( - self, - elasticsearch_connection: dict, - index_name: str, - caplog: pytest.LogCaptureFixture, - ) -> None: - """Test bulk exception logging is giving better hints.""" - - docsearch = ElasticsearchStore( - embedding=ConsistentFakeEmbeddings(), - **elasticsearch_connection, - index_name=index_name, - ) - - docsearch.client.indices.create( - index=index_name, - mappings={"properties": {}}, - settings={"index": {"default_pipeline": "not-existing-pipeline"}}, - ) - - texts = ["foo"] - - with pytest.raises(BulkIndexError): - docsearch.add_texts(texts) - - error_reason = "pipeline with id [not-existing-pipeline] does not exist" - log_message = f"First error reason: {error_reason}" - - assert log_message in caplog.text - - def test_elasticsearch_with_user_agent( - self, es_client: Any, index_name: str - ) -> None: - """Test to make sure the user-agent is set correctly.""" - - texts = ["foo", "bob", "baz"] - ElasticsearchStore.from_texts( - texts, - FakeEmbeddings(), - es_connection=es_client, - index_name=index_name, - ) - - user_agent = es_client.transport.requests[0]["headers"]["User-Agent"] - assert ( - re.match(r"^langchain-py-vs/\d+\.\d+\.\d+$", user_agent) is not None - ), f"The string '{user_agent}' does not match the expected pattern." - - def test_elasticsearch_with_internal_user_agent( - self, elasticsearch_connection: Dict, index_name: str - ) -> None: - """Test to make sure the user-agent is set correctly.""" - - texts = ["foo"] - store = ElasticsearchStore.from_texts( - texts, - FakeEmbeddings(), - **elasticsearch_connection, - index_name=index_name, - ) - - user_agent = store.client._headers["User-Agent"] - assert ( - re.match(r"^langchain-py-vs/\d+\.\d+\.\d+$", user_agent) is not None - ), f"The string '{user_agent}' does not match the expected pattern." - - def test_bulk_args(self, es_client: Any, index_name: str) -> None: - """Test to make sure the bulk arguments work as expected.""" - - texts = ["foo", "bob", "baz"] - ElasticsearchStore.from_texts( - texts, - FakeEmbeddings(), - es_connection=es_client, - index_name=index_name, - bulk_kwargs={"chunk_size": 1}, - ) - - # 1 for index exist, 1 for index create, 3 for index docs - assert len(es_client.transport.requests) == 5 # type: ignore diff --git a/libs/partners/elasticsearch/tests/unit_tests/__init__.py b/libs/partners/elasticsearch/tests/unit_tests/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libs/partners/elasticsearch/tests/unit_tests/test_imports.py b/libs/partners/elasticsearch/tests/unit_tests/test_imports.py deleted file mode 100644 index 2346ab99ad..0000000000 --- a/libs/partners/elasticsearch/tests/unit_tests/test_imports.py +++ /dev/null @@ -1,15 +0,0 @@ -from langchain_elasticsearch import __all__ - -EXPECTED_ALL = [ - "ApproxRetrievalStrategy", - "ElasticsearchChatMessageHistory", - "ElasticsearchEmbeddings", - "ElasticsearchRetriever", - "ElasticsearchStore", - "ExactRetrievalStrategy", - "SparseRetrievalStrategy", -] - - -def test_all_imports() -> None: - assert sorted(EXPECTED_ALL) == sorted(__all__) diff --git a/libs/partners/elasticsearch/tests/unit_tests/test_vectorstores.py b/libs/partners/elasticsearch/tests/unit_tests/test_vectorstores.py deleted file mode 100644 index 4ad407f71e..0000000000 --- a/libs/partners/elasticsearch/tests/unit_tests/test_vectorstores.py +++ /dev/null @@ -1,34 +0,0 @@ -"""Test Elasticsearch functionality.""" - -import pytest - -from langchain_elasticsearch.vectorstores import ( - ApproxRetrievalStrategy, - ElasticsearchStore, -) - -from ..fake_embeddings import FakeEmbeddings - - -@pytest.mark.requires("elasticsearch") -def test_elasticsearch_hybrid_scores_guard() -> None: - """Ensure an error is raised when search with score in hybrid mode - because in this case Elasticsearch does not return any score. - """ - from elasticsearch import Elasticsearch - - query_string = "foo" - embeddings = FakeEmbeddings() - - store = ElasticsearchStore( - index_name="dummy_index", - es_connection=Elasticsearch(hosts=["http://dummy-host:9200"]), - embedding=embeddings, - strategy=ApproxRetrievalStrategy(hybrid=True), - ) - with pytest.raises(ValueError): - store.similarity_search_with_score(query_string) - - embedded_query = embeddings.embed_query(query_string) - with pytest.raises(ValueError): - store.similarity_search_by_vector_with_relevance_scores(embedded_query)