From 48d6ea427f4a21663b6a7ee13dcb6d4f91dae785 Mon Sep 17 00:00:00 2001 From: Erick Friis Date: Wed, 19 Jun 2024 10:56:07 -0700 Subject: [PATCH] upstage: move to external repo (#22506) --- libs/partners/upstage/LICENSE | 21 - libs/partners/upstage/Makefile | 57 - libs/partners/upstage/README.md | 26 +- .../upstage/langchain_upstage/__init__.py | 17 - .../upstage/langchain_upstage/chat_models.py | 120 -- .../upstage/langchain_upstage/embeddings.py | 276 --- .../langchain_upstage/layout_analysis.py | 248 --- .../layout_analysis_parsers.py | 396 ----- .../upstage/langchain_upstage/py.typed | 0 .../tools/groundedness_check.py | 117 -- libs/partners/upstage/poetry.lock | 1480 ----------------- libs/partners/upstage/pyproject.toml | 104 -- .../partners/upstage/scripts/check_imports.py | 17 - .../upstage/scripts/check_pydantic.sh | 27 - libs/partners/upstage/scripts/lint_imports.sh | 17 - libs/partners/upstage/tests/__init__.py | 0 .../partners/upstage/tests/examples/solar.pdf | Bin 111524 -> 0 bytes .../tests/integration_tests/__init__.py | 0 .../integration_tests/test_chat_models.py | 136 -- .../test_chat_models_standard.py | 18 - .../tests/integration_tests/test_compile.py | 7 - .../integration_tests/test_embeddings.py | 51 - .../test_groundedness_check.py | 63 - .../upstage/tests/unit_tests/__init__.py | 0 .../tests/unit_tests/test_chat_models.py | 194 --- .../unit_tests/test_chat_models_standard.py | 18 - .../tests/unit_tests/test_embeddings.py | 32 - .../unit_tests/test_groundedness_check.py | 12 - .../upstage/tests/unit_tests/test_imports.py | 14 - .../tests/unit_tests/test_layout_analysis.py | 253 --- .../upstage/tests/unit_tests/test_secrets.py | 13 - 31 files changed, 2 insertions(+), 3732 deletions(-) delete mode 100644 libs/partners/upstage/LICENSE delete mode 100644 libs/partners/upstage/Makefile delete mode 100644 libs/partners/upstage/langchain_upstage/__init__.py delete mode 100644 libs/partners/upstage/langchain_upstage/chat_models.py delete mode 100644 libs/partners/upstage/langchain_upstage/embeddings.py delete mode 100644 libs/partners/upstage/langchain_upstage/layout_analysis.py delete mode 100644 libs/partners/upstage/langchain_upstage/layout_analysis_parsers.py delete mode 100644 libs/partners/upstage/langchain_upstage/py.typed delete mode 100644 libs/partners/upstage/langchain_upstage/tools/groundedness_check.py delete mode 100644 libs/partners/upstage/poetry.lock delete mode 100644 libs/partners/upstage/pyproject.toml delete mode 100644 libs/partners/upstage/scripts/check_imports.py delete mode 100755 libs/partners/upstage/scripts/check_pydantic.sh delete mode 100755 libs/partners/upstage/scripts/lint_imports.sh delete mode 100644 libs/partners/upstage/tests/__init__.py delete mode 100644 libs/partners/upstage/tests/examples/solar.pdf delete mode 100644 libs/partners/upstage/tests/integration_tests/__init__.py delete mode 100644 libs/partners/upstage/tests/integration_tests/test_chat_models.py delete mode 100644 libs/partners/upstage/tests/integration_tests/test_chat_models_standard.py delete mode 100644 libs/partners/upstage/tests/integration_tests/test_compile.py delete mode 100644 libs/partners/upstage/tests/integration_tests/test_embeddings.py delete mode 100644 libs/partners/upstage/tests/integration_tests/test_groundedness_check.py delete mode 100644 libs/partners/upstage/tests/unit_tests/__init__.py delete mode 100644 libs/partners/upstage/tests/unit_tests/test_chat_models.py delete mode 100644 libs/partners/upstage/tests/unit_tests/test_chat_models_standard.py delete mode 100644 libs/partners/upstage/tests/unit_tests/test_embeddings.py delete mode 100644 libs/partners/upstage/tests/unit_tests/test_groundedness_check.py delete mode 100644 libs/partners/upstage/tests/unit_tests/test_imports.py delete mode 100644 libs/partners/upstage/tests/unit_tests/test_layout_analysis.py delete mode 100644 libs/partners/upstage/tests/unit_tests/test_secrets.py diff --git a/libs/partners/upstage/LICENSE b/libs/partners/upstage/LICENSE deleted file mode 100644 index fc0602feec..0000000000 --- a/libs/partners/upstage/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/upstage/Makefile b/libs/partners/upstage/Makefile deleted file mode 100644 index 1fbb1e8220..0000000000 --- a/libs/partners/upstage/Makefile +++ /dev/null @@ -1,57 +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 - -# 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/upstage --name-only --diff-filter=d master | grep -E '\.py$$|\.ipynb$$') -lint_package: PYTHON_FILES=langchain_upstage -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_upstage -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/upstage/README.md b/libs/partners/upstage/README.md index e26cb409a7..c8b61f4859 100644 --- a/libs/partners/upstage/README.md +++ b/libs/partners/upstage/README.md @@ -1,25 +1,3 @@ -# langchain-upstage +This package has moved! -This package contains the LangChain integrations for [Upstage](https://upstage.ai) through their [APIs](https://developers.upstage.ai/docs/getting-started/models). - -## Installation and Setup - -- Install the LangChain partner package -```bash -pip install -U langchain-upstage -``` - -- Get an Upstage api key from [Upstage Console](https://console.upstage.ai/home) and set it as an environment variable (`UPSTAGE_API_KEY`) - -## Chat Models - -This package contains the `ChatUpstage` class, which is the recommended way to interface with Upstage models. - -See a [usage example](https://python.langchain.com/docs/integrations/chat/upstage) - -## Embeddings - -See a [usage example](https://python.langchain.com/docs/integrations/text_embedding/upstage) - -Use `solar-embedding-1-large` model for embeddings. Do not add suffixes such as `-query` or `-passage` to the model name. -`UpstageEmbeddings` will automatically add the suffixes based on the method called. +https://github.com/langchain-ai/langchain-upstage/tree/main/libs/upstage \ No newline at end of file diff --git a/libs/partners/upstage/langchain_upstage/__init__.py b/libs/partners/upstage/langchain_upstage/__init__.py deleted file mode 100644 index 77c1b91724..0000000000 --- a/libs/partners/upstage/langchain_upstage/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -from langchain_upstage.chat_models import ChatUpstage -from langchain_upstage.embeddings import UpstageEmbeddings -from langchain_upstage.layout_analysis import UpstageLayoutAnalysisLoader -from langchain_upstage.layout_analysis_parsers import UpstageLayoutAnalysisParser -from langchain_upstage.tools.groundedness_check import ( - GroundednessCheck, - UpstageGroundednessCheck, -) - -__all__ = [ - "ChatUpstage", - "UpstageEmbeddings", - "UpstageLayoutAnalysisLoader", - "UpstageLayoutAnalysisParser", - "UpstageGroundednessCheck", - "GroundednessCheck", -] diff --git a/libs/partners/upstage/langchain_upstage/chat_models.py b/libs/partners/upstage/langchain_upstage/chat_models.py deleted file mode 100644 index a8466a7864..0000000000 --- a/libs/partners/upstage/langchain_upstage/chat_models.py +++ /dev/null @@ -1,120 +0,0 @@ -import os -from typing import ( - Any, - Dict, - List, - Optional, -) - -import openai -from langchain_core.language_models.chat_models import LangSmithParams -from langchain_core.pydantic_v1 import Field, SecretStr, root_validator -from langchain_core.utils import ( - convert_to_secret_str, - get_from_dict_or_env, -) -from langchain_openai.chat_models.base import BaseChatOpenAI - - -class ChatUpstage(BaseChatOpenAI): - """ChatUpstage chat model. - - To use, you should have the environment variable `UPSTAGE_API_KEY` - set with your API key or pass it as a named parameter to the constructor. - - Example: - .. code-block:: python - - from langchain_upstage import ChatUpstage - - - model = ChatUpstage() - """ - - @property - def lc_secrets(self) -> Dict[str, str]: - return {"upstage_api_key": "UPSTAGE_API_KEY"} - - @classmethod - def get_lc_namespace(cls) -> List[str]: - return ["langchain", "chat_models", "upstage"] - - @property - def lc_attributes(self) -> Dict[str, Any]: - attributes: Dict[str, Any] = {} - - if self.upstage_api_base: - attributes["upstage_api_base"] = self.upstage_api_base - - return attributes - - @property - def _llm_type(self) -> str: - """Return type of chat model.""" - return "upstage-chat" - - def _get_ls_params( - self, stop: Optional[List[str]] = None, **kwargs: Any - ) -> LangSmithParams: - """Get the parameters used to invoke the model.""" - params = super()._get_ls_params(stop=stop, **kwargs) - params["ls_provider"] = "upstage" - return params - - model_name: str = Field(default="solar-1-mini-chat", alias="model") - """Model name to use.""" - upstage_api_key: Optional[SecretStr] = Field(default=None, alias="api_key") - """Automatically inferred from env are `UPSTAGE_API_KEY` if not provided.""" - upstage_api_base: Optional[str] = Field( - default="https://api.upstage.ai/v1/solar", alias="base_url" - ) - """Base URL path for API requests, leave blank if not using a proxy or service - emulator.""" - openai_api_key: Optional[SecretStr] = Field(default=None) - """openai api key is not supported for upstage. use `upstage_api_key` instead.""" - openai_api_base: Optional[str] = Field(default=None) - """openai api base is not supported for upstage. use `upstage_api_base` instead.""" - openai_organization: Optional[str] = Field(default=None) - """openai organization is not supported for upstage.""" - tiktoken_model_name: Optional[str] = None - """tiktoken is not supported for upstage.""" - - @root_validator() - def validate_environment(cls, values: Dict) -> Dict: - """Validate that api key and python package exists in environment.""" - if values["n"] < 1: - raise ValueError("n must be at least 1.") - if values["n"] > 1 and values["streaming"]: - raise ValueError("n must be 1 when streaming.") - - values["upstage_api_key"] = convert_to_secret_str( - get_from_dict_or_env(values, "upstage_api_key", "UPSTAGE_API_KEY") - ) - values["upstage_api_base"] = values["upstage_api_base"] or os.getenv( - "UPSTAGE_API_BASE" - ) - - client_params = { - "api_key": ( - values["upstage_api_key"].get_secret_value() - if values["upstage_api_key"] - else None - ), - "base_url": values["upstage_api_base"], - "timeout": values["request_timeout"], - "max_retries": values["max_retries"], - "default_headers": values["default_headers"], - "default_query": values["default_query"], - } - - if not values.get("client"): - sync_specific = {"http_client": values["http_client"]} - values["client"] = openai.OpenAI( - **client_params, **sync_specific - ).chat.completions - if not values.get("async_client"): - async_specific = {"http_client": values["http_async_client"]} - values["async_client"] = openai.AsyncOpenAI( - **client_params, **async_specific - ).chat.completions - return values diff --git a/libs/partners/upstage/langchain_upstage/embeddings.py b/libs/partners/upstage/langchain_upstage/embeddings.py deleted file mode 100644 index 5a74b32832..0000000000 --- a/libs/partners/upstage/langchain_upstage/embeddings.py +++ /dev/null @@ -1,276 +0,0 @@ -import logging -import os -import warnings -from typing import ( - Any, - Dict, - List, - Literal, - Mapping, - Optional, - Sequence, - Set, - Tuple, - Union, -) - -import openai -from langchain_core.embeddings import Embeddings -from langchain_core.pydantic_v1 import ( - BaseModel, - Extra, - Field, - SecretStr, - root_validator, -) -from langchain_core.utils import ( - convert_to_secret_str, - get_from_dict_or_env, - get_pydantic_field_names, -) - -logger = logging.getLogger(__name__) - -DEFAULT_EMBED_BATCH_SIZE = 10 -MAX_EMBED_BATCH_SIZE = 100 - - -class UpstageEmbeddings(BaseModel, Embeddings): - """UpstageEmbeddings embedding model. - - To use, set the environment variable `UPSTAGE_API_KEY` with your API key or - pass it as a named parameter to the constructor. - - Example: - .. code-block:: python - - from langchain_upstage import UpstageEmbeddings - - model = UpstageEmbeddings(model='solar-embedding-1-large') - """ - - client: Any = Field(default=None, exclude=True) #: :meta private: - async_client: Any = Field(default=None, exclude=True) #: :meta private: - model: str = Field(...) - """Embeddings model name to use. Do not add suffixes like `-query` and `-passage`. - Instead, use 'solar-embedding-1-large' for example. - """ - dimensions: Optional[int] = None - """The number of dimensions the resulting output embeddings should have. - - Not yet supported. - """ - upstage_api_key: Optional[SecretStr] = Field(default=None, alias="api_key") - """API Key for Solar API.""" - upstage_api_base: str = Field( - default="https://api.upstage.ai/v1/solar", alias="base_url" - ) - """Endpoint URL to use.""" - embedding_ctx_length: int = 4096 - """The maximum number of tokens to embed at once. - - Not yet supported. - """ - embed_batch_size: int = DEFAULT_EMBED_BATCH_SIZE - allowed_special: Union[Literal["all"], Set[str]] = set() - """Not yet supported.""" - disallowed_special: Union[Literal["all"], Set[str], Sequence[str]] = "all" - """Not yet supported.""" - chunk_size: int = 1000 - """Maximum number of texts to embed in each batch. - - Not yet supported. - """ - max_retries: int = 2 - """Maximum number of retries to make when generating.""" - request_timeout: Optional[Union[float, Tuple[float, float], Any]] = Field( - default=None, alias="timeout" - ) - """Timeout for requests to Upstage embedding API. Can be float, httpx.Timeout or - None.""" - show_progress_bar: bool = False - """Whether to show a progress bar when embedding. - - Not yet supported. - """ - model_kwargs: Dict[str, Any] = Field(default_factory=dict) - """Holds any model parameters valid for `create` call not explicitly specified.""" - skip_empty: bool = False - """Whether to skip empty strings when embedding or raise an error. - Defaults to not skipping. - - Not yet supported.""" - default_headers: Union[Mapping[str, str], None] = None - default_query: Union[Mapping[str, object], None] = None - # Configure a custom httpx client. See the - # [httpx documentation](https://www.python-httpx.org/api/#client) for more details. - http_client: Union[Any, None] = None - """Optional httpx.Client. Only used for sync invocations. Must specify - http_async_client as well if you'd like a custom client for async invocations. - """ - http_async_client: Union[Any, None] = None - """Optional httpx.AsyncClient. Only used for async invocations. Must specify - http_client as well if you'd like a custom client for sync invocations.""" - - class Config: - extra = Extra.forbid - allow_population_by_field_name = True - - @root_validator(pre=True) - def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]: - """Build extra kwargs from additional params that were passed in.""" - all_required_field_names = get_pydantic_field_names(cls) - extra = values.get("model_kwargs", {}) - for field_name in list(values): - if field_name in extra: - raise ValueError(f"Found {field_name} supplied twice.") - if field_name not in all_required_field_names: - warnings.warn( - f"""WARNING! {field_name} is not default parameter. - {field_name} was transferred to model_kwargs. - Please confirm that {field_name} is what you intended.""" - ) - extra[field_name] = values.pop(field_name) - - invalid_model_kwargs = all_required_field_names.intersection(extra.keys()) - if invalid_model_kwargs: - raise ValueError( - f"Parameters {invalid_model_kwargs} should be specified explicitly. " - f"Instead they were passed in as part of `model_kwargs` parameter." - ) - - values["model_kwargs"] = extra - return values - - @root_validator() - def validate_environment(cls, values: Dict) -> Dict: - """Validate that api key and python package exists in environment.""" - - upstage_api_key = get_from_dict_or_env( - values, "upstage_api_key", "UPSTAGE_API_KEY" - ) - values["upstage_api_key"] = ( - convert_to_secret_str(upstage_api_key) if upstage_api_key else None - ) - values["upstage_api_base"] = values["upstage_api_base"] or os.getenv( - "UPSTAGE_API_BASE" - ) - client_params = { - "api_key": ( - values["upstage_api_key"].get_secret_value() - if values["upstage_api_key"] - else None - ), - "base_url": values["upstage_api_base"], - "timeout": values["request_timeout"], - "max_retries": values["max_retries"], - "default_headers": values["default_headers"], - "default_query": values["default_query"], - } - if not values.get("client"): - sync_specific = {"http_client": values["http_client"]} - values["client"] = openai.OpenAI( - **client_params, **sync_specific - ).embeddings - if not values.get("async_client"): - async_specific = {"http_client": values["http_async_client"]} - values["async_client"] = openai.AsyncOpenAI( - **client_params, **async_specific - ).embeddings - return values - - @property - def _invocation_params(self) -> Dict[str, Any]: - self.model = self.model.replace("-query", "").replace("-passage", "") - - params: Dict = {"model": self.model, **self.model_kwargs} - if self.dimensions is not None: - params["dimensions"] = self.dimensions - return params - - def embed_documents(self, texts: List[str]) -> List[List[float]]: - """Embed a list of document texts using passage model. - - Args: - texts: The list of texts to embed. - - Returns: - List of embeddings, one for each text. - """ - assert ( - self.embed_batch_size <= MAX_EMBED_BATCH_SIZE - ), f"The embed_batch_size should not be larger than {MAX_EMBED_BATCH_SIZE}." - if not texts: - return [] - params = self._invocation_params - params["model"] = params["model"] + "-passage" - embeddings = [] - - batch_size = min(self.embed_batch_size, len(texts)) - for i in range(0, len(texts), batch_size): - batch = texts[i : i + batch_size] - data = self.client.create(input=batch, **params).data - embeddings.extend([r.embedding for r in data]) - - return embeddings - - def embed_query(self, text: str) -> List[float]: - """Embed query text using query model. - - Args: - text: The text to embed. - - Returns: - Embedding for the text. - """ - params = self._invocation_params - params["model"] = params["model"] + "-query" - - response = self.client.create(input=text, **params) - - if not isinstance(response, dict): - response = response.model_dump() - return response["data"][0]["embedding"] - - async def aembed_documents(self, texts: List[str]) -> List[List[float]]: - """Embed a list of document texts using passage model asynchronously. - - Args: - texts: The list of texts to embed. - - Returns: - List of embeddings, one for each text. - """ - assert ( - self.embed_batch_size <= MAX_EMBED_BATCH_SIZE - ), f"The embed_batch_size should not be larger than {MAX_EMBED_BATCH_SIZE}." - if not texts: - return [] - params = self._invocation_params - params["model"] = params["model"] + "-passage" - embeddings = [] - - batch_size = min(self.embed_batch_size, len(texts)) - for i in range(0, len(texts), batch_size): - batch = texts[i : i + batch_size] - response = await self.async_client.create(input=batch, **params) - embeddings.extend([r.embedding for r in response.data]) - return embeddings - - async def aembed_query(self, text: str) -> List[float]: - """Asynchronous Embed query text using query model. - - Args: - text: The text to embed. - - Returns: - Embedding for the text. - """ - params = self._invocation_params - params["model"] = params["model"] + "-query" - - response = await self.async_client.create(input=text, **params) - - if not isinstance(response, dict): - response = response.model_dump() - return response["data"][0]["embedding"] diff --git a/libs/partners/upstage/langchain_upstage/layout_analysis.py b/libs/partners/upstage/langchain_upstage/layout_analysis.py deleted file mode 100644 index fc68f4d139..0000000000 --- a/libs/partners/upstage/langchain_upstage/layout_analysis.py +++ /dev/null @@ -1,248 +0,0 @@ -import os -import warnings -from pathlib import Path -from typing import Any, Dict, Iterator, List, Literal, Optional, Union - -from langchain_core.document_loaders import BaseLoader, Blob -from langchain_core.documents import Document - -from .layout_analysis_parsers import UpstageLayoutAnalysisParser - -DEFAULT_PAGE_BATCH_SIZE = 10 - -OutputType = Literal["text", "html"] -SplitType = Literal["none", "element", "page"] - - -def validate_api_key(api_key: str) -> None: - """ - Validates the provided API key. - - Args: - api_key (str): The API key to be validated. - - Raises: - ValueError: If the API key is empty or None. - - Returns: - None - """ - if not api_key: - raise ValueError("API Key is required for Upstage Document Loader") - - -def validate_file_path(file_path: Union[str, Path, List[str], List[Path]]) -> None: - """ - Validates if a file exists at the given file path. - - Args: - file_path (Union[str, Path, List[str], List[Path]): The file path(s) to be - validated. - - Raises: - FileNotFoundError: If the file or any of the files in the list do not exist. - """ - if isinstance(file_path, list): - for path in file_path: - validate_file_path(path) - return - if not os.path.exists(file_path): - raise FileNotFoundError(f"File not found: {file_path}") - - -def get_from_param_or_env( - key: str, - param: Optional[str] = None, - env_key: Optional[str] = None, - default: Optional[str] = None, -) -> str: - """Get a value from a param or an environment variable.""" - if param is not None: - return param - elif env_key and env_key in os.environ and os.environ[env_key]: - return os.environ[env_key] - elif default is not None: - return default - else: - raise ValueError( - f"Did not find {key}, please add an environment variable" - f" `{env_key}` which contains it, or pass" - f" `{key}` as a named parameter." - ) - - -class UpstageLayoutAnalysisLoader(BaseLoader): - """Upstage Layout Analysis. - - To use, you should have the environment variable `UPSTAGE_API_KEY` - set with your API key or pass it as a named parameter to the constructor. - - Example: - .. code-block:: python - - from langchain_upstage import UpstageLayoutAnalysis - - file_path = "/PATH/TO/YOUR/FILE.pdf" - loader = UpstageLayoutAnalysis( - file_path, split="page", output_type="text" - ) - """ - - def __init__( - self, - file_path: Union[str, Path, List[str], List[Path]], - output_type: Union[OutputType, dict] = "html", - split: SplitType = "none", - api_key: Optional[str] = None, - use_ocr: bool = False, - exclude: list = ["header", "footer"], - ): - """ - Initializes an instance of the Upstage document loader. - - Args: - file_path (Union[str, Path, List[str], List[Path]): The path to the document - to be loaded. - output_type (Union[OutputType, dict], optional): The type of output to be - generated by the parser. - Defaults to "html". - split (SplitType, optional): The type of splitting to be applied. - Defaults to "none" (no splitting). - api_key (str, optional): The API key for accessing the Upstage API. - Defaults to None, in which case it will be - fetched from the environment variable - `UPSTAGE_API_KEY`. - use_ocr (bool, optional): Extract text from images in the document. - Defaults to False. (Use text info in PDF file) - exclude (list, optional): Exclude specific elements from - the output. - Defaults to ["header", "footer"]. - """ - self.file_path = file_path - self.output_type = output_type - self.split = split - if deprecated_key := os.environ.get("UPSTAGE_DOCUMENT_AI_API_KEY"): - warnings.warn( - "UPSTAGE_DOCUMENT_AI_API_KEY is deprecated." - "Please use UPSTAGE_API_KEY instead." - ) - - self.api_key = get_from_param_or_env( - "UPSTAGE_API_KEY", api_key, "UPSTAGE_API_KEY", deprecated_key - ) - self.use_ocr = use_ocr - self.exclude = exclude - - validate_file_path(self.file_path) - validate_api_key(self.api_key) - - def load(self) -> List[Document]: - """ - Loads and parses the document using the UpstageLayoutAnalysisParser. - - Returns: - A list of Document objects representing the parsed layout analysis. - """ - - if isinstance(self.file_path, list): - result = [] - - for file_path in self.file_path: - blob = Blob.from_path(file_path) - - parser = UpstageLayoutAnalysisParser( - self.api_key, - split=self.split, - output_type=self.output_type, - use_ocr=self.use_ocr, - exclude=self.exclude, - ) - result.extend(list(parser.lazy_parse(blob, is_batch=True))) - - return result - - else: - blob = Blob.from_path(self.file_path) - - parser = UpstageLayoutAnalysisParser( - self.api_key, - split=self.split, - output_type=self.output_type, - use_ocr=self.use_ocr, - exclude=self.exclude, - ) - return list(parser.lazy_parse(blob, is_batch=True)) - - def lazy_load(self) -> Iterator[Document]: - """ - Lazily loads and parses the document using the UpstageLayoutAnalysisParser. - - Returns: - An iterator of Document objects representing the parsed layout analysis. - """ - - if isinstance(self.file_path, list): - for file_path in self.file_path: - blob = Blob.from_path(file_path) - - parser = UpstageLayoutAnalysisParser( - self.api_key, - split=self.split, - output_type=self.output_type, - use_ocr=self.use_ocr, - exclude=self.exclude, - ) - yield from parser.lazy_parse(blob, is_batch=True) - else: - blob = Blob.from_path(self.file_path) - - parser = UpstageLayoutAnalysisParser( - self.api_key, - split=self.split, - output_type=self.output_type, - use_ocr=self.use_ocr, - exclude=self.exclude, - ) - yield from parser.lazy_parse(blob) - - def merge_and_split( - self, documents: List[Document], splitter: Optional[object] = None - ) -> List[Document]: - """ - Merges the page content and metadata of multiple documents into a single - document, or splits the documents using a custom splitter. - - Args: - documents (list): A list of Document objects to be merged and split. - splitter (object, optional): An optional splitter object that implements the - `split_documents` method. If provided, the documents will be split using - this splitter. Defaults to None, in which case the documents are merged. - - Returns: - list: A list of Document objects. If no splitter is provided, a single - Document object is returned with the merged content and combined metadata. - If a splitter is provided, the documents are split and a list of Document - objects is returned. - - Raises: - AssertionError: If a splitter is provided but it does not implement the - `split_documents` method. - """ - if splitter is None: - merged_content = " ".join([doc.page_content for doc in documents]) - - metadatas: Dict[str, Any] = dict() - for _meta in [doc.metadata for doc in documents]: - for key, value in _meta.items(): - if key in metadatas: - metadatas[key].append(value) - else: - metadatas[key] = [value] - - return [Document(page_content=merged_content, metadata=metadatas)] - else: - assert hasattr( - splitter, "split_documents" - ), "splitter must implement split_documents method" - - return splitter.split_documents(documents) diff --git a/libs/partners/upstage/langchain_upstage/layout_analysis_parsers.py b/libs/partners/upstage/langchain_upstage/layout_analysis_parsers.py deleted file mode 100644 index 17b571c513..0000000000 --- a/libs/partners/upstage/langchain_upstage/layout_analysis_parsers.py +++ /dev/null @@ -1,396 +0,0 @@ -import io -import json -import os -import warnings -from typing import Dict, Iterator, List, Literal, Optional, Union - -import fitz # type: ignore -import requests -from fitz import Document as fitzDocument -from langchain_core.document_loaders import BaseBlobParser, Blob -from langchain_core.documents import Document - -LAYOUT_ANALYSIS_URL = "https://api.upstage.ai/v1/document-ai/layout-analysis" - -DEFAULT_NUMBER_OF_PAGE = 10 - -OutputType = Literal["text", "html"] -SplitType = Literal["none", "element", "page"] - - -def validate_api_key(api_key: str) -> None: - """ - Validates the provided API key. - - Args: - api_key (str): The API key to be validated. - - Raises: - ValueError: If the API key is empty or None. - - Returns: - None - """ - if not api_key: - raise ValueError("API Key is required for Upstage Document Loader") - - -def validate_file_path(file_path: str) -> None: - """ - Validates if a file exists at the given file path. - - Args: - file_path (str): The path to the file. - - Raises: - FileNotFoundError: If the file does not exist at the given file path. - """ - if not os.path.exists(file_path): - raise FileNotFoundError(f"File not found: {file_path}") - - -def parse_output(data: dict, output_type: Union[OutputType, dict]) -> str: - """ - Parse the output data based on the specified output type. - - Args: - data (dict): The data to be parsed. - output_type (Union[OutputType, dict]): The output type to parse the element data - into. - - Returns: - str: The parsed output. - - Raises: - ValueError: If the output type is invalid. - """ - if isinstance(output_type, dict): - if data["category"] in output_type: - return data[output_type[data["category"]]] - else: - return data["text"] - elif isinstance(output_type, str): - if output_type == "text": - return data["text"] - elif output_type == "html": - return data["html"] - else: - raise ValueError(f"Invalid output type: {output_type}") - else: - raise ValueError(f"Invalid output type: {output_type}") - - -def get_from_param_or_env( - key: str, - param: Optional[str] = None, - env_key: Optional[str] = None, - default: Optional[str] = None, -) -> str: - """Get a value from a param or an environment variable.""" - if param is not None: - return param - elif env_key and env_key in os.environ and os.environ[env_key]: - return os.environ[env_key] - elif default is not None: - return default - else: - raise ValueError( - f"Did not find {key}, please add an environment variable" - f" `{env_key}` which contains it, or pass" - f" `{key}` as a named parameter." - ) - - -class UpstageLayoutAnalysisParser(BaseBlobParser): - """Upstage Layout Analysis Parser. - - To use, you should have the environment variable `UPSTAGE_API_KEY` - set with your API key or pass it as a named parameter to the constructor. - - Example: - .. code-block:: python - - from langchain_upstage import UpstageLayoutAnalysisParser - - loader = UpstageLayoutAnalysisParser(split="page", output_type="text") - """ - - def __init__( - self, - api_key: Optional[str] = None, - output_type: Union[OutputType, dict] = "html", - split: SplitType = "none", - use_ocr: bool = False, - exclude: list = [], - ): - """ - Initializes an instance of the Upstage class. - - Args: - api_key (str, optional): The API key for accessing the Upstage API. - Defaults to None, in which case it will be - fetched from the environment variable - `UPSTAGE_API_KEY`. - output_type (Union[OutputType, dict], optional): The type of output to be - generated by the parser. - Defaults to "html". - split (SplitType, optional): The type of splitting to be applied. - Defaults to "none" (no splitting). - use_ocr (bool, optional): Extract text from images in the document. - Defaults to False. (Use text info in PDF file) - exclude (list, optional): Exclude specific elements from the output. - Defaults to [] (all included). - """ - if deprecated_key := os.environ.get("UPSTAGE_DOCUMENT_AI_API_KEY"): - warnings.warn( - "UPSTAGE_DOCUMENT_AI_API_KEY is deprecated." - "Please use UPSTAGE_API_KEY instead." - ) - self.api_key = get_from_param_or_env( - "UPSTAGE_API_KEY", api_key, "UPSTAGE_API_KEY", deprecated_key - ) - - self.output_type = output_type - self.split = split - self.use_ocr = use_ocr - self.exclude = exclude - - validate_api_key(self.api_key) - - def _get_response(self, files: Dict) -> List: - """ - Sends a POST request to the API endpoint with the provided files and - returns the response. - - Args: - files (dict): A dictionary containing the files to be sent in the request. - - Returns: - dict: The JSON response from the API. - - Raises: - ValueError: If there is an error in the API call. - """ - try: - headers = {"Authorization": f"Bearer {self.api_key}"} - options = {"ocr": self.use_ocr} - response = requests.post( - LAYOUT_ANALYSIS_URL, headers=headers, files=files, data=options - ) - response.raise_for_status() - - result = response.json().get("elements", []) - - elements = [ - element for element in result if element["category"] not in self.exclude - ] - - return elements - - except requests.RequestException as req_err: - # Handle any request-related exceptions - print(f"Request Exception: {req_err}") - raise ValueError(f"Failed to send request: {req_err}") - except json.JSONDecodeError as json_err: - # Handle JSON decode errors - print(f"JSON Decode Error: {json_err}") - raise ValueError(f"Failed to decode JSON response: {json_err}") - - return [] - - def _split_and_request( - self, - full_docs: fitzDocument, - start_page: int, - num_pages: int = DEFAULT_NUMBER_OF_PAGE, - ) -> List: - """ - Splits the full pdf document into partial pages and sends a request to the - server. - - Args: - full_docs (str): The full document to be split and requested. - start_page (int): The starting page number for splitting the document. - num_pages (int, optional): The number of pages to split the document - into. - Defaults to DEFAULT_NUMBER_OF_PAGE. - - Returns: - response: The response from the server. - """ - with fitz.open() as chunk_pdf: - chunk_pdf.insert_pdf( - full_docs, - from_page=start_page, - to_page=start_page + num_pages - 1, - ) - pdf_bytes = chunk_pdf.write() - - with io.BytesIO(pdf_bytes) as f: - response = self._get_response({"document": f}) - - return response - - def _element_document(self, elements: Dict) -> Document: - """ - Converts an elements into a Document object. - - Args: - elements: The elements to convert. - - Returns: - A list containing a single Document object. - - """ - return Document( - page_content=(parse_output(elements, self.output_type)), - metadata={ - "page": elements["page"], - "id": elements["id"], - "type": self.output_type, - "split": self.split, - "bbox": elements["bounding_box"], - "category": elements["category"], - }, - ) - - def _page_document(self, elements: List) -> List[Document]: - """ - Combines elements with the same page number into a single Document object. - - Args: - elements (List): A list of elements containing page numbers. - - Returns: - List[Document]: A list of Document objects, each representing a page - with its content and metadata. - """ - _docs = [] - pages = sorted(set(map(lambda x: x["page"], elements))) - - page_group = [ - [element for element in elements if element["page"] == x] for x in pages - ] - - for group in page_group: - page_content = " ".join( - [parse_output(element, self.output_type) for element in group] - ) - - _docs.append( - Document( - page_content=page_content, - metadata={ - "page": group[0]["page"], - "type": self.output_type, - "split": self.split, - }, - ) - ) - - return _docs - - def lazy_parse(self, blob: Blob, is_batch: bool = False) -> Iterator[Document]: - """ - Lazily parses a document and yields Document objects based on the specified - split type. - - Args: - blob (Blob): The input document blob to parse. - is_batch (bool, optional): Whether to parse the document in batches. - Defaults to False (single page parsing) - - Yields: - Document: The parsed document object. - - Raises: - ValueError: If an invalid split type is provided. - - """ - - if is_batch: - num_pages = DEFAULT_NUMBER_OF_PAGE - else: - num_pages = 1 - - full_docs = fitz.open(blob.path) - number_of_pages = full_docs.page_count - - if self.split == "none": - if full_docs.is_pdf: - result = "" - start_page = 0 - num_pages = DEFAULT_NUMBER_OF_PAGE - for _ in range(number_of_pages): - if start_page >= number_of_pages: - break - - elements = self._split_and_request(full_docs, start_page, num_pages) - for element in elements: - result += parse_output(element, self.output_type) - - start_page += num_pages - - else: - if not blob.path: - raise ValueError("Blob path is required for non-PDF files.") - - result = "" - with open(blob.path, "rb") as f: - elements = self._get_response({"document": f}) - - for element in elements: - result += parse_output(element, self.output_type) - - yield Document( - page_content=result, - metadata={ - "total_pages": number_of_pages, - "type": self.output_type, - "split": self.split, - }, - ) - - elif self.split == "element": - if full_docs.is_pdf: - start_page = 0 - for _ in range(number_of_pages): - if start_page >= number_of_pages: - break - - elements = self._split_and_request(full_docs, start_page, num_pages) - for element in elements: - yield self._element_document(element) - - start_page += num_pages - - else: - if not blob.path: - raise ValueError("Blob path is required for non-PDF files.") - with open(blob.path, "rb") as f: - elements = self._get_response({"document": f}) - - for element in elements: - yield self._element_document(element) - - elif self.split == "page": - if full_docs.is_pdf: - start_page = 0 - for _ in range(number_of_pages): - if start_page >= number_of_pages: - break - - elements = self._split_and_request(full_docs, start_page, num_pages) - yield from self._page_document(elements) - - start_page += num_pages - else: - if not blob.path: - raise ValueError("Blob path is required for non-PDF files.") - with open(blob.path, "rb") as f: - elements = self._get_response({"document": f}) - - yield from self._page_document(elements) - - else: - raise ValueError(f"Invalid split type: {self.split}") diff --git a/libs/partners/upstage/langchain_upstage/py.typed b/libs/partners/upstage/langchain_upstage/py.typed deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libs/partners/upstage/langchain_upstage/tools/groundedness_check.py b/libs/partners/upstage/langchain_upstage/tools/groundedness_check.py deleted file mode 100644 index fa93303491..0000000000 --- a/libs/partners/upstage/langchain_upstage/tools/groundedness_check.py +++ /dev/null @@ -1,117 +0,0 @@ -import os -from typing import Any, List, Literal, Optional, Type, Union - -from langchain_core._api.deprecation import deprecated -from langchain_core.callbacks import ( - AsyncCallbackManagerForToolRun, - CallbackManagerForToolRun, -) -from langchain_core.documents import Document -from langchain_core.messages import AIMessage, HumanMessage -from langchain_core.pydantic_v1 import BaseModel, Field, SecretStr -from langchain_core.tools import BaseTool -from langchain_core.utils import convert_to_secret_str - -from langchain_upstage import ChatUpstage - - -class UpstageGroundednessCheckInput(BaseModel): - """Input for the Groundedness Check tool.""" - - context: Union[str, List[Document]] = Field( - description="context in which the answer should be verified" - ) - answer: str = Field( - description="assistant's reply or a text that is subject to groundedness check" - ) - - -class UpstageGroundednessCheck(BaseTool): - """Tool that checks the groundedness of a context and an assistant message. - - To use, you should have the environment variable `UPSTAGE_API_KEY` - set with your API key or pass it as a named parameter to the constructor. - - Example: - .. code-block:: python - - from langchain_upstage import UpstageGroundednessCheck - - tool = UpstageGroundednessCheck() - """ - - name: str = "groundedness_check" - description: str = ( - "A tool that checks the groundedness of an assistant response " - "to user-provided context. UpstageGroundednessCheck ensures that " - "the assistant’s response is not only relevant but also " - "precisely aligned with the user's initial context, " - "promoting a more reliable and context-aware interaction. " - "When using retrieval-augmented generation (RAG), " - "the Groundedness Check can be used to determine whether " - "the assistant's message is grounded in the provided context." - ) - upstage_api_key: Optional[SecretStr] = Field(default=None, alias="api_key") - api_wrapper: ChatUpstage - - args_schema: Type[BaseModel] = UpstageGroundednessCheckInput - - def __init__(self, **kwargs: Any) -> None: - upstage_api_key = kwargs.get("upstage_api_key", None) - if not upstage_api_key: - upstage_api_key = kwargs.get("api_key", None) - if not upstage_api_key: - upstage_api_key = SecretStr(os.getenv("UPSTAGE_API_KEY", "")) - upstage_api_key = convert_to_secret_str(upstage_api_key) - - if ( - not upstage_api_key - or not upstage_api_key.get_secret_value() - or upstage_api_key.get_secret_value() == "" - ): - raise ValueError("UPSTAGE_API_KEY must be set or passed") - - api_wrapper = ChatUpstage( - model_name="solar-1-mini-answer-verification", - upstage_api_key=upstage_api_key.get_secret_value(), - ) - super().__init__(upstage_api_key=upstage_api_key, api_wrapper=api_wrapper) - - def formatDocumentsAsString(self, docs: List[Document]) -> str: - return "\n".join([doc.page_content for doc in docs]) - - def _run( - self, - context: Union[str, List[Document]], - answer: str, - run_manager: Optional[CallbackManagerForToolRun] = None, - ) -> Union[str, Literal["grounded", "notGrounded", "notSure"]]: - """Use the tool.""" - if isinstance(context, List): - context = self.formatDocumentsAsString(context) - response = self.api_wrapper.invoke( - [HumanMessage(context), AIMessage(answer)], stream=False - ) - return str(response.content) - - async def _arun( - self, - context: Union[str, List[Document]], - answer: str, - run_manager: Optional[AsyncCallbackManagerForToolRun] = None, - ) -> Union[str, Literal["grounded", "notGrounded", "notSure"]]: - if isinstance(context, List): - context = self.formatDocumentsAsString(context) - response = await self.api_wrapper.ainvoke( - [HumanMessage(context), AIMessage(answer)], stream=False - ) - return str(response.content) - - -@deprecated( - since="0.1.3", - removal="0.3.0", - alternative_import="langchain_upstage.UpstageGroundednessCheck", -) -class GroundednessCheck(UpstageGroundednessCheck): - pass diff --git a/libs/partners/upstage/poetry.lock b/libs/partners/upstage/poetry.lock deleted file mode 100644 index f0ea89c917..0000000000 --- a/libs/partners/upstage/poetry.lock +++ /dev/null @@ -1,1480 +0,0 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. - -[[package]] -name = "annotated-types" -version = "0.7.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, -] - -[[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 = "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 = "distro" -version = "1.9.0" -description = "Distro - an OS platform information API" -optional = false -python-versions = ">=3.6" -files = [ - {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, - {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, -] - -[[package]] -name = "docarray" -version = "0.32.1" -description = "The data structure for multimodal data" -optional = false -python-versions = ">=3.7,<4.0" -files = [ - {file = "docarray-0.32.1-py3-none-any.whl", hash = "sha256:abd6d8999f44fd37b0c1d54f7cedd9007ab13b8b6c69933a9d30abbd0cbad5cd"}, - {file = "docarray-0.32.1.tar.gz", hash = "sha256:ef349d2501d5cb0f205497e5e7de5b5d034965bdad98cf6daab1baa6aa3e39d2"}, -] - -[package.dependencies] -numpy = ">=1.17.3" -orjson = ">=3.8.2" -pydantic = ">=1.10.2" -rich = ">=13.1.0" -types-requests = ">=2.28.11.6" -typing-inspect = ">=0.8.0" - -[package.extras] -audio = ["pydub (>=0.25.1,<0.26.0)"] -aws = ["smart-open[s3] (>=6.3.0)"] -elasticsearch = ["elastic-transport (>=8.4.0,<9.0.0)", "elasticsearch (>=7.10.1)"] -full = ["av (>=10.0.0)", "lz4 (>=1.0.0)", "pandas (>=1.1.0)", "pillow (>=9.3.0)", "protobuf (>=3.19.0)", "pydub (>=0.25.1,<0.26.0)", "trimesh[easy] (>=3.17.1)", "types-pillow (>=9.3.0.1)"] -hnswlib = ["hnswlib (>=0.6.2)", "protobuf (>=3.19.0)"] -image = ["pillow (>=9.3.0)", "types-pillow (>=9.3.0.1)"] -jac = ["jina-hubble-sdk (>=0.34.0)"] -mesh = ["trimesh[easy] (>=3.17.1)"] -pandas = ["pandas (>=1.1.0)"] -proto = ["lz4 (>=1.0.0)", "protobuf (>=3.19.0)"] -qdrant = ["qdrant-client (>=1.1.4)"] -torch = ["torch (>=1.0.0)"] -video = ["av (>=10.0.0)"] -weaviate = ["weaviate-client (>=3.15)"] -web = ["fastapi (>=0.87.0)"] - -[[package]] -name = "exceptiongroup" -version = "1.2.1" -description = "Backport of PEP 654 (exception groups)" -optional = false -python-versions = ">=3.7" -files = [ - {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, - {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, -] - -[package.extras] -test = ["pytest (>=6)"] - -[[package]] -name = "freezegun" -version = "1.5.1" -description = "Let your Python tests travel through time" -optional = false -python-versions = ">=3.7" -files = [ - {file = "freezegun-1.5.1-py3-none-any.whl", hash = "sha256:bf111d7138a8abe55ab48a71755673dbaa4ab87f4cff5634a4442dfec34c15f1"}, - {file = "freezegun-1.5.1.tar.gz", hash = "sha256:b29dedfcda6d5e8e083ce71b2b542753ad48cfec44037b3fc79702e2980a89e9"}, -] - -[package.dependencies] -python-dateutil = ">=2.7" - -[[package]] -name = "h11" -version = "0.14.0" -description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -optional = false -python-versions = ">=3.7" -files = [ - {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, - {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, -] - -[[package]] -name = "httpcore" -version = "1.0.5" -description = "A minimal low-level HTTP client." -optional = false -python-versions = ">=3.8" -files = [ - {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"}, - {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"}, -] - -[package.dependencies] -certifi = "*" -h11 = ">=0.13,<0.15" - -[package.extras] -asyncio = ["anyio (>=4.0,<5.0)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] -trio = ["trio (>=0.22.0,<0.26.0)"] - -[[package]] -name = "httpx" -version = "0.27.0" -description = "The next generation HTTP client." -optional = false -python-versions = ">=3.8" -files = [ - {file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"}, - {file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"}, -] - -[package.dependencies] -anyio = "*" -certifi = "*" -httpcore = "==1.*" -idna = "*" -sniffio = "*" - -[package.extras] -brotli = ["brotli", "brotlicffi"] -cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] - -[[package]] -name = "idna" -version = "3.7" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.5" -files = [ - {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, - {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, -] - -[[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-core" -version = "0.2.9" -description = "Building applications with LLMs through composability" -optional = false -python-versions = ">=3.8.1,<4.0" -files = [] -develop = true - -[package.dependencies] -jsonpatch = "^1.33" -langsmith = "^0.1.75" -packaging = ">=23.2,<25" -pydantic = [ - {version = ">=1,<3", markers = "python_full_version < \"3.12.4\""}, - {version = ">=2.7.4,<3.0.0", markers = "python_full_version >= \"3.12.4\""}, -] -PyYAML = ">=5.3" -tenacity = "^8.1.0,!=8.4.0" - -[package.source] -type = "directory" -url = "../../core" - -[[package]] -name = "langchain-openai" -version = "0.1.8" -description = "An integration package connecting OpenAI and LangChain" -optional = false -python-versions = ">=3.8.1,<4.0" -files = [] -develop = true - -[package.dependencies] -langchain-core = ">=0.2.2,<0.3" -openai = "^1.26.0" -tiktoken = ">=0.7,<1" - -[package.source] -type = "directory" -url = "../openai" - -[[package]] -name = "langchain-standard-tests" -version = "0.1.1" -description = "Standard tests for LangChain implementations" -optional = false -python-versions = ">=3.8.1,<4.0" -files = [] -develop = true - -[package.dependencies] -httpx = "^0.27.0" -langchain-core = ">=0.1.40,<0.3" -pytest = ">=7,<9" - -[package.source] -type = "directory" -url = "../../standard-tests" - -[[package]] -name = "langsmith" -version = "0.1.77" -description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." -optional = false -python-versions = "<4.0,>=3.8.1" -files = [ - {file = "langsmith-0.1.77-py3-none-any.whl", hash = "sha256:2202cc21b1ed7e7b9e5d2af2694be28898afa048c09fdf09f620cbd9301755ae"}, - {file = "langsmith-0.1.77.tar.gz", hash = "sha256:4ace09077a9a4e412afeb4b517ca68e7de7b07f36e4792dc8236ac5207c0c0c7"}, -] - -[package.dependencies] -orjson = ">=3.9.14,<4.0.0" -pydantic = ">=1,<3" -requests = ">=2,<3" - -[[package]] -name = "markdown-it-py" -version = "3.0.0" -description = "Python port of markdown-it. Markdown parsing, done right!" -optional = false -python-versions = ">=3.8" -files = [ - {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, - {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, -] - -[package.dependencies] -mdurl = ">=0.1,<1.0" - -[package.extras] -benchmarking = ["psutil", "pytest", "pytest-benchmark"] -code-style = ["pre-commit (>=3.0,<4.0)"] -compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] -linkify = ["linkify-it-py (>=1,<3)"] -plugins = ["mdit-py-plugins"] -profiling = ["gprof2dot"] -rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] -testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] - -[[package]] -name = "mdurl" -version = "0.1.2" -description = "Markdown URL utilities" -optional = false -python-versions = ">=3.7" -files = [ - {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, - {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, -] - -[[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 = "numpy" -version = "1.26.4" -description = "Fundamental package for array computing in Python" -optional = false -python-versions = ">=3.9" -files = [ - {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, - {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, - {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"}, - {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"}, - {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"}, - {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"}, - {file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"}, - {file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"}, - {file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"}, - {file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"}, - {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"}, - {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"}, - {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"}, - {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"}, - {file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"}, - {file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"}, - {file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"}, - {file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"}, - {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"}, - {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"}, - {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"}, - {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"}, - {file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"}, - {file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"}, - {file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"}, - {file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"}, - {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"}, - {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"}, - {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"}, - {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"}, - {file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"}, - {file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"}, - {file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"}, - {file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"}, - {file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"}, - {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, -] - -[[package]] -name = "openai" -version = "1.30.1" -description = "The official Python library for the openai API" -optional = false -python-versions = ">=3.7.1" -files = [ - {file = "openai-1.30.1-py3-none-any.whl", hash = "sha256:c9fb3c3545c118bbce8deb824397b9433a66d0d0ede6a96f7009c95b76de4a46"}, - {file = "openai-1.30.1.tar.gz", hash = "sha256:4f85190e577cba0b066e1950b8eb9b11d25bc7ebcc43a86b326ce1bfa564ec74"}, -] - -[package.dependencies] -anyio = ">=3.5.0,<5" -distro = ">=1.7.0,<2" -httpx = ">=0.23.0,<1" -pydantic = ">=1.9.0,<3" -sniffio = "*" -tqdm = ">4" -typing-extensions = ">=4.7,<5" - -[package.extras] -datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] - -[[package]] -name = "orjson" -version = "3.10.3" -description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" -optional = false -python-versions = ">=3.8" -files = [ - {file = "orjson-3.10.3-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9fb6c3f9f5490a3eb4ddd46fc1b6eadb0d6fc16fb3f07320149c3286a1409dd8"}, - {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:252124b198662eee80428f1af8c63f7ff077c88723fe206a25df8dc57a57b1fa"}, - {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9f3e87733823089a338ef9bbf363ef4de45e5c599a9bf50a7a9b82e86d0228da"}, - {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8334c0d87103bb9fbbe59b78129f1f40d1d1e8355bbed2ca71853af15fa4ed3"}, - {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1952c03439e4dce23482ac846e7961f9d4ec62086eb98ae76d97bd41d72644d7"}, - {file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c0403ed9c706dcd2809f1600ed18f4aae50be263bd7112e54b50e2c2bc3ebd6d"}, - {file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:382e52aa4270a037d41f325e7d1dfa395b7de0c367800b6f337d8157367bf3a7"}, - {file = "orjson-3.10.3-cp310-none-win32.whl", hash = "sha256:be2aab54313752c04f2cbaab4515291ef5af8c2256ce22abc007f89f42f49109"}, - {file = "orjson-3.10.3-cp310-none-win_amd64.whl", hash = "sha256:416b195f78ae461601893f482287cee1e3059ec49b4f99479aedf22a20b1098b"}, - {file = "orjson-3.10.3-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:73100d9abbbe730331f2242c1fc0bcb46a3ea3b4ae3348847e5a141265479700"}, - {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a12eee96e3ab828dbfcb4d5a0023aa971b27143a1d35dc214c176fdfb29b3"}, - {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:520de5e2ef0b4ae546bea25129d6c7c74edb43fc6cf5213f511a927f2b28148b"}, - {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ccaa0a401fc02e8828a5bedfd80f8cd389d24f65e5ca3954d72c6582495b4bcf"}, - {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7bc9e8bc11bac40f905640acd41cbeaa87209e7e1f57ade386da658092dc16"}, - {file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3582b34b70543a1ed6944aca75e219e1192661a63da4d039d088a09c67543b08"}, - {file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c23dfa91481de880890d17aa7b91d586a4746a4c2aa9a145bebdbaf233768d5"}, - {file = "orjson-3.10.3-cp311-none-win32.whl", hash = "sha256:1770e2a0eae728b050705206d84eda8b074b65ee835e7f85c919f5705b006c9b"}, - {file = "orjson-3.10.3-cp311-none-win_amd64.whl", hash = "sha256:93433b3c1f852660eb5abdc1f4dd0ced2be031ba30900433223b28ee0140cde5"}, - {file = "orjson-3.10.3-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a39aa73e53bec8d410875683bfa3a8edf61e5a1c7bb4014f65f81d36467ea098"}, - {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0943a96b3fa09bee1afdfccc2cb236c9c64715afa375b2af296c73d91c23eab2"}, - {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e852baafceff8da3c9defae29414cc8513a1586ad93e45f27b89a639c68e8176"}, - {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18566beb5acd76f3769c1d1a7ec06cdb81edc4d55d2765fb677e3eaa10fa99e0"}, - {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bd2218d5a3aa43060efe649ec564ebedec8ce6ae0a43654b81376216d5ebd42"}, - {file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cf20465e74c6e17a104ecf01bf8cd3b7b252565b4ccee4548f18b012ff2f8069"}, - {file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ba7f67aa7f983c4345eeda16054a4677289011a478ca947cd69c0a86ea45e534"}, - {file = "orjson-3.10.3-cp312-none-win32.whl", hash = "sha256:17e0713fc159abc261eea0f4feda611d32eabc35708b74bef6ad44f6c78d5ea0"}, - {file = "orjson-3.10.3-cp312-none-win_amd64.whl", hash = "sha256:4c895383b1ec42b017dd2c75ae8a5b862fc489006afde06f14afbdd0309b2af0"}, - {file = "orjson-3.10.3-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:be2719e5041e9fb76c8c2c06b9600fe8e8584e6980061ff88dcbc2691a16d20d"}, - {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0175a5798bdc878956099f5c54b9837cb62cfbf5d0b86ba6d77e43861bcec2"}, - {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:978be58a68ade24f1af7758626806e13cff7748a677faf95fbb298359aa1e20d"}, - {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16bda83b5c61586f6f788333d3cf3ed19015e3b9019188c56983b5a299210eb5"}, - {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ad1f26bea425041e0a1adad34630c4825a9e3adec49079b1fb6ac8d36f8b754"}, - {file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9e253498bee561fe85d6325ba55ff2ff08fb5e7184cd6a4d7754133bd19c9195"}, - {file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0a62f9968bab8a676a164263e485f30a0b748255ee2f4ae49a0224be95f4532b"}, - {file = "orjson-3.10.3-cp38-none-win32.whl", hash = "sha256:8d0b84403d287d4bfa9bf7d1dc298d5c1c5d9f444f3737929a66f2fe4fb8f134"}, - {file = "orjson-3.10.3-cp38-none-win_amd64.whl", hash = "sha256:8bc7a4df90da5d535e18157220d7915780d07198b54f4de0110eca6b6c11e290"}, - {file = "orjson-3.10.3-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9059d15c30e675a58fdcd6f95465c1522b8426e092de9fff20edebfdc15e1cb0"}, - {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d40c7f7938c9c2b934b297412c067936d0b54e4b8ab916fd1a9eb8f54c02294"}, - {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4a654ec1de8fdaae1d80d55cee65893cb06494e124681ab335218be6a0691e7"}, - {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:831c6ef73f9aa53c5f40ae8f949ff7681b38eaddb6904aab89dca4d85099cb78"}, - {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99b880d7e34542db89f48d14ddecbd26f06838b12427d5a25d71baceb5ba119d"}, - {file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2e5e176c994ce4bd434d7aafb9ecc893c15f347d3d2bbd8e7ce0b63071c52e25"}, - {file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b69a58a37dab856491bf2d3bbf259775fdce262b727f96aafbda359cb1d114d8"}, - {file = "orjson-3.10.3-cp39-none-win32.whl", hash = "sha256:b8d4d1a6868cde356f1402c8faeb50d62cee765a1f7ffcfd6de732ab0581e063"}, - {file = "orjson-3.10.3-cp39-none-win_amd64.whl", hash = "sha256:5102f50c5fc46d94f2033fe00d392588564378260d64377aec702f21a7a22912"}, - {file = "orjson-3.10.3.tar.gz", hash = "sha256:2b166507acae7ba2f7c315dcf185a9111ad5e992ac81f2d507aac39193c2c818"}, -] - -[[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.5.0" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, - {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - -[[package]] -name = "pydantic" -version = "1.10.15" -description = "Data validation and settings management using python type hints" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pydantic-1.10.15-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:22ed12ee588b1df028a2aa5d66f07bf8f8b4c8579c2e96d5a9c1f96b77f3bb55"}, - {file = "pydantic-1.10.15-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:75279d3cac98186b6ebc2597b06bcbc7244744f6b0b44a23e4ef01e5683cc0d2"}, - {file = "pydantic-1.10.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50f1666a9940d3d68683c9d96e39640f709d7a72ff8702987dab1761036206bb"}, - {file = "pydantic-1.10.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82790d4753ee5d00739d6cb5cf56bceb186d9d6ce134aca3ba7befb1eedbc2c8"}, - {file = "pydantic-1.10.15-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:d207d5b87f6cbefbdb1198154292faee8017d7495a54ae58db06762004500d00"}, - {file = "pydantic-1.10.15-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e49db944fad339b2ccb80128ffd3f8af076f9f287197a480bf1e4ca053a866f0"}, - {file = "pydantic-1.10.15-cp310-cp310-win_amd64.whl", hash = "sha256:d3b5c4cbd0c9cb61bbbb19ce335e1f8ab87a811f6d589ed52b0254cf585d709c"}, - {file = "pydantic-1.10.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c3d5731a120752248844676bf92f25a12f6e45425e63ce22e0849297a093b5b0"}, - {file = "pydantic-1.10.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c365ad9c394f9eeffcb30a82f4246c0006417f03a7c0f8315d6211f25f7cb654"}, - {file = "pydantic-1.10.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3287e1614393119c67bd4404f46e33ae3be3ed4cd10360b48d0a4459f420c6a3"}, - {file = "pydantic-1.10.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be51dd2c8596b25fe43c0a4a59c2bee4f18d88efb8031188f9e7ddc6b469cf44"}, - {file = "pydantic-1.10.15-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6a51a1dd4aa7b3f1317f65493a182d3cff708385327c1c82c81e4a9d6d65b2e4"}, - {file = "pydantic-1.10.15-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4e316e54b5775d1eb59187f9290aeb38acf620e10f7fd2f776d97bb788199e53"}, - {file = "pydantic-1.10.15-cp311-cp311-win_amd64.whl", hash = "sha256:0d142fa1b8f2f0ae11ddd5e3e317dcac060b951d605fda26ca9b234b92214986"}, - {file = "pydantic-1.10.15-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7ea210336b891f5ea334f8fc9f8f862b87acd5d4a0cbc9e3e208e7aa1775dabf"}, - {file = "pydantic-1.10.15-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3453685ccd7140715e05f2193d64030101eaad26076fad4e246c1cc97e1bb30d"}, - {file = "pydantic-1.10.15-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bea1f03b8d4e8e86702c918ccfd5d947ac268f0f0cc6ed71782e4b09353b26f"}, - {file = "pydantic-1.10.15-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:005655cabc29081de8243126e036f2065bd7ea5b9dff95fde6d2c642d39755de"}, - {file = "pydantic-1.10.15-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:af9850d98fc21e5bc24ea9e35dd80a29faf6462c608728a110c0a30b595e58b7"}, - {file = "pydantic-1.10.15-cp37-cp37m-win_amd64.whl", hash = "sha256:d31ee5b14a82c9afe2bd26aaa405293d4237d0591527d9129ce36e58f19f95c1"}, - {file = "pydantic-1.10.15-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5e09c19df304b8123938dc3c53d3d3be6ec74b9d7d0d80f4f4b5432ae16c2022"}, - {file = "pydantic-1.10.15-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7ac9237cd62947db00a0d16acf2f3e00d1ae9d3bd602b9c415f93e7a9fc10528"}, - {file = "pydantic-1.10.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:584f2d4c98ffec420e02305cf675857bae03c9d617fcfdc34946b1160213a948"}, - {file = "pydantic-1.10.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbc6989fad0c030bd70a0b6f626f98a862224bc2b1e36bfc531ea2facc0a340c"}, - {file = "pydantic-1.10.15-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d573082c6ef99336f2cb5b667b781d2f776d4af311574fb53d908517ba523c22"}, - {file = "pydantic-1.10.15-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6bd7030c9abc80134087d8b6e7aa957e43d35714daa116aced57269a445b8f7b"}, - {file = "pydantic-1.10.15-cp38-cp38-win_amd64.whl", hash = "sha256:3350f527bb04138f8aff932dc828f154847fbdc7a1a44c240fbfff1b57f49a12"}, - {file = "pydantic-1.10.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:51d405b42f1b86703555797270e4970a9f9bd7953f3990142e69d1037f9d9e51"}, - {file = "pydantic-1.10.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a980a77c52723b0dc56640ced396b73a024d4b74f02bcb2d21dbbac1debbe9d0"}, - {file = "pydantic-1.10.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67f1a1fb467d3f49e1708a3f632b11c69fccb4e748a325d5a491ddc7b5d22383"}, - {file = "pydantic-1.10.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:676ed48f2c5bbad835f1a8ed8a6d44c1cd5a21121116d2ac40bd1cd3619746ed"}, - {file = "pydantic-1.10.15-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:92229f73400b80c13afcd050687f4d7e88de9234d74b27e6728aa689abcf58cc"}, - {file = "pydantic-1.10.15-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2746189100c646682eff0bce95efa7d2e203420d8e1c613dc0c6b4c1d9c1fde4"}, - {file = "pydantic-1.10.15-cp39-cp39-win_amd64.whl", hash = "sha256:394f08750bd8eaad714718812e7fab615f873b3cdd0b9d84e76e51ef3b50b6b7"}, - {file = "pydantic-1.10.15-py3-none-any.whl", hash = "sha256:28e552a060ba2740d0d2aabe35162652c1459a0b9069fe0db7f4ee0e18e74d58"}, - {file = "pydantic-1.10.15.tar.gz", hash = "sha256:ca832e124eda231a60a041da4f013e3ff24949d94a01154b137fc2f2a43c3ffb"}, -] - -[package.dependencies] -typing-extensions = ">=4.2.0" - -[package.extras] -dotenv = ["python-dotenv (>=0.10.4)"] -email = ["email-validator (>=1.0.3)"] - -[[package]] -name = "pydantic" -version = "2.7.4" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pydantic-2.7.4-py3-none-any.whl", hash = "sha256:ee8538d41ccb9c0a9ad3e0e5f07bf15ed8015b481ced539a1759d8cc89ae90d0"}, - {file = "pydantic-2.7.4.tar.gz", hash = "sha256:0c84efd9548d545f63ac0060c1e4d39bb9b14db8b3c0652338aecc07b5adec52"}, -] - -[package.dependencies] -annotated-types = ">=0.4.0" -pydantic-core = "2.18.4" -typing-extensions = ">=4.6.1" - -[package.extras] -email = ["email-validator (>=2.0.0)"] - -[[package]] -name = "pydantic-core" -version = "2.18.4" -description = "Core functionality for Pydantic validation and serialization" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pydantic_core-2.18.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:f76d0ad001edd426b92233d45c746fd08f467d56100fd8f30e9ace4b005266e4"}, - {file = "pydantic_core-2.18.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:59ff3e89f4eaf14050c8022011862df275b552caef8082e37b542b066ce1ff26"}, - {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a55b5b16c839df1070bc113c1f7f94a0af4433fcfa1b41799ce7606e5c79ce0a"}, - {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4d0dcc59664fcb8974b356fe0a18a672d6d7cf9f54746c05f43275fc48636851"}, - {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8951eee36c57cd128f779e641e21eb40bc5073eb28b2d23f33eb0ef14ffb3f5d"}, - {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4701b19f7e3a06ea655513f7938de6f108123bf7c86bbebb1196eb9bd35cf724"}, - {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e00a3f196329e08e43d99b79b286d60ce46bed10f2280d25a1718399457e06be"}, - {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:97736815b9cc893b2b7f663628e63f436018b75f44854c8027040e05230eeddb"}, - {file = "pydantic_core-2.18.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6891a2ae0e8692679c07728819b6e2b822fb30ca7445f67bbf6509b25a96332c"}, - {file = "pydantic_core-2.18.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bc4ff9805858bd54d1a20efff925ccd89c9d2e7cf4986144b30802bf78091c3e"}, - {file = "pydantic_core-2.18.4-cp310-none-win32.whl", hash = "sha256:1b4de2e51bbcb61fdebd0ab86ef28062704f62c82bbf4addc4e37fa4b00b7cbc"}, - {file = "pydantic_core-2.18.4-cp310-none-win_amd64.whl", hash = "sha256:6a750aec7bf431517a9fd78cb93c97b9b0c496090fee84a47a0d23668976b4b0"}, - {file = "pydantic_core-2.18.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:942ba11e7dfb66dc70f9ae66b33452f51ac7bb90676da39a7345e99ffb55402d"}, - {file = "pydantic_core-2.18.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b2ebef0e0b4454320274f5e83a41844c63438fdc874ea40a8b5b4ecb7693f1c4"}, - {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a642295cd0c8df1b86fc3dced1d067874c353a188dc8e0f744626d49e9aa51c4"}, - {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f09baa656c904807e832cf9cce799c6460c450c4ad80803517032da0cd062e2"}, - {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:98906207f29bc2c459ff64fa007afd10a8c8ac080f7e4d5beff4c97086a3dabd"}, - {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19894b95aacfa98e7cb093cd7881a0c76f55731efad31073db4521e2b6ff5b7d"}, - {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fbbdc827fe5e42e4d196c746b890b3d72876bdbf160b0eafe9f0334525119c8"}, - {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f85d05aa0918283cf29a30b547b4df2fbb56b45b135f9e35b6807cb28bc47951"}, - {file = "pydantic_core-2.18.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e85637bc8fe81ddb73fda9e56bab24560bdddfa98aa64f87aaa4e4b6730c23d2"}, - {file = "pydantic_core-2.18.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2f5966897e5461f818e136b8451d0551a2e77259eb0f73a837027b47dc95dab9"}, - {file = "pydantic_core-2.18.4-cp311-none-win32.whl", hash = "sha256:44c7486a4228413c317952e9d89598bcdfb06399735e49e0f8df643e1ccd0558"}, - {file = "pydantic_core-2.18.4-cp311-none-win_amd64.whl", hash = "sha256:8a7164fe2005d03c64fd3b85649891cd4953a8de53107940bf272500ba8a788b"}, - {file = "pydantic_core-2.18.4-cp311-none-win_arm64.whl", hash = "sha256:4e99bc050fe65c450344421017f98298a97cefc18c53bb2f7b3531eb39bc7805"}, - {file = "pydantic_core-2.18.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:6f5c4d41b2771c730ea1c34e458e781b18cc668d194958e0112455fff4e402b2"}, - {file = "pydantic_core-2.18.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2fdf2156aa3d017fddf8aea5adfba9f777db1d6022d392b682d2a8329e087cef"}, - {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4748321b5078216070b151d5271ef3e7cc905ab170bbfd27d5c83ee3ec436695"}, - {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:847a35c4d58721c5dc3dba599878ebbdfd96784f3fb8bb2c356e123bdcd73f34"}, - {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c40d4eaad41f78e3bbda31b89edc46a3f3dc6e171bf0ecf097ff7a0ffff7cb1"}, - {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:21a5e440dbe315ab9825fcd459b8814bb92b27c974cbc23c3e8baa2b76890077"}, - {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01dd777215e2aa86dfd664daed5957704b769e726626393438f9c87690ce78c3"}, - {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4b06beb3b3f1479d32befd1f3079cc47b34fa2da62457cdf6c963393340b56e9"}, - {file = "pydantic_core-2.18.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:564d7922e4b13a16b98772441879fcdcbe82ff50daa622d681dd682175ea918c"}, - {file = "pydantic_core-2.18.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0eb2a4f660fcd8e2b1c90ad566db2b98d7f3f4717c64fe0a83e0adb39766d5b8"}, - {file = "pydantic_core-2.18.4-cp312-none-win32.whl", hash = "sha256:8b8bab4c97248095ae0c4455b5a1cd1cdd96e4e4769306ab19dda135ea4cdb07"}, - {file = "pydantic_core-2.18.4-cp312-none-win_amd64.whl", hash = "sha256:14601cdb733d741b8958224030e2bfe21a4a881fb3dd6fbb21f071cabd48fa0a"}, - {file = "pydantic_core-2.18.4-cp312-none-win_arm64.whl", hash = "sha256:c1322d7dd74713dcc157a2b7898a564ab091ca6c58302d5c7b4c07296e3fd00f"}, - {file = "pydantic_core-2.18.4-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:823be1deb01793da05ecb0484d6c9e20baebb39bd42b5d72636ae9cf8350dbd2"}, - {file = "pydantic_core-2.18.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ebef0dd9bf9b812bf75bda96743f2a6c5734a02092ae7f721c048d156d5fabae"}, - {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae1d6df168efb88d7d522664693607b80b4080be6750c913eefb77e34c12c71a"}, - {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f9899c94762343f2cc2fc64c13e7cae4c3cc65cdfc87dd810a31654c9b7358cc"}, - {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99457f184ad90235cfe8461c4d70ab7dd2680e28821c29eca00252ba90308c78"}, - {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18f469a3d2a2fdafe99296a87e8a4c37748b5080a26b806a707f25a902c040a8"}, - {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7cdf28938ac6b8b49ae5e92f2735056a7ba99c9b110a474473fd71185c1af5d"}, - {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:938cb21650855054dc54dfd9120a851c974f95450f00683399006aa6e8abb057"}, - {file = "pydantic_core-2.18.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:44cd83ab6a51da80fb5adbd9560e26018e2ac7826f9626bc06ca3dc074cd198b"}, - {file = "pydantic_core-2.18.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:972658f4a72d02b8abfa2581d92d59f59897d2e9f7e708fdabe922f9087773af"}, - {file = "pydantic_core-2.18.4-cp38-none-win32.whl", hash = "sha256:1d886dc848e60cb7666f771e406acae54ab279b9f1e4143babc9c2258213daa2"}, - {file = "pydantic_core-2.18.4-cp38-none-win_amd64.whl", hash = "sha256:bb4462bd43c2460774914b8525f79b00f8f407c945d50881568f294c1d9b4443"}, - {file = "pydantic_core-2.18.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:44a688331d4a4e2129140a8118479443bd6f1905231138971372fcde37e43528"}, - {file = "pydantic_core-2.18.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a2fdd81edd64342c85ac7cf2753ccae0b79bf2dfa063785503cb85a7d3593223"}, - {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:86110d7e1907ab36691f80b33eb2da87d780f4739ae773e5fc83fb272f88825f"}, - {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:46387e38bd641b3ee5ce247563b60c5ca098da9c56c75c157a05eaa0933ed154"}, - {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:123c3cec203e3f5ac7b000bd82235f1a3eced8665b63d18be751f115588fea30"}, - {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dc1803ac5c32ec324c5261c7209e8f8ce88e83254c4e1aebdc8b0a39f9ddb443"}, - {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53db086f9f6ab2b4061958d9c276d1dbe3690e8dd727d6abf2321d6cce37fa94"}, - {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:abc267fa9837245cc28ea6929f19fa335f3dc330a35d2e45509b6566dc18be23"}, - {file = "pydantic_core-2.18.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a0d829524aaefdebccb869eed855e2d04c21d2d7479b6cada7ace5448416597b"}, - {file = "pydantic_core-2.18.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:509daade3b8649f80d4e5ff21aa5673e4ebe58590b25fe42fac5f0f52c6f034a"}, - {file = "pydantic_core-2.18.4-cp39-none-win32.whl", hash = "sha256:ca26a1e73c48cfc54c4a76ff78df3727b9d9f4ccc8dbee4ae3f73306a591676d"}, - {file = "pydantic_core-2.18.4-cp39-none-win_amd64.whl", hash = "sha256:c67598100338d5d985db1b3d21f3619ef392e185e71b8d52bceacc4a7771ea7e"}, - {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:574d92eac874f7f4db0ca653514d823a0d22e2354359d0759e3f6a406db5d55d"}, - {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1f4d26ceb5eb9eed4af91bebeae4b06c3fb28966ca3a8fb765208cf6b51102ab"}, - {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77450e6d20016ec41f43ca4a6c63e9fdde03f0ae3fe90e7c27bdbeaece8b1ed4"}, - {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d323a01da91851a4f17bf592faf46149c9169d68430b3146dcba2bb5e5719abc"}, - {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43d447dd2ae072a0065389092a231283f62d960030ecd27565672bd40746c507"}, - {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:578e24f761f3b425834f297b9935e1ce2e30f51400964ce4801002435a1b41ef"}, - {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:81b5efb2f126454586d0f40c4d834010979cb80785173d1586df845a632e4e6d"}, - {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ab86ce7c8f9bea87b9d12c7f0af71102acbf5ecbc66c17796cff45dae54ef9a5"}, - {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:90afc12421df2b1b4dcc975f814e21bc1754640d502a2fbcc6d41e77af5ec312"}, - {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:51991a89639a912c17bef4b45c87bd83593aee0437d8102556af4885811d59f5"}, - {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:293afe532740370aba8c060882f7d26cfd00c94cae32fd2e212a3a6e3b7bc15e"}, - {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b48ece5bde2e768197a2d0f6e925f9d7e3e826f0ad2271120f8144a9db18d5c8"}, - {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:eae237477a873ab46e8dd748e515c72c0c804fb380fbe6c85533c7de51f23a8f"}, - {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:834b5230b5dfc0c1ec37b2fda433b271cbbc0e507560b5d1588e2cc1148cf1ce"}, - {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e858ac0a25074ba4bce653f9b5d0a85b7456eaddadc0ce82d3878c22489fa4ee"}, - {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2fd41f6eff4c20778d717af1cc50eca52f5afe7805ee530a4fbd0bae284f16e9"}, - {file = "pydantic_core-2.18.4.tar.gz", hash = "sha256:ec3beeada09ff865c344ff3bc2f427f5e6c26401cc6113d77e372c3fdac73864"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "pygments" -version = "2.18.0" -description = "Pygments is a syntax highlighting package written in Python." -optional = false -python-versions = ">=3.8" -files = [ - {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, - {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, -] - -[package.extras] -windows-terminal = ["colorama (>=0.4.6)"] - -[[package]] -name = "pymupdf" -version = "1.24.3" -description = "A high performance Python library for data extraction, analysis, conversion & manipulation of PDF (and other) documents." -optional = false -python-versions = ">=3.8" -files = [ - {file = "PyMuPDF-1.24.3-cp310-none-macosx_10_9_x86_64.whl", hash = "sha256:8d63d850d337c10fa49859697b9517e461b28e6d5d5a80121c72cc518eb0bae0"}, - {file = "PyMuPDF-1.24.3-cp310-none-macosx_11_0_arm64.whl", hash = "sha256:5f4a9ffabbcf8f19f6938484702e393ed6d423516f3e52c9d443162e3e42a884"}, - {file = "PyMuPDF-1.24.3-cp310-none-manylinux2014_aarch64.whl", hash = "sha256:c7dfddf19d2a8c734c5439692e87419c86f2621f1f205100355afb3bb43e5675"}, - {file = "PyMuPDF-1.24.3-cp310-none-manylinux2014_x86_64.whl", hash = "sha256:cf743d8c7f7261112153525ba7de1d954f9d563b875414814b27da35fb0df2cc"}, - {file = "PyMuPDF-1.24.3-cp310-none-win32.whl", hash = "sha256:e30e8dec04c241739e0e9cf89b8a0317e991889dbca781e30abef228009c8cbd"}, - {file = "PyMuPDF-1.24.3-cp310-none-win_amd64.whl", hash = "sha256:3ceca02b143efe6b6f159d64a2f0e0aa32d0670894149a7f7144125fe2982da2"}, - {file = "PyMuPDF-1.24.3-cp311-none-macosx_10_9_x86_64.whl", hash = "sha256:171313ee03e031437687cf856914eb61f66a5a76eddedc63048a63b69b00474b"}, - {file = "PyMuPDF-1.24.3-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:a421b332c257e70d9daed350cebefc043817ae0fd6b361734ee27f98288cc8c7"}, - {file = "PyMuPDF-1.24.3-cp311-none-manylinux2014_aarch64.whl", hash = "sha256:cc519230e352024111f065a1d32366eea4f1f1034e01515f10dbed709d9ab5ad"}, - {file = "PyMuPDF-1.24.3-cp311-none-manylinux2014_x86_64.whl", hash = "sha256:9df2d5e89810d3708fb8933dbc07505a57bfcb976a72bc559c7f0ccacc054c76"}, - {file = "PyMuPDF-1.24.3-cp311-none-win32.whl", hash = "sha256:1de61f186c8367d1647d679bf6a4a77198751b378f9b67958a3b5d59adbc8c95"}, - {file = "PyMuPDF-1.24.3-cp311-none-win_amd64.whl", hash = "sha256:28e8c6c29de2951e29f98f17752eff0e80776fca7fe7ed5c7368363dff887c6c"}, - {file = "PyMuPDF-1.24.3-cp312-none-macosx_10_9_x86_64.whl", hash = "sha256:34ab87e6d0f79eea9b632ed0401de20aff2622c95aa1a57fd17b49401c22c906"}, - {file = "PyMuPDF-1.24.3-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:ef2311861a3173072c489dc365827bb26f2c4487f969501afbbf1746478553ea"}, - {file = "PyMuPDF-1.24.3-cp312-none-manylinux2014_aarch64.whl", hash = "sha256:c4df2c50eba8fb8d8ffe63bd4099c57b562d11ed01dcf6cd922c4ea774212a34"}, - {file = "PyMuPDF-1.24.3-cp312-none-manylinux2014_x86_64.whl", hash = "sha256:401f2da8621f19bc302efa2a404c794b17982dea0e552b48ecd2c3f8d10b4707"}, - {file = "PyMuPDF-1.24.3-cp312-none-win32.whl", hash = "sha256:ce4c07355b45e95803d1221cece01be58e32d1d9daec0d1ebc075ad03640c177"}, - {file = "PyMuPDF-1.24.3-cp312-none-win_amd64.whl", hash = "sha256:4f084f735e2e2d21f2c76de1abdcb44261889ec01a2842b57e69c89502f74b7a"}, - {file = "PyMuPDF-1.24.3-cp38-none-macosx_10_9_x86_64.whl", hash = "sha256:14b2459e1a7e4dbf9ec6026e6056ccba6868bdfff1ffb346fd910108a61be095"}, - {file = "PyMuPDF-1.24.3-cp38-none-macosx_11_0_arm64.whl", hash = "sha256:f3572c2a85a12026637d485d6156b7f279a4aac7f474a341e5e06e8943ab2e0b"}, - {file = "PyMuPDF-1.24.3-cp38-none-manylinux2014_aarch64.whl", hash = "sha256:b0ceed71fa62eebd1bf8b55875cd6da7c2f09bbe2067218b68b5deb0d9feaa6e"}, - {file = "PyMuPDF-1.24.3-cp38-none-manylinux2014_x86_64.whl", hash = "sha256:e6b9100fa5194be1240b9998643ba122fcffd76149dccda3607455ccfed5fa2b"}, - {file = "PyMuPDF-1.24.3-cp38-none-win32.whl", hash = "sha256:88e52a5c6d0375d27401c08fe7f7894f19db4af31169ba6deb6b3c1453f8b6e0"}, - {file = "PyMuPDF-1.24.3-cp38-none-win_amd64.whl", hash = "sha256:45c93944a14b19da3ee9b6d648e609f3ca35b8bca5c1cd16e6addcc59e7816d9"}, - {file = "PyMuPDF-1.24.3-cp39-none-macosx_10_9_x86_64.whl", hash = "sha256:0d4b6caf5ad25b7bd654ad4d42b8b3a00683b742bc5a81b8aeface79811386d5"}, - {file = "PyMuPDF-1.24.3-cp39-none-macosx_11_0_arm64.whl", hash = "sha256:6b52ee0460db88c71a06677353a0c768a8bb17718aa313462e9847ed1bf53f87"}, - {file = "PyMuPDF-1.24.3-cp39-none-manylinux2014_aarch64.whl", hash = "sha256:06a8a3226c9ec97c5e1df8cd16ec29b5df83d04ae88e9e0f5f4e25fcc1b997a1"}, - {file = "PyMuPDF-1.24.3-cp39-none-manylinux2014_x86_64.whl", hash = "sha256:ce113303b41adb74ae30ebd98761d9bd53477573e47566f05b3b7ff1c7354675"}, - {file = "PyMuPDF-1.24.3-cp39-none-win32.whl", hash = "sha256:e4b4b2d5700c48a67da278476767488005408fac29426467b5bb437012197c0b"}, - {file = "PyMuPDF-1.24.3-cp39-none-win_amd64.whl", hash = "sha256:39acbac2854ef5b58f28c71bb19e84840771a771ec09cb33c4e66e2679c3b419"}, - {file = "PyMuPDF-1.24.3.tar.gz", hash = "sha256:af412df645fa7c15d2fc9b64edb7031477dc8597d16e278157a760adaea49551"}, -] - -[package.dependencies] -PyMuPDFb = "1.24.3" - -[[package]] -name = "pymupdfb" -version = "1.24.3" -description = "MuPDF shared libraries for PyMuPDF." -optional = false -python-versions = ">=3.8" -files = [ - {file = "PyMuPDFb-1.24.3-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:d2ccca660042896d4af479f979ec10674c5a0b3cd2d9ecb0011f08dc82380cce"}, - {file = "PyMuPDFb-1.24.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:ad51d21086a16199684a3eebcb47d9c8460fc27e7bebae77f5fe64e8c34ebf34"}, - {file = "PyMuPDFb-1.24.3-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e7aab000d707c40e3254cd60152897b90952ed9a3567584d70974292f4912ce"}, - {file = "PyMuPDFb-1.24.3-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f39588fd2b7a63e2456df42cd8925c316202e0eb77d115d9c01ba032b2c9086f"}, - {file = "PyMuPDFb-1.24.3-py3-none-win32.whl", hash = "sha256:0d606a10cb828cefc9f864bf67bc9d46e8007af55e643f022b59d378af4151a8"}, - {file = "PyMuPDFb-1.24.3-py3-none-win_amd64.whl", hash = "sha256:e88289bd4b4afe5966a028774b302f37d4b51dad5c5e6720dd04524910db6c6e"}, - {file = "PyMuPDFb-1.24.3.tar.gz", hash = "sha256:7cc5da3031d160e0f01dbb88567ddca70adc82f062a3a5b4e2dd2a57646f442c"}, -] - -[[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.2" -description = "Pytest support for asyncio" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pytest_asyncio-0.21.2-py3-none-any.whl", hash = "sha256:ab664c88bb7998f711d8039cacd4884da6430886ae8bbd4eded552ed2004f16b"}, - {file = "pytest_asyncio-0.21.2.tar.gz", hash = "sha256:d67738fc232b94b326b9d060750beb16e0074210b98dd8b58a5239fa2a154f45"}, -] - -[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.14.0" -description = "Thin-wrapper around the mock package for easier use with pytest" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"}, - {file = "pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f"}, -] - -[package.dependencies] -pytest = ">=6.2.5" - -[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_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, - {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 = "regex" -version = "2024.5.15" -description = "Alternative regular expression module, to replace re." -optional = false -python-versions = ">=3.8" -files = [ - {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a81e3cfbae20378d75185171587cbf756015ccb14840702944f014e0d93ea09f"}, - {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7b59138b219ffa8979013be7bc85bb60c6f7b7575df3d56dc1e403a438c7a3f6"}, - {file = "regex-2024.5.15-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0bd000c6e266927cb7a1bc39d55be95c4b4f65c5be53e659537537e019232b1"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eaa7ddaf517aa095fa8da0b5015c44d03da83f5bd49c87961e3c997daed0de7"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba68168daedb2c0bab7fd7e00ced5ba90aebf91024dea3c88ad5063c2a562cca"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6e8d717bca3a6e2064fc3a08df5cbe366369f4b052dcd21b7416e6d71620dca1"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1337b7dbef9b2f71121cdbf1e97e40de33ff114801263b275aafd75303bd62b5"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9ebd0a36102fcad2f03696e8af4ae682793a5d30b46c647eaf280d6cfb32796"}, - {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9efa1a32ad3a3ea112224897cdaeb6aa00381627f567179c0314f7b65d354c62"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1595f2d10dff3d805e054ebdc41c124753631b6a471b976963c7b28543cf13b0"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b802512f3e1f480f41ab5f2cfc0e2f761f08a1f41092d6718868082fc0d27143"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a0981022dccabca811e8171f913de05720590c915b033b7e601f35ce4ea7019f"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:19068a6a79cf99a19ccefa44610491e9ca02c2be3305c7760d3831d38a467a6f"}, - {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1b5269484f6126eee5e687785e83c6b60aad7663dafe842b34691157e5083e53"}, - {file = "regex-2024.5.15-cp310-cp310-win32.whl", hash = "sha256:ada150c5adfa8fbcbf321c30c751dc67d2f12f15bd183ffe4ec7cde351d945b3"}, - {file = "regex-2024.5.15-cp310-cp310-win_amd64.whl", hash = "sha256:ac394ff680fc46b97487941f5e6ae49a9f30ea41c6c6804832063f14b2a5a145"}, - {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f5b1dff3ad008dccf18e652283f5e5339d70bf8ba7c98bf848ac33db10f7bc7a"}, - {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c6a2b494a76983df8e3d3feea9b9ffdd558b247e60b92f877f93a1ff43d26656"}, - {file = "regex-2024.5.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a32b96f15c8ab2e7d27655969a23895eb799de3665fa94349f3b2fbfd547236f"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10002e86e6068d9e1c91eae8295ef690f02f913c57db120b58fdd35a6bb1af35"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ec54d5afa89c19c6dd8541a133be51ee1017a38b412b1321ccb8d6ddbeb4cf7d"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10e4ce0dca9ae7a66e6089bb29355d4432caed736acae36fef0fdd7879f0b0cb"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e507ff1e74373c4d3038195fdd2af30d297b4f0950eeda6f515ae3d84a1770f"}, - {file = "regex-2024.5.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1f059a4d795e646e1c37665b9d06062c62d0e8cc3c511fe01315973a6542e40"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0721931ad5fe0dda45d07f9820b90b2148ccdd8e45bb9e9b42a146cb4f695649"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:833616ddc75ad595dee848ad984d067f2f31be645d603e4d158bba656bbf516c"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:287eb7f54fc81546346207c533ad3c2c51a8d61075127d7f6d79aaf96cdee890"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:19dfb1c504781a136a80ecd1fff9f16dddf5bb43cec6871778c8a907a085bb3d"}, - {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:119af6e56dce35e8dfb5222573b50c89e5508d94d55713c75126b753f834de68"}, - {file = "regex-2024.5.15-cp311-cp311-win32.whl", hash = "sha256:1c1c174d6ec38d6c8a7504087358ce9213d4332f6293a94fbf5249992ba54efa"}, - {file = "regex-2024.5.15-cp311-cp311-win_amd64.whl", hash = "sha256:9e717956dcfd656f5055cc70996ee2cc82ac5149517fc8e1b60261b907740201"}, - {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:632b01153e5248c134007209b5c6348a544ce96c46005d8456de1d552455b014"}, - {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e64198f6b856d48192bf921421fdd8ad8eb35e179086e99e99f711957ffedd6e"}, - {file = "regex-2024.5.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68811ab14087b2f6e0fc0c2bae9ad689ea3584cad6917fc57be6a48bbd012c49"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8ec0c2fea1e886a19c3bee0cd19d862b3aa75dcdfb42ebe8ed30708df64687a"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d0c0c0003c10f54a591d220997dd27d953cd9ccc1a7294b40a4be5312be8797b"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2431b9e263af1953c55abbd3e2efca67ca80a3de8a0437cb58e2421f8184717a"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a605586358893b483976cffc1723fb0f83e526e8f14c6e6614e75919d9862cf"}, - {file = "regex-2024.5.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391d7f7f1e409d192dba8bcd42d3e4cf9e598f3979cdaed6ab11288da88cb9f2"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9ff11639a8d98969c863d4617595eb5425fd12f7c5ef6621a4b74b71ed8726d5"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4eee78a04e6c67e8391edd4dad3279828dd66ac4b79570ec998e2155d2e59fd5"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8fe45aa3f4aa57faabbc9cb46a93363edd6197cbc43523daea044e9ff2fea83e"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d0a3d8d6acf0c78a1fff0e210d224b821081330b8524e3e2bc5a68ef6ab5803d"}, - {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c486b4106066d502495b3025a0a7251bf37ea9540433940a23419461ab9f2a80"}, - {file = "regex-2024.5.15-cp312-cp312-win32.whl", hash = "sha256:c49e15eac7c149f3670b3e27f1f28a2c1ddeccd3a2812cba953e01be2ab9b5fe"}, - {file = "regex-2024.5.15-cp312-cp312-win_amd64.whl", hash = "sha256:673b5a6da4557b975c6c90198588181029c60793835ce02f497ea817ff647cb2"}, - {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:87e2a9c29e672fc65523fb47a90d429b70ef72b901b4e4b1bd42387caf0d6835"}, - {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c3bea0ba8b73b71b37ac833a7f3fd53825924165da6a924aec78c13032f20850"}, - {file = "regex-2024.5.15-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bfc4f82cabe54f1e7f206fd3d30fda143f84a63fe7d64a81558d6e5f2e5aaba9"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5bb9425fe881d578aeca0b2b4b3d314ec88738706f66f219c194d67179337cb"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64c65783e96e563103d641760664125e91bd85d8e49566ee560ded4da0d3e704"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf2430df4148b08fb4324b848672514b1385ae3807651f3567871f130a728cc3"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5397de3219a8b08ae9540c48f602996aa6b0b65d5a61683e233af8605c42b0f2"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:455705d34b4154a80ead722f4f185b04c4237e8e8e33f265cd0798d0e44825fa"}, - {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2b6f1b3bb6f640c1a92be3bbfbcb18657b125b99ecf141fb3310b5282c7d4ed"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:3ad070b823ca5890cab606c940522d05d3d22395d432f4aaaf9d5b1653e47ced"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5b5467acbfc153847d5adb21e21e29847bcb5870e65c94c9206d20eb4e99a384"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:e6662686aeb633ad65be2a42b4cb00178b3fbf7b91878f9446075c404ada552f"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:2b4c884767504c0e2401babe8b5b7aea9148680d2e157fa28f01529d1f7fcf67"}, - {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3cd7874d57f13bf70078f1ff02b8b0aa48d5b9ed25fc48547516c6aba36f5741"}, - {file = "regex-2024.5.15-cp38-cp38-win32.whl", hash = "sha256:e4682f5ba31f475d58884045c1a97a860a007d44938c4c0895f41d64481edbc9"}, - {file = "regex-2024.5.15-cp38-cp38-win_amd64.whl", hash = "sha256:d99ceffa25ac45d150e30bd9ed14ec6039f2aad0ffa6bb87a5936f5782fc1569"}, - {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13cdaf31bed30a1e1c2453ef6015aa0983e1366fad2667657dbcac7b02f67133"}, - {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cac27dcaa821ca271855a32188aa61d12decb6fe45ffe3e722401fe61e323cd1"}, - {file = "regex-2024.5.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7dbe2467273b875ea2de38ded4eba86cbcbc9a1a6d0aa11dcf7bd2e67859c435"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64f18a9a3513a99c4bef0e3efd4c4a5b11228b48aa80743be822b71e132ae4f5"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d347a741ea871c2e278fde6c48f85136c96b8659b632fb57a7d1ce1872547600"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1878b8301ed011704aea4c806a3cadbd76f84dece1ec09cc9e4dc934cfa5d4da"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4babf07ad476aaf7830d77000874d7611704a7fcf68c9c2ad151f5d94ae4bfc4"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35cb514e137cb3488bce23352af3e12fb0dbedd1ee6e60da053c69fb1b29cc6c"}, - {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cdd09d47c0b2efee9378679f8510ee6955d329424c659ab3c5e3a6edea696294"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:72d7a99cd6b8f958e85fc6ca5b37c4303294954eac1376535b03c2a43eb72629"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a094801d379ab20c2135529948cb84d417a2169b9bdceda2a36f5f10977ebc16"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c0c18345010870e58238790a6779a1219b4d97bd2e77e1140e8ee5d14df071aa"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:16093f563098448ff6b1fa68170e4acbef94e6b6a4e25e10eae8598bb1694b5d"}, - {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e38a7d4e8f633a33b4c7350fbd8bad3b70bf81439ac67ac38916c4a86b465456"}, - {file = "regex-2024.5.15-cp39-cp39-win32.whl", hash = "sha256:71a455a3c584a88f654b64feccc1e25876066c4f5ef26cd6dd711308aa538694"}, - {file = "regex-2024.5.15-cp39-cp39-win_amd64.whl", hash = "sha256:cab12877a9bdafde5500206d1020a584355a97884dfd388af3699e9137bf7388"}, - {file = "regex-2024.5.15.tar.gz", hash = "sha256:d3ee02d9e5f482cc8309134a91eeaacbdd2261ba111b0fef3748eeb4913e6a2c"}, -] - -[[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 = "rich" -version = "13.7.1" -description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -optional = false -python-versions = ">=3.7.0" -files = [ - {file = "rich-13.7.1-py3-none-any.whl", hash = "sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222"}, - {file = "rich-13.7.1.tar.gz", hash = "sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432"}, -] - -[package.dependencies] -markdown-it-py = ">=2.2.0" -pygments = ">=2.13.0,<3.0.0" -typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.9\""} - -[package.extras] -jupyter = ["ipywidgets (>=7.5.1,<9)"] - -[[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 = "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.3.0" -description = "Retry code until it succeeds" -optional = false -python-versions = ">=3.8" -files = [ - {file = "tenacity-8.3.0-py3-none-any.whl", hash = "sha256:3649f6443dbc0d9b01b9d8020a9c4ec7a1ff5f6f3c6c8a036ef371f573fe9185"}, - {file = "tenacity-8.3.0.tar.gz", hash = "sha256:953d4e6ad24357bceffbc9707bc74349aca9d245f68eb65419cf0c249a1949a2"}, -] - -[package.extras] -doc = ["reno", "sphinx"] -test = ["pytest", "tornado (>=4.5)", "typeguard"] - -[[package]] -name = "tiktoken" -version = "0.7.0" -description = "tiktoken is a fast BPE tokeniser for use with OpenAI's models" -optional = false -python-versions = ">=3.8" -files = [ - {file = "tiktoken-0.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:485f3cc6aba7c6b6ce388ba634fbba656d9ee27f766216f45146beb4ac18b25f"}, - {file = "tiktoken-0.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e54be9a2cd2f6d6ffa3517b064983fb695c9a9d8aa7d574d1ef3c3f931a99225"}, - {file = "tiktoken-0.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79383a6e2c654c6040e5f8506f3750db9ddd71b550c724e673203b4f6b4b4590"}, - {file = "tiktoken-0.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d4511c52caacf3c4981d1ae2df85908bd31853f33d30b345c8b6830763f769c"}, - {file = "tiktoken-0.7.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:13c94efacdd3de9aff824a788353aa5749c0faee1fbe3816df365ea450b82311"}, - {file = "tiktoken-0.7.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8e58c7eb29d2ab35a7a8929cbeea60216a4ccdf42efa8974d8e176d50c9a3df5"}, - {file = "tiktoken-0.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:21a20c3bd1dd3e55b91c1331bf25f4af522c525e771691adbc9a69336fa7f702"}, - {file = "tiktoken-0.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:10c7674f81e6e350fcbed7c09a65bca9356eaab27fb2dac65a1e440f2bcfe30f"}, - {file = "tiktoken-0.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:084cec29713bc9d4189a937f8a35dbdfa785bd1235a34c1124fe2323821ee93f"}, - {file = "tiktoken-0.7.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:811229fde1652fedcca7c6dfe76724d0908775b353556d8a71ed74d866f73f7b"}, - {file = "tiktoken-0.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86b6e7dc2e7ad1b3757e8a24597415bafcfb454cebf9a33a01f2e6ba2e663992"}, - {file = "tiktoken-0.7.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1063c5748be36344c7e18c7913c53e2cca116764c2080177e57d62c7ad4576d1"}, - {file = "tiktoken-0.7.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:20295d21419bfcca092644f7e2f2138ff947a6eb8cfc732c09cc7d76988d4a89"}, - {file = "tiktoken-0.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:959d993749b083acc57a317cbc643fb85c014d055b2119b739487288f4e5d1cb"}, - {file = "tiktoken-0.7.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:71c55d066388c55a9c00f61d2c456a6086673ab7dec22dd739c23f77195b1908"}, - {file = "tiktoken-0.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:09ed925bccaa8043e34c519fbb2f99110bd07c6fd67714793c21ac298e449410"}, - {file = "tiktoken-0.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03c6c40ff1db0f48a7b4d2dafeae73a5607aacb472fa11f125e7baf9dce73704"}, - {file = "tiktoken-0.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d20b5c6af30e621b4aca094ee61777a44118f52d886dbe4f02b70dfe05c15350"}, - {file = "tiktoken-0.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d427614c3e074004efa2f2411e16c826f9df427d3c70a54725cae860f09e4bf4"}, - {file = "tiktoken-0.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8c46d7af7b8c6987fac9b9f61041b452afe92eb087d29c9ce54951280f899a97"}, - {file = "tiktoken-0.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:0bc603c30b9e371e7c4c7935aba02af5994a909fc3c0fe66e7004070858d3f8f"}, - {file = "tiktoken-0.7.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2398fecd38c921bcd68418675a6d155fad5f5e14c2e92fcf5fe566fa5485a858"}, - {file = "tiktoken-0.7.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8f5f6afb52fb8a7ea1c811e435e4188f2bef81b5e0f7a8635cc79b0eef0193d6"}, - {file = "tiktoken-0.7.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:861f9ee616766d736be4147abac500732b505bf7013cfaf019b85892637f235e"}, - {file = "tiktoken-0.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54031f95c6939f6b78122c0aa03a93273a96365103793a22e1793ee86da31685"}, - {file = "tiktoken-0.7.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:fffdcb319b614cf14f04d02a52e26b1d1ae14a570f90e9b55461a72672f7b13d"}, - {file = "tiktoken-0.7.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c72baaeaefa03ff9ba9688624143c858d1f6b755bb85d456d59e529e17234769"}, - {file = "tiktoken-0.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:131b8aeb043a8f112aad9f46011dced25d62629091e51d9dc1adbf4a1cc6aa98"}, - {file = "tiktoken-0.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cabc6dc77460df44ec5b879e68692c63551ae4fae7460dd4ff17181df75f1db7"}, - {file = "tiktoken-0.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8d57f29171255f74c0aeacd0651e29aa47dff6f070cb9f35ebc14c82278f3b25"}, - {file = "tiktoken-0.7.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ee92776fdbb3efa02a83f968c19d4997a55c8e9ce7be821ceee04a1d1ee149c"}, - {file = "tiktoken-0.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e215292e99cb41fbc96988ef62ea63bb0ce1e15f2c147a61acc319f8b4cbe5bf"}, - {file = "tiktoken-0.7.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8a81bac94769cab437dd3ab0b8a4bc4e0f9cf6835bcaa88de71f39af1791727a"}, - {file = "tiktoken-0.7.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d6d73ea93e91d5ca771256dfc9d1d29f5a554b83821a1dc0891987636e0ae226"}, - {file = "tiktoken-0.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:2bcb28ddf79ffa424f171dfeef9a4daff61a94c631ca6813f43967cb263b83b9"}, - {file = "tiktoken-0.7.0.tar.gz", hash = "sha256:1077266e949c24e0291f6c350433c6f0971365ece2b173a23bc3b9f9defef6b6"}, -] - -[package.dependencies] -regex = ">=2022.1.18" -requests = ">=2.26.0" - -[package.extras] -blobfile = ["blobfile (>=2)"] - -[[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 = "tqdm" -version = "4.66.4" -description = "Fast, Extensible Progress Meter" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tqdm-4.66.4-py3-none-any.whl", hash = "sha256:b75ca56b413b030bc3f00af51fd2c1a1a5eac6a0c1cca83cbb37a5c52abce644"}, - {file = "tqdm-4.66.4.tar.gz", hash = "sha256:e4d936c9de8727928f3be6079590e97d9abfe8d39a590be678eb5919ffc186bb"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[package.extras] -dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"] -notebook = ["ipywidgets (>=6)"] -slack = ["slack-sdk"] -telegram = ["requests"] - -[[package]] -name = "types-requests" -version = "2.31.0.20240406" -description = "Typing stubs for requests" -optional = false -python-versions = ">=3.8" -files = [ - {file = "types-requests-2.31.0.20240406.tar.gz", hash = "sha256:4428df33c5503945c74b3f42e82b181e86ec7b724620419a2966e2de604ce1a1"}, - {file = "types_requests-2.31.0.20240406-py3-none-any.whl", hash = "sha256:6216cdac377c6b9a040ac1c0404f7284bd13199c0e1bb235f4324627e8898cf5"}, -] - -[package.dependencies] -urllib3 = ">=2" - -[[package]] -name = "typing-extensions" -version = "4.11.0" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -files = [ - {file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"}, - {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"}, -] - -[[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)"] - -[metadata] -lock-version = "2.0" -python-versions = ">=3.8.1,<4.0" -content-hash = "65b3799471f43551c912f436d7d2511ff6375d670659b8d8044bbde0dfcc2d90" diff --git a/libs/partners/upstage/pyproject.toml b/libs/partners/upstage/pyproject.toml deleted file mode 100644 index b1bafb3d3f..0000000000 --- a/libs/partners/upstage/pyproject.toml +++ /dev/null @@ -1,104 +0,0 @@ -[tool.poetry] -name = "langchain-upstage" -version = "0.1.6" -description = "An integration package connecting Upstage 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/upstage" - -[tool.poetry.dependencies] -python = ">=3.8.1,<4.0" -langchain-core = ">=0.2.0,<0.3" -langchain-openai = "^0.1.8" -pymupdf = "^1.24.1" -requests = "^2.31.0" - -[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-openai = { path = "../openai", develop = true } -langchain-core = { path = "../../core", develop = true } -docarray = "^0.32.1" -langchain-standard-tests = { path = "../../standard-tests", develop = true } - -[tool.poetry.group.codespell] -optional = true - -[tool.poetry.group.codespell.dependencies] -codespell = "^2.2.0" - -[tool.poetry.group.test_integration] -optional = true - -[tool.poetry.group.test_integration.dependencies] -# Support Python 3.8 and 3.12+. -numpy = [ - {version = "^1", python = "<3.12"}, - {version = "^1.26.0", python = ">=3.12"} -] - - -[tool.poetry.group.lint] -optional = true - -[tool.poetry.group.lint.dependencies] -ruff = "^0.1.5" - -[tool.poetry.group.typing.dependencies] -mypy = "^0.991" -types-requests = ">=2.31.0" -langchain-core = { path = "../../core", develop = true } - -[tool.poetry.group.dev] -optional = true - -[tool.poetry.group.dev.dependencies] -langchain-core = { path = "../../core", develop = true } - -[tool.ruff.lint] -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/upstage/scripts/check_imports.py b/libs/partners/upstage/scripts/check_imports.py deleted file mode 100644 index fd21a4975b..0000000000 --- a/libs/partners/upstage/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/upstage/scripts/check_pydantic.sh b/libs/partners/upstage/scripts/check_pydantic.sh deleted file mode 100755 index 06b5bb81ae..0000000000 --- a/libs/partners/upstage/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/upstage/scripts/lint_imports.sh b/libs/partners/upstage/scripts/lint_imports.sh deleted file mode 100755 index 695613c7ba..0000000000 --- a/libs/partners/upstage/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/upstage/tests/__init__.py b/libs/partners/upstage/tests/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libs/partners/upstage/tests/examples/solar.pdf b/libs/partners/upstage/tests/examples/solar.pdf deleted file mode 100644 index e5266aa483af3ba3ac8d1c989990ee9525315065..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111524 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 None: - """Test ChatUpstage wrapper handles model_name.""" - chat = ChatUpstage(model="foo") - assert chat.model_name == "foo" - chat = ChatUpstage(model_name="bar") - assert chat.model_name == "bar" - - -def test_chat_upstage_system_message() -> None: - """Test ChatOpenAI wrapper with system message.""" - chat = ChatUpstage(max_tokens=10) - system_message = SystemMessage(content="You are to chat with the user.") - human_message = HumanMessage(content="Hello") - response = chat.invoke([system_message, human_message]) - assert isinstance(response, BaseMessage) - assert isinstance(response.content, str) - - -def test_chat_upstage_llm_output_contains_model_name() -> None: - """Test llm_output contains model_name.""" - chat = ChatUpstage(max_tokens=10) - message = HumanMessage(content="Hello") - llm_result = chat.generate([[message]]) - assert llm_result.llm_output is not None - assert llm_result.llm_output["model_name"] == chat.model_name - - -def test_chat_upstage_streaming_llm_output_contains_model_name() -> None: - """Test llm_output contains model_name.""" - chat = ChatUpstage(max_tokens=10, streaming=True) - message = HumanMessage(content="Hello") - llm_result = chat.generate([[message]]) - assert llm_result.llm_output is not None - assert llm_result.llm_output["model_name"] == chat.model_name - - -def test_chat_upstage_invalid_streaming_params() -> None: - """Test that streaming correctly invokes on_llm_new_token callback.""" - with pytest.raises(ValueError): - ChatUpstage( - max_tokens=10, - streaming=True, - temperature=0, - n=5, - ) - - -def test_chat_upstage_extra_kwargs() -> None: - """Test extra kwargs to chat upstage.""" - # Check that foo is saved in extra_kwargs. - llm = ChatUpstage(foo=3, max_tokens=10) - assert llm.max_tokens == 10 - assert llm.model_kwargs == {"foo": 3} - - # Test that if extra_kwargs are provided, they are added to it. - llm = ChatUpstage(foo=3, model_kwargs={"bar": 2}) - assert llm.model_kwargs == {"foo": 3, "bar": 2} - - # Test that if provided twice it errors - with pytest.raises(ValueError): - ChatUpstage(foo=3, model_kwargs={"foo": 2}) - - # Test that if explicit param is specified in kwargs it errors - with pytest.raises(ValueError): - ChatUpstage(model_kwargs={"temperature": 0.2}) - - # Test that "model" cannot be specified in kwargs - with pytest.raises(ValueError): - ChatUpstage(model_kwargs={"model": "solar-1-mini-chat"}) - - -def test_stream() -> None: - """Test streaming tokens from OpenAI.""" - llm = ChatUpstage() - - for token in llm.stream("I'm Pickle Rick"): - assert isinstance(token.content, str) - - -async def test_astream() -> None: - """Test streaming tokens from OpenAI.""" - llm = ChatUpstage() - - async for token in llm.astream("I'm Pickle Rick"): - assert isinstance(token.content, str) - - -async def test_abatch() -> None: - """Test streaming tokens from ChatUpstage.""" - llm = ChatUpstage() - - result = await llm.abatch(["I'm Pickle Rick", "I'm not Pickle Rick"]) - for token in result: - assert isinstance(token.content, str) - - -async def test_abatch_tags() -> None: - """Test batch tokens from ChatUpstage.""" - llm = ChatUpstage() - - result = await llm.abatch( - ["I'm Pickle Rick", "I'm not Pickle Rick"], config={"tags": ["foo"]} - ) - for token in result: - assert isinstance(token.content, str) - - -def test_batch() -> None: - """Test batch tokens from ChatUpstage.""" - llm = ChatUpstage() - - result = llm.batch(["I'm Pickle Rick", "I'm not Pickle Rick"]) - for token in result: - assert isinstance(token.content, str) - - -async def test_ainvoke() -> None: - """Test invoke tokens from ChatUpstage.""" - llm = ChatUpstage() - - result = await llm.ainvoke("I'm Pickle Rick", config={"tags": ["foo"]}) - assert isinstance(result.content, str) - - -def test_invoke() -> None: - """Test invoke tokens from ChatUpstage.""" - llm = ChatUpstage() - - result = llm.invoke("I'm Pickle Rick", config=dict(tags=["foo"])) - assert isinstance(result.content, str) diff --git a/libs/partners/upstage/tests/integration_tests/test_chat_models_standard.py b/libs/partners/upstage/tests/integration_tests/test_chat_models_standard.py deleted file mode 100644 index 0d1b29ec82..0000000000 --- a/libs/partners/upstage/tests/integration_tests/test_chat_models_standard.py +++ /dev/null @@ -1,18 +0,0 @@ -"""Standard LangChain interface tests""" - -from typing import Type - -from langchain_core.language_models import BaseChatModel -from langchain_standard_tests.integration_tests import ChatModelIntegrationTests - -from langchain_upstage import ChatUpstage - - -class TestUpstageStandard(ChatModelIntegrationTests): - @property - def chat_model_class(self) -> Type[BaseChatModel]: - return ChatUpstage - - @property - def chat_model_params(self) -> dict: - return {"model": "solar-1-mini-chat"} diff --git a/libs/partners/upstage/tests/integration_tests/test_compile.py b/libs/partners/upstage/tests/integration_tests/test_compile.py deleted file mode 100644 index 33ecccdfa0..0000000000 --- a/libs/partners/upstage/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/upstage/tests/integration_tests/test_embeddings.py b/libs/partners/upstage/tests/integration_tests/test_embeddings.py deleted file mode 100644 index c8e4765d5e..0000000000 --- a/libs/partners/upstage/tests/integration_tests/test_embeddings.py +++ /dev/null @@ -1,51 +0,0 @@ -"""Test Upstage embeddings.""" - -from langchain_upstage import UpstageEmbeddings - - -def test_langchain_upstage_embed_documents() -> None: - """Test Upstage embeddings.""" - documents = ["foo bar", "bar foo"] - embedding = UpstageEmbeddings(model="solar-embedding-1-large") - output = embedding.embed_documents(documents) - assert len(output) == 2 - assert len(output[0]) > 0 - - -def test_langchain_upstage_embed_query() -> None: - """Test Upstage embeddings.""" - query = "foo bar" - embedding = UpstageEmbeddings(model="solar-embedding-1-large") - output = embedding.embed_query(query) - assert len(output) > 0 - - -async def test_langchain_upstage_aembed_documents() -> None: - """Test Upstage embeddings asynchronous.""" - documents = ["foo bar", "bar foo"] - embedding = UpstageEmbeddings(model="solar-embedding-1-large") - output = await embedding.aembed_documents(documents) - assert len(output) == 2 - assert len(output[0]) > 0 - - -async def test_langchain_upstage_aembed_query() -> None: - """Test Upstage embeddings asynchronous.""" - query = "foo bar" - embedding = UpstageEmbeddings(model="solar-embedding-1-large") - output = await embedding.aembed_query(query) - assert len(output) > 0 - - -def test_langchain_upstage_embed_documents_with_empty_list() -> None: - """Test Upstage embeddings with empty list.""" - embedding = UpstageEmbeddings(model="solar-embedding-1-large") - output = embedding.embed_documents([]) - assert len(output) == 0 - - -async def test_langchain_upstage_aembed_documents_with_empty_list() -> None: - """Test Upstage embeddings asynchronous with empty list.""" - embedding = UpstageEmbeddings(model="solar-embedding-1-large") - output = await embedding.aembed_documents([]) - assert len(output) == 0 diff --git a/libs/partners/upstage/tests/integration_tests/test_groundedness_check.py b/libs/partners/upstage/tests/integration_tests/test_groundedness_check.py deleted file mode 100644 index d4b56d795d..0000000000 --- a/libs/partners/upstage/tests/integration_tests/test_groundedness_check.py +++ /dev/null @@ -1,63 +0,0 @@ -import os - -import openai -import pytest -from langchain_core.documents import Document - -from langchain_upstage import GroundednessCheck, UpstageGroundednessCheck - - -def test_langchain_upstage_groundedness_check_deprecated() -> None: - """Test Upstage Groundedness Check.""" - tool = GroundednessCheck() - output = tool.invoke({"context": "foo bar", "answer": "bar foo"}) - - assert output in ["grounded", "notGrounded", "notSure"] - - api_key = os.environ.get("UPSTAGE_API_KEY", None) - - tool = GroundednessCheck(upstage_api_key=api_key) - output = tool.invoke({"context": "foo bar", "answer": "bar foo"}) - - assert output in ["grounded", "notGrounded", "notSure"] - - -def test_langchain_upstage_groundedness_check() -> None: - """Test Upstage Groundedness Check.""" - tool = UpstageGroundednessCheck() - output = tool.invoke({"context": "foo bar", "answer": "bar foo"}) - - assert output in ["grounded", "notGrounded", "notSure"] - - api_key = os.environ.get("UPSTAGE_API_KEY", None) - - tool = UpstageGroundednessCheck(upstage_api_key=api_key) - output = tool.invoke({"context": "foo bar", "answer": "bar foo"}) - - assert output in ["grounded", "notGrounded", "notSure"] - - -def test_langchain_upstage_groundedness_check_with_documents_input() -> None: - """Test Upstage Groundedness Check.""" - tool = UpstageGroundednessCheck() - docs = [ - Document(page_content="foo bar"), - Document(page_content="bar foo"), - ] - output = tool.invoke({"context": docs, "answer": "bar foo"}) - - assert output in ["grounded", "notGrounded", "notSure"] - - -def test_langchain_upstage_groundedness_check_fail_with_wrong_api_key() -> None: - tool = UpstageGroundednessCheck(api_key="wrong-key") - with pytest.raises(openai.AuthenticationError): - tool.invoke({"context": "foo bar", "answer": "bar foo"}) - - -async def test_langchain_upstage_groundedness_check_async() -> None: - """Test Upstage Groundedness Check asynchronous.""" - tool = UpstageGroundednessCheck() - output = await tool.ainvoke({"context": "foo bar", "answer": "bar foo"}) - - assert output in ["grounded", "notGrounded", "notSure"] diff --git a/libs/partners/upstage/tests/unit_tests/__init__.py b/libs/partners/upstage/tests/unit_tests/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libs/partners/upstage/tests/unit_tests/test_chat_models.py b/libs/partners/upstage/tests/unit_tests/test_chat_models.py deleted file mode 100644 index 0af4f4acdd..0000000000 --- a/libs/partners/upstage/tests/unit_tests/test_chat_models.py +++ /dev/null @@ -1,194 +0,0 @@ -import json -from typing import Any -from unittest.mock import AsyncMock, MagicMock, patch - -import pytest -from langchain_core.messages import ( - AIMessage, - FunctionMessage, - HumanMessage, - SystemMessage, - ToolMessage, -) -from langchain_openai.chat_models.base import ( - _convert_dict_to_message, - _convert_message_to_dict, -) - -from langchain_upstage import ChatUpstage - - -def test_initialization() -> None: - """Test chat model initialization.""" - ChatUpstage() - - -def test_upstage_model_param() -> None: - llm = ChatUpstage(model="foo") - assert llm.model_name == "foo" - llm = ChatUpstage(model_name="foo") - assert llm.model_name == "foo" - ls_params = llm._get_ls_params() - assert ls_params["ls_provider"] == "upstage" - - -def test_function_dict_to_message_function_message() -> None: - content = json.dumps({"result": "Example #1"}) - name = "test_function" - result = _convert_dict_to_message( - { - "role": "function", - "name": name, - "content": content, - } - ) - assert isinstance(result, FunctionMessage) - assert result.name == name - assert result.content == content - - -def test_convert_dict_to_message_human() -> None: - message = {"role": "user", "content": "foo"} - result = _convert_dict_to_message(message) - expected_output = HumanMessage(content="foo") - assert result == expected_output - assert _convert_message_to_dict(expected_output) == message - - -def test__convert_dict_to_message_human_with_name() -> None: - message = {"role": "user", "content": "foo", "name": "test"} - result = _convert_dict_to_message(message) - expected_output = HumanMessage(content="foo", name="test") - assert result == expected_output - assert _convert_message_to_dict(expected_output) == message - - -def test_convert_dict_to_message_ai() -> None: - message = {"role": "assistant", "content": "foo"} - result = _convert_dict_to_message(message) - expected_output = AIMessage(content="foo") - assert result == expected_output - assert _convert_message_to_dict(expected_output) == message - - -def test_convert_dict_to_message_ai_with_name() -> None: - message = {"role": "assistant", "content": "foo", "name": "test"} - result = _convert_dict_to_message(message) - expected_output = AIMessage(content="foo", name="test") - assert result == expected_output - assert _convert_message_to_dict(expected_output) == message - - -def test_convert_dict_to_message_system() -> None: - message = {"role": "system", "content": "foo"} - result = _convert_dict_to_message(message) - expected_output = SystemMessage(content="foo") - assert result == expected_output - assert _convert_message_to_dict(expected_output) == message - - -def test_convert_dict_to_message_system_with_name() -> None: - message = {"role": "system", "content": "foo", "name": "test"} - result = _convert_dict_to_message(message) - expected_output = SystemMessage(content="foo", name="test") - assert result == expected_output - assert _convert_message_to_dict(expected_output) == message - - -def test_convert_dict_to_message_tool() -> None: - message = {"role": "tool", "content": "foo", "tool_call_id": "bar"} - result = _convert_dict_to_message(message) - expected_output = ToolMessage(content="foo", tool_call_id="bar") - assert result == expected_output - assert _convert_message_to_dict(expected_output) == message - - -@pytest.fixture -def mock_completion() -> dict: - return { - "id": "chatcmpl-7fcZavknQda3SQ", - "object": "chat.completion", - "created": 1689989000, - "model": "solar-1-mini-chat", - "choices": [ - { - "index": 0, - "message": { - "role": "assistant", - "content": "Bab", - "name": "KimSolar", - }, - "finish_reason": "stop", - } - ], - } - - -def test_upstage_invoke(mock_completion: dict) -> None: - llm = ChatUpstage() - mock_client = MagicMock() - completed = False - - def mock_create(*args: Any, **kwargs: Any) -> Any: - nonlocal completed - completed = True - return mock_completion - - mock_client.create = mock_create - with patch.object( - llm, - "client", - mock_client, - ): - res = llm.invoke("bab") - assert res.content == "Bab" - assert completed - - -async def test_upstage_ainvoke(mock_completion: dict) -> None: - llm = ChatUpstage() - mock_client = AsyncMock() - completed = False - - async def mock_create(*args: Any, **kwargs: Any) -> Any: - nonlocal completed - completed = True - return mock_completion - - mock_client.create = mock_create - with patch.object( - llm, - "async_client", - mock_client, - ): - res = await llm.ainvoke("bab") - assert res.content == "Bab" - assert completed - - -def test_upstage_invoke_name(mock_completion: dict) -> None: - llm = ChatUpstage() - - mock_client = MagicMock() - mock_client.create.return_value = mock_completion - - with patch.object( - llm, - "client", - mock_client, - ): - messages = [ - HumanMessage(content="Foo", name="Zorba"), - ] - res = llm.invoke(messages) - call_args, call_kwargs = mock_client.create.call_args - assert len(call_args) == 0 # no positional args - call_messages = call_kwargs["messages"] - assert len(call_messages) == 1 - assert call_messages[0]["role"] == "user" - assert call_messages[0]["content"] == "Foo" - assert call_messages[0]["name"] == "Zorba" - - # check return type has name - assert res.content == "Bab" - assert res.name == "KimSolar" diff --git a/libs/partners/upstage/tests/unit_tests/test_chat_models_standard.py b/libs/partners/upstage/tests/unit_tests/test_chat_models_standard.py deleted file mode 100644 index 91dcb760ad..0000000000 --- a/libs/partners/upstage/tests/unit_tests/test_chat_models_standard.py +++ /dev/null @@ -1,18 +0,0 @@ -"""Standard LangChain interface tests""" - -from typing import Type - -from langchain_core.language_models import BaseChatModel -from langchain_standard_tests.unit_tests import ChatModelUnitTests - -from langchain_upstage import ChatUpstage - - -class TestUpstageStandard(ChatModelUnitTests): - @property - def chat_model_class(self) -> Type[BaseChatModel]: - return ChatUpstage - - @property - def chat_model_params(self) -> dict: - return {"model": "solar-1-mini-chat"} diff --git a/libs/partners/upstage/tests/unit_tests/test_embeddings.py b/libs/partners/upstage/tests/unit_tests/test_embeddings.py deleted file mode 100644 index 8a838a6c3b..0000000000 --- a/libs/partners/upstage/tests/unit_tests/test_embeddings.py +++ /dev/null @@ -1,32 +0,0 @@ -"""Test embedding model integration.""" - -import os - -import pytest - -from langchain_upstage import UpstageEmbeddings - -os.environ["UPSTAGE_API_KEY"] = "foo" - - -def test_initialization() -> None: - """Test embedding model initialization.""" - UpstageEmbeddings(model="solar-embedding-1-large") - - -def test_upstage_invalid_model_kwargs() -> None: - with pytest.raises(ValueError): - UpstageEmbeddings( - model="solar-embedding-1-large", model_kwargs={"model": "foo"} - ) - - -def test_upstage_invalid_model() -> None: - with pytest.raises(ValueError): - UpstageEmbeddings() - - -def test_upstage_incorrect_field() -> None: - with pytest.warns(match="not default parameter"): - llm = UpstageEmbeddings(model="solar-embedding-1-large", foo="bar") - assert llm.model_kwargs == {"foo": "bar"} diff --git a/libs/partners/upstage/tests/unit_tests/test_groundedness_check.py b/libs/partners/upstage/tests/unit_tests/test_groundedness_check.py deleted file mode 100644 index fdb0502574..0000000000 --- a/libs/partners/upstage/tests/unit_tests/test_groundedness_check.py +++ /dev/null @@ -1,12 +0,0 @@ -import os - -from langchain_upstage import UpstageGroundednessCheck - -os.environ["UPSTAGE_API_KEY"] = "foo" - - -def test_initialization() -> None: - """Test embedding model initialization.""" - UpstageGroundednessCheck() - UpstageGroundednessCheck(upstage_api_key="key") - UpstageGroundednessCheck(api_key="key") diff --git a/libs/partners/upstage/tests/unit_tests/test_imports.py b/libs/partners/upstage/tests/unit_tests/test_imports.py deleted file mode 100644 index 900826a074..0000000000 --- a/libs/partners/upstage/tests/unit_tests/test_imports.py +++ /dev/null @@ -1,14 +0,0 @@ -from langchain_upstage import __all__ - -EXPECTED_ALL = [ - "ChatUpstage", - "GroundednessCheck", - "UpstageEmbeddings", - "UpstageLayoutAnalysisLoader", - "UpstageLayoutAnalysisParser", - "UpstageGroundednessCheck", -] - - -def test_all_imports() -> None: - assert sorted(EXPECTED_ALL) == sorted(__all__) diff --git a/libs/partners/upstage/tests/unit_tests/test_layout_analysis.py b/libs/partners/upstage/tests/unit_tests/test_layout_analysis.py deleted file mode 100644 index 86c5cbb0d9..0000000000 --- a/libs/partners/upstage/tests/unit_tests/test_layout_analysis.py +++ /dev/null @@ -1,253 +0,0 @@ -import json -from pathlib import Path -from typing import Any, Dict, get_args -from unittest import TestCase -from unittest.mock import MagicMock, Mock, patch - -import requests - -from langchain_upstage import UpstageLayoutAnalysisLoader -from langchain_upstage.layout_analysis import OutputType, SplitType - -MOCK_RESPONSE_JSON: Dict[str, Any] = { - "api": "1.0", - "billed_pages": 1, - "elements": [ - { - "bounding_box": [ - {"x": 74, "y": 906}, - {"x": 148, "y": 906}, - {"x": 148, "y": 2338}, - {"x": 74, "y": 2338}, - ], - "category": "header", - "html": "
arXiv:2103.15348v2
", - "id": 0, - "page": 1, - "text": "arXiv:2103.15348v2", - }, - { - "bounding_box": [ - {"x": 654, "y": 474}, - {"x": 1912, "y": 474}, - {"x": 1912, "y": 614}, - {"x": 654, "y": 614}, - ], - "category": "paragraph", - "html": "

LayoutParser Toolkit

", - "id": 1, - "page": 1, - "text": "LayoutParser Toolkit", - }, - ], - "html": "
arXiv:2103.15348v2
" - + "

LayoutParser Toolkit

", - "mimetype": "multipart/form-data", - "model": "layout-analyzer-0.1.0", - "text": "arXiv:2103.15348v2LayoutParser Toolkit", -} - -EXAMPLE_PDF_PATH = Path(__file__).parent.parent / "examples/solar.pdf" - - -def test_initialization() -> None: - """Test layout analysis document loader initialization.""" - UpstageLayoutAnalysisLoader(file_path=EXAMPLE_PDF_PATH, api_key="bar") - - -def test_layout_analysis_param() -> None: - for output_type in get_args(OutputType): - for split in get_args(SplitType): - loader = UpstageLayoutAnalysisLoader( - file_path=EXAMPLE_PDF_PATH, - api_key="bar", - output_type=output_type, - split=split, - exclude=[], - ) - assert loader.output_type == output_type - assert loader.split == split - assert loader.api_key == "bar" - assert loader.file_path == EXAMPLE_PDF_PATH - - -@patch("requests.post") -def test_none_split_text_output(mock_post: Mock) -> None: - mock_post.return_value = MagicMock( - status_code=200, json=MagicMock(return_value=MOCK_RESPONSE_JSON) - ) - - loader = UpstageLayoutAnalysisLoader( - file_path=EXAMPLE_PDF_PATH, - output_type="text", - split="none", - api_key="valid_api_key", - exclude=[], - ) - documents = loader.load() - - assert len(documents) == 1 - assert documents[0].page_content == MOCK_RESPONSE_JSON["text"] - assert documents[0].metadata["total_pages"] == 1 - assert documents[0].metadata["type"] == "text" - assert documents[0].metadata["split"] == "none" - - -@patch("requests.post") -def test_element_split_text_output(mock_post: Mock) -> None: - mock_post.return_value = MagicMock( - status_code=200, json=MagicMock(return_value=MOCK_RESPONSE_JSON) - ) - - loader = UpstageLayoutAnalysisLoader( - file_path=EXAMPLE_PDF_PATH, - output_type="text", - split="element", - api_key="valid_api_key", - exclude=[], - ) - documents = loader.load() - - assert len(documents) == 2 - - for i, document in enumerate(documents): - assert document.page_content == MOCK_RESPONSE_JSON["elements"][i]["text"] - assert document.metadata["page"] == MOCK_RESPONSE_JSON["elements"][i]["page"] - assert document.metadata["id"] == MOCK_RESPONSE_JSON["elements"][i]["id"] - assert document.metadata["type"] == "text" - assert document.metadata["split"] == "element" - - -@patch("requests.post") -def test_page_split_text_output(mock_post: Mock) -> None: - mock_post.return_value = MagicMock( - status_code=200, json=MagicMock(return_value=MOCK_RESPONSE_JSON) - ) - - loader = UpstageLayoutAnalysisLoader( - file_path=EXAMPLE_PDF_PATH, - output_type="text", - split="page", - api_key="valid_api_key", - exclude=[], - ) - documents = loader.load() - - assert len(documents) == 1 - - for i, document in enumerate(documents): - assert document.metadata["page"] == MOCK_RESPONSE_JSON["elements"][i]["page"] - assert document.metadata["type"] == "text" - assert document.metadata["split"] == "page" - - -@patch("requests.post") -def test_none_split_html_output(mock_post: Mock) -> None: - mock_post.return_value = MagicMock( - status_code=200, json=MagicMock(return_value=MOCK_RESPONSE_JSON) - ) - - loader = UpstageLayoutAnalysisLoader( - file_path=EXAMPLE_PDF_PATH, - output_type="html", - split="none", - api_key="valid_api_key", - exclude=[], - ) - documents = loader.load() - - assert len(documents) == 1 - assert documents[0].page_content == MOCK_RESPONSE_JSON["html"] - assert documents[0].metadata["total_pages"] == 1 - assert documents[0].metadata["type"] == "html" - assert documents[0].metadata["split"] == "none" - - -@patch("requests.post") -def test_element_split_html_output(mock_post: Mock) -> None: - mock_post.return_value = MagicMock( - status_code=200, json=MagicMock(return_value=MOCK_RESPONSE_JSON) - ) - - loader = UpstageLayoutAnalysisLoader( - file_path=EXAMPLE_PDF_PATH, - output_type="html", - split="element", - api_key="valid_api_key", - exclude=[], - ) - documents = loader.load() - - assert len(documents) == 2 - - for i, document in enumerate(documents): - assert document.page_content == MOCK_RESPONSE_JSON["elements"][i]["html"] - assert document.metadata["page"] == MOCK_RESPONSE_JSON["elements"][i]["page"] - assert document.metadata["id"] == MOCK_RESPONSE_JSON["elements"][i]["id"] - assert document.metadata["type"] == "html" - assert document.metadata["split"] == "element" - - -@patch("requests.post") -def test_page_split_html_output(mock_post: Mock) -> None: - mock_post.return_value = MagicMock( - status_code=200, json=MagicMock(return_value=MOCK_RESPONSE_JSON) - ) - - loader = UpstageLayoutAnalysisLoader( - file_path=EXAMPLE_PDF_PATH, - output_type="html", - split="page", - api_key="valid_api_key", - exclude=[], - ) - documents = loader.load() - - assert len(documents) == 1 - - for i, document in enumerate(documents): - assert document.metadata["page"] == MOCK_RESPONSE_JSON["elements"][i]["page"] - assert document.metadata["type"] == "html" - assert document.metadata["split"] == "page" - - -@patch("requests.post") -def test_request_exception(mock_post: Mock) -> None: - mock_post.side_effect = requests.RequestException("Mocked request exception") - - loader = UpstageLayoutAnalysisLoader( - file_path=EXAMPLE_PDF_PATH, - output_type="html", - split="page", - api_key="valid_api_key", - exclude=[], - ) - - with TestCase.assertRaises(TestCase(), ValueError) as context: - loader.load() - - assert "Failed to send request: Mocked request exception" == str(context.exception) - - -@patch("requests.post") -def test_json_decode_error(mock_post: Mock) -> None: - mock_response = Mock() - mock_response.status_code = 200 - mock_response.json.side_effect = json.JSONDecodeError("Expecting value", "", 0) - mock_post.return_value = mock_response - - loader = UpstageLayoutAnalysisLoader( - file_path=EXAMPLE_PDF_PATH, - output_type="html", - split="page", - api_key="valid_api_key", - exclude=[], - ) - - with TestCase.assertRaises(TestCase(), ValueError) as context: - loader.load() - - assert ( - "Failed to decode JSON response: Expecting value: line 1 column 1 (char 0)" - == str(context.exception) - ) diff --git a/libs/partners/upstage/tests/unit_tests/test_secrets.py b/libs/partners/upstage/tests/unit_tests/test_secrets.py deleted file mode 100644 index 5a023cfeb9..0000000000 --- a/libs/partners/upstage/tests/unit_tests/test_secrets.py +++ /dev/null @@ -1,13 +0,0 @@ -from langchain_upstage import ChatUpstage, UpstageEmbeddings - - -def test_chat_upstage_secrets() -> None: - o = ChatUpstage(upstage_api_key="foo") - s = str(o) - assert "foo" not in s - - -def test_upstage_embeddings_secrets() -> None: - o = UpstageEmbeddings(model="solar-embedding-1-large", upstage_api_key="foo") - s = str(o) - assert "foo" not in s