From 33a88cb47d3826cb4c023f80b0486ca6ae5ffbb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pstr=C4=85g?= Date: Thu, 17 Oct 2024 08:28:53 +0000 Subject: [PATCH 1/2] chore: move examples to the root folder (#114) --- .../examples => examples/apps}/documents_chat.py | 0 .../examples/llm_example.py => examples/core/llm.py | 0 .../examples/prompt_example.py => examples/core/prompt.py | 0 .../simple_text.py => examples/document-search/basic.py | 0 .../chromadb_example.py => examples/document-search/chroma.py | 0 .../document-search/from_config.py | 0 scripts/create_ragbits_package.py | 3 --- 7 files changed, 3 deletions(-) rename {packages/ragbits-document-search/examples => examples/apps}/documents_chat.py (100%) rename packages/ragbits-core/examples/llm_example.py => examples/core/llm.py (100%) rename packages/ragbits-core/examples/prompt_example.py => examples/core/prompt.py (100%) rename packages/ragbits-document-search/examples/simple_text.py => examples/document-search/basic.py (100%) rename packages/ragbits-core/examples/chromadb_example.py => examples/document-search/chroma.py (100%) rename packages/ragbits-document-search/examples/from_config_example.py => examples/document-search/from_config.py (100%) diff --git a/packages/ragbits-document-search/examples/documents_chat.py b/examples/apps/documents_chat.py similarity index 100% rename from packages/ragbits-document-search/examples/documents_chat.py rename to examples/apps/documents_chat.py diff --git a/packages/ragbits-core/examples/llm_example.py b/examples/core/llm.py similarity index 100% rename from packages/ragbits-core/examples/llm_example.py rename to examples/core/llm.py diff --git a/packages/ragbits-core/examples/prompt_example.py b/examples/core/prompt.py similarity index 100% rename from packages/ragbits-core/examples/prompt_example.py rename to examples/core/prompt.py diff --git a/packages/ragbits-document-search/examples/simple_text.py b/examples/document-search/basic.py similarity index 100% rename from packages/ragbits-document-search/examples/simple_text.py rename to examples/document-search/basic.py diff --git a/packages/ragbits-core/examples/chromadb_example.py b/examples/document-search/chroma.py similarity index 100% rename from packages/ragbits-core/examples/chromadb_example.py rename to examples/document-search/chroma.py diff --git a/packages/ragbits-document-search/examples/from_config_example.py b/examples/document-search/from_config.py similarity index 100% rename from packages/ragbits-document-search/examples/from_config_example.py rename to examples/document-search/from_config.py diff --git a/scripts/create_ragbits_package.py b/scripts/create_ragbits_package.py index 56b9e0031..f17afcdc6 100644 --- a/scripts/create_ragbits_package.py +++ b/scripts/create_ragbits_package.py @@ -36,9 +36,6 @@ def run() -> None: src_dir.mkdir(exist_ok=True, parents=True) (src_dir / "__init__.py").touch() - examples_dir = package_dir / "examples" - examples_dir.mkdir(exist_ok=True) - tests_dir = package_dir / "tests" tests_dir.mkdir(exist_ok=True) From bf7d2c68089afb613ffc2fa5677348d4fac0f861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pstr=C4=85g?= Date: Thu, 17 Oct 2024 08:45:02 +0000 Subject: [PATCH 2/2] feat(sources): add hf data source (#106) --- .../src/ragbits/core/utils/decorators.py | 55 ++++++ .../tests/unit/utils/test_decorators.py | 47 +++++ .../ragbits-document-search/pyproject.toml | 5 +- .../document_search/documents/document.py | 9 +- .../document_search/documents/exceptions.py | 27 +++ .../document_search/documents/sources.py | 118 ++++++++++-- .../tests/integration/test_sources.py | 45 +++++ .../tests/unit/test_gcs_source.py | 22 --- .../tests/unit/test_sources.py | 37 ++++ pyproject.toml | 2 +- uv.lock | 179 +++++++++++++++++- 11 files changed, 490 insertions(+), 56 deletions(-) create mode 100644 packages/ragbits-core/src/ragbits/core/utils/decorators.py create mode 100644 packages/ragbits-core/tests/unit/utils/test_decorators.py create mode 100644 packages/ragbits-document-search/src/ragbits/document_search/documents/exceptions.py create mode 100644 packages/ragbits-document-search/tests/integration/test_sources.py delete mode 100644 packages/ragbits-document-search/tests/unit/test_gcs_source.py create mode 100644 packages/ragbits-document-search/tests/unit/test_sources.py diff --git a/packages/ragbits-core/src/ragbits/core/utils/decorators.py b/packages/ragbits-core/src/ragbits/core/utils/decorators.py new file mode 100644 index 000000000..a585fe5ef --- /dev/null +++ b/packages/ragbits-core/src/ragbits/core/utils/decorators.py @@ -0,0 +1,55 @@ +# pylint: disable=missing-function-docstring,missing-return-doc + +import asyncio +from functools import wraps +from importlib.util import find_spec +from typing import Callable, ParamSpec, TypeVar + +_P = ParamSpec("_P") +_T = TypeVar("_T") + + +def requires_dependencies( + dependencies: str | list[str], + extras: str | None = None, +) -> Callable[[Callable[_P, _T]], Callable[_P, _T]]: + """ + Decorator to check if the dependencies are installed before running the function. + + Args: + dependencies: The dependencies to check. + extras: The extras to install. + + Returns: + The decorated function. + """ + if isinstance(dependencies, str): + dependencies = [dependencies] + + def decorator(func: Callable[_P, _T]) -> Callable[_P, _T]: + def run_check() -> None: + missing_dependencies = [dependency for dependency in dependencies if not find_spec(dependency)] + if len(missing_dependencies) > 0: + missing_deps = ", ".join(missing_dependencies) + install_cmd = ( + f"pip install 'ragbits[{extras}]'" if extras else f"pip install {' '.join(missing_dependencies)}" + ) + raise ImportError( + f"Following dependencies are missing: {missing_deps}. Please install them using `{install_cmd}`." + ) + + @wraps(func) + def wrapper(*args: _P.args, **kwargs: _P.kwargs) -> _T: + run_check() + return func(*args, **kwargs) + + @wraps(func) + async def wrapper_async(*args: _P.args, **kwargs: _P.kwargs) -> _T: + run_check() + return await func(*args, **kwargs) # type: ignore + + if asyncio.iscoroutinefunction(func): + return wrapper_async # type: ignore + return wrapper + + return decorator diff --git a/packages/ragbits-core/tests/unit/utils/test_decorators.py b/packages/ragbits-core/tests/unit/utils/test_decorators.py new file mode 100644 index 000000000..49752e3d4 --- /dev/null +++ b/packages/ragbits-core/tests/unit/utils/test_decorators.py @@ -0,0 +1,47 @@ +import pytest + +from ragbits.core.utils.decorators import requires_dependencies + + +def test_single_dependency_installed() -> None: + @requires_dependencies("pytest") + def some_function() -> str: + return "success" + + assert some_function() == "success" + + +def test_single_dependency_missing() -> None: + @requires_dependencies("nonexistent_dependency") + def some_function() -> str: + return "success" + + with pytest.raises(ImportError) as exc: + some_function() + + assert ( + str(exc.value) + == "Following dependencies are missing: nonexistent_dependency. Please install them using `pip install nonexistent_dependency`." + ) + + +def test_multiple_dependencies_installed() -> None: + @requires_dependencies(["pytest", "asyncio"]) + def some_function() -> str: + return "success" + + assert some_function() == "success" + + +def test_multiple_dependencies_some_missing() -> None: + @requires_dependencies(["pytest", "nonexistent_dependency"]) + def some_function() -> str: + return "success" + + with pytest.raises(ImportError) as exc: + some_function() + + assert ( + str(exc.value) + == "Following dependencies are missing: nonexistent_dependency. Please install them using `pip install nonexistent_dependency`." + ) diff --git a/packages/ragbits-document-search/pyproject.toml b/packages/ragbits-document-search/pyproject.toml index 996e6baf7..ecd0063a6 100644 --- a/packages/ragbits-document-search/pyproject.toml +++ b/packages/ragbits-document-search/pyproject.toml @@ -34,13 +34,16 @@ dependencies = [ "numpy~=1.24.0", "unstructured>=0.15.13", "unstructured-client>=0.26.0", - "ragbits-core==0.1.0" + "ragbits-core==0.1.0", ] [project.optional-dependencies] gcs = [ "gcloud-aio-storage~=9.3.0" ] +huggingface = [ + "datasets~=3.0.1", +] [tool.uv] dev-dependencies = [ diff --git a/packages/ragbits-document-search/src/ragbits/document_search/documents/document.py b/packages/ragbits-document-search/src/ragbits/document_search/documents/document.py index 0d43df918..581f33006 100644 --- a/packages/ragbits-document-search/src/ragbits/document_search/documents/document.py +++ b/packages/ragbits-document-search/src/ragbits/document_search/documents/document.py @@ -1,11 +1,10 @@ import tempfile from enum import Enum from pathlib import Path -from typing import Union from pydantic import BaseModel, Field -from ragbits.document_search.documents.sources import GCSSource, LocalFileSource +from ragbits.document_search.documents.sources import GCSSource, HuggingFaceSource, LocalFileSource class DocumentType(str, Enum): @@ -39,7 +38,7 @@ class DocumentMeta(BaseModel): """ document_type: DocumentType - source: Union[LocalFileSource, GCSSource] = Field(..., discriminator="source_type") + source: LocalFileSource | GCSSource | HuggingFaceSource = Field(..., discriminator="source_type") @property def id(self) -> str: @@ -49,7 +48,7 @@ def id(self) -> str: Returns: The document ID. """ - return self.source.get_id() + return self.source.id async def fetch(self) -> "Document": """ @@ -98,7 +97,7 @@ def from_local_path(cls, local_path: Path) -> "DocumentMeta": ) @classmethod - async def from_source(cls, source: Union[LocalFileSource, GCSSource]) -> "DocumentMeta": + async def from_source(cls, source: LocalFileSource | GCSSource | HuggingFaceSource) -> "DocumentMeta": """ Create a document metadata from a source. diff --git a/packages/ragbits-document-search/src/ragbits/document_search/documents/exceptions.py b/packages/ragbits-document-search/src/ragbits/document_search/documents/exceptions.py new file mode 100644 index 000000000..9a41e5fd5 --- /dev/null +++ b/packages/ragbits-document-search/src/ragbits/document_search/documents/exceptions.py @@ -0,0 +1,27 @@ +class SourceError(Exception): + """ + Class for all exceptions raised by the document source. + """ + + def __init__(self, message: str) -> None: + super().__init__(message) + self.message = message + + +class SourceConnectionError(SourceError): + """ + Raised when there is an error connecting to the document source. + """ + + def __init__(self) -> None: + super().__init__("Connection error.") + + +class SourceNotFoundError(SourceError): + """ + Raised when the document is not found. + """ + + def __init__(self, source_id: str) -> None: + super().__init__(f"Source with ID {source_id} not found.") + self.source_id = source_id diff --git a/packages/ragbits-document-search/src/ragbits/document_search/documents/sources.py b/packages/ragbits-document-search/src/ragbits/document_search/documents/sources.py index fc5a93a83..8d254d2d5 100644 --- a/packages/ragbits-document-search/src/ragbits/document_search/documents/sources.py +++ b/packages/ragbits-document-search/src/ragbits/document_search/documents/sources.py @@ -7,13 +7,16 @@ from pydantic import BaseModel try: + from datasets import load_dataset + from datasets.exceptions import DatasetNotFoundError from gcloud.aio.storage import Storage - - HAS_GCLOUD_AIO = True except ImportError: - HAS_GCLOUD_AIO = False + pass + +from ragbits.core.utils.decorators import requires_dependencies +from ragbits.document_search.documents.exceptions import SourceConnectionError, SourceNotFoundError -LOCAL_STORAGE_DIR_ENV = "LOCAL_STORAGE_DIR_ENV" +LOCAL_STORAGE_DIR_ENV = "LOCAL_STORAGE_DIR" class Source(BaseModel, ABC): @@ -21,8 +24,9 @@ class Source(BaseModel, ABC): An object representing a source. """ + @property @abstractmethod - def get_id(self) -> str: + def id(self) -> str: """ Get the source ID. @@ -48,7 +52,8 @@ class LocalFileSource(Source): source_type: Literal["local_file"] = "local_file" path: Path - def get_id(self) -> str: + @property + def id(self) -> str: """ Get unique identifier of the object in the source. @@ -63,7 +68,12 @@ async def fetch(self) -> Path: Returns: The local path to the object fetched from the source. + + Raises: + SourceNotFoundError: If the source document is not found. """ + if not self.path.is_file(): + raise SourceNotFoundError(source_id=self.id) return self.path @@ -73,11 +83,11 @@ class GCSSource(Source): """ source_type: Literal["gcs"] = "gcs" - bucket: str object_name: str - def get_id(self) -> str: + @property + def id(self) -> str: """ Get unique identifier of the object in the source. @@ -86,39 +96,107 @@ def get_id(self) -> str: """ return f"gcs:gs://{self.bucket}/{self.object_name}" + @requires_dependencies(["gcloud.aio.storage"], "gcs") async def fetch(self) -> Path: """ Fetch the file from Google Cloud Storage and store it locally. The file is downloaded to a local directory specified by `local_dir`. If the file already exists locally, it will not be downloaded again. If the file doesn't exist locally, it will be fetched from GCS. - The local directory is determined by the environment variable `LOCAL_STORAGE_DIR_ENV`. If this environment + The local directory is determined by the environment variable `LOCAL_STORAGE_DIR`. If this environment variable is not set, a temporary directory is used. Returns: Path: The local path to the downloaded file. Raises: - ImportError: If the required 'gcloud' package is not installed for Google Cloud Storage source. + ImportError: If the 'gcp' extra is not installed. """ - - if not HAS_GCLOUD_AIO: - raise ImportError("You need to install the 'gcloud-aio-storage' package to use Google Cloud Storage") - - if (local_dir_env := os.getenv(LOCAL_STORAGE_DIR_ENV)) is None: - local_dir = Path(tempfile.gettempdir()) / "ragbits" - else: - local_dir = Path(local_dir_env) - + local_dir = get_local_storage_dir() bucket_local_dir = local_dir / self.bucket bucket_local_dir.mkdir(parents=True, exist_ok=True) path = bucket_local_dir / self.object_name if not path.is_file(): - async with Storage() as client: + async with Storage() as client: # type: ignore + # TODO: Add error handling for download content = await client.download(self.bucket, self.object_name) Path(bucket_local_dir / self.object_name).parent.mkdir(parents=True, exist_ok=True) with open(path, mode="wb+") as file_object: file_object.write(content) return path + + +class HuggingFaceSource(Source): + """ + An object representing a Hugging Face dataset source. + """ + + source_type: Literal["huggingface"] = "huggingface" + path: str + split: str = "train" + row: int + + @property + def id(self) -> str: + """ + Get unique identifier of the object in the source. + + Returns: + Unique identifier. + """ + return f"huggingface:{self.path}/{self.split}/{self.row}" + + @requires_dependencies(["datasets"], "huggingface") + async def fetch(self) -> Path: + """ + Fetch the file from Hugging Face and store it locally. + + Returns: + Path: The local path to the downloaded file. + + Raises: + ImportError: If the 'huggingface' extra is not installed. + SourceConnectionError: If the source connection fails. + SourceNotFoundError: If the source document is not found. + """ + try: + dataset = load_dataset(self.path, split=self.split, streaming=True) # type: ignore + except ConnectionError as exc: + raise SourceConnectionError() from exc + except DatasetNotFoundError as exc: # type: ignore + raise SourceNotFoundError(source_id=self.id) from exc + + try: + data = next(iter(dataset.skip(self.row).take(1))) # type: ignore + except StopIteration as exc: + raise SourceNotFoundError(source_id=self.id) from exc + + storage_dir = get_local_storage_dir() + source_dir = storage_dir / Path(data["source"]).parent + source_dir.mkdir(parents=True, exist_ok=True) + path = storage_dir / data["source"] + + if not path.is_file(): + with open(path, mode="w", encoding="utf-8") as file: + file.write(data["content"]) + + return path + + +def get_local_storage_dir() -> Path: + """ + Get the local storage directory. + + The local storage directory is determined by the environment variable `LOCAL_STORAGE_DIR`. If this environment + variable is not set, a temporary directory is used. + + Returns: + The local storage directory. + """ + return ( + Path(local_dir_env) + if (local_dir_env := os.getenv(LOCAL_STORAGE_DIR_ENV)) is not None + else Path(tempfile.gettempdir()) / "ragbits" + ) diff --git a/packages/ragbits-document-search/tests/integration/test_sources.py b/packages/ragbits-document-search/tests/integration/test_sources.py new file mode 100644 index 000000000..f42ab8a56 --- /dev/null +++ b/packages/ragbits-document-search/tests/integration/test_sources.py @@ -0,0 +1,45 @@ +import os +from pathlib import Path + +import pytest + +from ragbits.document_search.documents.exceptions import SourceNotFoundError +from ragbits.document_search.documents.sources import LOCAL_STORAGE_DIR_ENV, HuggingFaceSource + +from ..helpers import env_vars_not_set + +os.environ[LOCAL_STORAGE_DIR_ENV] = Path(__file__).parent.as_posix() + +HF_TOKEN_ENV = "HF_TOKEN" # nosec +HF_DATASET_PATH = "micpst/hf-docs" + + +@pytest.mark.skipif( + env_vars_not_set([HF_TOKEN_ENV]), + reason="Hugging Face environment variables not set", +) +async def test_huggingface_source_fetch() -> None: + source = HuggingFaceSource(path=HF_DATASET_PATH, row=0) + path = await source.fetch() + + assert path.is_file() + assert path.name == "README.md" + assert ( + path.read_text() + == " `tokenizers-linux-x64-musl`\n\nThis is the **x86_64-unknown-linux-musl** binary for `tokenizers`\n" + ) + + path.unlink() + + +@pytest.mark.skipif( + env_vars_not_set([HF_TOKEN_ENV]), + reason="Hugging Face environment variables not set", +) +async def test_huggingface_source_fetch_not_found() -> None: + source = HuggingFaceSource(path=HF_DATASET_PATH, row=1000) + + with pytest.raises(SourceNotFoundError) as exc: + await source.fetch() + + assert str(exc.value) == "Source with ID huggingface:micpst/hf-docs/train/1000 not found." diff --git a/packages/ragbits-document-search/tests/unit/test_gcs_source.py b/packages/ragbits-document-search/tests/unit/test_gcs_source.py deleted file mode 100644 index da32b5a9f..000000000 --- a/packages/ragbits-document-search/tests/unit/test_gcs_source.py +++ /dev/null @@ -1,22 +0,0 @@ -import os -from pathlib import Path - -import aiohttp -import pytest - -from ragbits.document_search.documents.sources import GCSSource - -TEST_FILE_PATH = Path(__file__) - -os.environ["LOCAL_STORAGE_DIR_ENV"] = TEST_FILE_PATH.parent.as_posix() - - -async def test_gcs_source_fetch(): - source = GCSSource(bucket="", object_name="test_gcs_source.py") - - path = await source.fetch() - assert path == TEST_FILE_PATH - - source = GCSSource(bucket="", object_name="not_found_file.py") - with pytest.raises(aiohttp.ClientConnectionError): - await source.fetch() diff --git a/packages/ragbits-document-search/tests/unit/test_sources.py b/packages/ragbits-document-search/tests/unit/test_sources.py new file mode 100644 index 000000000..1c90df6e0 --- /dev/null +++ b/packages/ragbits-document-search/tests/unit/test_sources.py @@ -0,0 +1,37 @@ +import os +from pathlib import Path +from unittest.mock import MagicMock, patch + +from ragbits.document_search.documents.sources import LOCAL_STORAGE_DIR_ENV, GCSSource, HuggingFaceSource + +os.environ[LOCAL_STORAGE_DIR_ENV] = Path(__file__).parent.as_posix() + + +async def test_gcs_source_fetch() -> None: + data = b"This is the content of the file." + source = GCSSource(bucket="", object_name="doc.md") + + with patch("ragbits.document_search.documents.sources.Storage.download", return_value=data): + path = await source.fetch() + + assert source.id == "gcs:gs:///doc.md" + assert path.name == "doc.md" + assert path.read_text() == "This is the content of the file." + + path.unlink() + + +async def test_huggingface_source_fetch() -> None: + take = MagicMock(return_value=[{"content": "This is the content of the file.", "source": "doc.md"}]) + skip = MagicMock(return_value=MagicMock(take=take)) + data = MagicMock(skip=skip) + source = HuggingFaceSource(path="org/docs", split="train", row=1) + + with patch("ragbits.document_search.documents.sources.load_dataset", return_value=data): + path = await source.fetch() + + assert source.id == "huggingface:org/docs/train/1" + assert path.name == "doc.md" + assert path.read_text() == "This is the content of the file." + + path.unlink() diff --git a/pyproject.toml b/pyproject.toml index 60e050b53..112ea2bcf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ readme = "README.md" requires-python = ">=3.10" dependencies = [ "ragbits-core[litellm,local,lab,chromadb]", - "ragbits-document-search[gcs]", + "ragbits-document-search[gcs, huggingface]", "ragbits-cli" ] diff --git a/uv.lock b/uv.lock index 6156c1afe..cc35e00ab 100644 --- a/uv.lock +++ b/uv.lock @@ -675,6 +675,32 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c3/be/d0d44e092656fe7a06b55e6103cbce807cdbdee17884a5367c68c9860853/dataclasses_json-0.6.7-py3-none-any.whl", hash = "sha256:0dbf33f26c8d5305befd61b39d2b3414e8a407bedc2834dea9b8d642666fb40a", size = 28686 }, ] +[[package]] +name = "datasets" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohttp" }, + { name = "dill" }, + { name = "filelock" }, + { name = "fsspec", extra = ["http"] }, + { name = "huggingface-hub" }, + { name = "multiprocess" }, + { name = "numpy" }, + { name = "packaging" }, + { name = "pandas", version = "2.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, + { name = "pandas", version = "2.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, + { name = "pyarrow" }, + { name = "pyyaml" }, + { name = "requests" }, + { name = "tqdm" }, + { name = "xxhash" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3b/1b/ce839a6a127935f8e87a8d5887e7dfa76cbdbe94ee7ac04c855221ea1e0a/datasets-3.0.1.tar.gz", hash = "sha256:40d63b09e76a3066c32e746d6fdc36fd3f29ed2acd49bf5b1a2100da32936511", size = 1875319 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/be/3e/e58d4db4cfe71e3ed07d169af24db30cfd582e16f977378bd43fd7ec1998/datasets-3.0.1-py3-none-any.whl", hash = "sha256:db080aab41c8cc68645117a0f172e5c6789cbc672f066de0aa5a08fc3eebc686", size = 471557 }, +] + [[package]] name = "deprecated" version = "1.2.14" @@ -687,6 +713,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c", size = 9561 }, ] +[[package]] +name = "dill" +version = "0.3.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/17/4d/ac7ffa80c69ea1df30a8aa11b3578692a5118e7cd1aa157e3ef73b092d15/dill-0.3.8.tar.gz", hash = "sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca", size = 184847 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c9/7a/cef76fd8438a42f96db64ddaa85280485a9c395e7df3db8158cfec1eee34/dill-0.3.8-py3-none-any.whl", hash = "sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7", size = 116252 }, +] + [[package]] name = "distlib" version = "0.3.8" @@ -886,11 +921,16 @@ wheels = [ [[package]] name = "fsspec" -version = "2024.9.0" +version = "2024.6.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/62/7c/12b0943011daaaa9c35c2a2e22e5eb929ac90002f08f1259d69aedad84de/fsspec-2024.9.0.tar.gz", hash = "sha256:4b0afb90c2f21832df142f292649035d80b421f60a9e1c027802e5a0da2b04e8", size = 286206 } +sdist = { url = "https://files.pythonhosted.org/packages/90/b6/eba5024a9889fcfff396db543a34bef0ab9d002278f163129f9f01005960/fsspec-2024.6.1.tar.gz", hash = "sha256:fad7d7e209dd4c1208e3bbfda706620e0da5142bebbd9c384afb95b07e798e49", size = 284584 } wheels = [ - { url = "https://files.pythonhosted.org/packages/1d/a0/6aaea0c2fbea2f89bfd5db25fb1e3481896a423002ebe4e55288907a97a3/fsspec-2024.9.0-py3-none-any.whl", hash = "sha256:a0947d552d8a6efa72cc2c730b12c41d043509156966cca4fb157b0f2a0c574b", size = 179253 }, + { url = "https://files.pythonhosted.org/packages/5e/44/73bea497ac69bafde2ee4269292fa3b41f1198f4bb7bbaaabde30ad29d4a/fsspec-2024.6.1-py3-none-any.whl", hash = "sha256:3cb443f8bcd2efb31295a5b9fdb02aee81d8452c80d28f97a6d0959e6cee101e", size = 177561 }, +] + +[package.optional-dependencies] +http = [ + { name = "aiohttp" }, ] [[package]] @@ -1961,6 +2001,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/99/b7/b9e70fde2c0f0c9af4cc5277782a89b66d35948ea3369ec9f598358c3ac5/multidict-6.1.0-py3-none-any.whl", hash = "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506", size = 10051 }, ] +[[package]] +name = "multiprocess" +version = "0.70.16" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "dill" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b5/ae/04f39c5d0d0def03247c2893d6f2b83c136bf3320a2154d7b8858f2ba72d/multiprocess-0.70.16.tar.gz", hash = "sha256:161af703d4652a0e1410be6abccecde4a7ddffd19341be0a7011b94aeb171ac1", size = 1772603 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/76/6e712a2623d146d314f17598df5de7224c85c0060ef63fd95cc15a25b3fa/multiprocess-0.70.16-pp310-pypy310_pp73-macosx_10_13_x86_64.whl", hash = "sha256:476887be10e2f59ff183c006af746cb6f1fd0eadcfd4ef49e605cbe2659920ee", size = 134980 }, + { url = "https://files.pythonhosted.org/packages/0f/ab/1e6e8009e380e22254ff539ebe117861e5bdb3bff1fc977920972237c6c7/multiprocess-0.70.16-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d951bed82c8f73929ac82c61f01a7b5ce8f3e5ef40f5b52553b4f547ce2b08ec", size = 134982 }, + { url = "https://files.pythonhosted.org/packages/bc/f7/7ec7fddc92e50714ea3745631f79bd9c96424cb2702632521028e57d3a36/multiprocess-0.70.16-py310-none-any.whl", hash = "sha256:c4a9944c67bd49f823687463660a2d6daae94c289adff97e0f9d696ba6371d02", size = 134824 }, + { url = "https://files.pythonhosted.org/packages/50/15/b56e50e8debaf439f44befec5b2af11db85f6e0f344c3113ae0be0593a91/multiprocess-0.70.16-py311-none-any.whl", hash = "sha256:af4cabb0dac72abfb1e794fa7855c325fd2b55a10a44628a3c1ad3311c04127a", size = 143519 }, + { url = "https://files.pythonhosted.org/packages/0a/7d/a988f258104dcd2ccf1ed40fdc97e26c4ac351eeaf81d76e266c52d84e2f/multiprocess-0.70.16-py312-none-any.whl", hash = "sha256:fc0544c531920dde3b00c29863377f87e1632601092ea2daca74e4beb40faa2e", size = 146741 }, + { url = "https://files.pythonhosted.org/packages/ea/89/38df130f2c799090c978b366cfdf5b96d08de5b29a4a293df7f7429fa50b/multiprocess-0.70.16-py38-none-any.whl", hash = "sha256:a71d82033454891091a226dfc319d0cfa8019a4e888ef9ca910372a446de4435", size = 132628 }, + { url = "https://files.pythonhosted.org/packages/da/d9/f7f9379981e39b8c2511c9e0326d212accacb82f12fbfdc1aa2ce2a7b2b6/multiprocess-0.70.16-py39-none-any.whl", hash = "sha256:a0bafd3ae1b732eac64be2e72038231c1ba97724b60b09400d68f229fcc2fbf3", size = 133351 }, +] + [[package]] name = "mypy-extensions" version = "1.0.0" @@ -2660,8 +2718,6 @@ version = "6.0.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/18/c7/8c6872f7372eb6a6b2e4708b88419fb46b857f7a2e1892966b851cc79fc9/psutil-6.0.0.tar.gz", hash = "sha256:8faae4f310b6d969fa26ca0545338b21f73c6b15db7c4a8d934a5482faa818f2", size = 508067 } wheels = [ - { url = "https://files.pythonhosted.org/packages/c5/66/78c9c3020f573c58101dc43a44f6855d01bbbd747e24da2f0c4491200ea3/psutil-6.0.0-cp27-none-win32.whl", hash = "sha256:02b69001f44cc73c1c5279d02b30a817e339ceb258ad75997325e0e6169d8b35", size = 249766 }, - { url = "https://files.pythonhosted.org/packages/e1/3f/2403aa9558bea4d3854b0e5e567bc3dd8e9fbc1fc4453c0aa9aafeb75467/psutil-6.0.0-cp27-none-win_amd64.whl", hash = "sha256:21f1fb635deccd510f69f485b87433460a603919b45e2a324ad65b0cc74f8fb1", size = 253024 }, { url = "https://files.pythonhosted.org/packages/0b/37/f8da2fbd29690b3557cca414c1949f92162981920699cd62095a984983bf/psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0", size = 250961 }, { url = "https://files.pythonhosted.org/packages/35/56/72f86175e81c656a01c4401cd3b1c923f891b31fbcebe98985894176d7c9/psutil-6.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ed2440ada7ef7d0d608f20ad89a04ec47d2d3ab7190896cd62ca5fc4fe08bf0", size = 287478 }, { url = "https://files.pythonhosted.org/packages/19/74/f59e7e0d392bc1070e9a70e2f9190d652487ac115bb16e2eff6b22ad1d24/psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd", size = 290455 }, @@ -2699,6 +2755,38 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a2/51/db376181d05716de595515fac736e3d06e96d3345ba0e31c0a90c352eae1/pulsar_client-3.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:443b786eed96bc86d2297a6a42e79f39d1abf217ec603e0bd303f3488c0234af", size = 3306515 }, ] +[[package]] +name = "pyarrow" +version = "17.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/27/4e/ea6d43f324169f8aec0e57569443a38bab4b398d09769ca64f7b4d467de3/pyarrow-17.0.0.tar.gz", hash = "sha256:4beca9521ed2c0921c1023e68d097d0299b62c362639ea315572a58f3f50fd28", size = 1112479 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/39/5d/78d4b040bc5ff2fc6c3d03e80fca396b742f6c125b8af06bcf7427f931bc/pyarrow-17.0.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:a5c8b238d47e48812ee577ee20c9a2779e6a5904f1708ae240f53ecbee7c9f07", size = 28994846 }, + { url = "https://files.pythonhosted.org/packages/3b/73/8ed168db7642e91180330e4ea9f3ff8bab404678f00d32d7df0871a4933b/pyarrow-17.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:db023dc4c6cae1015de9e198d41250688383c3f9af8f565370ab2b4cb5f62655", size = 27165908 }, + { url = "https://files.pythonhosted.org/packages/81/36/e78c24be99242063f6d0590ef68c857ea07bdea470242c361e9a15bd57a4/pyarrow-17.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da1e060b3876faa11cee287839f9cc7cdc00649f475714b8680a05fd9071d545", size = 39264209 }, + { url = "https://files.pythonhosted.org/packages/18/4c/3db637d7578f683b0a8fb8999b436bdbedd6e3517bd4f90c70853cf3ad20/pyarrow-17.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75c06d4624c0ad6674364bb46ef38c3132768139ddec1c56582dbac54f2663e2", size = 39862883 }, + { url = "https://files.pythonhosted.org/packages/81/3c/0580626896c842614a523e66b351181ed5bb14e5dfc263cd68cea2c46d90/pyarrow-17.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:fa3c246cc58cb5a4a5cb407a18f193354ea47dd0648194e6265bd24177982fe8", size = 38723009 }, + { url = "https://files.pythonhosted.org/packages/ee/fb/c1b47f0ada36d856a352da261a44d7344d8f22e2f7db3945f8c3b81be5dd/pyarrow-17.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:f7ae2de664e0b158d1607699a16a488de3d008ba99b3a7aa5de1cbc13574d047", size = 39855626 }, + { url = "https://files.pythonhosted.org/packages/19/09/b0a02908180a25d57312ab5919069c39fddf30602568980419f4b02393f6/pyarrow-17.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:5984f416552eea15fd9cee03da53542bf4cddaef5afecefb9aa8d1010c335087", size = 25147242 }, + { url = "https://files.pythonhosted.org/packages/f9/46/ce89f87c2936f5bb9d879473b9663ce7a4b1f4359acc2f0eb39865eaa1af/pyarrow-17.0.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:1c8856e2ef09eb87ecf937104aacfa0708f22dfeb039c363ec99735190ffb977", size = 29028748 }, + { url = "https://files.pythonhosted.org/packages/8d/8e/ce2e9b2146de422f6638333c01903140e9ada244a2a477918a368306c64c/pyarrow-17.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2e19f569567efcbbd42084e87f948778eb371d308e137a0f97afe19bb860ccb3", size = 27190965 }, + { url = "https://files.pythonhosted.org/packages/3b/c8/5675719570eb1acd809481c6d64e2136ffb340bc387f4ca62dce79516cea/pyarrow-17.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b244dc8e08a23b3e352899a006a26ae7b4d0da7bb636872fa8f5884e70acf15", size = 39269081 }, + { url = "https://files.pythonhosted.org/packages/5e/78/3931194f16ab681ebb87ad252e7b8d2c8b23dad49706cadc865dff4a1dd3/pyarrow-17.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b72e87fe3e1db343995562f7fff8aee354b55ee83d13afba65400c178ab2597", size = 39864921 }, + { url = "https://files.pythonhosted.org/packages/d8/81/69b6606093363f55a2a574c018901c40952d4e902e670656d18213c71ad7/pyarrow-17.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:dc5c31c37409dfbc5d014047817cb4ccd8c1ea25d19576acf1a001fe07f5b420", size = 38740798 }, + { url = "https://files.pythonhosted.org/packages/4c/21/9ca93b84b92ef927814cb7ba37f0774a484c849d58f0b692b16af8eebcfb/pyarrow-17.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:e3343cb1e88bc2ea605986d4b94948716edc7a8d14afd4e2c097232f729758b4", size = 39871877 }, + { url = "https://files.pythonhosted.org/packages/30/d1/63a7c248432c71c7d3ee803e706590a0b81ce1a8d2b2ae49677774b813bb/pyarrow-17.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:a27532c38f3de9eb3e90ecab63dfda948a8ca859a66e3a47f5f42d1e403c4d03", size = 25151089 }, + { url = "https://files.pythonhosted.org/packages/d4/62/ce6ac1275a432b4a27c55fe96c58147f111d8ba1ad800a112d31859fae2f/pyarrow-17.0.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:9b8a823cea605221e61f34859dcc03207e52e409ccf6354634143e23af7c8d22", size = 29019418 }, + { url = "https://files.pythonhosted.org/packages/8e/0a/dbd0c134e7a0c30bea439675cc120012337202e5fac7163ba839aa3691d2/pyarrow-17.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f1e70de6cb5790a50b01d2b686d54aaf73da01266850b05e3af2a1bc89e16053", size = 27152197 }, + { url = "https://files.pythonhosted.org/packages/cb/05/3f4a16498349db79090767620d6dc23c1ec0c658a668d61d76b87706c65d/pyarrow-17.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0071ce35788c6f9077ff9ecba4858108eebe2ea5a3f7cf2cf55ebc1dbc6ee24a", size = 39263026 }, + { url = "https://files.pythonhosted.org/packages/c2/0c/ea2107236740be8fa0e0d4a293a095c9f43546a2465bb7df34eee9126b09/pyarrow-17.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:757074882f844411fcca735e39aae74248a1531367a7c80799b4266390ae51cc", size = 39880798 }, + { url = "https://files.pythonhosted.org/packages/f6/b0/b9164a8bc495083c10c281cc65064553ec87b7537d6f742a89d5953a2a3e/pyarrow-17.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:9ba11c4f16976e89146781a83833df7f82077cdab7dc6232c897789343f7891a", size = 38715172 }, + { url = "https://files.pythonhosted.org/packages/f1/c4/9625418a1413005e486c006e56675334929fad864347c5ae7c1b2e7fe639/pyarrow-17.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b0c6ac301093b42d34410b187bba560b17c0330f64907bfa4f7f7f2444b0cf9b", size = 39874508 }, + { url = "https://files.pythonhosted.org/packages/ae/49/baafe2a964f663413be3bd1cf5c45ed98c5e42e804e2328e18f4570027c1/pyarrow-17.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:392bc9feabc647338e6c89267635e111d71edad5fcffba204425a7c8d13610d7", size = 25099235 }, +] + [[package]] name = "pyasn1" version = "0.6.1" @@ -3167,6 +3255,9 @@ dependencies = [ gcs = [ { name = "gcloud-aio-storage" }, ] +huggingface = [ + { name = "datasets" }, +] [package.dev-dependencies] dev = [ @@ -3180,6 +3271,7 @@ dev = [ [package.metadata] requires-dist = [ + { name = "datasets", marker = "extra == 'huggingface'", specifier = "~=3.0.1" }, { name = "gcloud-aio-storage", marker = "extra == 'gcs'", specifier = "~=9.3.0" }, { name = "numpy", specifier = "~=1.24.0" }, { name = "ragbits-core", editable = "packages/ragbits-core" }, @@ -3204,7 +3296,7 @@ source = { virtual = "." } dependencies = [ { name = "ragbits-cli" }, { name = "ragbits-core", extra = ["chromadb", "lab", "litellm", "local"] }, - { name = "ragbits-document-search", extra = ["gcs"] }, + { name = "ragbits-document-search", extra = ["gcs", "huggingface"] }, ] [package.dev-dependencies] @@ -3228,7 +3320,7 @@ dev = [ requires-dist = [ { name = "ragbits-cli", editable = "packages/ragbits-cli" }, { name = "ragbits-core", extras = ["litellm", "local", "lab", "chromadb"], editable = "packages/ragbits-core" }, - { name = "ragbits-document-search", extras = ["gcs"], editable = "packages/ragbits-document-search" }, + { name = "ragbits-document-search", extras = ["gcs", "huggingface"], editable = "packages/ragbits-document-search" }, ] [package.metadata.requires-dev] @@ -4291,6 +4383,79 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ff/21/abdedb4cdf6ff41ebf01a74087740a709e2edb146490e4d9beea054b0b7a/wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1", size = 23362 }, ] +[[package]] +name = "xxhash" +version = "3.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/00/5e/d6e5258d69df8b4ed8c83b6664f2b47d30d2dec551a29ad72a6c69eafd31/xxhash-3.5.0.tar.gz", hash = "sha256:84f2caddf951c9cbf8dc2e22a89d4ccf5d86391ac6418fe81e3c67d0cf60b45f", size = 84241 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bb/8a/0e9feca390d512d293afd844d31670e25608c4a901e10202aa98785eab09/xxhash-3.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ece616532c499ee9afbb83078b1b952beffef121d989841f7f4b3dc5ac0fd212", size = 31970 }, + { url = "https://files.pythonhosted.org/packages/16/e6/be5aa49580cd064a18200ab78e29b88b1127e1a8c7955eb8ecf81f2626eb/xxhash-3.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3171f693dbc2cef6477054a665dc255d996646b4023fe56cb4db80e26f4cc520", size = 30801 }, + { url = "https://files.pythonhosted.org/packages/20/ee/b8a99ebbc6d1113b3a3f09e747fa318c3cde5b04bd9c197688fadf0eeae8/xxhash-3.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c5d3e570ef46adaf93fc81b44aca6002b5a4d8ca11bd0580c07eac537f36680", size = 220927 }, + { url = "https://files.pythonhosted.org/packages/58/62/15d10582ef159283a5c2b47f6d799fc3303fe3911d5bb0bcc820e1ef7ff4/xxhash-3.5.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7cb29a034301e2982df8b1fe6328a84f4b676106a13e9135a0d7e0c3e9f806da", size = 200360 }, + { url = "https://files.pythonhosted.org/packages/23/41/61202663ea9b1bd8e53673b8ec9e2619989353dba8cfb68e59a9cbd9ffe3/xxhash-3.5.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d0d307d27099bb0cbeea7260eb39ed4fdb99c5542e21e94bb6fd29e49c57a23", size = 428528 }, + { url = "https://files.pythonhosted.org/packages/f2/07/d9a3059f702dec5b3b703737afb6dda32f304f6e9da181a229dafd052c29/xxhash-3.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0342aafd421795d740e514bc9858ebddfc705a75a8c5046ac56d85fe97bf196", size = 194149 }, + { url = "https://files.pythonhosted.org/packages/eb/58/27caadf78226ecf1d62dbd0c01d152ed381c14c1ee4ad01f0d460fc40eac/xxhash-3.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3dbbd9892c5ebffeca1ed620cf0ade13eb55a0d8c84e0751a6653adc6ac40d0c", size = 207703 }, + { url = "https://files.pythonhosted.org/packages/b1/08/32d558ce23e1e068453c39aed7b3c1cdc690c177873ec0ca3a90d5808765/xxhash-3.5.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4cc2d67fdb4d057730c75a64c5923abfa17775ae234a71b0200346bfb0a7f482", size = 216255 }, + { url = "https://files.pythonhosted.org/packages/3f/d4/2b971e2d2b0a61045f842b622ef11e94096cf1f12cd448b6fd426e80e0e2/xxhash-3.5.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:ec28adb204b759306a3d64358a5e5c07d7b1dd0ccbce04aa76cb9377b7b70296", size = 202744 }, + { url = "https://files.pythonhosted.org/packages/19/ae/6a6438864a8c4c39915d7b65effd85392ebe22710412902487e51769146d/xxhash-3.5.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:1328f6d8cca2b86acb14104e381225a3d7b42c92c4b86ceae814e5c400dbb415", size = 210115 }, + { url = "https://files.pythonhosted.org/packages/48/7d/b3c27c27d1fc868094d02fe4498ccce8cec9fcc591825c01d6bcb0b4fc49/xxhash-3.5.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8d47ebd9f5d9607fd039c1fbf4994e3b071ea23eff42f4ecef246ab2b7334198", size = 414247 }, + { url = "https://files.pythonhosted.org/packages/a1/05/918f9e7d2fbbd334b829997045d341d6239b563c44e683b9a7ef8fe50f5d/xxhash-3.5.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b96d559e0fcddd3343c510a0fe2b127fbff16bf346dd76280b82292567523442", size = 191419 }, + { url = "https://files.pythonhosted.org/packages/08/29/dfe393805b2f86bfc47c290b275f0b7c189dc2f4e136fd4754f32eb18a8d/xxhash-3.5.0-cp310-cp310-win32.whl", hash = "sha256:61c722ed8d49ac9bc26c7071eeaa1f6ff24053d553146d5df031802deffd03da", size = 30114 }, + { url = "https://files.pythonhosted.org/packages/7b/d7/aa0b22c4ebb7c3ccb993d4c565132abc641cd11164f8952d89eb6a501909/xxhash-3.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:9bed5144c6923cc902cd14bb8963f2d5e034def4486ab0bbe1f58f03f042f9a9", size = 30003 }, + { url = "https://files.pythonhosted.org/packages/69/12/f969b81541ee91b55f1ce469d7ab55079593c80d04fd01691b550e535000/xxhash-3.5.0-cp310-cp310-win_arm64.whl", hash = "sha256:893074d651cf25c1cc14e3bea4fceefd67f2921b1bb8e40fcfeba56820de80c6", size = 26773 }, + { url = "https://files.pythonhosted.org/packages/b8/c7/afed0f131fbda960ff15eee7f304fa0eeb2d58770fade99897984852ef23/xxhash-3.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:02c2e816896dc6f85922ced60097bcf6f008dedfc5073dcba32f9c8dd786f3c1", size = 31969 }, + { url = "https://files.pythonhosted.org/packages/8c/0c/7c3bc6d87e5235672fcc2fb42fd5ad79fe1033925f71bf549ee068c7d1ca/xxhash-3.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6027dcd885e21581e46d3c7f682cfb2b870942feeed58a21c29583512c3f09f8", size = 30800 }, + { url = "https://files.pythonhosted.org/packages/04/9e/01067981d98069eec1c20201f8c145367698e9056f8bc295346e4ea32dd1/xxhash-3.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1308fa542bbdbf2fa85e9e66b1077eea3a88bef38ee8a06270b4298a7a62a166", size = 221566 }, + { url = "https://files.pythonhosted.org/packages/d4/09/d4996de4059c3ce5342b6e1e6a77c9d6c91acce31f6ed979891872dd162b/xxhash-3.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c28b2fdcee797e1c1961cd3bcd3d545cab22ad202c846235197935e1df2f8ef7", size = 201214 }, + { url = "https://files.pythonhosted.org/packages/62/f5/6d2dc9f8d55a7ce0f5e7bfef916e67536f01b85d32a9fbf137d4cadbee38/xxhash-3.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:924361811732ddad75ff23e90efd9ccfda4f664132feecb90895bade6a1b4623", size = 429433 }, + { url = "https://files.pythonhosted.org/packages/d9/72/9256303f10e41ab004799a4aa74b80b3c5977d6383ae4550548b24bd1971/xxhash-3.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89997aa1c4b6a5b1e5b588979d1da048a3c6f15e55c11d117a56b75c84531f5a", size = 194822 }, + { url = "https://files.pythonhosted.org/packages/34/92/1a3a29acd08248a34b0e6a94f4e0ed9b8379a4ff471f1668e4dce7bdbaa8/xxhash-3.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:685c4f4e8c59837de103344eb1c8a3851f670309eb5c361f746805c5471b8c88", size = 208538 }, + { url = "https://files.pythonhosted.org/packages/53/ad/7fa1a109663366de42f724a1cdb8e796a260dbac45047bce153bc1e18abf/xxhash-3.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dbd2ecfbfee70bc1a4acb7461fa6af7748ec2ab08ac0fa298f281c51518f982c", size = 216953 }, + { url = "https://files.pythonhosted.org/packages/35/02/137300e24203bf2b2a49b48ce898ecce6fd01789c0fcd9c686c0a002d129/xxhash-3.5.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:25b5a51dc3dfb20a10833c8eee25903fd2e14059e9afcd329c9da20609a307b2", size = 203594 }, + { url = "https://files.pythonhosted.org/packages/23/03/aeceb273933d7eee248c4322b98b8e971f06cc3880e5f7602c94e5578af5/xxhash-3.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a8fb786fb754ef6ff8c120cb96629fb518f8eb5a61a16aac3a979a9dbd40a084", size = 210971 }, + { url = "https://files.pythonhosted.org/packages/e3/64/ed82ec09489474cbb35c716b189ddc1521d8b3de12b1b5ab41ce7f70253c/xxhash-3.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:a905ad00ad1e1c34fe4e9d7c1d949ab09c6fa90c919860c1534ff479f40fd12d", size = 415050 }, + { url = "https://files.pythonhosted.org/packages/71/43/6db4c02dcb488ad4e03bc86d70506c3d40a384ee73c9b5c93338eb1f3c23/xxhash-3.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:963be41bcd49f53af6d795f65c0da9b4cc518c0dd9c47145c98f61cb464f4839", size = 192216 }, + { url = "https://files.pythonhosted.org/packages/22/6d/db4abec29e7a567455344433d095fdb39c97db6955bb4a2c432e486b4d28/xxhash-3.5.0-cp311-cp311-win32.whl", hash = "sha256:109b436096d0a2dd039c355fa3414160ec4d843dfecc64a14077332a00aeb7da", size = 30120 }, + { url = "https://files.pythonhosted.org/packages/52/1c/fa3b61c0cf03e1da4767213672efe186b1dfa4fc901a4a694fb184a513d1/xxhash-3.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:b702f806693201ad6c0a05ddbbe4c8f359626d0b3305f766077d51388a6bac58", size = 30003 }, + { url = "https://files.pythonhosted.org/packages/6b/8e/9e6fc572acf6e1cc7ccb01973c213f895cb8668a9d4c2b58a99350da14b7/xxhash-3.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:c4dcb4120d0cc3cc448624147dba64e9021b278c63e34a38789b688fd0da9bf3", size = 26777 }, + { url = "https://files.pythonhosted.org/packages/07/0e/1bfce2502c57d7e2e787600b31c83535af83746885aa1a5f153d8c8059d6/xxhash-3.5.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:14470ace8bd3b5d51318782cd94e6f94431974f16cb3b8dc15d52f3b69df8e00", size = 31969 }, + { url = "https://files.pythonhosted.org/packages/3f/d6/8ca450d6fe5b71ce521b4e5db69622383d039e2b253e9b2f24f93265b52c/xxhash-3.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:59aa1203de1cb96dbeab595ded0ad0c0056bb2245ae11fac11c0ceea861382b9", size = 30787 }, + { url = "https://files.pythonhosted.org/packages/5b/84/de7c89bc6ef63d750159086a6ada6416cc4349eab23f76ab870407178b93/xxhash-3.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08424f6648526076e28fae6ea2806c0a7d504b9ef05ae61d196d571e5c879c84", size = 220959 }, + { url = "https://files.pythonhosted.org/packages/fe/86/51258d3e8a8545ff26468c977101964c14d56a8a37f5835bc0082426c672/xxhash-3.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:61a1ff00674879725b194695e17f23d3248998b843eb5e933007ca743310f793", size = 200006 }, + { url = "https://files.pythonhosted.org/packages/02/0a/96973bd325412feccf23cf3680fd2246aebf4b789122f938d5557c54a6b2/xxhash-3.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2f2c61bee5844d41c3eb015ac652a0229e901074951ae48581d58bfb2ba01be", size = 428326 }, + { url = "https://files.pythonhosted.org/packages/11/a7/81dba5010f7e733de88af9555725146fc133be97ce36533867f4c7e75066/xxhash-3.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d32a592cac88d18cc09a89172e1c32d7f2a6e516c3dfde1b9adb90ab5df54a6", size = 194380 }, + { url = "https://files.pythonhosted.org/packages/fb/7d/f29006ab398a173f4501c0e4977ba288f1c621d878ec217b4ff516810c04/xxhash-3.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70dabf941dede727cca579e8c205e61121afc9b28516752fd65724be1355cc90", size = 207934 }, + { url = "https://files.pythonhosted.org/packages/8a/6e/6e88b8f24612510e73d4d70d9b0c7dff62a2e78451b9f0d042a5462c8d03/xxhash-3.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e5d0ddaca65ecca9c10dcf01730165fd858533d0be84c75c327487c37a906a27", size = 216301 }, + { url = "https://files.pythonhosted.org/packages/af/51/7862f4fa4b75a25c3b4163c8a873f070532fe5f2d3f9b3fc869c8337a398/xxhash-3.5.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3e5b5e16c5a480fe5f59f56c30abdeba09ffd75da8d13f6b9b6fd224d0b4d0a2", size = 203351 }, + { url = "https://files.pythonhosted.org/packages/22/61/8d6a40f288f791cf79ed5bb113159abf0c81d6efb86e734334f698eb4c59/xxhash-3.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:149b7914451eb154b3dfaa721315117ea1dac2cc55a01bfbd4df7c68c5dd683d", size = 210294 }, + { url = "https://files.pythonhosted.org/packages/17/02/215c4698955762d45a8158117190261b2dbefe9ae7e5b906768c09d8bc74/xxhash-3.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:eade977f5c96c677035ff39c56ac74d851b1cca7d607ab3d8f23c6b859379cab", size = 414674 }, + { url = "https://files.pythonhosted.org/packages/31/5c/b7a8db8a3237cff3d535261325d95de509f6a8ae439a5a7a4ffcff478189/xxhash-3.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fa9f547bd98f5553d03160967866a71056a60960be00356a15ecc44efb40ba8e", size = 192022 }, + { url = "https://files.pythonhosted.org/packages/78/e3/dd76659b2811b3fd06892a8beb850e1996b63e9235af5a86ea348f053e9e/xxhash-3.5.0-cp312-cp312-win32.whl", hash = "sha256:f7b58d1fd3551b8c80a971199543379be1cee3d0d409e1f6d8b01c1a2eebf1f8", size = 30170 }, + { url = "https://files.pythonhosted.org/packages/d9/6b/1c443fe6cfeb4ad1dcf231cdec96eb94fb43d6498b4469ed8b51f8b59a37/xxhash-3.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:fa0cafd3a2af231b4e113fba24a65d7922af91aeb23774a8b78228e6cd785e3e", size = 30040 }, + { url = "https://files.pythonhosted.org/packages/0f/eb/04405305f290173acc0350eba6d2f1a794b57925df0398861a20fbafa415/xxhash-3.5.0-cp312-cp312-win_arm64.whl", hash = "sha256:586886c7e89cb9828bcd8a5686b12e161368e0064d040e225e72607b43858ba2", size = 26796 }, + { url = "https://files.pythonhosted.org/packages/c9/b8/e4b3ad92d249be5c83fa72916c9091b0965cb0faeff05d9a0a3870ae6bff/xxhash-3.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:37889a0d13b0b7d739cfc128b1c902f04e32de17b33d74b637ad42f1c55101f6", size = 31795 }, + { url = "https://files.pythonhosted.org/packages/fc/d8/b3627a0aebfbfa4c12a41e22af3742cf08c8ea84f5cc3367b5de2d039cce/xxhash-3.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:97a662338797c660178e682f3bc180277b9569a59abfb5925e8620fba00b9fc5", size = 30792 }, + { url = "https://files.pythonhosted.org/packages/c3/cc/762312960691da989c7cd0545cb120ba2a4148741c6ba458aa723c00a3f8/xxhash-3.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f85e0108d51092bdda90672476c7d909c04ada6923c14ff9d913c4f7dc8a3bc", size = 220950 }, + { url = "https://files.pythonhosted.org/packages/fe/e9/cc266f1042c3c13750e86a535496b58beb12bf8c50a915c336136f6168dc/xxhash-3.5.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd2fd827b0ba763ac919440042302315c564fdb797294d86e8cdd4578e3bc7f3", size = 199980 }, + { url = "https://files.pythonhosted.org/packages/bf/85/a836cd0dc5cc20376de26b346858d0ac9656f8f730998ca4324921a010b9/xxhash-3.5.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:82085c2abec437abebf457c1d12fccb30cc8b3774a0814872511f0f0562c768c", size = 428324 }, + { url = "https://files.pythonhosted.org/packages/b4/0e/15c243775342ce840b9ba34aceace06a1148fa1630cd8ca269e3223987f5/xxhash-3.5.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07fda5de378626e502b42b311b049848c2ef38784d0d67b6f30bb5008642f8eb", size = 194370 }, + { url = "https://files.pythonhosted.org/packages/87/a1/b028bb02636dfdc190da01951d0703b3d904301ed0ef6094d948983bef0e/xxhash-3.5.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c279f0d2b34ef15f922b77966640ade58b4ccdfef1c4d94b20f2a364617a493f", size = 207911 }, + { url = "https://files.pythonhosted.org/packages/80/d5/73c73b03fc0ac73dacf069fdf6036c9abad82de0a47549e9912c955ab449/xxhash-3.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:89e66ceed67b213dec5a773e2f7a9e8c58f64daeb38c7859d8815d2c89f39ad7", size = 216352 }, + { url = "https://files.pythonhosted.org/packages/b6/2a/5043dba5ddbe35b4fe6ea0a111280ad9c3d4ba477dd0f2d1fe1129bda9d0/xxhash-3.5.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:bcd51708a633410737111e998ceb3b45d3dbc98c0931f743d9bb0a209033a326", size = 203410 }, + { url = "https://files.pythonhosted.org/packages/a2/b2/9a8ded888b7b190aed75b484eb5c853ddd48aa2896e7b59bbfbce442f0a1/xxhash-3.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3ff2c0a34eae7df88c868be53a8dd56fbdf592109e21d4bfa092a27b0bf4a7bf", size = 210322 }, + { url = "https://files.pythonhosted.org/packages/98/62/440083fafbc917bf3e4b67c2ade621920dd905517e85631c10aac955c1d2/xxhash-3.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:4e28503dccc7d32e0b9817aa0cbfc1f45f563b2c995b7a66c4c8a0d232e840c7", size = 414725 }, + { url = "https://files.pythonhosted.org/packages/75/db/009206f7076ad60a517e016bb0058381d96a007ce3f79fa91d3010f49cc2/xxhash-3.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a6c50017518329ed65a9e4829154626f008916d36295b6a3ba336e2458824c8c", size = 192070 }, + { url = "https://files.pythonhosted.org/packages/1f/6d/c61e0668943a034abc3a569cdc5aeae37d686d9da7e39cf2ed621d533e36/xxhash-3.5.0-cp313-cp313-win32.whl", hash = "sha256:53a068fe70301ec30d868ece566ac90d873e3bb059cf83c32e76012c889b8637", size = 30172 }, + { url = "https://files.pythonhosted.org/packages/96/14/8416dce965f35e3d24722cdf79361ae154fa23e2ab730e5323aa98d7919e/xxhash-3.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:80babcc30e7a1a484eab952d76a4f4673ff601f54d5142c26826502740e70b43", size = 30041 }, + { url = "https://files.pythonhosted.org/packages/27/ee/518b72faa2073f5aa8e3262408d284892cb79cf2754ba0c3a5870645ef73/xxhash-3.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:4811336f1ce11cac89dcbd18f3a25c527c16311709a89313c3acaf771def2d4b", size = 26801 }, + { url = "https://files.pythonhosted.org/packages/ab/9a/233606bada5bd6f50b2b72c45de3d9868ad551e83893d2ac86dc7bb8553a/xxhash-3.5.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:2014c5b3ff15e64feecb6b713af12093f75b7926049e26a580e94dcad3c73d8c", size = 29732 }, + { url = "https://files.pythonhosted.org/packages/0c/67/f75276ca39e2c6604e3bee6c84e9db8a56a4973fde9bf35989787cf6e8aa/xxhash-3.5.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fab81ef75003eda96239a23eda4e4543cedc22e34c373edcaf744e721a163986", size = 36214 }, + { url = "https://files.pythonhosted.org/packages/0f/f8/f6c61fd794229cc3848d144f73754a0c107854372d7261419dcbbd286299/xxhash-3.5.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e2febf914ace002132aa09169cc572e0d8959d0f305f93d5828c4836f9bc5a6", size = 32020 }, + { url = "https://files.pythonhosted.org/packages/79/d3/c029c99801526f859e6b38d34ab87c08993bf3dcea34b11275775001638a/xxhash-3.5.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5d3a10609c51da2a1c0ea0293fc3968ca0a18bd73838455b5bca3069d7f8e32b", size = 40515 }, + { url = "https://files.pythonhosted.org/packages/62/e3/bef7b82c1997579c94de9ac5ea7626d01ae5858aa22bf4fcb38bf220cb3e/xxhash-3.5.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5a74f23335b9689b66eb6dbe2a931a88fcd7a4c2cc4b1cb0edba8ce381c7a1da", size = 30064 }, +] + [[package]] name = "yarl" version = "1.13.1"